diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index fddd70ad5..000000000 --- a/.editorconfig +++ /dev/null @@ -1,17 +0,0 @@ -root = true - -[*] -end_of_line = lf -indent_style = space -trim_trailing_whitespace = true -insert_final_newline = true -charset = utf-8 - -[*.{txt,build,json,xml,xml.in,in}] -indent_size = 2 - -[*.{vala,py}] -indent_size = 4 -block_comment_start = /** -block_comment = * -block_comment_end = */ diff --git a/.gitignore b/.gitignore index 172b03c3e..899182c02 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,8 @@ _build/ build*/ .flatpak-builder/ *~ + + +# Added by cargo + +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 000000000..a7dd1278e --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,915 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "akira" +version = "0.1.0" +dependencies = [ + "gettext-rs", + "granite-rs", + "gtk4", + "once_cell", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "cairo-rs" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a0ea147c94108c9613235388f540e4d14c327f7081c9e471fc8ee8a2533e69" +dependencies = [ + "bitflags", + "cairo-sys-rs", + "glib", + "libc", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428290f914b9b86089f60f5d8a9f6e440508e1bcff23b25afd51502b0a2da88f" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "cc" +version = "1.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-expr" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345c78335be0624ed29012dc10c49102196c6882c12dde65d9f35b02da2aada8" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-macro", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8730751991b97419fc3f0c2dca2c9e45b48edf46e48e0f965964ecf33889812f" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffbf649fd5b1c8c0f0feeb015b7533c3ef92da2887fb95ddd338bc2b1644a7c" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk4" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b7d7237c1487ed4b300aac7744efcbf1319e12d60d7afcd6f505414bd5b5dea" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk4-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk4-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a67576c8ec012156d7f680e201a807b4432a77babb3157e0555e990ab6bcd878" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gettext-rs" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a6716b8a0db461a2720b850ba1623e5b69e4b1aa0224cf5e1fb23a0fe49e65c" +dependencies = [ + "gettext-sys", + "locale_config", +] + +[[package]] +name = "gettext-sys" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b8797f28f2dabfbe2caadb6db4f7fd739e251b5ede0a2ba49e506071edcf67" +dependencies = [ + "cc", + "temp-dir", +] + +[[package]] +name = "gio" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcacaa37401cad0a95aadd266bc39c72a131d454fc012f6dfd217f891d76cc52" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "pin-project-lite", + "smallvec", +] + +[[package]] +name = "gio-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5237611e97e9b86ab5768adc3eef853ae713ea797aa3835404acdfacffc9fb38" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "windows-sys", +] + +[[package]] +name = "glib" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95648aac01b75503000bb3bcaa5ec7a7a2dd61e43636b8b1814854de94dd80e4" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "smallvec", +] + +[[package]] +name = "glib-macros" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302f1d633c9cdef4350330e7b68fd8016e2834bb106c93fdf9789fcde753c1ab" +dependencies = [ + "heck", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92eee4531c1c9abba945d19378b205031b5890e1f99c319ba0503b6e0c06a163" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "gobject-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa3d1dcd8a1eb2e7c22be3d5e792b14b186f3524f79b25631730f9a8c169d49a" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "granite-rs" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7299514cbcfda05321dc6e7546ebc6d4ea1cbc27dcc7f1dc9089fea27dbf4399" +dependencies = [ + "bitflags", + "gdk4", + "gio", + "glib", + "granite-rs-sys", + "gtk4", + "libc", + "once_cell", +] + +[[package]] +name = "granite-rs-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0481fc89d9cf5ce0afb46978bd63dac19f3eb7324cb66156165b14e8c2e5ee0" +dependencies = [ + "gdk4-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk4-sys", + "libc", + "system-deps", +] + +[[package]] +name = "graphene-rs" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80aac87f74e81c0e13433e892a047237abdc37945c86887f5eed905038356e69" +dependencies = [ + "glib", + "graphene-sys", + "libc", +] + +[[package]] +name = "graphene-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2f91ecd32989efad60326cc20a8fb252bd2852239a08e4e70cde8c100de9ca" +dependencies = [ + "glib-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gsk4" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3cf2091e1af185b347b3450817d93dea6fe435df7abd4c2cd7fb5bcb4cfda8" +dependencies = [ + "cairo-rs", + "gdk4", + "glib", + "graphene-rs", + "gsk4-sys", + "libc", + "pango", +] + +[[package]] +name = "gsk4-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aa69614a26d8760c186c3690f1b0fbb917572ca23ef83137445770ceddf8cde" +dependencies = [ + "cairo-sys-rs", + "gdk4-sys", + "glib-sys", + "gobject-sys", + "graphene-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk4" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fe572bf318e5dbc6f5a2f8a25d853f1ae3f42768c0b08af6ca20a18f4057e1" +dependencies = [ + "cairo-rs", + "field-offset", + "futures-channel", + "gdk-pixbuf", + "gdk4", + "gio", + "glib", + "graphene-rs", + "gsk4", + "gtk4-macros", + "gtk4-sys", + "libc", + "pango", +] + +[[package]] +name = "gtk4-macros" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e7b362c8fccd2712297903717d65d30defdab2b509bc9d209cbe5ffb9fabaf" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "gtk4-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1114a207af8ada02cf4658a76692f4190f06f093380d5be07e3ca8b43aa7c666" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk4-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "graphene-sys", + "gsk4-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.158" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" + +[[package]] +name = "locale_config" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d2c35b16f4483f6c26f0e4e9550717a2f6575bcd6f12a53ff0c490a94a6934" +dependencies = [ + "lazy_static", + "objc", + "objc-foundation", + "regex", + "winapi", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "pango" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5764e5a174a5a0ec054fe5962ce6d4fc7052e2d0dcc23bbc77202b40a4a403d3" +dependencies = [ + "gio", + "glib", + "libc", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd317e1de76b14b3d3efe05518c08b360327f1ab7fec150473a89ffcad4b072d" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +dependencies = [ + "serde", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "syn" +version = "2.0.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "system-deps" +version = "7.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "070a0a5e7da2d24be457809c4b3baa57a835fd2829ad8b86f9a049052fe71031" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + +[[package]] +name = "temp-dir" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f227968ec00f0e5322f9b8173c7a0cbcff6181a0a5b28e9892491c286277231" + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 000000000..bafb8343e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "akira" +version = "0.1.0" +edition = "2021" + +[dependencies] +gettext-rs = "0.7.1" +granite = { version = "1.1", package = "granite-rs", features = ["v7_2"] } +gtk = { version = "0.9.1", package = "gtk4" } +once_cell = "1.19.0" diff --git a/README.md b/README.md index 521702bfb..90f9dbf60 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,12 @@ -

-
- Akira -

-

The Linux Design Tool

-

- Build Status - AkiraUX on Liberapay - AkiraUX on Patreon -

-

- Install • - Compile • - Questions • - Contributing • - Support • - Mascot • - License -

- -![screenshot](data/screenshots/screenshot-1.png) - -Akira is a native Linux Design application built in Vala and GTK. Akira focuses on offering a modern and fast approach to UI and UX Design, mainly targeting web designers and graphic designers. The main goal is to offer a valid and professional solution for designers who want to use Linux as their main OS. +# Akira -⚠️⚠️ **AKIRA IS CURRENTLY IN EARLY DEVELOPMENT, NOT READY TO BE USED FOR PRODUCTION!** ⚠️⚠️ - -Feel free to download the Alpha and help us testing it. +> The Linux Design Tool -## 📦 Install +⚠️⚠️ **AKIRA IS CURRENTLY IN EARLY DEVELOPMENT, NOT READY TO BE USED FOR PRODUCTION!** ⚠️⚠️ -| elementaryOS AppCenter | FlatHub | -|------------------------ |--------------- | -|[![Get it on AppCenter](https://appcenter.elementary.io/badge.svg)](https://appcenter.elementary.io/com.github.akiraux.akira/)|Get it from Flathub! +## Experimental Rust branch -### Flathub Beta -``` -flatpak remote-add flathub-beta https://flathub.org/beta-repo/flathub-beta.flatpakrepo -flatpak install akira -``` +Akira is a native Linux Design application built in Rust. Akira focuses on offering a modern and fast approach to UI and UX Design, mainly targeting web and graphic designers. ## 🛠 Compile @@ -47,32 +14,11 @@ You can install Akira by compiling it from the source ### Install Dependencies - - `gtk+-3.0>=3.18` - - `granite>=6.0.0` - - `glib-2.0` - - `gee-0.8` - - `gobject-2.0` - - `libxml-2.0` - - `libjson-glib-1.0` - - `libarchive` - - `gettext` - - `cairo` - - `meson` - -> _**Note:** For non-elementary distros, (such as Arch, Debian etc) you are required to install "vala", "elementary-theme" and "elementary-icon-theme" as additional dependencies._ +WIP ### Compile & Run -Once the above mentioned dependencies are resolved, Akira can be compiled & installed - -```sh -meson build --prefix=/usr -Dprofile=default -cd build -ninja && sudo ninja install -./src/com.github.akiraux.akira -``` - -> _**Note:** Replace the `-Dprofile=default` with `-Dprofile=development` to compile and install Akira in **development** mode where you can make changes._ +WIP ## 🤔 Questions @@ -99,13 +45,14 @@ If you like Akira and you want to support its development, consider donating via ![](https://raw.githubusercontent.com/akiraux/assets/master/mascot/akira-mascot-akari.png) -**Akari the Cyber Phoenix** is a perfectionist. She is tidy, collected and has a sharp eye for detail. Her name Akari (灯理、) means *"the enlightenment of a sophisticated order"*. Her costume resembles the project's icon. Get the Mascot and all the other assets from [here](https://github.com/akiraux/assets). +**Akari the Cyber Phoenix** is a perfectionist. She is tidy, collected and has a sharp eye for detail. Her name Akari (灯理、) means _"the enlightenment of a sophisticated order"_. Her costume resembles the project's icon. Get the Mascot and all the other assets from [here](https://github.com/akiraux/assets). Mascot character designed by **Tyson Tan**. Tyson Tan offers mascot design service for free and open source software, free of charge, under free license. -Contact: [http://tysontan.com](http://tysontan.com) / [tysontan@mail.com](mailto:tysontan@mail.com) +Contact: [http://tysontan.com](http://tysontan.com) / [tysontan@mail.com](mailto:tysontan@mail.com) ## 📜 License + #### [GNU GPLv3 / Creative Commons BY-SA](./COPYING) -Copyright © 2019-2020 Akira Project. +Copyright © 2019-2024 Alessandro Castellani. diff --git a/akira-logo-transparent.png b/akira-logo-transparent.png deleted file mode 100644 index fc83522da..000000000 Binary files a/akira-logo-transparent.png and /dev/null differ diff --git a/akira-screenshot.png b/akira-screenshot.png deleted file mode 100644 index 0b541a35e..000000000 Binary files a/akira-screenshot.png and /dev/null differ diff --git a/aux/flatpak/com.github.akiraux.akira.json b/aux/flatpak/com.github.akiraux.akira.json deleted file mode 100644 index c33eceb77..000000000 --- a/aux/flatpak/com.github.akiraux.akira.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "app-id": "com.github.akiraux.akiraDevel", - "runtime": "org.gnome.Platform", - "runtime-version": "40", - "sdk": "org.gnome.Sdk", - "base": "io.elementary.BaseApp", - "base-version": "juno-20.08", - "command": "com.github.akiraux.akiraDevel", - "cleanup": [ - "/include", - "/lib/pkgconfig", - "/lib/debug", - "/share/vala", - "/man", - "*.a", - "*.la" - ], - "finish-args": [ - "--share=ipc", - "--socket=fallback-x11", - "--socket=wayland", - "--talk-name=org.gtk.vfs.*", - "--filesystem=xdg-run/gvfs", - "--filesystem=xdg-run/gvfsd" - ], - "modules": [ - { - "name": "elementary-stylesheet", - "buildsystem": "meson", - "sources": [{ - "type": "git", - "url": "https://github.com/elementary/stylesheet.git", - "commit": "3047efbfabe723e0b0f2b8ee3d53bed528be4b14" - }], - "modules": [{ - "name": "sassc", - "cleanup": [ - "*" - ], - "sources": [{ - "type": "git", - "url": "https://github.com/sass/sassc.git", - "tag": "3.6.1" - }, - { - "type": "script", - "dest-filename": "autogen.sh", - "commands": [ - "autoreconf -si" - ] - } - ], - "modules": [{ - "name": "libsass", - "cleanup": [ - "*" - ], - "sources": [{ - "type": "git", - "url": "https://github.com/sass/libsass.git", - "tag": "3.6.4" - }, - { - "type": "script", - "dest-filename": "autogen.sh", - "commands": [ - "autoreconf -si" - ] - } - ] - }] - }] - }, - { - "name": "elementary-icons", - "buildsystem": "meson", - "sources": [{ - "type": "git", - "url": "https://github.com/elementary/icons.git", - "commit": "9e7ace3d6c1d1e3b5ea64012a371e46039bf044a" - }], - "modules": [{ - "name": "xcursorgen", - "cleanup": [ - "*" - ], - "sources": [{ - "type": "git", - "url": "https://gitlab.freedesktop.org/xorg/app/xcursorgen.git", - "tag": "xcursorgen-1.0.7" - }] - }] - }, - { - "name": "akira", - "buildsystem": "meson", - "config-opts": [ - "-Dprofile=development" - ], - "sources": [{ - "type": "dir", - "path": "../../" - }] - } - ] -} diff --git a/aux/meson/post_install.py b/aux/meson/post_install.py deleted file mode 100755 index 401004d21..000000000 --- a/aux/meson/post_install.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python3 - -import os -import subprocess - -install_prefix = os.environ['MESON_INSTALL_PREFIX'] -schemadir = os.path.join(install_prefix, 'share/glib-2.0/schemas') - -if not os.environ.get('DESTDIR'): - print('Compiling gsettings schemas...') - subprocess.call(['glib-compile-schemas', schemadir]) - - print('Updating icon cache...') - icon_cache_dir = os.path.join(install_prefix, 'share/icons/hicolor') - subprocess.call(['gtk-update-icon-cache', '-qtf', icon_cache_dir]) - - print('Updating desktop database...') - desktop_database_dir = os.path.join(install_prefix, 'share/applications') - subprocess.call(['update-desktop-database', '-q', desktop_database_dir]) diff --git a/com.github.akiraux.akira.yml b/com.github.akiraux.akira.yml deleted file mode 100644 index 7f6ad0263..000000000 --- a/com.github.akiraux.akira.yml +++ /dev/null @@ -1,23 +0,0 @@ -app-id: com.github.akiraux.akira -runtime: io.elementary.Platform -runtime-version: '6' -sdk: io.elementary.Sdk -command: com.github.akiraux.akira - -finish-args: - - '--share=ipc' - - '--socket=fallback-x11' - - '--socket=wayland' - - # needed for perfers-color-scheme - - '--system-talk-name=org.freedesktop.Accounts' - - - '--filesystem=home' - - '--device=dri' - -modules: - - name: akira - buildsystem: meson - sources: - - type: dir - path: . diff --git a/data/assets.gresource.xml b/data/assets.gresource.xml deleted file mode 100644 index 85dd3a710..000000000 --- a/data/assets.gresource.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - css/colors.css - css/layout.css - css/artboard.css - css/layer.css - css/headerbar.css - css/option-panel.css - css/dialogs.css - - - assets/akira-banner.jpg - - css/stylesheet.css - - icons/hicolor/document-layout.svg - icons/symbolic/document-layout-symbolic.svg - - icons/symbolic/layer-visible-symbolic.svg - icons/symbolic/layer-hidden-symbolic.svg - - icons/symbolic/input-hash-symbolic.svg - icons/symbolic/input-percentage-symbolic.svg - icons/symbolic/input-pixel-symbolic.svg - icons/symbolic/input-degrees-symbolic.svg - - icons/symbolic/shape-image-symbolic.svg - icons/symbolic/shape-pencil-symbolic.svg - icons/symbolic/shape-rectangle-symbolic.svg - icons/symbolic/shape-triangle-symbolic.svg - icons/symbolic/shape-circle-symbolic.svg - icons/symbolic/shape-text-symbolic.svg - - diff --git a/data/assets/akira-banner.jpg b/data/assets/akira-banner.jpg deleted file mode 100644 index 4a7a98d1a..000000000 Binary files a/data/assets/akira-banner.jpg and /dev/null differ diff --git a/data/com.github.akiraux.akira.appdata.xml.in.in b/data/com.github.akiraux.akira.appdata.xml.in.in deleted file mode 100644 index 3a58975dc..000000000 --- a/data/com.github.akiraux.akira.appdata.xml.in.in +++ /dev/null @@ -1,199 +0,0 @@ - - - - @APP_ID@ - CC0-1.0 - GPL-3.0+ - Akira - The Linux Design Tool - -

- A modern UX Design Application for UI and UX Designers -

-

- ⚠ WARNING! Akira is still under development and not ready for production. Missing features, random bugs, and black holes opening in your kitchen are to be expected.

-

- Akira is a native Linux Design application built in Vala and Gtk. Akira focuses on offering a modern and fast approach to UI and UX Design, mainly targeting web and graphic designers. The main goal is to offer a valid and professional solution for designers who want to use Linux as their main OS. -

-

- Features Include: -

- -
- - @APP_ID@ - - - - -

Performance improvements and Global colors library

-
    -
  • Improved "Modes" detection (insert, select, transform).
  • -
  • Fixed Artboard label issues on zoom.
  • -
  • Improved Pixel Grid detection and z-index stack with other items.
  • -
  • Implemented editable zoom value.
  • -
  • Fix application activation when opening a new file.
  • -
  • Fix sizing issue when dropping images into the Canvas.
  • -
  • Implemented Global colors library.
  • -
  • Italian translation.
  • -
-
-
- - -

New Features and Bug Fixes

-
    -
  • Complete rebuild of the Canvas library architecture.
  • -
  • Implemented Pixel Grid.
  • -
  • Customize color of Pixel Grid.
  • -
  • Implemented smart Snapping Guides.
  • -
  • Customize color and magnetic threshold of Snapping Guides.
  • -
  • Allow items resizing in all directions.
  • -
  • Add images via click and drag with the Image Tool.
  • -
  • Handle multiple Fills and Border colors for each item.
  • -
  • Allow scaling items from the center.
  • -
  • Enable dropping images on the canvas.
  • -
  • A lot of code improvements and optimization.
  • -
-
-
- - -

New Features and Bug Fixes

-
    -
  • New color picker for Fills and Borders.
  • -
  • Zooming with mouse wheel follows the position of the cursor.
  • -
  • Fix loading Artboards background color when opening a file.
  • -
  • Fix numbering of newly created items.
  • -
  • Fix Gtk-CRITICAL warning when opening the Export Dialog.
  • -
  • Fix flipping items inside Artboards.
  • -
  • Fix crash when dropping flipped items inside Artboards.
  • -
  • General code improvements and optimization.
  • -
-
-
- - -

Bug fixes and Artboards improvements

-
    -
  • Control Artboards background color.
  • -
  • Hide and Lock Artboards from the Layers panel.
  • -
  • Items inside Artboards are masked when extending outside the edges of the Artboard.
  • -
  • Fix items reordering with the layers panel drag and drop.
  • -
  • Fix random segfault at startup while setting accelerators.
  • -
  • Updated goocanvas vapi.
  • -
-
-
- - -

🚀 Experimental Alpha Release, say Hi to Akira!

-
    -
  • Create Artboards and basic shapes
  • -
  • Manage the fill and border properties of shapes
  • -
  • Import images
  • -
  • Export custom areas, selections, and artboards
  • -
  • So many crashes and missing features you wouldn't believe, but hey, this is an experimental alpha…
  • -
-
-
- - -

🚀 Experimental Alpha Release, say Hi to Akira!

-
    -
  • Create Artboards and basic shapes
  • -
  • Manage the fill and border properties of shapes
  • -
  • Import images
  • -
  • Export custom areas, selections, and artboards
  • -
  • So many crashes and missing features you wouldn't believe, but hey, this is an experimental alpha…
  • -
-
-
- - -

🚀 Experimental Alpha Release, say Hi to Akira!

-
    -
  • Create Artboards and basic shapes
  • -
  • Manage the fill and border properties of shapes
  • -
  • Import images
  • -
  • Export custom areas, selections, and artboards
  • -
  • So many crashes and missing features you wouldn't believe, but hey, this is an experimental alpha…
  • -
-
-
-
- - - https://raw.githubusercontent.com/akiraux/akira/master/data/screenshots/screenshot-1.png - - - https://raw.githubusercontent.com/akiraux/akira/master/data/screenshots/screenshot-2.png - - - https://raw.githubusercontent.com/akiraux/akira/master/data/screenshots/screenshot-3.png - - - https://raw.githubusercontent.com/akiraux/akira/master/data/screenshots/screenshot-4.png - - - @APP_ID@.desktop - Alessandro Castellani - https://github.com/akiraux/akira - https://github.com/akiraux/akira/issues - https://github.com/akiraux/akira/issues - https://www.paypal.me/alecaddd - castellani.ale@gmail.com - @GETTEXT_PACKAGE@ - - - ModernToolkit - HighContrast - HiDpiIcon - - - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - none - - - #3f3f3f - #ffffff - 15 - pk_live_515yF9YDvXGakAYGJ74PQwmIwxs6xQrm0q0ULEAYO6vZyzsTIaOI40ZtDYj6qUGq6sjzCgwd25VQ4REbJob6pkB9r00tU1lgu6W - -
diff --git a/data/com.github.akiraux.akira.desktop.in.in b/data/com.github.akiraux.akira.desktop.in.in deleted file mode 100644 index 5eb577887..000000000 --- a/data/com.github.akiraux.akira.desktop.in.in +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Name=Akira -GenericName=Akira App -Comment=The Linux Design Tool -Categories=Utility;Graphics; -Exec=@EXECUTABLE@ -Icon=@ICON_NAME@ -Terminal=false -Type=Application -Keywords=Design;Web;UX;UI;Graphics; -MimeType=application/x-akira; diff --git a/data/com.github.akiraux.akira.mime.xml b/data/com.github.akiraux.akira.mime.xml deleted file mode 100644 index f1bfd2958..000000000 --- a/data/com.github.akiraux.akira.mime.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - Akira Design File - - - - - diff --git a/data/css/artboard.css b/data/css/artboard.css deleted file mode 100644 index cfd0e4135..000000000 --- a/data/css/artboard.css +++ /dev/null @@ -1,13 +0,0 @@ -row.artboard { - transition: box-shadow 160ms ease, background-color 160ms ease; - background-color: shade (@bg_color, 1); -} - -row.artboard label { - font-weight: bold; - padding: 8px 0; -} - -row.artboard:hover .actions { - opacity: 1; -} diff --git a/data/css/colors.css b/data/css/colors.css deleted file mode 100644 index 7faa04668..000000000 --- a/data/css/colors.css +++ /dev/null @@ -1,11 +0,0 @@ -.label-colors { - color: alpha (@fg_color, 0.8); -} - -.disabled { - opacity: 0.5; -} - -.border-bottom { - border-bottom: 1px solid shade (@bg_color, 0.8); -} diff --git a/data/css/dialogs.css b/data/css/dialogs.css deleted file mode 100644 index 29c844daa..000000000 --- a/data/css/dialogs.css +++ /dev/null @@ -1,30 +0,0 @@ -.warning-message { - background-color: alpha (@STRAWBERRY_300, 0.2); - border: 1px solid @STRAWBERRY_500; - border-radius: 4px; -} - -.banner { - background-color: @bg_color; - background-image: - url("/com/github/akiraux/akira/akira-banner.jpg"), - linear-gradient( - to bottom, - shade(@bg_color, 1.02), - shade(@bg_color, 0.98) - ); - background-position: center center; - background-repeat: no-repeat; - background-size: cover; - border: 1px solid alpha(black, 0.15); - border-radius: 6px; - box-shadow: - inset 0 0 0 1px alpha(white, 0.05), - inset 0 1px 0 0 alpha(white, 0.45), - inset 0 -1px 0 0 alpha(white, 0.15), - 0 3px 2px -1px alpha(black, 0.15), - 0 3px 5px alpha(black, 0.1); - color: @fg_color; - font-size: 32px; - font-weight: 300; -} diff --git a/data/css/headerbar.css b/data/css/headerbar.css deleted file mode 100644 index c398da796..000000000 --- a/data/css/headerbar.css +++ /dev/null @@ -1,41 +0,0 @@ -.headerbar-label { - font-size: 8pt; -} - -.button-zoom { - padding: 0 6px; -} - -.button-zoom-start { - border-top-right-radius: 0px; - border-bottom-right-radius: 0px; -} - -.button-zoom-end { - border-top-left-radius: 0px; - border-bottom-left-radius: 0px; -} - -entry.input-zoom { - padding: 3px 8px 4px; - margin: 6px; -} - -.linked-flat button { - background-color: shade (@bg_color, 1); -} - -.export-titlebar { - padding: 0; -} - -/* Temporary elementary OS 6 stylesheet fixes */ -button.flat:disabled { - background-color: transparent; - box-shadow: none; - border: none; -} - -popover.menu stack { - padding: 6px 10px; -} diff --git a/data/css/layer.css b/data/css/layer.css deleted file mode 100644 index 7fa882246..000000000 --- a/data/css/layer.css +++ /dev/null @@ -1,42 +0,0 @@ -row { - transition: box-shadow 160ms ease, background-color 160ms ease; -} - -row:not(.item-property), -row entry { - background-color: @base_color; -} - -row label { - padding: 8px 0; -} - -row:selected { - background-color: alpha (@accent_color, 0.4); -} - -row:hover:not(:selected) { - box-shadow: inset 0 0 0 2px @accent_color; -} - -.actions button { - opacity: 0; -} - -row:hover .actions button { - opacity: 0.5; -} - -row:hover .actions button:hover, -row:hover .actions button.active, -.actions button.active { - opacity: 1; -} - -.button-toggle.collapsed image { - -gtk-icon-transform: rotate(-90deg); -} - -.grid-motion { - background-color: alpha (@accent_color, 0.3); -} diff --git a/data/css/layout.css b/data/css/layout.css deleted file mode 100644 index 3c5653044..000000000 --- a/data/css/layout.css +++ /dev/null @@ -1,132 +0,0 @@ -.main-canvas { - background-color: alpha (@fg_color, 0.05); -} - -.sidebar-l { - background-color: shade (@bg_color, 0.95); - border-right: 1px solid shade (@bg_color, 0.9); -} - -.sidebar-r { - background-color: shade (@bg_color, 0.95); - border-left: 1px solid shade (@bg_color, 0.9); -} - -.layers-panel { - background-color: alpha (@base_color, 0.7); -} - -.sidebar-export-header { - background-color: shade (@bg_color, 0.95); - border-radius: 4px 0 0 0; -} - -.sidebar-export { - background-color: shade (@bg_color, 0.95); - border-radius: 0 0 0 4px; -} - -.color-chooser { - padding: 8px 5px; -} - -.color-grid flowboxchild { - background-color: transparent; -} - -.color-chooser label { - font-size: 9pt; - font-weight: bold; - color: @fg_color; -} - -.popover-toggler { - padding: 3px; - margin: 3px; -} - -.popover-list row { - padding: 3px; -} - -.popover-list row:selected, -.popover-list row:selected:hover { - background-color: shade (@base_color, 0.85); - color: shade (@fg_color, 0.7); -} - -.popover-list row:hover { - background-color: shade (@base_color, 0.9); -} - -.alignment-panel { - background-color: alpha (@base_color, 0.7); - border-bottom: 1px solid shade (@bg_color, 0.8); - padding: 3px; -} - -.alignment-panel separator { - border-right: none; -} - -.button-rounded { - border-radius: 50%; - padding-left: 3px; - padding-right: 3px; -} - -.color-picker-button { - border-radius: 0 3px 3px 0; - border-left: none; -} - -.group-title { - font-size: 9pt; - font-weight: 600; - color: alpha (@fg_color, 0.9); -} - -.entry-label { - font-size: 8pt; - font-weight: bold; - color: alpha (@fg_color, 0.8); -} - -.linked entry { - padding: 3px 5px; - border-left-width: 1px; - border-radius: 2.5px; -} - -.panel-separator { - border: none; -} - -paned > separator { - min-width: 1px; - margin-right: 0; - margin-left: 0; -} - -.export-panel { - background-color: @bg_color; -} - -.export-panel flowboxchild:focus { - background-color: transparent; -} - -.export-widget { - background-color: shade (@bg_color, 0.98); - padding: 9px; - border-radius: 4px; -} - -.export-image { - border: 1px solid shade (@bg_color, 0.85); -} - -.export-info { - color: alpha (@fg_color, 0.7); - font-size: 0.85em; -} diff --git a/data/css/option-panel.css b/data/css/option-panel.css deleted file mode 100644 index 0aca09aad..000000000 --- a/data/css/option-panel.css +++ /dev/null @@ -1,51 +0,0 @@ -.option-panel { - background-color: alpha (@base_color, 0.7); - border-top: 1px solid shade (@bg_color, 0.7); - border-bottom: 1px solid shade (@bg_color, 0.7); -} - -.option-panel label { - padding: 9px; - font-size: 9pt; - font-weight: bold; - color: @fg_color; -} - -.option-panel button { - margin-right: 6px; - border-radius: 50%; -} - -.fills-list { - background: transparent; -} - -.bg-pattern { - background-image: /* tint image */ - linear-gradient(to right, rgba(192, 192, 192, 0.75), rgba(192, 192, 192, 0.75)), - /* checkered effect */ - linear-gradient(to right, black 50%, white 50%), - linear-gradient(to bottom, black 50%, white 50%); - background-blend-mode: normal, difference, normal; - background-size: 8px 8px; -} - -.selected-color-container { - border-radius: 4px 0 0 4px; -} - -button.selected-color { - border-radius: 3px 0 0 3px; - border: 1px solid; -} - -.saved-color-button { - border-radius: 4px; -} - -/* spin button */ -.sidebar-l spinbutton.horizontal button.down, -.sidebar-l spinbutton.horizontal button.up { - -gtk-icon-transform: scale(0.7); - padding: 0 1px; -} diff --git a/data/css/stylesheet.css b/data/css/stylesheet.css deleted file mode 100644 index 455d1226e..000000000 --- a/data/css/stylesheet.css +++ /dev/null @@ -1,8 +0,0 @@ -/* akira stylesheet */ -@import url("css/colors.css"); -@import url("css/layout.css"); -@import url("css/artboard.css"); -@import url("css/headerbar.css"); -@import url("css/layer.css"); -@import url("css/option-panel.css"); -@import url("css/dialogs.css"); diff --git a/data/meson.build b/data/meson.build deleted file mode 100644 index c57de70b7..000000000 --- a/data/meson.build +++ /dev/null @@ -1,84 +0,0 @@ -assets_dir = join_paths(akira_datadir, 'pixmaps', application_id) -install_data( - 'assets/akira-banner.jpg', - install_dir: assets_dir -) - -icon_sizes = ['16', '24', '32', '48', '64', '128'] -icons_dir = join_paths(akira_datadir, 'icons', 'hicolor') -foreach size : icon_sizes - install_data( - join_paths('icons', size + 'x' + size, application_id + '.svg'), - install_dir: join_paths(icons_dir, size + 'x' + size, 'apps') - ) - install_data( - join_paths('icons', size + 'x' + size, application_id + '.svg'), - install_dir: join_paths(icons_dir, size + 'x' + size + '@2', 'apps') - ) - install_data( - join_paths('icons', size + 'x' + size, application_id + '.svg'), - install_dir: join_paths(icons_dir, size + 'x' + size, 'mimetypes') - ) -endforeach - -install_data( - 'icons/128x128/' + meson.project_name() + '.svg', - rename: application_id + '.svg', - install_dir: join_paths(icons_dir, 'scalable', 'apps') -) - -desktop_file_conf = configuration_data() -desktop_file_conf.set('ICON_NAME', application_id) -desktop_file_conf.set('EXECUTABLE', application_id) - -desktop_file = i18n.merge_file( - input: configure_file( - input: meson.project_name() + '.desktop.in.in', - output: '@BASENAME@', - configuration: desktop_file_conf - ), - output: application_id + '.desktop', - po_dir: join_paths(meson.source_root(), 'po'), - type: 'desktop', - install: true, - install_dir: join_paths(akira_datadir, 'applications') -) -if desktop_file_validate.found() - test( - 'validate-desktop', - desktop_file_validate, - args: [ - desktop_file.full_path() - ] - ) -endif - -appdata_file_conf = configuration_data() -appdata_file_conf.set('APP_ID', application_id) -appdata_file_conf.set('GETTEXT_PACKAGE', application_id) - -appdata_file = i18n.merge_file( - input: configure_file( - input: meson.project_name() + '.appdata.xml.in.in', - output: '@BASENAME@', - configuration: appdata_file_conf - ), - output: application_id + '.appdata.xml', - po_dir: join_paths(meson.source_root(), 'po'), - install: true, - install_dir: join_paths(akira_datadir, 'metainfo') -) -if appstream_util.found() - test( - 'validate-appdata', appstream_util, - args: [ - 'validate-relax', '--nonet', appdata_file.full_path() - ] - ) -endif - -install_data( - meson.project_name() + '.mime.xml', - install_dir: join_paths(akira_datadir, 'mime', 'packages') -) -subdir('schemas') diff --git a/data/schemas/com.github.akiraux.akira.gschema.xml.in b/data/schemas/com.github.akiraux.akira.gschema.xml.in deleted file mode 100644 index 0e8c401b9..000000000 --- a/data/schemas/com.github.akiraux.akira.gschema.xml.in +++ /dev/null @@ -1,195 +0,0 @@ - - - - '0.0.0' - The currently installed version. - The currently installed version of Akira, updated only after the user launched the app. This is used to know when to trigger the Release Dialog. - - - - 360 - The saved horizontal position of the window. - The saved horizontal position of the window. - - - - 360 - The vertical position width of the window. - The saved vertical position of the window. - - - - 1024 - The saved width of the window. - The saved width of the window. - - - - 768 - The saved height of the window. - The saved height of the window. - - - - 804 - The saved width of the right panel. - The saved width of the right panel containing the MainCanvas and RightSidebar. - - - - 220 - The saved width of the left panel. - The saved width of the left panel. Must be greater than 220, or it will not take effect. - - - - false - Use dark theme - Switch between Light and Dark theme. - - - - true - Follow system theme variation - Follow system theme dark/light variation - - - - true - Show button labels - Show or Hide the button labels to slim the UI. - - - - false - Use Symbolic Icons - Allow user to choose between normal and symbolic icons in HeaderBar. - - - - false - Invert Panels Order - Allow user to choose between default and inverted panels order. - - - - '#888888' - Default Grid Color. - The default color of the pixel grid. - - - - true - Enable Snapping Guides - Allow user to enable or disable the snapping guides when moving items. - - - - '#ff0000' - Default Snaps Color. - The default color of the snapping guides. - - - - 4 - Default Snaps Sensitivity. - The default sensitivity of the snapping threshold. - - - - '#CCCCCC' - Default Shape Color. - The default color of a newly created shape. - - - - true - Add Border on Shape Creation - Enable the addition of the border style when creating a new shape. - - - - 1 - Default Border Width. - The default width of the border for a newly created shape. - - - - '#AAAAAA' - Default Border Color. - The default color of the border for a newly created shape. - - - - false - Auto Reopen latest file - Automatically reopen the latest file on startup. - - - - [] - Recently opened files - Keep track of the 10 most recently opened files. - - - - '' - Default export folder. - The default folder where exported images will be saved. - - - - 1000 - The saved width of the export dialog. - The saved width of the export dialog. - - - - 600 - The saved height of the export dialog. - The saved height of the export dialog. - - - - 300 - The saved position of the export left panel. - The saved position of the left panel in the export dialog. - - - - 100 - The quality value for exporting JPG images. - The quality value for exporting JPG images in the export dialog. - - - - 0 - The compression value for exporting PNG images. - The compression value for exporting PNG images in the export dialog. - - - - 'png' - The format type for exporting images. - The format type for exporting images in the export dialog. - - - - 1 - The scaled resolution for exporting images. - The scaled resolution for exporting images in the export dialog. - - - - true - The alpha setting for exporting PNG images. - The alpha setting for exporting PNG images in the export dialog. - - - - [] - The list of global colors - Keep track of the colors saved by the user and available in every document file. - - - diff --git a/data/schemas/meson.build b/data/schemas/meson.build deleted file mode 100644 index bb14630dd..000000000 --- a/data/schemas/meson.build +++ /dev/null @@ -1,11 +0,0 @@ -schemas_conf = configuration_data() -schemas_conf.set('SCHEMA_ID', application_id) -schemas_conf.set('SCHEMA_PATH', schema_path) -schemas_conf.set('GETTEXT_PACKAGE', gettext_package) - -configure_file( - input: meson.project_name() + '.gschema.xml.in', - output: application_id + '.gschema.xml', - configuration: schemas_conf, - install_dir: join_paths(akira_datadir, 'glib-2.0', 'schemas') -) diff --git a/data/screenshots/screenshot-1.png b/data/screenshots/screenshot-1.png deleted file mode 100644 index 77a4fd1ca..000000000 Binary files a/data/screenshots/screenshot-1.png and /dev/null differ diff --git a/data/screenshots/screenshot-2.png b/data/screenshots/screenshot-2.png deleted file mode 100644 index f025b2dfe..000000000 Binary files a/data/screenshots/screenshot-2.png and /dev/null differ diff --git a/data/screenshots/screenshot-3.png b/data/screenshots/screenshot-3.png deleted file mode 100644 index 61c43b3de..000000000 Binary files a/data/screenshots/screenshot-3.png and /dev/null differ diff --git a/data/screenshots/screenshot-4.png b/data/screenshots/screenshot-4.png deleted file mode 100644 index acd747f84..000000000 Binary files a/data/screenshots/screenshot-4.png and /dev/null differ diff --git a/meson.build b/meson.build deleted file mode 100644 index acbd73fff..000000000 --- a/meson.build +++ /dev/null @@ -1,72 +0,0 @@ -# project name and programming language -project('com.github.akiraux.akira', 'vala', 'c', - default_options: 'default_library=static') - -akira_prefix = get_option('prefix') -akira_datadir = join_paths(akira_prefix, get_option('datadir')) -akira_pkgdatadir = join_paths(akira_datadir, meson.project_name()) -install_tests = get_option('install-tests') - -source_root = meson.current_source_dir() -vapi_dir = join_paths(source_root, 'vapi') -add_project_arguments('--vapidir=' + vapi_dir, language: 'vala') - -# Include the translations module -i18n = import('i18n') -# Dependencies -gtk_dependency = dependency('gtk+-3.0') -granite_dependency = dependency('granite', version: '>= 6.0.0') -gee_dependency = dependency('gee-0.8') -libxml_dependency = dependency('libxml-2.0') -cairo_dependency = dependency('cairo', version: '>=1.14') -libarchive_dependency = dependency('libarchive') -json_glib_dependency = dependency('json-glib-1.0') - -# Optional dependencies -desktop_file_validate = find_program('desktop-file-validate', required: false) -appstream_util = find_program('appstream-util', required: false) - -# Include the gnome module -gnome = import('gnome') -asresources = gnome.compile_resources( - 'as-resources', 'data/assets.gresource.xml', - source_dir: 'data', - c_name: 'as' -) - -cc = meson.get_compiler('c') -m_dep = cc.find_library('m', required: true) - -vala_lint = find_program('io.elementary.vala-lint', required : false) -if vala_lint.found() - test ( - 'Vala lint', - vala_lint, - args: ['-d', join_paths(meson.source_root(), 'src')] - ) -endif - -# Set up the profile -profile = get_option('profile') -if profile == 'development' - application_id = meson.project_name() + 'Devel' - schema_path = '/com/github/akiraux/akiraDevel/' -else - application_id = meson.project_name() - schema_path = '/com/github/akiraux/akira/' -endif -gettext_package = application_id - -# Set our translation domain -add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format (gettext_package), language:'c') -add_global_arguments(['-DG_LOG_DOMAIN="Akira"'], language:'c') - -subdir('src') -subdir('data') -subdir('po') - -if install_tests - subdir('tests') -endif - -meson.add_install_script('aux/meson/post_install.py') diff --git a/meson_options.txt b/meson_options.txt deleted file mode 100644 index b475d4c26..000000000 --- a/meson_options.txt +++ /dev/null @@ -1,4 +0,0 @@ -option('profile', type: 'combo', choices: ['default', 'development'], value: 'default') - -option('install-tests', type : 'boolean', value : 'false', - description : 'install test executables') diff --git a/po/LINGUAS b/po/LINGUAS deleted file mode 100644 index ec99956ee..000000000 --- a/po/LINGUAS +++ /dev/null @@ -1,195 +0,0 @@ -da -mh -ps -rm -sn -uk -si -mk -hu -nv -id -mo -zh_HK -my -he -eu -ia -km -jv -as -cr -ay -kl -vi -ak -uz -kr -zu -gl -is -ha -lo -la -ii -kv -so -zh_CN -sa -ro -ff -cu -fi -lg -sm -te -ig -sw -iu -mt -ki -ky -zh -kk -oc -ko -su -ar -fr -ce -mi -bs -am -bn -dz -ny -tl -ty -br -ks -hi -th -sr -co -bg -io -nl -gd -hy -ch -ta -oj -nn -wa -bh -bm -pa -ur -az -yi -hr -bo -cs -fa -wo -cy -eo -pt -li -nr -fr_CA -lv -pi -lu -ho -ee -kw -tt -ts -sl -mg -om -ae -ug -ve -pl -sg -mr -tw -nd -lt -ast -af -ms -se -ti -fo -sma -ht -kn -nb -en_AU -lb -kj -sq -na -et -qu -ku -sd -en_CA -mn -to -fj -st -pt_BR -ja -xh -ab -ik -av -hz -ckb -ng -gv -ss -aa kg -rue -en_GB -tg -ba -ln -ga -cv -sc -el -tr -sk -za -fy -ie -dv -it -rw -ml -es -ca -os -gn -zh_TW -vo -bi -or -ru -be -no -gu -an -tk -ka -ne -rn -tn -de -sv -yo diff --git a/po/aa.po b/po/aa.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/aa.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ab.po b/po/ab.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ab.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ae.po b/po/ae.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ae.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/af.po b/po/af.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/af.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ak.po b/po/ak.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ak.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/am.po b/po/am.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/am.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/an.po b/po/an.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/an.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ar.po b/po/ar.po deleted file mode 100644 index d91cc1009..000000000 --- a/po/ar.po +++ /dev/null @@ -1,711 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: 2020-09-06 14:27+0300\n" -"PO-Revision-Date: \n" -"Last-Translator: \n" -"Language-Team: \n" -"Language: ar\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.4.1\n" -"X-Poedit-Basepath: ../src\n" -"X-Poedit-SearchPath-0: .\n" - -#: Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "التصدير الى:" - -#: Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "اختر مجلد" - -#: Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "الصيغة:" - -#: Dialogs/ExportDialog.vala:179 -msgid "Quality:" -msgstr "الجودة:" - -#: Dialogs/ExportDialog.vala:191 -msgid "Compression:" -msgstr "الضغط:" - -#: Dialogs/ExportDialog.vala:205 -msgid "Transparency:" -msgstr "الشفافية:" - -#: Dialogs/ExportDialog.vala:218 -msgid "Scale:" -msgstr "الحجم:" - -#: Dialogs/ExportDialog.vala:242 FileFormat/FileManager.vala:49 -#: FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "إلغاء" - -#: Dialogs/ExportDialog.vala:249 Dialogs/ShortcutsDialog.vala:63 -#: Layouts/HeaderBar.vala:112 -msgid "Export" -msgstr "تصدير" - -#: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing " -"features, random bugs, and black holes opening in your kitchen are to be " -"expected." -msgstr "" -"تحدير!\n" -"لا يزال أكيرا تحت التطوير وغير جاهز للاستخدام النهائي.عليك توقع العديد " -"من المزايا المفقودة والمشاكل البرمجية، وقد تؤدي الى ثقوب سوداء في مطبخك." - -#: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "قم بالتبرع" - -#: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "اقترح ترجمة" - -#: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "بلغ عن مشكلة" - -#: Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "التفضيلات" - -#: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 -#: Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "عام" - -#: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "الواجهة" - -#: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 -msgid "Shapes" -msgstr "الأشكال" - -#: Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "عن" - -#: Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "فتح آخر ملف تلقائياً:" - -#: Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "استخدام السمة الداكنة:" - -#: Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "عكس ترتيب اللوحات:" - -#: Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "عليك اعادة تشغيل البرنامج لتطبيق التغييرات." - -#: Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "نمط شريط الادوات" - -#: Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "أظهر اسماء الأزرار:" - -#: Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "إستخدم ايقونات رمزية:" - -#: Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "الألوان الافتراضية" - -#: Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "تحديد النمط الافتراضي المستخدم عند إنشاء شكل جديد." - -#: Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "لون الملء:" - -#: Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "تفعيل نمط الحد الخارجي:" - -#: Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "لون الحدود:" - -#: Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "سماكة الحدود:" - -#: Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "أداة تصميم لينكس" - -#: Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "شكراً لداعمينا الرائعين!" - -#: Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "عرض قائمة الداعمين" - -#: Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "نافذة جديدة:" - -#: Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "التفضيلات:" - -#: Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "خروج:" - -#: Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "وضع التقديم:" - -#: Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "ملف" - -#: Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "فتح:" - -#: Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "حفظ:" - -#: Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "حفظ باسم:" - -#: Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "تصدير اللوحات:" - -#: Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "تصدير العناصر المحددة:" - -#: Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "حدد المنطقة المراد تصديرها:" - -#: Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "مساحة العمل" - -#: Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "تكبير:" - -#: Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "تصغير:" - -#: Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "اعادة تعيين الحجم:" - -#: Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "إنشاء غرض" - -#: Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "المساحة الفنية:" - -#: Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "مستطيل:" - -#: Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "شكل بيضاوي:" - -#: Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "نص:" - -#: Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "صورة:" - -#: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "التحول" - -#: Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "ارفع المحدد:" - -#: Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "اخفض المحدد:" - -#: Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "ارفع المحدد للقمة:" - -#: Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "اخفض المحدد للقاع:" - -#: Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "قلب افقي:" - -#: Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "قلب عمودي:" - -#: FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "حفظ ملف أكيرا" - -#: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 -msgid "Save" -msgstr "حفظ" - -#: FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "ملفات أكيرا" - -#: FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "كل الملفات" - -#: FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "فتح ملف أكيرا" - -#: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 -msgid "Open" -msgstr "فتح" - -#: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "بدون عنوان" - -#: Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "القائمة" - -#: Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "ادراج" - -#: Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "تجميع" - -#: Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "تفكيك" - -#: Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "للأعلى" - -#: Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "للأسفل" - -#: Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "للقمة" - -#: Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "للقاع" - -#: Layouts/HeaderBar.vala:107 -msgid "Settings" -msgstr "الاعدادات" - -#: Layouts/HeaderBar.vala:118 -msgid "Difference" -msgstr "الفرق" - -#: Layouts/HeaderBar.vala:120 -msgid "Exclusion" -msgstr "استثناء" - -#: Layouts/HeaderBar.vala:122 -msgid "Intersect" -msgstr "تداخل" - -#: Layouts/HeaderBar.vala:124 -msgid "Union" -msgstr "اتحاد" - -#: Layouts/HeaderBar.vala:161 -msgid "New Window" -msgstr "نافذة جديدة" - -#: Layouts/HeaderBar.vala:182 -msgid "Open Recent" -msgstr "فتح المستندات الاخيرة" - -#: Layouts/HeaderBar.vala:195 -msgid "Save As" -msgstr "حفظ باسم" - -#: Layouts/HeaderBar.vala:204 -msgid "Quit" -msgstr "خروج" - -#: Layouts/HeaderBar.vala:237 -msgid "Artboard" -msgstr "مساحة فنية" - -#: Layouts/HeaderBar.vala:254 -msgid "Add Items" -msgstr "اضافة عناصر" - -#: Layouts/HeaderBar.vala:262 -msgid "Rectangle" -msgstr "مستطيل" - -#: Layouts/HeaderBar.vala:268 -msgid "Ellipse" -msgstr "شكل بيضاوي" - -#: Layouts/HeaderBar.vala:286 -msgid "Vector" -msgstr "متجه" - -#: Layouts/HeaderBar.vala:288 -msgid "Pencil" -msgstr "قلم رصاص" - -#: Layouts/HeaderBar.vala:291 -msgid "Text" -msgstr "نص" - -#: Layouts/HeaderBar.vala:297 -msgid "Image" -msgstr "صورة" - -#: Layouts/HeaderBar.vala:330 -msgid "Export Current Selection" -msgstr "تصدير العناصر المحددة" - -#: Layouts/HeaderBar.vala:336 -msgid "Export Artboards" -msgstr "تصدير اللوحات" - -#: Layouts/HeaderBar.vala:345 -msgid "Highlight Area to Export" -msgstr "حدد المنطقة المراد تصديرها" - -#: Layouts/HeaderBar.vala:391 -msgid "Main Menu" -msgstr "القائمة الرئيسة" - -#: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:224 -#: Services/ActionManager.vala:243 Services/ActionManager.vala:262 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "غير قادر فتح الملف في '%s'" - -#: Layouts/MainCanvas.vala:46 -msgid "Button was pressed!" -msgstr "تم ضغط زر!" - -#: Layouts/MainCanvas.vala:206 -msgid "Export completed!" -msgstr "انتهى التصدير!" - -#: Layouts/Partials/AlignItemsPanel.vala:48 -msgid "Distribute Horizontally" -msgstr "توزيع بشكل أفقي" - -#: Layouts/Partials/AlignItemsPanel.vala:50 -msgid "Distribute Vertically" -msgstr "توزيع بشكل عمودي" - -#: Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "محاذاة يساراً" - -#: Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "توسيط" - -#: Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "محاذاة يميناً" - -#: Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "محاذاة للقمة" - -#: Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "توسيط عمودي" - -#: Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "محاذة للأسفل" - -#: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 -#: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 -msgid "Lock Layer" -msgstr "قفل الطبقة" - -#: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 -#: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 -msgid "Hide Layer" -msgstr "اخفاء الطبقة" - -#: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 -msgid "Unlock Layer" -msgstr "فك قفل الطبقة" - -#: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 -msgid "Show Layer" -msgstr "اظهار الطبقة" - -#: Layouts/Partials/BorderItem.vala:121 -msgid "Choose border color" -msgstr "اختر لون الحدود" - -#: Layouts/Partials/BorderItem.vala:176 Layouts/Partials/FillItem.vala:178 -msgid "Pick color" -msgstr "اختر لون" - -#: Layouts/Partials/BorderItem.vala:191 -msgid "Remove border" -msgstr "ازالة الحدود" - -#: Layouts/Partials/BorderItem.vala:275 -msgid "Show border" -msgstr "اظهار الحدود" - -#: Layouts/Partials/BorderItem.vala:279 -msgid "Hide border" -msgstr "اخفاء الحدود" - -#: Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "النمط" - -#: Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "استدارة الحدود" - -#: Layouts/Partials/BorderRadiusPanel.vala:137 -msgid "Border radius options" -msgstr "خيارات استدارة الحدود" - -#: Layouts/Partials/BorderRadiusPanel.vala:199 -msgid "Autoscale Corners" -msgstr "حجم تلقائي للزوايا" - -#: Layouts/Partials/BorderRadiusPanel.vala:208 -msgid "Uniform Corners" -msgstr "توحيد الزوايا" - -#: Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "الحدود" - -#: Layouts/Partials/BordersPanel.vala:64 -msgid "Add border" -msgstr "اضافة حد" - -#: Layouts/Partials/FillItem.vala:114 -msgid "Choose fill color" -msgstr "اختر لون الملء" - -#: Layouts/Partials/FillItem.vala:193 -msgid "Remove fill color" -msgstr "ازالة لون الملء" - -#: Layouts/Partials/FillItem.vala:277 -msgid "Show fill color" -msgstr "أظهار لون الملء" - -#: Layouts/Partials/FillItem.vala:281 -msgid "Hide fill color" -msgstr "اخفاء لون الملئ" - -#: Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "التعبئات" - -#: Layouts/Partials/FillsPanel.vala:65 -msgid "Add fill color" -msgstr "اضف لون ملئ" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "س" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "الموقع الأفقي" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "ص" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "الموقع العمودي" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "ع" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "العرض" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "ط" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "الطول" - -#: Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "قفل النسبة" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "ر" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "Rotation degrees" -msgstr "درجات التدوير" - -#: Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "قلب افقي" - -#: Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "قلب عمودي" - -#: Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "الموقع" - -#: Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "الحجم" - -#: Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "الشفافية" - -#: Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "البحث عن طبقة" - -#: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "تكوين العرض، الرجاء الانتظار..." - -#: Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "بدون عنوان %i" - -#: Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "تصدير الصور..." - -#: Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i بكسل · %s" - -#: Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "جاري احضار حجم الصورة..." - -#: Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "تصغير" - -#: Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "اعادة تعيين التكبير" - -#: Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "تكبير" - -#: Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "تكبير" - -#: Services/ActionManager.vala:217 -msgid "No recently opened file available!" -msgstr "لا يوجد ملف مفتوح مؤخراً!" - -#: Services/ActionManager.vala:236 -msgid "No second most recently opened file available!" -msgstr "لا يوجد ملف ثاني مفتوح مؤخراً!" - -#: Services/ActionManager.vala:255 -msgid "No third most recently opened file available!" -msgstr "لا يوجد ملف ثالث مفتوح مؤخراً!" - -#: Services/ActionManager.vala:293 -msgid "Nothing selected to export!" -msgstr "لم يتم تحديد شيء لتصديره!" - -#: Services/ActionManager.vala:302 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "تصدير المساحات الفنية حاليا غير متوف...آسف 😑️" - -#: Services/ActionManager.vala:373 -msgid "Choose image file" -msgstr "اختر ملف صورة" - -#: Services/ActionManager.vala:373 -msgid "Select" -msgstr "اختر" - -#: Services/ActionManager.vala:373 -msgid "Close" -msgstr "اغلاق" - -#: Services/ActionManager.vala:442 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "خطأ . ملفات %s غير مدعومة!" - -#: Window.vala:121 -msgid "Are you sure you want to quit?" -msgstr "هل أنت متأكد انك تريد الخروج؟" - -#: Window.vala:122 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "كل البيانات التي لم يتم حفظها ستفقد ويستحيل استعادتها." - -#: Window.vala:124 -msgid "Quit without saving!" -msgstr "الخروج دون حفظ!" - -#: Window.vala:125 -msgid "Save file" -msgstr "حفظ ملف " diff --git a/po/as.po b/po/as.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/as.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ast.po b/po/ast.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ast.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/av.po b/po/av.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/av.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ay.po b/po/ay.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ay.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/az.po b/po/az.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/az.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ba.po b/po/ba.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ba.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/be.po b/po/be.po deleted file mode 100644 index 6188ef853..000000000 --- a/po/be.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" diff --git a/po/bg.po b/po/bg.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/bg.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/bh.po b/po/bh.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/bh.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/bi.po b/po/bi.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/bi.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/bm.po b/po/bm.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/bm.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/bn.po b/po/bn.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/bn.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/bo.po b/po/bo.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/bo.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/br.po b/po/br.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/br.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/bs.po b/po/bs.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/bs.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ca.po b/po/ca.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ca.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ce.po b/po/ce.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ce.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ch.po b/po/ch.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ch.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ckb.po b/po/ckb.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ckb.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/co.po b/po/co.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/co.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/cr.po b/po/cr.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/cr.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/cs.po b/po/cs.po deleted file mode 100644 index fb0b545a5..000000000 --- a/po/cs.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" diff --git a/po/cu.po b/po/cu.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/cu.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/cv.po b/po/cv.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/cv.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/cy.po b/po/cy.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/cy.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/da.po b/po/da.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/da.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/de.po b/po/de.po deleted file mode 100644 index ba16a987f..000000000 --- a/po/de.po +++ /dev/null @@ -1,672 +0,0 @@ -# -# XP312 < >, 2020. -# -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" -"Project-Id-Version: unnamed project\n" -"Last-Translator: XP312 < >\n" -"Language-Team: German < >\n" -"Language: de\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2020-09-03 14:38+0200\n" -"X-Generator: Gtranslator 3.36.0\n" - -#: Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "Exportiere nach:" - -#: Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "Ordner auswählen" - -#: Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "Format:" - -#: Dialogs/ExportDialog.vala:180 -msgid "Quality:" -msgstr "Qualität:" - -#: Dialogs/ExportDialog.vala:192 -msgid "Compression:" -msgstr "Kompression:" - -#: Dialogs/ExportDialog.vala:206 -msgid "Transparency:" -msgstr "Transparenz:" - -#: Dialogs/ExportDialog.vala:219 -msgid "Scale:" -msgstr "Größe:" - -#: Dialogs/ExportDialog.vala:243 FileFormat/FileManager.vala:49 -#: FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "Abbrechen" - -#: Dialogs/ExportDialog.vala:250 Dialogs/ShortcutsDialog.vala:63 -#: Layouts/HeaderBar.vala:112 -msgid "Export" -msgstr "Exportieren" - -#: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing " -"features, random bugs, and black holes opening in your kitchen are to be " -"expected." -msgstr "" -"ACHTUNG:\n" -"Akira ist noch in Entwicklung und deshalb noch nicht für die Verwendung in der Produktion geeignet." -"Fehlende Funktionen, Bugs und schwarze Löcher die sich in der Küche öffnen " -"sind zu erwarten." - -#: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "Für das Projekt spenden" - -#: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "Übersetzungen vorschlagen" - -#: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "Fehler melden" - -#: Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "Einstellungen" - -#: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 -#: Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "Allgemein" - -#: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "Oberfläche" - -#: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 -msgid "Shapes" -msgstr "Formen" - -#: Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "Über" - -#: Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "Automatisch die letzte Datei erneut öffnen:" - -#: Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "Schwarzes Thema nutzen:" - -#: Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "Reihenfolge der Panels umkehren:" - -#: Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "Anwendungen neustarten um Änderungen zu übernehmen." - -#: Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "Werkzeugleistenstil" - -#: Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "Knopfbeschreibungen anzeigen:" - -#: Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "Symbolische Icons nutzen:" - -#: Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "Standardfarben" - -#: Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "Definierung des Standardaussehens einer neuen Form." - -#: Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "Füllfarbe:" - -#: Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "Aktiviere Ränderstil:" - -#: Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "Ränder Farbe:" - -#: Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "Ränder Breite:" - -#: Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "Das Linux Designwerkzeug" - -#: Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "Danke an unsere tollen Unterstützer!" - -#: Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "Liste aller Unterstützer" - -#: Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "Neues Fenster:" - -#: Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "Einstellungen:" - -#: Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "Beenden:" - -#: Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "Präsentationsmodus:" - -#: Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "Datei" - -#: Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "Öffnen:" - -#: Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "Speichern:" - -#: Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "Speichern als:" - -#: Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "Zeichenbrett exportieren:" - -#: Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "Auswahl exportieren:" - -#: Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "Bereich zum exportieren auswählen:" - -#: Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "Leinwand" - -#: Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "Vergrößern" - -#: Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "Verkleinern" - -#: Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "Zoom zurücksetzen" - -#: Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "Objekterstellung" - -#: Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "Zeichenbrett:" - -#: Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "Rechteck:" - -#: Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "Ellipse:" - -#: Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "Text:" - -#: Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "Foto:" - -#: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "Transformieren" - -#: Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "Auswahl erhöhen:" - -#: Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "Auswahl verringern:" - -#: Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "Auswahl nach oben erhöhen:" - -#: Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "Auswahl nach unten verringern:" - -#: Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "Horizontal drehen:" - -#: Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "Vertikal drehen:" - -#: FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "Akira-Datei speichern" - -#: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 -msgid "Save" -msgstr "Speichern" - -#: FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "Akira-Dateien" - -#: FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "Alle Dateien" - -#: FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "Akira-Datei öffnen" - -#: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 -msgid "Open" -msgstr "Öffnen" - -#: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "Nicht gespeichert" - -#: Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "Menü" - -#: Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "Einfügen" - -#: Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "Gruppieren" - -#: Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "Gruppierung aufheben" - -#: Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "Hoch" - -#: Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "Runter" - -#: Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "Oben" - -#: Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "Unten" - -#: Layouts/HeaderBar.vala:107 -msgid "Settings" -msgstr "Einstellungen" - -# ? -#: Layouts/HeaderBar.vala:118 -#, fuzzy -msgid "Difference" -msgstr "Differenz" - -#: Layouts/HeaderBar.vala:120 -#, fuzzy -msgid "Exclusion" -msgstr "Ausgrenzen" - -#: Layouts/HeaderBar.vala:122 -#, fuzzy -msgid "Intersect" -msgstr "Überschneiden" - -#: Layouts/HeaderBar.vala:124 -msgid "Union" -msgstr "Verbinden" - -#: Layouts/HeaderBar.vala:161 -msgid "New Window" -msgstr "Neues Fenster" - -#: Layouts/HeaderBar.vala:182 -msgid "Open Recent" -msgstr "Zuletzt geöffnet" - -#: Layouts/HeaderBar.vala:195 -msgid "Save As" -msgstr "Speichern als" - -#: Layouts/HeaderBar.vala:204 -msgid "Quit" -msgstr "Schließen" - -#: Layouts/HeaderBar.vala:237 -msgid "Artboard" -msgstr "Zeichenbrett" - -#: Layouts/HeaderBar.vala:254 -msgid "Add Items" -msgstr "Objekt hinzufügen" - -#: Layouts/HeaderBar.vala:262 -msgid "Rectangle" -msgstr "Rechteck" - -#: Layouts/HeaderBar.vala:268 -msgid "Ellipse" -msgstr "Ellipse" - -#: Layouts/HeaderBar.vala:286 -msgid "Vector" -msgstr "Vektor" - -#: Layouts/HeaderBar.vala:288 -msgid "Pencil" -msgstr "Stift" - -#: Layouts/HeaderBar.vala:291 -msgid "Text" -msgstr "Text" - -#: Layouts/HeaderBar.vala:297 -msgid "Image" -msgstr "Bild" - -#: Layouts/HeaderBar.vala:330 -msgid "Export Current Selection" -msgstr "Aktuelle Auswahl exportieren" - -#: Layouts/HeaderBar.vala:336 -msgid "Export Artboards" -msgstr "Aktuelles Zeichenbrett exportieren" - -#: Layouts/HeaderBar.vala:345 -msgid "Highlight Area to Export" -msgstr "Bereich zum Exportieren auswählen" - -#: Layouts/HeaderBar.vala:391 -msgid "Main Menu" -msgstr "Hauptmenü" - -#: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:218 -#: Services/ActionManager.vala:237 Services/ActionManager.vala:256 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "Konnte Datei \"%s\" nicht öffnen" - -#: Layouts/MainCanvas.vala:52 -msgid "Button was pressed!" -msgstr "Knopf wurde gedrückt!" - -#: Layouts/MainCanvas.vala:160 -msgid "Export completed!" -msgstr "Export abgeschlossen!" - -#: Layouts/Partials/AlignItemsPanel.vala:48 -#, fuzzy -msgid "Distribute Horizontally" -msgstr "Horizontall verteilen" - -#: Layouts/Partials/AlignItemsPanel.vala:50 -#, fuzzy -msgid "Distribute Vertically" -msgstr "Vertikal verteilen" - -#: Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "Links ausrichten" - -#: Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "Zentral ausrichten" - -#: Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "Rechts ausrichten" - -#: Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "Nach oben ausrichten" - -#: Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "Mittig ausrichten" - -#: Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "Nach unten ausrichten" - -#: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 -#: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 -msgid "Lock Layer" -msgstr "Ebene sperren" - -#: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 -#: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 -msgid "Hide Layer" -msgstr "Ebene verstecken" - -#: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 -msgid "Unlock Layer" -msgstr "Ebene entsperren" - -#: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 -msgid "Show Layer" -msgstr "Ebene anzeigen" - -#: Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "Stil" - -#: Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "Randradius" - -#: Layouts/Partials/BorderRadiusPanel.vala:198 -msgid "Autoscale Corners" -msgstr "Ecken Automatisch skallieren" - -#: Layouts/Partials/BorderRadiusPanel.vala:207 -msgid "Uniform Corners" -msgstr "Ecken angleichen" - -#: Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "Ränder" - -#: Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "Füllungen" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "X" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "Horizontale Position" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "Y" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "Vertikale Position" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "W" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "Breite" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "H" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "Höhe" - -#: Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "Rotation sperren" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "R" - -#: Layouts/Partials/TransformPanel.vala:114 -#, fuzzy -msgid "Rotation degrees" -msgstr "Rotationsgrad" - -#: Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "Horizontahl drehen" - -#: Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "Vertikal drehen" - -#: Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "Position" - -#: Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "Größe" - -#: Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "Deckkraft" - -#: Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "Ebenensuche" - -#: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "Vorschau wird generiert, bitte warten..." - -#: Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "Unbenannt %i" - -#: Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "Exportiere Bilder..." - -#: Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i px · %s" - -#: Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "Frage Bildgröße ab..." - -#: Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "Verkleinern" - -#: Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "Zoom zurücksetzen" - -#: Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "Vergrößern" - -#: Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "Zoom" - -#: Services/ActionManager.vala:211 -msgid "No recently opened file available!" -msgstr "Keine zuletzt geöffnete Datei vorhanden!" - -#: Services/ActionManager.vala:230 -msgid "No second most recently opened file available!" -msgstr "Keine zweit zuletzt geöffnete Datei vorhanden!" - -#: Services/ActionManager.vala:249 -msgid "No third most recently opened file available!" -msgstr "Keine dritt zuletzt geöffnete Datei vorhanden!" - -#: Services/ActionManager.vala:287 -msgid "Nothing selected to export!" -msgstr "Nichts zum Exportieren ausgewählt!" - -#: Services/ActionManager.vala:296 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "Das Exportieren von Zeichenbrettern ist momentan leider nicht möglich… 😑️" - -#: Services/ActionManager.vala:363 -msgid "Choose image file" -msgstr "Bilddatei auswählen" - -#: Services/ActionManager.vala:363 -msgid "Select" -msgstr "Auswählen" - -#: Services/ActionManager.vala:363 -msgid "Close" -msgstr "Schließen" - -#: Services/ActionManager.vala:432 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "Fehler: .%s Dateien werden nicht Unterstützt." - -#: Window.vala:119 -msgid "Are you sure you want to quit?" -msgstr "Soll das Programm wirklich geschlossen werden?" - -#: Window.vala:120 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "Alle nicht gespeicherten Dateien gehen verloren und können nicht wiederhergestellt werden." - -#: Window.vala:122 -msgid "Quit without saving!" -msgstr "Ohne speichern schließen!" - -#: Window.vala:123 -msgid "Save file" -msgstr "Datei speichern" diff --git a/po/dv.po b/po/dv.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/dv.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/dz.po b/po/dz.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/dz.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ee.po b/po/ee.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ee.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/el.po b/po/el.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/el.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/en_AU.po b/po/en_AU.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/en_AU.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/en_CA.po b/po/en_CA.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/en_CA.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/en_GB.po b/po/en_GB.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/en_GB.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/eo.po b/po/eo.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/eo.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/es.po b/po/es.po deleted file mode 100644 index e2249bc25..000000000 --- a/po/es.po +++ /dev/null @@ -1,666 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: 2020-08-12 22:06-0500\n" -"PO-Revision-Date: \n" -"Last-Translator: Adolfo Jayme Barrientos \n" -"Language-Team: \n" -"Language: es\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Poedit 2.4.1\n" -"X-Poedit-Basepath: ../src\n" -"X-Poedit-SearchPath-0: .\n" - -#: Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "Exportar en:" - -#: Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "Seleccionar carpeta" - -#: Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "Formato:" - -#: Dialogs/ExportDialog.vala:180 -msgid "Quality:" -msgstr "Calidad:" - -#: Dialogs/ExportDialog.vala:192 -msgid "Compression:" -msgstr "Compresión:" - -#: Dialogs/ExportDialog.vala:206 -msgid "Transparency:" -msgstr "Transparencia:" - -#: Dialogs/ExportDialog.vala:219 -msgid "Scale:" -msgstr "Escala:" - -#: Dialogs/ExportDialog.vala:243 FileFormat/FileManager.vala:49 -#: FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "Cancelar" - -#: Dialogs/ExportDialog.vala:250 Dialogs/ShortcutsDialog.vala:63 -#: Layouts/HeaderBar.vala:112 -msgid "Export" -msgstr "Exportar" - -#: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing " -"features, random bugs, and black holes opening in your kitchen are to be " -"expected." -msgstr "" -"ATENCIÓN:\n" -"Akira se encuentra en desarrollo y no está destinado a entornos de " -"producción. Es de esperar que falten funciones y haya defectos inesperados." - -#: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "Donar" - -#: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "Sugerir traducciones" - -#: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "Informar de un problema" - -#: Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "Preferencias" - -#: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 -#: Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "Generales" - -#: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "Interfaz" - -#: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 -msgid "Shapes" -msgstr "Formas" - -#: Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "Acerca de" - -#: Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "Reabrir automáticamente archivo más reciente:" - -#: Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "Utilizar tema oscuro:" - -#: Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "Intercambiar posición de paneles:" - -#: Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "Reinicie la aplicación para aplicar el cambio." - -#: Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "Estilo de barra de herramientas" - -#: Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "Mostrar etiquetas de botones:" - -#: Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "Utilizar iconos monocromáticos:" - -#: Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "Colores predeterminados" - -#: Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "" -"Defina el estilo que se utilizará de manera predeterminada al crear formas." - -#: Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "Color de relleno:" - -#: Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "Activar estilo con borde:" - -#: Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "Color de borde:" - -#: Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "Anchura de borde:" - -#: Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "La herramienta de diseño para Linux" - -#: Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "¡Gracias a nuestros geniales partidarios!" - -#: Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "Ver lista de partidarios" - -#: Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "Ventana nueva:" - -#: Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "Preferencias:" - -#: Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "Salir:" - -#: Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "Modo de presentación:" - -#: Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "Archivo" - -#: Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "Abrir:" - -#: Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "Guardar:" - -#: Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "Guardar como:" - -#: Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "Exportar mesas de trabajo:" - -#: Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "Exportar selección:" - -#: Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "Resaltar área que exportar:" - -#: Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "Lienzo" - -#: Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "Acercar" - -#: Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "Alejar" - -#: Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "Restablecer escala:" - -#: Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "Creación de elemento" - -#: Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "Mesa de trabajo:" - -#: Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "Rectángulo:" - -#: Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "Elipse:" - -#: Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "Texto:" - -#: Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "Imagen:" - -#: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "Transformar" - -#: Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "Subir selección:" - -#: Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "Bajar selección:" - -#: Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "Traer selección hasta arriba:" - -#: Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "Enviar selección hasta abajo:" - -#: Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "Voltear horizontalmente:" - -#: Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "Voltear verticalmente:" - -#: FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "Guardar archivo de Akira" - -#: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 -msgid "Save" -msgstr "Guardar" - -#: FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "Archivos de Akira" - -#: FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "Todos los archivos" - -#: FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "Abrir archivo de Akira" - -#: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 -msgid "Open" -msgstr "Abrir" - -#: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "Sin título" - -#: Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "Menú" - -#: Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "Insertar" - -#: Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "Agrupar" - -#: Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "Desagrupar" - -#: Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "Subir" - -#: Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "Bajar" - -#: Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "Al principio" - -#: Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "Al final" - -#: Layouts/HeaderBar.vala:107 -msgid "Settings" -msgstr "Configuración" - -#: Layouts/HeaderBar.vala:118 -msgid "Difference" -msgstr "Diferencia" - -#: Layouts/HeaderBar.vala:120 -msgid "Exclusion" -msgstr "Exclusión" - -#: Layouts/HeaderBar.vala:122 -msgid "Intersect" -msgstr "Intersección" - -#: Layouts/HeaderBar.vala:124 -msgid "Union" -msgstr "Unión" - -#: Layouts/HeaderBar.vala:161 -msgid "New Window" -msgstr "Ventana nueva" - -#: Layouts/HeaderBar.vala:182 -msgid "Open Recent" -msgstr "Abrir recientes" - -#: Layouts/HeaderBar.vala:195 -msgid "Save As" -msgstr "Guardar como" - -#: Layouts/HeaderBar.vala:204 -msgid "Quit" -msgstr "Salir" - -#: Layouts/HeaderBar.vala:237 -msgid "Artboard" -msgstr "Mesa de trabajo" - -#: Layouts/HeaderBar.vala:254 -msgid "Add Items" -msgstr "Añadir elementos" - -#: Layouts/HeaderBar.vala:262 -msgid "Rectangle" -msgstr "Rectángulo" - -#: Layouts/HeaderBar.vala:268 -msgid "Ellipse" -msgstr "Elipse" - -#: Layouts/HeaderBar.vala:286 -msgid "Vector" -msgstr "Vector" - -#: Layouts/HeaderBar.vala:288 -msgid "Pencil" -msgstr "Lápiz" - -#: Layouts/HeaderBar.vala:291 -msgid "Text" -msgstr "Texto" - -#: Layouts/HeaderBar.vala:297 -msgid "Image" -msgstr "Imagen" - -#: Layouts/HeaderBar.vala:330 -msgid "Export Current Selection" -msgstr "Exportar selección actual" - -#: Layouts/HeaderBar.vala:336 -msgid "Export Artboards" -msgstr "Exportar mesas de trabajo" - -#: Layouts/HeaderBar.vala:345 -msgid "Highlight Area to Export" -msgstr "Resaltar área que exportar" - -#: Layouts/HeaderBar.vala:391 -msgid "Main Menu" -msgstr "Menú principal" - -#: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:218 -#: Services/ActionManager.vala:237 Services/ActionManager.vala:256 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "No se puede abrir el archivo en «%s»" - -#: Layouts/MainCanvas.vala:52 -msgid "Button was pressed!" -msgstr "Se ha presionado el botón." - -#: Layouts/MainCanvas.vala:160 -msgid "Export completed!" -msgstr "Finalizó la exportación." - -#: Layouts/Partials/AlignItemsPanel.vala:48 -msgid "Distribute Horizontally" -msgstr "Distribuir horizontalmente" - -#: Layouts/Partials/AlignItemsPanel.vala:50 -msgid "Distribute Vertically" -msgstr "Distribuir verticalmente" - -#: Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "Alinear a la izquierda" - -#: Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "Centrar horizontalmente" - -#: Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "Alinear a la derecha" - -#: Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "Alinear arriba" - -#: Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "Centrar verticalmente" - -#: Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "Alinear abajo" - -#: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 -#: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 -msgid "Lock Layer" -msgstr "Bloquear capa" - -#: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 -#: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 -msgid "Hide Layer" -msgstr "Ocultar capa" - -#: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 -msgid "Unlock Layer" -msgstr "Desbloquear capa" - -#: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 -msgid "Show Layer" -msgstr "Mostrar capa" - -#: Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "Estilo" - -#: Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "Radio de borde" - -#: Layouts/Partials/BorderRadiusPanel.vala:198 -msgid "Autoscale Corners" -msgstr "Escalar esquinas automáticamente" - -#: Layouts/Partials/BorderRadiusPanel.vala:207 -msgid "Uniform Corners" -msgstr "Esquinas uniformes" - -#: Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "Bordes" - -#: Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "Rellenos" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "X" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "Posición horizontal" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "Y" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "Posición vertical" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "↔" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "Anchura" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "↕" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "Altura" - -#: Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "Bloquear relación" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "↻" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "Rotation degrees" -msgstr "Grados de giro" - -#: Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "Voltear horizontalmente" - -#: Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "Voltear verticalmente" - -#: Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "Posición" - -#: Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "Tamaño" - -#: Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "Opacidad" - -#: Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "Buscar capa" - -#: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "Generando previsualización; espere…" - -#: Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "Sin título %i" - -#: Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "Exportando imágenes…" - -#: Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i px · %s" - -#: Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "Recuperando tamaño de imagen…" - -#: Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "Alejar" - -#: Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "Restablecer escala" - -#: Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "Acercar" - -#: Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "Escala" - -#: Services/ActionManager.vala:211 -msgid "No recently opened file available!" -msgstr "No hay ningún archivo reciente." - -#: Services/ActionManager.vala:230 -msgid "No second most recently opened file available!" -msgstr "No hay ningún segundo archivo reciente." - -#: Services/ActionManager.vala:249 -msgid "No third most recently opened file available!" -msgstr "No hay ningún tercer archivo reciente." - -#: Services/ActionManager.vala:287 -msgid "Nothing selected to export!" -msgstr "No se ha seleccionado nada para exportar." - -#: Services/ActionManager.vala:296 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "" -"La exportación de mesas de trabajo no está disponible por el momento… 😑️" - -#: Services/ActionManager.vala:363 -msgid "Choose image file" -msgstr "Seleccionar archivo de imagen" - -#: Services/ActionManager.vala:363 -msgid "Select" -msgstr "Seleccionar" - -#: Services/ActionManager.vala:363 -msgid "Close" -msgstr "Cerrar" - -#: Services/ActionManager.vala:432 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "Error: no se admiten los archivos .%s." - -#: Window.vala:119 -msgid "Are you sure you want to quit?" -msgstr "¿Confirma que quiere salir?" - -#: Window.vala:120 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "Se perderán los datos no guardados y no podrán recuperarse." - -#: Window.vala:122 -msgid "Quit without saving!" -msgstr "Salir sin guardar" - -#: Window.vala:123 -msgid "Save file" -msgstr "Guardar archivo" diff --git a/po/et.po b/po/et.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/et.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/eu.po b/po/eu.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/eu.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/fa.po b/po/fa.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/fa.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ff.po b/po/ff.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ff.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/fi.po b/po/fi.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/fi.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/fj.po b/po/fj.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/fj.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/fo.po b/po/fo.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/fo.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/fr.po b/po/fr.po deleted file mode 100644 index 7c83c6877..000000000 --- a/po/fr.po +++ /dev/null @@ -1,724 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: 2020-10-07 21:17+0200\n" -"PO-Revision-Date: 2020-10-31 14:08+0100\n" -"Last-Translator: Yannicka\n" -"Language-Team: \n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.4.1\n" -"X-Poedit-Basepath: .\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Poedit-SearchPath-0: .\n" - -#: src/Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "Exporter vers :" - -#: src/Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "Sélectionner un dossier" - -#: src/Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "Format :" - -#: src/Dialogs/ExportDialog.vala:179 -msgid "Quality:" -msgstr "Qualité :" - -#: src/Dialogs/ExportDialog.vala:191 -msgid "Compression:" -msgstr "Compression :" - -#: src/Dialogs/ExportDialog.vala:205 -msgid "Transparency:" -msgstr "Transparence :" - -#: src/Dialogs/ExportDialog.vala:218 -msgid "Scale:" -msgstr "Échelle :" - -#: src/Dialogs/ExportDialog.vala:242 src/FileFormat/FileManager.vala:49 -#: src/FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "Annuler" - -#: src/Dialogs/ExportDialog.vala:249 src/Dialogs/ShortcutsDialog.vala:63 -#: src/Layouts/HeaderBar.vala:112 -msgid "Export" -msgstr "Exporter" - -#: src/Dialogs/ReleaseDialog.vala:47 src/Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing " -"features, random bugs, and black holes opening in your kitchen are to be " -"expected." -msgstr "" -"ATTENTION !\n" -"Akira est encore en cours de développement et n'est pas prêt à être " -"utilisé en production. Attendez-vous à ce que des fonctionnalités " -"manquent, des bugs se produisent voire qu'un trou noir s'ouvre dans votre " -"cuisine." - -#: src/Dialogs/ReleaseDialog.vala:100 src/Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "Faire un don" - -#: src/Dialogs/ReleaseDialog.vala:109 src/Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "Suggérer des traductions" - -#: src/Dialogs/ReleaseDialog.vala:118 src/Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "Signaler un problème" - -#: src/Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "Préférences" - -#: src/Dialogs/SettingsDialog.vala:50 src/Dialogs/SettingsDialog.vala:73 -#: src/Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "Général" - -#: src/Dialogs/SettingsDialog.vala:51 src/Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "Interface" - -#: src/Dialogs/SettingsDialog.vala:52 src/Layouts/HeaderBar.vala:280 -msgid "Shapes" -msgstr "Formes" - -#: src/Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "À propos" - -#: src/Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "Rouvrir automatiquement le dernier fichier :" - -#: src/Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "Utiliser le thème sombre :" - -#: src/Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "Inverser l'ordre des barres latérales :" - -#: src/Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "Redémarrez l'application pour appliquer ce changement." - -#: src/Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "Style de la barre d'outils" - -#: src/Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "Afficher l'étiquette des boutons :" - -#: src/Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "Utiliser les icônes symboliques :" - -#: src/Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "Couleurs par défaut" - -#: src/Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "" -"Définit le style par défaut utilisé lors de la création d'une nouvelle " -"forme." - -#: src/Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "Couleur de remplissage :" - -#: src/Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "Activer le style de bordure :" - -#: src/Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "Couleur de la bordure :" - -#: src/Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "Largeur de la bordure :" - -#: src/Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "L'outil de conception Linux" - -#: src/Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "Merci à toutes les merveilleuses personnes qui nous soutiennent !" - -#: src/Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "Voir la liste des personnes qui soutiennent le projet" - -#: src/Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "Nouvelle fenêtre :" - -#: src/Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "Préférences :" - -#: src/Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "Quitter :" - -#: src/Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "Mode présentation :" - -#: src/Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "Ficher" - -#: src/Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "Ouvrir :" - -#: src/Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "Enregistrer :" - -#: src/Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "Enregistrer sous :" - -#: src/Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "Exporter les espaces de travail :" - -#: src/Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "Exporter la sélection :" - -#: src/Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "Sélectionner la zone à exporter :" - -#: src/Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "Canevas" - -#: src/Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "Zoomer :" - -#: src/Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "Dézoomer :" - -#: src/Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "Réinitialiser le zoom :" - -#: src/Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "Création d'élément" - -#: src/Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "Espace de travail :" - -#: src/Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "Rectangle :" - -#: src/Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "Ellipse :" - -#: src/Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "Texte :" - -#: src/Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "Image :" - -#: src/Dialogs/ShortcutsDialog.vala:97 -#: src/Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "Transformer" - -#: src/Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "Monter la sélection :" - -#: src/Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "Descendre la sélection :" - -#: src/Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "Monter la sélection tout en haut :" - -#: src/Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "Descendre la sélection tout en bas :" - -#: src/Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "Retourner horizontalement :" - -#: src/Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "Retourner verticalement :" - -#: src/FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "Enregistrer un fichier Akira" - -#: src/FileFormat/FileManager.vala:48 src/Layouts/HeaderBar.vala:190 -msgid "Save" -msgstr "Enregistrer" - -#: src/FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "Fichiers Akira" - -#: src/FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "Tous les fichiers" - -#: src/FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "Ouvrir un fichier Akira" - -#: src/FileFormat/FileManager.vala:105 src/Layouts/HeaderBar.vala:170 -msgid "Open" -msgstr "Ouvrir" - -#: src/Layouts/HeaderBar.vala:69 src/Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "Sans titre" - -#: src/Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "Menu" - -#: src/Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "Insérer" - -#: src/Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "Grouper" - -#: src/Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "Dégrouper" - -#: src/Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "Monter" - -#: src/Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "Descendre" - -#: src/Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "Devant" - -#: src/Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "Derrière" - -#: src/Layouts/HeaderBar.vala:107 -msgid "Settings" -msgstr "Paramètres" - -#: src/Layouts/HeaderBar.vala:118 -msgid "Difference" -msgstr "Différence" - -#: src/Layouts/HeaderBar.vala:120 -msgid "Exclusion" -msgstr "Exclusion" - -#: src/Layouts/HeaderBar.vala:122 -msgid "Intersect" -msgstr "Intersection" - -#: src/Layouts/HeaderBar.vala:124 -msgid "Union" -msgstr "Union" - -#: src/Layouts/HeaderBar.vala:161 -msgid "New Window" -msgstr "Nouvelle fenêtre" - -#: src/Layouts/HeaderBar.vala:182 -msgid "Open Recent" -msgstr "Ouvert récemment" - -#: src/Layouts/HeaderBar.vala:195 -msgid "Save As" -msgstr "Enregistrer sous..." - -#: src/Layouts/HeaderBar.vala:204 -msgid "Quit" -msgstr "Quitter" - -#: src/Layouts/HeaderBar.vala:237 -msgid "Artboard" -msgstr "Espace de travail" - -#: src/Layouts/HeaderBar.vala:254 -msgid "Add Items" -msgstr "Ajouter des éléments" - -#: src/Layouts/HeaderBar.vala:262 -msgid "Rectangle" -msgstr "Rectangle" - -#: src/Layouts/HeaderBar.vala:268 -msgid "Ellipse" -msgstr "Ellipse" - -#: src/Layouts/HeaderBar.vala:286 -msgid "Vector" -msgstr "Vecteur" - -#: src/Layouts/HeaderBar.vala:288 -msgid "Pencil" -msgstr "Crayon" - -#: src/Layouts/HeaderBar.vala:291 -msgid "Text" -msgstr "Texte" - -#: src/Layouts/HeaderBar.vala:297 -msgid "Image" -msgstr "Image" - -#: src/Layouts/HeaderBar.vala:330 -msgid "Export Current Selection" -msgstr "Exporter la sélection courante" - -#: src/Layouts/HeaderBar.vala:336 -msgid "Export Artboards" -msgstr "Exporter les espaces de travail" - -#: src/Layouts/HeaderBar.vala:345 -msgid "Highlight Area to Export" -msgstr "Sélectionner la zone à exporter" - -#: src/Layouts/HeaderBar.vala:391 -msgid "Main Menu" -msgstr "Menu principal" - -#: src/Layouts/HeaderBar.vala:468 src/Services/ActionManager.vala:224 -#: src/Services/ActionManager.vala:243 src/Services/ActionManager.vala:262 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "Impossible d'ouvrir le fichier « %s »" - -#: src/Layouts/MainCanvas.vala:46 -msgid "Button was pressed!" -msgstr "Un bouton a été pressé !" - -#: src/Layouts/MainCanvas.vala:206 -msgid "Export completed!" -msgstr "Export terminée !" - -#: src/Layouts/Partials/AlignItemsPanel.vala:48 -msgid "Distribute Horizontally" -msgstr "Distribuer horizontalement" - -#: src/Layouts/Partials/AlignItemsPanel.vala:50 -msgid "Distribute Vertically" -msgstr "Distribuer verticalement" - -#: src/Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "Aligner à gauche" - -#: src/Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "Aligner au centre" - -#: src/Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "Aligner à droite" - -#: src/Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "Aligner en haut" - -#: src/Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "Aligner au milieu" - -#: src/Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "Aligner en bas" - -#: src/Layouts/Partials/Artboard.vala:144 -#: src/Layouts/Partials/Artboard.vala:487 src/Layouts/Partials/Layer.vala:139 -#: src/Layouts/Partials/Layer.vala:687 -msgid "Lock Layer" -msgstr "Verrouiller le calque" - -#: src/Layouts/Partials/Artboard.vala:155 -#: src/Layouts/Partials/Artboard.vala:529 src/Layouts/Partials/Layer.vala:156 -#: src/Layouts/Partials/Layer.vala:729 -msgid "Hide Layer" -msgstr "Cacher le calque" - -#: src/Layouts/Partials/Artboard.vala:487 src/Layouts/Partials/Layer.vala:687 -msgid "Unlock Layer" -msgstr "Dévérouiller le calque" - -#: src/Layouts/Partials/Artboard.vala:529 src/Layouts/Partials/Layer.vala:729 -msgid "Show Layer" -msgstr "Afficher le calque" - -#: src/Layouts/Partials/BorderItem.vala:121 -msgid "Choose border color" -msgstr "Choisir la couleur de la bordure" - -#: src/Layouts/Partials/BorderItem.vala:176 -#: src/Layouts/Partials/FillItem.vala:178 -msgid "Pick color" -msgstr "Choisir une couleur" - -#: src/Layouts/Partials/BorderItem.vala:191 -msgid "Remove border" -msgstr "Supprimer la bordure" - -#: src/Layouts/Partials/BorderItem.vala:275 -msgid "Show border" -msgstr "Afficher la bordure" - -#: src/Layouts/Partials/BorderItem.vala:279 -msgid "Hide border" -msgstr "Masquer la bordure" - -#: src/Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "Style" - -#: src/Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "Arrondi" - -#: src/Layouts/Partials/BorderRadiusPanel.vala:137 -msgid "Border radius options" -msgstr "Options de l'arrondi" - -#: src/Layouts/Partials/BorderRadiusPanel.vala:199 -msgid "Autoscale Corners" -msgstr "Mise à l'échelle automatique des coins" - -#: src/Layouts/Partials/BorderRadiusPanel.vala:208 -msgid "Uniform Corners" -msgstr "Coins uniformes" - -#: src/Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "Bordures" - -#: src/Layouts/Partials/BordersPanel.vala:64 -msgid "Add border" -msgstr "Ajouter une bordure" - -#: src/Layouts/Partials/FillItem.vala:114 -msgid "Choose fill color" -msgstr "Choisir la couleur de remplissage" - -#: src/Layouts/Partials/FillItem.vala:193 -msgid "Remove fill color" -msgstr "Supprimer la couleur de remplissage" - -#: src/Layouts/Partials/FillItem.vala:277 -msgid "Show fill color" -msgstr "Afficher la couleur de remplissage" - -#: src/Layouts/Partials/FillItem.vala:281 -msgid "Hide fill color" -msgstr "Masquer la couleur de remplissage" - -#: src/Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "Remplissages" - -#: src/Layouts/Partials/FillsPanel.vala:65 -msgid "Add fill color" -msgstr "Ajouter une couleur de remplissage" - -#: src/Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "X" - -#: src/Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "Position horizontale" - -#: src/Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "Y" - -#: src/Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "Position verticale" - -#: src/Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "L" - -#: src/Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "Largeur" - -#: src/Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "H" - -#: src/Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "Hauteur" - -#: src/Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "Verrouiller le ratio" - -#: src/Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "A" - -#: src/Layouts/Partials/TransformPanel.vala:114 -msgid "Rotation degrees" -msgstr "Angle de rotation" - -#: src/Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "Retourner horizontalement" - -#: src/Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "Retourner verticalement" - -#: src/Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "Position" - -#: src/Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "Taille" - -#: src/Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "Opacité" - -#: src/Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "Rechercher un calque" - -#: src/Lib/Managers/ExportManager.vala:192 -#: src/Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "Génération de l'aperçu, veuillez patienter…" - -#: src/Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "Sans titre %i" - -#: src/Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "Export des images en cours…" - -#: src/Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i px · %s" - -#: src/Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "Récupération de la taille de l'image…" - -#: src/Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "Dézoomer" - -#: src/Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "Réinitialiser le zoom" - -#: src/Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "Zoomer" - -#: src/Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "Zoom" - -#: src/Services/ActionManager.vala:217 -msgid "No recently opened file available!" -msgstr "Aucun dossier récemment ouvert n'est disponible !" - -#: src/Services/ActionManager.vala:236 -msgid "No second most recently opened file available!" -msgstr "Pas de deuxième fichier le plus récemment ouvert disponible !" - -#: src/Services/ActionManager.vala:255 -msgid "No third most recently opened file available!" -msgstr "Pas de troisième fichier le plus récemment ouvert disponible !" - -#: src/Services/ActionManager.vala:293 -msgid "Nothing selected to export!" -msgstr "Aucun élément sélectionné pour l'export !" - -#: src/Services/ActionManager.vala:302 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "" -"L'export des espaces de travail est actuellement indisponible… pardon 😑️" - -#: src/Services/ActionManager.vala:373 -msgid "Choose image file" -msgstr "Choisir un fichier image" - -#: src/Services/ActionManager.vala:373 -msgid "Select" -msgstr "Sélectionner" - -#: src/Services/ActionManager.vala:373 -msgid "Close" -msgstr "Fermer" - -#: src/Services/ActionManager.vala:442 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "Erreur ! Les fichiers .%s ne sont pas pris en charge !" - -#: src/Window.vala:121 -msgid "Are you sure you want to quit?" -msgstr "Êtes-vous sûr de vouloir quitter ?" - -#: src/Window.vala:122 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "" -"Toutes les données non sauvegardées seront perdues et impossibles à " -"récupérer." - -#: src/Window.vala:124 -msgid "Quit without saving!" -msgstr "Quitter sans sauvegarder !" - -#: src/Window.vala:125 -msgid "Save file" -msgstr "Enregistrer le fichier" diff --git a/po/fr_CA.po b/po/fr_CA.po deleted file mode 100644 index 044613fb7..000000000 --- a/po/fr_CA.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n>1;\n" diff --git a/po/fy.po b/po/fy.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/fy.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ga.po b/po/ga.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ga.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/gd.po b/po/gd.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/gd.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/gl.po b/po/gl.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/gl.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/gn.po b/po/gn.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/gn.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/gu.po b/po/gu.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/gu.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/gv.po b/po/gv.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/gv.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ha.po b/po/ha.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ha.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/he.po b/po/he.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/he.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/hi.po b/po/hi.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/hi.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ho.po b/po/ho.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ho.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/hr.po b/po/hr.po deleted file mode 100644 index 6188ef853..000000000 --- a/po/hr.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" diff --git a/po/ht.po b/po/ht.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ht.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/hu.po b/po/hu.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/hu.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/hy.po b/po/hy.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/hy.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/hz.po b/po/hz.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/hz.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ia.po b/po/ia.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ia.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/id.po b/po/id.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/id.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ie.po b/po/ie.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ie.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ig.po b/po/ig.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ig.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ii.po b/po/ii.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ii.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ik.po b/po/ik.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ik.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/io.po b/po/io.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/io.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/is.po b/po/is.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/is.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/it.po b/po/it.po deleted file mode 100644 index 336429033..000000000 --- a/po/it.po +++ /dev/null @@ -1,671 +0,0 @@ -# -# XP312 < >, 2020. -# Saverio , 2021. -# -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" -"Project-Id-Version: unnamed project\n" -"Last-Translator: Saverio \n" -"Language-Team: Italian \n" -"Language: it\n" -"Content-Transfer-Encoding: 8bit\n" -"PO-Revision-Date: 2021-06-28 18:59+0200\n" -"X-Generator: Gtranslator 40.0\n" - -#: Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "Esporta come:" - -#: Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "Seleziona la cartella" - -#: Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "Formato:" - -#: Dialogs/ExportDialog.vala:180 -msgid "Quality:" -msgstr "Qualità:" - -#: Dialogs/ExportDialog.vala:192 -msgid "Compression:" -msgstr "Compressione:" - -#: Dialogs/ExportDialog.vala:206 -msgid "Transparency:" -msgstr "Trasparenza:" - -#: Dialogs/ExportDialog.vala:219 -msgid "Scale:" -msgstr "Scala:" - -#: Dialogs/ExportDialog.vala:243 FileFormat/FileManager.vala:49 -#: FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "Annulla" - -#: Dialogs/ExportDialog.vala:250 Dialogs/ShortcutsDialog.vala:63 -#: Layouts/HeaderBar.vala:112 -msgid "Export" -msgstr "Esporta" - -#: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing " -"features, random bugs, and black holes opening in your kitchen are to be " -"expected." -msgstr "" -"ATTENZIONE!\n" -"Akira è ancora in fase di sviluppo e non è pronta per la produzione. " -"Potrebbero verificarsi bug casuali, funzionalità mancanti, o apertura di " -"buchi neri nella tua cucina." - -#: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "Fai una donazione" - -#: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "Suggerisci traduzione" - -#: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "Segnala un problema" - -#: Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "Preferenze" - -#: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 -#: Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "Generale" - -#: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "Interfaccia" - -#: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 -msgid "Shapes" -msgstr "Figure" - -#: Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "Informazioni" - -# In Italian the literal translation would be a little weird, so I've added a "edited" at the end of the sentence -#: Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "Apri automaticamente l'ultimo file modificato" - -#: Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "Utilizza il tema scuro:" - -#: Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "Inverti l'ordine dei pannelli:" - -#: Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "Riavvia l'applicazione applicare questa modifica" - -#: Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "Stile della barra degli strumenti" - -#: Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "Mostra le etichette dei pulsanti:" - -#: Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "Utilizza le icone simboliche:" - -#: Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "Colori predefiniti" - -#: Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "" -"Definisci lo stile predefinito usato quando viene creata una nuova figura." - -#: Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "Colore di riempimento:" - -#: Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "Attiva lo stile dei bordi:" - -#: Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "Colore dei bordi:" - -#: Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "Spessore dei bordi:" - -#: Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "Lo strumento di design di Linux" - -#: Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "Grazie ai nostri meravigliosi collaboratori!" - -#: Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "Visualizza la lista dei collaboratori" - -#: Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "Nuova finestra:" - -#: Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "Preferenze:" - -#: Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "Esci:" - -#: Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "Modalità presentazione:" - -#: Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "File" - -#: Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "Apri:" - -#: Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "Salva:" - -#: Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "Salva come:" - -#: Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "Esporta artboard:" - -#: Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "Esporta la selezione:" - -#: Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "Evidenzia l'area da esportare:" - -#: Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "Canvas" - -#: Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "Aumenta lo zoom:" - -#: Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "Riduci lo zoom:" - -#: Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "Reimposta lo zoom:" - -#: Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "Creazione elemento" - -#: Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "Artboard:" - -#: Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "Rettangolo:" - -#: Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "Ellisse:" - -#: Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "Testo:" - -#: Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "Immagine:" - -#: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "Trasforma:" - -#: Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "Porta la selezione sopra:" - -#: Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "Porta la selezione in basso:" - -#: Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "Porta la selezione in primo piano:" - -#: Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "Porta la selezione in ultimo piano:" - -#: Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "Capovolgi orizzontalmente:" - -#: Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "Capovolgi verticalmente:" - -#: FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "Salva file Akira" - -#: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 -msgid "Save" -msgstr "Salva" - -#: FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "File Akira" - -#: FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "Tutti i file" - -#: FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "Apri file Akira" - -#: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 -msgid "Open" -msgstr "Apri" - -#: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "Senza titolo" - -#: Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "Menu" - -#: Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "Inserisci" - -#: Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "Ragruppa" - -#: Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "Separa" - -#: Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "Sopra" - -#: Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "Sotto" - -#: Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "Più in alto" - -#: Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "Più in basso" - -#: Layouts/HeaderBar.vala:107 -msgid "Settings" -msgstr "Impostazioni" - -# ? -#: Layouts/HeaderBar.vala:118 -msgid "Difference" -msgstr "Differenza" - -#: Layouts/HeaderBar.vala:120 -msgid "Exclusion" -msgstr "Esclusione" - -#: Layouts/HeaderBar.vala:122 -msgid "Intersect" -msgstr "Intersezione" - -#: Layouts/HeaderBar.vala:124 -msgid "Union" -msgstr "Unione" - -#: Layouts/HeaderBar.vala:161 -msgid "New Window" -msgstr "Nuova finestra" - -#: Layouts/HeaderBar.vala:182 -msgid "Open Recent" -msgstr "Apri recenti" - -#: Layouts/HeaderBar.vala:195 -msgid "Save As" -msgstr "Salva come" - -#: Layouts/HeaderBar.vala:204 -msgid "Quit" -msgstr "Esci" - -#: Layouts/HeaderBar.vala:237 -msgid "Artboard" -msgstr "Artboard" - -#: Layouts/HeaderBar.vala:254 -msgid "Add Items" -msgstr "Aggiungi elementi" - -#: Layouts/HeaderBar.vala:262 -msgid "Rectangle" -msgstr "Rettangolo" - -#: Layouts/HeaderBar.vala:268 -msgid "Ellipse" -msgstr "Ellisse" - -#: Layouts/HeaderBar.vala:286 -msgid "Vector" -msgstr "Vettore" - -#: Layouts/HeaderBar.vala:288 -msgid "Pencil" -msgstr "Matita" - -#: Layouts/HeaderBar.vala:291 -msgid "Text" -msgstr "Testo" - -#: Layouts/HeaderBar.vala:297 -msgid "Image" -msgstr "Immagine" - -#: Layouts/HeaderBar.vala:330 -msgid "Export Current Selection" -msgstr "Esporta selezione corrente" - -#: Layouts/HeaderBar.vala:336 -msgid "Export Artboards" -msgstr "Esporta le artboard" - -#: Layouts/HeaderBar.vala:345 -msgid "Highlight Area to Export" -msgstr "Evidenza l'area da esportare" - -#: Layouts/HeaderBar.vala:391 -msgid "Main Menu" -msgstr "Menu principale" - -#: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:218 -#: Services/ActionManager.vala:237 Services/ActionManager.vala:256 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "Non è possibile aprirle il file “%s”" - -#: Layouts/MainCanvas.vala:52 -msgid "Button was pressed!" -msgstr "Il pulsante è stato premuto!" - -#: Layouts/MainCanvas.vala:160 -msgid "Export completed!" -msgstr "Esportazione completata!" - -#: Layouts/Partials/AlignItemsPanel.vala:48 -msgid "Distribute Horizontally" -msgstr "Distribuisci orizzontalmente" - -#: Layouts/Partials/AlignItemsPanel.vala:50 -msgid "Distribute Vertically" -msgstr "Distribuisci verticalmente" - -#: Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "Allineamento a sinistra" - -#: Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "Allineamento al centro" - -#: Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "Allicenamento a destra" - -#: Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "Allineamento in alto" - -#: Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "Allineamento al centro" - -#: Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "Allineamento in basso" - -#: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 -#: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 -msgid "Lock Layer" -msgstr "Blocca livello" - -#: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 -#: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 -msgid "Hide Layer" -msgstr "Nascondi livello" - -#: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 -msgid "Unlock Layer" -msgstr "Sblocca livello" - -#: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 -msgid "Show Layer" -msgstr "Mostra livello" - -#: Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "Stile" - -#: Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "Raggio bordo" - -#: Layouts/Partials/BorderRadiusPanel.vala:198 -msgid "Autoscale Corners" -msgstr "Angoli automaticamente scalati" - -#: Layouts/Partials/BorderRadiusPanel.vala:207 -msgid "Uniform Corners" -msgstr "Angoli uniformati" - -#: Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "Bordi" - -#: Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "Riempi" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "X" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "Posizione orizzontale" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "Y" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "Posizione verticale" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "W" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "Larghezza" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "H" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "Altezza" - -#: Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "Blocca proporzioni" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "R" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "Rotation degrees" -msgstr "Angolo di rotazione" - -#: Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "Capovolgi orizzontalmente" - -#: Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "Capovolgi verticalmente" - -#: Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "Posizione" - -#: Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "Grandezza" - -#: Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "Opacità" - -#: Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "Cerca livello" - -#: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "Generazione dell'anteprima in corso…" - -#: Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "Senza titolo %i" - -#: Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "Esportazione delle immagini in corso…" - -#: Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i px · %s" - -#: Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "Calcolo delle dimensioni dell'immagine in corso…" - -#: Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "Riduci zoom" - -#: Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "Reimposta zoom" - -#: Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "Aumenta zoom" - -#: Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "Zoom" - -#: Services/ActionManager.vala:211 -msgid "No recently opened file available!" -msgstr "Nessun file aperto recentemente disponibile!" - -#: Services/ActionManager.vala:230 -msgid "No second most recently opened file available!" -msgstr "Nessun secondo file aperto recentemente disponibile!" - -#: Services/ActionManager.vala:249 -msgid "No third most recently opened file available!" -msgstr "Nessun terzo file aperto recentemente disponibile!" - -#: Services/ActionManager.vala:287 -msgid "Nothing selected to export!" -msgstr "Nessuna selezione da esportare!" - -#: Services/ActionManager.vala:296 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "" -"Spiacente, l'esportazione delle artboard non è al momento disponibile 😑️" - -#: Services/ActionManager.vala:363 -msgid "Choose image file" -msgstr "Scegli l'immagine" - -#: Services/ActionManager.vala:363 -msgid "Select" -msgstr "Seleziona" - -#: Services/ActionManager.vala:363 -msgid "Close" -msgstr "Chiudi" - -#: Services/ActionManager.vala:432 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "Errore! I file %s non sono supportati." - -#: Window.vala:119 -msgid "Are you sure you want to quit?" -msgstr "Sei sicuro di voler uscire?" - -#: Window.vala:120 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "" -"Tutti i dati non salvati saranno persi e non sarà possibile recuperarli." - -#: Window.vala:122 -msgid "Quit without saving!" -msgstr "Esci senza salvare!" - -#: Window.vala:123 -msgid "Save file" -msgstr "Salva file" diff --git a/po/iu.po b/po/iu.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/iu.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ja.po b/po/ja.po deleted file mode 100644 index 2f3f844f3..000000000 --- a/po/ja.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;\n" diff --git a/po/jv.po b/po/jv.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/jv.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ka.po b/po/ka.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ka.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/kg.po b/po/kg.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/kg.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ki.po b/po/ki.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ki.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/kj.po b/po/kj.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/kj.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/kk.po b/po/kk.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/kk.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/kl.po b/po/kl.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/kl.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/km.po b/po/km.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/km.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/kn.po b/po/kn.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/kn.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ko.po b/po/ko.po deleted file mode 100644 index bb8b6d67d..000000000 --- a/po/ko.po +++ /dev/null @@ -1,717 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: 2020-10-07 21:17+0200\n" -"PO-Revision-Date: 2021-04-05 15:52+0900\n" -"Last-Translator: 이정희 \n" -"Language-Team: \n" -"Language: ko\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.4.1\n" -"X-Poedit-Basepath: .\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Poedit-SearchPath-0: .\n" - -#: src/Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "다음으로 내보내기:" - -#: src/Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "폴더 선택" - -#: src/Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "형식:" - -#: src/Dialogs/ExportDialog.vala:179 -msgid "Quality:" -msgstr "품질:" - -#: src/Dialogs/ExportDialog.vala:191 -msgid "Compression:" -msgstr "압축:" - -#: src/Dialogs/ExportDialog.vala:205 -msgid "Transparency:" -msgstr "투명도:" - -#: src/Dialogs/ExportDialog.vala:218 -msgid "Scale:" -msgstr "크기 조정:" - -#: src/Dialogs/ExportDialog.vala:242 src/FileFormat/FileManager.vala:49 -#: src/FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "취소" - -#: src/Dialogs/ExportDialog.vala:249 src/Dialogs/ShortcutsDialog.vala:63 -#: src/Layouts/HeaderBar.vala:112 -msgid "Export" -msgstr "내보내기" - -#: src/Dialogs/ReleaseDialog.vala:47 src/Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing " -"features, random bugs, and black holes opening in your kitchen are to be " -"expected." -msgstr "" -"경고!\n" -"아키라는 아직 개발 중이며 제품 준비가 되지 않았습니다. 누락된 기능, 임의의 " -"버그 및 부엌에서 열리는 블랙홀이 예상됩니다." - -#: src/Dialogs/ReleaseDialog.vala:100 src/Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "기부하기" - -#: src/Dialogs/ReleaseDialog.vala:109 src/Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "번역 제안" - -#: src/Dialogs/ReleaseDialog.vala:118 src/Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "문제 보고" - -#: src/Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "환경설정" - -#: src/Dialogs/SettingsDialog.vala:50 src/Dialogs/SettingsDialog.vala:73 -#: src/Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "일반" - -#: src/Dialogs/SettingsDialog.vala:51 src/Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "인터페이스" - -#: src/Dialogs/SettingsDialog.vala:52 src/Layouts/HeaderBar.vala:280 -msgid "Shapes" -msgstr "모양" - -#: src/Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "정보" - -#: src/Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "최근 파일 자동 다시 열기:" - -#: src/Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "어두운 테마 사용:" - -#: src/Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "패널 순서 반전:" - -#: src/Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "이 변경 내용을 적용하려면 응용 프로그램을 다시 시작하십시오." - -#: src/Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "도구모음 스타일" - -#: src/Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "버튼 레이블 표시:" - -#: src/Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "기호 아이콘 사용:" - -#: src/Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "기본 색상" - -#: src/Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "새 모양을 만들 때 사용되는 기본 스타일을 정의합니다." - -#: src/Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "색상 채우기:" - -#: src/Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "테두리 스타일 사용:" - -#: src/Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "테두리 색상:" - -#: src/Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "테두리 너비:" - -#: src/Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "리눅스 디자인 도구" - -#: src/Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "멋진 서포터들에게 감사드립니다!" - -#: src/Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "서포터 목록보기" - -#: src/Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "새 창:" - -#: src/Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "환경설정:" - -#: src/Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "종료:" - -#: src/Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "프레젠테이션 모드:" - -#: src/Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "파일" - -#: src/Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "열기:" - -#: src/Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "저장:" - -#: src/Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "다른 이름으로 저장:" - -#: src/Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "아트보드 내보내기:" - -#: src/Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "내보내기 선택:" - -#: src/Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "내보낼 영역 강조표시:" - -#: src/Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "캔버스" - -#: src/Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "확대:" - -#: src/Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "축소:" - -#: src/Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "확대/축소 재설정" - -#: src/Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "항목 만들기" - -#: src/Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "아트보드:" - -#: src/Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "직사각형:" - -#: src/Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "타원형:" - -#: src/Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "텍스트:" - -#: src/Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "이미지:" - -#: src/Dialogs/ShortcutsDialog.vala:97 -#: src/Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "변환" - -#: src/Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "선택 항목 올리기:" - -#: src/Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "선택 항목 내리기:" - -#: src/Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "선택 항목을 맨 위로 올리기 :" - -#: src/Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "선택 항목을 맨 아래로 내리기:" - -#: src/Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "수평으로 뒤집기:" - -#: src/Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "수직으로 뒤집기:" - -#: src/FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "아키라 파일 저장" - -#: src/FileFormat/FileManager.vala:48 src/Layouts/HeaderBar.vala:190 -msgid "Save" -msgstr "저장" - -#: src/FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "아키라 파일" - -#: src/FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "모든 파일" - -#: src/FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "아키라 파일 열기" - -#: src/FileFormat/FileManager.vala:105 src/Layouts/HeaderBar.vala:170 -msgid "Open" -msgstr "열기" - -#: src/Layouts/HeaderBar.vala:69 src/Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "제목 없음" - -#: src/Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "메뉴" - -#: src/Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "삽입" - -#: src/Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "그룹" - -#: src/Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "그룹 해제" - -#: src/Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "위로" - -#: src/Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "아래로" - -#: src/Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "맨 위로" - -#: src/Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "맨 아래로" - -#: src/Layouts/HeaderBar.vala:107 -msgid "Settings" -msgstr "설정" - -#: src/Layouts/HeaderBar.vala:118 -msgid "Difference" -msgstr "차이" - -#: src/Layouts/HeaderBar.vala:120 -msgid "Exclusion" -msgstr "제외" - -#: src/Layouts/HeaderBar.vala:122 -msgid "Intersect" -msgstr "교차" - -#: src/Layouts/HeaderBar.vala:124 -msgid "Union" -msgstr "결합" - -#: src/Layouts/HeaderBar.vala:161 -msgid "New Window" -msgstr "새 창" - -#: src/Layouts/HeaderBar.vala:182 -msgid "Open Recent" -msgstr "최근 파일 열기" - -#: src/Layouts/HeaderBar.vala:195 -msgid "Save As" -msgstr "다른 이름으로 저장" - -#: src/Layouts/HeaderBar.vala:204 -msgid "Quit" -msgstr "종료" - -#: src/Layouts/HeaderBar.vala:237 -msgid "Artboard" -msgstr "아트보드" - -#: src/Layouts/HeaderBar.vala:254 -msgid "Add Items" -msgstr "항목 추가" - -#: src/Layouts/HeaderBar.vala:262 -msgid "Rectangle" -msgstr "직사각" - -#: src/Layouts/HeaderBar.vala:268 -msgid "Ellipse" -msgstr "타원" - -#: src/Layouts/HeaderBar.vala:286 -msgid "Vector" -msgstr "벡터" - -#: src/Layouts/HeaderBar.vala:288 -msgid "Pencil" -msgstr "연필" - -#: src/Layouts/HeaderBar.vala:291 -msgid "Text" -msgstr "텍스트" - -#: src/Layouts/HeaderBar.vala:297 -msgid "Image" -msgstr "이미지" - -#: src/Layouts/HeaderBar.vala:330 -msgid "Export Current Selection" -msgstr "현재 선택 내보내기" - -#: src/Layouts/HeaderBar.vala:336 -msgid "Export Artboards" -msgstr "아트보드 내보내기" - -#: src/Layouts/HeaderBar.vala:345 -msgid "Highlight Area to Export" -msgstr "내보낼 영역 강조 표시" - -#: src/Layouts/HeaderBar.vala:391 -msgid "Main Menu" -msgstr "기본 메뉴" - -#: src/Layouts/HeaderBar.vala:468 src/Services/ActionManager.vala:224 -#: src/Services/ActionManager.vala:243 src/Services/ActionManager.vala:262 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "'%s'에서 파일을 열 수 없습니다." - -#: src/Layouts/MainCanvas.vala:46 -msgid "Button was pressed!" -msgstr "버튼을 눌렀습니다!" - -#: src/Layouts/MainCanvas.vala:206 -msgid "Export completed!" -msgstr "내보내기 완료!" - -#: src/Layouts/Partials/AlignItemsPanel.vala:48 -msgid "Distribute Horizontally" -msgstr "수평으로 분배" - -#: src/Layouts/Partials/AlignItemsPanel.vala:50 -msgid "Distribute Vertically" -msgstr "수직으로 분배" - -#: src/Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "왼쪽 정렬" - -#: src/Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "가운데 정렬" - -#: src/Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "오른쪽 정렬" - -#: src/Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "상단 정렬" - -#: src/Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "중간 정렬" - -#: src/Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "하단 정렬" - -#: src/Layouts/Partials/Artboard.vala:144 -#: src/Layouts/Partials/Artboard.vala:487 src/Layouts/Partials/Layer.vala:139 -#: src/Layouts/Partials/Layer.vala:687 -msgid "Lock Layer" -msgstr "레이어 잠금" - -#: src/Layouts/Partials/Artboard.vala:155 -#: src/Layouts/Partials/Artboard.vala:529 src/Layouts/Partials/Layer.vala:156 -#: src/Layouts/Partials/Layer.vala:729 -msgid "Hide Layer" -msgstr "레이어 숨김" - -#: src/Layouts/Partials/Artboard.vala:487 src/Layouts/Partials/Layer.vala:687 -msgid "Unlock Layer" -msgstr "레이어 잠금 해제" - -#: src/Layouts/Partials/Artboard.vala:529 src/Layouts/Partials/Layer.vala:729 -msgid "Show Layer" -msgstr "레이어 표시" - -#: src/Layouts/Partials/BorderItem.vala:121 -msgid "Choose border color" -msgstr "테두리 색상 선택" - -#: src/Layouts/Partials/BorderItem.vala:176 -#: src/Layouts/Partials/FillItem.vala:178 -msgid "Pick color" -msgstr "색상 선택" - -#: src/Layouts/Partials/BorderItem.vala:191 -msgid "Remove border" -msgstr "테두리 제거" - -#: src/Layouts/Partials/BorderItem.vala:275 -msgid "Show border" -msgstr "테두리 표시" - -#: src/Layouts/Partials/BorderItem.vala:279 -msgid "Hide border" -msgstr "테두리 숨김" - -#: src/Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "스타일" - -#: src/Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "테두리 반경" - -#: src/Layouts/Partials/BorderRadiusPanel.vala:137 -msgid "Border radius options" -msgstr "테두리 반경 옵션" - -#: src/Layouts/Partials/BorderRadiusPanel.vala:199 -msgid "Autoscale Corners" -msgstr "모서리 자동 크기조정" - -#: src/Layouts/Partials/BorderRadiusPanel.vala:208 -msgid "Uniform Corners" -msgstr "균일한 모서리" - -#: src/Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "테두리" - -#: src/Layouts/Partials/BordersPanel.vala:64 -msgid "Add border" -msgstr "테두리 추가" - -#: src/Layouts/Partials/FillItem.vala:114 -msgid "Choose fill color" -msgstr "채우기 색상 선택" - -#: src/Layouts/Partials/FillItem.vala:193 -msgid "Remove fill color" -msgstr "채우기 색상 제거" - -#: src/Layouts/Partials/FillItem.vala:277 -msgid "Show fill color" -msgstr "채우기 색상 표시" - -#: src/Layouts/Partials/FillItem.vala:281 -msgid "Hide fill color" -msgstr "채우기 색상 숨김" - -#: src/Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "채우기" - -#: src/Layouts/Partials/FillsPanel.vala:65 -msgid "Add fill color" -msgstr "채우기 색상 추가" - -#: src/Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "X" - -#: src/Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "수평 위치" - -#: src/Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "Y" - -#: src/Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "수직 위치" - -#: src/Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "W" - -#: src/Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "너비" - -#: src/Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "H" - -#: src/Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "높이" - -#: src/Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "비율 잠금" - -#: src/Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "R" - -#: src/Layouts/Partials/TransformPanel.vala:114 -msgid "Rotation degrees" -msgstr "회전 각도" - -#: src/Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "수평으로 뒤집기" - -#: src/Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "수직으로 뒤집기" - -#: src/Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "위치" - -#: src/Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "크기" - -#: src/Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "불투명도" - -#: src/Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "레이어 검색" - -#: src/Lib/Managers/ExportManager.vala:192 -#: src/Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "미리보기를 생성하는 중입니다. 잠시 기다려주세요…" - -#: src/Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "%i 제목 없음" - -#: src/Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "이미지 내보내는 중…" - -#: src/Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i px · %s" - -#: src/Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "이미지 크기 가져오는 중..." - -#: src/Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "축소" - -#: src/Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "확대/축소 재설정" - -#: src/Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "확대" - -#: src/Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "확대/축소" - -#: src/Services/ActionManager.vala:217 -msgid "No recently opened file available!" -msgstr "최근에 연 파일을 사용할 수 없습니다!" - -#: src/Services/ActionManager.vala:236 -msgid "No second most recently opened file available!" -msgstr "두 번째로 가장 최근에 연 파일을 사용할 수 없습니다!" - -#: src/Services/ActionManager.vala:255 -msgid "No third most recently opened file available!" -msgstr "세 번째로 가장 최근에 연 파일을 사용할 수 없습니다!" - -#: src/Services/ActionManager.vala:293 -msgid "Nothing selected to export!" -msgstr "내보낼 항목을 선택하지 않았습니다!" - -#: src/Services/ActionManager.vala:302 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "현재 아트보드 내보내기를 사용할 수 없습니다... 미안해요 😑️" - -#: src/Services/ActionManager.vala:373 -msgid "Choose image file" -msgstr "이미지 파일 선택" - -#: src/Services/ActionManager.vala:373 -msgid "Select" -msgstr "선택" - -#: src/Services/ActionManager.vala:373 -msgid "Close" -msgstr "닫기" - -#: src/Services/ActionManager.vala:442 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "오류! .%s 파일은 지원되지 않습니다!" - -#: src/Window.vala:121 -msgid "Are you sure you want to quit?" -msgstr "종료 하시겠습니까?" - -#: src/Window.vala:122 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "저장되지 않은 모든 데이터는 손실되고 복구할 수 없습니다." - -#: src/Window.vala:124 -msgid "Quit without saving!" -msgstr "저장하지 않고 종료!" - -#: src/Window.vala:125 -msgid "Save file" -msgstr "파일 저장" diff --git a/po/kr.po b/po/kr.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/kr.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ks.po b/po/ks.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ks.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ku.po b/po/ku.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ku.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/kv.po b/po/kv.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/kv.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/kw.po b/po/kw.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/kw.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ky.po b/po/ky.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ky.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/la.po b/po/la.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/la.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/lb.po b/po/lb.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/lb.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/lg.po b/po/lg.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/lg.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/li.po b/po/li.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/li.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ln.po b/po/ln.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ln.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/lo.po b/po/lo.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/lo.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/lt.po b/po/lt.po deleted file mode 100644 index d80210d2b..000000000 --- a/po/lt.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2;\n" diff --git a/po/lu.po b/po/lu.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/lu.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/lv.po b/po/lv.po deleted file mode 100644 index 72a9a4c3e..000000000 --- a/po/lv.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2;\n" diff --git a/po/meson.build b/po/meson.build deleted file mode 100644 index 57d1266b3..000000000 --- a/po/meson.build +++ /dev/null @@ -1 +0,0 @@ -i18n.gettext(gettext_package, preset: 'glib') diff --git a/po/mg.po b/po/mg.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/mg.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/mh.po b/po/mh.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/mh.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/mi.po b/po/mi.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/mi.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/mk.po b/po/mk.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/mk.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ml.po b/po/ml.po deleted file mode 100644 index 26ea173ec..000000000 --- a/po/ml.po +++ /dev/null @@ -1,711 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: 2020-09-27 19:02+0300\n" -"PO-Revision-Date: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.3\n" -"X-Poedit-Basepath: ../src\n" -"Language: ml\n" -"Last-Translator: \n" -"X-Poedit-SearchPath-0: .\n" - -#: Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "കയറ്റുമതി ചെയ്യുക:" - -#: Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "ഫോള്‍ഡര്‍ തിരഞ്ഞെടുക്കുക" - -#: Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "തരം:" - -#: Dialogs/ExportDialog.vala:179 -msgid "Quality:" -msgstr "മേന്‍മ:" - -#: Dialogs/ExportDialog.vala:191 -msgid "Compression:" -msgstr "ചുരുക്കല്‍:" - -#: Dialogs/ExportDialog.vala:205 -msgid "Transparency:" -msgstr "സുതാര്യത:" - -#: Dialogs/ExportDialog.vala:218 -msgid "Scale:" -msgstr "തോത്:" - -#: Dialogs/ExportDialog.vala:242 FileFormat/FileManager.vala:49 -#: FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "റദ്ദാക്കുക" - -#: Dialogs/ExportDialog.vala:249 Dialogs/ShortcutsDialog.vala:63 Layouts/HeaderBar.vala:112 -msgid "Export" -msgstr "കയറ്റുമതി" - -#: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing features, random " -"bugs, and black holes opening in your kitchen are to be expected." -msgstr "" -"മുന്നറിയിപ്പ്\n" -"ജോലിക്കുപാകത്തിന് അകിര ഇനിയും പണിതു തീര്‍ന്നിട്ടില്ല. സൗകര്യക്കുറവുകളും തുടരെത്തടസ്സങ്ങളും അടുക്കള കാലിയാക്കുന്ന " -"തമോഗര്‍ത്തങ്ങള്‍ വരെയും പ്രതീക്ഷിക്കാം." - -#: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "സംഭാവന നല്കുക" - -#: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "തര്‍ജ്ജമ നിര്‍ദ്ദേശിക്കുക" - -#: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "പ്രശ്നങ്ങള്‍ അറിയിക്കുക" - -#: Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "സജ്ജീകരണങ്ങള്‍" - -#: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 -#: Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "പൊതുസജ്ജീകരങ്ങള്‍" - -#: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "ദൃശ്യമുഖം" - -#: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 -msgid "Shapes" -msgstr "രൂപങ്ങള്‍" - -#: Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "സംബന്ധിച്ച്" - -#: Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "പുതിയ രേഖ താനേ തുറക്കുക:" - -#: Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "ഇരുണ്ട അലങ്കാരങ്ങള്‍ ഉപയോഗിക്കുക:" - -#: Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "പാനലുകള്‍ വിപരീതക്രമത്തിലാക്കുക:" - -#: Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "മാറ്റം നടപ്പിലാക്കാനായി അകിര പുനര്‍പ്രവര്‍ത്തിപ്പിക്കുക." - -#: Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "ഉപകരണത്തട്ടിന്റെ രൂപം" - -#: Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "ബട്ടണില്‍ എഴുത്തുകള്‍ കാണിക്കുക:" - -#: Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "പ്രതീകാത്മക ചിന്ഹങ്ങള്‍ ഉപയോഗിക്കുക:" - -#: Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "തനത് നിറങ്ങള്‍" - -#: Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "രൂപം വരയ്ക്കുമ്പോള്‍ ഉപയോഗിക്കേണ്ട തനത് ഭംഗി നിര്‍വചിക്കുക." - -#: Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "അകനിറം:" - -#: Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "അതിര്‍ ഭംഗി വേണം:" - -#: Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "അതിര്‍നിറം:" - -#: Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "അതിര്‍വീതി:" - -#: Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "ലിനക്സിനു വേണ്ടിയുള്ള രൂപകല്‍പ്പനാതന്ത്രം" - -#: Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "ഞങ്ങളെ പിന്താങ്ങുന്നവര്‍ക്ക് നന്ദി!" - -#: Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "ദാതാക്കളുടെ പട്ടിക കാണുക" - -#: Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "പുതിയ ജാലകം:" - -#: Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "സജ്ജീകരണങ്ങള്‍:" - -#: Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "പുറത്തിരങ്ങുക:" - -#: Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "അവതരണ രൂപം:" - -#: Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "രേഖ" - -#: Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "തുറക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "സൂക്ഷിക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "മറ്റൊന്നായി സൂക്ഷിക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "കലാഫലകങ്ങള്‍ കയറ്റുമതി ചെയ്യുക:" - -#: Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "തിരഞ്ഞെടുത്തത് സൂക്ഷിക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "കയറ്റുമതി ചെയ്യേണ്ടിടം എടുത്തുകാട്ടുക:" - -#: Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "ചിത്രത്തുണി" - -#: Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "വലുതാക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "ചെറുതാക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "പഴയ വലുപ്പത്തിലാക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "വസ്തു നിര്‍മാണം" - -#: Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "കലാഫലകം:" - -#: Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "ചതുരം:" - -#: Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "വട്ടം:" - -#: Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "എഴുത്ത്:" - -#: Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "ചിത്രം:" - -#: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "മാറ്റുക" - -#: Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "തിരഞ്ഞെടുത്തത് പൊക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "തിരഞ്ഞെടുത്തത് താഴ്ത്തുക:" - -#: Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "തിരഞ്ഞെടുത്തത് ഏറ്റവും മുകളിലാക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "തിരഞ്ഞെടുത്തത് ഏറ്റവും അടിയിലാക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "വിലങ്ങനെ മറിക്കുക:" - -#: Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "കുത്തനെ മറിക്കുക:" - -#: FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "അകിര രേഖയാക്കി സൂക്ഷിക്കുക" - -#: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 -msgid "Save" -msgstr "സുക്ഷിക്കുക" - -#: FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "അകിര രേഖക" - -#: FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "എല്ലാ രേഖകളും" - -#: FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "ഒരു അകിര രേഖ തുറക്കുക" - -#: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 -msgid "Open" -msgstr "തുറക്കുക" - -#: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "പേരില്ലാത്തത്" - -#: Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "മെനു" - -#: Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "തിരുകുക" - -#: Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "കൂട്ടമാക്കുക" - -#: Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "കൂട്ടം തെറ്റിക്കുക" - -#: Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "മേലെ" - -#: Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "താഴെ" - -#: Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "മുകളില്‍" - -#: Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "അടിയില്‍" - -#: Layouts/HeaderBar.vala:107 -msgid "Settings" -msgstr "സജ്ജീകരണങ്ങള്‍" - -#: Layouts/HeaderBar.vala:118 -msgid "Difference" -msgstr "വ്യത്യാസം" - -#: Layouts/HeaderBar.vala:120 -msgid "Exclusion" -msgstr "ഒഴിവാക്കിയത്" - -#: Layouts/HeaderBar.vala:122 -msgid "Intersect" -msgstr "നുറുക്കുക" - -#: Layouts/HeaderBar.vala:124 -msgid "Union" -msgstr "ഏകീകരിക്കുക" - -#: Layouts/HeaderBar.vala:161 -msgid "New Window" -msgstr "പുതിയ ജാലകം" - -#: Layouts/HeaderBar.vala:182 -msgid "Open Recent" -msgstr "അടുത്തിടെയുള്ളവ തുറക്കുക" - -#: Layouts/HeaderBar.vala:195 -msgid "Save As" -msgstr "മറ്റൊന്നായി സൂക്ഷിക്കുക" - -#: Layouts/HeaderBar.vala:204 -msgid "Quit" -msgstr "പുറത്ത് കടക്കുക" - -#: Layouts/HeaderBar.vala:237 -msgid "Artboard" -msgstr "കലാഫലകം" - -#: Layouts/HeaderBar.vala:254 -msgid "Add Items" -msgstr "സാധനങ്ങള്‍ ചേര്‍ക്കുക" - -#: Layouts/HeaderBar.vala:262 -msgid "Rectangle" -msgstr "ചതുരം" - -#: Layouts/HeaderBar.vala:268 -msgid "Ellipse" -msgstr "വട്ടം" - -#: Layouts/HeaderBar.vala:286 -msgid "Vector" -msgstr "ജ്യാമിത്ചിത്രം(വെക്ടര്‍)" - -#: Layouts/HeaderBar.vala:288 -msgid "Pencil" -msgstr "പെന്‍സില്‍" - -#: Layouts/HeaderBar.vala:291 -msgid "Text" -msgstr "എഴുത്ത്" - -#: Layouts/HeaderBar.vala:297 -msgid "Image" -msgstr "ചിത്രം" - -#: Layouts/HeaderBar.vala:330 -msgid "Export Current Selection" -msgstr "തിരഞ്ഞെടുത്തിരിക്കുന്നവ കയറ്റുമതി ചെയ്യുക" - -#: Layouts/HeaderBar.vala:336 -msgid "Export Artboards" -msgstr "കലാഫലകങ്ങള്‍ ഇറക്കുമതി ചെയ്യുക" - -#: Layouts/HeaderBar.vala:345 -msgid "Highlight Area to Export" -msgstr "കയറ്റുമതി ചെയ്യാനുള്ള സ്ഥലം എടുത്തുകാട്ടുക" - -#: Layouts/HeaderBar.vala:391 -msgid "Main Menu" -msgstr "പ്രധാന മെനു" - -#: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:224 Services/ActionManager.vala:243 -#: Services/ActionManager.vala:262 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "'%s'ലുള്ള രേഖ തുറക്കുവാന്‍ സാധിക്കുന്നില്ല" - -#: Layouts/MainCanvas.vala:46 -msgid "Button was pressed!" -msgstr "ബട്ടണ്‍ അമര്‍ത്തി!" - -#: Layouts/MainCanvas.vala:206 -msgid "Export completed!" -msgstr "കയറ്റുമതി ചെയ്തു കഴിഞ്ഞു!" - -#: Layouts/Partials/AlignItemsPanel.vala:48 -msgid "Distribute Horizontally" -msgstr "വരിയില്‍ അടുക്കുക" - -#: Layouts/Partials/AlignItemsPanel.vala:50 -msgid "Distribute Vertically" -msgstr "നിരയില്‍ അടുക്കുക" - -#: Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "ഇടതു ചേര്‍ക്കുക" - -#: Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "നടുക്കു വയ്ക്കുക" - -#: Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "വലതു ചേര്‍ക്കുക" - -#: Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "മേലെ ചേര്‍ത്തു വയ്ക്കുക" - -#: Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "ഇടയില്‍ വയ്ക്കുക" - -#: Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "അടിചേര്‍ക്കുക" - -#: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 -#: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 -msgid "Lock Layer" -msgstr "പാളി പൂട്ടുക" - -#: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 -#: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 -msgid "Hide Layer" -msgstr "പാളി ഒളിപ്പിക്കുക" - -#: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 -msgid "Unlock Layer" -msgstr "പാളി തുറന്നിടുക" - -#: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 -msgid "Show Layer" -msgstr "പാളി കാണിക്കുക" - -#: Layouts/Partials/BorderItem.vala:121 -msgid "Choose border color" -msgstr "അതിര്‍ നിറം തിരഞ്ഞെടുക്കുക" - -#: Layouts/Partials/BorderItem.vala:176 Layouts/Partials/FillItem.vala:178 -msgid "Pick color" -msgstr "നിറം എടുക്കുക" - -#: Layouts/Partials/BorderItem.vala:191 -msgid "Remove border" -msgstr "അതിര് നീക്കം ചെയ്യുക" - -#: Layouts/Partials/BorderItem.vala:275 -msgid "Show border" -msgstr "അതിര് കാണിക്കുക" - -#: Layouts/Partials/BorderItem.vala:279 -msgid "Hide border" -msgstr "അതിര് ഒളിപ്പിക്കുക" - -#: Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "ഭംഗി" - -#: Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "അതിരിന്റെ ആരം" - -#: Layouts/Partials/BorderRadiusPanel.vala:137 -msgid "Border radius options" -msgstr "അതിര്‍ ആരത്തിന്റെ സജ്ജീകരണങ്ങള്‍" - -#: Layouts/Partials/BorderRadiusPanel.vala:199 -msgid "Autoscale Corners" -msgstr "മൂലകള്‍ താനേ വിസ്തൃതമാക്കുക" - -#: Layouts/Partials/BorderRadiusPanel.vala:208 -msgid "Uniform Corners" -msgstr "മൂലകള്‍ ഏകികരിക്കുക" - -#: Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "അതിരുകള്‍" - -#: Layouts/Partials/BordersPanel.vala:64 -msgid "Add border" -msgstr "അതിരു ചേര്‍ക്കുക" - -#: Layouts/Partials/FillItem.vala:114 -msgid "Choose fill color" -msgstr "അകനിറം തിരഞ്ഞെടുക്കുക" - -#: Layouts/Partials/FillItem.vala:193 -msgid "Remove fill color" -msgstr "അകനിറം ഒഴിവാക്കുക" - -#: Layouts/Partials/FillItem.vala:277 -msgid "Show fill color" -msgstr "അകനിറം കാണിക്കുക" - -#: Layouts/Partials/FillItem.vala:281 -msgid "Hide fill color" -msgstr "അകനിറം ഒളിപ്പിക്കുക" - -#: Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "അകനിറങ്ങള്‍" - -#: Layouts/Partials/FillsPanel.vala:65 -msgid "Add fill color" -msgstr "അകനിറം ചേര്‍ക്കുക" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "X" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "വിലങ്ങനെയുള്ള സ്ഥാനം" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "Y" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "കുത്തനെയുള്ള സ്ഥാനം" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "W" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "വീതി" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "H" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "ഉയരം" - -#: Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "സ്ഥിര അംശബന്ധം" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "R" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "Rotation degrees" -msgstr "കറക്കം ഡിഗ്രിയില്‍" - -#: Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "വിലങ്ങനെ മറിക്കുക" - -#: Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "കുത്തനെ മറിക്കുക" - -#: Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "സ്ഥാനം" - -#: Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "വലുപ്പം" - -#: Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "സുതാര്യത" - -#: Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "പാളി പരതുക" - -#: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "പൂര്‍വ്വദൃശ്യം രുപികരിക്കുന്നു, ദയവായി കാക്കുക…" - -#: Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "പേരില്ലാത്തത് %i" - -#: Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "ചിത്രങ്ങള്‍ കയറ്റുമതി ചെയ്യുന്നു…" - -#: Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i px · %s" - -#: Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "ചിത്രവലുപ്പം കണ്ടെത്തുന്നു…" - -#: Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "ചെറുതാക്കിക്കാണിക്കുക" - -#: Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "പഴയ വലുപ്പത്തിലാക്കുക" - -#: Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "വലുതാക്കിക്കാണിക്കുക" - -#: Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "വലുപ്പം ക്രമീകരിക്കുക" - -#: Services/ActionManager.vala:217 -msgid "No recently opened file available!" -msgstr "അവസാനം തുറന്ന ഒരു രേഖയും കിട്ടാനില്ല!" - -#: Services/ActionManager.vala:236 -msgid "No second most recently opened file available!" -msgstr "അവസാനം രണ്ടാമതായി തുറന്ന ഒരു രേഖയും കിട്ടാനില്ല!" - -#: Services/ActionManager.vala:255 -msgid "No third most recently opened file available!" -msgstr "അവസാനം മൂന്നാമതായി തുറന്ന ഒരു രേഖയും കിട്ടാനില്ല!" - -#: Services/ActionManager.vala:293 -msgid "Nothing selected to export!" -msgstr "കയറ്റുമതി ചെയ്യാന്‍ ഒന്നും തിരഞ്ഞെടുത്തിട്ടില്ല!" - -#: Services/ActionManager.vala:302 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "ക്ഷമിക്കണം…കലാഫലകങ്ങളുടെ കയറ്റുമതി ഇപ്പോള്‍ സാധ്യമല്ല 😑️" - -#: Services/ActionManager.vala:373 -msgid "Choose image file" -msgstr "ചിത്രരേഖ തുറക്കുക" - -#: Services/ActionManager.vala:373 -msgid "Select" -msgstr "തിരഞ്ഞെടുക്കുക" - -#: Services/ActionManager.vala:373 -msgid "Close" -msgstr "അടക്കുക" - -#: Services/ActionManager.vala:442 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "പ്രശ്നമായി! .%s രേഖകള്‍ പിന്തുണക്കപ്പെടുന്നവയല്ല!" - -#: Window.vala:121 -msgid "Are you sure you want to quit?" -msgstr "പുറത്തിറങ്ങുകയാണെന്നുറപ്പാണോ?" - -#: Window.vala:122 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "സൂക്ഷിക്കാത്ത എല്ലാ വിവരങ്ങളും തിരിച്ചെടുക്കാനാകാത്തവിധത്തില്‍ നഷ്ടപ്പെടും." - -#: Window.vala:124 -msgid "Quit without saving!" -msgstr "സൂക്ഷിക്കാതെ പുറത്തുറങ്ങുക!" - -#: Window.vala:125 -msgid "Save file" -msgstr "രേഖ സൂക്ഷിക്കുക" diff --git a/po/mn.po b/po/mn.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/mn.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/mo.po b/po/mo.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/mo.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/mr.po b/po/mr.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/mr.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ms.po b/po/ms.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ms.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/mt.po b/po/mt.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/mt.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/my.po b/po/my.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/my.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/na.po b/po/na.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/na.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/nb.po b/po/nb.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/nb.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/nd.po b/po/nd.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/nd.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ne.po b/po/ne.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ne.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ng.po b/po/ng.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ng.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/nl.po b/po/nl.po deleted file mode 100644 index 1802a9dc8..000000000 --- a/po/nl.po +++ /dev/null @@ -1,711 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: 2020-09-03 18:20+0200\n" -"PO-Revision-Date: \n" -"Last-Translator: Heimen Stoffels \n" -"Language-Team: \n" -"Language: nl\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Poedit 2.4.1\n" -"X-Poedit-Basepath: ../src\n" -"X-Poedit-SearchPath-0: .\n" - -#: Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "Exporteren naar:" - -#: Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "Kies een map" - -#: Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "Formaat:" - -#: Dialogs/ExportDialog.vala:179 -msgid "Quality:" -msgstr "Kwaliteit:" - -#: Dialogs/ExportDialog.vala:191 -msgid "Compression:" -msgstr "Compressie:" - -#: Dialogs/ExportDialog.vala:205 -msgid "Transparency:" -msgstr "Doorzichtigheid:" - -#: Dialogs/ExportDialog.vala:218 -msgid "Scale:" -msgstr "Schaal:" - -#: Dialogs/ExportDialog.vala:242 FileFormat/FileManager.vala:49 -#: FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "Annuleren" - -#: Dialogs/ExportDialog.vala:249 Dialogs/ShortcutsDialog.vala:63 -#: Layouts/HeaderBar.vala:112 -msgid "Export" -msgstr "Exporteren" - -#: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing " -"features, random bugs, and black holes opening in your kitchen are to be " -"expected." -msgstr "" - -#: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "Doneren" - -#: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "Vertalen" - -#: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "Probleem melden" - -#: Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "Voorkeuren" - -#: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 -#: Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "Algemeen" - -#: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "Uiterlijk" - -#: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 -msgid "Shapes" -msgstr "Vormen" - -#: Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "Over" - -#: Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "Recentste bestand automatisch openen:" - -#: Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "Donker thema gebruiken:" - -#: Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "Paneelvolgorde omkeren:" - -#: Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "Herstart de toepassing om de wijzigingen toe te passen." - -#: Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "Werkbalkstijl" - -#: Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "Knopteksten tonen:" - -#: Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "Symbolische pictogrammen gebruiken:" - -#: Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "Standaardkleuren" - -#: Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "" -"Geef op welke stijl moet worden gebruikt bij het maken van een nieuwe " -"vorm." - -#: Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "Opvulkleur:" - -#: Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "Randstijl gebruiken:" - -#: Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "Randkleur:" - -#: Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "Randbreedte:" - -#: Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "Hét Linux-ontwerpprogramma" - -#: Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "Met dank aan onze geweldige ondersteuners!" - -#: Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "Ondersteunerlijst bekijken" - -#: Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "Nieuw venster:" - -#: Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "Voorkeuren:" - -#: Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "Afsluiten:" - -#: Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "Presentatiemodus:" - -#: Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "Bestand" - -#: Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "Openen:" - -#: Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "Opslaan:" - -#: Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "Opslaan als:" - -#: Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "Ontwerpborden exporteren:" - -#: Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "Selectie exporteren:" - -#: Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "Markeer het te exporteren gebied:" - -#: Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "Canvas" - -#: Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "Inzoomen:" - -#: Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "Uitzoomen:" - -#: Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "Standaard zoomniveau:" - -#: Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "Items maken" - -#: Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "Ontwerpbord:" - -#: Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "Rechthoek:" - -#: Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "Ellips:" - -#: Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "Tekst:" - -#: Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "Afbeelding:" - -#: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "Transformeren" - -#: Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "Selectie verhogen:" - -#: Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "Selectie verlagen:" - -#: Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "Selectie naar bovenkant:" - -#: Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "Selectie naar onderkant:" - -#: Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "Horizontaal spiegelen:" - -#: Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "Verticaal spiegelen:" - -#: FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "Akira-bestand opslaan" - -#: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 -msgid "Save" -msgstr "Opslaan" - -#: FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "Akira-bestanden" - -#: FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "Alle bestanden" - -#: FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "Akira-bestand openen" - -#: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 -msgid "Open" -msgstr "Openen" - -#: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "Naamloos" - -#: Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "Menu" - -#: Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "Invoegen" - -#: Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "Groeperen" - -#: Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "Degroeperen" - -#: Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "Omhoog" - -#: Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "Omlaag" - -#: Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "Bovenkant" - -#: Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "Onderkant" - -#: Layouts/HeaderBar.vala:107 -msgid "Settings" -msgstr "Instellingen" - -#: Layouts/HeaderBar.vala:118 -msgid "Difference" -msgstr "Verschil" - -#: Layouts/HeaderBar.vala:120 -msgid "Exclusion" -msgstr "Uitsluiten" - -#: Layouts/HeaderBar.vala:122 -msgid "Intersect" -msgstr "Kruisen" - -#: Layouts/HeaderBar.vala:124 -msgid "Union" -msgstr "Verenigen" - -#: Layouts/HeaderBar.vala:161 -msgid "New Window" -msgstr "Nieuw venster" - -#: Layouts/HeaderBar.vala:182 -msgid "Open Recent" -msgstr "Recent bestand openen" - -#: Layouts/HeaderBar.vala:195 -msgid "Save As" -msgstr "Opslaan als" - -#: Layouts/HeaderBar.vala:204 -msgid "Quit" -msgstr "Afsluiten" - -#: Layouts/HeaderBar.vala:237 -msgid "Artboard" -msgstr "Ontwerpbord" - -#: Layouts/HeaderBar.vala:254 -msgid "Add Items" -msgstr "Items toevoegen" - -#: Layouts/HeaderBar.vala:262 -msgid "Rectangle" -msgstr "Rechthoek" - -#: Layouts/HeaderBar.vala:268 -msgid "Ellipse" -msgstr "Ellips" - -#: Layouts/HeaderBar.vala:286 -msgid "Vector" -msgstr "Vector" - -#: Layouts/HeaderBar.vala:288 -msgid "Pencil" -msgstr "Potlood" - -#: Layouts/HeaderBar.vala:291 -msgid "Text" -msgstr "Tekst" - -#: Layouts/HeaderBar.vala:297 -msgid "Image" -msgstr "Afbeelding" - -#: Layouts/HeaderBar.vala:330 -msgid "Export Current Selection" -msgstr "Huidige selectie exporteren" - -#: Layouts/HeaderBar.vala:336 -msgid "Export Artboards" -msgstr "Ontwerpborden exporteren" - -#: Layouts/HeaderBar.vala:345 -msgid "Highlight Area to Export" -msgstr "Markeer het te exporteren gebied" - -#: Layouts/HeaderBar.vala:391 -msgid "Main Menu" -msgstr "Hoofdmenu" - -#: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:224 -#: Services/ActionManager.vala:243 Services/ActionManager.vala:262 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "Het bestand in '%s' kan niet worden geopend" - -#: Layouts/MainCanvas.vala:46 -msgid "Button was pressed!" -msgstr "De knop is ingedrukt!" - -#: Layouts/MainCanvas.vala:206 -msgid "Export completed!" -msgstr "Exporteren voltooid!" - -#: Layouts/Partials/AlignItemsPanel.vala:48 -msgid "Distribute Horizontally" -msgstr "Horizontaal opdelen" - -#: Layouts/Partials/AlignItemsPanel.vala:50 -msgid "Distribute Vertically" -msgstr "Verticaal opdelen" - -#: Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "Links uitlijnen" - -#: Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "Centreren" - -#: Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "Rechts uitlijnen" - -#: Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "Aan bovenkant uitlijnen" - -#: Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "Gecentreerd uitlijnen" - -#: Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "Aan onderkant uitlijnen" - -#: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 -#: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 -msgid "Lock Layer" -msgstr "Laag vergrendelen" - -#: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 -#: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 -msgid "Hide Layer" -msgstr "Laag verbergen" - -#: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 -msgid "Unlock Layer" -msgstr "Laag ontgrendelen" - -#: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 -msgid "Show Layer" -msgstr "Laag tonen" - -#: Layouts/Partials/BorderItem.vala:121 -msgid "Choose border color" -msgstr "Kies een randkleur" - -#: Layouts/Partials/BorderItem.vala:176 Layouts/Partials/FillItem.vala:178 -msgid "Pick color" -msgstr "Kleur kiezen" - -#: Layouts/Partials/BorderItem.vala:191 -msgid "Remove border" -msgstr "Rand verwijderen" - -#: Layouts/Partials/BorderItem.vala:275 -msgid "Show border" -msgstr "Rand tonen" - -#: Layouts/Partials/BorderItem.vala:279 -msgid "Hide border" -msgstr "Rand verbergen" - -#: Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "Stijl" - -#: Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "Randstraal" - -#: Layouts/Partials/BorderRadiusPanel.vala:137 -msgid "Border radius options" -msgstr "Randstraalopties" - -#: Layouts/Partials/BorderRadiusPanel.vala:199 -msgid "Autoscale Corners" -msgstr "Hoeken automatisch schalen" - -#: Layouts/Partials/BorderRadiusPanel.vala:208 -msgid "Uniform Corners" -msgstr "Hoeken verenigen" - -#: Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "Randen" - -#: Layouts/Partials/BordersPanel.vala:64 -msgid "Add border" -msgstr "Rand toevoegen" - -#: Layouts/Partials/FillItem.vala:114 -msgid "Choose fill color" -msgstr "Kies een opvulkleur" - -#: Layouts/Partials/FillItem.vala:193 -msgid "Remove fill color" -msgstr "Opvulkleur verwijderen" - -#: Layouts/Partials/FillItem.vala:277 -msgid "Show fill color" -msgstr "Opvulkleur tonen" - -#: Layouts/Partials/FillItem.vala:281 -msgid "Hide fill color" -msgstr "Opvulkleur verbergen" - -#: Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "Opvullen" - -#: Layouts/Partials/FillsPanel.vala:65 -msgid "Add fill color" -msgstr "Opvulkleur toevoegen" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "X" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "Horizontale positie" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "Y" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "Verticale positie" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "W" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "Breedte" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "H" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "Hoogte" - -#: Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "Verhouding vergrendelen" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "R" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "Rotation degrees" -msgstr "Aantal graden draaien" - -#: Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "Horizontaal spiegelen" - -#: Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "Verticaal spiegelen" - -#: Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "Positie" - -#: Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "Grootte" - -#: Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "Doorzichtigheid" - -#: Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "Laag zoeken" - -#: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "Bezig met samenstellen van voorvertoning…" - -#: Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "Naamloos %i" - -#: Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "Bezig met exporteren…" - -#: Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i px · %s" - -#: Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "Bezig met ophalen van afbeeldingsgrootte…" - -#: Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "Uitzoomen" - -#: Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "Standaard zoomniveau" - -#: Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "Inzoomen" - -#: Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "Zoom" - -#: Services/ActionManager.vala:217 -msgid "No recently opened file available!" -msgstr "Er is geen onlangs geopend bestand!" - -#: Services/ActionManager.vala:236 -msgid "No second most recently opened file available!" -msgstr "Er is geen tweede onlangs geopend bestand!" - -#: Services/ActionManager.vala:255 -msgid "No third most recently opened file available!" -msgstr "Er is geen derde onlangs geopend bestand!" - -#: Services/ActionManager.vala:293 -msgid "Nothing selected to export!" -msgstr "Niets geselecteerd om te exporteren!" - -#: Services/ActionManager.vala:302 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "Ontwerpborden kunnen momenteel niet worden geëxporteerd… 😑️" - -#: Services/ActionManager.vala:373 -msgid "Choose image file" -msgstr "Kies een afbeelding" - -#: Services/ActionManager.vala:373 -msgid "Select" -msgstr "Kiezen" - -#: Services/ActionManager.vala:373 -msgid "Close" -msgstr "Sluiten" - -#: Services/ActionManager.vala:442 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "Fout: .%s-bestanden worden niet ondersteund!" - -#: Window.vala:121 -msgid "Are you sure you want to quit?" -msgstr "Weet je zeker dat je wilt afsluiten?" - -#: Window.vala:122 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "Alle niet-opgeslagen gegevens gaan permanent verloren." - -#: Window.vala:124 -msgid "Quit without saving!" -msgstr "Sluiten zonder opslaan" - -#: Window.vala:125 -msgid "Save file" -msgstr "Bestand opslaan" diff --git a/po/nn.po b/po/nn.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/nn.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/no.po b/po/no.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/no.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/nr.po b/po/nr.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/nr.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/nv.po b/po/nv.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/nv.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ny.po b/po/ny.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ny.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/oc.po b/po/oc.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/oc.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/oj.po b/po/oj.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/oj.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/om.po b/po/om.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/om.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/or.po b/po/or.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/or.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/os.po b/po/os.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/os.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/pa.po b/po/pa.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/pa.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/pi.po b/po/pi.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/pi.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/pl.po b/po/pl.po deleted file mode 100644 index 24392d3a0..000000000 --- a/po/pl.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" diff --git a/po/ps.po b/po/ps.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ps.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/pt.po b/po/pt.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/pt.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/pt_BR.po b/po/pt_BR.po deleted file mode 100644 index b7d531f2c..000000000 --- a/po/pt_BR.po +++ /dev/null @@ -1,664 +0,0 @@ -msgid "" -msgstr "" -"Language: pt_BR\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" -"Project-Id-Version: \n" -"POT-Creation-Date: \n" -"PO-Revision-Date: \n" -"Last-Translator: codedracula <62944284+codedracula4ec@users.noreply." -"github.com>\n" -"Language-Team: \n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.4.1\n" - -#: Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "Exportar para:" - -#: Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "Selecionar pasta" - -#: Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "Formato:" - -#: Dialogs/ExportDialog.vala:180 -msgid "Quality:" -msgstr "Qualidade:" - -#: Dialogs/ExportDialog.vala:192 -msgid "Compression:" -msgstr "Compressão:" - -#: Dialogs/ExportDialog.vala:206 -msgid "Transparency:" -msgstr "Transparência:" - -#: Dialogs/ExportDialog.vala:219 -msgid "Scale:" -msgstr "Escala:" - -#: Dialogs/ExportDialog.vala:243 FileFormat/FileManager.vala:49 -#: FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "Cancelar" - -#: Dialogs/ExportDialog.vala:250 Dialogs/ShortcutsDialog.vala:63 -#: Layouts/HeaderBar.vala:112 -msgid "Export" -msgstr "Exportar" - -#: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing " -"features, random bugs, and black holes opening in your kitchen are to be " -"expected." -msgstr "" -"ATENÇÃO!\n" -"Akira está sob desenvolvimento e não está pronto para produção. É de se " -"esperar o mau funcionamento e a inexistência de algumas funcionalidades." - -#: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "Doar" - -#: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "Sugerir traduções" - -#: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "Reportar um problema" - -#: Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "Preferências" - -#: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 -#: Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "Geral" - -#: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "Interface" - -#: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 -msgid "Shapes" -msgstr "Formas" - -#: Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "Sobre" - -#: Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "Reabrir automaticamente arquivo mais recente:" - -#: Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "Usar tema escuro:" - -#: Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "Inverter ordem dos painéis:" - -#: Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "Reinicie a aplicação para aplicar a mudança." - -#: Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "Estilo da barra de ferramentas" - -#: Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "Mostrar legendas de botões:" - -#: Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "Usar ícones monocromáticos:" - -#: Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "Cores padrão" - -#: Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "Define o estilo padrão a ser usado para criar uma nova forma." - -#: Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "Cor de preenchimento:" - -#: Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "Ativar estilo com bordas:" - -#: Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "Cor da borda:" - -#: Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "Largura da borda:" - -#: Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "A ferramenta de design para Linux" - -#: Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "Obrigado aos nossos apoiadores incríveis!" - -#: Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "Ver lista de apoiadores" - -#: Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "Nova Janela:" - -#: Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "Preferências:" - -#: Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "Sair:" - -#: Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "Modo de apresentação:" - -#: Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "Arquivo" - -#: Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "Abrir:" - -#: Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "Salvar:" - -#: Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "Salvar como:" - -#: Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "Exportar pranchetas:" - -#: Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "Exportar seleção:" - -#: Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "Selecionar área para exportar:" - -#: Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "Tela" - -#: Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "Aumentar zoom:" - -#: Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "Reduzir zoom:" - -#: Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "Redefinir zoom:" - -#: Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "Criação de item" - -#: Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "Prancheta:" - -#: Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "Retângulo:" - -#: Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "Elipse:" - -#: Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "Texto:" - -#: Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "Imagem:" - -#: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "Transformar" - -#: Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "Subir seleção:" - -#: Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "Descer seleção:" - -#: Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "Trazer seleção para frente:" - -#: Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "Enviar seleção para trás:" - -#: Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "Inverter horizontalmente:" - -#: Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "Inverter verticalmente:" - -#: FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "Salvar arquivo Akira" - -#: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 -msgid "Save" -msgstr "Salvar" - -#: FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "Arquivos Akira" - -#: FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "Todos os arquivos" - -#: FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "Abrir arquivo Akira" - -#: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 -msgid "Open" -msgstr "Abrir" - -#: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "Sem título" - -#: Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "Menu" - -#: Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "Inserir" - -#: Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "Agrupar" - -#: Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "Desagrupar" - -#: Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "Cima" - -#: Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "Baixo" - -#: Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "Acima" - -#: Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "Abaixo" - -#: Layouts/HeaderBar.vala:107 -msgid "Settings" -msgstr "Configuração" - -#: Layouts/HeaderBar.vala:118 -msgid "Difference" -msgstr "Diferença" - -#: Layouts/HeaderBar.vala:120 -msgid "Exclusion" -msgstr "Exclusão" - -#: Layouts/HeaderBar.vala:122 -msgid "Intersect" -msgstr "Interseção" - -#: Layouts/HeaderBar.vala:124 -msgid "Union" -msgstr "União" - -#: Layouts/HeaderBar.vala:161 -msgid "New Window" -msgstr "Nova Janela" - -#: Layouts/HeaderBar.vala:182 -msgid "Open Recent" -msgstr "Abrir Recente" - -#: Layouts/HeaderBar.vala:195 -msgid "Save As" -msgstr "Salvar Como" - -#: Layouts/HeaderBar.vala:204 -msgid "Quit" -msgstr "Sair" - -#: Layouts/HeaderBar.vala:237 -msgid "Artboard" -msgstr "Prancheta" - -#: Layouts/HeaderBar.vala:254 -msgid "Add Items" -msgstr "Adicionar Itens" - -#: Layouts/HeaderBar.vala:262 -msgid "Rectangle" -msgstr "Retângulo" - -#: Layouts/HeaderBar.vala:268 -msgid "Ellipse" -msgstr "Elipse" - -#: Layouts/HeaderBar.vala:286 -msgid "Vector" -msgstr "Vetor" - -#: Layouts/HeaderBar.vala:288 -msgid "Pencil" -msgstr "Lápis" - -#: Layouts/HeaderBar.vala:291 -msgid "Text" -msgstr "Texto" - -#: Layouts/HeaderBar.vala:297 -msgid "Image" -msgstr "Imagem" - -#: Layouts/HeaderBar.vala:330 -msgid "Export Current Selection" -msgstr "Exportar Seleção Atual" - -#: Layouts/HeaderBar.vala:336 -msgid "Export Artboards" -msgstr "Exportar Pranchetas" - -#: Layouts/HeaderBar.vala:345 -msgid "Highlight Area to Export" -msgstr "Selecionar Área para Exportar" - -#: Layouts/HeaderBar.vala:391 -msgid "Main Menu" -msgstr "Menu Principal" - -#: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:218 -#: Services/ActionManager.vala:237 Services/ActionManager.vala:256 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "Não foi possível abrir o arquivo em «%s»" - -#: Layouts/MainCanvas.vala:52 -msgid "Button was pressed!" -msgstr "Botão pressionado!" - -#: Layouts/MainCanvas.vala:160 -msgid "Export completed!" -msgstr "Exportação finalizada!" - -#: Layouts/Partials/AlignItemsPanel.vala:48 -msgid "Distribute Horizontally" -msgstr "Distribuir Horizontalmente" - -#: Layouts/Partials/AlignItemsPanel.vala:50 -msgid "Distribute Vertically" -msgstr "Distribuir Verticalmente" - -#: Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "Alinhar à Esquerda" - -#: Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "Alinhar Horizontalmente" - -#: Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "Alinhar à Direita" - -#: Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "Alinhar Acima" - -#: Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "Centralizar Verticalmente" - -#: Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "Alinhar Abaixo" - -#: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 -#: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 -msgid "Lock Layer" -msgstr "Bloquear Camada" - -#: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 -#: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 -msgid "Hide Layer" -msgstr "Ocultar Camada" - -#: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 -msgid "Unlock Layer" -msgstr "Desbloquear Camada" - -#: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 -msgid "Show Layer" -msgstr "Mostrar Camada" - -#: Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "Estilo" - -#: Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "Raio da Borda" - -#: Layouts/Partials/BorderRadiusPanel.vala:198 -msgid "Autoscale Corners" -msgstr "Escalar Cantos Automaticamente" - -#: Layouts/Partials/BorderRadiusPanel.vala:207 -msgid "Uniform Corners" -msgstr "Cantos Uniformes" - -#: Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "Bordas" - -#: Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "Preenchimentos" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "X" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "Posição horizontal" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "Y" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "Posição vertical" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "↔" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "Largura" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "↕" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "Altura" - -#: Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "Bloquear Aspecto" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "↻" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "Rotation degrees" -msgstr "Graus de rotação" - -#: Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "Inverter Horizontalmente" - -#: Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "Inverter Verticalmente" - -#: Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "Posição" - -#: Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "Tamanho" - -#: Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "Opacidade" - -#: Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "Buscar Camada" - -#: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "Gerando pré-visualização, aguarde por favor…" - -#: Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "Sem título %i" - -#: Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "Exportando imagens…" - -#: Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i px · %s" - -#: Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "Recuperando tamanho de imagem…" - -#: Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "Reduzir Zoom" - -#: Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "Redefinir Zoom" - -#: Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "Aumentar Zoom" - -#: Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "Zoom" - -#: Services/ActionManager.vala:211 -msgid "No recently opened file available!" -msgstr "Não há arquivos recentes!" - -#: Services/ActionManager.vala:230 -msgid "No second most recently opened file available!" -msgstr "Não há nenhum segundo arquivo recente!" - -#: Services/ActionManager.vala:249 -msgid "No third most recently opened file available!" -msgstr "Não há nenhum terceiro arquivo recente!" - -#: Services/ActionManager.vala:287 -msgid "Nothing selected to export!" -msgstr "Nada selecionado para exportar!" - -#: Services/ActionManager.vala:296 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "Exportação de Pranchetas atualmente está indisponível... 😑️" - -#: Services/ActionManager.vala:363 -msgid "Choose image file" -msgstr "Selecionar um arquivo de imagem" - -#: Services/ActionManager.vala:363 -msgid "Select" -msgstr "Selecionar" - -#: Services/ActionManager.vala:363 -msgid "Close" -msgstr "Fechar" - -#: Services/ActionManager.vala:432 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "Erro! Arquivos .%s não são suportados!" - -#: Window.vala:119 -msgid "Are you sure you want to quit?" -msgstr "Tem certeza que quer sair?" - -#: Window.vala:120 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "" -"Todos os dados não salvos serão perdidos e será impossível recuperar." - -#: Window.vala:122 -msgid "Quit without saving!" -msgstr "Sair sem salvar!" - -#: Window.vala:123 -msgid "Save file" -msgstr "Salvar arquivo" diff --git a/po/qu.po b/po/qu.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/qu.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/rm.po b/po/rm.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/rm.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/rn.po b/po/rn.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/rn.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ro.po b/po/ro.po deleted file mode 100644 index a66282f54..000000000 --- a/po/ro.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2;\n" diff --git a/po/ru.po b/po/ru.po deleted file mode 100644 index 6188ef853..000000000 --- a/po/ru.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" diff --git a/po/rue.po b/po/rue.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/rue.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/rw.po b/po/rw.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/rw.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/sa.po b/po/sa.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/sa.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/sc.po b/po/sc.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/sc.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/sd.po b/po/sd.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/sd.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/se.po b/po/se.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/se.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/sg.po b/po/sg.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/sg.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/si.po b/po/si.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/si.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/sk.po b/po/sk.po deleted file mode 100644 index fb0b545a5..000000000 --- a/po/sk.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" diff --git a/po/sl.po b/po/sl.po deleted file mode 100644 index 1a8e08ebf..000000000 --- a/po/sl.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n" diff --git a/po/sm.po b/po/sm.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/sm.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/sma.po b/po/sma.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/sma.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/sn.po b/po/sn.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/sn.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/so.po b/po/so.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/so.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/sq.po b/po/sq.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/sq.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/sr.po b/po/sr.po deleted file mode 100644 index 6188ef853..000000000 --- a/po/sr.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" diff --git a/po/ss.po b/po/ss.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ss.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/st.po b/po/st.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/st.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/su.po b/po/su.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/su.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/sv.po b/po/sv.po deleted file mode 100644 index ca301d2fd..000000000 --- a/po/sv.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n != 1;\n" diff --git a/po/sw.po b/po/sw.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/sw.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ta.po b/po/ta.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ta.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/te.po b/po/te.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/te.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/tg.po b/po/tg.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/tg.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/th.po b/po/th.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/th.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ti.po b/po/ti.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ti.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/tk.po b/po/tk.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/tk.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/tl.po b/po/tl.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/tl.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/tn.po b/po/tn.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/tn.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/to.po b/po/to.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/to.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/tr.po b/po/tr.po deleted file mode 100644 index 5f33969bb..000000000 --- a/po/tr.po +++ /dev/null @@ -1,717 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: \n" -"POT-Creation-Date: 2020-09-27 19:02+0300\n" -"PO-Revision-Date: \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.4.1\n" -"X-Poedit-Basepath: ../src\n" -"Last-Translator: Nazım Gediz Aydındoğmuş \n" -"Language: tr\n" -"X-Poedit-SearchPath-0: .\n" - -#: Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "Aktarılacak konum:" - -#: Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "Dizin Seç" - -#: Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "Biçim:" - -#: Dialogs/ExportDialog.vala:179 -msgid "Quality:" -msgstr "Kalite:" - -#: Dialogs/ExportDialog.vala:191 -msgid "Compression:" -msgstr "Sıkıştırma:" - -#: Dialogs/ExportDialog.vala:205 -msgid "Transparency:" -msgstr "Saydamlık:" - -#: Dialogs/ExportDialog.vala:218 -msgid "Scale:" -msgstr "Ölçek:" - -#: Dialogs/ExportDialog.vala:242 FileFormat/FileManager.vala:49 -#: FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "İptal" - -#: Dialogs/ExportDialog.vala:249 Dialogs/ShortcutsDialog.vala:63 -#: Layouts/HeaderBar.vala:112 -msgid "Export" -msgstr "Dışarı Aktar" - -#: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing " -"features, random bugs, and black holes opening in your kitchen are to be " -"expected." -msgstr "" -"UYARI!\n" -"Akira hala geliştirme aşamasındadır ve son ürün oluşturmaya yönelik " -"kullanıma hazır değildir. Kullanım esnasında eksik özellikler, rastgele " -"hatalar ve mutfağınızda zuhur eden kara delikler ile karşılaşabilirsiniz." - -#: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "Bağış Yap" - -#: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "Çeviri Öner" - -#: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "Sorun Bildir" - -#: Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "Tercihler" - -#: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 -#: Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "Genel" - -#: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "Arayüz" - -#: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:280 -msgid "Shapes" -msgstr "Şekiller" - -#: Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "Hakkında" - -#: Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "Başlangıçta Son Dosyayı Aç:" - -#: Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "Karanlık Temayı Kullan:" - -#: Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "Panel Düzenini Tersine Çevir:" - -#: Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "" -"Bu değişikliği geçerli hale getirmek için uygulamayı yeniden başlat." - -#: Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "Araç Çubuğu Biçimi" - -#: Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "Buton Metinlerini Göster:" - -#: Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "Sembolik Simgeleri Kullan:" - -#: Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "Varsayılan Renkler" - -#: Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "" -"Yeni bir simge oluşturulurken kullanılacak varsayılan biçimi tanımla." - -#: Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "Dolgu Rengi:" - -#: Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "Kenar Biçimini Etkinleştir:" - -#: Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "Kenar Rengi:" - -#: Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "Kenar Genişliği:" - -#: Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "Linux'un Tasarım Aracı" - -#: Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "Harika destekçilerimiz sayesinde!" - -#: Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "Destekleyenlerin listesini görüntüle" - -#: Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "Yeni pencere:" - -#: Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "Tercihler:" - -#: Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "Çıkış Yap:" - -#: Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "Sunum modu:" - -#: Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "Dosya" - -#: Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "Aç:" - -#: Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "Kaydet:" - -#: Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "Farklı Kaydet:" - -#: Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "Çalışma yüzeylerini dışarı aktar:" - -#: Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "Seçimi dışarı aktar:" - -#: Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "Dışa aktarılacak alanı vurgula:" - -#: Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "Tuval" - -#: Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "Büyüt:" - -#: Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "Küçült:" - -#: Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "Yakınlaştırmayı sıfırla:" - -#: Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "Öğe oluşturma" - -#: Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "Çalışma yüzeyi:" - -#: Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "Dikdörtgen:" - -#: Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "Elips:" - -#: Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "Metin:" - -#: Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "Resim:" - -#: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "Dönüştürme" - -#: Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "Seçimi yükselt:" - -#: Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "Seçimi alçalt:" - -#: Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "Seçimi en öne getir:" - -#: Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "Seçimi en arkaya gönder:" - -#: Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "Yatay olarak çevir:" - -#: Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "Dikey olarak çevir:" - -#: FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "Akira dosyasını kaydet" - -#: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:190 -msgid "Save" -msgstr "Kaydet" - -#: FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "Akira dosyaları" - -#: FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "Tüm dosyalar" - -#: FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "Akira dosyasını aç" - -#: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:170 -msgid "Open" -msgstr "Aç" - -#: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "İsimsiz" - -#: Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "Menü" - -#: Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "Ekle" - -#: Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "Gruplandır" - -#: Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "Grubu dağıt" - -#: Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "Yukarı" - -#: Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "Aşağı" - -#: Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "Üst" - -#: Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "Alt" - -#: Layouts/HeaderBar.vala:107 -msgid "Settings" -msgstr "Ayarlar" - -#: Layouts/HeaderBar.vala:118 -msgid "Difference" -msgstr "Fark" - -#: Layouts/HeaderBar.vala:120 -msgid "Exclusion" -msgstr "Dışlama" - -#: Layouts/HeaderBar.vala:122 -msgid "Intersect" -msgstr "Kesişim" - -#: Layouts/HeaderBar.vala:124 -msgid "Union" -msgstr "Birleşim" - -#: Layouts/HeaderBar.vala:161 -msgid "New Window" -msgstr "Yeni Pencere" - -#: Layouts/HeaderBar.vala:182 -msgid "Open Recent" -msgstr "Son Kullanılan" - -#: Layouts/HeaderBar.vala:195 -msgid "Save As" -msgstr "Farklı Kaydet" - -#: Layouts/HeaderBar.vala:204 -msgid "Quit" -msgstr "Çıkış Yap" - -#: Layouts/HeaderBar.vala:237 -msgid "Artboard" -msgstr "Çalışma Yüzeyi" - -#: Layouts/HeaderBar.vala:254 -msgid "Add Items" -msgstr "Öğeleri Ekle" - -#: Layouts/HeaderBar.vala:262 -msgid "Rectangle" -msgstr "Dikdörtgen" - -#: Layouts/HeaderBar.vala:268 -msgid "Ellipse" -msgstr "Elips" - -#: Layouts/HeaderBar.vala:286 -msgid "Vector" -msgstr "Vektör" - -#: Layouts/HeaderBar.vala:288 -msgid "Pencil" -msgstr "Kalem" - -#: Layouts/HeaderBar.vala:291 -msgid "Text" -msgstr "Metin" - -#: Layouts/HeaderBar.vala:297 -msgid "Image" -msgstr "Resim" - -#: Layouts/HeaderBar.vala:330 -msgid "Export Current Selection" -msgstr "Mevcut Seçimi Dışarı Aktar" - -#: Layouts/HeaderBar.vala:336 -msgid "Export Artboards" -msgstr "Çalışma Yüzeylerini Dışarı Aktar" - -#: Layouts/HeaderBar.vala:345 -msgid "Highlight Area to Export" -msgstr "Dışa Aktarılacak Alanı Vurgula" - -#: Layouts/HeaderBar.vala:391 -msgid "Main Menu" -msgstr "Ana Menü" - -#: Layouts/HeaderBar.vala:468 Services/ActionManager.vala:224 -#: Services/ActionManager.vala:243 Services/ActionManager.vala:262 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "'%s' konumundaki dosya açılamıyor" - -#: Layouts/MainCanvas.vala:46 -msgid "Button was pressed!" -msgstr "Butona basıldı!" - -#: Layouts/MainCanvas.vala:206 -msgid "Export completed!" -msgstr "Dışarı aktarma tamamlandı!" - -#: Layouts/Partials/AlignItemsPanel.vala:48 -msgid "Distribute Horizontally" -msgstr "Yatay Olarak Dağıt" - -#: Layouts/Partials/AlignItemsPanel.vala:50 -msgid "Distribute Vertically" -msgstr "Dikey Olarak Dağıt" - -#: Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "Sola Hizala" - -#: Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "Ortaya Hizala" - -#: Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "Sağa Hizala" - -#: Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "Yukarı Hizala" - -#: Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "Ortaya Hizala" - -#: Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "Aşağı Hizala" - -#: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Artboard.vala:487 -#: Layouts/Partials/Layer.vala:139 Layouts/Partials/Layer.vala:687 -msgid "Lock Layer" -msgstr "Katmanı Kilitle" - -#: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Artboard.vala:529 -#: Layouts/Partials/Layer.vala:156 Layouts/Partials/Layer.vala:729 -msgid "Hide Layer" -msgstr "Katmanı Gizle" - -#: Layouts/Partials/Artboard.vala:487 Layouts/Partials/Layer.vala:687 -msgid "Unlock Layer" -msgstr "Katmanın Kilidini Aç" - -#: Layouts/Partials/Artboard.vala:529 Layouts/Partials/Layer.vala:729 -msgid "Show Layer" -msgstr "Katmanı Göster" - -#: Layouts/Partials/BorderItem.vala:121 -msgid "Choose border color" -msgstr "Kenar rengi seç" - -#: Layouts/Partials/BorderItem.vala:176 Layouts/Partials/FillItem.vala:178 -msgid "Pick color" -msgstr "Renk seç" - -#: Layouts/Partials/BorderItem.vala:191 -msgid "Remove border" -msgstr "Kenarı kaldır" - -#: Layouts/Partials/BorderItem.vala:275 -msgid "Show border" -msgstr "Kenarı göster" - -#: Layouts/Partials/BorderItem.vala:279 -msgid "Hide border" -msgstr "Kenarı gizle" - -#: Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "Biçim" - -#: Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "Kenar Yarıçapı" - -#: Layouts/Partials/BorderRadiusPanel.vala:137 -msgid "Border radius options" -msgstr "Kenar yarıçapı seçenekleri" - -#: Layouts/Partials/BorderRadiusPanel.vala:199 -msgid "Autoscale Corners" -msgstr "Köşeleri Otomatik Ölçeklendir" - -#: Layouts/Partials/BorderRadiusPanel.vala:208 -msgid "Uniform Corners" -msgstr "Tüm Köşeler Aynı Biçimde" - -#: Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "Kenarlar" - -#: Layouts/Partials/BordersPanel.vala:64 -msgid "Add border" -msgstr "Kenar ekle" - -#: Layouts/Partials/FillItem.vala:114 -msgid "Choose fill color" -msgstr "Dolgu rengi seç" - -#: Layouts/Partials/FillItem.vala:193 -msgid "Remove fill color" -msgstr "Dolgu rengini kaldır" - -#: Layouts/Partials/FillItem.vala:277 -msgid "Show fill color" -msgstr "Dolgu rengini göster" - -#: Layouts/Partials/FillItem.vala:281 -msgid "Hide fill color" -msgstr "Dolgu rengini gizle" - -#: Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "Dolgular" - -#: Layouts/Partials/FillsPanel.vala:65 -msgid "Add fill color" -msgstr "Dolgu rengi ekle" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "X" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "Yatay konum" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "Y" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "Dikey konum" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "G" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "Genişlik" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "Y" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "Yükseklik" - -#: Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "Oranı Sabitle" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "D" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "Rotation degrees" -msgstr "Dönme derecesi" - -#: Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "Yatay Olarak Çevir" - -#: Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "Dikey Olarak Çevir" - -#: Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "Konum" - -#: Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "Boyut" - -#: Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "Saydamlık" - -#: Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "Katman Ara" - -#: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "Önizleme oluşturuluyor, lütfen bekleyin…" - -#: Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "İsimsiz %i" - -#: Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "Resimler dışarı aktarılıyor…" - -#: Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i px · %s" - -#: Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "Resim boyutu getiriliyor…" - -#: Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "Küçült" - -#: Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "Yakınlaştırmayı Sıfırla" - -#: Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "Büyüt" - -#: Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "Yakınlaştırma" - -#: Services/ActionManager.vala:217 -msgid "No recently opened file available!" -msgstr "Yakın zamanda açılmış bir dosya yok!" - -#: Services/ActionManager.vala:236 -msgid "No second most recently opened file available!" -msgstr "Yakın zamanda açılmış ikinci bir dosya yok!" - -#: Services/ActionManager.vala:255 -msgid "No third most recently opened file available!" -msgstr "Yakın zamanda açılmış üçüncü bir dosya yok!" - -#: Services/ActionManager.vala:293 -msgid "Nothing selected to export!" -msgstr "Dışarı aktarılacak bir şey seçilmedi!" - -#: Services/ActionManager.vala:302 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "Çalışma yüzeylerini dışarı aktarmak henüz mümkün değil…üzgünüm 😑️" - -#: Services/ActionManager.vala:373 -msgid "Choose image file" -msgstr "Resim dosyası seç" - -#: Services/ActionManager.vala:373 -msgid "Select" -msgstr "Seç" - -#: Services/ActionManager.vala:373 -msgid "Close" -msgstr "Kapat" - -#: Services/ActionManager.vala:442 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "Hata! .%s dosyaları desteklenmemektedir!" - -#: Window.vala:121 -msgid "Are you sure you want to quit?" -msgstr "Çıkış yapmak istediğinizden emin misiniz?" - -#: Window.vala:122 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "" -"Kaydedilmemiş tüm veriler kurtarması mümkün olmayacak şekilde " -"kaybolacaktır." - -#: Window.vala:124 -msgid "Quit without saving!" -msgstr "Kaydetmeden çık!" - -#: Window.vala:125 -msgid "Save file" -msgstr "Dosyayı kaydet" diff --git a/po/ts.po b/po/ts.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ts.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/tt.po b/po/tt.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/tt.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/tw.po b/po/tw.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/tw.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ty.po b/po/ty.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ty.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ug.po b/po/ug.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ug.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/uk.po b/po/uk.po deleted file mode 100644 index 6188ef853..000000000 --- a/po/uk.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" diff --git a/po/ur.po b/po/ur.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ur.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/uz.po b/po/uz.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/uz.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/ve.po b/po/ve.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/ve.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/vi.po b/po/vi.po deleted file mode 100644 index 2f3f844f3..000000000 --- a/po/vi.po +++ /dev/null @@ -1,5 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Plural-Forms: nplurals=2; plural=n == 1 ? 0 : 1;\n" diff --git a/po/vo.po b/po/vo.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/vo.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/wa.po b/po/wa.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/wa.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/wo.po b/po/wo.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/wo.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/xh.po b/po/xh.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/xh.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/yi.po b/po/yi.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/yi.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/yo.po b/po/yo.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/yo.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/za.po b/po/za.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/za.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/zh.po b/po/zh.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/zh.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/zh_CN.po b/po/zh_CN.po deleted file mode 100644 index cb1a3728a..000000000 --- a/po/zh_CN.po +++ /dev/null @@ -1,666 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Akira 0.0.11 alpha\n" -"POT-Creation-Date: 2020-08-05 20:25+0800\n" -"PO-Revision-Date: \n" -"Last-Translator: WhiredPlanck \n" -"Language-Team: \n" -"Language: zh_CN\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.3.1\n" -"X-Poedit-Basepath: ../src\n" -"Plural-Forms: nplurals=1; plural=0;\n" -"X-Poedit-SearchPath-0: .\n" - -#: Dialogs/ExportDialog.vala:151 -msgid "Export to:" -msgstr "导出到:" - -#: Dialogs/ExportDialog.vala:157 -msgid "Select Folder" -msgstr "选择文件夹" - -#: Dialogs/ExportDialog.vala:166 -msgid "Format:" -msgstr "格式:" - -#: Dialogs/ExportDialog.vala:180 -msgid "Quality:" -msgstr "质量:" - -#: Dialogs/ExportDialog.vala:192 -msgid "Compression:" -msgstr "压缩等级:" - -#: Dialogs/ExportDialog.vala:206 -msgid "Transparency:" -msgstr "透明度:" - -#: Dialogs/ExportDialog.vala:219 -msgid "Scale:" -msgstr "比例:" - -#: Dialogs/ExportDialog.vala:243 FileFormat/FileManager.vala:49 -#: FileFormat/FileManager.vala:105 -msgid "Cancel" -msgstr "取消" - -#: Dialogs/ExportDialog.vala:250 Dialogs/ShortcutsDialog.vala:63 -#: Layouts/HeaderBar.vala:113 -msgid "Export" -msgstr "导出" - -#: Dialogs/ReleaseDialog.vala:47 Dialogs/SettingsDialog.vala:217 -msgid "" -"WARNING!\n" -"Akira is still under development and not ready for production. Missing " -"features, random bugs, and black holes opening in your kitchen are to be " -"expected." -msgstr "" -"** 警告!**\n" -"Akira 仍在开发当中,尚未能正式成为生产工具。请准备好忍受功能上的缺失、随" -"机出现的 Bug,以及吞噬劳作成果的“黑洞”。" - -#: Dialogs/ReleaseDialog.vala:100 Dialogs/SettingsDialog.vala:249 -msgid "Make a Donation" -msgstr "捐献我们" - -#: Dialogs/ReleaseDialog.vala:109 Dialogs/SettingsDialog.vala:258 -msgid "Suggest Translations" -msgstr "提供翻译建议" - -#: Dialogs/ReleaseDialog.vala:118 Dialogs/SettingsDialog.vala:267 -msgid "Report a Problem" -msgstr "向我们报告问题" - -#: Dialogs/SettingsDialog.vala:40 -msgid "Preferences" -msgstr "偏好设置" - -#: Dialogs/SettingsDialog.vala:50 Dialogs/SettingsDialog.vala:73 -#: Dialogs/ShortcutsDialog.vala:45 -msgid "General" -msgstr "常规" - -#: Dialogs/SettingsDialog.vala:51 Dialogs/SettingsDialog.vala:86 -msgid "Interface" -msgstr "界面" - -#: Dialogs/SettingsDialog.vala:52 Layouts/HeaderBar.vala:281 -msgid "Shapes" -msgstr "形状" - -#: Dialogs/SettingsDialog.vala:53 -msgid "About" -msgstr "关于" - -#: Dialogs/SettingsDialog.vala:74 -msgid "Auto Reopen Latest File:" -msgstr "自动重新打开最新(近)文件:" - -#: Dialogs/SettingsDialog.vala:88 -msgid "Use Dark Theme:" -msgstr "使用暗色主题:" - -#: Dialogs/SettingsDialog.vala:92 -msgid "Invert Panels Order:" -msgstr "反转面板顺序:" - -#: Dialogs/SettingsDialog.vala:96 -msgid "Restart application to apply this change." -msgstr "重启应用程序以应用更改。" - -#: Dialogs/SettingsDialog.vala:100 -msgid "ToolBar Style" -msgstr "工具栏样式" - -#: Dialogs/SettingsDialog.vala:102 -msgid "Show Button Labels:" -msgstr "显示按钮标签:" - -#: Dialogs/SettingsDialog.vala:106 -msgid "Use Symbolic Icons:" -msgstr "使用符号图标:" - -#: Dialogs/SettingsDialog.vala:129 -msgid "Default Colors" -msgstr "默认颜色" - -#: Dialogs/SettingsDialog.vala:131 -msgid "Define the default style used when creating a new shape." -msgstr "定义创建新形状时使用的默认样式。" - -#: Dialogs/SettingsDialog.vala:136 -msgid "Fill Color:" -msgstr "填充颜色:" - -#: Dialogs/SettingsDialog.vala:157 -msgid "Enable Border Style:" -msgstr "启用边框样式:" - -#: Dialogs/SettingsDialog.vala:160 -msgid "Border Color:" -msgstr "边框颜色:" - -#: Dialogs/SettingsDialog.vala:181 -msgid "Border Width:" -msgstr "边框宽度:" - -#: Dialogs/SettingsDialog.vala:209 -msgid "The Linux Design Tool" -msgstr "Linux 设计工具" - -#: Dialogs/SettingsDialog.vala:226 -msgid "Thanks to our awesome supporters!" -msgstr "感谢我们出色的支持者!" - -#: Dialogs/SettingsDialog.vala:231 -msgid "View the list of supporters" -msgstr "查看支持者名单" - -#: Dialogs/ShortcutsDialog.vala:46 -msgid "New window:" -msgstr "新建窗口:" - -#: Dialogs/ShortcutsDialog.vala:48 -msgid "Preferences:" -msgstr "偏好设置:" - -#: Dialogs/ShortcutsDialog.vala:50 -msgid "Quit:" -msgstr "退出:" - -#: Dialogs/ShortcutsDialog.vala:52 -msgid "Presentation mode:" -msgstr "演示模式:" - -#: Dialogs/ShortcutsDialog.vala:55 -msgid "File" -msgstr "文件" - -#: Dialogs/ShortcutsDialog.vala:56 -msgid "Open:" -msgstr "打开:" - -#: Dialogs/ShortcutsDialog.vala:58 -msgid "Save:" -msgstr "保存:" - -#: Dialogs/ShortcutsDialog.vala:60 -msgid "Save as:" -msgstr "另存为:" - -#: Dialogs/ShortcutsDialog.vala:64 -msgid "Export artboards:" -msgstr "导出画板:" - -#: Dialogs/ShortcutsDialog.vala:66 -msgid "Export selection:" -msgstr "导出所选:" - -#: Dialogs/ShortcutsDialog.vala:68 -msgid "Highlight area to export:" -msgstr "高亮要导出的区域:" - -#: Dialogs/ShortcutsDialog.vala:77 -msgid "Canvas" -msgstr "帆布" - -#: Dialogs/ShortcutsDialog.vala:78 -msgid "Zoom in:" -msgstr "放大:" - -#: Dialogs/ShortcutsDialog.vala:80 -msgid "Zoom out:" -msgstr "缩小:" - -#: Dialogs/ShortcutsDialog.vala:82 -msgid "Zoom reset:" -msgstr "重置缩放:" - -#: Dialogs/ShortcutsDialog.vala:85 -msgid "Item creation" -msgstr "项目创建" - -#: Dialogs/ShortcutsDialog.vala:86 -msgid "Artboard:" -msgstr "画板:" - -#: Dialogs/ShortcutsDialog.vala:88 -msgid "Rectangle:" -msgstr "矩形:" - -#: Dialogs/ShortcutsDialog.vala:90 -msgid "Ellipse:" -msgstr "椭圆:" - -#: Dialogs/ShortcutsDialog.vala:92 -msgid "Text:" -msgstr "文本:" - -#: Dialogs/ShortcutsDialog.vala:94 -msgid "Image:" -msgstr "图像:" - -#: Dialogs/ShortcutsDialog.vala:97 Layouts/Partials/TransformPanel.vala:174 -msgid "Transform" -msgstr "变换" - -#: Dialogs/ShortcutsDialog.vala:98 -msgid "Raise selection:" -msgstr "上移所选:" - -#: Dialogs/ShortcutsDialog.vala:100 -msgid "Lower selection:" -msgstr "下移所选:" - -#: Dialogs/ShortcutsDialog.vala:102 -msgid "Raise selection to top:" -msgstr "将所选上移到顶层:" - -#: Dialogs/ShortcutsDialog.vala:104 -msgid "Lower selection to bottom:" -msgstr "将所选下移到底层:" - -#: Dialogs/ShortcutsDialog.vala:106 -msgid "Flip horizontally:" -msgstr "水平翻转:" - -#: Dialogs/ShortcutsDialog.vala:108 -msgid "Flip vertically:" -msgstr "垂直翻转:" - -#: FileFormat/FileManager.vala:46 -msgid "Save Akira file" -msgstr "保存 Akira 文件" - -#: FileFormat/FileManager.vala:48 Layouts/HeaderBar.vala:191 -msgid "Save" -msgstr "保存" - -#: FileFormat/FileManager.vala:71 -msgid "Akira files" -msgstr "Akira 文件" - -#: FileFormat/FileManager.vala:76 -msgid "All files" -msgstr "所有文件" - -#: FileFormat/FileManager.vala:103 -msgid "Open Akira file" -msgstr "打开 Akira 文件" - -#: FileFormat/FileManager.vala:105 Layouts/HeaderBar.vala:171 -msgid "Open" -msgstr "打开" - -#: Layouts/HeaderBar.vala:69 Lib/Managers/ExportManager.vala:296 -msgid "Untitled" -msgstr "无标题" - -#: Layouts/HeaderBar.vala:71 -msgid "Menu" -msgstr "菜单" - -#: Layouts/HeaderBar.vala:75 -msgid "Insert" -msgstr "插入" - -#: Layouts/HeaderBar.vala:82 -msgid "Group" -msgstr "合并" - -#: Layouts/HeaderBar.vala:84 -msgid "Ungroup" -msgstr "取消合并" - -#: Layouts/HeaderBar.vala:87 -msgid "Up" -msgstr "上移一层" - -#: Layouts/HeaderBar.vala:92 -msgid "Down" -msgstr "下移一层" - -#: Layouts/HeaderBar.vala:97 -msgid "Top" -msgstr "置于顶层" - -#: Layouts/HeaderBar.vala:102 -msgid "Bottom" -msgstr "置于底层" - -#: Layouts/HeaderBar.vala:108 -msgid "Settings" -msgstr "设置" - -#: Layouts/HeaderBar.vala:119 -msgid "Difference" -msgstr "差异" - -#: Layouts/HeaderBar.vala:121 -msgid "Exclusion" -msgstr "排除" - -#: Layouts/HeaderBar.vala:123 -msgid "Intersect" -msgstr "交集" - -#: Layouts/HeaderBar.vala:125 -msgid "Union" -msgstr "并集" - -#: Layouts/HeaderBar.vala:162 -msgid "New Window" -msgstr "新窗口" - -#: Layouts/HeaderBar.vala:183 -msgid "Open Recent" -msgstr "打开最近文件" - -#: Layouts/HeaderBar.vala:196 -msgid "Save As" -msgstr "另存为" - -#: Layouts/HeaderBar.vala:205 -msgid "Quit" -msgstr "退出" - -#: Layouts/HeaderBar.vala:238 -msgid "Artboard" -msgstr "画板" - -#: Layouts/HeaderBar.vala:255 -msgid "Add Items" -msgstr "添加项目" - -#: Layouts/HeaderBar.vala:263 -msgid "Rectangle" -msgstr "矩形" - -#: Layouts/HeaderBar.vala:269 -msgid "Ellipse" -msgstr "椭圆" - -#: Layouts/HeaderBar.vala:287 -msgid "Vector" -msgstr "矢量" - -#: Layouts/HeaderBar.vala:289 -msgid "Pencil" -msgstr "铅笔" - -#: Layouts/HeaderBar.vala:292 -msgid "Text" -msgstr "文本" - -#: Layouts/HeaderBar.vala:298 -msgid "Image" -msgstr "图像" - -#: Layouts/HeaderBar.vala:331 -msgid "Export Current Selection" -msgstr "导出当前所选" - -#: Layouts/HeaderBar.vala:337 -msgid "Export Artboards" -msgstr "导出画板" - -#: Layouts/HeaderBar.vala:346 -msgid "Highlight Area to Export" -msgstr "截取要导出的区域" - -#: Layouts/HeaderBar.vala:394 -msgid "Main Menu" -msgstr "主菜单" - -#: Layouts/HeaderBar.vala:471 Services/ActionManager.vala:215 -#: Services/ActionManager.vala:234 Services/ActionManager.vala:253 -#, c-format -msgid "Unable to open file at '%s'" -msgstr "无法在 '%s' 打开文件" - -#: Layouts/MainCanvas.vala:52 -#, fuzzy -msgid "Button was pressed!" -msgstr "按钮被按下!" - -#: Layouts/MainCanvas.vala:160 -msgid "Export completed!" -msgstr "导出完毕!" - -#: Layouts/Partials/AlignItemsPanel.vala:48 -msgid "Distribute Horizontally" -msgstr "水平分布" - -#: Layouts/Partials/AlignItemsPanel.vala:50 -msgid "Distribute Vertically" -msgstr "垂直分布" - -#: Layouts/Partials/AlignItemsPanel.vala:52 -msgid "Align Left" -msgstr "左对齐" - -#: Layouts/Partials/AlignItemsPanel.vala:53 -msgid "Align Center" -msgstr "居中对齐" - -#: Layouts/Partials/AlignItemsPanel.vala:54 -msgid "Align Right" -msgstr "右对齐" - -#: Layouts/Partials/AlignItemsPanel.vala:56 -msgid "Align Top" -msgstr "顶端对齐" - -#: Layouts/Partials/AlignItemsPanel.vala:57 -msgid "Align Middle" -msgstr "中间对齐" - -#: Layouts/Partials/AlignItemsPanel.vala:58 -msgid "Align Bottom" -msgstr "底端对齐" - -#: Layouts/Partials/Artboard.vala:144 Layouts/Partials/Layer.vala:139 -#: Layouts/Partials/Layer.vala:686 -msgid "Lock Layer" -msgstr "锁定图层" - -#: Layouts/Partials/Artboard.vala:155 Layouts/Partials/Layer.vala:156 -#: Layouts/Partials/Layer.vala:727 -msgid "Hide Layer" -msgstr "隐藏图层" - -#: Layouts/Partials/BorderRadiusPanel.vala:86 -msgid "Style" -msgstr "样式" - -#: Layouts/Partials/BorderRadiusPanel.vala:103 -msgid "Border Radius" -msgstr "边框半径" - -#: Layouts/Partials/BorderRadiusPanel.vala:198 -#, fuzzy -msgid "Autoscale Corners" -msgstr "自动最佳化圆角比例" - -#: Layouts/Partials/BorderRadiusPanel.vala:207 -msgid "Uniform Corners" -msgstr "统一圆角半径" - -#: Layouts/Partials/BordersPanel.vala:53 -msgid "Borders" -msgstr "边框" - -#: Layouts/Partials/FillsPanel.vala:54 -msgid "Fills" -msgstr "填充" - -#: Layouts/Partials/Layer.vala:686 -msgid "Unlock Layer" -msgstr "解锁图层" - -#: Layouts/Partials/Layer.vala:727 -msgid "Show Layer" -msgstr "显示图层" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "X" -msgstr "X" - -#: Layouts/Partials/TransformPanel.vala:96 -msgid "Horizontal position" -msgstr "水平位置" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Y" -msgstr "Y" - -#: Layouts/Partials/TransformPanel.vala:98 -msgid "Vertical position" -msgstr "垂直位置" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "W" -msgstr "W" - -#: Layouts/Partials/TransformPanel.vala:100 -msgid "Width" -msgstr "宽度" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "H" -msgstr "H" - -#: Layouts/Partials/TransformPanel.vala:102 -msgid "Height" -msgstr "高度" - -#: Layouts/Partials/TransformPanel.vala:107 -msgid "Lock Ratio" -msgstr "锁定高宽比" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "R" -msgstr "R" - -#: Layouts/Partials/TransformPanel.vala:114 -msgid "Rotation degrees" -msgstr "旋转角度" - -#: Layouts/Partials/TransformPanel.vala:126 -msgid "Flip Horizontally" -msgstr "水平翻转" - -#: Layouts/Partials/TransformPanel.vala:137 -msgid "Flip Vertically" -msgstr "垂直翻转" - -#: Layouts/Partials/TransformPanel.vala:165 -msgid "Position" -msgstr "位置" - -#: Layouts/Partials/TransformPanel.vala:169 -msgid "Size" -msgstr "大小" - -#: Layouts/Partials/TransformPanel.vala:178 -msgid "Opacity" -msgstr "不透明度" - -#: Layouts/RightSideBar.vala:111 -msgid "Search Layer" -msgstr "搜索图层" - -#: Lib/Managers/ExportManager.vala:192 Lib/Managers/ExportManager.vala:219 -msgid "Generating preview, please wait…" -msgstr "生成预览中,请稍候…" - -#: Lib/Managers/ExportManager.vala:313 -#, c-format -msgid "Untitled %i" -msgstr "无标题 %i" - -#: Lib/Managers/ExportManager.vala:484 -msgid "Exporting images…" -msgstr "导出图像…" - -#: Partials/ExportWidget.vala:117 -#, c-format -msgid "%i × %i px · %s" -msgstr "%i × %i px · %s" - -#: Partials/ExportWidget.vala:124 -msgid "Fetching image size…" -msgstr "撷取图片大小…" - -#: Partials/ZoomButton.vala:49 -msgid "Zoom Out" -msgstr "缩小" - -#: Partials/ZoomButton.vala:55 -msgid "Reset Zoom" -msgstr "重置缩放" - -#: Partials/ZoomButton.vala:62 -msgid "Zoom In" -msgstr "放大" - -#: Partials/ZoomButton.vala:68 -msgid "Zoom" -msgstr "缩放" - -#: Services/ActionManager.vala:208 -msgid "No recently opened file available!" -msgstr "没有最近打开的文件!" - -#: Services/ActionManager.vala:227 -msgid "No second most recently opened file available!" -msgstr "没有第二个最近打开的文件!" - -#: Services/ActionManager.vala:246 -msgid "No third most recently opened file available!" -msgstr "没有第三个最近打开的文件!" - -#: Services/ActionManager.vala:284 -msgid "Nothing selected to export!" -msgstr "没有选择要导出的内容!" - -#: Services/ActionManager.vala:293 -msgid "Export of Artboards currently unavailable…sorry 😑️" -msgstr "目前无法导出画板…对不起 😑️" - -#: Services/ActionManager.vala:360 -msgid "Choose image file" -msgstr "选择图像文件" - -#: Services/ActionManager.vala:360 -msgid "Select" -msgstr "选择" - -#: Services/ActionManager.vala:360 -msgid "Close" -msgstr "关闭" - -#: Services/ActionManager.vala:429 -#, c-format -msgid "Error! .%s files are not supported!" -msgstr "错误!不支持 .%s 文件!" - -#: Window.vala:119 -msgid "Are you sure you want to quit?" -msgstr "确定要退出吗?" - -#: Window.vala:120 -msgid "All unsaved data will be lost and impossible to recover." -msgstr "所有未保存的数据将丢失,并且无法恢复。" - -#: Window.vala:122 -msgid "Quit without saving!" -msgstr "不保存并退出!" - -#: Window.vala:123 -msgid "Save file" -msgstr "保存文件" diff --git a/po/zh_HK.po b/po/zh_HK.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/zh_HK.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/zh_TW.po b/po/zh_TW.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/zh_TW.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/po/zu.po b/po/zu.po deleted file mode 100644 index 7d7bf5d53..000000000 --- a/po/zu.po +++ /dev/null @@ -1,4 +0,0 @@ -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" diff --git a/src/Application.vala b/src/Application.vala deleted file mode 100644 index e02e2bec8..000000000 --- a/src/Application.vala +++ /dev/null @@ -1,178 +0,0 @@ -/* -* Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -namespace Akira { - public Akira.Services.Settings settings; -} - -public class Akira.Application : Gtk.Application { - public GLib.List windows; - - construct { - flags |= ApplicationFlags.HANDLES_OPEN; - - settings = new Akira.Services.Settings (); - windows = new GLib.List (); - - application_id = Constants.APP_ID; - } - - public override void open (File[] files, string hint) { - // Loop through all selected files. - foreach (var file in files) { - if (is_file_opened (file)) { - // Present active window with currently opened file. - // We don't allow opening the same file on multiple windows. - var window = get_window_from_file (file); - window.show_app (); - continue; - } - - // If the current window is empty, load the file in this one. - var current_window = active_window as Akira.Window; - if (current_window != null && current_window.akira_file == null && !current_window.edited) { - current_window.open_file (file); - current_window.event_bus.file_saved (file.get_basename ()); - continue; - } - - // The application was requested to open some files. Be sure to - // initialize the theme in case it wasn't already running. - init_theme (); - - // Open a new window. - var window = new Akira.Window (this); - this.add_window (window); - - window.open_file (file); - window.show_app (); - window.event_bus.file_saved (file.get_basename ()); - } - } - - public Akira.Window? get_window_from_file (File file) { - foreach (Akira.Window window in windows) { - if (window.akira_file != null && window.akira_file.opened_file.get_path () == file.get_path ()) { - return window; - } - } - - return null; - } - - public bool is_file_opened (File file) { - foreach (Akira.Window window in windows) { - if (window.akira_file != null && window.akira_file.opened_file.get_path () == file.get_path ()) { - return true; - } - } - - return false; - } - - public void new_window () { - new Akira.Window (this).present (); - } - - public override void window_added (Gtk.Window window) { - windows.append (window as Akira.Window); - base.window_added (window); - } - - public override void window_removed (Gtk.Window window) { - windows.remove (window as Akira.Window); - base.window_removed (window); - } - - /** - * Update the list of recently opened files in all the currently opened Windows. - */ - public void update_recent_files_list () { - foreach (Akira.Window window in windows) { - window.event_bus.update_recent_files_list (); - } - } - - protected override void activate () { - init_theme (); - - var window = new Akira.Window (this); - this.add_window (window); - - if (settings.version != Constants.VERSION) { - var dialog = new Akira.Dialogs.ReleaseDialog (window); - dialog.show_all (); - dialog.present (); - - // Update the settings so we don't show the same dialog again. - settings.version = Constants.VERSION; - } - - // Load the most recently opened/saved file. - if (settings.open_quick) { - window.action_manager.action_load_first (); - } - } - - private void init_theme () { - // Interrupt if we have at least one existing window, meaning the theme - // was previously initialized. - if (windows.length () > 0) { - return; - } - - // Add the resource path to load custom icons. - weak Gtk.IconTheme default_theme = Gtk.IconTheme.get_default (); - default_theme.add_resource_path ("/com/github/akiraux/akira"); - - // Load the custom CSS. - var css_provider = new Gtk.CssProvider (); - css_provider.load_from_resource ("/com/github/akiraux/akira/stylesheet.css"); - Gtk.StyleContext.add_provider_for_screen ( - Gdk.Screen.get_default (), css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - - // Force set the elementary OS style and icons for visual consistency. - // In the future we might support other themes if doable. - var gtk_settings = Gtk.Settings.get_default (); - gtk_settings.set_property ("gtk-icon-theme-name", "elementary"); - gtk_settings.set_property ("gtk-theme-name", "io.elementary.stylesheet.blueberry"); - - // Use the Granite API to listen for global dark style changes. - var granite_settings = Granite.Settings.get_default (); - if (settings.follow_system_theme) { - // Follow the system themeing. - gtk_settings.gtk_application_prefer_dark_theme = - granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK; - } else { - // Follow the user's settings. - gtk_settings.gtk_application_prefer_dark_theme = settings.dark_theme; - } - - // Listen for the changes in the theme's preferences. - granite_settings.notify["prefers-color-scheme"].connect (() => { - if (settings.follow_system_theme) { - gtk_settings.gtk_application_prefer_dark_theme = - granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK; - } - }); - } -} diff --git a/src/Dialogs/ExportDialog.vala b/src/Dialogs/ExportDialog.vala deleted file mode 100644 index 85f29f39f..000000000 --- a/src/Dialogs/ExportDialog.vala +++ /dev/null @@ -1,359 +0,0 @@ -/* -* Copyright (c) 2020-2022 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.Dialogs.ExportDialog : Gtk.Dialog { - public unowned Lib.ViewCanvas canvas { get; construct; } - public unowned Lib.Managers.ExportManager manager { get; construct; } - - public GLib.ListStore list_store; - - private Gtk.FlowBox export_grid; - private Gtk.Grid sidebar; - public Gtk.FileChooserButton folder_button; - public Gtk.Adjustment quality_adj; - public Gtk.Scale quality_scale; - public Gtk.Adjustment compression_adj; - public Gtk.Scale compression_scale; - public Gtk.ComboBoxText file_format; - public Gtk.Label jpg_title; - public Gtk.Label png_title; - public Gtk.Label alpha_title; - public Gtk.Switch alpha_switch; - - private Gtk.Button export_button; - - private Gtk.Overlay main_overlay; - private Granite.Widgets.Toast notification; - private Granite.Widgets.OverlayBar overlaybar; - - private GLib.Cancellable? preview_cancellable; - - public ExportDialog (Lib.ViewCanvas view_canvas, Lib.Managers.ExportManager export_manager) { - Object ( - canvas: view_canvas, - manager: export_manager, - border_width: 0, - deletable: true, - resizable: true, - modal: true - ); - } - - construct { - transient_for = canvas.window; - use_header_bar = 1; - default_width = settings.export_width; - default_height = settings.export_height; - - var sidebar_header = new Gtk.Grid () { - vexpand = true, - height_request = 30 - }; - sidebar_header.get_style_context ().add_class ("sidebar-export-header"); - - var main_header = new Gtk.Grid () { - vexpand = true - }; - - var pane_header = new Gtk.Paned (Gtk.Orientation.HORIZONTAL); - pane_header.pack1 (sidebar_header, false, false); - pane_header.pack2 (main_header, false, false); - pane_header.get_style_context ().add_class ("export-titlebar"); - - // Hack to remove the default header area and replace it with - // a custom widget. - var header_area = get_header_bar (); - header_area.destroy (); - set_titlebar (pane_header); - - // Another hack to remove the bottom action area. - var button = add_button ("OK", 3); - var button_area = button.get_parent (); - button_area.destroy (); - - sidebar = new Gtk.Grid (); - sidebar.get_style_context ().add_class ("sidebar-export"); - build_export_sidebar (); - - main_overlay = new Gtk.Overlay (); - notification = new Granite.Widgets.Toast (""); - overlaybar = new Granite.Widgets.OverlayBar (main_overlay); - overlaybar.active = true; - - var main = new Gtk.Grid () { - expand = true - }; - - list_store = new GLib.ListStore (typeof (Akira.Models.ExportModel)); - - export_grid = new Gtk.FlowBox () { - activate_on_single_click = false, - max_children_per_line = 1, - selection_mode = Gtk.SelectionMode.NONE, - column_spacing = 12, - row_spacing = 12 - }; - export_grid.get_style_context ().add_class ("export-panel"); - - export_grid.bind_model (list_store, model => { - return new Widgets.ExportWidget (model as Akira.Models.ExportModel); - }); - - var scrolled = new Gtk.ScrolledWindow (null, null) { - expand = true - }; - scrolled.get_style_context ().add_class (Gtk.STYLE_CLASS_VIEW); - scrolled.add (export_grid); - main.add (scrolled); - - main_overlay.add (main); - main_overlay.add_overlay (notification); - - var pane = new Gtk.Paned (Gtk.Orientation.HORIZONTAL); - pane.pack1 (sidebar, false, false); - pane.pack2 (main_overlay, true, false); - - var content_area = get_content_area (); - content_area.border_width = 0; - content_area.add (pane); - - pane.bind_property ("position", pane_header, "position"); - - pane_header.notify["position"].connect (() => { - pane_header.position = pane.position; - }); - - settings.bind ("export-paned", pane, "position", SettingsBindFlags.DEFAULT); - // GTK issue: combobox need to be added to a parent and be visible before - // we can use bind () to prevent a critical error. - settings.bind ("export-format", file_format, "active_id", - SettingsBindFlags.DEFAULT | GLib.SettingsBindFlags.GET_NO_CHANGES); - - manager.busy.connect (on_busy); - manager.show_preview.connect (on_show_preview); - manager.free.connect (on_free); - manager.export_finished.connect (on_export_finished); - - canvas.window.event_bus.toggle_export_button.connect (on_toggle_export_button); - } - - private void build_export_sidebar () { - var grid = new Gtk.Grid () { - expand = true, - column_spacing = 12, - margin_start = 12, - margin_end = 12, - margin_bottom = 12, - row_spacing = 6 - }; - - // Folder location. - grid.attach (section_title (_("Export to:")), 0, 0, 1, 1); - - if (settings.export_folder == "") { - settings.export_folder = Environment.get_user_special_dir (UserDirectory.PICTURES); - } - - folder_button = new Gtk.FileChooserButton (_("Select Folder"), Gtk.FileChooserAction.SELECT_FOLDER); - folder_button.set_current_folder (settings.export_folder); - folder_button.hexpand = true; - grid.attach (folder_button, 1, 0, 1, 1); - folder_button.selection_changed.connect (() => { - settings.export_folder = folder_button.get_filename (); - }); - - // File format. - var format_title = section_title (_("Format:")); - grid.attach (format_title, 0, 2, 1, 1); - - file_format = new Gtk.ComboBoxText (); - file_format.append ("png", "PNG"); - file_format.append ("jpg", "JPG"); - file_format.changed.connect (update_format_ui); - grid.attach (file_format, 1, 2, 1, 1); - settings.changed["export-format"].connect (() => { - if (preview_cancellable != null) { - preview_cancellable.cancel (); - } - - preview_cancellable = new GLib.Cancellable (); - manager.generate_preview.begin (preview_cancellable); - }); - - // Quality spinbutton. - jpg_title = section_title (_("Quality:")); - grid.attach (jpg_title, 0, 3, 1, 1); - - quality_adj = new Gtk.Adjustment (100.0, 0, 100.0, 0, 0, 0); - quality_scale = new Gtk.Scale (Gtk.Orientation.HORIZONTAL, quality_adj) { - hexpand = true, - draw_value = true, - digits = 0 - }; - grid.attach (quality_scale, 1, 3, 1, 1); - quality_scale.button_release_event.connect (() => { - settings.export_quality = (int) quality_adj.value; - return false; - }); - - // Compression spinbutton. - png_title = section_title (_("Compression:")); - grid.attach (png_title, 0, 4, 1, 1); - - compression_adj = new Gtk.Adjustment (0.0, 0, 9.0, 1, 0, 0); - compression_scale = new Gtk.Scale (Gtk.Orientation.HORIZONTAL, compression_adj) { - hexpand = true, - draw_value = true, - digits = 0 - }; - for (int i = 1; i <= 9; i++) { - compression_scale.add_mark (i, Gtk.PositionType.BOTTOM, null); - } - grid.attach (compression_scale, 1, 4, 1, 1); - compression_scale.button_release_event.connect (() => { - settings.export_compression = (int) compression_adj.value; - return false; - }); - - alpha_title = section_title (_("Transparency:")); - grid.attach (alpha_title, 0, 5, 1, 1); - - alpha_switch = new Gtk.Switch () { - valign = Gtk.Align.CENTER, - halign = Gtk.Align.START - }; - grid.attach (alpha_switch, 1, 5, 1, 1); - settings.bind ("export-alpha", alpha_switch, "active", - SettingsBindFlags.DEFAULT | SettingsBindFlags.GET_NO_CHANGES); - settings.changed["export-alpha"].connect (() => { - if (preview_cancellable != null) { - preview_cancellable.cancel (); - } - - preview_cancellable = new GLib.Cancellable (); - manager.generate_preview.begin (preview_cancellable); - }); - - // Resolution. - var size_title = section_title (_("Scale:")); - grid.attach (size_title, 0, 6, 1, 1); - - var scale_button = new Granite.Widgets.ModeButton () { - halign = Gtk.Align.FILL - }; - scale_button.append_text ("0.5×"); - scale_button.append_text ("1×"); - scale_button.append_text ("2×"); - scale_button.append_text ("4×"); - scale_button.set_active (settings.export_scale); - settings.bind ("export-scale", scale_button, "selected", - SettingsBindFlags.DEFAULT | SettingsBindFlags.GET_NO_CHANGES); - grid.attach (scale_button, 1, 6, 1, 1); - settings.changed["export-scale"].connect (() => { - if (preview_cancellable != null) { - preview_cancellable.cancel (); - } - - preview_cancellable = new GLib.Cancellable (); - manager.generate_preview.begin (preview_cancellable); - }); - - // Buttons. - var action_area = new Gtk.Grid () { - column_spacing = 6, - halign = Gtk.Align.END, - valign = Gtk.Align.END, - vexpand = true - }; - grid.attach (action_area, 0, 7, 2, 1); - - var cancel_button = new Gtk.Button.with_label (_("Cancel")) { - halign = Gtk.Align.START - }; - action_area.add (cancel_button); - cancel_button.clicked.connect (() => { - close (); - }); - - export_button = new Gtk.Button.with_label (_("Export")) { - halign = Gtk.Align.END - }; - export_button.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); - action_area.add (export_button); - export_button.clicked.connect (() => { - manager.export_images.begin (list_store); - }); - - sidebar.add (grid); - } - - public void update_format_ui () { - jpg_title.visible = (file_format.active_id == "jpg"); - quality_scale.visible = (file_format.active_id == "jpg"); - - png_title.visible = (file_format.active_id == "png"); - compression_scale.visible = (file_format.active_id == "png"); - alpha_title.visible = (file_format.active_id == "png"); - alpha_switch.visible = (file_format.active_id == "png"); - } - - public async void on_show_preview (Gee.HashMap pixbufs) { - list_store.remove_all (); - foreach (var entry in pixbufs.entries) { - var node = entry.key == Lib.Items.Model.ORIGIN_ID ? - null : canvas.items_manager.node_from_id (entry.key); - var model = new Models.ExportModel (canvas, node, entry.value); - list_store.append (model); - } - } - - private Gtk.Label section_title (string title) { - var title_label = new Gtk.Label (title) { - halign = Gtk.Align.END - }; - - return title_label; - } - - private async void on_busy (string message) { - overlaybar.label = message; - overlaybar.visible = true; - sidebar.@foreach ((child) => { - child.sensitive = false; - }); - } - - private async void on_free () { - sidebar.@foreach ((child) => { - child.sensitive = true; - }); - overlaybar.visible = false; - } - - public void on_export_finished (string message) { - notification.title = message; - notification.send_notification (); - } - - private void on_toggle_export_button (bool sensitive) { - export_button.sensitive = sensitive; - } -} diff --git a/src/Dialogs/ReleaseDialog.vala b/src/Dialogs/ReleaseDialog.vala deleted file mode 100644 index e5dfada93..000000000 --- a/src/Dialogs/ReleaseDialog.vala +++ /dev/null @@ -1,145 +0,0 @@ -/* -* Copyright (c) 2020 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.Dialogs.ReleaseDialog : Gtk.Dialog { - public weak Akira.Window window { get; construct; } - - public ReleaseDialog (Akira.Window window) { - Object ( - window: window, - border_width: 10, - deletable: true, - resizable: false, - modal: true - ); - } - - construct { - transient_for = window; - default_width = 624; - - var banner_grid = new Gtk.Grid (); - banner_grid.get_style_context ().add_class ("banner"); - banner_grid.halign = Gtk.Align.CENTER; - banner_grid.width_request = 600; - banner_grid.height_request = 200; - banner_grid.margin_bottom = 6; - - var disclaimer = new Gtk.Label ( - _("WARNING!\nAkira is still under development and not ready for production. Missing features, random bugs, and black holes opening in your kitchen are to be expected." - ) - ); - disclaimer.justify = Gtk.Justification.CENTER; - disclaimer.margin_top = disclaimer.margin_bottom = 6; - disclaimer.margin_start = disclaimer.margin_end = 3; - disclaimer.max_width_chars = 80; - disclaimer.wrap = true; - - var warning_grid = new Gtk.Grid (); - warning_grid.halign = Gtk.Align.CENTER; - warning_grid.margin_bottom = 24; - warning_grid.get_style_context ().add_class ("warning-message"); - warning_grid.add (disclaimer); - - var app_version = new Gtk.Label ("v" + Constants.VERSION + " - alpha"); - app_version.get_style_context ().add_class ("h2"); - app_version.selectable = true; - - var version_title = new Gtk.Label ("Performance improvements and Global colors library"); - version_title.get_style_context ().add_class ("h3"); - - var version_date = new Gtk.Label ("Jul 20th, 2021"); - version_date.get_style_context ().add_class ("dim-label"); - - var header_grid = new Gtk.Grid (); - header_grid.halign = Gtk.Align.CENTER; - header_grid.margin_bottom = 12; - header_grid.attach (app_version, 0, 0); - header_grid.attach (version_title, 0, 1); - header_grid.attach (version_date, 0, 2); - - var scrolled = new Gtk.ScrolledWindow (null, null); - scrolled.min_content_height = 200; - scrolled.expand = true; - - var release_info = new Gtk.TextView (); - release_info.buffer.text = "✓ Improved 'Modes' detection (insert, select, transform).\n✓ Fixed Artboard label issues on zoom.\n✓ Improved Pixel Grid detection and z-index stack with other items.\n✓ Implemented editable zoom value.\n✓ Fix application activation when opening a new file.\n✓ Fix sizing issue when dropping images into the Canvas.\n✓ Implemented Global colors library.\n✓ Italian translation.\n"; - release_info.pixels_below_lines = 3; - release_info.border_width = 12; - release_info.wrap_mode = Gtk.WrapMode.WORD; - release_info.cursor_visible = false; - release_info.editable = false; - release_info.get_style_context ().add_class (Granite.STYLE_CLASS_TERMINAL); - - scrolled.add (release_info); - - // Button grid at the bottom of the dialog. - var button_grid = new Gtk.ButtonBox (Gtk.Orientation.HORIZONTAL); - button_grid.halign = Gtk.Align.CENTER; - button_grid.spacing = 6; - button_grid.margin_top = 12; - - var donate_button = new Gtk.Button.with_label (_("Make a Donation")); - donate_button.clicked.connect (() => { - try { - AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira#-support", null); - } catch (Error e) { - warning (e.message); - } - }); - - var translate_button = new Gtk.Button.with_label (_("Suggest Translations")); - translate_button.clicked.connect (() => { - try { - AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira/issues", null); - } catch (Error e) { - warning (e.message); - } - }); - - var bug_button = new Gtk.Button.with_label (_("Report a Problem")); - bug_button.clicked.connect (() => { - try { - AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira/issues", null); - } catch (Error e) { - warning (e.message); - } - }); - - button_grid.add (donate_button); - button_grid.add (translate_button); - button_grid.add (bug_button); - - var grid = new Gtk.Grid (); - grid.column_spacing = 12; - grid.hexpand = true; - - grid.attach (banner_grid, 0, 0); - grid.attach (warning_grid, 0, 1); - grid.attach (header_grid, 0, 2); - grid.attach (scrolled, 0, 3); - grid.attach (button_grid, 0, 4); - - var content_area = get_content_area (); - content_area.border_width = 12; - content_area.add (grid); - } -} diff --git a/src/Dialogs/SettingsDialog.vala b/src/Dialogs/SettingsDialog.vala deleted file mode 100644 index 427d6b61e..000000000 --- a/src/Dialogs/SettingsDialog.vala +++ /dev/null @@ -1,430 +0,0 @@ -/* -* Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.Dialogs.SettingsDialog : Gtk.Dialog { - public weak Akira.Window window { get; construct; } - private Gtk.Stack stack; - private Gtk.Switch dark_theme_switch; - private Gtk.Switch follow_system_switch; - private Gtk.Switch label_switch; - private Gtk.Switch symbolic_switch; - private Gtk.Switch border_switch; - private Gtk.ColorButton grid_color; - private Gtk.ColorButton snaps_color; - private Gtk.ColorButton fill_color; - private Gtk.ColorButton border_color; - private Gtk.SpinButton border_size; - - public SettingsDialog (Akira.Window _window) { - Object ( - window: _window, - border_width: 6, - deletable: true, - resizable: false, - modal: true, - title: _("Preferences") - ); - } - - construct { - transient_for = window; - stack = new Gtk.Stack (); - stack.margin = 6; - stack.margin_bottom = 15; - stack.margin_top = 15; - stack.add_titled (get_general_box (), "general", _("General")); - stack.add_titled (get_interface_box (), "interface", _("Interface")); - stack.add_titled (get_canvas_box (), "canvas", _("Canvas")); - stack.add_titled (get_shapes_box (), "shapes", _("Shapes")); - stack.add_titled (get_about_box (), "about", _("About")); - - var stack_switcher = new Gtk.StackSwitcher (); - stack_switcher.set_stack (stack); - stack_switcher.halign = Gtk.Align.CENTER; - - var grid = new Gtk.Grid (); - grid.halign = Gtk.Align.CENTER; - grid.attach (stack_switcher, 1, 1, 1, 1); - grid.attach (stack, 1, 2, 1, 1); - - get_content_area ().add (grid); - } - - private Gtk.Widget get_general_box () { - var grid = new Gtk.Grid (); - grid.row_spacing = 6; - grid.column_spacing = 12; - grid.column_homogeneous = true; - - grid.attach (new SettingsHeader (_("General")), 0, 0, 2, 1); - grid.attach (new SettingsLabel (_("Auto Reopen Latest File:")), 0, 1, 1, 1); - grid.attach (new SettingsSwitch ("open-quick"), 1, 1, 1, 1); - - return grid; - } - - private Gtk.Widget get_interface_box () { - var grid = new Gtk.Grid (); - grid.row_spacing = 6; - grid.column_spacing = 12; - grid.column_homogeneous = true; - - grid.attach (new SettingsHeader (_("Interface")), 0, 0, 2, 1); - - grid.attach (new SettingsLabel (_("Use Dark Theme:")), 0, 1, 1, 1); - dark_theme_switch = new SettingsSwitch ("dark-theme"); - dark_theme_switch.sensitive = !settings.follow_system_theme; - grid.attach (dark_theme_switch, 1, 1, 1, 1); - - grid.attach (new SettingsLabel (_("Follow the system theme variation:")), 0, 2, 1, 1); - follow_system_switch = new SettingsSwitch ("follow-system-theme"); - grid.attach (follow_system_switch, 1, 2, 1, 1); - - var theme_helper_label = new Gtk.Label (_("If enabled, the Dark Theme switch will be disabled.")); - theme_helper_label.get_style_context ().add_class ("dim-label"); - theme_helper_label.halign = Gtk.Align.START; - grid.attach (theme_helper_label, 1, 3, 1, 1); - - grid.attach (new SettingsLabel (_("Invert Panels Order:")), 0, 4, 1, 1); - symbolic_switch = new SettingsSwitch ("invert-sidebar"); - grid.attach (symbolic_switch, 1, 4, 1, 1); - - var panels_helper_label = new Gtk.Label (_("Restart application to apply this change.")); - panels_helper_label.get_style_context ().add_class ("dim-label"); - panels_helper_label.halign = Gtk.Align.START; - grid.attach (panels_helper_label, 1, 5, 1, 1); - - grid.attach (new SettingsHeader (_("ToolBar Style")), 0, 6, 2, 1); - - grid.attach (new SettingsLabel (_("Show Button Labels:")), 0, 7, 1, 1); - label_switch = new SettingsSwitch ("show-label"); - grid.attach (label_switch, 1, 7, 1, 1); - - grid.attach (new SettingsLabel (_("Use Symbolic Icons:")), 0, 8, 1, 1); - symbolic_switch = new SettingsSwitch ("use-symbolic"); - grid.attach (symbolic_switch, 1, 8, 1, 1); - - dark_theme_switch.notify["active"].connect (() => { - Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = settings.dark_theme; - window.event_bus.change_theme (); - }); - - follow_system_switch.notify["active"].connect (() => { - if (settings.follow_system_theme) { - dark_theme_switch.sensitive = false; - Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = Granite.Settings.get_default ().prefers_color_scheme == Granite.Settings.ColorScheme.DARK; - return; - } - dark_theme_switch.sensitive = true; - Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = settings.dark_theme; - }); - - return grid; - } - - private Gtk.Widget get_canvas_box () { - var grid = new Gtk.Grid (); - grid.row_spacing = 6; - grid.column_spacing = 12; - grid.column_homogeneous = true; - - // Pixel grid. - var grid_rgba = Gdk.RGBA (); - grid_rgba.parse (settings.grid_color); - - grid.attach (new SettingsHeader (_("Pixel Grid")), 0, 0, 2, 1); - - var description = new Gtk.Label (_("Define the default color for the Canvas pixel grid.")); - description.halign = Gtk.Align.START; - description.margin_bottom = 10; - grid.attach (description, 0, 1, 2, 1); - - grid.attach (new SettingsLabel (_("Pixel Grid Color:")), 0, 2, 1, 1); - grid_color = new Gtk.ColorButton.with_rgba (grid_rgba); - grid_color.halign = Gtk.Align.START; - grid.attach (grid_color, 1, 2, 1, 1); - - grid_color.color_set.connect (() => { - var rgba = grid_color.get_rgba (); - - // Gdk.RGBA uses rgb() if alpha is 1. - string rgba_str = "rgba(%d,%d,%d,%d)".printf ( - (int) (rgba.red * 255), - (int) (rgba.green * 255), - (int) (rgba.blue * 255), - (int) (rgba.alpha) - ); - - debug ("pixel grid color: %s", rgba_str); - - settings.grid_color = rgba_str; - window.event_bus.update_pixel_grid (); - }); - - // Snapping guides. - var snaps_rgba = Gdk.RGBA (); - snaps_rgba.parse (settings.snaps_color); - - grid.attach (new SettingsHeader (_("Snapping Guides")), 0, 3, 2, 1); - - var snaps_description = new Gtk.Label (_("Define the default options for the Snapping Guides.")); - snaps_description.halign = Gtk.Align.START; - snaps_description.margin_bottom = 10; - grid.attach (snaps_description, 0, 4, 2, 1); - - grid.attach (new SettingsLabel (_("Enable Snapping Guides:")), 0, 5, 1, 1); - var snaps_switch = new SettingsSwitch ("enable-snaps"); - grid.attach (snaps_switch, 1, 5, 1, 1); - - grid.attach (new SettingsLabel (_("Snapping Guides Color:")), 0, 6, 1, 1); - snaps_color = new Gtk.ColorButton.with_rgba (snaps_rgba); - snaps_color.halign = Gtk.Align.START; - grid.attach (snaps_color, 1, 6, 1, 1); - - snaps_color.color_set.connect (() => { - var rgba = snaps_color.get_rgba (); - - // Gdk.RGBA uses rgb() if alpha is 1. - string rgba_str = "rgba(%d,%d,%d,%d)".printf ( - (int) (rgba.red * 255), - (int) (rgba.green * 255), - (int) (rgba.blue * 255), - (int) (rgba.alpha) - ); - - debug ("pixel snaps color: %s", rgba_str); - - settings.snaps_color = rgba_str; - window.event_bus.update_snaps_color (); - }); - - grid.attach (new SettingsLabel (_("Snapping Sensitivity Threshold:")), 0, 7, 1, 1); - var snaps_sensitivity = new Gtk.SpinButton.with_range (0, 9999, 1); - snaps_sensitivity.halign = Gtk.Align.START; - snaps_sensitivity.width_chars = 6; - snaps_sensitivity.get_style_context ().add_class ("input-icon-right"); - snaps_sensitivity.secondary_icon_name = "input-pixel-symbolic"; - snaps_sensitivity.secondary_icon_sensitive = false; - snaps_sensitivity.secondary_icon_activatable = false; - grid.attach (snaps_sensitivity, 1, 7, 1, 1); - - settings.bind ("snaps-sensitivity", snaps_sensitivity, "value", SettingsBindFlags.DEFAULT); - - snaps_switch.bind_property ("active", snaps_color, "sensitive", BindingFlags.SYNC_CREATE); - snaps_switch.bind_property ("active", snaps_sensitivity, "sensitive", BindingFlags.SYNC_CREATE); - - return grid; - } - - private Gtk.Widget get_shapes_box () { - var grid = new Gtk.Grid (); - grid.row_spacing = 6; - grid.column_spacing = 12; - grid.column_homogeneous = true; - - var fill_rgba = Gdk.RGBA (); - fill_rgba.parse (settings.fill_color); - var border_rgba = Gdk.RGBA (); - border_rgba.parse (settings.border_color); - - grid.attach (new SettingsHeader (_("Default Colors")), 0, 0, 2, 1); - - var description = new Gtk.Label (_("Define the default style used when creating a new shape.")); - description.halign = Gtk.Align.START; - description.margin_bottom = 10; - grid.attach (description, 0, 1, 2, 1); - - grid.attach (new SettingsLabel (_("Fill Color:")), 0, 2, 1, 1); - fill_color = new Gtk.ColorButton.with_rgba (fill_rgba); - fill_color.halign = Gtk.Align.START; - grid.attach (fill_color, 1, 2, 1, 1); - - fill_color.color_set.connect (() => { - var rgba = fill_color.get_rgba (); - - // Gdk.RGBA uses rgb() if alpha is 1. - string rgba_str = "rgba(%d,%d,%d,%d)".printf ( - (int) (rgba.red * 255), - (int) (rgba.green * 255), - (int) (rgba.blue * 255), - (int) (rgba.alpha) - ); - - debug ("setting color: %s", rgba_str); - - settings.fill_color = rgba_str; - }); - - grid.attach (new SettingsLabel (_("Enable Border Style:")), 0, 3, 1, 1); - border_switch = new SettingsSwitch ("set-border"); - grid.attach (border_switch, 1, 3, 1, 1); - grid.attach (new SettingsLabel (_("Border Color:")), 0, 4, 1, 1); - border_color = new Gtk.ColorButton.with_rgba (border_rgba); - border_color.halign = Gtk.Align.START; - grid.attach (border_color, 1, 4, 1, 1); - - border_color.color_set.connect (() => { - var rgba = border_color.get_rgba (); - - // Gdk.RGBA uses rgb() if alpha is 1. - string rgba_str = "rgba(%d,%d,%d,%d)".printf ( - (int) (rgba.red * 255), - (int) (rgba.green * 255), - (int) (rgba.blue * 255), - (int) (rgba.alpha) - ); - - debug ("setting color: %s", rgba_str); - - settings.border_color = rgba_str; - }); - - grid.attach (new SettingsLabel (_("Border Width:")), 0, 5, 1, 1); - border_size = new Gtk.SpinButton.with_range (1, 9999, 1); - border_size.halign = Gtk.Align.START; - border_size.width_chars = 6; - border_size.get_style_context ().add_class ("input-icon-right"); - border_size.secondary_icon_name = "input-pixel-symbolic"; - border_size.secondary_icon_sensitive = false; - border_size.secondary_icon_activatable = false; - grid.attach (border_size, 1, 5, 1, 1); - - settings.bind ("border-size", border_size, "value", SettingsBindFlags.DEFAULT); - - border_switch.bind_property ("active", border_color, "sensitive", BindingFlags.SYNC_CREATE); - border_switch.bind_property ("active", border_size, "sensitive", BindingFlags.SYNC_CREATE); - - return grid; - } - - private Gtk.Widget get_about_box () { - var grid = new Gtk.Grid (); - grid.row_spacing = 6; - grid.column_spacing = 12; - grid.halign = Gtk.Align.CENTER; - - var app_icon = new Gtk.Image (); - app_icon.gicon = new ThemedIcon (Constants.APP_ID); - app_icon.pixel_size = 64; - app_icon.margin_top = 12; - - var app_name = new Gtk.Label (Constants.APP_NAME); - app_name.get_style_context ().add_class ("h2"); - app_name.margin_top = 6; - - var app_description = new Gtk.Label (_("The Linux Design Tool")); - app_description.get_style_context ().add_class ("h3"); - - var app_version = new Gtk.Label ("v" + Constants.VERSION + " - alpha"); - app_version.get_style_context ().add_class ("dim-label"); - app_version.selectable = true; - - var disclaimer = new Gtk.Label ( - _("WARNING!\nAkira is still under development and not ready for production. Missing features, random bugs, and black holes opening in your kitchen are to be expected." - ) - ); - disclaimer.justify = Gtk.Justification.CENTER; - disclaimer.get_style_context ().add_class ("warning-message"); - disclaimer.max_width_chars = 60; - disclaimer.wrap = true; - disclaimer.margin_top = disclaimer.margin_bottom = 12; - - var patreons_label = new Gtk.Label (_("Thanks to our awesome supporters!")); - patreons_label.get_style_context ().add_class ("h4"); - - var patreons_url = new Gtk.LinkButton.with_label ( - "https://github.com/akiraux/Akira/blob/master/SUPPORTERS.md", - _("View the list of supporters") - ); - patreons_url.halign = Gtk.Align.CENTER; - patreons_url.margin_bottom = 12; - - grid.attach (app_icon, 0, 0); - grid.attach (app_name, 0, 1); - grid.attach (app_description, 0, 2); - grid.attach (app_version, 0, 3); - grid.attach (disclaimer, 0, 4); - grid.attach (patreons_label, 0, 5); - grid.attach (patreons_url, 0, 6); - - // Button grid at the bottom of the About page. - var button_grid = new Gtk.ButtonBox (Gtk.Orientation.HORIZONTAL); - button_grid.halign = Gtk.Align.CENTER; - button_grid.spacing = 6; - - var donate_button = new Gtk.Button.with_label (_("Make a Donation")); - donate_button.clicked.connect (() => { - try { - AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira#-support", null); - } catch (Error e) { - warning (e.message); - } - }); - - var translate_button = new Gtk.Button.with_label (_("Suggest Translations")); - translate_button.clicked.connect (() => { - try { - AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira/issues", null); - } catch (Error e) { - warning (e.message); - } - }); - - var bug_button = new Gtk.Button.with_label (_("Report a Problem")); - bug_button.clicked.connect (() => { - try { - AppInfo.launch_default_for_uri ("https://github.com/akiraux/Akira/issues", null); - } catch (Error e) { - warning (e.message); - } - }); - - button_grid.add (donate_button); - button_grid.add (translate_button); - button_grid.add (bug_button); - - grid.attach (button_grid, 0, 7); - - return grid; - } - - private class SettingsHeader : Gtk.Label { - public SettingsHeader (string text) { - label = text; - get_style_context ().add_class ("h4"); - halign = Gtk.Align.START; - } - } - - private class SettingsLabel : Gtk.Label { - public SettingsLabel (string text) { - label = text; - halign = Gtk.Align.END; - } - } - - private class SettingsSwitch : Gtk.Switch { - public SettingsSwitch (string setting) { - halign = Gtk.Align.START; - settings.bind (setting, this, "active", SettingsBindFlags.DEFAULT); - } - } -} diff --git a/src/Dialogs/ShortcutsDialog.vala b/src/Dialogs/ShortcutsDialog.vala deleted file mode 100644 index 9049702e6..000000000 --- a/src/Dialogs/ShortcutsDialog.vala +++ /dev/null @@ -1,157 +0,0 @@ -/* -* Copyright (c) 2020 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.Dialogs.ShortcutsDialog : Gtk.Dialog { - public weak Akira.Window window { get; construct; } - - public ShortcutsDialog (Akira.Window window) { - Object ( - window: window, - border_width: 10, - deletable: true, - resizable: true, - modal: true - ); - } - - construct { - transient_for = window; - default_width = 800; - - var column_start = new Gtk.Grid (); - column_start.column_spacing = 12; - column_start.row_spacing = 12; - column_start.hexpand = true; - column_start.column_homogeneous = true; - - column_start.attach (new Granite.HeaderLabel (_("General")), 0, 0, 2); - column_start.attach (new NameLabel (_("New window:")), 0, 1); - column_start.attach (new ShortcutLabel ({"Ctrl", "N"}), 1, 1); - column_start.attach (new NameLabel (_("Preferences:")), 0, 2); - column_start.attach (new ShortcutLabel ({"Ctrl", ","}), 1, 2); - column_start.attach (new NameLabel (_("Quit:")), 0, 3); - column_start.attach (new ShortcutLabel ({"Ctrl", "Q"}), 1, 3); - column_start.attach (new NameLabel (_("Presentation mode:")), 0, 4); - column_start.attach (new ShortcutLabel ({"Ctrl", "."}), 1, 4); - - column_start.attach (new Granite.HeaderLabel (_("File")), 0, 5, 2); - column_start.attach (new NameLabel (_("Open:")), 0, 6); - column_start.attach (new ShortcutLabel ({"Ctrl", "O"}), 1, 6); - column_start.attach (new NameLabel (_("Save:")), 0, 7); - column_start.attach (new ShortcutLabel ({"Ctrl", "S"}), 1, 7); - column_start.attach (new NameLabel (_("Save as:")), 0, 8); - column_start.attach (new ShortcutLabel ({"Ctrl", "Shift", "S"}), 1, 8); - - column_start.attach (new Granite.HeaderLabel (_("Export")), 0, 9, 2); - column_start.attach (new NameLabel (_("Export artboards:")), 0, 10); - column_start.attach (new ShortcutLabel ({"Ctrl", "Alt", "A"}), 1, 10); - column_start.attach (new NameLabel (_("Export selection:")), 0, 11); - column_start.attach (new ShortcutLabel ({"Ctrl", "Alt", "E"}), 1, 11); - column_start.attach (new NameLabel (_("Highlight area to export:")), 0, 12); - column_start.attach (new ShortcutLabel ({"Ctrl", "Alt", "G"}), 1, 12); - - var column_end = new Gtk.Grid (); - column_end.column_spacing = 12; - column_end.row_spacing = 12; - column_end.hexpand = true; - column_end.column_homogeneous = true; - - column_end.attach (new Granite.HeaderLabel (_("Canvas")), 0, 0, 2); - column_end.attach (new NameLabel (_("Zoom in:")), 0, 1); - column_end.attach (new ShortcutLabel ({"Ctrl", "+"}), 1, 1); - column_end.attach (new NameLabel (_("Zoom out:")), 0, 2); - column_end.attach (new ShortcutLabel ({"Ctrl", "-"}), 1, 2); - column_end.attach (new NameLabel (_("Zoom reset:")), 0, 3); - column_end.attach (new ShortcutLabel ({"Ctrl", "0"}), 1, 3); - - column_end.attach (new Granite.HeaderLabel (_("Item creation")), 0, 4, 2); - column_end.attach (new NameLabel (_("Artboard:")), 0, 5); - column_end.attach (new ShortcutLabel ({"A"}), 1, 5); - column_end.attach (new NameLabel (_("Rectangle:")), 0, 6); - column_end.attach (new ShortcutLabel ({"R"}), 1, 6); - column_end.attach (new NameLabel (_("Ellipse:")), 0, 7); - column_end.attach (new ShortcutLabel ({"E"}), 1, 7); - column_end.attach (new NameLabel (_("Text:")), 0, 8); - column_end.attach (new ShortcutLabel ({"T"}), 1, 8); - column_end.attach (new NameLabel (_("Image:")), 0, 9); - column_end.attach (new ShortcutLabel ({"I"}), 1, 9); - - column_end.attach (new Granite.HeaderLabel (_("Transform")), 0, 10, 2); - column_end.attach (new NameLabel (_("Raise selection:")), 0, 11); - column_end.attach (new ShortcutLabel ({"Ctrl", "↑"}), 1, 11); - column_end.attach (new NameLabel (_("Lower selection:")), 0, 12); - column_end.attach (new ShortcutLabel ({"Ctrl", "↓"}), 1, 12); - column_end.attach (new NameLabel (_("Raise selection to top:")), 0, 13); - column_end.attach (new ShortcutLabel ({"Ctrl", "Shift", "↑"}), 1, 13); - column_end.attach (new NameLabel (_("Lower selection to bottom:")), 0, 14); - column_end.attach (new ShortcutLabel ({"Ctrl", "Shift", "↓"}), 1, 14); - column_end.attach (new NameLabel (_("Flip horizontally:")), 0, 15); - column_end.attach (new ShortcutLabel ({"Ctrl", "["}), 1, 15); - column_end.attach (new NameLabel (_("Flip vertically:")), 0, 16); - column_end.attach (new ShortcutLabel ({"Ctrl", "]"}), 1, 16); - - var grid = new Gtk.Grid (); - grid.column_spacing = 12; - grid.hexpand = true; - grid.attach (column_start, 0, 0); - grid.attach (new Gtk.Separator (Gtk.Orientation.VERTICAL), 1, 0); - grid.attach (column_end, 2, 0); - - var content_area = get_content_area (); - content_area.border_width = 12; - content_area.add (grid); - } - - private class NameLabel : Gtk.Label { - public NameLabel (string label) { - Object ( - label: label - ); - } - - construct { - halign = Gtk.Align.END; - xalign = 1; - } - } - - private class ShortcutLabel : Gtk.Grid { - public string[] accels { get; set construct; } - - public ShortcutLabel (string[] accels) { - Object (accels: accels); - } - - construct { - column_spacing = 6; - - foreach (unowned string accel in accels) { - if (accel == "") { - continue; - } - var label = new Gtk.Label (accel); - label.get_style_context ().add_class ("keycap"); - add (label); - } - halign = Gtk.Align.START; - } - } -} diff --git a/src/Drawables/Drawable.vala b/src/Drawables/Drawable.vala deleted file mode 100644 index 42d4b787c..000000000 --- a/src/Drawables/Drawable.vala +++ /dev/null @@ -1,405 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * Overrides methods in Goo.CanvasItemSimple to handle a few things differently: - * 1. Have uniform strokes in transformed objects. - * 2. Add a clipping quad to make clipping more efficient. - */ -public class Akira.Drawables.Drawable { - public enum HitTestType { - SELECT, - GROUP_REGION - } - - public enum BorderType { - CENTER, - INSIDE, - OUTSIDE - } - - public enum DrawType { - NORMAL, - XRAY - } - - // Style - public double line_width { get; set; default = 0; } - public Gdk.RGBA fill_rgba { get; set; default = Gdk.RGBA (); } - public Gdk.RGBA stroke_rgba { get; set; default = Gdk.RGBA (); } - public BorderType border_type { get; set; default = BorderType.CENTER; } - public double radius_tr { get; set; default = 0; } - public double radius_tl { get; set; default = 0; } - public double radius_br { get; set; default = 0; } - public double radius_bl { get; set; default = 0; } - - public int parent_id { get; set; default = -1; } - public string label { get; set; default = ""; } - public double center_x { get; set; default = 0; } - public double center_y { get; set; default = 0; } - public double width { get; set; default = 0; } - public double height { get; set; default = 0; } - public Cairo.Matrix transform { get; set; default = Cairo.Matrix.identity (); } - - public Geometry.Rectangle bounds { get; set; default = Geometry.Rectangle (); } - - // Clipping path in global reference frame - public Geometry.Quad? clipping_path = null; - - // Convenience getters - public bool has_radius { get { return (radius_tr + radius_tl + radius_br + radius_bl) > 0; } } - - public bool is_drawn = false; - - /* - * Return true if the position x,y in local coordinates is inside of the selectable - * area of a drawable. - */ - public virtual bool hit_test ( - double x, - double y, - Cairo.Context context, - double scale, - HitTestType hit_test_type - ) { - if (hit_test_type == GROUP_REGION) { - return false; - } - - double user_x = x, user_y = y; - bool add_item = false; - - // Ignore if out of bounds - if (bounds.does_not_contain (x, y)) { - return false; - } - - Cairo.Matrix global_transform = context.get_matrix (); - context.save (); - - Cairo.Matrix tr = transform; - context.transform (tr); - - // Account for clipping path first, since they should be in the global reference - if (clipping_path != null) { - context.move_to (clipping_path.tl_x, clipping_path.tl_y); - context.line_to (clipping_path.tr_x, clipping_path.tr_y); - context.line_to (clipping_path.br_x, clipping_path.br_y); - context.line_to (clipping_path.bl_x, clipping_path.bl_y); - context.close_path (); - - context.set_fill_rule (Cairo.FillRule.WINDING); - if (!context.in_fill (user_x, user_y)) { - context.restore (); - context.new_path (); - return false; - } - } - - context.device_to_user (ref user_x, ref user_y); - - /* Remove any current translation, to avoid the 16-bit cairo limit. */ - var tmp = context.get_matrix (); - tmp.x0 = 0.0; - tmp.y0 = 0.0; - context.set_matrix (tmp); - - simple_create_path (context); - - /* Check the filled path, if required. */ - if (set_fill_options (context, DrawType.NORMAL)) { - if (context.in_fill (user_x, user_y)) { - add_item = true; - } - } - - /* Check the stroke, if required. */ - if (set_stroke_options (context, DrawType.NORMAL)) { - context.set_matrix (global_transform); - user_x = x - tr.x0; - user_y = y - tr.y0; - - if (context.in_stroke (user_x, user_y)) { - add_item = true; - } - } - - context.restore (); - context.new_path (); - - return add_item; - } - - /* - * Create the path for an drawable, used in other methods. - */ - public virtual void simple_create_path (Cairo.Context context) {} - - /* - * Main paint method. - */ - public virtual void paint (Cairo.Context context, Geometry.Rectangle target_bounds, double scale, DrawType draw_type) { - // Simple bounds check - if (bounds.left > target_bounds.right || bounds.right < target_bounds.left - || bounds.top > target_bounds.bottom || bounds.bottom < target_bounds.top) { - return; - } - - Cairo.Matrix global_transform = context.get_matrix (); - - context.save (); - - var normal_draw = draw_type == DrawType.NORMAL; - - // The clipping path is in global coordinates, so we can ignore the transformation. - if (normal_draw && clipping_path != null) { - context.move_to (clipping_path.tl_x, clipping_path.tl_y); - context.line_to (clipping_path.tr_x, clipping_path.tr_y); - context.line_to (clipping_path.br_x, clipping_path.br_y); - context.line_to (clipping_path.bl_x, clipping_path.bl_y); - context.close_path (); - context.set_fill_rule (Cairo.FillRule.WINDING); - context.clip (); - } - - // We apply the item transform before creating the path - Cairo.Matrix tr = transform; - context.transform (tr); - - simple_create_path (context); - - if (set_fill_options (context, draw_type)) { - context.fill_preserve (); - } - - // We restore the global transformation to draw strokes with uniform width. Changing - // the matrix does not affect the path already generated. - context.set_matrix (global_transform); - - if (set_stroke_options (context, draw_type)) { - context.stroke (); - } - - context.restore (); - - // Very important to initialize new path - context.new_path (); - - is_drawn = true; - } - - /* - * Hover paint method for the drawable. - */ - public virtual void paint_hover ( - Cairo.Context context, - Gdk.RGBA color, - double line_width, - Geometry.Rectangle target_bounds, - double scale - ) { - context.save (); - Cairo.Matrix global_transform = context.get_matrix (); - - // We apply the item transform before creating the path - Cairo.Matrix tr = transform; - context.transform (tr); - - simple_create_path (context); - - context.set_line_width (line_width / scale); - context.set_source_rgba (color.red, color.green, color.blue, color.alpha); - context.set_matrix (global_transform); - context.stroke (); - - context.restore (); - - // Very important to initialize new path - context.new_path (); - } - - /* - * Create a target like element on top of the drawable to represent the - * current subselection anchor point that will be used as alignment pivot. - */ - public virtual void paint_anchor ( - Cairo.Context context, - Gdk.RGBA color, - double line_width, - double scale - ) { - context.save (); - - // We apply the item transform before creating the path - Cairo.Matrix tr = transform; - context.transform (tr); - - // Set the visual properties. - context.set_line_width (line_width / scale); - context.set_source_rgba (color.red, color.green, color.blue, color.alpha); - - // Create the circle. - context.new_path (); - context.arc (0.0, 0.0, 5 / scale, 0.0, 2.0 * GLib.Math.PI); - // Draw the circle and preserve the visual properties. - context.stroke (); - - var length = 10 / scale; - // Create the horizontal stroke. - context.new_path (); - context.move_to (-length, 0); - context.line_to (length, 0); - context.stroke (); - - // Create the vertical stroke. - context.new_path (); - context.move_to (0, -length); - context.line_to (0, length); - context.stroke (); - context.restore (); - - // Very important to initialize new path - context.new_path (); - } - - /* - * Generates the bounding box for the drawable. - */ - public virtual Geometry.Rectangle generate_bounding_box () { - double x1 = 0; - double x2 = 0; - double y1 = 0; - double y2 = 0; - - Cairo.ImageSurface surface = new Cairo.ImageSurface (Cairo.Format.A1, 1, 1); - Cairo.Context context = new Cairo.Context (surface); - - context.set_antialias (Cairo.Antialias.GRAY); - - Cairo.Matrix tr = transform; - context.transform (tr); - - double translate_x = tr.x0; - double translate_y = tr.y0; - - var fill_bounds = Geometry.Rectangle (); - var stroke_bounds = Geometry.Rectangle (); - - set_fill_options (context, DrawType.NORMAL); - - simple_create_path (context); - - context.set_matrix (Cairo.Matrix (1.0, 0.0, 0.0, 1.0, translate_x, translate_y)); - - context.fill_extents ( - out fill_bounds.left, - out fill_bounds.top, - out fill_bounds.right, - out fill_bounds.bottom - ); - - set_stroke_options (context, DrawType.NORMAL); - - context.stroke_extents ( - out stroke_bounds.left, - out stroke_bounds.top, - out stroke_bounds.right, - out stroke_bounds.bottom - ); - - if (fill_bounds.left == 0.0 && fill_bounds.right == 0.0) { - /* The fill bounds are empty so just use the stroke bounds. - If the stroke bounds are also empty the bounds will be all 0.0. */ - x1 = stroke_bounds.left; - x2 = stroke_bounds.right; - y1 = stroke_bounds.top; - y2 = stroke_bounds.bottom; - } else if (stroke_bounds.left == 0.0 && stroke_bounds.right == 0.0) { - /* The stroke bounds are empty so just use the fill bounds. */ - x1 = fill_bounds.left; - x2 = fill_bounds.right; - y1 = fill_bounds.top; - y2 = fill_bounds.bottom; - } else { - /* Both fill & stoke bounds are non-empty so combine them. */ - Utils.GeometryMath.min_max_coords ( - fill_bounds.left, - fill_bounds.right, - stroke_bounds.left, - stroke_bounds.right, - ref x1, - ref x2 - ); - - Utils.GeometryMath.min_max_coords ( - fill_bounds.top, - fill_bounds.bottom, - stroke_bounds.top, - stroke_bounds.bottom, - ref y1, - ref y2 - ); - } - - return Geometry.Rectangle.with_coordinates ( - x1 + translate_x, - y1 + translate_y, - x2 + translate_x, - y2 + translate_y - ); - } - - public virtual void request_redraw (ViewLayers.BaseCanvas canvas, bool recalculate_bounds) { - if (recalculate_bounds) { - bounds = generate_bounding_box (); - } - else if (!is_drawn) { - // This request is to clear the old draw, but since it was never drawn, we can ignore. - return; - } - - canvas.request_redraw (bounds); - } - - public bool set_fill_options (Cairo.Context context, DrawType draw_type) { - if (draw_type == DrawType.XRAY) { - return false; - } - context.set_source_rgba (fill_rgba.red, fill_rgba.green, fill_rgba.blue, fill_rgba.alpha); - context.set_antialias (Cairo.Antialias.GRAY); - return true; - } - - public bool set_stroke_options (Cairo.Context context, DrawType draw_type) { - if (draw_type == DrawType.XRAY) { - context.set_source_rgba (0.0, 0.0, 0.0, 1.0); - context.set_line_width (1); - context.set_antialias (Cairo.Antialias.GRAY); - return true; - } - - context.set_source_rgba (stroke_rgba.red, stroke_rgba.green, stroke_rgba.blue, stroke_rgba.alpha); - context.set_line_width (line_width); - context.set_antialias (Cairo.Antialias.GRAY); - return line_width > 0; - } - -} diff --git a/src/Drawables/DrawableArtboard.vala b/src/Drawables/DrawableArtboard.vala deleted file mode 100644 index e18012aaa..000000000 --- a/src/Drawables/DrawableArtboard.vala +++ /dev/null @@ -1,185 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * Drawable for artboards. - */ -public class Akira.Drawables.DrawableArtboard : Drawable { - private const double LABEL_HEIGHT = 20; - private const double LABEL_MARGIN = 5; - - public DrawableArtboard (double tl_x, double tl_y, double width, double height) { - this.center_x = tl_x + width / 2.0; - this.center_y = tl_y + height / 2.0; - this.width = width; - this.height = height; - } - - public override bool hit_test ( - double x, - double y, - Cairo.Context context, - double scale, - Drawable.HitTestType hit_test_type - ) { - if (hit_test_type == GROUP_REGION) { - return base.hit_test (x, y, context, scale, Drawable.HitTestType.SELECT); - } - - var lheight = LABEL_HEIGHT / scale; - var lbot = bounds.top; - var ltop = lbot - lheight; - - var m = label_margin (scale); - var w = bounds.width - m * 2; - if (w <= 0) { - return false; - } - - double extent_width = 0; - create_pango_layout (context, label, w, scale, &extent_width); - extent_width /= scale; - return !(x < bounds.left || x > bounds.left + extent_width + m * 2 || y < ltop || y > lbot); - } - - public override void simple_create_path (Cairo.Context context) { - Drawables.DrawableRect.rect_path (context, this); - } - - public override void paint (Cairo.Context context, Geometry.Rectangle target_bounds, double scale, Drawable.DrawType draw_type) { - base.paint (context, target_bounds, scale, draw_type); - - draw_text (context, scale); - } - - private void draw_text (Cairo.Context context, double scale) { - var m = label_margin (scale); - var w = bounds.width - m * 2; - if (w <= 0) { - return; - } - - context.save (); - - if (settings.follow_system_theme) { - var granite_settings = Granite.Settings.get_default (); - if (granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK) { - context.set_source_rgba (1, 1, 1, 0.75); - } else { - context.set_source_rgba (0, 0, 0, 0.75); - } - } else { - if (settings.dark_theme) { - context.set_source_rgba (1, 1, 1, 0.75); - } else { - context.set_source_rgba (0, 0, 0, 0.75); - } - } - - var layout = create_pango_layout (context, label, w, scale, null); - context.move_to (bounds.left + m, bounds.top - LABEL_HEIGHT / scale); - context.scale (1 / scale, 1 / scale); - Pango.cairo_show_layout (context, layout); - - context.restore (); - context.new_path (); - } - - private static Pango.Layout create_pango_layout ( - Cairo.Context context, - string text, - double layout_width, - double scale, - double* extent_width - ) { - var p_layout = Pango.cairo_create_layout (context); - var p_context = p_layout.get_context (); - - if (layout_width > 0) { - p_layout.set_width ( (int)(layout_width * Pango.SCALE)); - } - - p_layout.set_text (text, -1); - - // Load font description - var desc = new Pango.FontDescription (); - desc.set_family ("Open Sans"); - desc.set_size ((int) (10 * Pango.SCALE)); - p_layout.set_font_description (desc); - - // Load hint metrics - - var font_options = new Cairo.FontOptions (); - font_options.set_hint_metrics (Cairo.HintMetrics.DEFAULT); - Pango.cairo_context_set_font_options (p_context, font_options); - - p_layout.set_alignment (Pango.Alignment.LEFT); - p_layout.set_ellipsize (Pango.EllipsizeMode.END); - p_layout.set_wrap (Pango.WrapMode.WORD); - - if (extent_width != null) { - Pango.Rectangle ink_rect; - Pango.Rectangle logical_rect; - p_layout.get_extents (out ink_rect, out logical_rect); - - var logical_width = (double) logical_rect.width / Pango.SCALE; - *extent_width = logical_width; - } - - return p_layout; - } - - /* - * Hover paint method for the drawable. - */ - public override void paint_hover ( - Cairo.Context context, - Gdk.RGBA color, - double line_width, - Geometry.Rectangle target_bounds, - double scale - ) { - base.paint_hover (context, color, line_width, target_bounds, scale); - } - - public override Geometry.Rectangle generate_bounding_box () { - var r = base.generate_bounding_box (); - return r; - } - - public override void request_redraw (ViewLayers.BaseCanvas canvas, bool recalculate_bounds) { - if (recalculate_bounds) { - bounds = generate_bounding_box (); - } - else if (!is_drawn) { - // This request is to clear the old draw, but since it was never drawn, we can ignore. - return; - } - - var tb = bounds; - tb.top -= LABEL_HEIGHT / canvas.scale; - canvas.request_redraw (tb); - } - - protected double label_margin (double scale) { - return LABEL_MARGIN / scale; - } -} diff --git a/src/Drawables/DrawableEllipse.vala b/src/Drawables/DrawableEllipse.vala deleted file mode 100644 index adc5dfc7d..000000000 --- a/src/Drawables/DrawableEllipse.vala +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * Drawable for ellipses. - */ -public class Akira.Drawables.DrawableEllipse : Drawable { - public double radius_x { get; set; default = 0; } - public double radius_y { get; set; default = 0; } - - public DrawableEllipse ( - double center_x, - double center_y, - double radius_x, - double radius_y - ) { - this.center_x = center_x; - this.center_y = center_y; - this.radius_x = radius_x; - this.radius_y = radius_x; - } - - public override void simple_create_path (Cairo.Context cr) { - cr.save (); - cr.new_path (); - cr.translate (center_x, center_y); - cr.scale (radius_x, radius_y); - cr.arc (0.0, 0.0, 1.0, 0.0, 2.0 * GLib.Math.PI); - cr.restore (); - } -} diff --git a/src/Drawables/DrawableGroup.vala b/src/Drawables/DrawableGroup.vala deleted file mode 100644 index 0b6c1211c..000000000 --- a/src/Drawables/DrawableGroup.vala +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Drawable for groups. - */ -public class Akira.Drawables.DrawableGroup : Drawable { - - public DrawableGroup () {} - - public override void simple_create_path (Cairo.Context context) {} - - public override void paint (Cairo.Context context, Geometry.Rectangle target_bounds, double scale, Drawable.DrawType draw_type) {} - - /* - * Hover paint method for the drawable. - */ - public override void paint_hover ( - Cairo.Context context, - Gdk.RGBA color, - double line_width, - Geometry.Rectangle target_bounds, - double scale - ) { - context.save (); - Cairo.Matrix global_transform = context.get_matrix (); - - // We apply the item transform before creating the path. - Cairo.Matrix tr = transform; - context.transform (tr); - - context.rectangle (bounds.left, bounds.top, bounds.width, bounds.height); - - context.set_line_width (line_width / scale); - context.set_source_rgba (color.red, color.green, color.blue, color.alpha); - context.set_matrix (global_transform); - context.stroke (); - - context.restore (); - - // Very important to initialize new path. - context.new_path (); - } -} diff --git a/src/Drawables/DrawablePath.vala b/src/Drawables/DrawablePath.vala deleted file mode 100644 index 36da73a69..000000000 --- a/src/Drawables/DrawablePath.vala +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * Drawable for paths. - */ -public class Akira.Drawables.DrawablePath : Drawable { - // In the future we will probably want control points with more data. - - // This array stores the list of all points required to draw the point. - public Geometry.PathSegment[]? points = null; - // This flag tells us if the first and last point need to be joined. - public bool close; - - public DrawablePath (Geometry.PathSegment[]? points = null, bool close = false) { - if (points != null) { - this.points = points; - this.close = close; - } - } - - public override void simple_create_path (Cairo.Context cr) { - if (points == null || points.length < 2) { - return; - } - - cr.save (); - cr.translate (center_x, center_y); - cr.new_path (); - cr.move_to (points[0].line_end.x, points[0].line_end.y); - - - for (int i = 0; i < points.length; ++i) { - var point = points[i]; - if (point.type == Lib.Modes.PathEditMode.Type.LINE) { - cr.line_to (point.line_end.x, point.line_end.y); - } else if (point.type == Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT) { - var pb = points[i - 1].last_point; - var cb = point.curve_begin; - var t1 = point.tangent_1; - cr.move_to (pb.x, pb.y); - cr.curve_to (pb.x, pb.y, t1.x, t1.y, cb.x, cb.y); - } else if (point.type == Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT) { - var pb = points[i - 1].last_point; - var ce = point.curve_end; - var t2 = point.tangent_2; - cr.move_to (pb.x, pb.y); - cr.curve_to (t2.x, t2.y, ce.x, ce.y, ce.x, ce.y); - } else if (point.type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE) { - var cb = point.curve_begin; - var t1 = point.tangent_1; - var t2 = point.tangent_2; - var ce = point.curve_end; - cr.move_to (cb.x, cb.y); - cr.curve_to (t1.x, t1.y, t2.x, t2.y, ce.x, ce.y); - } else if (point.type == Lib.Modes.PathEditMode.Type.CUBIC_DOUBLE) { - var pb = points[i - 1].last_point; - var cb = point.curve_begin; - var t1 = point.tangent_1; - var t2 = point.tangent_2; - var ce = point.curve_end; - cr.curve_to (pb.x, pb.y, t1.x, t1.y, cb.x, cb.y); - cr.curve_to (cb.x, cb.y, t2.x, t2.y, ce.x, ce.y); - } - } - - if (close) { - cr.line_to (points[0].line_end.x, points[0].line_end.y); - } - - cr.restore (); - } -} diff --git a/src/Drawables/DrawableRect.vala b/src/Drawables/DrawableRect.vala deleted file mode 100644 index b875f05b0..000000000 --- a/src/Drawables/DrawableRect.vala +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * - * Parts of this code are taken from GooCanvas - */ - -/* - * Drawable for rects. - */ -public class Akira.Drawables.DrawableRect : Drawable { - public DrawableRect (double tl_x, double tl_y, double width, double height) { - this.center_x = tl_x + width / 2.0; - this.center_y = tl_y + height / 2.0; - this.width = width; - this.height = height; - } - - public override void simple_create_path (Cairo.Context context) { - rect_path (context, this); - } - - public static void rect_path (Cairo.Context context, Drawable drawable) { - if (drawable.has_radius) { - //path_impl1 (cr); - rounded_rect_path (context, drawable); - return; - } - - var w = drawable.width; - var h = drawable.height; - var x = drawable.center_x - w / 2.0; - var y = drawable.center_y - h / 2.0; - context.rectangle (x, y, w, h); - } - - public static void rounded_rect_path (Cairo.Context context, Drawable drawable) { - var w = drawable.width; - var h = drawable.height; - - // aspect_ratio yet unused - var aspect_ratio = 1.0; - double rtl = drawable.radius_tl / aspect_ratio; - double rtr = drawable.radius_tr / aspect_ratio; - double rbl = drawable.radius_bl / aspect_ratio; - double rbr = drawable.radius_br / aspect_ratio; - - double r_top = rtl + rtr; - double r_bot = rbl + rbr; - double r_right = rtr + rbr; - double r_left = rtl + rbl; - - if (r_top > 0) { - rtr = double.min (rtr, rtr / r_top * w); - rtl = double.min (rtl, rtl / r_top * w); - } - - if (r_bot > 0) { - rbr = double.min (rbr, rbr / r_bot * w); - rbl = double.min (rbl, rbl / r_bot * w); - } - - if (r_left > 0) { - rtl = double.min (rtl, rtl / r_left * h); - rbl = double.min (rbl, rbl / r_left * h); - } - - if (r_right > 0) { - rtr = double.min (rtr, rtr / r_right * h); - rbr = double.min (rbr, rbr / r_right * h); - } - - - var x = drawable.center_x - w / 2.0; - var y = drawable.center_y - h / 2.0; - var degrees = GLib.Math.PI / 180.0; - - // Add top-right - if (rtr > 0) { - context.arc (x + w - rtr, y + rtr, rtr, -90 * degrees, 0); - } else { - context.move_to (x + w, y); - } - - if (rbr > 0) { - // Add bottom-right - context.arc (x + w - rbr, y + h - rbr, rbr, 0, 90 * degrees); - } else { - context.line_to (x + w, y + h); - } - - if (rbl > 0) { - // Add bottom-left - context.arc (x + rbl, y + h - rbl, rbl, 90 * degrees, 180 * degrees); - } else { - context.line_to (x, y + h); - } - - if (rtl > 0) { - // Add top-left - context.arc (x + rtl, y + rtl, rtl, 180 * degrees, 270 * degrees); - } else { - context.line_to (x, y); - } - - context.close_path (); - } - - //public override void simple_update (Cairo.Context cr) { - // /* We can quickly compute the bounds as being just the rectangle's size - // plus half the line width around each edge. - // For now we keep it as the full width to avoid weird clipping issues*/ - // var half_line_width = get_line_width (); // / 2; - - // var x = center_x - width / 2.0; - // var y = center_y - height / 2.0; - - // bounds.left = x - half_line_width; - // bounds.top = y - half_line_width; - // bounds.right = x + width + half_line_width; - // bounds.bottom = y + height + half_line_width; - //} -} diff --git a/src/Drawables/DrawableText.vala b/src/Drawables/DrawableText.vala deleted file mode 100644 index ae5925568..000000000 --- a/src/Drawables/DrawableText.vala +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * - * Parts of this code are taken from GooCanvas - */ - -/* - * Drawable for rects. - */ -public class Akira.Drawables.DrawableText : Drawable { - - public DrawableText (double tl_x, double tl_y, double width, double height, string text) { - this.center_x = tl_x + width / 2.0; - this.center_y = tl_y + height / 2.0; - this.width = width; - this.height = height; - this.label = text; - } - - public override void simple_create_path (Cairo.Context context) { - var w = width; - var h = height; - var x = center_x - w / 2.0; - var y = center_y - h / 2.0; - - - context.rectangle (x, y, w, h); - } - - public override void paint (Cairo.Context context, Geometry.Rectangle target_bounds, double scale, Drawable.DrawType draw_type) { - // Simple bounds check - if (bounds.left > target_bounds.right || bounds.right < target_bounds.left - || bounds.top > target_bounds.bottom || bounds.bottom < target_bounds.top) { - return; - } - - context.save (); - context.transform (transform); - context.set_source_rgba (0.0, 0.0, 0.0, 1.0); - draw_text (context, scale); - context.restore (); - - context.new_path (); - - is_drawn = true; - } - - private void draw_text (Cairo.Context context, double scale) { - var m = 0;//label_margin (scale); - - var w = bounds.width - m * 2; - var h = bounds.height - m * 2; - var x = center_x - w / 2.0; - var y = center_y - h / 2.0; - - if (w <= 0 || h <= 0) { - return; - } - - Cairo.Matrix global_transform = context.get_matrix (); - var tr = transform; - context.set_matrix (tr); - - var layout = create_pango_layout (context, label, w, scale, null); - context.set_matrix (global_transform); - context.rectangle (x, y, w, h); - context.clip (); - context.move_to (x, y); - Pango.cairo_show_layout (context, layout); - } - - private static Pango.Layout create_pango_layout ( - Cairo.Context context, - string text, - double layout_width, - double scale, - double* extent_width - ) { - var layout = Pango.cairo_create_layout (context); - var pango_context = layout.get_context (); - - if (layout_width > 0) { - layout.set_width ( (int)(layout_width * Pango.SCALE)); - } - - layout.set_text (text, -1); - - // Load font description - var desc = new Pango.FontDescription (); - desc.set_family ("Open Sans"); - desc.set_size ((int) (10 * Pango.SCALE)); - layout.set_font_description (desc); - - // Load hint metrics - - var font_options = new Cairo.FontOptions (); - font_options.set_hint_metrics (Cairo.HintMetrics.DEFAULT); - Pango.cairo_context_set_font_options (pango_context, font_options); - - //layout.set_alignment (Pango.Alignment.LEFT); - //layout.set_ellipsize (Pango.EllipsizeMode.END); - layout.set_wrap (Pango.WrapMode.WORD); - return layout; - } - -} diff --git a/src/FileFormat/AkiraFile.vala b/src/FileFormat/AkiraFile.vala deleted file mode 100644 index d4b0e54ec..000000000 --- a/src/FileFormat/AkiraFile.vala +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Felipe Escoto - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.FileFormat.AkiraFile : Akira.FileFormat.ZipArchiveHandler { - public weak Akira.Window window { get; construct; } - - public File pictures_folder { get; private set; } - public File thumbnails_folder { get; private set; } - - public bool overwrite = false; - - private File content_file { get; set; } - public string path { - owned get { - return opened_file.get_parent ().get_path () + "/" + opened_file.get_basename (); - } - } - - public AkiraFile (File _gzipped_file, Akira.Window window) { - Object (opened_file: _gzipped_file.dup (), window: window); - } - - public void load_file () { - try { - open_archive (); - - var content_json = get_content_as_json (content_file); - - FileFormat.JsonDeserializer.json_object_to_world (content_json, window); - - update_recent_list.begin (); - - debug ("Version from file: %s", content_json.get_string_member ("version")); - } catch (Error e) { - error ("Could not load file: %s", e.message); - } - } - - public void save_file () { - try { - //save_images.begin (); - - var world_json = FileFormat.JsonSerializer.world_to_json_node (window); - write_content_to_file (content_file, FileFormat.JsonSerializer.json_to_string (world_json, true)); - - write_to_archive (); - update_recent_list.begin (); - } catch (Error e) { - warning ("%s\n", e.message); - } - } - - public void close () { - try { - clean (); - } catch (Error e) { - warning ("%s\n", e.message); - } - } - - public override void prepare () { - base.prepare (); - - var base_path = unarchived_location.get_path (); - pictures_folder = File.new_for_path (Path.build_filename (base_path, "Pictures")); - thumbnails_folder = File.new_for_path (Path.build_filename (base_path, "Thumbnails")); - - make_dir (pictures_folder); - make_dir (thumbnails_folder); - - content_file = File.new_for_path (Path.build_filename (base_path, "content.json")); - - make_file (content_file); - } - - /** - * Update the GSettings array of recently opened files. - */ - private async void update_recent_list () { - string[] array = {}; - // Add the last opened file always on top. - array += path; - - for (var i = 0; i <= settings.recently_opened.length; i++) { - // Skip if the record is empty. - if (settings.recently_opened[i] == null) { - continue; - } - - // If the file doesn't exist anymore, remove it from the list. - var file = File.new_for_path (settings.recently_opened[i]); - if (!file.query_exists ()) { - continue; - } - - // Don't store more than 10 files. - if (i >= 9) { - break; - } - - // If the same file was already in the list, don't save it again. - if (path == settings.recently_opened[i]) { - continue; - } - - array += settings.recently_opened[i]; - } - - settings.set_strv ("recently-opened", array); - - window.app.update_recent_files_list (); - } - - /** - * Save all the images used in the Canvas and make a copy in the Pictures folder. - */ - // public async void save_images () { - // // Clear potential leftover images if we're overwriting an existing file. - // if (overwrite) { - // try { - // Dir dir = Dir.open (pictures_folder.get_path (), 0); - // string? name = null; - // while ((name = dir.read_name ()) != null) { - // var file = File.new_for_path (Path.build_filename (pictures_folder.get_path (), name)); - // file_collector.mark_for_deletion (file); - // } - // } catch (FileError err) { - // stderr.printf (err.message); - // } - // overwrite = false; - // } - - // foreach (var image in window.items_manager.images) { - // var image_file = File.new_for_path ( - // Path.build_filename (pictures_folder.get_path (), image.manager.filename) - // ); - - // // Copy the file if it doesn't exist, or increase the reference count. - // if (!image_file.query_exists ()) { - // copy_image (image.manager.file, image_file); - // continue; - // } - // } - // } - - /** - * Decrease the reference count to an existing image, which will cause its - * deletion if the count reaches 0. - */ - public async void remove_image (string filename) { - var image_file = File.new_for_path ( - Path.build_filename (pictures_folder.get_path (), filename) - ); - - if (image_file.query_exists ()) { - file_collector.unref_file (image_file); - } - } -} diff --git a/src/FileFormat/FileManager.vala b/src/FileFormat/FileManager.vala deleted file mode 100644 index 5754d1902..000000000 --- a/src/FileFormat/FileManager.vala +++ /dev/null @@ -1,130 +0,0 @@ -/* -* Copyright (c) 2020 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.FileFormat.FileManager : Object { - public weak Akira.Window window { get; construct; } - - public FileManager (Akira.Window window) { - Object ( - window: window - ); - } - - // Save file. - public void save_file () { - // Check if we already have a file open to save or save a new one. - if (window.akira_file != null) { - window.akira_file.save_file (); - window.event_bus.file_saved (null); - return; - } - - save_file_as (); - } - - // Save as. - public void save_file_as () { - var dialog = new Gtk.FileChooserNative ( - _("Save Akira file"), window, - Gtk.FileChooserAction.SAVE, - _("Save"), - _("Cancel")); - - dialog.set_do_overwrite_confirmation (true); - add_filters (dialog); - dialog.set_modal (true); - if (window.akira_file != null) { - var file = File.new_for_path (window.akira_file.path); - try { - dialog.set_file (file); - } - catch (GLib.Error error) { - info ("%s\n", error.message); - } - } - - dialog.response.connect ((response_id) => save_file_as_response (dialog, response_id)); - dialog.show (); - } - - private void add_filters (Gtk.FileChooserNative chooser) { - Gtk.FileFilter filter = new Gtk.FileFilter (); - filter.add_pattern ("*.akira"); - filter.set_filter_name (_("Akira files")); - chooser.add_filter (filter); - - filter = new Gtk.FileFilter (); - filter.add_pattern ("*"); - filter.set_filter_name (_("All files")); - chooser.add_filter (filter); - } - - private void save_file_as_response (Gtk.FileChooserNative dialog, int response_id) { - bool overwrite = false; - - switch (response_id) { - case Gtk.ResponseType.ACCEPT: - File file; - var save_file = dialog.get_file (); - var path = save_file.get_path (); - if (path.has_suffix (".akira")) { - file = save_file; - overwrite = true; - } else { - file = File.new_for_path (path + ".akira"); - } - window.save_new_file (file, overwrite); - window.event_bus.file_saved (dialog.get_current_name ()); - break; - } - dialog.destroy (); - } - - // Open file. - public void open_file () { - var dialog = new Gtk.FileChooserNative (_("Open Akira file"), window, - Gtk.FileChooserAction.OPEN, - _("Open"), _("Cancel")); - - add_filters (dialog); - dialog.local_only = true; - dialog.select_multiple = false; - dialog.response.connect ((response_id) => open_file_response (dialog, response_id)); - dialog.show (); - } - - private void open_file_response (Gtk.FileChooserNative dialog, int response_id) { - switch (response_id) { - case Gtk.ResponseType.ACCEPT: - case Gtk.ResponseType.OK: - File[] files = {}; - files += dialog.get_file (); - window.app.open (files, ""); - info ("opened: %s\n", (dialog.get_filename ())); - break; - - case Gtk.ResponseType.CANCEL: - info ("Cancelled: FileChooserAction.OPEN\n"); - break; - } - dialog.destroy (); - } -} diff --git a/src/FileFormat/JsonDeserializer.vala b/src/FileFormat/JsonDeserializer.vala deleted file mode 100644 index e1158bae5..000000000 --- a/src/FileFormat/JsonDeserializer.vala +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2020-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.FileFormat.JsonDeserializer { - /* - * Deserialize a Json.Node and apply it to the current world state. - * This deserializes a node, which is symmetric with the output of JsonSerializer. - */ - public static void json_node_to_world (Json.Node node, Akira.Window window, bool items_only = false) { - var obj = node.get_object (); - if (obj != null) { - json_object_to_world (obj, window, items_only); - } - } - - /* - * Deserialize a Json.Node and apply it to the current world state. - */ - public static void json_object_to_world (Json.Object obj, Akira.Window window, bool items_only = false) { - var view_canvas = window.main_window.main_view_canvas.canvas; - - // Set the canvas to simulate a click + holding state to avoid triggering - // redrawing methods connected to that state. - view_canvas.holding = true; - - - if (!items_only) { - load_window_states (window, obj); - } - - deserialize_model (window.main_window.main_view_canvas.canvas, obj); - - // Reset the holding state at the end of it. - view_canvas.holding = false; - } - - /* - * Deserialize window states and apply them to the window. - */ - private static void load_window_states (Akira.Window window, Json.Object obj) { - window.event_bus.adjust_zoom (obj.get_double_member ("scale"), true, null); - window.main_window.main_view_canvas.main_scroll.hadjustment.value = obj.get_double_member ("hadjustment"); - window.main_window.main_view_canvas.main_scroll.vadjustment.value = obj.get_double_member ("vadjustment"); - } - - /* - * Deserialize the model. - */ - private static void deserialize_model (Lib.ViewCanvas view_canvas, Json.Object obj) { - var roots = obj.get_member ("roots"); - if (roots == null) { - // bad file - assert (false); - return; - } - - foreach (unowned Json.Node root in roots.get_array ().get_elements ()) { - deserialize_node (view_canvas, root.get_object (), Lib.Items.Model.ORIGIN_ID); - } - - view_canvas.items_manager.compile_model (); - } - - /* - * Deserialize a specific node, recursive. - */ - private static void deserialize_node (Lib.ViewCanvas view_canvas, Json.Object node_obj, int group_id) { - if (!node_obj.has_member ("type")) { - assert (false); - return; - } - - int new_id = -1; - var type = node_obj.get_string_member ("type"); - - var components_json = node_obj.get_member ("components"); - var components = Lib.Components.Components.deserialize (components_json); - - Lib.Items.ModelInstance? new_inst = null; - if (type == "rect") { - new_inst = new Lib.Items.ModelInstance (-1, new Lib.Items.ModelTypeRect ()); - } else if (type == "ellipse") { - new_inst = new Lib.Items.ModelInstance (-1, new Lib.Items.ModelTypeEllipse ()); - } else if (type == "group") { - new_inst = new Lib.Items.ModelInstance (-1, new Lib.Items.ModelTypeGroup ()); - } else if (type == "artboard") { - new_inst = new Lib.Items.ModelInstance (-1, new Lib.Items.ModelTypeArtboard ()); - } else if (type == "path") { - new_inst = new Lib.Items.ModelInstance (-1, new Lib.Items.ModelTypePath ()); - } else if (type == "text") { - new_inst = new Lib.Items.ModelInstance (-1, new Lib.Items.ModelTypeText ()); - } - else { - // Unknown type - assert (false); - return; - } - - new_inst.components = components; - - new_id = view_canvas.items_manager.add_item_to_group (group_id, new_inst, true); - - var children = node_obj.get_member ("children"); - if (children != null) { - foreach (unowned Json.Node child in children.get_array ().get_elements ()) { - deserialize_node (view_canvas, child.get_object (), new_id); - } - } - } -} diff --git a/src/FileFormat/JsonItemSerializer.vala b/src/FileFormat/JsonItemSerializer.vala deleted file mode 100644 index 72e19b3b1..000000000 --- a/src/FileFormat/JsonItemSerializer.vala +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Felipe Escoto - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/** - * Converts an item into a JSON Object, converting all the child attributes to string. - */ -public class Akira.FileFormat.JsonItemSerializer { - - /* - * Serialize an item and return its corresponding Json.Node. - */ - public static void serialize_node (Akira.Lib.Items.ModelNode node, ref Json.Builder builder) { - builder.begin_object (); - - // serialize type - { - builder.set_member_name ("type"); - builder.add_string_value (node.instance.type.name_id); - } - - // serialize components - node.instance.components.serialize (ref builder); - - // serialize children - if (node.instance.children != null && node.instance.children.length != 0) { - serialize_children (node, ref builder); - } - - builder.end_object (); - } - - /* - * Serialize all children of a node recursively. - */ - public static void serialize_children (Akira.Lib.Items.ModelNode node, ref Json.Builder builder) { - builder.set_member_name ("children"); - - { - builder.begin_array (); - - foreach (unowned var child in node.children.data) { - serialize_node (child, ref builder); - } - - builder.end_array (); - } - } -} diff --git a/src/FileFormat/JsonSerializer.vala b/src/FileFormat/JsonSerializer.vala deleted file mode 100644 index 72fe6a79a..000000000 --- a/src/FileFormat/JsonSerializer.vala +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2020 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.FileFormat.JsonSerializer { - - /* - * Converts the world (window, and canvas item information) to a Json.Node. - * Use this and json_to_string to save Akira's file state. - */ - public static Json.Node world_to_json_node (Akira.Window window, bool items_only = false) { - var builder = new Json.Builder (); - builder.begin_object (); - - if (!items_only) { - serialize_window_state (window, ref builder); - } - - var view_canvas = window.main_window.main_view_canvas.canvas; - - // Convert Model to JSON. - serialize_model (view_canvas.items_manager.item_model, ref builder); - - builder.end_object (); - - return builder.get_root (); - } - - /* - * Converts a Json.Node to a string - */ - public static string json_to_string (Json.Node node, bool pretty) { - var generator = new Json.Generator (); - generator.pretty = pretty; - generator.set_root (node); - return generator.to_data (null); - } - - /* - * Serialize window states to the builder. - */ - public static void serialize_window_state ( Akira.Window window, ref Json.Builder builder) { - // Save the current version of Akira. - builder.set_member_name ("version"); - builder.add_string_value (Constants.VERSION); - - // Save the current Canvas status. - builder.set_member_name ("scale"); - builder.add_double_value (window.main_window.main_view_canvas.canvas.scale); - builder.set_member_name ("hadjustment"); - builder.add_double_value (window.main_window.main_view_canvas.main_scroll.hadjustment.value); - builder.set_member_name ("vadjustment"); - builder.add_double_value (window.main_window.main_view_canvas.main_scroll.vadjustment.value); - } - - /* - * Serialize canvas artboards to the builder. - */ - public static void serialize_model (Akira.Lib.Items.Model item_model, ref Json.Builder builder) { - var origin = item_model.node_from_id (Akira.Lib.Items.Model.ORIGIN_ID); - builder.set_member_name ("roots"); - builder.begin_array (); - foreach (var root in origin.children.data) { - JsonItemSerializer.serialize_node (root, ref builder); - } - - builder.end_array (); - } -} diff --git a/src/FileFormat/ZipArchiveHandler.vala b/src/FileFormat/ZipArchiveHandler.vala deleted file mode 100644 index 56151c1f3..000000000 --- a/src/FileFormat/ZipArchiveHandler.vala +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Felipe Escoto - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.FileFormat.ZipArchiveHandler : GLib.Object { - // Prefix to be added at the beginning of the folder name when a gzipped file is opened. - // Should start with a period to hide the folder by default. - private const string UNARCHIVED_PREFIX = ".~lock.akira."; - - /** - * The GZipped File that opened this archive - */ - public File opened_file { get; construct set; } - - /** - * The Unzipped folder location - */ - public File unarchived_location { get; private set; } - - /** - * Creates a zipped file for archive purposes - */ - public ZipArchiveHandler (File gzipped_file) { - Object (opened_file: gzipped_file.dup ()); - } - - public FileCollector file_collector { get; private set; } - - construct { - var parent_folder = opened_file.get_parent ().get_path (); - unarchived_location = File.new_for_path ( - Path.build_filename (parent_folder, UNARCHIVED_PREFIX + opened_file.get_basename ())); - - file_collector = new FileCollector (unarchived_location); - } - - protected static string get_content_from_file (File file) { - try { - string data; - FileUtils.get_contents (file.get_path (), out data); - - return data; - } catch (Error e) { - warning (e.message); - return ""; - } - } - - protected static Json.Object get_content_as_json (File file) { - try { - var parser = new Json.Parser (); - parser.load_from_data (get_content_from_file (file)); - - return parser.get_root ().get_object (); - } catch (Error e) { - return new Json.Object (); - } - } - - protected static void write_content_to_file (File file, string data) { - try { - FileUtils.set_contents (file.get_path (), data); - } catch (Error e) { - warning (e.message); - } - } - - /** - * Helper function to create a directory if it does not exist - */ - protected void make_dir (File file) { - if (!file.query_exists ()) { - try { - file.make_directory_with_parents (); - } catch (Error e) { - warning ("%s\n", e.message); - } - } - } - - /** - * Helper function to create a file if it does not exist - */ - protected void make_file (File file) { - if (!file.query_exists ()) { - try { - file.create (FileCreateFlags.REPLACE_DESTINATION); - } catch (Error e) { - warning ("%s\n", e.message); - } - } - } - - /** - * Used to create all the files needed for this if they do not exist. - * - * Can be overwritten to add your own files and folders for the internal - * file structure you require. If overwritten, make sure to call base.prepare () - */ - public virtual void prepare () { - var parent_folder = opened_file.get_parent (); - make_dir (parent_folder); - make_file (opened_file); - make_dir (unarchived_location); - } - - /** - * Used to check if the file was already extracted. Use this to handle recovery for your users. - */ - protected virtual bool is_opened () { - return unarchived_location.query_exists (); - } - - /** - * Extracts the contents of the file to unarchived_location - */ - protected void open_archive () throws Error { - extract (opened_file, unarchived_location); - } - - /** - * Saves content from the unzipped location to the GZipped file. - */ - protected void write_to_archive () throws Error { - // Clear files marked before archiving anything - file_collector.delete_files_marked_for_deletion (); - - // Saving to a temp file first to avoid dataloss on a crash - var tmp_file = File.new_for_path (opened_file.get_path () + ".tmp"); - - compress (unarchived_location, tmp_file); - if (opened_file.query_exists ()) { - opened_file.delete (); - } - - FileUtils.rename (tmp_file.get_path (), opened_file.get_path ()); - } - - /** - * Removes all files from the unarchived location. Should run before closing the program to cleanup temp files - */ - protected void clean () throws Error { - // Checking if it contains the prefix as a safety to prevent errors - if (is_opened () && unarchived_location.get_path ().contains (UNARCHIVED_PREFIX)) { - delete_recursive (unarchived_location); - unarchived_location.delete (); - } - } - - public File get_file_from_basename (File location, string basename) { - var path = Path.build_filename (location.get_path (), basename); - return File.new_for_path (path); - } - - /** - * Gets a random file inside the archive at the location specified - * using a guid-like name. - * - * @param location - Location inside of the archive where the file will live at. - * @param extension - The extension the file created will have. - * @param format - The format for the file. The character "?" will be replaced - * with a random character. For example, XXXX-XX can become a5b7-Df. - * The default is "XXXXXXXX-XXXX-XX". - */ - public File get_random_file_name (File location, string extension, string format = "XXXXXXXX-XXXX-XX") { - do { - var path = Path.build_filename (location.get_path (), get_guid (format) + "." + extension); - - var file = File.new_for_path (path); - if (!file.query_exists ()) { - return file; - } - } while (true); - } - - private Rand? rand = new Rand (); - private const string GUID_CHARS = "0123456789ABCDEFabcdef"; - - private string get_guid (string format) { - var guid = new StringBuilder.sized (format.length); - int format_length = format.length; - - for (int i = 0; i < format_length; i++) { - switch (format[i]) { - case 'X': - var r = rand.next_int () % GUID_CHARS.length; - guid.append_c (GUID_CHARS[r]); - break; - default: - guid.append_c (format[i]); - break; - } - } - - return guid.str; - } - - // DANGEROUS, use with caution - private void delete_recursive (File file) { - try { - var enumerator = file.enumerate_children (FileAttribute.STANDARD_NAME, 0); - - FileInfo file_info; - while ((file_info = enumerator.next_file ()) != null) { - var current_file = file.resolve_relative_path (file_info.get_name ()); - - if (file_info.get_file_type () == FileType.DIRECTORY) { - delete_recursive (current_file); - } - - current_file.delete (); - } - } catch (Error e) { - critical ("Error: %s\n", e.message); - } - } - - // Extracts all contents of the gzip file to the location - private static void extract (File gzipped_file, File location) throws Error { - Archive.ExtractFlags flags; - flags = Archive.ExtractFlags.TIME; - flags |= Archive.ExtractFlags.PERM; - flags |= Archive.ExtractFlags.ACL; - flags |= Archive.ExtractFlags.FFLAGS; - - Archive.Read archive = new Archive.Read (); - archive.support_format_all (); - archive.support_filter_all (); - - Archive.WriteDisk extractor = new Archive.WriteDisk (); - extractor.set_options (flags); - extractor.set_standard_lookup (); - - if (archive.open_filename (gzipped_file.get_path (), 10240) != Archive.Result.OK) { - throw new FileError.FAILED ( - "Error opening %s: %s (%d)", gzipped_file.get_path (), archive.error_string (), archive.errno () - ); - } - - unowned Archive.Entry entry; - Archive.Result last_result; - - while ((last_result = archive.next_header (out entry)) == Archive.Result.OK) { - entry.set_perm (0644); - entry.set_pathname (Path.build_filename (location.get_path (), entry.pathname ())); - - if (extractor.write_header (entry) != Archive.Result.OK) { - continue; - } - - Posix.off_t offset; - uint8[] buffer; - while (archive.read_data_block (out buffer, out offset) == Archive.Result.OK) { - if (extractor.write_data_block (buffer, offset) != Archive.Result.OK) { - break; - } - } - } - - if (last_result != Archive.Result.EOF) { - critical ("Error: %s (%d)", archive.error_string (), archive.errno ()); - } - } - - // Compresses all files recursibly from location to the gzipped file. - private static void compress (File location, File gzipped_file) throws Error { - var to_write = File.new_for_path (gzipped_file.get_path ()); - if (to_write.query_exists ()) { - to_write.delete (); - } - - to_write.create (FileCreateFlags.REPLACE_DESTINATION); - - Archive.Write archive = new Archive.Write (); - archive.set_format_zip (); - archive.open_filename (to_write.get_path ()); - - add_to_archive_recursive (location, location, archive); - - if (archive.close () != Archive.Result.OK) { - critical ("Error : %s (%d)", archive.error_string (), archive.errno ()); - } - } - - private static void add_to_archive_recursive (File initial_folder, File folder, Archive.Write archive) { - try { - var enumerator = folder.enumerate_children (FileAttribute.STANDARD_NAME, 0); - - FileInfo current_info; - while ((current_info = enumerator.next_file ()) != null) { - var current_file = folder.resolve_relative_path (current_info.get_name ()); - - if (current_info.get_file_type () == FileType.DIRECTORY) { - add_to_archive_recursive (initial_folder, current_file, archive); - } else { - GLib.FileInfo file_info = current_file.query_info (GLib.FileAttribute.STANDARD_SIZE, - GLib.FileQueryInfoFlags.NONE); - - FileInputStream input_stream = current_file.read (); - DataInputStream data_input_stream = new DataInputStream (input_stream); - - // Add an entry to the archive - Archive.Entry entry = new Archive.Entry (); - entry.set_pathname (initial_folder.get_relative_path (current_file)); - entry.set_size ((Archive.int64_t) file_info.get_size ()); - entry.set_filetype (Archive.FileType.IFREG); - entry.set_perm (0644); - - if (archive.write_header (entry) != Archive.Result.OK) { - critical ( - "Error writing '%s': %s (%d)", - current_file.get_path (), - archive.error_string (), - archive.errno () - ); - return; - } - - // Add the actual content of the file - size_t bytes_read; - uint8[] buffer = new uint8[64]; - while (data_input_stream.read_all (buffer, out bytes_read)) { - if (bytes_read <= 0) { - break; - } - - archive.write_data (buffer[0:bytes_read]); - } - } - } - } catch (Error e) { - critical ("Error: %s\n", e.message); - } - } - - public virtual void copy_image (GLib.File old_file, GLib.File new_file) { - try { - old_file.copy (new_file, 0, null, (current_num_bytes, total_num_bytes) => { - // Report copy-status: - print ("%" + int64.FORMAT + " bytes of %" + int64.FORMAT + " bytes copied.\n", - current_num_bytes, total_num_bytes); - }); - file_collector.ref_file (new_file); - } catch (Error e) { - print ("Error: %s\n", e.message); - } - } - - - /** - * Takes care of the reference counting for files inside the archive. - * This allows to multiple objects to reference the same file, and only - * mark the file for deletion if no other object is using it. - */ - protected class FileCollector { - private unowned File unarchived_location; - private Gee.HashMap for_deletion; - private Gee.HashMap ref_counter; - - public FileCollector (File _unarchived_location) { - unarchived_location = _unarchived_location; - - for_deletion = new Gee.HashMap (); - ref_counter = new Gee.HashMap (); - } - - /** - * Gets the number of times a file is being used - */ - public int file_references (File file) { - var file_basename = file.get_basename (); - return ref_counter.has_key (file_basename) ? ref_counter.get (file_basename) : 0; - } - - /** - * Adds 1 to the ref counter for that file. - */ - public void ref_file (File file) { - var file_basename = file.get_basename (); - if (for_deletion.has_key (file_basename)) { - unmark_for_deletion (file); - } - - var ref_count = file_references (file); - ref_counter.set (file_basename, ref_count + 1); - print ("File ref %d %s \n", ref_count + 1, file.get_basename ()); - } - - /** - * Subtracts 1 on the ref counter for that file. If set to 0, the file will be marked for deletion - */ - public void unref_file (File file) { - var file_basename = file.get_basename (); - - var ref_count = file_references (file); - if (ref_count > 0) { - ref_counter.set (file_basename, ref_count - 1); - - if (ref_count == 1) { - mark_for_deletion (file); - } - print ("File unref %d %s \n", ref_count - 1, file.get_basename ()); - } - } - - /** - * Marks a file to be deleted and not saved to the archive. Said files will be deleted - * when write_to_archive runs or when you manually call "delete_files_marked_for_deletion". - * - * Files will only be added to the list when they are inside the unarchived location - */ - public void mark_for_deletion (File file) { - if (file.get_path ().contains (unarchived_location.get_path ())) { - for_deletion.set (file.get_basename (), file); - print ("Marked for deletion: %s\n", file.get_basename ()); - } - } - - /** - * Unmarks a file previously marked for deletion. - */ - public void unmark_for_deletion (File file) { - for_deletion.unset (file.get_basename ()); - print ("unmarked for deletion: %s\n", file.get_basename ()); - } - - /** - * Deletes all files whose ref counter is set to 0, or those marked for deletion - */ - public void delete_files_marked_for_deletion () { - foreach (var file in for_deletion.values) { - try { - file.delete (); - } catch (Error e) { - warning ("File could not be deleted %s\n", e.message); - } - }; - - for_deletion.clear (); - } - } -} diff --git a/src/Geometry/PathSegment.vala b/src/Geometry/PathSegment.vala deleted file mode 100644 index 87767b854..000000000 --- a/src/Geometry/PathSegment.vala +++ /dev/null @@ -1,359 +0,0 @@ -/** - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Ashish Shevale -*/ - -/* - * Following is a generic structure used for storing all types of segments - * in a path. - * type : refers to the type of segment. - * curve_begin : first point of a curve or end point of line. - * tangent_1, tangent_2 : control points for controlling curves. - * curve_end : last point of a curve - * - * We can create a different types of segments using this rep as - * 1. Symmetric Bezier Curve (both control points are equi-distant from curve_begin) - * 2. Asymmetric Bezier Curve (control points can be at different distances from curve_begin) - * 3. Quadratic Curve (single control point) => Left handed and right handed - * 4. Line (pretty obvious) - * 5. Single Segment bezier curve. - */ -public struct Akira.Geometry.PathSegment { - public Lib.Modes.PathEditMode.Type type; - - // This point is used for drawing lines. - // Store point in segment_begin to save space, but use the alias to make code readable. - public Geometry.Point line_end { - get { - return curve_begin; - } - set { - curve_begin = value; - } - } - - public Geometry.Point last_point { - get { - if (type == Lib.Modes.PathEditMode.Type.LINE) { - return line_end; - } else if (type == Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT) { - return curve_begin; - } - - return curve_end; - } - } - - // These points are used for drawing curves. - public Geometry.Point curve_begin; - public Geometry.Point tangent_1; - public Geometry.Point tangent_2; - public Geometry.Point curve_end; - - // Creates new line segment. - public PathSegment.line (Geometry.Point point) { - type = Lib.Modes.PathEditMode.Type.LINE; - line_end = point; - - // Initializing the remaining unused points allows us to - // transform the whole segment without worrying its type. - tangent_1 = Geometry.Point (0, 0); - tangent_2 = Geometry.Point (0, 0); - curve_end = Geometry.Point (0, 0); - } - - // Creates new cubic bezier curve. - public PathSegment.cubic_bezier ( - Geometry.Point curve_begin, - Geometry.Point control_point_1, - Geometry.Point control_point_2, - Geometry.Point curve_end - ) { - type = Lib.Modes.PathEditMode.Type.CUBIC_DOUBLE; - - this.curve_begin = curve_begin; - this.tangent_1 = control_point_1; - this.tangent_2 = control_point_2; - this.curve_end = curve_end; - } - - public PathSegment.cubic_bezier_single ( - Geometry.Point curve_begin, - Geometry.Point control_point_1, - Geometry.Point control_point_2, - Geometry.Point curve_end - ) { - type = Lib.Modes.PathEditMode.Type.CUBIC_SINGLE; - - this.curve_begin = curve_begin; - this.tangent_1 = control_point_1; - this.tangent_2 = control_point_2; - this.curve_end = curve_end; - } - - // Creates new quadratic bezier curve - public PathSegment.quadratic_bezier_left ( - Geometry.Point curve_begin, - Geometry.Point control_point - ) { - type = Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT; - - this.curve_begin = curve_begin; - this.tangent_1 = control_point; - - tangent_2 = Geometry.Point (0, 0); - curve_end = Geometry.Point (0, 0); - } - - public PathSegment.quadratic_bezier_right ( - Geometry.Point curve_end, - Geometry.Point control_point - ) { - type = Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT; - - this.curve_end = curve_end; - this.tangent_2 = control_point; - - tangent_1 = Geometry.Point (0, 0); - curve_begin = Geometry.Point (0, 0); - } - - public PathSegment copy () { - var segment = PathSegment (); - - segment.type = type; - segment.curve_begin = curve_begin; - segment.tangent_1 = tangent_1; - segment.tangent_2 = tangent_2; - segment.curve_end = curve_end; - - return segment; - } - - // Use for converting a line segment to a curve. - // point_before and point_after are used for calculating positions of control points. - // If point_after is not provided, create a quadratic curve - // If it is provided, create a symmetric cubic_DOUBLE bezier curve - public void line_to_curve ( - PathSegment? segment_before, - PathSegment? segment_after - ) { - // Atleast one of the segments must be present inorder to calculate tangents. - assert (segment_before != null && segment_after != null); - - // When converting to quadratic curves, this is the dist. at which tangents are placed. - double tangent_length = 100; - type = Lib.Modes.PathEditMode.Type.CUBIC_DOUBLE; - - // If we are converting the first point of the segment, - // Make it a quadratic curve. Never occurs, but kept as safeguard. - if (segment_before == null) { - type = Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT; - tangent_1 = Geometry.Point (curve_begin.x - tangent_length, curve_begin.y - tangent_length); - - return; - } - - // If last segment is being converted to curve, make it quadratic. - if (segment_after == null) { - type = Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT; - tangent_1 = Geometry.Point (curve_begin.x + tangent_length, curve_begin.y + tangent_length); - - return; - } - - // For all other segments, we need to find position for tangents. - // Following will create tangents that are parallel to CURVE_BEGIN and CURVE_END - // to make result more appealing. - Geometry.Point point_before, point_after; - - if (segment_before.type == Lib.Modes.PathEditMode.Type.LINE) { - point_before = segment_before.line_end; - } else { - point_before = Geometry.Point ( - (curve_begin.x + segment_before.curve_begin.x) / 2.0, - (curve_begin.y + segment_before.curve_begin.y) / 2.0 - ); - } - - if (segment_after.type == Lib.Modes.PathEditMode.Type.LINE) { - point_after = segment_after.line_end; - } else { - point_after = Geometry.Point ( - (curve_begin.x + segment_after.curve_begin.x) / 2.0, - (curve_begin.y + segment_after.curve_begin.y) / 2.0 - ); - } - - var mid_vector = Geometry.Point ( - (point_after.x - point_before.x) / 2.0, - (point_after.y - point_before.y) / 2.0 - ); - - tangent_1 = Geometry.Point (curve_begin.x - mid_vector.x, curve_begin.y - mid_vector.y); - tangent_2 = Geometry.Point (curve_begin.x + mid_vector.x, curve_begin.y + mid_vector.y); - curve_end = point_after; - } - - // Use for converting a curve segment to a line. - public void curve_to_line () { - type = Lib.Modes.PathEditMode.Type.LINE; - } - - public Geometry.Point get_by_type (Lib.Modes.PathEditMode.PointType ptype) { - if (ptype == Lib.Modes.PathEditMode.PointType.LINE_END) { - return line_end; - } - - if (ptype == Lib.Modes.PathEditMode.PointType.CURVE_BEGIN) { - return curve_begin; - } - - if (ptype == Lib.Modes.PathEditMode.PointType.TANGENT_FIRST) { - return tangent_1; - } - - if (ptype == Lib.Modes.PathEditMode.PointType.TANGENT_SECOND) { - return tangent_2; - } - - if (ptype == Lib.Modes.PathEditMode.PointType.CURVE_END) { - return curve_end; - } - - assert (false); - return Geometry.Point (0, 0); - } - - public Lib.Modes.PathEditMode.PointType hit_test (Geometry.Point point, double thresh) { - if (type == Lib.Modes.PathEditMode.Type.LINE) { - if (Utils.GeometryMath.compare_points (line_end, point, thresh)) { - return Lib.Modes.PathEditMode.PointType.LINE_END; - } - } else if (type == Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT) { - if (Utils.GeometryMath.compare_points (curve_begin, point, thresh)) { - return Lib.Modes.PathEditMode.PointType.CURVE_BEGIN; - } - - if (Utils.GeometryMath.compare_points (tangent_1, point, thresh)) { - return Lib.Modes.PathEditMode.PointType.TANGENT_FIRST; - } - } else if (type == Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT) { - if (Utils.GeometryMath.compare_points (curve_end, point, thresh)) { - return Lib.Modes.PathEditMode.PointType.CURVE_END; - } - - if (Utils.GeometryMath.compare_points (tangent_2, point, thresh)) { - return Lib.Modes.PathEditMode.PointType.TANGENT_SECOND; - } - } else if ( - type == Lib.Modes.PathEditMode.Type.CUBIC_DOUBLE || - type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE - ) { - if (Utils.GeometryMath.compare_points (curve_begin, point, thresh)) { - return Lib.Modes.PathEditMode.PointType.CURVE_BEGIN; - } - - if (Utils.GeometryMath.compare_points (tangent_1, point, thresh)) { - return Lib.Modes.PathEditMode.PointType.TANGENT_FIRST; - } - - if (Utils.GeometryMath.compare_points (tangent_2, point, thresh)) { - return Lib.Modes.PathEditMode.PointType.TANGENT_SECOND; - } - - if (Utils.GeometryMath.compare_points (curve_end, point, thresh)) { - return Lib.Modes.PathEditMode.PointType.CURVE_END; - } - } - - return Lib.Modes.PathEditMode.PointType.NONE; - } - - public bool check_tangents_inline () { - var tangent_mid_x = (tangent_1.x + tangent_2.x) / 2.0; - var tangent_mid_y = (tangent_1.y + tangent_2.y) / 2.0; - - double err_x = (tangent_mid_x - curve_begin.x).abs (); - double err_y = (tangent_mid_y - curve_begin.y).abs (); - - if (err_x <= double.EPSILON && err_y <= double.EPSILON) { - return true; - } - - return false; - } - - public void translate (double dx, double dy) { - curve_begin = Geometry.Point (curve_begin.x - dx, curve_begin.y - dy); - tangent_1 = Geometry.Point (tangent_1.x - dx, tangent_1.y - dy); - tangent_2 = Geometry.Point (tangent_2.x - dx, tangent_2.y - dy); - curve_end = Geometry.Point (curve_end.x - dx, curve_end.y - dy); - } - - public void transform (Cairo.Matrix transform, bool invert = false) { - curve_begin = Utils.GeometryMath.transform_point_around_item_origin (curve_begin, transform, invert); - tangent_1 = Utils.GeometryMath.transform_point_around_item_origin (tangent_1, transform, invert); - tangent_2 = Utils.GeometryMath.transform_point_around_item_origin (tangent_2, transform, invert); - curve_end = Utils.GeometryMath.transform_point_around_item_origin (curve_end, transform, invert); - } - - public void move_tangents (double delta_x, double delta_y, bool is_tan1_reference) { - if (is_tan1_reference) { - tangent_1.x -= delta_x; - tangent_1.y -= delta_y; - - tangent_2.x += delta_x; - tangent_2.y += delta_y; - } else { - tangent_1.x += delta_x; - tangent_1.y += delta_y; - - tangent_2.x -= delta_x; - tangent_2.y -= delta_y; - } - } - - public void snap_points () { - curve_begin = Geometry.Point (Math.round (curve_begin.x), Math.round (curve_begin.y)); - tangent_1 = Geometry.Point (Math.round (tangent_1.x), Math.round (tangent_1.y)); - tangent_2 = Geometry.Point (Math.round (tangent_2.x), Math.round (tangent_2.y)); - curve_end = Geometry.Point (Math.round (curve_end.x), Math.round (curve_end.y)); - } - - - public PathSegment.deserialized (Json.Object obj) { - // TODO: - } - - public Json.Node PathSegment.serialize () { - var node = new Json.Node (Json.NodeType.OBJECT); - return node; - } -} - -public struct Akira.Geometry.SelectedPoint { - public int sel_index; - public Lib.Modes.PathEditMode.PointType sel_type; - public bool tangents_staggered; - - public SelectedPoint () { - tangents_staggered = false; - } -} diff --git a/src/Geometry/Point.vala b/src/Geometry/Point.vala deleted file mode 100644 index 6d5766b64..000000000 --- a/src/Geometry/Point.vala +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - - /* - * Simple 2d point. - */ -public struct Akira.Geometry.Point { - public double x; - public double y; - - public Point (double x = 0, double y = 0) { - this.x = x; - this.y = y; - } - - public Point.deserialized (Json.Object obj) { - x = obj.get_double_member ("x"); - y = obj.get_double_member ("y"); - } - - public Json.Node serialize () { - var obj = new Json.Object (); - obj.set_double_member ("x", x); - obj.set_double_member ("y", y); - var node = new Json.Node (Json.NodeType.OBJECT); - node.set_object (obj); - return node; - } -} diff --git a/src/Geometry/Quad.vala b/src/Geometry/Quad.vala deleted file mode 100644 index 18bee6e70..000000000 --- a/src/Geometry/Quad.vala +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - - /* - * Naive rotated rectangle meant for convenience. This struct does not guarantee - * that the properties of a rectangle are kept. For all intents and purposes, this - * is simply a collection of four points and a rotation. - */ -public struct Akira.Geometry.Quad { - public Cairo.Matrix transformation; - public double tl_x; - public double tl_y; - public double tr_x; - public double tr_y; - public double bl_x; - public double bl_y; - public double br_x; - public double br_y; - - public double center_x { get { return (tl_x + tr_x + bl_x + br_x) / 4.0; } } - public double center_y { get { return (tl_y + tr_y + bl_y + br_y) / 4.0; } } - - public double width { get { return Utils.GeometryMath.distance (tl_x, tl_y, tr_x, tr_y).abs (); } } - public double height { get { return Utils.GeometryMath.distance (tl_x, tl_y, bl_x, bl_y).abs (); } } - - public void top_bottom (ref double top, ref double bottom) { - Utils.GeometryMath.min_max_coords (tl_y, tr_y, bl_y, br_y, ref top, ref bottom); - } - - public void left_right (ref double left, ref double right) { - Utils.GeometryMath.min_max_coords (tl_x, tr_x, bl_x, br_x, ref left, ref right); - } - - public Rectangle bounding_box { - get { - double min_x = 0; - double max_x = 0; - Utils.GeometryMath.min_max_coords (tl_x, tr_x, bl_x, br_x, ref min_x, ref max_x); - - double min_y = 0; - double max_y = 0; - Utils.GeometryMath.min_max_coords (tl_y, tr_y, bl_y, br_y, ref min_y, ref max_y); - - return Rectangle .with_coordinates (min_x, min_y, max_x, max_y); - } - } - - - public Quad () { - transformation = Cairo.Matrix.identity (); - tl_x = 0; - tl_y = 0; - tr_x = 0; - tr_y = 0; - bl_x = 0; - bl_y = 0; - br_x = 0; - br_y = 0; - } - - public Quad.from_rectangle (Geometry.Rectangle rect) { - transformation = Cairo.Matrix.identity (); - tl_x = rect.left; - tl_y = rect.top; - tr_x = rect.right; - tr_y = rect.top; - bl_x = rect.left; - bl_y = rect.bottom; - br_x = rect.right; - br_y = rect.bottom; - } - - public Quad.from_components ( - double center_x, - double center_y, - double width, - double height, - Cairo.Matrix transform - ) { - transformation = transform; - - var hw = width / 2.0; - var hh = height / 2.0; - - tl_x = - hw; - tl_y = - hh; - br_x = hw; - br_y = hh; - - var woffx = width; - var woffy = 0.0; - transform.transform_distance (ref tl_x, ref tl_y); - transform.transform_distance (ref br_x, ref br_y); - transform.transform_distance (ref woffx, ref woffy); - - tl_x = center_x + tl_x; - tl_y = center_y + tl_y; - - tr_x = tl_x + woffx; - tr_y = tl_y + woffy; - - br_x = center_x + br_x; - br_y = center_y + br_y; - bl_x = br_x - woffx; - bl_y = br_y - woffy; - - transform.x0 = center_x - hw; - transform.y0 = center_y - hh; - } - - public bool contains (double x, double y) { - if (!bounding_box.contains (x, y)) { - return false; - } - - return Utils.GeometryMath.points_on_same_side_of_line (tl_x, tl_y, tr_x, tr_y, br_x, br_y, x, y) - && Utils.GeometryMath.points_on_same_side_of_line (tr_x, tr_y, br_x, br_y, bl_x, bl_y, x, y) - && Utils.GeometryMath.points_on_same_side_of_line (br_x, br_y, bl_x, bl_y, tl_x, tl_y, x, y) - && Utils.GeometryMath.points_on_same_side_of_line (bl_x, bl_y, tl_x, tl_y, tr_x, tr_y, x, y); - } - - public void translate (double dx, double dy) { - tl_x += dx; - tr_x += dx; - bl_x += dx; - br_x += dx; - - tl_y += dy; - tr_y += dy; - bl_y += dy; - br_y += dy; - } - - public void transform (Cairo.Matrix matrix) { - transformation = matrix; - matrix.transform_point (ref tl_x, ref tl_y); - matrix.transform_point (ref tr_x, ref tr_y); - matrix.transform_point (ref bl_x, ref bl_y); - matrix.transform_point (ref br_x, ref br_y); - } - - public string to_string () { - return "tl: %f %f tr: %f %f br: %f %f bl: %f %f".printf ( - tl_x, - tl_y, - tr_x, - tr_y, - br_x, - br_y, - bl_x, - bl_y - ); - } -} diff --git a/src/Geometry/Rectangle.vala b/src/Geometry/Rectangle.vala deleted file mode 100644 index 8452163e0..000000000 --- a/src/Geometry/Rectangle.vala +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - - /* - * Naive rectangle. It does not guarantee relative positions of left/right, top/left - * unless the `with_coordinates` constructor is used. - */ -public struct Akira.Geometry.Rectangle { - public double top; - public double left; - public double bottom; - public double right; - - public double center_x { get { return (left + right) / 2.0; } } - public double center_y { get { return (bottom + top) / 2.0; } } - public double width { get { return (right - left).abs (); } } - public double height { get { return (bottom - top).abs (); } } - - public Rectangle.empty () { - top = 0; - bottom = 0; - left = 0; - right = 0; - } - - public Rectangle.with_coordinates (double x0, double y0, double x1, double y1) { - if (x0 < x1) { - left = x0; - right = x1; - } else { - right = x0; - left = x1; - } - - if (y0 < y1) { - top = y0; - bottom = y1; - } else { - bottom = y0; - top = y1; - } - } - - public bool contains (double x, double y) { - return (left < x < right) && (top < y < bottom); - } - - public bool contains_bound (Geometry.Rectangle bound) { - return (left <= bound.left) && (top <= bound.top) && (right >= bound.right) && (bottom >= bound.bottom); - } - - public bool does_not_contain (double x, double y) { - return x < left || x > right || y < top || y > bottom; - } - - public void translate (double dx, double dy) { - left += dx; - right += dx; - top += dy; - bottom += dy; - } - - public string to_string () { - return "t: %f l: %f b: %f r: %f".printf (top, left, bottom , right); - } -} diff --git a/src/Geometry/TransformedRectangle.vala b/src/Geometry/TransformedRectangle.vala deleted file mode 100644 index 444884ccf..000000000 --- a/src/Geometry/TransformedRectangle.vala +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - - /* - * Consists of an original rectangle, and a matrix to transform it to the - * world coordinates. - */ - public struct Akira.Geometry.TransformedRectangle { - public Rectangle rect; - public Cairo.Matrix matrix; - - public TransformedRectangle () {} - - public TransformedRectangle.with_geometry (Rectangle rectangle, Cairo.Matrix matrix) { - rect = rectangle; - this.matrix = matrix; - } - - public TransformedRectangle.empty () { - rect = Rectangle.empty (); - this.matrix = Cairo.Matrix.identity (); - } - - public Quad quad () { - var quad = Quad.from_rectangle (rect); - quad.transform (matrix); - return quad; - } - - /* - * Maps x, y from the world coordinates to the rect - * coordinates. - */ - public void map_to_local (ref double x, ref double y) { - var inv = matrix; - inv.invert (); - inv.transform_point (ref x, ref y); - } - - /* - * Map x, y from the rect coordinates to the world coordinates. - */ - public void map_from_local (ref double x, ref double y) { - matrix.transform_point (ref x, ref y); - } - - /* - * Returns true if the transformed rectangle contains the x, y position - * in the world coordinates defined by the `matrix` mapping - */ - public bool contains (double x, double y) { - map_to_local (ref x, ref y); - return rect.contains (x, y); - } -} diff --git a/src/Layouts/Alignment/AlignmentPanel.vala b/src/Layouts/Alignment/AlignmentPanel.vala deleted file mode 100644 index 781fa746d..000000000 --- a/src/Layouts/Alignment/AlignmentPanel.vala +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2019-2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Giacomo "giacomoalbe" Alberini - * Alessandro "Alecaddd" Castellani - */ -public class Akira.Layouts.Alignment.AlignmentPanel : Gtk.Grid { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - private Gee.ArrayList buttons; - private int grid_column { get; set; default = 0; } - - private struct AlignBoxItem { - public string type; - public Utils.ItemAlignment.AlignmentDirection? alignment_direction; - public string? icon_name; - public string? tooltip_text; - public string[]? accels; - - public AlignBoxItem ( - string type, - Utils.ItemAlignment.AlignmentDirection? alignment_direction = null, - string? icon_name = null, - string? tooltip_text = null, - string[]? accels = null) { - this.type = type; - this.alignment_direction = alignment_direction; - this.icon_name = icon_name; - this.tooltip_text = tooltip_text; - this.accels = accels; - } - } - - private AlignBoxItem[] align_items_buttons = { - //AlignBoxItem ("btn", Utils.ItemAlignment.AlignmentDirection.HEVEN, "distribute-horizontal-center", _("Distribute Horizontally"), {"1"}), - //AlignBoxItem ("btn", Utils.ItemAlignment.AlignemtDirection.VEVEN, "distribute-vertical-center", _("Distribute Vertically"), {"2"}), - //AlignBoxItem ("sep"), - AlignBoxItem ("btn", Utils.ItemAlignment.AlignmentDirection.LEFT, "align-horizontal-left", _("Align Left"), {"1"}), - AlignBoxItem ("btn", Utils.ItemAlignment.AlignmentDirection.HCENTER, "align-horizontal-center", _("Align Center"), {"2"}), - AlignBoxItem ("btn", Utils.ItemAlignment.AlignmentDirection.RIGHT, "align-horizontal-right", _("Align Right"), {"3"}), - AlignBoxItem ("sep"), - AlignBoxItem ("btn", Utils.ItemAlignment.AlignmentDirection.TOP, "align-vertical-top", _("Align Top"), {"4"}), - AlignBoxItem ("btn", Utils.ItemAlignment.AlignmentDirection.VCENTER, "align-vertical-center", _("Align Middle"), {"5"}), - AlignBoxItem ("btn", Utils.ItemAlignment.AlignmentDirection.BOTTOM, "align-vertical-bottom", _("Align Bottom"), {"6"}) - }; - - public AlignmentPanel (Lib.ViewCanvas view_canvas) { - Object (view_canvas: view_canvas); - } - - construct { - get_style_context ().add_class ("alignment-panel"); - column_homogeneous = true; - hexpand = true; - buttons = new Gee.ArrayList (); - - foreach (var item in align_items_buttons) { - switch (item.type) { - case "sep": - var separator = new Gtk.Separator (Gtk.Orientation.VERTICAL) { - halign = Gtk.Align.CENTER, - margin_top = margin_bottom = 4 - }; - - attach (separator, grid_column++, 0, 1, 1); - break; - - case "btn": - var button = new Gtk.Button () { - halign = valign = Gtk.Align.CENTER, - can_focus = false, - sensitive = false, - tooltip_markup = Granite.markup_accel_tooltip (item.accels, item.tooltip_text) - }; - button.add (new Widgets.ButtonImage (item.icon_name, Gtk.IconSize.SMALL_TOOLBAR)); - button.clicked.connect (() => { - view_canvas.window.event_bus.selection_align (item.alignment_direction); - }); - button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - button.get_style_context ().add_class ("button-rounded"); - - attach (button, grid_column++, 0, 1, 1); - buttons.add (button); - break; - } - } - - view_canvas.window.event_bus.selection_modified.connect (on_selection_modified); - } - - private void on_selection_modified () { - unowned var sm = view_canvas.selection_manager; - bool is_sensitive = sm.count () > 1; - foreach (var button in buttons) { - button.sensitive = is_sensitive; - } - } -} diff --git a/src/Layouts/BordersList/BorderItemModel.vala b/src/Layouts/BordersList/BorderItemModel.vala deleted file mode 100644 index 5a45d3cd4..000000000 --- a/src/Layouts/BordersList/BorderItemModel.vala +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Simple Object to be handled by the BordersListBoxModel and to give easy access - * the border component of the Lib.Items.ModelNode. - */ -public class Akira.Layouts.BordersList.BorderItemModel : Models.ColorModel { - private unowned Lib.ViewCanvas _view_canvas; - - private Lib.Items.ModelInstance _cached_instance; - - public int border_id; - - public override void on_value_changed () { - if (block_signal > 0) { - return; - } - - unowned var im = _view_canvas.items_manager; - var node = im.item_model.node_from_id (_cached_instance.id); - assert (node != null); - - var new_color = Lib.Components.Color.from_rgba (color, hidden); - var new_borders = node.instance.components.borders.copy (); - new_borders.replace (Lib.Components.Borders.Border (border_id, new_color)); - node.instance.components.borders = new_borders; - - im.item_model.alert_node_changed (node, Lib.Components.Component.Type.COMPILED_BORDER); - im.compile_model (); - } - - public override void delete () { - unowned var im = _view_canvas.items_manager; - var node = im.item_model.node_from_id (_cached_instance.id); - assert (node != null); - - var new_borders = node.instance.components.borders.copy (); - new_borders.remove (border_id); - node.instance.components.borders = new_borders; - - im.item_model.alert_node_changed (node, Lib.Components.Component.Type.COMPILED_BORDER); - im.compile_model (); - } - - public BorderItemModel (Lib.ViewCanvas view_canvas, Lib.Items.ModelNode node, int border_id) { - update_node (node, border_id); - _view_canvas = view_canvas; - } - - private void update_node (Lib.Items.ModelNode new_node, int border_id) { - _cached_instance = new_node.instance; - this.border_id = border_id; - - var blocker = new SignalBlocker (this); - (blocker); - - var border = _cached_instance.components.borders.border_from_id (border_id); - color = border.color; - hidden = border.hidden; - } -} diff --git a/src/Layouts/BordersList/BorderListBox.vala b/src/Layouts/BordersList/BorderListBox.vala deleted file mode 100644 index bea90d6bf..000000000 --- a/src/Layouts/BordersList/BorderListBox.vala +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * The borders panel. - */ -public class Akira.Layouts.BordersList.BorderListBox : VirtualizingSimpleListBox { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - private Gee.HashMap borders; - private BorderListStore list_store; - - public BorderListBox (Lib.ViewCanvas canvas) { - Object ( - view_canvas: canvas - ); - - borders = new Gee.HashMap (); - list_store = new BorderListStore (); - // list_store.set_sort_func (borders_sort_function); - - model = list_store; - - // Factory function to reuse the already generated row UI element when - // a new border is created or the borders list scrolls to reveal borders - // outside of the viewport. - factory_func = (item, old_widget) => { - BorderListItem? row = null; - if (old_widget != null) { - row = old_widget as BorderListItem; - } else { - row = new BorderListItem (view_canvas); - } - - row.assign ((BorderItemModel) item); - row.show_all (); - - return row; - }; - } - - public void refresh_list () { - if (borders.size > 0) { - var removed = borders.size; - borders.clear (); - list_store.remove_all (); - list_store.items_changed (0, removed, 0); - } - - unowned var sm = view_canvas.selection_manager; - var count = sm.count (); - if (count == 0) { - return; - } - - var added = 0; - foreach (var selected in sm.selection.nodes.values) { - // Break out of the look if we have multiple selected items and more - // than 4 fills to avoid creating too many widgets at once. - if (added > 4 && count > 1) { - break; - } - - var node = selected.node; - if (node.instance.components.borders == null) { - continue; - } - foreach (var border in node.instance.components.borders.data) { - var item = new BorderItemModel (view_canvas, node, border.id); - borders[node.id] = item; - list_store.add (item); - added++; - } - } - - list_store.items_changed (0, 0, added); - } -} diff --git a/src/Layouts/BordersList/BorderListItem.vala b/src/Layouts/BordersList/BorderListItem.vala deleted file mode 100644 index d90a1d32d..000000000 --- a/src/Layouts/BordersList/BorderListItem.vala +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * The single color border row. - */ -public class Akira.Layouts.BordersList.BorderListItem : VirtualizingListBoxRow { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - private BorderItemModel model; - - private Widgets.ColorButton color_button; - private Widgets.ColorField color_field; - private Widgets.OpacityField opacity_field; - private Widgets.EyeDropperButton eyedropper_button; - private Widgets.HideButton hide_button; - private Gtk.Button delete_button; - - private bool? current_state = null; - - public BorderListItem (Lib.ViewCanvas canvas) { - Object ( - view_canvas: canvas - ); - - get_style_context ().add_class ("item-property"); - - var grid = new Gtk.Grid () { - margin = 3 - }; - - var container = new Gtk.Grid (); - var context = container.get_style_context (); - context.add_class ("selected-color-container"); - context.add_class ("bg-pattern"); - - color_button = new Widgets.ColorButton (); - container.add (color_button); - - eyedropper_button = new Widgets.EyeDropperButton () {}; - grid.add (container); - grid.add (eyedropper_button); - - color_field = new Widgets.ColorField (view_canvas); - grid.add (color_field); - - opacity_field = new Widgets.OpacityField (view_canvas); - grid.add (opacity_field); - - hide_button = new Widgets.HideButton () {}; - grid.add (hide_button); - - delete_button = new Gtk.Button.from_icon_name ("user-trash-symbolic", Gtk.IconSize.SMALL_TOOLBAR) { - valign = Gtk.Align.CENTER, - can_focus = false, - tooltip_text = _("Remove color"), - margin_start = 3 - }; - delete_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - delete_button.get_style_context ().add_class ("button-rounded"); - delete_button.clicked.connect (delete_border); - grid.add (delete_button); - - add (grid); - } - - ~BorderListItem () { - model.value_changed.disconnect (on_model_changed); - } - - public void assign (BorderItemModel data) { - model_item = data; - model = (BorderItemModel) model_item; - color_button.assign (model); - color_field.assign (model); - opacity_field.assign (model); - hide_button.assign (model); - eyedropper_button.assign (model); - - model.value_changed.connect (on_model_changed); - on_model_changed (); - } - - private void on_model_changed () { - if (current_state == model.hidden) { - return; - } - - if (model.hidden) { - get_style_context ().add_class ("disabled"); - selectable = false; - } else { - get_style_context ().remove_class ("disabled"); - selectable = true; - } - - current_state = model.hidden; - } - - private void delete_border () { - model.delete (); - view_canvas.window.main_window.refresh_borders (); - } -} diff --git a/src/Layouts/BordersList/BorderListStore.vala b/src/Layouts/BordersList/BorderListStore.vala deleted file mode 100644 index a802cad72..000000000 --- a/src/Layouts/BordersList/BorderListStore.vala +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * The model holding the borders panel rows. - */ -public class Akira.Layouts.BordersList.BorderListStore : VirtualizingListBoxModel { - public delegate bool RowVisibilityFunc (GLib.Object row); - - private GLib.Sequence data = new GLib.Sequence (); - private uint last_position = uint.MAX; - private GLib.SequenceIter? last_iter; - private unowned GLib.CompareDataFunc compare_func; - private unowned RowVisibilityFunc filter_func; - - public override uint get_n_items () { - return data.get_length (); - } - - public override GLib.Object? get_item (uint index) { - return get_item_internal (index); - } - - public override GLib.Object? get_item_unfiltered (uint index) { - return get_item_internal (index, true); - } - - private GLib.Object? get_item_internal (uint index, bool unfiltered = false) { - GLib.SequenceIter? iter = null; - - if (last_position != uint.MAX) { - if (last_position == index + 1) { - iter = last_iter.prev (); - } else if (last_position == index - 1) { - iter = last_iter.next (); - } else if (last_position == index) { - iter = last_iter; - } - } - - if (iter == null) { - iter = data.get_iter_at_pos ((int)index); - } - - last_iter = iter; - last_position = index; - - if (iter.is_end ()) { - return null; - } - - if (filter_func == null) { - return iter.get (); - } else if (filter_func (iter.get ())) { - return iter.get (); - } else if (unfiltered) { - return iter.get (); - } else { - return null; - } - } - - public void add (BorderItemModel model) { - if (compare_func != null) { - this.data.insert_sorted (model, compare_func); - } else { - this.data.prepend (model); - } - - last_iter = null; - last_position = uint.MAX; - } - - public void remove (BorderItemModel data) { - var iter = this.data.get_iter_at_pos (get_index_of_unfiltered (data)); - iter.remove (); - - last_iter = null; - last_position = uint.MAX; - } - - public void remove_all () { - data.get_begin_iter ().remove_range (data.get_end_iter ()); - unselect_all (); - - last_iter = null; - last_position = uint.MAX; - } - - public void set_sort_func (GLib.CompareDataFunc function) { - this.compare_func = function; - } - - public void set_filter_func (RowVisibilityFunc? function) { - filter_func = function; - } -} diff --git a/src/Layouts/BordersList/BordersPanel.vala b/src/Layouts/BordersList/BordersPanel.vala deleted file mode 100644 index 750dd917d..000000000 --- a/src/Layouts/BordersList/BordersPanel.vala +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "alecaddd" Castellani - */ - -public class Akira.Layouts.BordersList.BordersPanel : Gtk.Grid { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - public BorderListBox borders_listbox; - - public BordersPanel (Lib.ViewCanvas canvas) { - Object ( - view_canvas: canvas - ); - - var title_cont = new Gtk.Grid () { - orientation = Gtk.Orientation.HORIZONTAL, - hexpand = true - }; - title_cont.get_style_context ().add_class ("option-panel"); - - var label = new Gtk.Label (_("Borders")) { - halign = Gtk.Align.FILL, - xalign = 0, - hexpand = true, - ellipsize = Pango.EllipsizeMode.END - }; - - var add_btn = new Gtk.Button.from_icon_name ("list-add-symbolic", Gtk.IconSize.SMALL_TOOLBAR) { - can_focus = false, - valign = Gtk.Align.CENTER, - halign = Gtk.Align.CENTER, - tooltip_text = _("Add border color") - }; - add_btn.clicked.connect (add_border); - add_btn.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - - title_cont.attach (label, 0, 0, 1, 1); - title_cont.attach (add_btn, 1, 0, 1, 1); - - attach (title_cont, 0, 0, 1, 1); - - borders_listbox = new BorderListBox (view_canvas); - attach (borders_listbox, 0, 1, 1, 1); - - // Show the widget by default. - show_all (); - // But then hide it right after so we can toggle it. - visible = false; - no_show_all = true; - - view_canvas.window.event_bus.selection_modified.connect (on_selection_modified); - } - - private void on_selection_modified () { - unowned var sm = view_canvas.selection_manager; - - bool is_visible = false; - foreach (var selected in sm.selection.nodes.values) { - // Show the borders panel only if at least one item is not an artboard. - if (!selected.node.instance.is_artboard) { - is_visible = true; - break; - } - } - - visible = is_visible; - no_show_all = !is_visible; - - if (is_visible) { - borders_listbox.refresh_list (); - } - } - - private void add_border () { - unowned var sm = view_canvas.selection_manager; - if (sm.count () == 0) { - return; - } - - var border_rgba = Gdk.RGBA (); - border_rgba.parse (settings.border_color); - var color = Lib.Components.Color.from_rgba (border_rgba); - - unowned var im = _view_canvas.items_manager; - foreach (var selected in sm.selection.nodes.values) { - // Don't add borders for Artboards. - if (selected.node.instance.is_artboard) { - continue; - } - - unowned var old_borders = selected.node.instance.components.borders; - Lib.Components.Borders? new_borders = (old_borders == null) ? null : old_borders.copy (); - double? size = null; - if (new_borders == null) { - new_borders = new Lib.Components.Borders (); - size = settings.border_size; - } - - new_borders.append_border_with_color (color, size); - selected.node.instance.components.borders = new_borders; - im.item_model.alert_node_changed (selected.node, Lib.Components.Component.Type.COMPILED_BORDER); - } - im.compile_model (); - borders_listbox.refresh_list (); - } -} diff --git a/src/Layouts/FillsList/FillItemModel.vala b/src/Layouts/FillsList/FillItemModel.vala deleted file mode 100644 index c924206fd..000000000 --- a/src/Layouts/FillsList/FillItemModel.vala +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Simple Object to be handled by the FillsListBoxModel and to give easy access - * the fill component of the Lib.Items.ModelNode. - */ -public class Akira.Layouts.FillsList.FillItemModel : Models.ColorModel { - private unowned Akira.Lib.ViewCanvas _view_canvas; - - private Lib.Items.ModelInstance _cached_instance; - - public int fill_id; - - public override void on_value_changed () { - if (block_signal > 0) { - return; - } - - unowned var im = _view_canvas.items_manager; - var node = im.item_model.node_from_id (_cached_instance.id); - assert (node != null); - - var new_color = Lib.Components.Color.from_rgba (color, hidden); - var new_fills = node.instance.components.fills.copy (); - new_fills.replace (Lib.Components.Fills.Fill (fill_id, new_color)); - node.instance.components.fills = new_fills; - - im.item_model.alert_node_changed (node, Lib.Components.Component.Type.COMPILED_FILL); - im.compile_model (); - } - - public override void delete () { - unowned var im = _view_canvas.items_manager; - var node = im.item_model.node_from_id (_cached_instance.id); - assert (node != null); - - var new_fills = node.instance.components.fills.copy (); - new_fills.remove (fill_id); - node.instance.components.fills = new_fills; - - im.item_model.alert_node_changed (node, Lib.Components.Component.Type.COMPILED_FILL); - im.compile_model (); - } - - public FillItemModel (Lib.ViewCanvas view_canvas, Lib.Items.ModelNode node, int fill_id) { - update_node (node, fill_id); - _view_canvas = view_canvas; - } - - private void update_node (Lib.Items.ModelNode new_node, int fill_id) { - _cached_instance = new_node.instance; - this.fill_id = fill_id; - - var blocker = new SignalBlocker (this); - (blocker); - - var fill = _cached_instance.components.fills.fill_from_id (fill_id); - color = fill.color; - hidden = fill.hidden; - } -} diff --git a/src/Layouts/FillsList/FillListBox.vala b/src/Layouts/FillsList/FillListBox.vala deleted file mode 100644 index e618bcc57..000000000 --- a/src/Layouts/FillsList/FillListBox.vala +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * The fills panel. - */ -public class Akira.Layouts.FillsList.FillListBox : VirtualizingSimpleListBox { - public unowned Akira.Lib.ViewCanvas view_canvas { get; construct; } - - private Gee.HashMap fills; - private FillListStore list_store; - - public FillListBox (Akira.Lib.ViewCanvas canvas) { - Object ( - view_canvas: canvas - ); - - fills = new Gee.HashMap (); - list_store = new FillListStore (); - // list_store.set_sort_func (fills_sort_function); - - model = list_store; - - // Factory function to reuse the already generated row UI element when - // a new fill is created or the fills list scrolls to reveal fills - // outside of the viewport. - factory_func = (item, old_widget) => { - FillListItem? row = null; - if (old_widget != null) { - row = old_widget as FillListItem; - } else { - row = new FillListItem (view_canvas); - } - - row.assign ((FillItemModel) item); - row.show_all (); - - return row; - }; - } - - public void refresh_list () { - if (fills.size > 0) { - var removed = fills.size; - fills.clear (); - list_store.remove_all (); - list_store.items_changed (0, removed, 0); - } - - unowned var sm = view_canvas.selection_manager; - var count = sm.count (); - if (count == 0) { - return; - } - - var added = 0; - foreach (var selected in sm.selection.nodes.values) { - // Break out of the look if we have multiple selected items and more - // than 4 fills to avoid creating too many widgets at once. - if (added > 4 && count > 1) { - break; - } - - var node = selected.node; - if (node.instance.components.fills == null) { - continue; - } - foreach (var fill in node.instance.components.fills.data) { - var item = new FillItemModel (view_canvas, node, fill.id); - fills[node.id] = item; - list_store.add (item); - added++; - } - } - - list_store.items_changed (0, 0, added); - } -} diff --git a/src/Layouts/FillsList/FillListItem.vala b/src/Layouts/FillsList/FillListItem.vala deleted file mode 100644 index 8421465c4..000000000 --- a/src/Layouts/FillsList/FillListItem.vala +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * The single color fill row. - */ -public class Akira.Layouts.FillsList.FillListItem : VirtualizingListBoxRow { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - private FillItemModel model; - - private Widgets.ColorButton color_button; - private Widgets.ColorField color_field; - private Widgets.OpacityField opacity_field; - private Widgets.EyeDropperButton eyedropper_button; - private Widgets.HideButton hide_button; - private Gtk.Button delete_button; - - private bool? current_state = null; - - public FillListItem (Akira.Lib.ViewCanvas canvas) { - Object ( - view_canvas: canvas - ); - - get_style_context ().add_class ("item-property"); - - var grid = new Gtk.Grid () { - margin = 3 - }; - - var container = new Gtk.Grid (); - var context = container.get_style_context (); - context.add_class ("selected-color-container"); - context.add_class ("bg-pattern"); - - color_button = new Widgets.ColorButton (); - container.add (color_button); - - eyedropper_button = new Widgets.EyeDropperButton () {}; - grid.add (container); - grid.add (eyedropper_button); - - color_field = new Widgets.ColorField (view_canvas); - grid.add (color_field); - - opacity_field = new Widgets.OpacityField (view_canvas); - grid.add (opacity_field); - - hide_button = new Widgets.HideButton () {}; - grid.add (hide_button); - - delete_button = new Gtk.Button.from_icon_name ("user-trash-symbolic", Gtk.IconSize.SMALL_TOOLBAR) { - valign = Gtk.Align.CENTER, - can_focus = false, - tooltip_text = _("Remove color"), - margin_start = 3 - }; - delete_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - delete_button.get_style_context ().add_class ("button-rounded"); - delete_button.clicked.connect (delete_fill); - grid.add (delete_button); - - add (grid); - } - - ~FillListItem () { - model.value_changed.disconnect (on_model_changed); - } - - public void assign (FillItemModel data) { - model_item = data; - model = (FillItemModel) model_item; - color_button.assign (model); - color_field.assign (model); - opacity_field.assign (model); - hide_button.assign (model); - eyedropper_button.assign (model); - - model.value_changed.connect (on_model_changed); - on_model_changed (); - } - - private void on_model_changed () { - if (current_state == model.hidden) { - return; - } - - if (model.hidden) { - get_style_context ().add_class ("disabled"); - selectable = false; - } else { - get_style_context ().remove_class ("disabled"); - selectable = true; - } - - current_state = model.hidden; - } - - private void delete_fill () { - model.delete (); - view_canvas.window.main_window.refresh_fills (); - } -} diff --git a/src/Layouts/FillsList/FillListStore.vala b/src/Layouts/FillsList/FillListStore.vala deleted file mode 100644 index 0adddba3b..000000000 --- a/src/Layouts/FillsList/FillListStore.vala +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * The model holding the fills panel rows. - */ -public class Akira.Layouts.FillsList.FillListStore : VirtualizingListBoxModel { - public delegate bool RowVisibilityFunc (GLib.Object row); - - private GLib.Sequence data = new GLib.Sequence (); - private uint last_position = uint.MAX; - private GLib.SequenceIter? last_iter; - private unowned GLib.CompareDataFunc compare_func; - private unowned RowVisibilityFunc filter_func; - - public override uint get_n_items () { - return data.get_length (); - } - - public override GLib.Object? get_item (uint index) { - return get_item_internal (index); - } - - public override GLib.Object? get_item_unfiltered (uint index) { - return get_item_internal (index, true); - } - - private GLib.Object? get_item_internal (uint index, bool unfiltered = false) { - GLib.SequenceIter? iter = null; - - if (last_position != uint.MAX) { - if (last_position == index + 1) { - iter = last_iter.prev (); - } else if (last_position == index - 1) { - iter = last_iter.next (); - } else if (last_position == index) { - iter = last_iter; - } - } - - if (iter == null) { - iter = data.get_iter_at_pos ((int)index); - } - - last_iter = iter; - last_position = index; - - if (iter.is_end ()) { - return null; - } - - if (filter_func == null) { - return iter.get (); - } else if (filter_func (iter.get ())) { - return iter.get (); - } else if (unfiltered) { - return iter.get (); - } else { - return null; - } - } - - public void add (FillItemModel model) { - if (compare_func != null) { - this.data.insert_sorted (model, compare_func); - } else { - this.data.prepend (model); - } - - last_iter = null; - last_position = uint.MAX; - } - - public void remove (FillItemModel data) { - var iter = this.data.get_iter_at_pos (get_index_of_unfiltered (data)); - iter.remove (); - - last_iter = null; - last_position = uint.MAX; - } - - public void remove_all () { - data.get_begin_iter ().remove_range (data.get_end_iter ()); - unselect_all (); - - last_iter = null; - last_position = uint.MAX; - } - - public void set_sort_func (GLib.CompareDataFunc function) { - this.compare_func = function; - } - - public void set_filter_func (RowVisibilityFunc? function) { - filter_func = function; - } -} diff --git a/src/Layouts/FillsList/FillsPanel.vala b/src/Layouts/FillsList/FillsPanel.vala deleted file mode 100644 index 843293b21..000000000 --- a/src/Layouts/FillsList/FillsPanel.vala +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "alecaddd" Castellani - */ - -public class Akira.Layouts.FillsList.FillsPanel : Gtk.Grid { - public unowned Akira.Lib.ViewCanvas view_canvas { get; construct; } - - public FillListBox fills_listbox; - - public FillsPanel (Akira.Lib.ViewCanvas canvas) { - Object ( - view_canvas: canvas - ); - - var title_cont = new Gtk.Grid () { - orientation = Gtk.Orientation.HORIZONTAL, - hexpand = true - }; - title_cont.get_style_context ().add_class ("option-panel"); - - var label = new Gtk.Label (_("Fills")) { - halign = Gtk.Align.FILL, - xalign = 0, - hexpand = true, - ellipsize = Pango.EllipsizeMode.END - }; - - var add_btn = new Gtk.Button.from_icon_name ("list-add-symbolic", Gtk.IconSize.SMALL_TOOLBAR) { - can_focus = false, - valign = Gtk.Align.CENTER, - halign = Gtk.Align.CENTER, - tooltip_text = _("Add fill color") - }; - add_btn.clicked.connect (add_fill); - add_btn.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - - title_cont.attach (label, 0, 0, 1, 1); - title_cont.attach (add_btn, 1, 0, 1, 1); - - attach (title_cont, 0, 0, 1, 1); - - fills_listbox = new FillListBox (view_canvas); - attach (fills_listbox, 0, 1, 1, 1); - - // Show the widget by default. - show_all (); - // But then hide it right after so we can toggle it. - visible = false; - no_show_all = true; - - view_canvas.window.event_bus.selection_modified.connect (on_selection_modified); - } - - private void on_selection_modified () { - unowned var sm = view_canvas.selection_manager; - bool is_visible = sm.count () > 0; - - visible = is_visible; - no_show_all = !is_visible; - - fills_listbox.refresh_list (); - } - - private void add_fill () { - unowned var sm = view_canvas.selection_manager; - if (sm.count () == 0) { - return; - } - - var fill_rgba = Gdk.RGBA (); - fill_rgba.parse (settings.fill_color); - var color = Lib.Components.Color.from_rgba (fill_rgba); - - unowned var im = _view_canvas.items_manager; - foreach (var selected in sm.selection.nodes.values) { - var new_fills = selected.node.instance.components.fills.copy (); - new_fills.append_fill_with_color (color); - selected.node.instance.components.fills = new_fills; - im.item_model.alert_node_changed (selected.node, Lib.Components.Component.Type.COMPILED_FILL); - } - im.compile_model (); - fills_listbox.refresh_list (); - } -} diff --git a/src/Layouts/HeaderBar.vala b/src/Layouts/HeaderBar.vala deleted file mode 100644 index e6c02a63c..000000000 --- a/src/Layouts/HeaderBar.vala +++ /dev/null @@ -1,592 +0,0 @@ -/* - * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Layouts.HeaderBar : Gtk.HeaderBar { - public weak Akira.Window window { get; construct; } - - public Widgets.HeaderBarButton new_document; - public Widgets.HeaderBarButton save_file; - public Widgets.HeaderBarButton save_file_as; - public Gtk.Grid recent_files_grid; - - public Widgets.MenuButton menu; - public Widgets.MenuButton items; - public Widgets.ZoomButton zoom; - public Widgets.HeaderBarButton group; - public Widgets.HeaderBarButton ungroup; - public Widgets.HeaderBarButton move_up; - public Widgets.HeaderBarButton move_down; - public Widgets.HeaderBarButton move_top; - public Widgets.HeaderBarButton move_bottom; - public Widgets.HeaderBarButton preferences; - public Widgets.HeaderBarButton path_difference; - public Widgets.HeaderBarButton path_exclusion; - public Widgets.HeaderBarButton path_intersect; - public Widgets.HeaderBarButton path_union; - - public Gtk.PopoverMenu popover_insert; - - public bool toggled { - get { - return visible; - } set { - visible = value; - no_show_all = !value; - } - } - - public HeaderBar (Akira.Window window) { - Object ( - toggled: true, - window: window - ); - } - - construct { - set_show_close_button (true); - set_project_title ( _("Untitled") ); - - menu = new Widgets.MenuButton ("document-open", _("Menu"), null); - var menu_popover = build_main_menu_popover (); - menu.button.popover = menu_popover; - - items = new Widgets.MenuButton ("insert-object", _("Insert"), null); - var items_popover = build_items_popover (); - items.button.popover = items_popover; - - zoom = new Widgets.ZoomButton (window); - - group =new Widgets.HeaderBarButton (window, "object-group", - _("Group"), {"g"}, "multiple"); - ungroup = new Widgets.HeaderBarButton (window, "object-ungroup", - _("Ungroup"), {"g"}, "group"); - - move_up = new Widgets.HeaderBarButton (window, "selection-raise", - _("Up"), {"Up"}, "single"); - move_up.button.action_name = Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_MOVE_UP; - - move_down = new Widgets.HeaderBarButton (window, "selection-lower", - _("Down"), {"Down"}, "single"); - move_down.button.action_name = Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_MOVE_DOWN; - - move_top = new Widgets.HeaderBarButton (window, "selection-top", - _("Top"), {"Up"}, "single"); - move_top.button.action_name = Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_MOVE_TOP; - - move_bottom = new Widgets.HeaderBarButton (window, "selection-bottom", - _("Bottom"), {"Down"}, "single"); - move_bottom.button.action_name = Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_MOVE_BOTTOM; - - preferences = new Widgets.HeaderBarButton (window, "open-menu", - _("Settings"), {"comma"}); - preferences.button.action_name = Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_PREFERENCES; - preferences.sensitive = true; - - var export = new Widgets.MenuButton ("document-export", _("Export"), null); - var export_popover = build_export_popover (); - export.button.popover = export_popover; - export.sensitive = true; - - var layout = new Widgets.MenuButton ("document-layout", _("Layout"), null); - var layout_popover = build_layout_popover (); - layout.button.popover = layout_popover; - layout.sensitive = true; - - path_difference = new Widgets.HeaderBarButton (window, "path-difference", - _("Difference"), null, "multiple"); - path_exclusion = new Widgets.HeaderBarButton (window, "path-exclusion", - _("Exclusion"), null, "multiple"); - path_intersect = new Widgets.HeaderBarButton (window, "path-intersection", - _("Intersect"), null, "multiple"); - path_union = new Widgets.HeaderBarButton (window, "path-union", - _("Union"), null, "multiple"); - - pack_start (menu); - pack_start (items); - pack_start (new Gtk.Separator (Gtk.Orientation.VERTICAL)); - pack_start (zoom); - pack_start (new Gtk.Separator (Gtk.Orientation.VERTICAL)); - pack_start (group); - pack_start (ungroup); - pack_start (new Gtk.Separator (Gtk.Orientation.VERTICAL)); - pack_start (move_up); - pack_start (move_down); - pack_start (move_top); - pack_start (move_bottom); - - pack_end (preferences); - pack_end (layout); - pack_end (export); - pack_end (new Gtk.Separator (Gtk.Orientation.VERTICAL)); - pack_end (path_difference); - pack_end (path_exclusion); - pack_end (path_intersect); - pack_end (path_union); - - build_signals (); - } - - private Gtk.PopoverMenu build_main_menu_popover () { - var grid = new Gtk.Grid (); - grid.margin_top = 6; - grid.margin_bottom = 3; - grid.orientation = Gtk.Orientation.VERTICAL; - grid.width_request = 240; - grid.name = "main"; - - var new_window_button = create_model_button ( - _("New Window"), - "window-new-symbolic", - Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_NEW_WINDOW); - - var separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - separator.margin_top = separator.margin_bottom = 3; - - var open_button = create_model_button ( - _("Open"), - "document-open-symbolic", - Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_OPEN); - - recent_files_grid = new Gtk.Grid (); - recent_files_grid.margin_top = 6; - recent_files_grid.margin_bottom = 3; - recent_files_grid.orientation = Gtk.Orientation.VERTICAL; - recent_files_grid.width_request = 220; - recent_files_grid.name = "files-menu"; - - var open_recent_button = new Gtk.ModelButton (); - open_recent_button.text = _("Open Recent"); - open_recent_button.menu_name = "files-menu"; - fetch_recent_files.begin (); - - var separator2 = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - separator2.margin_top = separator2.margin_bottom = 3; - - var save_button = create_model_button ( - _("Save"), - "document-save-symbolic", - Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_SAVE); - - var save_as_button = create_model_button ( - _("Save As"), - "document-save-as-symbolic", - Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_SAVE_AS); - - var separator3 = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - separator3.margin_top = separator3.margin_bottom = 3; - - var quit_button = create_model_button ( - _("Quit"), - "system-shutdown-symbolic", - Akira.Services.ActionManager.ACTION_PREFIX + Akira.Services.ActionManager.ACTION_QUIT); - - grid.add (new_window_button); - grid.add (separator); - grid.add (open_button); - grid.add (open_recent_button); - grid.add (separator2); - grid.add (save_button); - grid.add (save_as_button); - grid.add (separator3); - grid.add (quit_button); - grid.show_all (); - - var popover = new Gtk.PopoverMenu (); - popover.add (grid); - popover.add (recent_files_grid); - popover.child_set_property (grid, "submenu", "main"); - popover.child_set_property (recent_files_grid, "submenu", "files-menu"); - - return popover; - } - - private Gtk.PopoverMenu build_items_popover () { - var grid = new Gtk.Grid (); - grid.margin_top = 6; - grid.margin_bottom = 3; - grid.orientation = Gtk.Orientation.VERTICAL; - grid.width_request = 200; - grid.name = "main"; - - var artboard = create_model_button ( - _("Artboard"), - "window-new-symbolic", - Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_ARTBOARD_TOOL); - - var separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - separator.margin_top = separator.margin_bottom = 3; - - // Create the shapes submenu - var shapes_grid = new Gtk.Grid (); - shapes_grid.margin_top = 6; - shapes_grid.margin_bottom = 3; - shapes_grid.orientation = Gtk.Orientation.VERTICAL; - shapes_grid.width_request = 200; - shapes_grid.name = "shapes-menu"; - - var back_button = new Gtk.ModelButton (); - back_button.text = _("Add Items"); - back_button.inverted = true; - back_button.menu_name = "main"; - - var sub_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - sub_separator.margin_top = sub_separator.margin_bottom = 3; - - var rectangle = create_model_button ( - _("Rectangle"), - "shape-rectangle-symbolic", - Akira.Services.ActionManager.ACTION_PREFIX + - Akira.Services.ActionManager.ACTION_RECT_TOOL); - - var ellipse = create_model_button ( - _("Ellipse"), - "shape-circle-symbolic", - Akira.Services.ActionManager.ACTION_PREFIX + - Akira.Services.ActionManager.ACTION_ELLIPSE_TOOL); - - shapes_grid.add (back_button); - shapes_grid.add (sub_separator); - shapes_grid.add (rectangle); - shapes_grid.add (ellipse); - shapes_grid.show_all (); - - var shapes_button = new Gtk.ModelButton (); - shapes_button.text = _("Shapes"); - shapes_button.menu_name = "shapes-menu"; - - var separator2 = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - separator2.margin_top = separator2.margin_bottom = 3; - - var vector = create_model_button ( - _("Vector"), - "segment-curve", - Akira.Services.ActionManager.ACTION_PREFIX + - Akira.Services.ActionManager.ACTION_PATH_TOOL); - - var pencil = create_model_button (_("Pencil"), "edit-symbolic", "P"); - - var text = create_model_button ( - _("Text"), - "shape-text-symbolic", - Akira.Services.ActionManager.ACTION_PREFIX + - Akira.Services.ActionManager.ACTION_TEXT_TOOL); - - var image = create_model_button ( - _("Image"), - "image-x-generic-symbolic", - Akira.Services.ActionManager.ACTION_PREFIX + - Akira.Services.ActionManager.ACTION_IMAGE_TOOL); - - grid.add (artboard); - grid.add (separator); - grid.add (shapes_button); - grid.add (separator2); - grid.add (vector); - grid.add (pencil); - grid.add (text); - grid.add (image); - grid.show_all (); - - popover_insert = new Gtk.PopoverMenu (); - popover_insert.add (grid); - popover_insert.add (shapes_grid); - popover_insert.child_set_property (grid, "submenu", "main"); - popover_insert.child_set_property (shapes_grid, "submenu", "shapes-menu"); - - return popover_insert; - } - - private Gtk.PopoverMenu build_export_popover () { - var grid = new Gtk.Grid (); - grid.margin_top = 6; - grid.margin_bottom = 3; - grid.orientation = Gtk.Orientation.VERTICAL; - grid.width_request = 240; - grid.name = "main"; - - var export_selection = create_model_button ( - _("Export Current Selection"), - null, - Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_EXPORT_SELECTION); - - var export_artboards = create_model_button ( - _("Export Artboards"), - null, - Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_EXPORT_ARTBOARDS); - - var separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - separator.margin_top = separator.margin_bottom = 3; - - var export_area_grab = create_model_button ( - _("Highlight Area to Export"), - null, - Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_EXPORT_GRAB - ); - - grid.add (export_selection); - grid.add (export_artboards); - grid.add (separator); - grid.add (export_area_grab); - grid.show_all (); - - var popover = new Gtk.PopoverMenu (); - popover.add (grid); - - return popover; - } - - private Gtk.PopoverMenu build_layout_popover () { - var grid = new Gtk.Grid (); - grid.margin_top = 6; - grid.margin_bottom = 3; - grid.orientation = Gtk.Orientation.VERTICAL; - grid.width_request = 240; - grid.name = "main"; - - var pixel_grid = create_model_button ( - _("Toggle Pixel Grid"), - null, - Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_TOGGLE_PIXEL_GRID); - - var presentation_mode = create_model_button ( - _("Presentation Mode"), - null, - Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_PRESENTATION); - - grid.add (pixel_grid); - grid.add (presentation_mode); - grid.show_all (); - - var popover = new Gtk.PopoverMenu (); - popover.add (grid); - - return popover; - } - - private void build_signals () { - window.event_bus.toggle_presentation_mode.connect (toggle); - window.event_bus.file_edited.connect (on_file_edited); - window.event_bus.file_saved.connect (on_file_saved); - window.event_bus.selection_modified.connect (on_selection_modified); - window.event_bus.update_recent_files_list.connect (fetch_recent_files); - } - - private void toggle () { - toggled = !toggled; - if (!toggled) { - window.event_bus.canvas_notification (_("Presentation Mode enabled.")); - } - } - - /** - * Fetch the recently opened files from GSettings and add them to the list - * if those files still exists. - */ - public async void fetch_recent_files () { - recent_files_grid.@foreach (child => { - recent_files_grid.remove (child); - }); - - // Add default buttons. - var back_button = new Gtk.ModelButton (); - back_button.text = _("Main Menu"); - back_button.inverted = true; - back_button.menu_name = "main"; - back_button.expand = true; - - var sub_separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL); - sub_separator.margin_top = sub_separator.margin_bottom = 3; - - recent_files_grid.add (back_button); - recent_files_grid.add (sub_separator); - - // Loop a first time to clear missing files and prevent wrong accelerators. - string[] all_files = {}; - for (var i = 0; i <= settings.recently_opened.length; i++) { - // Skip if the record is empty. - if (settings.recently_opened[i] == null) { - continue; - } - - // Skip if the file doesn't exist. - var file = File.new_for_path (settings.recently_opened[i]); - if (!file.query_exists ()) { - continue; - } - - all_files += settings.recently_opened[i]; - } - - // Update the GSettings to prevent loading an unavailable file. - settings.set_strv ("recently-opened", all_files); - - for (var i = 0; i <= all_files.length; i++) { - // Skip if the record is empty. - if (all_files[i] == null) { - continue; - } - - // Store the full path in a variable before the split() method explodes the string. - var full_path = all_files[i]; - - // Get the file name. - string[] split_string = all_files[i].split ("/"); - var file_name = split_string[split_string.length - 1].replace (".akira", ""); - - var button = new Gtk.ModelButton (); - - // Add quick accelerators only for the first 3 items. - string? accels = null; - if (i < 3) { - switch (i) { - case 0: - accels = Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_LOAD_FIRST; - break; - case 1: - accels = Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_LOAD_SECOND; - break; - case 2: - accels = Akira.Services.ActionManager.ACTION_PREFIX - + Akira.Services.ActionManager.ACTION_LOAD_THIRD; - break; - } - - button.get_child ().destroy (); - var label = new Granite.AccelLabel.from_action_name (file_name, accels); - button.add (label); - button.action_name = accels; - } else { - button.text = file_name; - - // Define the open action on click only for those files that don't - // have an accelerator to prevent double calls. - button.clicked.connect (() => { - var file = File.new_for_path (full_path); - if (!file.query_exists ()) { - window.event_bus.canvas_notification ( - _("Unable to open file at '%s'").printf (full_path) - ); - return; - } - - File[] files = {}; - files += file; - window.app.open (files, ""); - }); - } - - button.tooltip_text = all_files[i]; - - recent_files_grid.add (button); - } - - recent_files_grid.show_all (); - } - - private void on_file_edited () { - if (title.has_suffix ("*")) { - return; - } - - title = ("%s*").printf (title); - } - - private void on_file_saved (string? file_name) { - if (file_name == null) { - title = title.has_suffix ("*") ? title.slice (0, title.length - 1) : title; - return; - } - - title = file_name.has_suffix (".akira") ? file_name.replace (".akira", "") : file_name; - } - - private void on_selection_modified () { - unowned var sm = window.main_window.main_view_canvas.canvas.selection_manager; - var count = sm.count (); - - if (count == 0) { - move_up.sensitive = false; - move_down.sensitive = false; - move_top.sensitive = false; - move_bottom.sensitive = false; - } else if (count > 1) { - move_up.sensitive = true; - move_down.sensitive = true; - move_top.sensitive = true; - move_bottom.sensitive = true; - } else { - var node = sm.selection.first_node (); - bool is_top = node.parent.children.length - 1 == node.pos_in_parent; - bool is_bottom = node.pos_in_parent == 0; - - move_up.sensitive = !is_top; - move_down.sensitive = !is_bottom; - move_top.sensitive = !is_top; - move_bottom.sensitive = !is_bottom; - } - } - - private Gtk.ModelButton create_model_button (string text, string? icon, string? accels = null) { - var button = new Gtk.ModelButton (); - button.get_child ().destroy (); - var label = new Granite.AccelLabel.from_action_name (text, accels); - - if (icon != null) { - var image = new Gtk.Image.from_icon_name (icon, Gtk.IconSize.MENU); - image.margin_end = 6; - label.attach_next_to ( - image, - label.get_child_at (0, 0), - Gtk.PositionType.LEFT - ); - } - - button.add (label); - button.action_name = accels; - - return button; - } - - private void set_project_title (string title) { - this.title = title; - Gtk.Label label = new Gtk.Label (title); - label.get_style_context ().add_class (Gtk.STYLE_CLASS_TITLE); - label.set_hexpand (true); - label.set_ellipsize (Pango.EllipsizeMode.END); - - set_custom_title (label); - } -} diff --git a/src/Layouts/LayersList/LayerItemModel.vala b/src/Layouts/LayersList/LayerItemModel.vala deleted file mode 100644 index 0e394a9c0..000000000 --- a/src/Layouts/LayersList/LayerItemModel.vala +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - * Adapted from the elementary OS Mail's VirtualizingListBox source code created - * by David Hewitt - */ - -/* - * Simple Object to be handled by the LayersListBoxModel and to give easy access - * the attributes of the Lib.Items.ModelNode. - */ -public class Akira.Layouts.LayersList.LayerItemModel : GLib.Object { - private unowned Akira.Lib.ViewCanvas _view_canvas; - - private Lib.Items.ModelInstance _cached_instance; - - public int id { - get { - return _cached_instance.id; - } - } - /* - * Control the name of the item. - */ - public string name { - owned get { - return _cached_instance.components.name.name; - } - set { - if (_cached_instance.components.name.name == value) { - return; - } - - unowned var im = _view_canvas.items_manager; - var node = im.item_model.node_from_id (_cached_instance.id); - assert (node != null); - - node.instance.components.name = new Lib.Components.Name (value, id.to_string ()); - im.item_model.alert_node_changed (node, Lib.Components.Component.Type.COMPILED_NAME); - im.compile_model (); - } - } - - public string icon { - get { - unowned var type = _cached_instance.type; - if (type is Lib.Items.ModelTypeRect) { - return "shape-rectangle-symbolic"; - } else if (type is Lib.Items.ModelTypeEllipse) { - return "shape-circle-symbolic"; - } else if (type is Lib.Items.ModelTypePath) { - return "segment-curve-symbolic"; - } else if (type is Lib.Items.ModelTypeGroup) { - return "folder-symbolic"; - } else if (type is Lib.Items.ModelTypeText) { - return "shape-text-symbolic"; - } - return ""; - } - } - - /* - * Control the hidden/visible state of the item. - */ - // TODO. - - /* - * Control the locked/unlocked state of the item. - */ - public bool locked { - get { - return _cached_instance.components.layer.locked; - } - set { - if (_cached_instance.components.layer.locked == value) { - return; - } - - // If the layer is being locked we need to remove it from the - // current selection if needed. - if (value) { - unowned var sm = _view_canvas.selection_manager; - sm.remove_from_selection (id); - sm.selection_modified_external (); - } - - unowned var im = _view_canvas.items_manager; - var node = im.item_model.node_from_id (_cached_instance.id); - assert (node != null); - - node.instance.components.layer = new Lib.Components.Layer (value); - // If the layer is a group we need to update the locked state on - // all of its children. - if (node.children != null) { - _view_canvas.window.main_window.set_children_locked (node.get_children_ids (), value); - } - } - } - - /* - * If the instance type is an Artboard. - */ - public bool is_artboard { - get { - return _cached_instance.is_artboard; - } - } - - /* - * If the instance type is a Group. - */ - public bool is_group { - get { - return _cached_instance.is_group; - } - } - - public int[] get_children () { - return _cached_instance.children; - } - - public int parent_uid { - get { - unowned var im = _view_canvas.items_manager; - var node = im.item_model.node_from_id (_cached_instance.id); - assert (node != null); - - return node.parent.id; - } - } - - public int ancestors_size { - get { - unowned var im = _view_canvas.items_manager; - var node = im.item_model.node_from_id (_cached_instance.id); - assert (node != null); - - return node.get_ancestors_size (); - } - } - - // Always show child layers when a new artboard or group is created. - private bool _children_visible = true; - public bool children_visible { - get { - return _children_visible; - } - set { - if (value == _children_visible) { - return; - } - _children_visible = value; - - // No need to update the layers UI if this model is not a group or - // an artboard. - if (!is_group && !is_artboard) { - return; - } - - var array = new GLib.Array (); - array.data = get_children (); - // Trigger the showing or hiding of all child layers. - if (_children_visible) { - _view_canvas.window.main_window.add_layers (array); - } else { - _view_canvas.window.main_window.remove_layers (array); - } - } - } - - public LayerItemModel (Lib.ViewCanvas view_canvas, Lib.Items.ModelNode node) { - update_node (node); - _view_canvas = view_canvas; - } - - private void update_node (Lib.Items.ModelNode new_node) { - _cached_instance = new_node.instance; - } -} diff --git a/src/Layouts/LayersList/LayerListBox.vala b/src/Layouts/LayersList/LayerListBox.vala deleted file mode 100644 index 094a035b6..000000000 --- a/src/Layouts/LayersList/LayerListBox.vala +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - * Adapted from the elementary OS Mail's VirtualizingListBox source code created - * by David Hewitt - */ - -/* - * The scrollable layers panel. - */ -public class Akira.Layouts.LayersList.LayerListBox : VirtualizingListBox { - public unowned Akira.Lib.ViewCanvas view_canvas { get; construct; } - - private Gee.HashMap layers; - private LayerListStore list_store; - - public LayerListBox (Akira.Lib.ViewCanvas canvas) { - Object ( - view_canvas: canvas - ); - - selection_mode = Gtk.SelectionMode.MULTIPLE; - activate_on_single_click = true; - edit_on_double_click = true; - layers = new Gee.HashMap (); - list_store = new LayerListStore (); - list_store.set_sort_func (layers_sort_function); - - model = list_store; - - // Factory function to reuse the already generated row UI element when - // a new layer is created or the layers list scrolls to reveal layers - // outside of the viewport. - factory_func = (item, old_widget) => { - LayerListItem? row = null; - if (old_widget != null) { - row = old_widget as LayerListItem; - if (row.is_editing) { - row.edit_end (); - } - } else { - row = new LayerListItem (); - } - - row.assign ((LayerItemModel) item); - row.show_all (); - - return row; - }; - - // When an item is selected from a click on the layers list. - row_selection_changed.connect (on_row_selection_changed); - - // When a row is hovered. - row_hovered.connect (on_row_hovered); - - // When the name of the layer is being edited. - row_edited.connect (on_row_edited); - - // Listen to the button release event only for the secondary click in - // order to trigger the context menu. - button_release_event.connect (e => { - if (e.button != Gdk.BUTTON_SECONDARY) { - return Gdk.EVENT_PROPAGATE; - } - var row = get_row_at_y ((int)e.y); - if (row == null) { - return Gdk.EVENT_PROPAGATE; - } - - if (selected_row_widget != row) { - select_row (row); - } - return create_context_menu (e, (LayerListItem)row); - }); - - // Trigger the context menu when the `menu` key is pressed. - key_release_event.connect ((e) => { - if (e.keyval != Gdk.Key.Menu) { - return Gdk.EVENT_PROPAGATE; - } - var row = selected_row_widget; - return create_context_menu (e, (LayerListItem)row); - }); - - view_canvas.items_manager.item_added.connect (on_item_added); - view_canvas.selection_manager.selection_modified_external.connect (on_selection_modified_external); - view_canvas.hover_manager.hover_changed.connect (on_hover_changed); - view_canvas.window.event_bus.request_escape.connect (on_escape_request); - } - - /* - * Add all existing nodes to the layers list when the UI is revealed. - */ - public void regenerate_list (bool go_to_layer) { - unowned var im = view_canvas.items_manager; - - // Bail out if we don't have anything to add. - if (im.item_model.group_nodes.size == 0 && im.item_model.item_nodes.size == 0) { - return; - } - - ulong microseconds; - double seconds; - // Create a timer object to track the regeneration of the layers list. - Timer timer = new Timer (); - var added = 0; - - foreach (var key in im.item_model.group_nodes.keys) { - var node = im.item_model.group_nodes[key]; - if (node.id == Lib.Items.Model.ORIGIN_ID) { - continue; - } - var item = new LayerItemModel (view_canvas, node); - layers[node.id] = item; - list_store.add (item); - added++; - } - - foreach (var key in im.item_model.item_nodes.keys) { - var node = im.item_model.item_nodes[key]; - var item = new LayerItemModel (view_canvas, node); - layers[node.id] = item; - list_store.add (item); - added++; - } - - list_store.items_changed (0, 0, added); - - // Restore the selected items. - on_selection_modified_external (go_to_layer); - - timer.stop (); - seconds = timer.elapsed (out microseconds); - print ("Created %i layers in %s s\n", added, seconds.to_string ()); - } - - /* - * Clear the layers list when the UI is hidden. - */ - public void clear_list () { - // Interrupt if the layers list is empty. - if (layers.size == 0) { - return; - } - - ulong microseconds; - double seconds; - // Create a timer object to track the deletion of the layers list. - Timer timer = new Timer (); - - // Remove all items. - var removed = layers.size; - layers.clear (); - list_store.remove_all (); - list_store.items_changed (0, removed, 0); - - timer.stop (); - seconds = timer.elapsed (out microseconds); - print ("Deleted %i layers in %s s\n", removed, seconds.to_string ()); - } - - private void on_item_added (int id) { - if (view_canvas.block_ui) { - return; - } - - var node = view_canvas.items_manager.node_from_id (id); - // No need to add any layer if we don't have an instance. - if (node == null) { - return; - } - - var node_id = node.id; - var item = new LayerItemModel (view_canvas, node); - layers[node_id] = item; - list_store.add (item); - - // Check if the newly created layer is inside an artboard or a group and - // show all its child layers if they were removed. - recursive_show_child_layers (node_id); - } - - private void recursive_show_child_layers (int node_id) { - var item = layers[node_id]; - if (item == null) { - return; - } - - var parent = layers[item.parent_uid]; - if (parent == null) { - return; - } - - parent.children_visible = true; - recursive_show_child_layers (parent.parent_uid); - } - - private bool create_context_menu (Gdk.Event e, LayerListItem row) { - var menu = new Gtk.Menu (); - menu.show_all (); - - if (e.type == Gdk.EventType.BUTTON_RELEASE) { - menu.popup_at_pointer (e); - return Gdk.EVENT_STOP; - } else if (e.type == Gdk.EventType.KEY_RELEASE) { - menu.popup_at_widget (row, Gdk.Gravity.EAST, Gdk.Gravity.CENTER, e); - return Gdk.EVENT_STOP; - } - - return Gdk.EVENT_PROPAGATE; - } - - /* - * Visually create layers from a list of items ids. This method is used to - * show layers that have been removed when a parent (artboard or group) - * collapses its children. - */ - public void add_items (GLib.Array ids) { - if (view_canvas.block_ui) { - return; - } - - var added = 0; - foreach (var uid in ids.data) { - // Don't create a layer if it already exists. This might happen when - // revealing the children of a collapsed artboard during the - // creation of a new child item. - if (layers[uid] == null) { - on_item_added (uid); - } - // Check if the layer was actually created. - if (layers[uid] != null) { - added++; - } - } - // Refresh the layers list UI. - show_added_layers (added); - } - - /* - * Triggers the update of the list store and refresh of the UI to show the - * newly added items that are currently visible. - */ - public void show_added_layers (int added) { - if (view_canvas.block_ui) { - return; - } - - list_store.items_changed (0, 0, added); - // Restore selected items. - on_selection_modified_external (); - } - - /* - * Remove all the currently selected layers. The list of ids comes from the - * selected nodes in the view canvas. - */ - public void remove_items (GLib.Array ids) { - if (view_canvas.block_ui) { - return; - } - - var removed = 0; - foreach (var uid in ids.data) { - var item = layers[uid]; - if (item != null) { - removed += inner_remove_items (item); - layers.unset (uid); - list_store.remove (item); - removed++; - } - } - - list_store.items_changed (0, removed, 0); - } - - /* - * Check if an item has children and recursively loop through them to - * remove all the matching layers. - */ - private int inner_remove_items (LayerItemModel item) { - var removed = 0; - foreach (var uid in item.get_children ()) { - if (uid == 0) { - continue; - } - - var child = layers[uid]; - if (child != null) { - removed += inner_remove_items (child); - layers.unset (uid); - list_store.remove (child); - removed++; - } - } - - return removed; - } - - /* - * Sort function to always add new layers at the top unless they belong to a - * group or an artboard. - */ - private int layers_sort_function (LayerItemModel layer1, LayerItemModel layer2) { - var im = view_canvas.items_manager.item_model; - var node1 = im.node_from_id (layer1.id); - var node2 = im.node_from_id (layer2.id); - - var node1_is_group = node1.instance.is_group; - var node2_is_group = node2.instance.is_group; - - if (node1_is_group != node2_is_group) { - unowned var group_node = node1_is_group ? node1 : node2; - unowned var child_node = node1_is_group ? node2 : node1; - if (child_node.has_ancestor (group_node.id)) { - return node1_is_group ? -1 : 1; - } - } - - var path1 = im.array_path_from_node (node1); - var path2 = im.array_path_from_node (node2); - - return Utils.Array.compare_arrays (path2, path1); - } - - /* - * Update the selected items in the canvas when the selection of rows in the - * listbox changes. - */ - private void on_row_selection_changed (bool clear) { - unowned var sm = view_canvas.selection_manager; - // Always reset the selection. - sm.reset_selection (); - - // No need to do anything else if all rows were deselected. - if (clear) { - reset_edited_row (); - return; - } - - var blocker = new Lib.Managers.SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - - // Add all currently selected rows to the selection. This won't trigger - // a selection changed loop since the selection_modified_external signal - // is only triggered from a click on the canvas. - foreach (var model in get_selected_rows ()) { - sm.add_to_selection (((LayerItemModel) model).id); - } - - // Trigger the transform mode if is not currently active. This might - // happen when no items is selected and the first selection is triggered - // from the layers listbox. - unowned var mm = view_canvas.mode_manager; - if (mm.active_mode_type != Lib.Modes.AbstractInteractionMode.ModeType.TRANSFORM) { - var new_mode = new Lib.Modes.TransformMode (view_canvas, Utils.Nobs.Nob.NONE, true); - mm.register_mode (new_mode); - mm.deregister_active_mode (); - } - } - - /* - * When an item in the canvas is selected via click interaction. - */ - private void on_selection_modified_external (bool go_to_layer = false) { - reset_edited_row (); - - // Always reset the selection of the layers. - unselect_all (); - - unowned var sm = view_canvas.selection_manager; - if (sm.is_empty ()) { - return; - } - - var it = sm.selection.nodes.map_iterator (); - - // If the selection was modified from a click on the canvas, we need to - // move the first selected layer into the viewport of the layers list. - if (go_to_layer) { - it.next (); - var first_node = it.get_value ().node; - if (layers[first_node.id] != null) { - select_row_at_index (model.get_index_of (layers[first_node.id])); - } - } - - // For all other scenarios where a selection is restored dynamically or - // multiple items are selected, we don't generate the layer row widgets - // but we only update the selection state of the model. - while (it.next ()) { - var node = it.get_value ().node; - if (layers[node.id] != null) { - list_store.set_item_selected (layers[node.id], true); - } - } - - if (sm.selection.count () > 1) { - // Trigger a visual refresh of the visible layers without changing - // anything in the list store in order to show the newly selected layers. - list_store.items_changed (0, 0, 0); - } - } - - /* - * Show the hover effect on a canvas item if available. - */ - private void on_row_hovered (GLib.Object? item) { - unowned var hm = view_canvas.hover_manager; - if (item == null) { - hm.remove_hover_effect (); - return; - } - - hm.maybe_create_hover_effect_by_id (((LayerItemModel) item).id); - } - - /* - * Show the hover effect on a layer row when an item from the canvas is - * hovered. Clear the hover effect if no canvas item was hovered. - */ - private void on_hover_changed (int? id) { - on_mouse_leave_internal (); - - if (id != null && layers[id] != null) { - set_hover_on_row_from_model (layers[id]); - } - } - - /* - * Toggle the edit state of rows and handle typing accelerators accordingly. - */ - private void on_row_edited (VirtualizingListBoxRow? item) { - reset_edited_row (); - - if (item == null) { - return; - } - - edited_row = item; - var layer = (LayerListItem) edited_row; - layer.edit (); - layer.entry.activate.connect (on_activate_entry); - view_canvas.window.event_bus.disconnect_typing_accel (); - } - - /* - * Handle the `activate` signal triggered by the edited label entry of a - * layer row. - */ - private void on_activate_entry () { - ((LayerListItem) edited_row).update_label (); - on_row_edited (null); - } - - /* - * If a layer row is currently being edited, reset it to the default state. - */ - private void reset_edited_row () { - if (edited_row != null) { - var layer = (LayerListItem) edited_row; - layer.edit_end (); - layer.entry.activate.disconnect (on_activate_entry); - - edited_row = null; - view_canvas.window.event_bus.connect_typing_accel (); - } - } - - /* - * Be sure to reset any potential leftover edited layer row when the user - * presses the `esc` button. - */ - private void on_escape_request () { - on_row_edited (null); - } - - /* - * Loop through the passed nodes and update the locked state. - */ - public void set_children_locked (int[] nodes, bool is_locked) { - foreach (var uid in nodes) { - if (layers[uid] != null) { - layers[uid].locked = is_locked; - } - } - // Trigger a visual refresh of the visible layers without changing - // anything in the list store. - list_store.items_changed (0, 0, 0); - } -} diff --git a/src/Layouts/LayersList/LayerListItem.vala b/src/Layouts/LayersList/LayerListItem.vala deleted file mode 100644 index a54b14a59..000000000 --- a/src/Layouts/LayersList/LayerListItem.vala +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - * Adapted from the elementary OS Mail's VirtualizingListBox source code created - * by David Hewitt - */ - -/* - * The single layer row. - */ -public class Akira.Layouts.LayersList.LayerListItem : VirtualizingListBoxRow { - private LayerItemModel model; - - private Gtk.StyleContext style_ctx; - // Main grid to attach all other grid widgets. - private Gtk.Grid grid_main; - // Grid to collect the label and entry widgets. - private Gtk.Grid grid_entry; - // Grid to collect the hide and lock action buttons. - private Gtk.Grid grid_action; - - public Gtk.Entry entry; - private Gtk.Label label; - private Gtk.Image icon; - private Gtk.Button btn_lock; - private Gtk.Button btn_view; - private Gtk.Button btn_toggle; - - private bool _is_editing = false; - public bool is_editing { - get { - return _is_editing; - } - set { - _is_editing = value; - if (value) { - grid_action.visible = false; - return; - } - - grid_action.visible = true; - } - } - - construct { - style_ctx = get_style_context (); - - btn_toggle = new Gtk.Button.from_icon_name ("pan-down-symbolic", Gtk.IconSize.MENU) { - tooltip_text = _("Toggle visibility of child layers"), - can_focus = false - }; - btn_toggle.clicked.connect (on_toggle_pressed); - btn_toggle.get_style_context ().add_class ("flat"); - btn_toggle.get_style_context ().add_class ("button-toggle"); - btn_toggle.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - - icon = new Gtk.Image () { - margin_end = 9, - vexpand = true, - valign = Gtk.Align.CENTER - }; - icon.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - - label = new Gtk.Label (null) { - halign = Gtk.Align.FILL, - xalign = 0, - expand = true, - ellipsize = Pango.EllipsizeMode.END - }; - - grid_entry = new Gtk.Grid (); - grid_entry.attach (label, 0, 0, 1, 1); - - btn_lock = new Gtk.Button.from_icon_name ("changes-allow-symbolic", Gtk.IconSize.MENU) { - tooltip_text = _("Lock layer"), - can_focus = false - }; - btn_lock.clicked.connect (toggle_lock); - btn_lock.get_style_context ().add_class ("flat"); - - btn_view = new Gtk.Button.from_icon_name ("layer-visible-symbolic", Gtk.IconSize.MENU) { - tooltip_text = _("Hide layer"), - can_focus = false - }; - btn_view.clicked.connect (toggle_view); - btn_view.get_style_context ().add_class ("flat"); - - grid_action = new Gtk.Grid () { - margin_end = 6, - vexpand = true, - valign = Gtk.Align.CENTER - }; - grid_action.get_style_context ().add_class ("actions"); - grid_action.attach (btn_lock, 0, 0, 1, 1); - grid_action.attach (btn_view, 1, 0, 1, 1); - - grid_main = new Gtk.Grid () { - vexpand = true, - valign = Gtk.Align.CENTER - }; - grid_main.attach (icon, 0, 0, 1, 1); - grid_main.attach (btn_toggle, 1, 0, 1, 1); - grid_main.attach (grid_entry, 2, 0, 1, 1); - grid_main.attach (grid_action, 3, 0, 1, 1); - - add (grid_main); - } - - public void assign (LayerItemModel data) { - model_item = data; - model = (LayerItemModel) model_item; - - label.label = model.name; - - // Build a specific UI based on the node instance's type. - if (data.is_artboard) { - build_artboard_ui (); - } else if (data.is_group) { - build_group_ui (); - } else { - build_layer_ui (); - } - - // Update the state of the action buttons to reflect the model state. - update_btn_lock (); - - // Indent child layers based on the amount of ancestors. - grid_main.margin_start = 12 * model.ancestors_size; - } - - private void build_artboard_ui () { - // Update the general UI. - style_ctx.remove_class ("layer"); - style_ctx.remove_class ("group"); - style_ctx.add_class ("artboard"); - - // Update icon. - icon.clear (); - icon.margin_start = 0; - - // Show the toggle button. - btn_toggle.no_show_all = false; - btn_toggle.visible = true; - update_btn_toggle (); - } - - private void build_group_ui () { - // Update the general UI. - style_ctx.remove_class ("layer"); - style_ctx.remove_class ("artboard"); - style_ctx.add_class ("group"); - - // Update icon. - icon.clear (); - icon.margin_start = 0; - - // Show the toggle button. - btn_toggle.no_show_all = false; - btn_toggle.visible = true; - - update_btn_toggle (); - } - - private void build_layer_ui () { - // Update general UI. - style_ctx.remove_class ("artboard"); - style_ctx.remove_class ("group"); - style_ctx.add_class ("layer"); - - // Update icon. - icon.set_from_icon_name (model.icon, Gtk.IconSize.MENU); - icon.margin_start = 12; - - // Hide the toggle button. - btn_toggle.no_show_all = true; - btn_toggle.visible = false; - } - - public override void edit () { - if (entry != null) { - show_entry (); - return; - } - - entry = new Gtk.Entry () { - expand = true, - margin_end = 6 - }; - entry.get_style_context ().add_class ("flat"); - - grid_entry.attach (entry, 0, 1, 1, 1); - - show_entry (); - } - - /* - * The user pressed `Enter` on the layer's entry, so we trigger the update - * of the layer's name. - */ - public void update_label () { - // Trigger the model update. - model.name = entry.text; - // Update the visible label with the new model.name, so we're sure the - // update took effect. - label.label = model.name; - } - - private void show_entry () { - entry.text = label.label; - entry.visible = true; - entry.no_show_all = false; - label.visible = false; - label.no_show_all = true; - entry.grab_focus (); - is_editing = true; - } - - public override void edit_end () { - entry.visible = false; - entry.no_show_all = true; - label.visible = true; - label.no_show_all = false; - is_editing = false; - } - - private void toggle_lock () { - model.locked = !model.locked; - update_btn_lock (); - } - - private void update_btn_lock () { - if (model.locked) { - btn_lock.get_style_context ().add_class ("active"); - btn_lock.image = new Gtk.Image.from_icon_name ("changes-prevent-symbolic", Gtk.IconSize.MENU); - btn_lock.tooltip_text = _("Unlock layer"); - selectable = false; - } else { - btn_lock.get_style_context ().remove_class ("active"); - btn_lock.image = new Gtk.Image.from_icon_name ("changes-allow-symbolic", Gtk.IconSize.MENU); - btn_lock.tooltip_text = _("Lock layer"); - selectable = true; - } - } - - // TODO. - private void toggle_view () { - print ("view pressed\n"); - } - - /* - * Hide or show the child layers of this layer when the user clicks on the - * toggle button. - */ - private void on_toggle_pressed () { - model.children_visible = !model.children_visible; - update_btn_toggle (); - } - - /* - * Visually update the toggle button. - */ - private void update_btn_toggle () { - if (model.children_visible) { - btn_toggle.get_style_context ().remove_class ("collapsed"); - } else { - btn_toggle.get_style_context ().add_class ("collapsed"); - } - } -} diff --git a/src/Layouts/LayersList/LayerListStore.vala b/src/Layouts/LayersList/LayerListStore.vala deleted file mode 100644 index 0b7c40c1e..000000000 --- a/src/Layouts/LayersList/LayerListStore.vala +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - * Adapted from the elementary OS Mail's VirtualizingListBox source code created - * by David Hewitt - */ - -/* - * The model holding the layers panel rows. - */ -public class Akira.Layouts.LayersList.LayerListStore : VirtualizingListBoxModel { - public delegate bool RowVisibilityFunc (GLib.Object row); - - private GLib.Sequence data = new GLib.Sequence (); - private uint last_position = uint.MAX; - private GLib.SequenceIter? last_iter; - private unowned GLib.CompareDataFunc compare_func; - private unowned RowVisibilityFunc filter_func; - - public override uint get_n_items () { - return data.get_length (); - } - - public override GLib.Object? get_item (uint index) { - return get_item_internal (index); - } - - public override GLib.Object? get_item_unfiltered (uint index) { - return get_item_internal (index, true); - } - - private GLib.Object? get_item_internal (uint index, bool unfiltered = false) { - GLib.SequenceIter? iter = null; - - if (last_position != uint.MAX) { - if (last_position == index + 1) { - iter = last_iter.prev (); - } else if (last_position == index - 1) { - iter = last_iter.next (); - } else if (last_position == index) { - iter = last_iter; - } - } - - if (iter == null) { - iter = data.get_iter_at_pos ((int)index); - } - - last_iter = iter; - last_position = index; - - if (iter.is_end ()) { - return null; - } - - if (filter_func == null) { - return iter.get (); - } else if (filter_func (iter.get ())) { - return iter.get (); - } else if (unfiltered) { - return iter.get (); - } else { - return null; - } - } - - public void add (LayerItemModel model) { - if (compare_func != null) { - this.data.insert_sorted (model, compare_func); - } else { - this.data.prepend (model); - } - - last_iter = null; - last_position = uint.MAX; - } - - public void remove (LayerItemModel data) { - var iter = this.data.get_iter_at_pos (get_index_of_unfiltered (data)); - iter.remove (); - - last_iter = null; - last_position = uint.MAX; - } - - public void remove_all () { - data.get_begin_iter ().remove_range (data.get_end_iter ()); - unselect_all (); - - last_iter = null; - last_position = uint.MAX; - } - - public void set_sort_func (GLib.CompareDataFunc function) { - this.compare_func = function; - } - - public void set_filter_func (RowVisibilityFunc? function) { - filter_func = function; - } -} diff --git a/src/Layouts/MainCanvas.vala b/src/Layouts/MainCanvas.vala deleted file mode 100644 index 383b8e1de..000000000 --- a/src/Layouts/MainCanvas.vala +++ /dev/null @@ -1,211 +0,0 @@ -/* -* Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -* Authored by: Giacomo "giacomoalbe" Alberini -*/ - -public class Akira.Layouts.MainCanvas : Gtk.Grid { - public const int CANVAS_SIZE = 100000; - public const double SCROLL_DISTANCE = 0; - - public Gtk.ScrolledWindow main_scroll; - - public Akira.Lib.Canvas canvas; - - public weak Akira.Window window { get; construct; } - - private Gtk.Overlay main_overlay; - private Granite.Widgets.OverlayBar overlaybar; - private Granite.Widgets.Toast notification; - - private double scroll_origin_x = 0; - private double scroll_origin_y = 0; - - public MainCanvas (Akira.Window window) { - Object (window: window, orientation: Gtk.Orientation.VERTICAL); - } - - construct { - get_style_context ().add_class ("main-canvas"); - - main_overlay = new Gtk.Overlay (); - notification = new Granite.Widgets.Toast (_("")); - - main_scroll = new Gtk.ScrolledWindow (null, null); - main_scroll.expand = true; - - // Overlay the scrollbars only if mouse pointer is inside canvas - main_scroll.overlay_scrolling = false; - - // Change visibility of canvas scrollbars - main_scroll.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER); - - canvas = new Akira.Lib.Canvas (window); - canvas.set_bounds (0, 0, CANVAS_SIZE, CANVAS_SIZE); - canvas.set_scale (1.0); - - canvas.canvas_moved.connect ((event_x, event_y) => { - // Move scroll window according to normalized mouse delta - // relative to the scroll window, so with Canvas' pixel - // coordinates translated into ScrolledWindow's one. - double event_x_pixel_space = event_x; - double event_y_pixel_space = event_y; - - // Convert coordinates to pixel space, which does account for - // canvas scale and canvas translation. - // Otherwise, delta can start to "diverge" due to the - // translation of starting point happening during canvas translation - canvas.convert_to_pixels (ref event_x_pixel_space, ref event_y_pixel_space); - - var delta_x = event_x_pixel_space - scroll_origin_x; - var delta_y = event_y_pixel_space - scroll_origin_y; - - main_scroll.hadjustment.value -= delta_x; - main_scroll.vadjustment.value -= delta_y; - }); - - canvas.canvas_scroll_set_origin.connect ((origin_x, origin_y) => { - // Update scroll origin on Canvas' button_press_event - scroll_origin_x = origin_x; - scroll_origin_y = origin_y; - - canvas.convert_to_pixels (ref scroll_origin_x, ref scroll_origin_y); - }); - - canvas.scroll_event.connect (on_scroll); - - main_scroll.add (canvas); - - main_overlay.add (main_scroll); - main_overlay.add_overlay (notification); - - add (main_overlay); - - // Set up event listeners. - window.event_bus.exporting.connect (on_exporting); - window.event_bus.export_completed.connect (on_export_completed); - window.event_bus.canvas_notification.connect (trigger_notification); - } - - public bool on_scroll (Gdk.EventScroll event) { - bool is_shift = (event.state & Gdk.ModifierType.SHIFT_MASK) > 0; - bool is_ctrl = (event.state & Gdk.ModifierType.CONTROL_MASK) > 0; - - double delta_x, delta_y; - event.get_scroll_deltas (out delta_x, out delta_y); - - if (delta_y < -SCROLL_DISTANCE) { - // Scroll UP. - if (is_ctrl) { - // Divide the delta if it's too high. This fixes the zoom with - // the mouse wheel. - if (delta_y <= -1) { - delta_y /= 10; - } - // Get the current zoom before zooming. - double old_zoom = canvas.get_scale (); - // Zoom in. - window.event_bus.adjust_zoom (delta_y * -1, false, null); - // Adjust zoom based on cursor position. - zoom_on_cursor (event, old_zoom); - } else if (is_shift) { - main_scroll.hadjustment.value += delta_y * 10; - } else { - main_scroll.vadjustment.value += delta_y * 10; - } - } else if (delta_y > SCROLL_DISTANCE) { - // Scroll DOWN. - if (is_ctrl) { - // Divide the delta if it's too high. This fixes the zoom with - // the mouse wheel. - if (delta_y >= 1) { - delta_y /= 10; - } - // Get the current zoom before zooming. - double old_zoom = canvas.get_scale (); - // Zoom out. - window.event_bus.adjust_zoom (-delta_y, false, null); - // Adjust zoom based on cursor position. - zoom_on_cursor (event, old_zoom); - } else if (is_shift) { - main_scroll.hadjustment.value += delta_y * 10; - } else { - main_scroll.vadjustment.value += delta_y * 10; - } - } - - if (delta_x < -SCROLL_DISTANCE) { - main_scroll.hadjustment.value += delta_x * 10; - } else if (delta_x > SCROLL_DISTANCE) { - main_scroll.hadjustment.value += delta_x * 10; - } - - return true; - } - - private void zoom_on_cursor (Gdk.EventScroll event, double old_zoom) { - // The regular zoom mode shifts the visible viewing area - // to center itself (it already has one translation applied) - // so you cannot just move the viewing area by the distance - // of the current mouse location and the new mouse location. - - // If you want to zoom to your mouse you need to find the - // difference between the distances of the current mouse location - // in the current view scale to the left view border and the new - // mouse location that has the new canvas scale applied to the - // new left view border and shift the view by that difference. - int width = main_scroll.get_allocated_width (); - int height = main_scroll.get_allocated_height (); - - var center_x = main_scroll.hadjustment.value + (width / 2); - var center_y = main_scroll.vadjustment.value + (height / 2); - - var old_center_x = (center_x / canvas.get_scale ()) * old_zoom; - var old_center_y = (center_y / canvas.get_scale ()) * old_zoom; - - var new_event_x = (event.x / old_zoom) * canvas.get_scale (); - var new_event_y = (event.y / old_zoom) * canvas.get_scale (); - - var old_hadjustment = old_center_x - (width / 2); - var old_vadjustment = old_center_y - (height / 2); - - main_scroll.hadjustment.value += - (new_event_x - main_scroll.hadjustment.value) - (event.x - old_hadjustment); - main_scroll.vadjustment.value += - (new_event_y - main_scroll.vadjustment.value) - (event.y - old_vadjustment); - } - - private async void on_exporting (string message) { - overlaybar = new Granite.Widgets.OverlayBar (main_overlay); - overlaybar.label = message; - overlaybar.active = true; - show_all (); - } - - private async void on_export_completed () { - main_overlay.remove (overlaybar); - overlaybar = null; - yield trigger_notification (_("Export completed!")); - } - - private async void trigger_notification (string message) { - notification.title = message; - notification.send_notification (); - } -} diff --git a/src/Layouts/MainViewCanvas.vala b/src/Layouts/MainViewCanvas.vala deleted file mode 100644 index 1f4b8feff..000000000 --- a/src/Layouts/MainViewCanvas.vala +++ /dev/null @@ -1,129 +0,0 @@ -/* -* Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -* Authored by: Giacomo "giacomoalbe" Alberini -*/ - -public class Akira.Layouts.MainViewCanvas : Gtk.Grid { - public const int CANVAS_SIZE = 100000; - public const double SCROLL_DISTANCE = 0; - - public Gtk.ScrolledWindow main_scroll; - - public Akira.Lib.ViewCanvas canvas; - - public weak Akira.Window window { get; construct; } - - private Gtk.Overlay main_overlay; - private Granite.Widgets.Toast notification; - - private double scroll_origin_x = 0; - private double scroll_origin_y = 0; - - public MainViewCanvas (Akira.Window window) { - Object (window: window, orientation: Gtk.Orientation.VERTICAL); - } - - construct { - get_style_context ().add_class ("main-canvas"); - - main_overlay = new Gtk.Overlay (); - notification = new Granite.Widgets.Toast (""); - - main_scroll = new Gtk.ScrolledWindow (null, null); - main_scroll.expand = true; - - // Overlay the scrollbars only if mouse pointer is inside canvas - main_scroll.overlay_scrolling = false; - - // Change visibility of canvas scrollbars - main_scroll.set_policy (Gtk.PolicyType.NEVER, Gtk.PolicyType.NEVER); - - canvas = new Akira.Lib.ViewCanvas (window); - canvas.set_bounds (Geometry.Rectangle.with_coordinates (0, 0, CANVAS_SIZE, CANVAS_SIZE)); - canvas.scale = 1.0; - - canvas.canvas_moved.connect ((event_x, event_y) => { - // Move scroll window according to normalized mouse delta - // relative to the scroll window, so with Canvas' pixel - // coordinates translated into ScrolledWindow's one. - double event_x_pixel_space = event_x; - double event_y_pixel_space = event_y; - - // Convert coordinates to pixel space, which does account for - // canvas scale and canvas translation. - // Otherwise, delta can start to "diverge" due to the - // translation of starting point happening during canvas translation - canvas.convert_to_pixels (ref event_x_pixel_space, ref event_y_pixel_space); - - var delta_x = event_x_pixel_space - scroll_origin_x; - var delta_y = event_y_pixel_space - scroll_origin_y; - - main_scroll.hadjustment.value -= delta_x; - main_scroll.vadjustment.value -= delta_y; - }); - - canvas.canvas_scroll_set_origin.connect ((origin_x, origin_y) => { - // Update scroll origin on Canvas' button_press_event - scroll_origin_x = origin_x; - scroll_origin_y = origin_y; - - canvas.convert_to_pixels (ref scroll_origin_x, ref scroll_origin_y); - }); - - canvas.scroll_event.connect (on_scroll); - - main_scroll.add (canvas); - - main_overlay.add (main_scroll); - main_overlay.add_overlay (notification); - - add (main_overlay); - } - - public bool on_scroll (Gdk.EventScroll event) { - double delta_x, delta_y; - event.get_scroll_deltas (out delta_x, out delta_y); - - if (canvas.ctrl_is_pressed) { - var norm_scale = canvas.scale / Lib.ViewCanvas.MAX_SCALE; - delta_y *= 1 - (1 - norm_scale) * (1 - norm_scale); - window.event_bus.adjust_zoom (-delta_y, false, Geometry.Point (event.x, event.y)); - return true; - } - - if (canvas.shift_is_pressed) { - main_scroll.hadjustment.value += delta_y * 10; - return true; - } - - main_scroll.hadjustment.value += delta_x * 10; - main_scroll.vadjustment.value += delta_y * 10; - return true; - } - - /** - * Pass a simple string message and trigger the Granite.Toast notification - * At the top of the Canvas. - */ - public void trigger_notification (string message) { - notification.title = message; - notification.send_notification (); - } -} diff --git a/src/Layouts/MainWindow.vala b/src/Layouts/MainWindow.vala deleted file mode 100644 index a4ea93e20..000000000 --- a/src/Layouts/MainWindow.vala +++ /dev/null @@ -1,103 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.Layouts.MainWindow : Gtk.Grid { - public weak Akira.Window window { get; construct; } - - public Akira.Layouts.MainViewCanvas main_view_canvas; - - private Layouts.Sidebars.LayersSidebar layers_sidebar; - private Layouts.Sidebars.OptionsSidebar options_sidebar; - - public Gtk.Paned pane; - public Gtk.Paned pane2; - - public MainWindow (Akira.Window window) { - Object (window: window); - } - - construct { - main_view_canvas = new Layouts.MainViewCanvas (window); - layers_sidebar = new Layouts.Sidebars.LayersSidebar (main_view_canvas.canvas); - options_sidebar = new Layouts.Sidebars.OptionsSidebar (main_view_canvas.canvas); - - pane = new Gtk.Paned (Gtk.Orientation.HORIZONTAL); - pane2 = new Gtk.Paned (Gtk.Orientation.HORIZONTAL); - pane.pack2 (pane2, true, false); - pane2.pack1 (main_view_canvas, true, true); - - if (!settings.get_boolean ("invert-sidebar")) { - pane.pack1 (options_sidebar, false, false); - pane2.pack2 (layers_sidebar, false, false); - } else { - pane.pack1 (layers_sidebar, false, false); - pane2.pack2 (options_sidebar, false, false); - } - - attach (pane, 0, 0, 1, 1); - } - - public void focus_canvas () { - main_view_canvas.canvas.focus_canvas (); - } - - /* - * Force the layers panel to show all its newly added children, only after - * all items have actually been created. - */ - public void show_added_layers (int added) { - layers_sidebar.layers_listbox.show_added_layers (added); - } - - /* - * Pass the list of nodes ids to be removed from the layers list. - */ - public void remove_layers (GLib.Array ids) { - layers_sidebar.layers_listbox.remove_items (ids); - } - - /* - * Pass the list of nodes ids to be added to the layers list. - */ - public void add_layers (GLib.Array ids) { - layers_sidebar.layers_listbox.add_items (ids); - } - - public void set_children_locked (int[] nodes, bool is_locked) { - layers_sidebar.layers_listbox.set_children_locked (nodes, is_locked); - } - - /* - * Regenerate the entire layers list. This is used during history navigation. - */ - public void regenerate_list (bool go_to_layer = false) { - layers_sidebar.layers_listbox.clear_list (); - layers_sidebar.layers_listbox.regenerate_list (go_to_layer); - } - - public void refresh_fills () { - options_sidebar.fills_panel.fills_listbox.refresh_list (); - } - - public void refresh_borders () { - options_sidebar.borders_panel.borders_listbox.refresh_list (); - } -} diff --git a/src/Layouts/Partials/BlendingModeItem.vala b/src/Layouts/Partials/BlendingModeItem.vala deleted file mode 100644 index 490d3990e..000000000 --- a/src/Layouts/Partials/BlendingModeItem.vala +++ /dev/null @@ -1,37 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Giacomo "giacomoalbe" Alberini -*/ - -public class Akira.Layouts.Partials.BlendingModeItem : Gtk.Label { - public Akira.Utils.BlendingMode mode { get; construct; } - - public BlendingModeItem (Akira.Utils.BlendingMode mode) { - Object ( - mode: mode - ); - } - - construct { - label = mode.get_name (); - halign = Gtk.Align.START; - - get_style_context ().add_class (Gtk.STYLE_CLASS_MENUITEM); - } -} diff --git a/src/Layouts/Partials/BorderItem.vala b/src/Layouts/Partials/BorderItem.vala deleted file mode 100644 index fdac3924a..000000000 --- a/src/Layouts/Partials/BorderItem.vala +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "alecaddd" Castellani - * Authored by: Ivan "isneezy" Vilanculo - */ - -public class Akira.Layouts.Partials.BorderItem : Gtk.Grid { - private unowned Akira.Window window; - private unowned Lib.Components.Border border; - - private Gtk.Button hidden_button; - private Gtk.Button delete_button; - private Gtk.Image hidden_button_icon; - - private bool hidden { - owned get { - return border.hidden; - } set { - border.hidden = value; - set_hidden_button (); - toggle_ui_visibility (); - } - } - - public signal void border_deleted (); - - public BorderItem (Akira.Window window, Lib.Components.Border border) { - this.window = window; - this.border = border; - - create_ui (); - hidden = border.hidden; - - create_event_bindings (); - show_all (); - } - - private void create_ui () { - margin_top = margin_bottom = 5; - - var fill_chooser = new Gtk.Grid (); - fill_chooser.hexpand = true; - fill_chooser.margin_end = 5; - - fill_chooser.add (new Widgets.ColorRow (window, new Models.ColorModel (null, border))); - - hidden_button = new Gtk.Button (); - hidden_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - hidden_button.get_style_context ().add_class ("button-rounded"); - hidden_button.can_focus = false; - hidden_button.valign = Gtk.Align.CENTER; - - delete_button = new Gtk.Button (); - delete_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - delete_button.get_style_context ().add_class ("button-rounded"); - delete_button.can_focus = false; - delete_button.valign = Gtk.Align.CENTER; - delete_button.set_tooltip_text (_("Remove border color")); - delete_button.add (new Gtk.Image.from_icon_name ("user-trash-symbolic", - Gtk.IconSize.SMALL_TOOLBAR)); - - attach (fill_chooser, 0, 0, 1, 1); - attach (hidden_button, 1, 0, 1, 1); - attach (delete_button, 2, 0, 1, 1); - } - - private void create_event_bindings () { - delete_button.clicked.connect (on_delete_item); - hidden_button.clicked.connect (toggle_visibility); - } - - private void on_delete_item () { - border.remove (); - border_deleted (); - } - - private void set_hidden_button () { - if (hidden_button_icon != null) { - hidden_button.remove (hidden_button_icon); - } - - hidden_button_icon = new Gtk.Image.from_icon_name ( - "layer-%s-symbolic".printf (hidden ? "hidden" : "visible"), - Gtk.IconSize.SMALL_TOOLBAR); - - hidden_button.add (hidden_button_icon); - hidden_button_icon.show_all (); - } - - private void toggle_visibility () { - hidden = !hidden; - toggle_ui_visibility (); - } - - private void toggle_ui_visibility () { - if (hidden) { - get_style_context ().add_class ("disabled"); - hidden_button.set_tooltip_text (_("Show border")); - return; - } - - hidden_button.set_tooltip_text (_("Hide border")); - get_style_context ().remove_class ("disabled"); - } -} diff --git a/src/Layouts/Partials/BorderRadiusPanel.vala b/src/Layouts/Partials/BorderRadiusPanel.vala deleted file mode 100644 index 6e55bc76a..000000000 --- a/src/Layouts/Partials/BorderRadiusPanel.vala +++ /dev/null @@ -1,362 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Bilal Elmoussaoui -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.Layouts.Partials.BorderRadiusPanel : Gtk.Grid { - public weak Akira.Window window { get; construct; } - - public Gtk.Label label; - private Gtk.Revealer options_revealer; - private Gtk.Grid options_grid; - private Gtk.Adjustment radius_adj; - private Gtk.Scale border_radius_scale; - private Widgets.InputField border_radius_entry; - private Gtk.ToggleButton options_button; - - private Widgets.InputField border_radius_bottom_left_entry; - private Widgets.InputField border_radius_bottom_right_entry; - private Widgets.InputField border_radius_top_left_entry; - private Widgets.InputField border_radius_top_right_entry; - - private Gtk.Switch autoscale_switch; - private Gtk.Switch uniform_switch; - private Binding radius_binding; - private Binding uniform_binding; - private Binding autoscale_binding; - private double max_value; - - private Akira.Lib.Items.CanvasRect _selected_item; - private Akira.Lib.Items.CanvasRect selected_item { - get { - return _selected_item; - } set { - // If the same item is already selected, or the value is still null - // we don't do anything to prevent redraw and calculations. - if (_selected_item == value) { - return; - } - disconnect_previous_item (); - _selected_item = value; - if (_selected_item == null || _selected_item.border_radius == null) { - disable (); - return; - } - enable (); - } - } - - public bool toggled { - get { - return visible; - } set { - visible = value; - no_show_all = !value; - } - } - - public BorderRadiusPanel (Akira.Window window) { - Object ( - window: window, - orientation: Gtk.Orientation.VERTICAL - ); - } - - construct { - var title_cont = new Gtk.Grid (); - title_cont.get_style_context ().add_class ("option-panel"); - - label = new Gtk.Label (_("Style")); - label.halign = Gtk.Align.FILL; - label.xalign = 0; - label.hexpand = true; - label.set_ellipsize (Pango.EllipsizeMode.END); - title_cont.attach (label, 0, 0, 1, 1); - - attach (title_cont, 0, 0, 1, 1); - - var panel_grid = new Gtk.Grid (); - get_style_context ().add_class ("style-panel"); - panel_grid.row_spacing = 6; - panel_grid.border_width = 12; - panel_grid.column_spacing = 6; - panel_grid.hexpand = true; - attach (panel_grid, 0, 1, 1, 1); - - var border_radius_label = new Gtk.Label (_("Border Radius")); - border_radius_label.get_style_context ().add_class ("group-title"); - border_radius_label.halign = Gtk.Align.START; - border_radius_label.hexpand = true; - border_radius_label.margin_bottom = 2; - panel_grid.attach (border_radius_label, 0, 1, 3, 1); - - radius_adj = new Gtk.Adjustment (0, 0, 1.0, 10.0, 0, 0); - border_radius_scale = new Gtk.Scale (Gtk.Orientation.HORIZONTAL, radius_adj); - border_radius_scale.digits = 0; - border_radius_scale.draw_value = false; - border_radius_scale.valign = Gtk.Align.CENTER; - border_radius_scale.halign = Gtk.Align.FILL; - border_radius_scale.hexpand = true; - panel_grid.attach (border_radius_scale, 0, 2, 1, 1); - - border_radius_entry = new Widgets.InputField ( - Widgets.InputField.Unit.PIXEL, 7, true, true); - border_radius_entry.entry.hexpand = false; - border_radius_entry.entry.width_request = 64; - border_radius_entry.valign = Gtk.Align.CENTER; - panel_grid.attach (border_radius_entry, 1, 2, 1, 1); - - border_radius_entry.entry.bind_property ( - "value", radius_adj, "value", - BindingFlags.BIDIRECTIONAL | BindingFlags.SYNC_CREATE); - - var options_image = new Gtk.Image.from_icon_name ("open-menu-symbolic", Gtk.IconSize.BUTTON); - options_button = new Gtk.ToggleButton (); - options_button.valign = Gtk.Align.CENTER; - options_button.halign = Gtk.Align.END; - options_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - options_button.add (options_image); - options_button.can_focus = false; - options_button.set_tooltip_text (_("Border radius options")); - panel_grid.attach (options_button, 2, 2, 1, 1); - - options_revealer = new Gtk.Revealer (); - options_revealer.transition_type = Gtk.RevealerTransitionType.NONE; - panel_grid.attach (options_revealer, 0, 3, 3, 1); - - options_grid = new Gtk.Grid (); - options_grid.border_width = 12; - options_grid.hexpand = true; - - var border_entries_grid = new Gtk.Grid (); - border_entries_grid.row_spacing = 12; - border_entries_grid.border_width = 12; - border_entries_grid.column_spacing = 12; - border_entries_grid.hexpand = true; - - border_radius_top_left_entry = new Widgets.InputField ( - Widgets.InputField.Unit.PIXEL, 7, true, true); - border_radius_top_left_entry.entry.hexpand = false; - border_radius_top_left_entry.entry.width_request = 64; - border_radius_top_left_entry.valign = Gtk.Align.CENTER; - border_radius_top_left_entry.halign = Gtk.Align.START; - border_entries_grid.attach (border_radius_top_left_entry, 0, 0, 1, 1); - - border_radius_top_right_entry = new Widgets.InputField ( - Widgets.InputField.Unit.PIXEL, 7, true, true); - border_radius_top_right_entry.entry.hexpand = false; - border_radius_top_right_entry.entry.width_request = 64; - border_radius_top_right_entry.valign = Gtk.Align.CENTER; - border_radius_top_right_entry.halign = Gtk.Align.END; - border_entries_grid.attach (border_radius_top_right_entry, 1, 0, 1, 1); - - border_radius_bottom_left_entry = new Widgets.InputField ( - Widgets.InputField.Unit.PIXEL, 7, true, true); - border_radius_bottom_left_entry.entry.hexpand = false; - border_radius_bottom_left_entry.entry.width_request = 64; - border_radius_bottom_left_entry.valign = Gtk.Align.CENTER; - border_radius_bottom_left_entry.halign = Gtk.Align.START; - border_entries_grid.attach (border_radius_bottom_left_entry, 0, 1, 1, 1); - - border_radius_bottom_right_entry = new Widgets.InputField ( - Widgets.InputField.Unit.PIXEL, 7, true, true); - border_radius_bottom_right_entry.entry.hexpand = false; - border_radius_bottom_right_entry.entry.width_request = 64; - border_radius_bottom_right_entry.valign = Gtk.Align.CENTER; - border_radius_bottom_right_entry.halign = Gtk.Align.END; - border_entries_grid.attach (border_radius_bottom_right_entry, 1, 1, 1, 1); - - options_grid.attach (border_entries_grid, 0, 0, 1, 1); - options_revealer.add (options_grid); - - var border_options_grid = new Gtk.Grid (); - border_options_grid.row_spacing = 6; - border_options_grid.border_width = 12; - border_options_grid.column_spacing = 6; - border_options_grid.hexpand = true; - - autoscale_switch = new Gtk.Switch (); - autoscale_switch.valign = Gtk.Align.CENTER; - autoscale_switch.halign = Gtk.Align.START; - border_options_grid.attach (autoscale_switch, 0, 0, 1, 1); - var autoscale_label = new Gtk.Label (_("Autoscale Corners")); - autoscale_label.valign = Gtk.Align.CENTER; - autoscale_label.halign = Gtk.Align.START; - border_options_grid.attach (autoscale_label, 1, 0, 1, 1); - - uniform_switch = new Gtk.Switch (); - uniform_switch.valign = Gtk.Align.CENTER; - uniform_switch.halign = Gtk.Align.START; - border_options_grid.attach (uniform_switch, 0, 1, 1, 1); - var uniform_label = new Gtk.Label (_("Uniform Corners")); - uniform_label.valign = Gtk.Align.CENTER; - uniform_label.halign = Gtk.Align.START; - border_options_grid.attach (uniform_label, 1, 1, 1, 1); - options_grid.attach (border_options_grid, 0, 1, 1, 1); - show_all (); - - bind_signals (); - } - - private void bind_signals () { - toggled = false; - window.event_bus.selected_items_list_changed.connect (on_selected_items_list_changed); - options_button.toggled.connect (() => { - options_revealer.reveal_child = !options_revealer.child_revealed; - window.event_bus.request_widget_redraw (); - }); - - uniform_switch.notify["active"].connect (() => { - update_all_borders (uniform_switch.active); - }); - - // border_radius_top_left_entry.entry.changed.connect (on_radius_change); - // border_radius_top_right_entry.entry.changed.connect (on_radius_change); - // border_radius_bottom_right_entry.entry.changed.connect (on_radius_change); - // border_radius_bottom_left_entry.entry.changed.connect (on_radius_change); - } - - private void on_selected_items_list_changed (List selected_items) { - // Interrupt if we don't have an item selected or if more than 1 is selected - // since we can't handle the border radius of multiple items at once. - if (selected_items.length () == 0 || selected_items.length () > 1) { - selected_item = null; - toggled = false; - return; - } - - if (!(selected_items.nth_data (0) is Akira.Lib.Items.CanvasRect)) { - selected_item = null; - toggled = false; - return; - } - - if (selected_item == null || selected_item != selected_items.nth_data (0)) { - toggled = true; - selected_item = (Akira.Lib.Items.CanvasRect) selected_items.nth_data (0); - } - } - - private void on_size_change () { - var max_size = double.min (selected_item.width, selected_item.height); - max_value = Math.round (max_size / 2); - radius_adj.upper = max_value; - border_radius_entry.set_range (0, max_value); - - if (!selected_item.border_radius.autoscale) { - return; - } - - // Calculate the radius percentage and update the value on shape resize. - var percentage = Math.round (border_radius_scale.get_value () / max_size * 100); - border_radius_scale.set_value (Math.round (percentage * max_size / 100)); - } - - private void enable () { - on_size_change (); - - uniform_switch.active = selected_item.border_radius.uniform; - autoscale_switch.active = selected_item.border_radius.autoscale; - - // Uniform radius - if (selected_item.border_radius.uniform) { - radius_adj.value = selected_item.border_radius.x; - } - update_all_borders (selected_item.border_radius.uniform); - - // Non-Uniform radius - // if (!selected_item.border_radius.uniform) { - // border_radius_top_left_entry.entry.text = selected_item.radius_tl; - // border_radius_top_right_entry.entry.text = selected_item.radius_tr; - // border_radius_bottom_right_entry.entry.text = selected_item.radius_br; - // border_radius_bottom_left_entry.entry.text = selected_item.radius_bl; - // } - - radius_binding = radius_adj.bind_property ( - "value", selected_item.border_radius, "x", - BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL); - - uniform_binding = uniform_switch.bind_property ( - "active", selected_item.border_radius, "uniform"); - autoscale_binding = autoscale_switch.bind_property ( - "active", selected_item.border_radius, "autoscale"); - - selected_item.notify["width"].connect (on_size_change); - selected_item.notify["height"].connect (on_size_change); - } - - private void disconnect_previous_item () { - // Disconnect the model binding if an item was previously stored. - // This is necessary to prevent GObject Critical errors. - if (selected_item != null) { - selected_item.notify["width"].disconnect (on_size_change); - selected_item.notify["height"].disconnect (on_size_change); - } - } - - private void update_all_borders (bool switch_active) { - border_radius_scale.sensitive = switch_active; - border_radius_entry.entry.sensitive = switch_active; - - border_radius_bottom_left_entry.entry.sensitive = !switch_active; - border_radius_bottom_right_entry.entry.sensitive = !switch_active; - border_radius_top_left_entry.entry.sensitive = !switch_active; - border_radius_top_right_entry.entry.sensitive = !switch_active; - - string border_value = !switch_active ? - ((int)border_radius_scale.get_value ()).to_string () : - ""; - border_radius_bottom_left_entry.entry.text = border_value; - border_radius_bottom_right_entry.entry.text = border_value; - border_radius_top_left_entry.entry.text = border_value; - border_radius_top_right_entry.entry.text = border_value; - } - - private void disable () { - // border_radius_top_left_entry.entry.changed.disconnect (on_radius_change); - // border_radius_top_right_entry.entry.changed.disconnect (on_radius_change); - // border_radius_bottom_right_entry.entry.changed.disconnect (on_radius_change); - // border_radius_bottom_left_entry.entry.changed.disconnect (on_radius_change); - - radius_binding.unbind (); - uniform_binding.unbind (); - autoscale_binding.unbind (); - - autoscale_switch.active = false; - uniform_switch.active = false; - - border_radius_scale.set_value (0); - - border_radius_entry.entry.text = ""; - border_radius_entry.entry.sensitive = false; - - border_radius_top_left_entry.entry.text = ""; - border_radius_top_left_entry.entry.sensitive = false; - - border_radius_top_right_entry.entry.text = ""; - border_radius_top_right_entry.entry.sensitive = false; - - border_radius_bottom_left_entry.entry.text = ""; - border_radius_bottom_left_entry.entry.sensitive = false; - - border_radius_bottom_right_entry.entry.text = ""; - border_radius_bottom_right_entry.entry.sensitive = false; - } -} diff --git a/src/Layouts/Partials/BordersPanel.vala b/src/Layouts/Partials/BordersPanel.vala deleted file mode 100644 index e193668b4..000000000 --- a/src/Layouts/Partials/BordersPanel.vala +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "alecaddd" Castellani - */ - -public class Akira.Layouts.Partials.BordersPanel : Gtk.Grid { - private unowned Akira.Window window; - - public Gtk.Button add_btn; - public Gtk.ListBox borders_list_container; - private GLib.ListStore list; - private unowned List? items; - - public bool toggled { - get { - return visible; - } set { - visible = value; - no_show_all = !value; - } - } - - public BordersPanel (Akira.Window window) { - this.window = window; - - var title_cont = new Gtk.Grid (); - title_cont.orientation = Gtk.Orientation.HORIZONTAL; - title_cont.hexpand = true; - title_cont.get_style_context ().add_class ("option-panel"); - - var label = new Gtk.Label (_("Borders")); - label.halign = Gtk.Align.FILL; - label.xalign = 0; - label.hexpand = true; - label.set_ellipsize (Pango.EllipsizeMode.END); - - add_btn = new Gtk.Button (); - add_btn.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - add_btn.can_focus = false; - add_btn.valign = Gtk.Align.CENTER; - add_btn.halign = Gtk.Align.CENTER; - add_btn.set_tooltip_text (_("Add border")); - add_btn.add (new Gtk.Image.from_icon_name ("list-add-symbolic", Gtk.IconSize.SMALL_TOOLBAR)); - - title_cont.attach (label, 0, 0, 1, 1); - title_cont.attach (add_btn, 1, 0, 1, 1); - - list = new GLib.ListStore (typeof (Lib.Components.Border)); - - borders_list_container = new Gtk.ListBox (); - borders_list_container.margin_top = 5; - borders_list_container.margin_bottom = 15; - borders_list_container.margin_start = 10; - borders_list_container.margin_end = 5; - borders_list_container.selection_mode = Gtk.SelectionMode.NONE; - borders_list_container.get_style_context ().add_class ("fills-list"); - - borders_list_container.bind_model (list, item => { - var border_items = new Layouts.Partials.BorderItem (window, (Lib.Components.Border) item); - border_items.border_deleted.connect (() => { - reload_list (items); - }); - return border_items; - }); - - attach (title_cont, 0, 0, 1, 1); - attach (borders_list_container, 0, 1, 1, 1); - show_all (); - - create_event_bindings (); - } - - private void create_event_bindings () { - toggled = false; - window.event_bus.selected_items_list_changed.connect (reload_list); - - add_btn.clicked.connect (() => { - var border_color = Gdk.RGBA (); - border_color.parse (settings.border_color); - - foreach (Lib.Items.CanvasItem item in items) { - list.insert (0, item.borders.add_border_color (border_color, (int) settings.border_size)); - } - }); - - // Listen to the model changes when adding/removing items. - list.items_changed.connect ((position, removed, added) => { - window.main_window.left_sidebar.queue_resize (); - }); - } - - private void reload_list (List selected_items) { - // Always clear the list model when a selection changes. - list.remove_all (); - - if (selected_items.length () == 0) { - items = null; - toggled = false; - return; - } - - items = selected_items; - - bool show = false; - foreach (Lib.Items.CanvasItem item in selected_items) { - // Skip items that don't have a border item since there will be nothing to show. - if (item.borders == null) { - continue; - } - - // At least an item has the borders component, so we can show the - show = true; - - // Loops through all the available borders and add them tot he list model. - // TODO: handle duplicate identical colors. - foreach (Lib.Components.Border border in item.borders.borders) { - list.insert (0, border); - } - } - - toggled = show; - } -} diff --git a/src/Layouts/Partials/FillsPanel.vala b/src/Layouts/Partials/FillsPanel.vala deleted file mode 100644 index f05344aea..000000000 --- a/src/Layouts/Partials/FillsPanel.vala +++ /dev/null @@ -1,140 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Giacomo "giacomoalbe" Alberini - * Authored by: Alessandro "alecaddd" Castellani - */ - -public class Akira.Layouts.Partials.FillsPanel : Gtk.Grid { - private unowned Akira.Window window; - - private Gtk.Button add_btn; - private Gtk.ListBox fills_list_container; - private GLib.ListStore list; - private unowned List? items; - - public bool toggled { - get { - return visible; - } set { - visible = value; - no_show_all = !value; - } - } - - public FillsPanel (Akira.Window window) { - this.window = window; - - var title_cont = new Gtk.Grid (); - title_cont.orientation = Gtk.Orientation.HORIZONTAL; - title_cont.hexpand = true; - title_cont.get_style_context ().add_class ("option-panel"); - - var label = new Gtk.Label (_("Fills")); - label.halign = Gtk.Align.FILL; - label.xalign = 0; - label.hexpand = true; - label.set_ellipsize (Pango.EllipsizeMode.END); - - add_btn = new Gtk.Button (); - add_btn.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - add_btn.can_focus = false; - add_btn.valign = Gtk.Align.CENTER; - add_btn.halign = Gtk.Align.CENTER; - add_btn.set_tooltip_text (_("Add fill color")); - add_btn.add (new Gtk.Image.from_icon_name ("list-add-symbolic", Gtk.IconSize.SMALL_TOOLBAR)); - - title_cont.attach (label, 0, 0, 1, 1); - title_cont.attach (add_btn, 1, 0, 1, 1); - - list = new GLib.ListStore (typeof (Lib.Components.Fill)); - - fills_list_container = new Gtk.ListBox (); - fills_list_container.margin_top = 5; - fills_list_container.margin_bottom = 15; - fills_list_container.margin_start = 10; - fills_list_container.margin_end = 5; - fills_list_container.selection_mode = Gtk.SelectionMode.NONE; - fills_list_container.get_style_context ().add_class ("fills-list"); - - fills_list_container.bind_model (list, item => { - var fill_item = new Layouts.Partials.FillItem (window, (Lib.Components.Fill) item); - fill_item.fill_deleted.connect (() => { - reload_list (items); - }); - return fill_item; - }); - - attach (title_cont, 0, 0, 1, 1); - attach (fills_list_container, 0, 1, 1, 1); - show_all (); - - create_event_bindings (); - } - - private void create_event_bindings () { - toggled = false; - window.event_bus.selected_items_list_changed.connect (reload_list); - - add_btn.clicked.connect (() => { - var fill_color = Gdk.RGBA (); - fill_color.parse (settings.fill_color); - - foreach (Lib.Items.CanvasItem item in items) { - list.insert (0, item.fills.add_fill_color (fill_color)); - } - }); - - // Listen to the model changes when adding or removing items. - list.items_changed.connect ((position, removed, added) => { - window.main_window.left_sidebar.queue_resize (); - }); - } - - private void reload_list (List selected_items) { - // Always clear the list model when a selection changes. - list.remove_all (); - - if (selected_items.length () == 0) { - items = null; - toggled = false; - return; - } - - items = selected_items; - - bool show = false; - foreach (Lib.Items.CanvasItem item in selected_items) { - // Skip items that don't have a fill item since there will be nothing to show. - if (item.fills == null) { - continue; - } - - // At least an item has the fills component, so we can show the - show = true; - - // Loops through all the available fills and add them tot he list model. - // TODO: handle duplicate identical colors. - foreach (Lib.Components.Fill fill in item.fills.fills) { - list.insert (0, fill); - } - } - - toggled = show; - } -} diff --git a/src/Layouts/Partials/PagesPanel.vala b/src/Layouts/Partials/PagesPanel.vala deleted file mode 100644 index 488cff008..000000000 --- a/src/Layouts/Partials/PagesPanel.vala +++ /dev/null @@ -1,49 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.Layouts.Partials.PagesPanel : Gtk.ListBox { - public weak Akira.Window window { get; construct; } - - // private bool scroll_up = false; - // private bool scrolling = false; - // private bool should_scroll = false; - // public Gtk.Adjustment vadjustment; - - // private const int SCROLL_STEP_SIZE = 5; - // private const int SCROLL_DISTANCE = 30; - // private const int SCROLL_DELAY = 50; - - private const Gtk.TargetEntry TARGET_ENTRIES[] = { - { "PAGES", Gtk.TargetFlags.SAME_APP, 0 } - }; - - public PagesPanel (Akira.Window window) { - Object ( - window: window, - activate_on_single_click: false, - selection_mode: Gtk.SelectionMode.SINGLE - ); - } - - construct { - expand = true; - } -} diff --git a/src/Layouts/Sidebars/LayersSidebar.vala b/src/Layouts/Sidebars/LayersSidebar.vala deleted file mode 100644 index a35a9941d..000000000 --- a/src/Layouts/Sidebars/LayersSidebar.vala +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Layout component containing the layers and pages containers. - */ -public class Akira.Layouts.Sidebars.LayersSidebar : Gtk.Grid { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - /* - * Boolean attribute to show/hide the layers sidebar when requested for the - * presentation mode option byt the user. - */ - private bool toggled { - get { - return visible; - } - set { - visible = value; - no_show_all = !value; - - if (value) { - layers_listbox.regenerate_list (true); - } else { - layers_listbox.clear_list (); - } - } - } - - // Drag and Drop properties. - private Gtk.Revealer motion_revealer; - private Gtk.TargetList drop_targets; - private const Gtk.TargetEntry TARGET_ENTRIES[] = { - { "ARTBOARD", Gtk.TargetFlags.SAME_APP, 0 }, - { "LAYER", Gtk.TargetFlags.SAME_APP, 0 } - }; - - public Layouts.LayersList.LayerListBox layers_listbox; - public Gtk.ScrolledWindow layers_scroll; - - public LayersSidebar (Lib.ViewCanvas canvas) { - Object ( - view_canvas: canvas - ); - } - - construct { - get_style_context ().add_class ("sidebar-r"); - width_request = 220; - - drop_targets = new Gtk.TargetList (TARGET_ENTRIES); - - var pane = new Gtk.Paned (Gtk.Orientation.VERTICAL); - pane.expand = true; - pane.wide_handle = false; - pane.position = 600; - - layers_listbox = new Layouts.LayersList.LayerListBox (view_canvas); - - layers_scroll = new Gtk.ScrolledWindow (null, null) { - hscrollbar_policy = Gtk.PolicyType.NEVER, - width_request = 158, - expand = true - }; - layers_scroll.add (layers_listbox); - - // Motion revealer for Drag and Drop on the top search bar. - var motion_grid = new Gtk.Grid (); - motion_grid.get_style_context ().add_class ("grid-motion"); - motion_grid.height_request = 2; - - motion_revealer = new Gtk.Revealer (); - motion_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN; - motion_revealer.add (motion_grid); - - var top_panel = new Gtk.Grid (); - top_panel.attach (build_search_bar (), 0, 0, 1, 1); - top_panel.attach (motion_revealer, 0, 1, 1, 1); - top_panel.attach (layers_scroll, 0, 2, 1, 1); - - pane.pack1 (top_panel, false, false); - - attach (pane, 0 , 0 , 1, 1); - - // Connect signals. - view_canvas.window.event_bus.toggle_presentation_mode.connect (toggle); - } - - private Gtk.Grid build_search_bar () { - var search = new Gtk.SearchEntry (); - search.hexpand = true; - search.margin = 5; - search.placeholder_text = _("Search Layers"); - - search.focus_in_event.connect (handle_focus_in); - search.focus_out_event.connect (handle_focus_out); - - var search_grid = new Gtk.Grid (); - search_grid.get_style_context ().add_class ("border-bottom"); - search_grid.add (search); - - return search_grid; - } - - private bool handle_focus_in (Gdk.EventFocus event) { - view_canvas.window.event_bus.disconnect_typing_accel (); - return false; - } - - private bool handle_focus_out (Gdk.EventFocus event) { - view_canvas.window.event_bus.connect_typing_accel (); - return false; - } - - /* - * Toggle the visibility of the entire panel. - */ - private void toggle () { - toggled = !toggled; - } -} diff --git a/src/Layouts/Sidebars/OptionsSidebar.vala b/src/Layouts/Sidebars/OptionsSidebar.vala deleted file mode 100644 index 182da60ca..000000000 --- a/src/Layouts/Sidebars/OptionsSidebar.vala +++ /dev/null @@ -1,72 +0,0 @@ -/* -* Copyright (c) 2021 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Giacomo "giacomoalbe" Alberini -*/ - -public class Akira.Layouts.Sidebars.OptionsSidebar : Gtk.Grid { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - public Layouts.FillsList.FillsPanel fills_panel; - public Layouts.BordersList.BordersPanel borders_panel; - - public bool toggled { - get { - return visible; - } set { - visible = value; - no_show_all = !value; - } - } - - public OptionsSidebar (Lib.ViewCanvas view_canvas) { - Object ( - view_canvas: view_canvas - ); - } - - construct { - get_style_context ().add_class ("sidebar-l"); - - // The alignment panel is the only widget that doesn't scroll. - attach (new Layouts.Alignment.AlignmentPanel (view_canvas), 0, 0); - - var main_scroll = new Gtk.ScrolledWindow (null, null) { - hscrollbar_policy = Gtk.PolicyType.NEVER, - expand = true - }; - - fills_panel = new Layouts.FillsList.FillsPanel (view_canvas); - borders_panel = new Layouts.BordersList.BordersPanel (view_canvas); - - var main_grid = new Gtk.Grid (); - main_grid.attach (new Layouts.Transforms.TransformPanel (view_canvas), 0, 0); - main_grid.attach (fills_panel, 0, 1); - main_grid.attach (borders_panel, 0, 2); - - main_scroll.add (main_grid); - attach (main_scroll, 0, 1); - - // Connect signals. - view_canvas.window.event_bus.toggle_presentation_mode.connect (toggle); - } - - private void toggle () { - toggled = !toggled; - } -} diff --git a/src/Layouts/Transforms/TransformPanel.vala b/src/Layouts/Transforms/TransformPanel.vala deleted file mode 100644 index 8fd212419..000000000 --- a/src/Layouts/Transforms/TransformPanel.vala +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Layout component containing the input fields representing the transformation - * matrix of the selected items. - */ -public class Akira.Layouts.Transforms.TransformPanel : Gtk.Grid { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - public Widgets.LinkedInput x_input; - public Widgets.LinkedInput y_input; - - public Widgets.LinkedInput width_input; - public Widgets.LinkedInput height_input; - - public Widgets.LinkedInput rotation_input; - - public TransformPanel (Lib.ViewCanvas canvas) { - Object (view_canvas: canvas); - - border_width = 12; - row_spacing = column_spacing = 6; - hexpand = true; - - var lock_image = new Gtk.Image.from_icon_name ("changes-allow-symbolic", Gtk.IconSize.BUTTON); - var lock_button = new Gtk.ToggleButton () { - tooltip_text = _("Lock Ratio"), - image = lock_image, - can_focus = false, - sensitive = false - }; - lock_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - lock_button.get_style_context ().add_class ("label-colors"); - - var hflip_button = new Gtk.ToggleButton () { - hexpand = false, - can_focus = false, - sensitive = false, - halign = valign = Gtk.Align.CENTER, - tooltip_markup = Granite.markup_accel_tooltip ({"bracketleft"}, _("Flip Horizontally")) - }; - hflip_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - hflip_button.add (new Widgets.ButtonImage ("object-flip-horizontal")); - - var vflip_button = new Gtk.ToggleButton () { - hexpand = false, - can_focus = false, - sensitive = false, - halign = valign = Gtk.Align.CENTER, - tooltip_markup = Granite.markup_accel_tooltip ({"bracketright"}, _("Flip Vertically")) - }; - vflip_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - vflip_button.add (new Widgets.ButtonImage ("object-flip-vertical")); - - var align_grid = new Gtk.Grid (); - align_grid.hexpand = true; - align_grid.column_homogeneous = true; - align_grid.attach (hflip_button, 0, 0, 1, 1); - align_grid.attach (vflip_button, 1, 0, 1, 1); - - var scale = new Gtk.Scale ( - Gtk.Orientation.HORIZONTAL, - new Gtk.Adjustment (100.0, 0, 100.0, 0, 0, 0) - ) { - hexpand = true, - sensitive = false, - draw_value = false, - digits = 0, - margin_end = 20 - }; - - var opacity_entry = new Widgets.InputField ( - view_canvas, Widgets.InputField.Unit.PERCENTAGE, 7, true, true); - opacity_entry.entry.hexpand = false; - opacity_entry.entry.width_request = 64; - - var opacity_grid = new Gtk.Grid (); - opacity_grid.hexpand = true; - opacity_grid.attach (scale, 0, 0, 1); - opacity_grid.attach (opacity_entry, 1, 0, 1); - - attach (group_title (_("Position")), 0, 0, 3); - - x_input = new Widgets.LinkedInput (view_canvas, _("X"), _("Horizontal position")); - attach (x_input, 0, 1, 1); - - y_input = new Widgets.LinkedInput (view_canvas, _("Y"), _("Vertical position")); - attach (y_input, 2, 1, 1); - - attach (separator (), 0, 2, 3); - - attach (group_title (_("Size")), 0, 3, 3); - width_input = new Widgets.LinkedInput (view_canvas, _("W"), _("Width")); - attach (width_input, 0, 4, 1); - - attach (lock_button, 1, 4, 1); - - height_input = new Widgets.LinkedInput (view_canvas, _("H"), _("Height")); - attach (height_input, 2, 4, 1); - - attach (separator (), 0, 5, 3); - - attach (group_title (_("Transform")), 0, 6, 3); - - rotation_input = new Widgets.LinkedInput (view_canvas, _("R"), _("Rotation degrees"), Widgets.InputField.Unit.DEGREES); - attach (rotation_input, 0, 7, 1); - - attach (align_grid, 2, 7, 1); - attach (separator (), 0, 8, 3); - attach (group_title (_("Opacity")), 0, 9, 3); - attach (opacity_grid, 0, 10, 3); - - view_canvas.window.event_bus.selection_geometry_modified.connect (on_selection_geometry_modified); - } - - private Gtk.Label group_title (string title) { - var title_label = new Gtk.Label (title) { - halign = Gtk.Align.START, - hexpand = true, - margin_bottom = 2 - }; - title_label.get_style_context ().add_class ("group-title"); - - return title_label; - } - - private Gtk.Separator separator () { - var sep = new Gtk.Separator (Gtk.Orientation.HORIZONTAL) { - margin_bottom = 6 - }; - sep.get_style_context ().add_class ("panel-separator"); - - return sep; - } - - private void on_selection_geometry_modified () { - unowned var sm = view_canvas.selection_manager; - if (sm.selection == null || sm.selection.is_empty ()) { - x_input.input_field.entry.set_value (0); - y_input.input_field.entry.set_value (0); - width_input.input_field.entry.set_value (0); - height_input.input_field.entry.set_value (0); - rotation_input.input_field.entry.set_value (0); - return; - } - - var quad = sm.selection.area (). quad (); - - x_input.input_field.entry.set_value (quad.tl_x); - y_input.input_field.entry.set_value (quad.tl_y); - width_input.input_field.entry.set_value (quad.width); - height_input.input_field.entry.set_value (quad.height); - - double rot = Utils.GeometryMath.matrix_rotation_component (quad.transformation) * 180 / Math.PI; - rotation_input.input_field.entry.set_value (rot); - } -} diff --git a/src/Lib/Components/BorderRadius.vala b/src/Lib/Components/BorderRadius.vala deleted file mode 100644 index 2b8dd246d..000000000 --- a/src/Lib/Components/BorderRadius.vala +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.BorderRadius : Component, Copyable { - private int _x; - private int _y; - private bool _autoscale; - private bool _uniform; - - public BorderRadius (int x, int y, bool autoscale, bool uniform) { - _x = x; - _y = y; - _autoscale = autoscale; - _uniform = uniform; - - if (_uniform) { - _x = _y; - } - } - - public BorderRadius.deserialized (Json.Object obj) { - _x = (int)obj.get_int_member ("x"); - _y = (int)obj.get_int_member ("y"); - _autoscale = obj.get_boolean_member ("autoscale"); - _uniform = obj.get_boolean_member ("uniform"); - } - - public override void serialize_details (ref Json.Object obj) { - obj.set_int_member ("x", _x); - obj.set_int_member ("y", _y); - obj.set_boolean_member ("autoscale", _autoscale); - obj.set_boolean_member ("uniform", _uniform); - } - - public BorderRadius copy () { - return new BorderRadius (_x, _y, _autoscale, _uniform); - } - - // Recommended accessors - - public int x () { return _x; } - public int y () { return _x; } - public bool autoscale () { return _autoscale; } - public bool uniform () { return _uniform; } - - // Mutators - - public BorderRadius with_x (int new_x) { - return new BorderRadius (_x, _y, _autoscale, _uniform); - } - - public BorderRadius with_y (int new_y) { - return new BorderRadius (_x, new_y, _autoscale, _uniform); - } - - public BorderRadius with_autoscale (bool new_autoscale) { - return new BorderRadius (_x, _y, new_autoscale, _uniform); - } - - public BorderRadius with_uniform (bool new_uniform) { - return new BorderRadius (_x, _y, _autoscale, new_uniform); - } -} diff --git a/src/Lib/Components/Borders.vala b/src/Lib/Components/Borders.vala deleted file mode 100644 index 4e99e4b3a..000000000 --- a/src/Lib/Components/Borders.vala +++ /dev/null @@ -1,193 +0,0 @@ -/** - * Copyright (c) 2019-2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.Borders : Component, Copyable { - public struct Border { - public int _id; - public Color _color; - public double _size; - - public Border (int id = -1, Color color = Color (), double? size = null) { - _id = id; - _color = color; - _size = size != null ? size : settings.border_size; - } - - public Border.deserialized (int id, Json.Object obj) { - _id = id; - _color = Color.deserialized (obj.get_object_member ("color")); - _size = (double)obj.get_int_member ("size"); - } - - public Json.Node serialize () { - var obj = new Json.Object (); - obj.set_int_member ("id", _id); - obj.set_member ("color", _color.serialize ()); - obj.set_double_member ("size", _size); - var node = new Json.Node (Json.NodeType.OBJECT); - node.set_object (obj); - return node; - } - - // Recommended accessors. - public int id { - get { - return _id; - } - } - public Gdk.RGBA color { - get { - return _color.rgba; - } - } - public bool hidden { - get { - return _color.hidden; - } - } - public double size { - get { - return _size; - } - } - - // Mutators. - public Border with_color (Color new_color) { - return Border (_id, new_color, _size); - } - - public Border with_size (double new_size) { - return Border (_id, _color, new_size); - } - } - - public Border[] data; - - public Borders () { - data = new Border[0]; - } - - public Borders.single_color (Color color, int size) { - data = new Border[1]; - data[0] = Border (0, color, size); - } - - public Borders.deserialized (Json.Object obj) { - var arr = obj.get_array_member ("border_data").get_elements (); - data = new Border[0]; - - var idx = 0; - foreach (unowned var border in arr) { - data.resize (data.length + 1); - data[idx] = Border.deserialized (idx, border.get_object ()); - ++idx; - } - } - - protected override void serialize_details (ref Json.Object obj) { - var array = new Json.Array (); - - foreach (unowned var d in data) { - array.add_element (d.serialize ()); - } - - var node = new Json.Node (Json.NodeType.ARRAY); - node.set_array (array); - obj.set_member ("border_data", node); - } - - public Borders copy () { - var cln = new Borders (); - cln.data = data; - return cln; - } - - // Recommended accessors. - public Border? border_from_id (int id) { - foreach (unowned var border in data) { - if (border.id == id) { - return border.with_color (border._color); - } - } - return null; - } - - public bool replace (Border border) { - for (var i = 0; i < data.length; ++i) { - if (data[i].id == border.id) { - data[i] = border; - return true; - } - } - return false; - } - - /* - * Create a new Border with the passed color and add it to the data structure. - * It's up to the code requiring this to then replace the borders component. - */ - public void append_border_with_color (Color color, double? size = null) { - int latest_id = int.MIN; - foreach (unowned var border in data) { - latest_id = int.max (latest_id, border.id); - } - latest_id++; - var border = Border ((int) latest_id, color, size); - data.resize (data.length + 1); - data[data.length - 1] = border; - } - - public int remove (uint id) { - var ct = 0; - foreach (unowned var border in data) { - if (border.id == id) { - return remove_at (ct) ? 1 : -1; - } - ++ct; - } - return -1; - } - - private bool remove_at (int pos) { - if (pos >= data.length || pos < 0) { - assert (false); - return false; - } - - data.move (pos + 1, pos, data.length - pos - 1); - data.resize (data.length - 1); - return true; - } - - /* - * Helper method used to retrieve the size of the thickest visible border. - */ - public double get_border_width () { - double size = 0; - foreach (unowned var border in data) { - if (border.hidden) { - continue; - } - size = double.max (size, border.size); - } - return size; - } -} diff --git a/src/Lib/Components/Color.vala b/src/Lib/Components/Color.vala deleted file mode 100644 index 2205c055d..000000000 --- a/src/Lib/Components/Color.vala +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public struct Akira.Lib.Components.Color { - public Gdk.RGBA rgba; - public bool hidden; - - public Color (double r = 0.0, double g = 0.0, double b = 0.0, double a = 1.0, bool hidden = false) { - rgba = Gdk.RGBA () { red = r, green = g, blue = b, alpha = a }; - } - - public Color.from_rgba (Gdk.RGBA rgba, bool hidden = false) { - this.rgba = rgba; - this.hidden = hidden; - } - - public Color.deserialized (Json.Object obj) { - var r = obj.get_double_member ("r"); - var g = obj.get_double_member ("g"); - var b = obj.get_double_member ("b"); - var a = obj.get_double_member ("a"); - rgba = Gdk.RGBA () { red = r, green = g, blue = b, alpha = a }; - hidden = obj.get_boolean_member ("hidden"); - } - - public Json.Node serialize () { - var obj = new Json.Object (); - obj.set_double_member ("r", rgba.red); - obj.set_double_member ("g", rgba.green); - obj.set_double_member ("b", rgba.blue); - obj.set_double_member ("a", rgba.alpha); - obj.set_boolean_member ("hidden", hidden); - var node = new Json.Node (Json.NodeType.OBJECT); - node.set_object (obj); - return node; - } - - // Mutators - public Color with_hidden (bool hidden) { - return Color (rgba.red, rgba.green, rgba.blue, rgba.alpha, hidden); - } -} diff --git a/src/Lib/Components/CompiledBorder.vala b/src/Lib/Components/CompiledBorder.vala deleted file mode 100644 index 0e788faae..000000000 --- a/src/Lib/Components/CompiledBorder.vala +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.CompiledBorder : Copyable { - private Gdk.RGBA _color; - private double _size; - private bool _visible; - - public Gdk.RGBA color { - get { return _color; } - } - - public double size { - get { return _size; } - } - - public bool is_visible { - get { return _visible; } - } - - public CompiledBorder (Gdk.RGBA color, double size, bool visible) { - _color = color; - _size = size; - _visible = visible; - } - - public CompiledBorder.as_empty () { - _color = Gdk.RGBA () { red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0}; - _size = 0; - _visible = false; - } - - public CompiledBorder copy () { - return new CompiledBorder (_color, _size, _visible); - } - - public static CompiledBorder compile (Components? components, Lib.Items.ModelNode? node) { - var rgba_border = Gdk.RGBA (); - bool has_colors = false; - double size = 0; - - if (components == null) { - return new CompiledBorder (rgba_border, size, has_colors); - } - - unowned var borders = components.borders; - unowned var opacity = components.opacity; - - // Set an initial arbitrary color with full transparency. - rgba_border.alpha = 0; - - if (borders == null) { - return new CompiledBorder (rgba_border, size, false); - } - - // Loop through all the configured borders and reload the color. - for (var i = 0; i < borders.data.length; ++i) { - // Skip if the border is hidden as we don't need to blend colors. - if (borders.data[i].hidden) { - continue; - } - - // Set the new blended color. - rgba_border = Utils.Color.blend_colors (rgba_border, borders.data[i].color); - size = double.max (size, borders.data[i].size); - has_colors = true; - } - - // Apply the mixed RGBA value only if we had one. - if (has_colors && opacity != null) { - // Keep in consideration the global opacity to properly update the border color. - rgba_border.alpha = rgba_border.alpha * opacity.opacity / 100; - } - - return new CompiledBorder (rgba_border, size, has_colors && size != 0); - } -} diff --git a/src/Lib/Components/CompiledFill.vala b/src/Lib/Components/CompiledFill.vala deleted file mode 100644 index 106b23876..000000000 --- a/src/Lib/Components/CompiledFill.vala +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.CompiledFill : Copyable { - private Gdk.RGBA _color; - private bool _visible; - - public Gdk.RGBA color { - get { return _color; } - } - - public bool is_visible { - get { return _visible; } - } - - public CompiledFill (Gdk.RGBA color, bool visible) { - _color = color; - _visible = visible; - } - - public CompiledFill.as_empty () { - _color = Gdk.RGBA () { red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0}; - _visible = false; - } - - public CompiledFill copy () { - return new CompiledFill (_color, _visible); - } - - public static CompiledFill compile (Components? components, Lib.Items.ModelNode? node) { - var rgba_fill = Gdk.RGBA (); - bool has_colors = false; - // Set an initial arbitrary color with full transparency. - rgba_fill.alpha = 0; - - if (components == null) { - return new CompiledFill (rgba_fill, has_colors); - } - - unowned var fills = components.fills; - unowned var opacity = components.opacity; - - if (fills == null) { - return new CompiledFill (rgba_fill, has_colors); - } - - // Loop through all the configured fills. - for (var i = 0; i < fills.data.length; ++i) { - // Skip if the fill is hidden as we don't need to blend colors. - if (fills.data[i].hidden) { - continue; - } - - // Set the new blended color. - rgba_fill = Utils.Color.blend_colors (rgba_fill, fills.data[i].color); - has_colors = true; - } - - // Apply the mixed RGBA value only if we had one. - if (has_colors && opacity != null) { - // Keep in consideration the global opacity to properly update the fill color. - rgba_fill.alpha = rgba_fill.alpha * opacity.opacity / 100; - } - - return new CompiledFill (rgba_fill, has_colors); - } -} diff --git a/src/Lib/Components/CompiledGeometry.vala b/src/Lib/Components/CompiledGeometry.vala deleted file mode 100644 index dba2db1d7..000000000 --- a/src/Lib/Components/CompiledGeometry.vala +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.CompiledGeometry : Copyable { - public struct CompiledGeometryData { - public Coordinates? source_center; - public Size? source_size; - public Transform? source_transform; - public Cairo.Matrix _transformation_matrix; - // Bounding box in local coordinates. - public Geometry.Rectangle local_bb; - // These rectangles are in global coordinates. - public Geometry.Quad area; - public Geometry.Quad drawable_area; - - // Cached bounding box that contains the rotated area. - public Geometry.Rectangle area_bb; - - public CompiledGeometryData () { - source_center = null; - source_size = null; - source_transform = null; - } - } - - public CompiledGeometryData _data; - - public Geometry.Rectangle local_bb { get { return _data.local_bb; }} - public Geometry.Quad area { get { return _data.area; }} - public Geometry.Rectangle area_bb { get { return _data.area_bb; }} - public Geometry.Rectangle drawable_bb { get { return _data.drawable_area.bounding_box; }} - - public double source_width { - get { - return _data.source_size == null ? area_bb.width : _data.source_size.width; - } - } - - public double source_height { - get { - return _data.source_size == null ? area_bb.height : _data.source_size.height; - } - } - - public double tl_x { get { return _data.area.tl_x; }} - public double tl_y { get { return _data.area.tl_y; }} - public double tr_x { get { return _data.area.tr_x; }} - public double tr_y { get { return _data.area.tr_y; }} - public double bl_x { get { return _data.area.bl_x; }} - public double bl_y { get { return _data.area.bl_y; }} - public double br_x { get { return _data.area.br_x; }} - public double br_y { get { return _data.area.br_y; }} - - public double bb_top { get { return _data.area_bb.top; }} - public double bb_left { get { return _data.area_bb.left; }} - public double bb_bottom { get { return _data.area_bb.bottom; }} - public double bb_right { get { return _data.area_bb.right; }} - - public Cairo.Matrix transformation_matrix { get { return _data._transformation_matrix; }} - - public CompiledGeometry (CompiledGeometryData data) { - _data = data; - } - - public CompiledGeometry.as_empty () { - _data = CompiledGeometryData (); - _data.area = Geometry.Quad (); - _data.area_bb = Geometry.Rectangle (); - _data._transformation_matrix = Cairo.Matrix.identity (); - } - - public CompiledGeometry copy () { - return new CompiledGeometry (_data); - } - - public CompiledGeometry.dummy () { - _data = CompiledGeometryData (); - } - - public CompiledGeometry.from_components ( - Components? components, - Lib.Items.ModelNode? node, - bool size_from_path = false - ) { - _data = CompiledGeometryData (); - - if (components == null) { - return; - } - - _data.source_center = components.center; - _data.source_transform = components.transform; - - unowned var compiled_border = node.instance.compiled_border; - var border_width = compiled_border == null ? 0 : compiled_border.size; - - assert (_data.source_center != null); - - if (_data.source_transform == null) { - _data._transformation_matrix = Cairo.Matrix.identity (); - } else { - _data._transformation_matrix = _data.source_transform.transformation_matrix; - } - - double width = 0; - double height = 0; - - int border_overestimate = 1; - - if (size_from_path) { - if (components.path == null) { - _data.local_bb = Geometry.Rectangle (); - _data.area = Geometry.Quad (); - _data.area_bb = Geometry.Rectangle (); - return; - } - - var ext = components.path.calculate_extents (); - width = ext.width; - height = ext.height; - _data.source_size = new Lib.Components.Size (ext.width, ext.height, false); - border_overestimate = 4; - } else { - if (components.size == null) { - _data.local_bb = Geometry.Rectangle (); - _data.area = Geometry.Quad (); - _data.area_bb = Geometry.Rectangle (); - return; - } - - _data.source_size = components.size; - height = _data.source_size.height; - width = _data.source_size.width; - } - - var center_x = _data.source_center.x; - var center_y = _data.source_center.y; - - var hw = width / 2.0; - var hh = height / 2.0; - _data.local_bb = Geometry.Rectangle.with_coordinates (-hw, -hh, hw, hh); - - _data.area = Geometry.Quad.from_components (center_x, center_y, width, height, _data._transformation_matrix); - - if (border_width > 0) { - var bw = border_width * 2 * border_overestimate; - _data.drawable_area = Geometry.Quad.from_components (center_x, center_y, width + bw, height + bw, _data._transformation_matrix); - } - else { - _data.drawable_area = _data.area; - } - - _data.area_bb = _data.area.bounding_box; - - _data._transformation_matrix.x0 = center_x; - _data._transformation_matrix.y0 = center_y; - } - - public static CompiledGeometry.from_descendants (Components? components, Lib.Items.ModelNode? node) { - _data = CompiledGeometryData (); - if (node == null || node.children == null) { - return; - } - - _data._transformation_matrix = Cairo.Matrix.identity (); - _data.area.transformation = _data._transformation_matrix; - - double top = int.MAX; - double bottom = int.MIN; - double left = int.MAX; - double right = int.MIN; - - foreach (var child in node.children.data) { - unowned var cg = child.instance.compiled_geometry; - if (cg == null) { - continue; - } - - top = double.min (top, cg.bb_top); - bottom = double.max (bottom, cg.bb_bottom); - left = double.min (left, cg.bb_left); - right = double.max (right, cg.bb_right); - } - - _data.area.tl_x = left; - _data.area.tl_y = top; - _data.area.tr_x = right; - _data.area.tr_y = top; - _data.area.bl_x = left; - _data.area.bl_y = bottom; - _data.area.br_x = right; - _data.area.br_y = bottom; - - _data.drawable_area = _data.area; - _data.local_bb = _data.area.bounding_box; - _data.area_bb = _data.area.bounding_box; - } -} diff --git a/src/Lib/Components/CompiledName.vala b/src/Lib/Components/CompiledName.vala deleted file mode 100644 index e49fb55a4..000000000 --- a/src/Lib/Components/CompiledName.vala +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "alecaddd" Castellani - */ - -public class Akira.Lib.Components.CompiledName : Copyable { - private string _name = ""; - - public string name { - get { - return _name; - } - } - - public CompiledName (string name) { - _name = name; - } - - public CompiledName.as_empty () { - _name = ""; - } - - public CompiledName copy () { - return new CompiledName (_name); - } -} diff --git a/src/Lib/Components/Component.vala b/src/Lib/Components/Component.vala deleted file mode 100644 index 3701e7bca..000000000 --- a/src/Lib/Components/Component.vala +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * Defines a copyable interface for components. - */ -public interface Akira.Lib.Components.Copyable { - public abstract T copy (); -} - -/* - * For now this is used as a namespace to hold some introspection. - */ -public class Akira.Lib.Components.Component { - /* - * Serialize the details of a component to an existing component - * object. This does not create a standalone node. - */ - public virtual void serialize_details (ref Json.Object obj) {} - - public Json.Node serialize_component (string cname) { - var obj = new Json.Object (); - obj.set_string_member ("cname", cname); - serialize_details (ref obj); - var res = new Json.Node (Json.NodeType.OBJECT); - res.set_object (obj); - return res; - } - - /* - * Type of component. - * For now this is only used for marking components dirty. It is technically - * not necessary to have all components have anenum Type. Only the ones - * that need respective View updates. - */ - public enum Type { - COMPILED_BORDER, - COMPILED_FILL, - COMPILED_GEOMETRY, - COMPILED_NAME - } - - public struct RegisteredType { - public Type type; - public bool dirty; - - public RegisteredType (Type t) { - type = t; - dirty = false; - } - } - - public struct RegisteredTypes { - RegisteredType[] types; - - public RegisteredTypes () { - types = new RegisteredType[4]; - types[0] = RegisteredType (Type.COMPILED_BORDER); - types[1] = RegisteredType (Type.COMPILED_FILL); - types[2] = RegisteredType (Type.COMPILED_GEOMETRY); - types[3] = RegisteredType (Type.COMPILED_NAME); - } - - public void mark_dirty (Type type, bool new_state) { - for (var i = 0; i < types.length; ++i) { - if (types[i].type == type) { - types[i].dirty = new_state; - } - } - } - } -} diff --git a/src/Lib/Components/Components.vala b/src/Lib/Components/Components.vala deleted file mode 100644 index b3802212d..000000000 --- a/src/Lib/Components/Components.vala +++ /dev/null @@ -1,282 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public struct Akira.Lib.Components.CompiledComponents { - public CompiledFill? compiled_fill; - public CompiledBorder? compiled_border; - public CompiledGeometry? compiled_geometry; - public CompiledName? compiled_name; - - public bool is_empty { get { - return compiled_fill == null - && compiled_border == null - && compiled_geometry == null - && compiled_name == null; - }} - - public Lib.Components.Component.RegisteredTypes dirty_components; - - public CompiledComponents () { - compiled_fill = null; - compiled_border = null; - compiled_geometry = null; - compiled_name = null; - dirty_components = Lib.Components.Component.RegisteredTypes (); - } - - /* - * Sets a component null based on passed Type. - * Returns false if component was already null. - */ - public bool clear_component (Lib.Components.Component.Type comp_type) { - switch (comp_type) { - case Component.Type.COMPILED_BORDER: { - if (compiled_border != null) { - compiled_border = null; - return true; - } - break; - } - case Component.Type.COMPILED_FILL: { - if (compiled_fill != null) { - compiled_fill = null; - return true; - } - break; - } - case Component.Type.COMPILED_GEOMETRY: { - if (compiled_geometry != null) { - compiled_geometry = null; - return true; - } - break; - } - case Component.Type.COMPILED_NAME: { - if (compiled_name != null) { - compiled_name = null; - return true; - } - break; - } - default: - break; - } - return false; - } - - /* - * Return true if new fill color was generated. - */ - public bool maybe_compile_fill (Lib.Items.ModelType type, Components? components, Lib.Items.ModelNode? node) { - if (compiled_fill != null) { - return false; - } - - compiled_fill = type.compile_fill (components, node); - - dirty_components.mark_dirty (Component.Type.COMPILED_FILL, true); - return true; - } - - /* - * Return true if new border color was generated. - */ - public bool maybe_compile_border (Lib.Items.ModelType type, Components? components, Lib.Items.ModelNode? node) { - if (compiled_border != null) { - return false; - } - - compiled_border = type.compile_border (components, node); - dirty_components.mark_dirty (Component.Type.COMPILED_BORDER, true); - return true; - } - - /* - * Return true if new geometry was generated. - */ - public bool maybe_compile_geometry (Lib.Items.ModelType type, Components? components, Lib.Items.ModelNode? node) { - if (compiled_geometry != null) { - return false; - } - - compiled_geometry = type.compile_geometry (components, node); - dirty_components.mark_dirty (Component.Type.COMPILED_GEOMETRY, true); - return true; - } - - public bool maybe_compile_name (Lib.Items.ModelType type, Components? components, Lib.Items.ModelNode? node) { - if (compiled_name != null) { - return false; - } - - compiled_name = type.compile_name (components, node); - dirty_components.mark_dirty (Component.Type.COMPILED_NAME, true); - return true; - } -} - -public struct Akira.Lib.Components.Components { - public Borders? borders; - public BorderRadius? border_radius; - public Fills? fills; - public Flipped? flipped; - public Layer? layer; - public Name? name; - public Opacity? opacity; - - public Coordinates? center; - public Size? size; - public Path? path; - public Transform? transform; - public Text? text; - - public Layout? layout; - - public Components () { - borders = null; - border_radius = null; - fills = null; - flipped = null; - layer = null; - name = null; - opacity = null; - center = null; - size = null; - path = null; - transform = null; - layout = null; - text = null; - } - - public static Name default_name () { - return new Name ("item", "-1"); - } - - public static Opacity default_opacity () { - return new Opacity (100.0); - } - - public static Transform default_transform () { - return new Transform.from_rotation (0.0); - } - - public static Flipped default_flipped () { - return new Flipped (false, false); - } - - public static BorderRadius default_border_radius () { - return new BorderRadius (0, 0, false, false); - } - - public static Layer default_layer () { - return new Layer (false); - } - - public void serialize (ref Json.Builder builder) { - builder.set_member_name ("components"); - - { - builder.begin_array (); - - if (borders != null) { - builder.add_value (borders.serialize_component ("borders")); - } - if (border_radius != null) { - builder.add_value (border_radius.serialize_component ("border_radius")); - } - if (fills != null) { - builder.add_value (fills.serialize_component ("fills")); - } - if (flipped != null) { - builder.add_value (flipped.serialize_component ("flipped")); - } - if (layer != null) { - builder.add_value (layer.serialize_component ("layer")); - } - if (name != null) { - builder.add_value (name.serialize_component ("name")); - } - if (center != null) { - builder.add_value (center.serialize_component ("center")); - } - if (size != null) { - builder.add_value (size.serialize_component ("size")); - } - if (path != null) { - builder.add_value (path.serialize_component ("path")); - } - if (transform != null) { - builder.add_value (transform.serialize_component ("transform")); - } - if (layout != null) { - builder.add_value (layout.serialize_component ("layout")); - } - if (text != null) { - builder.add_value (text.serialize_component ("text")); - } - - builder.end_array (); - } - } - - public static Components deserialize (Json.Node? components) { - var new_components = Components (); - - if (components == null) { - return new_components; - } - - foreach (unowned var comp_node in components.get_array ().get_elements ()) { - unowned var comp_obj = comp_node.get_object (); - assert (comp_obj != null); - var cname = comp_obj.get_string_member ("cname"); - - // Here we could probably use delegates in the future. - if (cname == "borders") { - new_components.borders = new Lib.Components.Borders.deserialized (comp_obj); - } else if (cname == "border_radius") { - new_components.border_radius = new Lib.Components.BorderRadius.deserialized (comp_obj); - } else if (cname == "fills") { - new_components.fills = new Lib.Components.Fills.deserialized (comp_obj); - } else if (cname == "flipped") { - new_components.flipped = new Lib.Components.Flipped.deserialized (comp_obj); - } else if (cname == "layer") { - new_components.layer = new Lib.Components.Layer.deserialized (comp_obj); - } else if (cname == "name") { - new_components.name = new Lib.Components.Name.deserialized (comp_obj); - } else if (cname == "center") { - new_components.center = new Lib.Components.Coordinates.deserialized (comp_obj); - } else if (cname == "size") { - new_components.size = new Lib.Components.Size.deserialized (comp_obj); - } else if (cname == "path") { - new_components.path = new Lib.Components.Path.deserialized (comp_obj); - } else if (cname == "transform") { - new_components.transform = new Lib.Components.Transform.deserialized (comp_obj); - } else if (cname == "layout") { - new_components.layout = new Lib.Components.Layout.deserialized (comp_obj); - } else if (cname == "text") { - new_components.text = new Lib.Components.Text.deserialized (comp_obj); - } - } - - return new_components; - } -} diff --git a/src/Lib/Components/Coordinates.vala b/src/Lib/Components/Coordinates.vala deleted file mode 100644 index 6542e30fb..000000000 --- a/src/Lib/Components/Coordinates.vala +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.Coordinates : Component, Copyable { - private double _x; - private double _y; - - public double x { - get { return _x; } - } - - public double y { - get { return _y; } - } - - public Coordinates (double x, double y) { - _x = x; - _y = y; - } - - public Coordinates.deserialized (Json.Object obj) { - _x = obj.get_double_member ("x"); - _y = obj.get_double_member ("y"); - } - - protected override void serialize_details (ref Json.Object obj) { - obj.set_double_member ("x", _x); - obj.set_double_member ("y", _y); - } - - public Coordinates copy () { - return new Coordinates (_x, _y); - } - - public Coordinates translated (double dx, double dy) { - return new Coordinates (_x + dx, _y + dy); - } -} diff --git a/src/Lib/Components/Fills.vala b/src/Lib/Components/Fills.vala deleted file mode 100644 index c9ea2f90c..000000000 --- a/src/Lib/Components/Fills.vala +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.Fills : Component, Copyable { - public struct Fill { - public int _id; - public Color _color; - - public Fill (int id = -1, Color color = Color ()) { - _id = id; - _color = color; - } - - public Fill.deserialized (int id, Json.Object obj) { - _id = id; - _color = Color.deserialized (obj.get_object_member ("color")); - } - - // Recommended accessors. - public int id { - get { - return _id; - } - } - public Gdk.RGBA color { - get { - return _color.rgba; - } - } - public bool hidden { - get { - return _color.hidden; - } - } - - // Mutators. - public Fill with_color (Color new_color) { - return Fill (_id, new_color); - } - - public Json.Node serialize () { - var obj = new Json.Object (); - obj.set_int_member ("id", _id); - obj.set_member ("color", _color.serialize ()); - var node = new Json.Node (Json.NodeType.OBJECT); - node.set_object (obj); - return node; - } - } - - public Fill[] data; - - public Fills () { - data = new Fill[1]; - } - - public Fills.with_color (Color color) { - data = new Fill[1]; - data[0] = Fill (0, color); - } - - public Fills.deserialized (Json.Object obj) { - var arr = obj.get_array_member ("fill_data").get_elements (); - data = new Fill[0]; - var idx = 0; - foreach (unowned var fill in arr) { - data.resize (data.length + 1); - data[idx] = Fill.deserialized (idx, fill.get_object ()); - ++idx; - } - } - - protected override void serialize_details (ref Json.Object obj) { - var array = new Json.Array (); - - foreach (unowned var d in data) { - array.add_element (d.serialize ()); - } - - var node = new Json.Node (Json.NodeType.ARRAY); - node.set_array (array); - obj.set_member ("fill_data", node); - } - - public Fills copy () { - var cln = new Fills (); - cln.data = data; - return cln; - } - - // Recommended accessors. - public Fill? fill_from_id (int id) { - foreach (unowned var fill in data) { - if (fill.id == id) { - return fill.with_color (fill._color); - } - } - return null; - } - - public bool replace (Fill fill) { - for (var i = 0; i < data.length; ++i) { - if (data[i].id == fill.id) { - data[i] = fill; - return true; - } - } - return false; - } - - /* - * Create a new Fill with the passed color and add it to the data structure. - * It's up to the code requiring this to then replace the fills component. - */ - public void append_fill_with_color (Color color) { - int latest_id = int.MIN; - foreach (unowned var fill in data) { - latest_id = int.max (latest_id, fill.id); - } - latest_id++; - var fill = Fill ((int) latest_id, color); - data.resize (data.length + 1); - data[data.length - 1] = fill; - } - - // Todo... - public void append_fill_with_image () {} - - // Todo... - public void append_fill_with_gradient () {} - - // Todo... - public void append_fill_with_pattern () {} - - public int remove (uint id) { - var ct = 0; - foreach (unowned var fill in data) { - if (fill.id == id) { - return remove_at (ct) ? 1 : -1; - } - ++ct; - } - return -1; - } - - private bool remove_at (int pos) { - if (pos >= data.length || pos < 0) { - assert (false); - return false; - } - - data.move (pos + 1, pos, data.length - pos - 1); - data.resize (data.length - 1); - return true; - } - } diff --git a/src/Lib/Components/Flipped.vala b/src/Lib/Components/Flipped.vala deleted file mode 100644 index e52da12ea..000000000 --- a/src/Lib/Components/Flipped.vala +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - - -public class Akira.Lib.Components.Flipped : Component, Copyable { - private bool _horizontal; - private bool _vertical; - - public bool horizontal { - get { return _horizontal; } - } - - public bool vertical { - get { return _vertical; } - } - - public Flipped (bool horizontal, bool vertical) { - _horizontal = horizontal; - _vertical = vertical; - } - - public Flipped.deserialized (Json.Object obj) { - _horizontal = obj.get_boolean_member ("horizontal"); - _vertical = obj.get_boolean_member ("vertical"); - } - - protected override void serialize_details (ref Json.Object obj) { - obj.set_boolean_member ("horizontal", _horizontal); - obj.set_boolean_member ("vertical", _vertical); - } - - public Flipped copy () { - return new Flipped (horizontal, vertical); - } -} diff --git a/src/Lib/Components/Layer.vala b/src/Lib/Components/Layer.vala deleted file mode 100644 index d6d0c52d9..000000000 --- a/src/Lib/Components/Layer.vala +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.Layer : Component, Copyable { - private bool _locked; - - public bool locked { - get { return _locked; } - } - - public Layer (bool locked) { - _locked = locked; - } - - public Layer.deserialized (Json.Object obj) { - _locked = obj.get_boolean_member ("locked"); - } - - protected override void serialize_details (ref Json.Object obj) { - obj.set_boolean_member ("locked", _locked); - } - - public Layer copy () { - return new Layer (_locked); - } - - public Layer with_locked (bool new_locked) { - return new Layer (new_locked); - } -} diff --git a/src/Lib/Components/Layout.vala b/src/Lib/Components/Layout.vala deleted file mode 100644 index ecb243d3c..000000000 --- a/src/Lib/Components/Layout.vala +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - - /* - * Defines how children will behave while in affine transforms. - * For now the options are quite simple, in the future more data - * and context could be added for more complex layouts. - */ -public class Akira.Lib.Components.Layout : Component, Copyable { - public struct LayoutData { - public bool can_rotate; - public bool dilated_resize; - public bool clips_children; - } - - // main data for boxed Fill - private LayoutData _data; - - public Layout (LayoutData data) { - _data = data; - } - - public Layout.deserialized (Json.Object obj) { - _data.can_rotate = obj.get_boolean_member ("can_rotate"); - _data.dilated_resize = obj.get_boolean_member ("dilated_resize"); - _data.clips_children = obj.get_boolean_member ("clips_children"); - } - - protected override void serialize_details (ref Json.Object obj) { - obj.set_boolean_member ("can_rotate", can_rotate); - obj.set_boolean_member ("dilated_resize", dilated_resize); - obj.set_boolean_member ("clips_children", clips_children); - } - - public Layout copy () { - return new Layout (_data); - } - - // Recommended accessors - public bool can_rotate { get { return _data.can_rotate; } } - public bool dilated_resize { get { return _data.dilated_resize; } } - public bool clips_children { get { return _data.clips_children; } } -} diff --git a/src/Lib/Components/Name.vala b/src/Lib/Components/Name.vala deleted file mode 100644 index cf919667f..000000000 --- a/src/Lib/Components/Name.vala +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.Name : Component, Copyable { - private string _id; - private string _name; - private string _filename; - - public string id { - get { return _id; } - } - - public string name { - get { return _name; } - } - - public string filename { - get { return _filename; } - } - - public Name (string name, string id, string? filename = null) { - _id = id; - _name = name; - _filename = filename != null ? filename : name; - } - - public Name.deserialized (Json.Object obj) { - _id = obj.get_string_member ("id"); - _name = obj.get_string_member ("name"); - _filename = obj.get_string_member ("filename"); - } - - protected override void serialize_details (ref Json.Object obj) { - obj.set_string_member ("id", _id); - obj.set_string_member ("name", _name); - obj.set_string_member ("filename", _filename); - } - - public Name copy () { - return new Name (_name, _id, _filename); - } -} diff --git a/src/Lib/Components/Opacity.vala b/src/Lib/Components/Opacity.vala deleted file mode 100644 index 19eccaab9..000000000 --- a/src/Lib/Components/Opacity.vala +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.Opacity : Component, Copyable { - private double _opacity; - - public double opacity { - get { return _opacity; } - } - - public Opacity (double opacity) { - if (opacity < 0.0) { - _opacity = 0.0; - return; - } - - _opacity = opacity <= 100.0 ? opacity : 100.0; - } - - public Opacity.deserialized (Json.Object obj) { - _opacity = obj.get_double_member ("opacity"); - } - - protected override void serialize_details (ref Json.Object obj) { - obj.set_double_member ("opacity", _opacity); - } - - public Opacity copy () { - return new Opacity (_opacity); - } -} diff --git a/src/Lib/Components/Path.vala b/src/Lib/Components/Path.vala deleted file mode 100644 index 4b5cab936..000000000 --- a/src/Lib/Components/Path.vala +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Modified by: Ashish Shevale - */ - -public class Akira.Lib.Components.Path : Component, Copyable { - // Control points relative to a top-left of 0,0. - // In the future we will probably want control points with more data. - public Geometry.PathSegment[] data; - public bool close = false; - - public Path (bool close = false) { - data = new Geometry.PathSegment[0]; - this.close = close; - } - - public Path.from_single_point (Geometry.Point pt, bool close = false) { - data = new Geometry.PathSegment[1]; - - // Only a line can be created from a single point. No need to check command. - data[0] = Geometry.PathSegment.line (pt); - - this.close = close; - } - - public Path.from_points (Geometry.PathSegment[] data, bool close = false) { - this.data = data; - this.close = close; - } - - public Path.deserialized (Json.Object obj) { - var arr = obj.get_array_member ("path_data").get_elements (); - data = new Geometry.PathSegment[0]; - var idx = 0; - - foreach (unowned var pt in arr) { - data.resize (data.length + 1); - data[idx] = Geometry.PathSegment.deserialized (pt.get_object ()); - ++idx; - } - } - - protected override void serialize_details (ref Json.Object obj) { - var array = new Json.Array (); - - foreach (unowned var d in data) { - array.add_element (d.serialize ()); - } - - var node = new Json.Node (Json.NodeType.ARRAY); - node.set_array (array); - obj.set_member ("path_data", node); - } - - public Path copy () { - var cln = new Path (); - cln.data = data; - cln.close = close; - return cln; - } - - public Geometry.Rectangle calculate_extents () { - // The minimum values need to be large for finding minimum to work. - Geometry.Rectangle extents = Geometry.Rectangle (); - extents.top = extents.left = double.MAX; - extents.bottom = extents.right = double.MIN; - - for (int i = 0; i < data.length; ++i) { - var segment = data[i]; - - if (segment.type == Lib.Modes.PathEditMode.Type.LINE) { - var point = segment.line_end; - extents.left = double.min (extents.left, point.x); - extents.right = double.max (extents.right, point.x); - extents.top = double.min (extents.top, point.y); - extents.bottom = double.max (extents.bottom, point.y); - } else { - var seg_extents = Utils.GeometryMath.calculate_bounds_for_curve (segment, data[i - 1].last_point); - - extents.left = double.min (extents.left, seg_extents.left); - extents.top = double.min (extents.top, seg_extents.top); - extents.right = double.max (extents.right, seg_extents.right); - extents.bottom = double.max (extents.bottom, seg_extents.bottom); - } - } - - return extents; - } -} diff --git a/src/Lib/Components/Size.vala b/src/Lib/Components/Size.vala deleted file mode 100644 index 58916e9ae..000000000 --- a/src/Lib/Components/Size.vala +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.Size : Component, Copyable { - private double _width; - private double _height; - private bool _locked; - - public double width { - get { return _width; } - } - - public double height { - get { return _height; } - } - - public bool locked { - get { return _locked; } - } - - public double ratio { - get { return _height == 0 ? 0.0 : _width / _height; } - } - - public Size (double width, double height, bool locked) { - _locked = locked; - _width = width; - _height = height; - } - - public Size.deserialized (Json.Object obj) { - _width = obj.get_double_member ("width"); - _height = obj.get_double_member ("height"); - _locked = obj.get_boolean_member ("locked"); - } - - protected override void serialize_details (ref Json.Object obj) { - obj.set_double_member ("width", _width); - obj.set_double_member ("height", _height); - obj.set_boolean_member ("locked", _locked); - } - - public Size copy () { - return new Size (_width, _height, _locked); - } - - public Size with_width (double new_width) { - return new Size (new_width, _height, _locked); - } - - public Size with_height (double new_height) { - return new Size (_width, new_height, _locked); - } -} diff --git a/src/Lib/Components/Text.vala b/src/Lib/Components/Text.vala deleted file mode 100644 index b77149d02..000000000 --- a/src/Lib/Components/Text.vala +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.Text : Component, Copyable { - private string p_text; - - public string text { get { return p_text; } } - - public Text (string new_text) { - p_text = new_text; - } - - public Text.deserialized (Json.Object obj) { - p_text = obj.get_string_member ("text"); - } - - protected override void serialize_details (ref Json.Object obj) { - obj.set_string_member ("text", p_text); - } - - public Text copy () { - return new Text (p_text); - } -} diff --git a/src/Lib/Components/Transform.vala b/src/Lib/Components/Transform.vala deleted file mode 100644 index c1b11e357..000000000 --- a/src/Lib/Components/Transform.vala +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Components.Transform : Component, Copyable { - private double _rotation = 0.0; - private double _scale_x = 1.0; - private double _scale_y = 1.0; - private double _skew_xy = 0.0; - private double _skew_yx = 0.0; - - public double rotation { get { return _rotation; } } - public double rotation_in_degrees { get { return _rotation * 180 / GLib.Math.PI; } } - - public Cairo.Matrix rotation_matrix { - get { - var mat = Cairo.Matrix.identity (); - mat.rotate (_rotation); - return mat; - } - } - - public Cairo.Matrix scale_matrix { - get { - var mat = Cairo.Matrix.identity (); - mat.scale (_scale_x, _scale_y); - return mat; - } - } - - public Cairo.Matrix skew_matrix { - get { - var mat = Cairo.Matrix.identity (); - mat.xy = _skew_xy; - mat.yx = _skew_yx; - return mat; - } - } - - public Cairo.Matrix transformation_matrix { - get { - Cairo.Matrix mat; - Utils.GeometryMath.recompose_matrix (out mat, _scale_x, _scale_y, _skew_xy, _rotation); - return mat; - } - } - - public Transform ( - double radians, - double scale_x, - double scale_y, - double skew_xy, - double skew_yx - ) { - _rotation = radians; - _scale_x = scale_x; - _scale_y = scale_y; - _skew_xy = skew_xy; - _skew_yx = skew_yx; - } - - public Transform.from_rotation (double in_radians) { - _rotation = in_radians; - } - - public Transform.deserialized (Json.Object obj) { - _rotation = obj.get_double_member ("rotation"); - _scale_x = obj.get_double_member ("scale_x"); - _scale_y = obj.get_double_member ("scale_y"); - _skew_xy = obj.get_double_member ("skew_xy"); - _skew_yx = obj.get_double_member ("skew_yx"); - } - - protected override void serialize_details (ref Json.Object obj) { - obj.set_double_member ("rotation", _rotation); - obj.set_double_member ("scale_x", _scale_x); - obj.set_double_member ("scale_y", _scale_y); - obj.set_double_member ("skew_xy", _skew_xy); - obj.set_double_member ("skew_yx", _skew_yx); - } - - public Transform copy () { - return new Transform ( - _rotation, - _scale_x, - _scale_y, - _skew_xy, - _skew_yx - ); - } - - public Transform with_main_rotation (double in_radians) { - return new Transform ( - in_radians, - _scale_x, - _scale_y, - _skew_xy, - _skew_yx - ); - } -} diff --git a/src/Lib/Items/ItemSelection.vala b/src/Lib/Items/ItemSelection.vala deleted file mode 100644 index 3396a9886..000000000 --- a/src/Lib/Items/ItemSelection.vala +++ /dev/null @@ -1,258 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * A selection of items with some useful accessors. - */ -public class Akira.Lib.Items.NodeSelection : Object { - private class ParentInfo { - public uint children_selected_ct = 1; - } - - // Used to determine first and last added nodes - private uint last_added_sid = 0; - - public class SelectedNode { - public ModelNode node; - public int parent_id; - public uint sid; - - public SelectedNode (ModelNode node, uint sid) { - this.node = node; - this.parent_id = node.parent.id; - this.sid = sid; - } - } - - public Gee.HashSet groups; - public Gee.TreeMap nodes; - - private Gee.HashMap parent_data; - - public NodeSelection (ModelNode? node) { - groups = new Gee.HashSet (); - nodes = new Gee.TreeMap (); - parent_data = new Gee.HashMap (); - - if (node != null) { - add_node (node); - } - } - - public ModelNode? first_node () { - if (nodes.size == 0) { - return null; - } - - var it = nodes.map_iterator (); - it.next (); - return it.get_value ().node; - } - - /* - * Returns true if the selection only spans a single group. Meaning all selected items reside in a single group. - * If true, the group id will be populated. Otherwise -1 is populated. - */ - public bool spans_one_group (out int group_id) { - group_id = -1; - - if (parent_data.size == 1) { - foreach (var k in parent_data.keys) { - group_id = k; - return true; - } - } - return false; - } - - public void add_node (ModelNode to_add) { - assert (to_add.parent != null); - if (has_id (to_add.id, false)) { - return; - } - - // If any ancestor is selected - if (ancestor_selected (to_add)) { - return; - } - - var cand = new SelectedNode (to_add, ++last_added_sid); - nodes[to_add.id] = cand; - register_parent (cand.parent_id); - - if (to_add.instance.is_group) { - groups.add (to_add.id); - - var to_del = new GLib.Array (); - foreach (var test in nodes.keys) { - if (to_add.has_child (test)) { - to_del.append_val (test); - } - } - - foreach (var did in to_del.data) { - nodes.unset (did); - } - } - } - - public void remove_node (int id) { - if (nodes.has_key (id)) { - deregister_parent (nodes[id].parent_id); - nodes.unset (id); - } - - if (groups.contains (id)) { - groups.remove (id); - } - } - - public bool has_id (int id, bool nested) { - if (nodes.has_key (id)) { - return true; - } - - if (groups.contains (id)) { - return true; - } - - if (!nested) { - return false; - } - - foreach (var group in groups) { - if (nodes[group].node.has_child (id)) { - return true; - } - } - - return false; - } - - public bool is_empty () { - return nodes.size == 0; - } - - public int count () { - return nodes.size; - } - - public Geometry.TransformedRectangle area () { - - if (nodes.size == 0) { - return Geometry.TransformedRectangle.empty (); - } - - if (nodes.size == 1) { - unowned var geom = first_node ().instance.compiled_geometry; - return Geometry.TransformedRectangle () { - matrix = geom.transformation_matrix, - rect = geom.local_bb - }; - } - - double top = int.MAX; - double bottom = int.MIN; - double left = int.MAX; - double right = int.MIN; - - foreach (var node in nodes.values) { - unowned var inst = node.node.instance; - top = double.min (top, inst.bounding_box.top); - bottom = double.max (bottom, inst.bounding_box.bottom); - left = double.min (left, inst.bounding_box.left); - right = double.max (right, inst.bounding_box.right); - } - - return Geometry.TransformedRectangle () { - matrix = Cairo.Matrix.identity (), - rect = Geometry.Rectangle () { - top = top, - right = right, - left = left, - bottom = bottom, - } - }; - } - - public void nob_coordinates (Utils.Nobs.Nob nob, double scale, ref double x, ref double y) { - Utils.Nobs.nob_xy_from_coordinates (nob, area ().quad (), scale, ref x, ref y); - } - - public Geometry.Rectangle bounding_box () { - var result = Geometry.Rectangle (); - if (nodes.size == 0) { - return result; - } - - var top = double.MAX; - var bottom = double.MIN; - var left = double.MAX; - var right = double.MIN; - - foreach (var node in nodes.values) { - unowned var inst = node.node.instance; - top = double.min (top, inst.bounding_box.top); - bottom = double.max (bottom, inst.bounding_box.bottom); - left = double.min (left, inst.bounding_box.left); - right = double.max (right, inst.bounding_box.right); - } - - result.top = top; - result.bottom = bottom; - result.left = left; - result.right = right; - return result; - } - - private bool ancestor_selected (ModelNode target) { - var parent = target.parent; - while (parent.id != Model.ORIGIN_ID) { - if (groups.contains (parent.id)) { - return true; - } - parent = parent.parent; - } - - return false; - } - - private void register_parent (int parent_id) { - if (parent_data.has_key (parent_id)) { - parent_data[parent_id].children_selected_ct++; - return; - } - parent_data[parent_id] = new ParentInfo (); - } - - private void deregister_parent (int parent_id) { - if (parent_data.has_key (parent_id)) { - parent_data[parent_id].children_selected_ct--; - - if (parent_data[parent_id].children_selected_ct == 0) { - parent_data.unset (parent_id); - } - return; - } - - assert (false); - } -} diff --git a/src/Lib/Items/Model.vala b/src/Lib/Items/Model.vala deleted file mode 100644 index d574c9ec6..000000000 --- a/src/Lib/Items/Model.vala +++ /dev/null @@ -1,795 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Authored by: Alessandro "alecaddd" Castellani - * - * Many of the methods inside this code base come from the Fireloom code base. - * https://gitlab.com/mbfraga/fireloom_core - */ - -public interface Akira.Lib.Items.ModelListener : Object { - public abstract void on_item_added (int id); - public abstract void on_item_geometry_changed (int id); - public abstract void on_items_deleted (GLib.Array ids); - public abstract void on_item_transferred (int id); -} - -/* - * Holds maps to instances that define connectivity between items and groups. - * Holds a dag based on nodes (starting from an origin node with `origin_id`. - * - * The dag needs to be rebuilt any time group topologies change. Changes that don't - * affect groups generally don't need to have the dag rebuilt. Rebuilding a dag - * repopulates all group nodes, but not item nodes. Item nodes can only have - * a single parent and no children, and they are populated when an operation changes them. - * - * The reason changes to items (add/remove/restack) don't require the dag to be rebuilt - * is for performance reasons--and the simplicity of their topology (single parent, no children). - * - * Group topologies rebuild the dag because in general those topologies will be small, and - * it ascertains that the dag is true and minimizes boilerplate code that is very tricky to - * begin with. - */ -public class Akira.Lib.Items.Model : Object { - public const int ORIGIN_ID = 5; - public const int GROUP_START_ID = 10; - public const int ITEM_START_ID = 10000000; - - private int last_group_id = GROUP_START_ID; - private int last_item_id = ITEM_START_ID; - - public Gee.HashMap group_map; - public Gee.HashMap item_map; - - public Gee.HashMap group_nodes; - public Gee.HashMap item_nodes; - - public Gee.HashSet changed_items; - public Gee.HashSet changed_groups; - - private ModelListener listener = null; - - private unowned ViewLayers.BaseCanvas? canvas = null; - - public Model () { - item_map = new Gee.HashMap (); - group_map = new Gee.HashMap (); - item_nodes = new Gee.HashMap (); - group_nodes = new Gee.HashMap (); - - changed_items = new Gee.HashSet (); - changed_groups = new Gee.HashSet (); - - var group_instance = new ModelInstance (ORIGIN_ID, new ModelTypeGroup ()); - add_to_maps (new ModelNode (group_instance, 0), false); - } - - public Model.live_model (ModelListener listener, ViewLayers.BaseCanvas? canvas) { - this (); - - this.listener = listener; - this.canvas = canvas; - } - - public Model.clone (Model other) { - this (); - - canvas = other.canvas; - this.listener = null; - last_group_id = other.last_group_id; - last_item_id = other.last_item_id; - - foreach (var item in other.item_map) { - item_map[item.key] = item.value.clone (true); - } - - foreach (var group in other.group_map) { - group_map[group.key] = group.value.clone (true); - } - - } - - /* - * Makes the model not be in a live state. - */ - public void sleep () { - listener = null; - } - - /* - * Makes the model live. - */ - public void wake (ModelListener listener, bool regenerate) { - this.listener = listener; - if (regenerate) { - var origin_node = node_from_id (ORIGIN_ID); - var origin_instance = instance_from_id (ORIGIN_ID); - origin_node.instance = origin_instance; - regenerate_node (origin_node); - } - } - - public void compile_geometries () { - internal_compile_geometries (); - } - - public ModelInstance? instance_from_id (int id) { - if (id >= ITEM_START_ID) { - return item_map.get (id); - } - - return group_map.get (id); - } - - public ModelInstance? child_instance_at (int parent_id, int pos) { - if (parent_id >= ITEM_START_ID) { - // items don't have children - return null; - } - - var node = node_from_id (parent_id); - - if (node == null || pos >= node.children.length) { - return null; - } - - return node.children.index (pos).instance; - } - - public ModelNode? node_from_id (int id) { - if (id >= ITEM_START_ID) { - return item_nodes.get (id); - } - - return group_nodes.get (id); - } - - public string path_from_id (int id) { - return path_from_node (node_from_id (id)); - } - - public string path_from_node (ModelNode node) { - if (node == null) { - return ""; - } - - var builder = new GLib.StringBuilder (); - build_path_recursive (node, ref builder); - return builder.str; - } - - /* - * Build an array of int representing the path IDs of a node. This path is - * unique for each node and changes based on the position relative to its - * parent. - */ - public int[] array_path_from_node (ModelNode node) { - Array path = new Array (); - build_array_path_recursive (node, ref path); - - return path.data; - } - - public GLib.Array children_in_group (int group_id) { - var group = group_nodes.get (group_id); - return group == null ? new GLib.Array () : group.children; - } - - public void alert_item_changed (int id, Components.Component.Type aspect_changed) { - var node = node_from_id (id); - if (node == null) { - assert (false); - return; - } - - alert_node_changed (node, aspect_changed); - } - - public void alert_node_changed (Lib.Items.ModelNode node, Components.Component.Type aspect_changed) { - internal_alert_item_change (node, false, aspect_changed); - } - - public void recalculate_children_stacking (int parent_id) { - var group = group_nodes.get (parent_id); - if (group == null) { - assert (false); - return; - } - - internal_recalculate_children_stacking (group); - } - - /* - TODO: Finish the transfer method based on - https://gitlab.com/mbfraga/fireloom_core/-/blob/main/packages/flmd/flmd_ItemModel.cpp#L148 - */ - public int transfer ( - int source_id, - int source_pos, - int num_items, - int target_id, - int target_pos, - bool restack = false, - Utils.TrivialDelegate? prep_for_op = null - ) { - if (num_items == 0) { - return 0; - } - - var source_node = node_from_id (source_id); - var target_node = node_from_id (target_id); - - if (!(source_node is Lib.Items.ModelNode) || !(target_node is Lib.Items.ModelNode)) { - assert (false); - return -1; - } - - unowned var source_children = source_node.children; - int source_children_size = (int) source_children.length; - - if (source_pos >= source_children_size || source_pos + num_items > source_children_size) { - assert (false); - return -1; - } - - if (source_id == target_id) { - // TODO: shift instead - assert (false); - return -1; - } - - unowned var target_children = target_node.children; - int target_children_size = (int) target_children.length; - - if (target_pos >= target_children_size) { - target_pos = target_children_size; - } - - if (source_id != ORIGIN_ID && target_id != ORIGIN_ID) { - // check for cycle - for (var i = source_pos; i < source_pos + num_items; ++i) { - unowned var node = source_children.index (i); - if (node.id == target_id || target_node.has_ancestor (node.id, true)) { - assert (false); - return -1; - } - } - } - - if (prep_for_op != null) { - prep_for_op (); - } - - var target_start_num_of_children = target_children.length; - - target_children.insert_vals (target_pos, source_children.data[source_pos : source_pos + num_items] , num_items); - - Utils.Array.insert_array_at_iarray ( - ref target_node.instance.children, - target_pos, - source_node.instance.children [source_pos : source_pos + num_items] - ); - - source_children.remove_range (source_pos, num_items); - Utils.Array.remove_from_iarray ( - ref source_node.instance.children, - source_pos, - num_items - ); - - if (restack) { - for (var i = source_pos; i < source_children.length; ++i) { - source_children.index (i).pos_in_parent = i; - } - } - - var target_count = target_pos >= target_start_num_of_children ? target_start_num_of_children : target_pos; - - var added_count = 0; - - for (var i = target_count; i < target_children.length; ++i) { - unowned var tgt = target_children.index (i); - - // Updating the parent is mandatory for nodes within the transfered range. - tgt.pos_in_parent = (int)(target_count + added_count++); - tgt.parent = target_node; - - if (!restack && added_count > num_items) { - // we need to set the new parent regardless. But further restacking is unnecessary - break; - } - - internal_alert_item_change (tgt, false, Components.Component.Type.COMPILED_GEOMETRY); - } - - if (source_node.id != ORIGIN_ID) { - internal_alert_item_change (source_node, false, Components.Component.Type.COMPILED_GEOMETRY); - } - - return 0; - } - - public int remove (int id, bool restack) { - var node = node_from_id (id); - - if (node == null) { - return -1; - } - - return extripate (node.parent.id, node.pos_in_parent, restack); - } - - public int extripate (int parent_id, uint pos, bool restack) { - var parent_node = group_nodes.get (parent_id); - - if (parent_node == null || pos >= parent_node.children.length) { - return -1; - } - - unowned var target_node = parent_node.children.index (pos); - - inner_remove (parent_node, target_node, pos); - - if (restack) { - for (var i = (int)pos; i < parent_node.children.length; ++i) { - parent_node.children.index (i).pos_in_parent--; - } - } - return 0; - } - - public int append_new_item (int parent_id, Lib.Items.ModelInstance candidate) { - var parent_node = group_nodes.get (parent_id); - if (parent_node == null) { - return -1; - } - - var pos = parent_node.children == null ? 0 : parent_node.children.length; - return inner_splice_new_item (parent_node, pos, candidate); - } - - public int splice_new_item (int parent_id, uint pos, Lib.Items.ModelInstance candidate) { - var parent_node = group_nodes.get (parent_id); - if (parent_node == null) { - return -1; - } - return inner_splice_new_item (parent_node, pos, candidate); - } - - /* - * Move items within a parent to change their z-order. - * - * Set restack to false if several move operations will be executed, which could make - * later restacking more efficient. Make sure to call recalculate_children_stacking - * after all operations. - * - * prep_for_op is an optional lambda that will get called only if the move ends up - * in an actual change to the model. it serves as a way to have side-effects that - * don't trigger on no-ops. For example, only add to the undo stack if a change happens. - */ - public int move_items ( - int parent_id, - uint pos, - uint newpos, - int length, - bool restack, - Utils.TrivialDelegate? prep_for_op = null - ) { - if (pos == newpos || length <= 0) { - return 0; - } - - var parent_node = group_nodes.get (parent_id); - if (parent_node == null) { - return -1; - } - - if (pos >= parent_node.children.length || pos + length > parent_node.children.length) { - return -1; - } - - if (newpos + length > parent_node.children.length) { - return 0; - } - - if (prep_for_op != null) { - prep_for_op (); - } - - // convert to rotation parameters - var f = (int) (uint.min (pos, newpos)); - var m = (int) (newpos > pos ? pos + length : pos); - var e = (int) (uint.max (pos + length, newpos + length)); - - Utils.Array.rotate_iarray (ref parent_node.instance.children, f, m, e); - Utils.Array.rotate_weak_garray (ref parent_node.children, f, m, e); - - if (restack) { - var start = int.min ((int)pos, (int)newpos); - for (var i = start; i < parent_node.children.length; ++i) { - unowned var ch = parent_node.children.index (i); - ch.pos_in_parent = i; - } - } - - if (parent_node.id != ORIGIN_ID) { - alert_node_changed (parent_node, Components.Component.Type.COMPILED_GEOMETRY); - } - - return 1; - } - - public static ModelNode? root (ModelNode node) { - if (node.parent == null) { - assert (node.id == ORIGIN_ID); - return node; - } - - if (node.parent.id == ORIGIN_ID) { - return node; - } - - return root (node.parent); - } - - public static ModelNode? next_sibling (ModelNode node, bool only_stackable) { - if (node == null || node.parent == null) { - return null; - } - - var sibling_pos = node.pos_in_parent + 1; - unowned ModelNode sibling = null; - while (sibling_pos < node.parent.children.length) { - sibling = node.parent.children.index (sibling_pos); - if (!only_stackable || sibling.instance.is_stackable) { - return sibling; - } - sibling_pos++; - } - - return null; - } - - public static ModelNode? previous_sibling (ModelNode node, bool only_stackable) { - if (node == null || node.parent == null) { - return null; - } - - var sibling_pos = node.pos_in_parent - 1; - unowned ModelNode sibling = null; - while (sibling_pos >= 0) { - sibling = node.parent.children.index (sibling_pos); - if (!only_stackable || sibling.instance.is_stackable) { - return sibling; - } - sibling_pos--; - } - - return null; - } - - public void print_instances () { - print ("Groups: \n"); - foreach (var inst in group_map) { - print (" >%d -- ", inst.value.id); - - if (inst.value.children != null) { - foreach (var id in inst.value.children) { - print ("%d ", id); - } - } - print ("\n"); - } - - print ("Instances: \n"); - foreach (var inst in item_map) { - print (" >%d -- \n", inst.value.id); - } - } - - public void print_dag () { - print ("DAG: \n"); - print_dag_recurse (group_nodes[ORIGIN_ID], 1); - } - - public void print_dag_recurse (ModelNode node, int level) { - for (var d = 0; d < level; ++d) { - print (" "); - } - - print (">%d -- (", node.id); - - if (node.parent != null) { - print ("%d", node.parent.id); - } - - print (")\n"); - - if (node.children != null) { - for (var i = 0; i < node.children.length; ++i) { - print_dag_recurse (node.children.index (i), level + 1); - } - } - } - - private int inner_splice_new_item (ModelNode parent_node, uint pos, ModelInstance candidate) { - var new_id = candidate.is_group ? ++last_group_id : ++last_item_id; - candidate.id = new_id; - // Generate the initial name for the item composed by the type name and - // the id. We subtract the starter IDs from what we show the user just - // to make it look prettier. The ID saved in the Name component is never - // used, maybe we could remove it. - var new_name_id = candidate.is_group ? new_id - GROUP_START_ID : new_id - ITEM_START_ID; - candidate.components.name = new Lib.Components.Name ( - "%s %i".printf (candidate.type.name_id, new_name_id), - new_id.to_string () - ); - var new_node = new ModelNode (candidate, (int) pos); - - if (parent_node.children == null) { - parent_node.children = new GLib.Array (); - } - - bool update_sibling_locations = false; - if (pos >= parent_node.children.length) { - parent_node.children.append_val (new_node); - Utils.Array.append_to_iarray (ref parent_node.instance.children, new_id); - } else { - parent_node.children.insert_val (pos, new_node); - Utils.Array.insert_at_iarray (ref parent_node.instance.children, (int)pos, new_id); - update_sibling_locations = true; - } - - if (update_sibling_locations) { - var ipos = (int) pos; - for (var i = ipos; i < parent_node.children.length; ++i) { - parent_node.children.index (ipos).pos_in_parent = ipos++; - } - } - - if (candidate.is_group) { - new_node.children = new GLib.Array (); - } - - new_node.parent = parent_node; - - add_to_maps (new_node, true); - - internal_alert_item_change (new_node, false, Components.Component.Type.COMPILED_GEOMETRY); - - return new_id; - } - - private int inner_remove (ModelNode parent_node, ModelNode to_delete, uint pos_in_parent) { - if (to_delete.children != null) { - for (var ci = (int) to_delete.children.length - 1; ci >= 0; --ci) { - unowned var child_node = to_delete.children.index (ci); - if (child_node.children != null && child_node.children.length > 0) { - inner_remove (to_delete, child_node, ci); - continue; - } - - child_node.instance.remove_from_canvas (canvas); - child_node.parent = null; - remove_from_maps (child_node.id); - } - } - - to_delete.instance.remove_from_canvas (canvas); - to_delete.parent = null; - - Utils.Array.remove_from_iarray (ref parent_node.instance.children, (int)pos_in_parent, 1); - parent_node.children.remove_index (pos_in_parent); - - if (parent_node.id != ORIGIN_ID) { - internal_alert_item_change (parent_node, false, Components.Component.Type.COMPILED_GEOMETRY); - } - - remove_from_maps (to_delete.id); - return 0; - } - - private void add_to_maps (ModelNode node, bool listen) { - // TODO create drawable in a nicer way. - node.instance.add_to_canvas (); - - naive_add_to_maps (node); - - if (listener != null && listen) { - listener.on_item_added (node.id); - } - } - - private void naive_add_to_maps (ModelNode node) { - if (node.instance.is_group) { - group_map[node.id] = node.instance; - group_nodes[node.id] = node; - } else { - item_map[node.id] = node.instance; - item_nodes[node.id] = node; - } - } - - private void remove_from_maps (int id) { - var target = instance_from_id (id); - if (target == null) { - return; - } - - if (id < ITEM_START_ID) { - group_nodes.unset (id); - group_map.unset (id); - } else { - item_nodes.unset (id); - item_map.unset (id); - } - } - - private void build_path_recursive (ModelNode node, ref StringBuilder builder) { - if (node.parent != null) { - build_path_recursive (node.parent, ref builder); - } - - if (builder.len > 0) { - builder.append ("_"); - } - - builder.append ((node.id == ORIGIN_ID) ? node.id.to_string () : node.pos_in_parent.to_string ()); - } - - private void build_array_path_recursive (ModelNode node, ref Array path) { - if (node.parent != null) { - build_array_path_recursive (node.parent, ref path); - } - - path.append_val (((node.id == ORIGIN_ID) ? node.id : node.pos_in_parent)); - } - - /* - * Internal operation to mark an instance as dirty. If 'simple' is true, - * only the instance's geometry is nullified, otherwise a recursive dirtying - * of items occurs. - */ - private void internal_alert_item_change ( - Lib.Items.ModelNode node, - bool simple, - Components.Component.Type aspect - ) { - node.instance.compiled_components.clear_component (aspect); - - if (!simple) { - mark_changed (node, aspect); - } - } - - private void mark_changed (Lib.Items.ModelNode node, Components.Component.Type aspect) { - if (listener == null) { - return; - } - - if (node.instance.is_group) { - changed_groups.add (node.id); - } else { - changed_items.add (node.id); - } - - unowned var parent = node.parent; - while (parent.id != ORIGIN_ID) { - internal_alert_item_change (parent, true, aspect); - mark_changed (parent, aspect); - parent = parent.parent; - } - } - - private void internal_recalculate_children_stacking (ModelNode parent_node) { - int ct = 0; - foreach (unowned var child in parent_node.children.data) { - child.pos_in_parent = ct++; - } - } - - private void regenerate_node (ModelNode node) { - var ct = 0; - - foreach (unowned var ch in node.instance.children) { - var ch_inst = instance_from_id (ch); - var ch_node = new ModelNode (ch_inst, ct); - ch_node.parent = node; - - if (node.children == null) { - node.children = new GLib.Array (); - } - - node.children.append_val (ch_node); - - naive_add_to_maps (ch_node); - - regenerate_node (ch_node); - ++ct; - } - - if (node.id != ORIGIN_ID) { - if (node.id < ITEM_START_ID) { - changed_groups.add (node.id); - } else { - changed_items.add (node.id); - } - - node.instance.add_to_canvas (); - } - } - - private void internal_compile_geometries () { - if (listener == null) { - return; - } - - if (changed_items.size == 0 && changed_groups.size == 0) { - return; - } - - foreach (var leaf in changed_items) { - var node = node_from_id (leaf); - if (node.instance.compile_components (node, canvas)) { - if (listener != null) { - listener.on_item_geometry_changed (node.id); - } - } - } - - changed_items.clear (); - - if (changed_groups.size == 0) { - return; - } - - var sorted = new Gee.TreeMap (); - foreach (var group_id in changed_groups) { - var group_node = node_from_id (group_id); - sorted[path_from_node (group_node)] = group_node; - } - - var it = sorted.bidir_map_iterator (); - for (var has_next = it.last (); has_next; has_next = it.previous ()) { - var node = it.get_value (); - if (node.instance.compile_components (node, canvas)) { - if (listener != null) { - listener.on_item_geometry_changed (node.id); - } - } - - // #TODO improve this - if (node.instance.components.layout.clips_children) { - if (node.children == null) { - continue; - } - - unowned var clip = node.instance.compiled_geometry.area; - foreach (unowned var child in node.children.data) { - unowned var dr = child.instance.drawable; - if (dr != null) { - dr.clipping_path = clip; - } - } - } - } - - changed_groups.clear (); - } -} diff --git a/src/Lib/Items/ModelInstance.vala b/src/Lib/Items/ModelInstance.vala deleted file mode 100644 index 9e8fc8829..000000000 --- a/src/Lib/Items/ModelInstance.vala +++ /dev/null @@ -1,191 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * An instance represents a single item. It contains information needed to represent and handle - * an item in the model. If it is a group, it may have children. - * - * Instances can live in a model or be freestanding. - * - Freestanding instances are generally clones of other instances used for caching or copying - * - Instances in a model are part of the scene and get an associated ModelNode within the Model. - * If there are children, then the corresponding ModelNode will have those children as nodes. - * There is obviously no trivial way to get a child instance without its parent model. - * - * Components are clonable collection of immutable bits of information about an instance, they - * are used to generate the scene or dictate behavior specific to an instance. In general, - * components are aspects of an instance that make sense being serialized / deserialized. If this - * is not the case for a specific bit of information (e.g., a volatile aspect like selection state), - * then that bit of information should NOT be a component - * Components should never depend on other nodes in the model. - * - * CompiledComponents are generated at model compilation from other components. They are volatile - * and do NOT get serialized / deserialized. They are always reconstructible from the original - * Components. For example, the bounding box of a component depends on it size, transformation, etc; - * so it is a compiled component. - * Compiled Components can depend on other nodes in the model. - * Freestanding items generally don't have or need compiled components. - * - * Some data is cached in the instance to make some calculations faster. This includes the actual - * drawable object and the boundingboxes calculated after compilation. - * - * Caching an instance is ok. HOWEVER, when modifying an instance, make sure to use the id - * and query it back from the Model. Instances can get replaced or deleted without warning, - * so it is vital to make sure that modifications occur directly on the model. This should - * not be a performance concern in the vast majority of cases. - */ -public class Akira.Lib.Items.ModelInstance { - public int id; - public int[] children; - - public ModelType type = null; - - public Lib.Components.Components components; - public Lib.Components.CompiledComponents compiled_components; - - public Drawables.Drawable drawable = null; - public Geometry.Rectangle bounding_box; - public Geometry.Rectangle drawable_bounding_box; - - public Components.CompiledGeometry compiled_geometry { get { return compiled_components.compiled_geometry; } } - public Components.CompiledFill compiled_fill { get { return compiled_components.compiled_fill; } } - public Components.CompiledBorder compiled_border { get { return compiled_components.compiled_border; } } - public Components.CompiledName compiled_name { get { return compiled_components.compiled_name; } } - - public bool is_group { get { return type.is_group (); } } - public bool is_artboard { get { return type.is_artboard (); } } - public bool is_stackable { get { return drawable != null; } } - - public ModelInstance (int uid, ModelType type) { - this.type = type; - components = Lib.Components.Components (); - compiled_components = Lib.Components.CompiledComponents (); - bounding_box = Geometry.Rectangle (); - drawable_bounding_box = Geometry.Rectangle (); - - if (is_group) { - this.children = new int[0]; - } - - this.id = uid; - } - - public ModelInstance clone (bool full = false) { - var cln = new ModelInstance (full ? id : -1, type); - cln.components = components; - - if (full) { - cln.children = children; - // TODO eventually this should be cachable--for now they break everything. - //cln.compiled_components = compiled_components; - //cln.drawable = drawable; - //cln.bounding_box = bounding_box; - //cln.drawable_bounding_box = drawable_bounding_box; - } - - return cln; - } - - /* - * Creates a dummy item -- useful for unit testing - */ - public static ModelInstance dummy_item () { - return new ModelInstance (-1, new DummyItemType ()); - } - - /* - * Creates a dummy group -- useful for unit testing - */ - public static ModelInstance dummy_group () { - return new ModelInstance (-1, new DummyGroupType ()); - } - - - /* - * Compiles the component for this item. If a corresponding node is passed, that node - * is used in the compilation process. - * This should almost always be called by the model--unless you really know what you are doing. - * If in doubt, you don't. - */ - public bool compile_components (ModelNode node, ViewLayers.BaseCanvas? canvas) { - bool something_changed = false; - something_changed = compiled_components.maybe_compile_fill (type, components, node) || something_changed; - something_changed = compiled_components.maybe_compile_border (type, components, node) || something_changed; - something_changed = compiled_components.maybe_compile_geometry (type, components, node) || something_changed; - something_changed = node.instance.is_artboard - && compiled_components.maybe_compile_name (type, components, node) - || something_changed; - - notify_view_of_changes (); - - if (something_changed) { - update_drawable_bounds (canvas); - } - - return something_changed; - } - - public void notify_view_of_changes () { - if (compiled_components.is_empty) { - return; - } - - if (drawable == null) { - return; - } - - var dirty_types = compiled_components.dirty_components.types; - for (var i = 0; i < dirty_types.length; ++i) { - var dirty_type = dirty_types[i]; - if (dirty_type.dirty) { - type.component_updated (this, dirty_type.type); - } - - compiled_components.dirty_components.mark_dirty (dirty_type.type, false); - } - } - - public void add_to_canvas () { - type.construct_canvas_item (this); - } - - public void remove_from_canvas (ViewLayers.BaseCanvas? canvas) { - // A ModelTypeGroup doesn't have a drawable instance. - if (canvas != null && drawable != null) { - drawable.request_redraw (canvas, false); - } - drawable = null; - } - - private void update_drawable_bounds (ViewLayers.BaseCanvas? canvas) { - bounding_box = compiled_geometry.area_bb; - if (drawable != null) { - if (canvas != null) { - drawable.request_redraw (canvas, false); - drawable.bounds = compiled_geometry.drawable_bb; - drawable.request_redraw (canvas, false); - drawable_bounding_box = drawable.bounds; - return; - } - } - - drawable_bounding_box = bounding_box; - } -} diff --git a/src/Lib/Items/ModelNode.vala b/src/Lib/Items/ModelNode.vala deleted file mode 100644 index ffd275f0f..000000000 --- a/src/Lib/Items/ModelNode.vala +++ /dev/null @@ -1,206 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * ModelNode is a DAG representation of the model. It populates the information of an ModelInstance - * that lives within a Model. This information includes its parent's ModelNode, its children - * ModelNodes (may be empty) and the original instance. - * - * The main purpose of a ModelNode is to ease traversal of the Model without n lookups. It should - * NOT be cached. There are few exceptions for performance, and when done, it is very important - * that the lifetime of the container of that cache gets notified whenever a node is destructed. - * This should very rarely be needed. - * - * It is recommended that nodes should be queried on demand from a model whenever needed. - */ -public class Akira.Lib.Items.ModelNode { - public int id; - // This is the position of the node relative to its parent. - public int pos_in_parent = -1; - public unowned ModelInstance instance; - - public unowned ModelNode parent = null; - public GLib.Array children; - - public ModelNode (ModelInstance instance, int pos_in_parent) { - this.instance = instance; - this.id = instance.id; - this.pos_in_parent = pos_in_parent; - } - - public void swap_children (int pos, int newpos) { - var tmp = children.data[pos]; - children.data[pos] = children.data[newpos]; - children.data[newpos] = tmp; - } - - public bool has_child (int id, bool recurse = true) { - if (children == null) { - return false; - } - - foreach (var child in children.data) { - if (child.id == id) { - return true; - } - - if (recurse && child.instance.is_group) { - if (child.has_child (id)) { - return true; - } - } - } - - return false; - } - - /* - * Return an array of int containing all IDs of the children of this node. - */ - public int[] get_children_ids () { - Array children_ids = new Array (); - - if (children == null) { - return children_ids.data; - } - - foreach (var child in children.data) { - children_ids.append_val (child.id); - get_children_ids_recursive (child, ref children_ids); - } - - return children_ids.data; - } - - private void get_children_ids_recursive (ModelNode node, ref Array children_ids) { - if (node.children == null) { - return; - } - - foreach (var child in node.children.data) { - children_ids.append_val (child.id); - get_children_ids_recursive (child, ref children_ids); - } - } - - public bool has_ancestor (int id, bool recurse = true) { - var p = parent; - - while (p != null) { - if (p.id == id) { - return true; - } - p = p.parent; - } - - return false; - } - - /* - * Get the number of ancestors the current model belongs to. - */ - public int get_ancestors_size () { - // Start with a negative value since all items have a parent, which is - // the main canvas, and we want to ignore that. - int n = -1; - var p = parent; - - while (p != null) { - n++; - p = p.parent; - } - - return n; - } - - /* - * Get the transform that maps this node's geometry to the world - */ - public Cairo.Matrix get_ancestor_transform () { - var result = Cairo.Matrix.identity (); - ModelNode? parent = parent; - while (parent != null && parent.id != Model.ORIGIN_ID) { - unowned var geom = parent.instance.compiled_geometry; - if (geom != null) { - var tmp = geom.transformation_matrix; - result.multiply (tmp, result); - } - parent = parent.parent; - } - return result; - } - - public void items_in_canvas ( - double x, - double y, - Cairo.Context cr, - double scale, - Drawables.Drawable.HitTestType hit_test_type, - ref Gee.ArrayList nodes - ) { - if (instance.components.layer.locked) { - return; - } - - unowned var dr = instance.drawable; - if (dr == null || (instance.is_group && !instance.is_artboard)) { - if (!instance.bounding_box.contains (x, y)) { - return; - } - } else { - if (dr.hit_test (x, y, cr, scale, hit_test_type)) { - nodes.add (this); - } - } - - if (children != null) { - foreach (unowned var child in children.data) { - child.items_in_canvas (x, y, cr, scale, hit_test_type, ref nodes); - } - } - } -} - -public class Akira.Lib.Items.PositionKey { - public string parent_path; - public int pos_in_parent; - - public static int compare (PositionKey a, PositionKey b) { - if (a.parent_path == b.parent_path) { - if (a.pos_in_parent == b.pos_in_parent) { - return 0; - } - - return a.pos_in_parent < b.pos_in_parent ? -1 : 1; - } - - return a.parent_path < b.parent_path ? -1 : 1; - } -} - -public class Akira.Lib.Items.ChildrenSet { - public ModelNode parent_node; - public int first_child; - public int length; - - // optional array with children nodes - public GLib.Array children_in_set; -} diff --git a/src/Lib/Items/ModelType.vala b/src/Lib/Items/ModelType.vala deleted file mode 100644 index 74817b8ef..000000000 --- a/src/Lib/Items/ModelType.vala +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Items.ModelType : Object { - public virtual string name_id { get { return "empty"; } } - - public virtual Components.CompiledFill compile_fill ( - Components.Components? components, - Lib.Items.ModelNode? node - ) { - return Components.CompiledFill.compile (components, node); - } - - public virtual Components.CompiledBorder compile_border ( - Components.Components? components, - Lib.Items.ModelNode? node - ) { - return Components.CompiledBorder.compile (components, node); - } - - public virtual Components.CompiledGeometry compile_geometry ( - Components.Components? components, - Lib.Items.ModelNode? node - ) { - return new Components.CompiledGeometry.from_components (components, node); - } - - public virtual Components.CompiledName compile_name ( - Components.Components? components, - Lib.Items.ModelNode? node - ) { - return new Components.CompiledName (components.name.name); - } - - public virtual void construct_canvas_item (ModelInstance item) {} - - public virtual void component_updated (ModelInstance item, Lib.Components.Component.Type type) {} - - public virtual void apply_scale_transform ( - Lib.Items.Model item_model, - Lib.Items.ModelNode node, - Lib.Modes.TransformMode.InitialDragState initial_drag_state, - Cairo.Matrix inverse_reference_matrix, - double global_offset_x, - double global_offset_y, - double reference_sx, - double reference_sy - ) { - Utils.AffineTransform.scale_node ( - item_model, - node, - initial_drag_state, - inverse_reference_matrix, - global_offset_x, - global_offset_y, - reference_sx, - reference_sy - ); - } - - public virtual bool is_group () { return false; } - public virtual bool is_artboard () { return false; } -} - -public class Akira.Lib.Items.DummyItemType : ModelType { - public override string name_id { get { return "dummy_item"; } } -} - -public class Akira.Lib.Items.DummyGroupType : ModelType { - public override string name_id { get { return "dummy_group"; } } - public override bool is_group () { return true; } -} diff --git a/src/Lib/Items/ModelTypeArtboard.vala b/src/Lib/Items/ModelTypeArtboard.vala deleted file mode 100644 index 7d7fc6ea2..000000000 --- a/src/Lib/Items/ModelTypeArtboard.vala +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Items.ModelTypeArtboard : ModelType { - - public static ModelInstance default_artboard ( - Lib.Components.Coordinates center, - Lib.Components.Size size - ) { - var new_item = new ModelInstance (-1, new ModelTypeArtboard ()); - new_item.components.center = center; - new_item.components.size = size; - new_item.components.transform = Lib.Components.Components.default_transform (); - new_item.components.flipped = Lib.Components.Components.default_flipped (); - - new_item.components.fills = new Lib.Components.Fills.with_color (Lib.Components.Color (1.0, 1.0, 1.0, 1.0)); - - var layout_data = Components.Layout.LayoutData () { - can_rotate = true, - dilated_resize = false, - clips_children = true - }; - new_item.components.layout = new Components.Layout (layout_data); - new_item.components.name = Lib.Components.Components.default_name (); - new_item.components.layer = Lib.Components.Components.default_layer (); - return new_item; - } - - public override string name_id { get { return "artboard"; } } - - public override void construct_canvas_item (ModelInstance instance) { - var w = instance.components.size.width; - var h = instance.components.size.height; - instance.drawable = new Drawables.DrawableArtboard ( - - (w / 2.0), - - (h / 2.0), - w, - h - ); - } - - public override void component_updated (ModelInstance instance, Lib.Components.Component.Type type) { - switch (type) { - case Lib.Components.Component.Type.COMPILED_FILL: - if (!instance.compiled_fill.is_visible) { - instance.drawable.fill_rgba = Gdk.RGBA () { alpha = 0 }; - break; - } - - instance.drawable.fill_rgba = instance.compiled_fill.color; - break; - case Lib.Components.Component.Type.COMPILED_GEOMETRY: - instance.drawable.width = instance.components.size.width; - instance.drawable.height = instance.components.size.height; - instance.drawable.transform = instance.compiled_geometry.transformation_matrix; - break; - case Lib.Components.Component.Type.COMPILED_NAME: - instance.drawable.label = instance.compiled_name.name; - break; - case Lib.Components.Component.Type.COMPILED_BORDER: - // Artboards can't have borders, so don't do anything. - break; - } - } - - public override bool is_group () { return true; } - public override bool is_artboard () { return true; } -} diff --git a/src/Lib/Items/ModelTypeEllipse.vala b/src/Lib/Items/ModelTypeEllipse.vala deleted file mode 100644 index 9e47d71e9..000000000 --- a/src/Lib/Items/ModelTypeEllipse.vala +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Items.ModelTypeEllipse : ModelType { - public static ModelInstance minimal_ellipse () { - return default_ellipse ( - new Lib.Components.Coordinates (0.5, 0.5), - new Lib.Components.Size (1, 1, false), - null, - null - ); - } - - public static ModelInstance default_ellipse ( - Lib.Components.Coordinates center, - Lib.Components.Size size, - Lib.Components.Borders? borders, - Lib.Components.Fills? fills - ) { - var new_item = new ModelInstance (-1, new ModelTypeEllipse ()); - new_item.components.center = center; - new_item.components.size = size; - new_item.components.borders = borders; - new_item.components.fills = fills; - new_item.components.transform = Lib.Components.Components.default_transform (); - new_item.components.flipped = Lib.Components.Components.default_flipped (); - new_item.components.border_radius = Lib.Components.Components.default_border_radius (); - new_item.components.name = Lib.Components.Components.default_name (); - new_item.components.layer = Lib.Components.Components.default_layer (); - return new_item; - } - - public override string name_id { get { return "ellipse"; } } - - public override void construct_canvas_item (ModelInstance instance) { - var radius_x = instance.components.size.width / 2.0; - var radius_y = instance.components.size.height / 2.0; - instance.drawable = new Drawables.DrawableEllipse (0, 0, radius_x, radius_y); - } - - public override void component_updated (ModelInstance instance, Lib.Components.Component.Type type) { - switch (type) { - case Lib.Components.Component.Type.COMPILED_BORDER: - if (!instance.compiled_border.is_visible) { - instance.drawable.line_width = 0; - instance.drawable.stroke_rgba = Gdk.RGBA () { alpha = 0 }; - break; - } - - // The "line-width" property expects a DOUBLE type, but we don't support subpixels - // so we always handle the border size as INT, therefore we need to type cast it here. - instance.drawable.line_width = (double) instance.compiled_border.size; - instance.drawable.stroke_rgba = instance.compiled_border.color; - break; - case Lib.Components.Component.Type.COMPILED_FILL: - if (!instance.compiled_fill.is_visible) { - instance.drawable.fill_rgba = Gdk.RGBA () { alpha = 0 }; - break; - } - - instance.drawable.fill_rgba = instance.compiled_fill.color; - break; - case Lib.Components.Component.Type.COMPILED_GEOMETRY: - var ellipse = instance.drawable as Drawables.DrawableEllipse; - ellipse.radius_x = instance.components.size.width / 2.0; - ellipse.radius_y = instance.components.size.height / 2.0; - instance.drawable.transform = instance.compiled_geometry.transformation_matrix; - break; - default: - break; - } - } -} diff --git a/src/Lib/Items/ModelTypeGroup.vala b/src/Lib/Items/ModelTypeGroup.vala deleted file mode 100644 index fadac8788..000000000 --- a/src/Lib/Items/ModelTypeGroup.vala +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Items.ModelTypeGroup : ModelType { - public static ModelInstance default_group () { - var new_item = new ModelInstance (-1, new ModelTypeGroup ()); - var layout_data = Components.Layout.LayoutData () { - can_rotate = true, - dilated_resize = true, - clips_children = false - }; - new_item.components.layout = new Components.Layout (layout_data); - new_item.components.name = Lib.Components.Components.default_name (); - new_item.components.layer = Lib.Components.Components.default_layer (); - return new_item; - } - - public override string name_id { get { return "group"; } } - - public override Components.CompiledGeometry compile_geometry ( - Components.Components? components, - Lib.Items.ModelNode? node - ) { - return new Components.CompiledGeometry.from_descendants (components, node); - } - - public override void construct_canvas_item (ModelInstance instance) { - instance.drawable = new Drawables.DrawableGroup (); - } - - public override bool is_group () { return true; } -} diff --git a/src/Lib/Items/ModelTypePath.vala b/src/Lib/Items/ModelTypePath.vala deleted file mode 100644 index 532e711c7..000000000 --- a/src/Lib/Items/ModelTypePath.vala +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Items.ModelTypePath : ModelType { - public static ModelInstance minimal_rect () { - return default_path ( - new Lib.Components.Coordinates (0.5, 0.5), - null, - null - ); - } - - public static ModelInstance default_path ( - Lib.Components.Coordinates center, - Lib.Components.Borders? borders, - Lib.Components.Fills? fills - ) { - var new_item = new ModelInstance (-1, new ModelTypePath ()); - new_item.components.center = center; - new_item.components.borders = borders; - new_item.components.fills = fills; - new_item.components.transform = Lib.Components.Components.default_transform (); - new_item.components.flipped = Lib.Components.Components.default_flipped (); - new_item.components.border_radius = Lib.Components.Components.default_border_radius (); - new_item.components.path = new Lib.Components.Path.from_single_point ( - Akira.Geometry.Point (center.x, center.y), - false - ); - new_item.components.size = new Lib.Components.Size (1, 1, false); - new_item.components.name = Lib.Components.Components.default_name (); - new_item.components.layer = Lib.Components.Components.default_layer (); - return new_item; - } - - public override string name_id { get { return "path"; } } - - public override Components.CompiledGeometry compile_geometry ( - Components.Components? components, - Lib.Items.ModelNode? node - ) { - return new Components.CompiledGeometry.from_components (components, node, true); - } - - public override void construct_canvas_item (ModelInstance instance) { - instance.drawable = new Drawables.DrawablePath ( - (instance.components.path == null) ? null : instance.components.path.data - ); - } - - public override void component_updated (ModelInstance instance, Lib.Components.Component.Type type) { - switch (type) { - case Lib.Components.Component.Type.COMPILED_BORDER: - if (!instance.compiled_border.is_visible) { - instance.drawable.line_width = 0; - instance.drawable.stroke_rgba = Gdk.RGBA () { alpha = 0 }; - break; - } - - // The "line-width" property expects a DOUBLE type, but we don't support subpixels - // so we always handle the border size as INT, therefore we need to type cast it here. - instance.drawable.line_width = (double) instance.compiled_border.size; - instance.drawable.stroke_rgba = instance.compiled_border.color; - break; - case Lib.Components.Component.Type.COMPILED_FILL: - if (!instance.compiled_fill.is_visible) { - instance.drawable.fill_rgba = Gdk.RGBA () { alpha = 0 }; - break; - } - - instance.drawable.fill_rgba = instance.compiled_fill.color; - break; - case Lib.Components.Component.Type.COMPILED_GEOMETRY: - // The points property is only available to DrawablePath, so first typecast it - // modify it, then assign to instance. - Drawables.DrawablePath drawable = instance.drawable as Drawables.DrawablePath; - drawable.center_x = -instance.compiled_geometry.source_width / 2.0; - drawable.center_y = -instance.compiled_geometry.source_height / 2.0; - drawable.transform = instance.compiled_geometry.transformation_matrix; - drawable.points = instance.components.path.data; - drawable.close = instance.components.path.close; - break; - default: - break; - } - } -} diff --git a/src/Lib/Items/ModelTypeRect.vala b/src/Lib/Items/ModelTypeRect.vala deleted file mode 100644 index c09384526..000000000 --- a/src/Lib/Items/ModelTypeRect.vala +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Items.ModelTypeRect : ModelType { - public static ModelInstance minimal_rect () { - return default_rect ( - new Lib.Components.Coordinates (0.5, 0.5), - new Lib.Components.Size (1, 1, false), - null, - null - ); - } - - public static ModelInstance default_rect ( - Lib.Components.Coordinates center, - Lib.Components.Size size, - Lib.Components.Borders? borders, - Lib.Components.Fills? fills - ) { - var new_item = new ModelInstance (-1, new ModelTypeRect ()); - new_item.components.center = center; - new_item.components.size = size; - new_item.components.borders = borders; - new_item.components.fills = fills; - new_item.components.transform = Lib.Components.Components.default_transform (); - new_item.components.flipped = Lib.Components.Components.default_flipped (); - new_item.components.border_radius = Lib.Components.Components.default_border_radius (); - new_item.components.name = Lib.Components.Components.default_name (); - new_item.components.layer = Lib.Components.Components.default_layer (); - return new_item; - } - - public override string name_id { get { return "rectangle"; } } - - public override void construct_canvas_item (ModelInstance instance) { - var w = instance.components.size.width; - var h = instance.components.size.height; - instance.drawable = new Drawables.DrawableRect ( - - (w / 2.0), - - (h / 2.0), - w, - h - ); - } - - public override void component_updated (ModelInstance instance, Lib.Components.Component.Type type) { - switch (type) { - case Lib.Components.Component.Type.COMPILED_BORDER: - if (!instance.compiled_border.is_visible) { - instance.drawable.line_width = 0; - instance.drawable.stroke_rgba = Gdk.RGBA () { alpha = 0 }; - break; - } - - // The "line-width" property expects a DOUBLE type, but we don't support subpixels - // so we always handle the border size as INT, therefore we need to type cast it here. - instance.drawable.line_width = (double) instance.compiled_border.size; - instance.drawable.stroke_rgba = instance.compiled_border.color; - break; - case Lib.Components.Component.Type.COMPILED_FILL: - if (!instance.compiled_fill.is_visible) { - instance.drawable.fill_rgba = Gdk.RGBA () { alpha = 0 }; - break; - } - - instance.drawable.fill_rgba = instance.compiled_fill.color; - break; - case Lib.Components.Component.Type.COMPILED_GEOMETRY: - instance.drawable.width = instance.components.size.width; - instance.drawable.height = instance.components.size.height; - instance.drawable.transform = instance.compiled_geometry.transformation_matrix; - break; - default: - break; - } - } -} diff --git a/src/Lib/Items/ModelTypeText.vala b/src/Lib/Items/ModelTypeText.vala deleted file mode 100644 index 445039acd..000000000 --- a/src/Lib/Items/ModelTypeText.vala +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Items.ModelTypeText : ModelType { - public static ModelInstance minimal_text () { - return default_text ( - new Lib.Components.Coordinates (0.5, 0.5), - new Lib.Components.Size (1, 1, false), - new Lib.Components.Text ("Akira") - ); - } - - public static ModelInstance default_text ( - Lib.Components.Coordinates center, - Lib.Components.Size size, - Lib.Components.Text text - ) { - var new_item = new ModelInstance (-1, new ModelTypeText ()); - new_item.components.center = center; - new_item.components.size = size; - new_item.components.text = text; - new_item.components.transform = Lib.Components.Components.default_transform (); - new_item.components.flipped = Lib.Components.Components.default_flipped (); - new_item.components.border_radius = Lib.Components.Components.default_border_radius (); - new_item.components.name = Lib.Components.Components.default_name (); - new_item.components.layer = Lib.Components.Components.default_layer (); - return new_item; - } - - public override string name_id { get { return "text"; } } - - public override void construct_canvas_item (ModelInstance instance) { - var w = instance.components.size.width; - var h = instance.components.size.height; - string text = (instance.components.text == null) ? "" : instance.components.text.text; - instance.drawable = new Drawables.DrawableText ( - - (w / 2.0), - - (h / 2.0), - w, - h, - text - ); - } - - public override void component_updated (ModelInstance instance, Lib.Components.Component.Type type) { - switch (type) { - case Lib.Components.Component.Type.COMPILED_BORDER: - if (!instance.compiled_border.is_visible) { - instance.drawable.line_width = 0; - instance.drawable.stroke_rgba = Gdk.RGBA () { alpha = 0 }; - break; - } - - // The "line-width" property expects a DOUBLE type, but we don't support subpixels - // so we always handle the border size as INT, therefore we need to type cast it here. - instance.drawable.line_width = (double) instance.compiled_border.size; - instance.drawable.stroke_rgba = instance.compiled_border.color; - break; - case Lib.Components.Component.Type.COMPILED_FILL: - if (!instance.compiled_fill.is_visible) { - instance.drawable.fill_rgba = Gdk.RGBA () { alpha = 0 }; - break; - } - - instance.drawable.fill_rgba = instance.compiled_fill.color; - break; - case Lib.Components.Component.Type.COMPILED_GEOMETRY: - instance.drawable.width = instance.components.size.width; - instance.drawable.height = instance.components.size.height; - instance.drawable.transform = instance.compiled_geometry.transformation_matrix; - break; - default: - break; - } - } -} diff --git a/src/Lib/Managers/CopyManager.vala b/src/Lib/Managers/CopyManager.vala deleted file mode 100644 index 632404a32..000000000 --- a/src/Lib/Managers/CopyManager.vala +++ /dev/null @@ -1,182 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Lib.Managers.CopyManager : Object { - public unowned ViewCanvas view_canvas { get; construct; } - - private Lib.Items.Model copy_model; - - public CopyManager (ViewCanvas canvas) { - Object (view_canvas : canvas); - } - - construct { - view_canvas.window.event_bus.request_copy.connect (do_copy); - view_canvas.window.event_bus.request_paste.connect (do_paste); - view_canvas.window.event_bus.request_duplicate.connect (do_duplicate); - } - - /* - * Return a tree map of the currently selected items, with their sorted position. - */ - public Gee.TreeMap collect_sorted_candidates () { - var candidates = new Gee.TreeMap (Lib.Items.PositionKey.compare); - foreach (var to_copy in view_canvas.selection_manager.selection.nodes.values) { - var key = new Lib.Items.PositionKey (); - key.parent_path = view_canvas.items_manager.item_model.path_from_node (to_copy.node.parent); - key.pos_in_parent = to_copy.node.pos_in_parent; - candidates[key] = to_copy.node.id; - } - - return candidates; - } - - /* - * Copy the currently selected nodes. - */ - public void do_copy () { - var sorted_candidates = collect_sorted_candidates (); - // Don't do anything if we don't have selected nodes. - if (sorted_candidates.size == 0) { - return; - } - - // Create a new Model to hold all the cloned nodes in memory. - copy_model = new Lib.Items.Model (); - - // Populate the model with all the currently selected nodes. - int res = 0; - foreach (var sorted_id in sorted_candidates.values) { - res += Utils.ModelUtil.clone_from_model ( - view_canvas.items_manager.item_model, - sorted_id, - copy_model, - Lib.Items.Model.ORIGIN_ID - ); - } - - assert (res == 0); - } - - /* - * Paste a copied node into the item_model. - * TODO: - * - If the `in_place` is true, the cloned node should be spliced at the same position of the - * currently selected node, ignoring the source node position (eg. paste into group, paste into - * another artboard, etc.), and the X & Y coordinates of the cloned node should match the - * coordiante sof the currently selected node. - * - If the `in_place` is false, we should paste the node at the center of the viewport, at the - * top most position. - */ - public void do_paste (bool in_place = false) { - if (copy_model == null) { - return; - } - - var children = copy_model.node_from_id (Lib.Items.Model.ORIGIN_ID).children; - if (children == null || children.length == 0) { - return; - } - - var blocker = new SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - - view_canvas.selection_manager.reset_selection (); - view_canvas.window.event_bus.create_model_snapshot ( - in_place ? "paste selection in place" : "paste selection"); - - int res = 0; - foreach (var child in children.data) { - res += Utils.ModelUtil.clone_from_model ( - copy_model, - child.id, - view_canvas.items_manager.item_model, - Lib.Items.Model.ORIGIN_ID, - on_subtree_cloned, - in_place ? Utils.ModelUtil.State.PASTE_IN_PLACE : Utils.ModelUtil.State.PASTE - ); - } - assert (res == 0); - on_after_paste (); - } - - private void do_duplicate () { - var sorted_candidates = collect_sorted_candidates (); - // Don't do anything if we don't have selected nodes. - if (sorted_candidates.size == 0) { - return; - } - - // Populate the model with all the currently selected nodes. Use a locally - // scoped variable to not override the copy_model in order to maintain any - // existing copied model. - var duplicate_model = new Lib.Items.Model (); - int res = 0; - foreach (var sorted_id in sorted_candidates.values) { - res += Utils.ModelUtil.clone_from_model ( - view_canvas.items_manager.item_model, - sorted_id, - duplicate_model, - Lib.Items.Model.ORIGIN_ID - ); - } - assert (res == 0); - - if (duplicate_model == null) { - return; - } - - var children = duplicate_model.node_from_id (Lib.Items.Model.ORIGIN_ID).children; - if (children == null || children.length == 0) { - return; - } - - var blocker = new SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - - view_canvas.selection_manager.reset_selection (); - view_canvas.window.event_bus.create_model_snapshot ("duplicate selection"); - - res = 0; - foreach (var child in children.data) { - res += Utils.ModelUtil.clone_from_model ( - duplicate_model, - child.id, - view_canvas.items_manager.item_model, - Lib.Items.Model.ORIGIN_ID, - on_subtree_cloned, - Utils.ModelUtil.State.DUPLICATE - ); - } - assert (res == 0); - on_after_paste (); - } - - private void on_after_paste () { - view_canvas.items_manager.compile_model (); - // Regenerate the layers list. - view_canvas.window.main_window.regenerate_list (true); - } - - private void on_subtree_cloned (int id) { - view_canvas.selection_manager.add_to_selection (id); - } -} diff --git a/src/Lib/Managers/ExportManager.vala b/src/Lib/Managers/ExportManager.vala deleted file mode 100644 index e1311c0f6..000000000 --- a/src/Lib/Managers/ExportManager.vala +++ /dev/null @@ -1,456 +0,0 @@ -/** - * Copyright (c) 2022-2023 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Lib.Managers.ExportManager : Object { - public signal void busy (string message); - public signal void show_preview (Gee.HashMap pixbufs); - public signal void free (); - public signal void export_finished (string message); - - public enum Type { - AREA, - SELECTION, - ARTBOARD - } - private Type export_type; - private Akira.Geometry.Rectangle area; - - public unowned Akira.Lib.ViewCanvas canvas { get; construct; } - - private Cairo.Format format; - private Cairo.ImageSurface? surface = null; - private Cairo.Context? context = null; - private Gdk.PixbufLoader loader; - private Gee.HashMap pixbufs; - - private GLib.Cancellable? preview_cancellable; - - public ExportManager (Lib.ViewCanvas view_canvas) { - Object (canvas: view_canvas); - pixbufs = new Gee.HashMap (); - } - - public async void export_selection () { - export_type = Type.SELECTION; - trigger_export_dialog (); - if (preview_cancellable != null) { - preview_cancellable.cancel (); - } - - preview_cancellable = new GLib.Cancellable (); - yield generate_preview (preview_cancellable); - } - - public async void export_area (Geometry.Rectangle bounds) { - export_type = Type.AREA; - area = bounds; - trigger_export_dialog (); - if (preview_cancellable != null) { - preview_cancellable.cancel (); - } - - preview_cancellable = new GLib.Cancellable (); - yield generate_preview (preview_cancellable); - } - - public async void generate_preview (GLib.Cancellable cancellable) { - busy (_("Generating preview, please wait…")); - - yield init_generate_preview (cancellable); - show_preview (pixbufs); - - free (); - } - - private async void init_generate_preview (GLib.Cancellable cancellable) { - pixbufs.clear (); - - if (settings.export_format == "png") { - format = Cairo.Format.ARGB32; - } else if (settings.export_format == "jpg") { - format = Cairo.Format.RGB24; - } - - switch (export_type) { - case Type.SELECTION: - yield generate_selection_pixbufs (cancellable); - break; - case Type.AREA: - yield generate_area_pixbuf (cancellable); - break; - } - } - - private async void generate_area_pixbuf (GLib.Cancellable cancellable) { - yield generate_image_surface (area); - var pixbuf = yield generate_pixbuf (surface); - - pixbufs.set (Lib.Items.Model.ORIGIN_ID, pixbuf); - } - - private async void generate_selection_pixbufs (GLib.Cancellable cancellable) { - // Loop through all items and clone the model. - unowned var selection = canvas.selection_manager.selection; - foreach (var node_id in selection.nodes.keys) { - var node = canvas.items_manager.node_from_id (node_id); - // Ignore a node if it doesn't exists, it's not attached to the canvas, or - // it's part of a group or artbaord. TODO: handle groups and artboards. - if (node == null || node.parent == null || node.parent.id != Lib.Items.Model.ORIGIN_ID) { - continue; - } - - unowned var inst = node.instance; - - // Account for the border size to define the export area. - double border_size = 0; - if (inst.components.borders != null) { - var size = inst.components.borders.get_border_width (); - // Currently we only support centered border as per SVG specs, but - // in the future we will support internal and external border types - // so we will need to account for those. - border_size = size > 0 ? size / 2 : 0; - } - - var top = inst.bounding_box.top - border_size; - var bottom = inst.bounding_box.bottom + border_size; - var left = inst.bounding_box.left - border_size; - var right = inst.bounding_box.right + border_size; - - var bounds = Geometry.Rectangle (); - bounds.top = top; - bounds.bottom = bottom; - bounds.left = left; - bounds.right = right; - - yield generate_image_surface (bounds); - var pixbuf = yield generate_pixbuf (surface); - - pixbufs.set (node_id, pixbuf); - } - } - - private async void generate_image_surface (Geometry.Rectangle bounds) { - double width = bounds.width; - double height = bounds.height; - scale_surface (ref width, ref height); - - // Create the rendered image with Cairo. - surface = new Cairo.ImageSurface ( - format, - (int) Math.round (width), - (int) Math.round (height) - ); - context = new Cairo.Context (surface); - - // Draw a white background if JPG export. - if (settings.export_format == "jpg" || !settings.export_alpha) { - context.set_source_rgba (1, 1, 1, 1); - context.rectangle ( - 0, 0, - (int) Math.round (width), - (int) Math.round (height) - ); - context.fill (); - } - - scale_context (ref context); - // Move the context to the right coordinates. - context.translate (-bounds.left, -bounds.top); - // Render what's currently on the canvas inside those coordinates. - canvas.draw_model (context, bounds); - } - - /* - * Scale the cairo surface to match the scaled canvas based on the chosen - * resolution from the user. This is to guarantee a sharp preview. - */ - private void scale_surface (ref double width, ref double height) { - switch (settings.export_scale) { - case 0: - width = width / 2; - height = height / 2; - break; - - case 2: - width = width * 2; - height = height * 2; - break; - - case 3: - width = width * 4; - height = height * 4; - break; - - default: - width = width * 1; - height = height * 1; - break; - } - } - - /* - * Scale the canvas context to match the user's export resolution. - */ - private void scale_context (ref Cairo.Context context) { - switch (settings.export_scale) { - case 0: - context.scale (0.5, 0.5); - break; - - case 2: - context.scale (2, 2); - break; - - case 3: - context.scale (4, 4); - break; - - default: - context.scale (1, 1); - break; - } - } - - /* - * Generate the pixbufs images on a separate async thread in order to now - * freeze the UI. - */ - private async Gdk.Pixbuf generate_pixbuf (Cairo.Surface surface) { - SourceFunc callback = generate_pixbuf.callback; - - var thread = new Thread (null, () => { - // Create pixbuf from stream. - try { - loader = new Gdk.PixbufLoader.with_mime_type ("image/png"); - } catch (Error e) { - error ("Could not create pixbuf loader: %s", e.message); - } - - surface.write_to_png_stream ((data) => { - try { - loader.write ((uint8 []) data); - } catch (Error e) { - return Cairo.Status.DEVICE_ERROR; - } - return Cairo.Status.SUCCESS; - }); - var pixbuf = loader.get_pixbuf (); - - try { - loader.close (); - } catch (Error e) { - error ("Could not close loader: %s", e.message); - } - - Idle.add ((owned) callback); - return pixbuf; - }); - - yield; - - return thread.join (); - } - - private void trigger_export_dialog () { - // Disable all those accels interfering with regular typing. - canvas.window.event_bus.disconnect_typing_accel (); - - var export_dialog = new Akira.Dialogs.ExportDialog (canvas, this); - export_dialog.show_all (); - export_dialog.present (); - - // Update the dialog UI based on the stored gsettings options. - export_dialog.update_format_ui (); - - export_dialog.close.connect (() => { - if (preview_cancellable != null) { - preview_cancellable.cancel (); - } - - // Store the dialog size into gsettings so users don't get upset. - int width, height; - export_dialog.get_size (out width, out height); - settings.export_width = width; - settings.export_height = height; - - // Enable accels again. - canvas.window.event_bus.connect_typing_accel (); - canvas.window.event_bus.set_focus_on_canvas (); - - // Clean up. - pixbufs.clear (); - context = null; - surface = null; - }); - } - - public async void export_images (GLib.ListStore list_store) { - busy (_("Exporting images…")); - - bool overwrite_all = false; - bool skip_all = false; - - // Loop through all generated models and handle the save to a file. - for (int i = 0; i < list_store.get_n_items () ; i++) { - var model = (Akira.Models.ExportModel) list_store.get_object (i); - var pixbuf = model.pixbuf; - var file_name = ("%s/%s.%s").printf ( - settings.export_folder, - model.filename, - settings.export_format - ); - - // Check for existing files to avoid overwriting them. - var image_file = File.new_for_path (file_name); - if (image_file.query_exists ()) { - // Overwrite them all if the user specified it in the dialog - // during the first loop. - if (overwrite_all) { - yield do_export (pixbuf, file_name); - continue; - } - - // Skip them all if the user specified it in the dialog - // during the first loop. - if (skip_all) { - free (); - continue; - } - - // Ask the user what to do. - var results = confirm_overwrite (file_name); - switch (results[0]) { - // Overwrite. - case 3: - overwrite_all = results[1] == 1; - yield do_export (pixbuf, file_name); - break; - // Skip. - case 2: - skip_all = results[1] == 1; - free (); - continue; - // Cancel. - case 1: - default: - free (); - return; - } - continue; - } - - // This file doesn't exist, just export it. - yield do_export (pixbuf, file_name); - } - - free (); - export_finished (_("Export completed!")); - } - - /* - * Trigger a dialog asking the user how to handle an existing file with - * the same filename. - */ - private int[] confirm_overwrite (string file_name) { - int dont_ask = 0; - int clicked = 0; - var dialog = canvas.window.dialogs.message_dialog ( - _("File already exists!"), - _("The file at this location already exists: %s.").printf (file_name), - "dialog-question", - _("Overwrite file"), - _("Skip file") - ); - - // If we're currently exporting more than one image, offer the option - // to use the chosen action as default in the current export loop. - if (pixbufs.size > 1) { - var checkbox = new Gtk.CheckButton.with_label (_("Apply the same action for all other files")); - dialog.custom_bin.add (checkbox); - checkbox.toggled.connect (() => { - dont_ask = checkbox.active ? 1 : 0; - }); - } - - dialog.show_all (); - - dialog.response.connect ((id) => { - switch (id) { - case Gtk.ResponseType.ACCEPT: - clicked = 3; - dialog.destroy (); - break; - case 2: - clicked = 2; - dialog.destroy (); - break; - default: - clicked = 1; - dialog.destroy (); - break; - } - }); - - // Use run() to make the UI busy and freeze the loop until we get a response. - dialog.run (); - - return new int[] {clicked, dont_ask}; - } - - /* - * Handle the actual export inside another async thread to avoid freezing - * the UI while exporting large images. - */ - private async void do_export (Gdk.Pixbuf pixbuf, string file_name) { - SourceFunc callback = do_export.callback; - - new Thread (null, () => { - try { - if (settings.export_format == "png") { - pixbuf.save ( - file_name, - "png", - "compression", - settings.export_compression.to_string (), - null); - } - - if (settings.export_format == "jpg") { - pixbuf.save ( - file_name, - "jpeg", - "quality", - settings.export_quality.to_string (), - null); - } - } catch (Error e) { - error ("Unable to export images: %s", e.message); - } - - Idle.add ((owned) callback); - Thread.exit (null); - - return null; - }); - - yield; - } -} diff --git a/src/Lib/Managers/HistoryManager.vala b/src/Lib/Managers/HistoryManager.vala deleted file mode 100644 index 0df910d9b..000000000 --- a/src/Lib/Managers/HistoryManager.vala +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * - */ -public class Akira.Lib.Managers.HistoryManager : Object { - public unowned ViewCanvas view_canvas { get; construct; } - - public class Snapshot { - public Snapshot (string description, Lib.Items.Model model) { - this.description = description; - this.model = model; - } - - public string description; - public Lib.Items.Model model; - } - - private Gee.LinkedList undo_stack; - private Gee.LinkedList redo_stack; - - - public HistoryManager (ViewCanvas canvas) { - Object (view_canvas : canvas); - view_canvas.window.event_bus.create_model_snapshot.connect (snapshot); - view_canvas.window.event_bus.undo.connect (undo); - view_canvas.window.event_bus.redo.connect (redo); - } - - construct { - undo_stack = new Gee.LinkedList (); - redo_stack = new Gee.LinkedList (); - } - - private void snapshot (string description) { - unowned var im = view_canvas.items_manager; - var clone = new Lib.Items.Model.clone (im.item_model); - undo_stack.add (new Snapshot (description, clone)); - - redo_stack.clear (); - } - - public void undo () { - apply_snapshot (undo_stack, redo_stack); - } - - public void redo () { - apply_snapshot (redo_stack, undo_stack); - } - - /* - * Implementation for undo/redo. Shared since they are symmetric. - */ - private void apply_snapshot (Gee.LinkedList source, Gee.LinkedList other) { - if (source.size == 0) { - return; - } - - unowned var im = view_canvas.items_manager; - view_canvas.selection_manager.reset_selection (); - view_canvas.mode_manager.deregister_active_mode (); - view_canvas.hover_manager.remove_hover_effect (); - - var last_stack = source.last (); - source.remove (last_stack); - other.add (new Snapshot (last_stack.description, new Lib.Items.Model.clone (im.item_model))); - - // replace model - im.replace_model (last_stack.model); - - // Regenerate the layers list. - view_canvas.window.main_window.regenerate_list (); - } - -} diff --git a/src/Lib/Managers/HoverManager.vala b/src/Lib/Managers/HoverManager.vala deleted file mode 100644 index ae7ccd536..000000000 --- a/src/Lib/Managers/HoverManager.vala +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Lib.Managers.HoverManager : Object { - // Signal used to notify other parts of the UI that the hover effect on a - // canvas item has changed. This must be used exclusively from the canvas to - // other items, and not vice-versa. If a UI element has to trigger the hover - // state of an item (like the layers), a dedicated method should be created - // that doesn't trigger this signal. - public signal void hover_changed (int? id); - - public unowned ViewCanvas view_canvas { get; construct; } - - private int current_hovered_id = -1; - private ViewLayers.ViewLayerHover hover_layer; - - public HoverManager (ViewCanvas canvas) { - Object (view_canvas : canvas); - } - - construct { - hover_layer = new ViewLayers.ViewLayerHover (); - hover_layer.add_to_canvas (ViewLayers.ViewLayer.HOVER_LAYER_ID, view_canvas); - } - - public void on_mouse_over (double event_x, double event_y) { - var target = view_canvas.items_manager.node_at_canvas_position ( - event_x, - event_y, - Drawables.Drawable.HitTestType.SELECT - ); - - // Remove the hover effect if no item is hovered. - // TODO: artboard - if (target == null) { - remove_hover_effect (); - hover_changed (null); - return; - } - - if (view_canvas.selection_manager.item_selected (target.id)) { - return; - } - - unowned var sm = view_canvas.selection_manager; - // Account for groups. - sm.ensure_correct_target (ref target); - - maybe_create_hover_effect (target); - return; - } - - public void remove_hover_effect () { - hover_layer.add_drawable (null); - hover_layer.set_visible (false); - current_hovered_id = -1; - } - - public void maybe_create_hover_effect_by_id (int id) { - var node = view_canvas.items_manager.node_from_id (id); - if (node == null) { - print ("Failed to create hover effect for %d", id); - assert (node != null); - return; - } - - if (view_canvas.selection_manager.item_selected (id)) { - return; - } - - maybe_create_hover_effect (node); - } - - private void maybe_create_hover_effect (Lib.Items.ModelNode node) { - if (current_hovered_id == node.id) { - return; - } - - remove_hover_effect (); - hover_layer.add_drawable (node.instance.drawable); - current_hovered_id = node.id; - hover_changed (node.instance.id); - } -} diff --git a/src/Lib/Managers/ItemsManager.vala b/src/Lib/Managers/ItemsManager.vala deleted file mode 100644 index a695cf1bb..000000000 --- a/src/Lib/Managers/ItemsManager.vala +++ /dev/null @@ -1,713 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Lib.Managers.ItemsManager : Object, Items.ModelListener { - private const bool CUSTOM_HITTEST = true; - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - private Lib.Items.Model p_item_model; - - public unowned Lib.Items.Model item_model { get { return p_item_model; } } - - public ItemsManager (Lib.ViewCanvas canvas) { - Object (view_canvas: canvas); - } - - construct { - p_item_model = new Lib.Items.Model.live_model (this, view_canvas); - - view_canvas.window.event_bus.selection_align.connect (selection_align); - } - - public void replace_model (Lib.Items.Model replacement) { - p_item_model = replacement; - p_item_model.wake (this, true); - view_canvas.set_model_to_render (p_item_model); - compile_model (); - } - - public signal void item_added (int id); - public signal void items_removed (GLib.Array ids); - public signal void item_transferred (int id); - - public void on_item_added (int id) { - item_added (id); - } - - public void on_item_geometry_changed (int id) { - view_canvas.selection_manager.on_selection_changed (id); - } - - public void on_items_deleted (GLib.Array ids) { - items_removed (ids); - } - - public void on_item_transferred (int id) { - item_transferred (id); - } - - public Lib.Items.ModelInstance? instance_from_id (int id) { - return item_model.instance_from_id (id); - } - - public Lib.Items.ModelNode? node_from_id (int id) { - return item_model.node_from_id (id); - } - - public int add_item_to_origin (Lib.Items.ModelInstance instance) { - return add_item_to_group (Lib.Items.Model.ORIGIN_ID, instance); - } - - public int add_item_to_group (int group_id, Lib.Items.ModelInstance instance, bool pause_compile = false) { - if (instance == null) { - return -1; - } - - if (item_model.append_new_item (group_id, instance) <= 0) { - return -1; - } - - if (!pause_compile) { - compile_model (); - } - - return instance.id; - } - - public int remove_items (GLib.Array to_remove, bool pause_compile = false) { - ulong microseconds; - double seconds; - - // create a timer object: - Timer timer = new Timer (); - - var to_delete = new Gee.TreeMap ( - Lib.Items.PositionKey.compare, - null - ); - - var modified_groups = new GLib.Array (); - - foreach (var id in to_remove.data) { - var node = item_model.node_from_id (id); - - if (node == null) { - continue; - } - - var key = new Lib.Items.PositionKey (); - key.parent_path = node.parent == null ? "" : item_model.path_from_node (node.parent); - key.pos_in_parent = node.pos_in_parent; - - to_delete[key] = node.instance; - - if (modified_groups.length == 0) { - modified_groups.append_val (node.parent.id); - continue; - } - - foreach (var gid in modified_groups.data) { - if (gid != node.parent.id) { - modified_groups.append_val (node.parent.id); - break; - } - } - } - - // Collect the nodes' ids to be removed in order to let the layers UI - // be aware of what to remove without needing to access selection manager - // which immediately loses the list of selected nodes. - var ids_array = new GLib.Array (); - - var it = to_delete.bidir_map_iterator (); - for (var has_next = it.last (); has_next; has_next = it.previous ()) { - var inst = it.get_value (); - ids_array.append_val (inst.id); - - if (0 != item_model.remove (inst.id, false)) { - assert (false); - continue; - } - } - - foreach (var gid in modified_groups.data) { - item_model.recalculate_children_stacking (gid); - } - - // TODO: move this to the model, have it collect deleted ids and alert this - items_removed (ids_array); - - if (!pause_compile) { - compile_model (); - } - - timer.stop (); - seconds = timer.elapsed (out microseconds); - print ("Deleted %u items in %s s\n", to_remove.length, seconds.to_string ()); - return 0; - } - - /* - * Alerts the model to recompile all dirty geometries. - */ - public void compile_model () { - item_model.compile_geometries (); - } - - /* - * Shift items by an amount up or down. - * If to_end is true, amount is only used for direction (down/up) - */ - public int shift_items (GLib.Array ids, int amount, bool to_end) { - if (amount == 0) { - return 0; - } - - var sorted_tree = new Gee.TreeMap ( - Lib.Items.PositionKey.compare, - null - ); - - var shift_groups = new Gee.ArrayList (); - - foreach (var id in ids.data) { - var node = item_model.node_from_id (id); - if (node == null) { - continue; - } - - var key = new Lib.Items.PositionKey (); - key.parent_path = node.parent == null ? "" : item_model.path_from_node (node.parent); - key.pos_in_parent = node.pos_in_parent; - - sorted_tree[key] = node; - } - - Lib.Items.ChildrenSet current_set = null; - int last_group_id = -1; - int last_pos = -1; - foreach (var mapit in sorted_tree) { - var snode = mapit.value; - bool is_next = last_group_id == snode.parent.id && snode.pos_in_parent == last_pos + 1; - - if (!is_next) { - last_group_id = snode.parent.id; - last_pos = snode.pos_in_parent; - - current_set = new Lib.Items.ChildrenSet (); - current_set.parent_node = snode.parent; - current_set.first_child = last_pos; - current_set.children_in_set = new GLib.Array (); - current_set.children_in_set.append_val (snode); - current_set.length = 1; - - shift_groups.add (current_set); - continue; - } - - last_pos = snode.pos_in_parent; - current_set.children_in_set.append_val (snode); - current_set.length++; - } - - bool no_operation_yet = true; - Utils.TrivialDelegate prep = () => { - view_canvas.window.event_bus.create_model_snapshot ("shift items' z-order"); - // run only once - no_operation_yet = false; - }; - - view_canvas.pause_redraw = true; - foreach (var cs in shift_groups) { - var pos = cs.first_child; - - var newpos = pos + amount; - - if (to_end) { - newpos = (amount > 0) ? (int)(cs.parent_node.children.length - cs.length) : 0; - } - - if (newpos < 0) { - newpos = 0; - } - - if (newpos + cs.length > cs.parent_node.children.length) { - newpos = (int)(cs.parent_node.children.length - cs.length); - } - - if (newpos < 0 || newpos + cs.length > cs.parent_node.children.length) { - cs = null; - // at edges, nothing to do - continue; - } - - if (0 >= item_model.move_items (cs.parent_node.id, pos, newpos, cs.length, true, prep)) { - // no items were shifted - cs = null; - continue; - } - } - - view_canvas.pause_redraw = false; - compile_model (); - view_canvas.request_redraw (view_canvas.get_bounds ()); - - return 0; - } - - public void flip_items (GLib.Array ids, bool vertical) { - /* - var blocker = new Lib.Managers.SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - - foreach (var target_id in ids.data) { - var target = item_model.instance_from_id (target_id); - if (target.item != null) { - unowned var old_flipped = target.item.components.flipped; - bool new_h = false; - bool new_v = false; - - if (old_flipped != null) { - new_h = old_flipped.horizontal; - new_v = old_flipped.vertical; - } - - new_h = vertical ? new_h : !new_h; - new_v = vertical ? !new_v : new_h; - - if (target.item.components.rotation != null) { - var tr = target.item.compiled_geometry.transform; - tr.x0 = 0; - tr.y0 = 0; - - double offset = vertical ? 0 : 90; - double start_x = vertical ? 0 : -1; - double start_y = vertical ? -1 : 0; - tr.transform_point (ref start_x, ref start_y); - double flipped_x = start_x; - double flipped_y = start_y; - - var radians = GLib.Math.atan2 ( - flipped_x, - flipped_y - ); - - var rotation = GLib.Math.fmod (radians * 180 / GLib.Math.PI + offset, 360); - target.item.components.rotation = new Lib.Components.Rotation (rotation); - } - - - target.item.components.flipped = new Lib.Components.Flipped (new_h, new_v); - target.item.mark_geometry_dirty (); - } - } - - compile_model (); - */ - } - - public GLib.Array children_in_group (int group_id) { - return item_model.children_in_group (group_id); - } - - public Lib.Items.ModelNode? node_at_canvas_position ( - double x, - double y, - Drawables.Drawable.HitTestType hit_test_type - ) { - var found_items = nodes_at_canvas_position (x, y, hit_test_type); - if (found_items.size == 0) { - return null; - } - - return found_items.last (); - } - - public Gee.ArrayList nodes_in_bounded_region ( - Geometry.Rectangle bound - ) { - var found_items = new Gee.ArrayList (); - - var origin = item_model.node_from_id (Lib.Items.Model.ORIGIN_ID); - - if (origin.children == null) { - return found_items; - } - - foreach (unowned var node in origin.children.data) { - var node_type = node.instance.type.name_id; - - if (node_type == "artboard" && node.children != null) { - foreach (unowned var child_node in node.children.data) { - // Only add items that are not currently selected. - if ( - !child_node.instance.components.layer.locked && - !view_canvas.selection_manager.item_selected (child_node.id) && - bound.contains_bound (child_node.instance.bounding_box) - ) { - found_items.add (child_node); - } - } - continue; - } - - // Only add items that are not currently selected. - if ( - !node.instance.components.layer.locked && - !view_canvas.selection_manager.item_selected (node.id) && - bound.contains_bound (node.instance.bounding_box) - ) { - found_items.add (node); - } - } - - return found_items; - } - - /* - * Returns the top-most group at position. Origin if no other group found. - */ - public Lib.Items.ModelNode first_group_at (double x, double y) { - var found_items = nodes_at_canvas_position (x, y, Drawables.Drawable.HitTestType.GROUP_REGION); - - var it = found_items.bidir_list_iterator (); - for (var has_next = it.last (); has_next; has_next = it.previous ()) { - unowned var cand = it.get (); - if (cand.instance.is_group) { - return cand; - } - } - - return item_model.node_from_id (Lib.Items.Model.ORIGIN_ID); - } - - public Gee.ArrayList nodes_at_canvas_position ( - double x, - double y, - Drawables.Drawable.HitTestType hit_test_type - ) { - Cairo.ImageSurface surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, 1, 1); - Cairo.Context context = new Cairo.Context (surface); - context.set_antialias (Cairo.Antialias.GRAY); - context.set_line_width (2.0); - - var found_items = new Gee.ArrayList (); - - var origin = item_model.node_from_id (Lib.Items.Model.ORIGIN_ID); - if (origin.children == null) { - return found_items; - } - - foreach (unowned var root in origin.children.data) { - root.items_in_canvas (x, y, context, view_canvas.scale, hit_test_type, ref found_items); - } - return found_items; - } - - /* - private void view_restack (Lib.Items.ChildrenSet children_set, bool up, Lib.Items.ModelNode reference) { - if (reference == null) { - assert (reference != null); - return; - } - if (children_set.children_in_set.length == 0) { - return; - } - - if (up) { - restack_up (children_set, reference); - return; - } - - restack_down (children_set, reference); - } - - private bool restack_up (Lib.Items.ChildrenSet children_set, Lib.Items.ModelNode reference) { - var sibling_under = Lib.Items.Model.previous_sibling (reference, true); - - if (sibling_under == null) { - return false; - } - - - for (var i = (int) children_set.children_in_set.length - 1; i >= 0; --i) { - unowned var model_item = children_set.children_in_set.index (i).instance.item; - if (model_item.is_stackable ()) { - model_item.canvas_item.raise (sibling_under.instance.item.canvas_item); - } - } - return true; - } - - private bool restack_down (Lib.Items.ChildrenSet children_set, Lib.Items.ModelNode reference) { - var sibling_over = Lib.Items.Model.next_sibling (reference, true); - - if (sibling_over == null) { - return false; - } - - foreach (var to_restack in children_set.children_in_set.data) { - unowned var model_item = to_restack.instance.item; - if (model_item.is_stackable ()) { - model_item.canvas_item.lower (sibling_over.instance.item.canvas_item); - } - } - return true; - } - */ - - public Lib.Items.ModelInstance add_debug_rect (double x, double y) { - var new_rect = Lib.Items.ModelTypeEllipse.default_ellipse ( - //new Lib.Components.Coordinates (x + i * 60, y), - new Lib.Components.Coordinates (x, y), - new Lib.Components.Size (50.0, 50.0, false), - new Lib.Components.Borders.single_color (Lib.Components.Color (0.3, 0.3, 0.3, 1.0), 2), - new Lib.Components.Fills.with_color (Lib.Components.Color (0.0, 0.0, 0.0, 1.0)) - ); - - add_item_to_origin (new_rect); - - return new_rect; - } - - public Lib.Items.ModelInstance add_debug_group (double x, double y, bool debug_timer = false) { - ulong microseconds; - double seconds; - - // create a timer object: - Timer timer = new Timer (); - - var blocker = new Lib.Managers.SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - view_canvas.pause_redraw = true; - - var group = Lib.Items.ModelTypeArtboard.default_artboard ( - new Lib.Components.Coordinates (520, 520), - new Lib.Components.Size (1000, 1000, false) - ); - add_item_to_origin (group); - - var num_of = 1000; - - for (var i = 0; i < num_of; ++i) { - x = GLib.Random.double_range (0, 1000); - y = GLib.Random.double_range (0, 1000); - - var new_rect = Lib.Items.ModelTypeEllipse.default_ellipse ( - //new Lib.Components.Coordinates (x + i * 60, y), - new Lib.Components.Coordinates (x, y), - new Lib.Components.Size (50.0, 50.0, false), - new Lib.Components.Borders.single_color (Lib.Components.Color (0.3, 0.3, 0.3, 1.0), 2), - new Lib.Components.Fills.with_color (Lib.Components.Color (0.0, 0.0, 0.0, 1.0)) - ); - - add_item_to_group (group.id, new_rect, true); - } - - compile_model (); - view_canvas.pause_redraw = false; - view_canvas.request_redraw (view_canvas.get_bounds ()); - - // Regenerate the layers list. - view_canvas.window.main_window.regenerate_list (); - - if (debug_timer) { - timer.stop (); - seconds = timer.elapsed (out microseconds); - print ("Created %u items in %s s\n", num_of, seconds.to_string ()); - } - - return group; - } - - public void debug_add_rectangles (uint num_of, bool debug_timer = false) { - // Always reset the selection before adding a chunk of items. - view_canvas.selection_manager.reset_selection (); - - ulong microseconds; - double seconds; - - // create a timer object: - Timer timer = new Timer (); - - var blocker = new SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - view_canvas.pause_redraw = true; - - for (var i = 0; i < num_of; ++i) { - var x = GLib.Random.double_range (0, (GLib.Math.log (num_of + GLib.Math.E) - 1) * 1000); - var y = GLib.Random.double_range (0, (GLib.Math.log (num_of + GLib.Math.E) - 1) * 1000) + 500; - var new_item = add_debug_rect (x, y); - view_canvas.selection_manager.add_to_selection (new_item.id); - } - - view_canvas.pause_redraw = false; - view_canvas.request_redraw (view_canvas.get_bounds ()); - - // Regenerate the layers list. - view_canvas.window.main_window.regenerate_list (); - - if (debug_timer) { - timer.stop (); - seconds = timer.elapsed (out microseconds); - print ("Created %u items in %s s\n", num_of, seconds.to_string ()); - } - } - - public void create_group_from_selection () { - // Don't create a group if we don't have any node selected. - unowned var selection = view_canvas.selection_manager.selection; - if (selection.count () == 0) { - return; - } - - var blocker = new SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - view_canvas.pause_redraw = true; - - var sorted_tree = new Gee.TreeMap ( - Lib.Items.PositionKey.compare, - null - ); - - var shift_groups = new Gee.ArrayList (); - - foreach (var node_id in selection.nodes.keys) { - var node = item_model.node_from_id (node_id); - if (node == null) { - continue; - } - - var key = new Lib.Items.PositionKey (); - key.parent_path = node.parent == null ? "" : item_model.path_from_node (node.parent); - key.pos_in_parent = node.pos_in_parent; - - sorted_tree[key] = node; - } - - Lib.Items.ChildrenSet current_set = null; - int target_group_id = -1; - int target_group_pos = -1; - int last_pos = -1; - foreach (var mapit in sorted_tree) { - var snode = mapit.value; - bool is_next = target_group_id == snode.parent.id && snode.pos_in_parent == last_pos + 1; - - if (!is_next) { - target_group_id = snode.parent.id; - last_pos = snode.pos_in_parent; - target_group_pos = last_pos; - - current_set = new Lib.Items.ChildrenSet (); - current_set.parent_node = snode.parent; - current_set.first_child = last_pos; - current_set.children_in_set = new GLib.Array (); - current_set.children_in_set.append_val (snode); - current_set.length = 1; - - shift_groups.add (current_set); - continue; - } - - last_pos = snode.pos_in_parent; - current_set.children_in_set.append_val (snode); - current_set.length++; - } - - if (target_group_id < Lib.Items.Model.ORIGIN_ID) { - assert (false); - return; - } - - - // Clear the current selection so we don't stumble upon weird states. - view_canvas.selection_manager.reset_selection (); - - view_canvas.window.event_bus.create_model_snapshot ("create group from selection"); - - unowned var model = view_canvas.items_manager.item_model; - // Create a new empty group and add it to the main canvas. - var group = Lib.Items.ModelTypeGroup.default_group (); - - var result_id = model.splice_new_item (target_group_id, int.MAX, group); - assert (result_id > Lib.Items.Model.ORIGIN_ID); - - var it = shift_groups.bidir_list_iterator (); - for (var has_next = it.last (); has_next; has_next = it.previous ()) { - var sg = it.get (); - - if (0 != model.transfer ( - sg.parent_node.id, - sg.first_child, - sg.length, - result_id, - int.MAX, - true, - null - )) { - assert (false); - return; - } - } - - - var container = model.node_from_id (target_group_id); - - var new_group = model.node_from_id (result_id); - if (model.move_items (container.id, new_group.pos_in_parent, target_group_pos, 1, true, null) < 0) { - assert (false); - } - - compile_model (); - view_canvas.pause_redraw = false; - view_canvas.request_redraw (view_canvas.get_bounds ()); - - // Regenerate the layers list. - view_canvas.window.main_window.regenerate_list (); - // Select the newly created group. - view_canvas.selection_manager.add_to_selection (group.id); - } - - public void selection_align (Utils.ItemAlignment.AlignmentDirection direction) { - unowned var selection = view_canvas.selection_manager.selection; - if (selection.count () <= 1) { - return; - } - - unowned int? anchor_point_node_id = view_canvas.nob_manager.anchor_point_node_id; - - var type = Utils.ItemAlignment.AlignmentType.AUTO; - Lib.Items.ModelNode? anchor = null; - - if (anchor_point_node_id != null) { - anchor = node_from_id (anchor_point_node_id); - type = Utils.ItemAlignment.AlignmentType.ANCHOR; - } - - Utils.TrivialDelegate prep = () => { - view_canvas.window.event_bus.create_model_snapshot ("autoalign items"); - }; - - Utils.ItemAlignment.align_selection (selection, direction, type, anchor, view_canvas, prep); - } - -} diff --git a/src/Lib/Managers/ModeManager.vala b/src/Lib/Managers/ModeManager.vala deleted file mode 100644 index 95ef6b687..000000000 --- a/src/Lib/Managers/ModeManager.vala +++ /dev/null @@ -1,217 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/** - * Manages InteractionMode's via registration. This class can be plugged into the event methods of a Canvas - * in order to allow these modes to affect items in the canvas as well as allowing them to absorb said - * events. - * - * Only one InteractionMode is guaranteed to exist at a time, and this manager will correctly alert the - * beginning and end of a registered mode. - * - * The exception to the above rule is pan_mode, which can be running on top of another mode in certain cases and - * masks events appropriately. - * - * See InteractionMode.vala for more details on how to create modes. - */ -public class Akira.Lib.Managers.ModeManager : Object { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - private Lib.Modes.PanMode pan_mode; - private Lib.Modes.AbstractInteractionMode active_mode; - - public Lib.Modes.AbstractInteractionMode.ModeType active_mode_type { - get { - return (active_mode == null) ? Lib.Modes.AbstractInteractionMode.ModeType.NONE : active_mode.mode_type (); - } - } - - public Utils.Nobs.Nob active_mode_nob { - get { - return (active_mode == null) ? Utils.Nobs.Nob.ALL : active_mode.active_nob (); - } - } - - public ModeManager (Akira.Lib.ViewCanvas canvas) { - Object (view_canvas: canvas); - - // any active mode must be ended when user presses Esc. - view_canvas.window.event_bus.request_escape.connect (() => { - deregister_active_mode (); - }); - } - - public signal void mode_changed (); - - /* - * Register a new mode as the active mode. Any prior mode will be deregistered. - */ - public void register_mode (Akira.Lib.Modes.AbstractInteractionMode new_mode) { - if (active_mode != null) { - inner_deregister_active_mode (false); - } - - active_mode = new_mode; - active_mode.request_deregistration.connect (on_deregistration_request); - active_mode.mode_begin (); - mode_changed (); - } - - /* - * Deregister active mode or pan mode if it matches the mode_type. - * This should generally be used for safety since a new mode may already have been - * registered by the time this method is called. - */ - public void deregister_mode (Akira.Lib.Modes.AbstractInteractionMode.ModeType mode_type) { - if (active_mode != null && active_mode.mode_type () == mode_type) { - inner_deregister_active_mode (true); - } else if (pan_mode != null && pan_mode.mode_type () == mode_type) { - stop_panning_mode (); - } - } - - /* - * Deregister the currently active mode. - */ - public void deregister_active_mode () { - if (active_mode != null) { - inner_deregister_active_mode (true); - } - } - - /* - * Start panning mode that will mask any existing mode. Also, other modes may be started - * during panning mode in certain conditions. - */ - public void start_panning_mode () { - if (pan_mode != null) { - return; - } - - pan_mode = new Akira.Lib.Modes.PanMode (view_canvas); - pan_mode.request_deregistration.connect (on_deregistration_request); - pan_mode.mode_begin (); - - mode_changed (); - } - - /* - * Stops panning mode. - */ - public void stop_panning_mode () { - if (pan_mode != null) { - inner_stop_panning_mode (true); - } - } - - /* - * Inner panning mode stop method with optional notification to canvas. - */ - private void inner_stop_panning_mode (bool notify) { - pan_mode.request_deregistration.disconnect (on_deregistration_request); - pan_mode.mode_end (); - pan_mode = null; - - if (notify) { - mode_changed (); - } - } - - /* - * Inner mode deregistration method with optional notification to canvas. - */ - private void inner_deregister_active_mode (bool notify) { - active_mode.request_deregistration.disconnect (on_deregistration_request); - active_mode.mode_end (); - active_mode = null; - - if (notify) { - mode_changed (); - } - } - - /* - * Returns optional extra context. See InteractionMode for more details. - */ - public Object? active_mode_extra_context () { - if (pan_mode != null) { - return pan_mode.extra_context (); - } - - return active_mode != null ? active_mode.extra_context () : null; - } - - /* - * Returns cursor that should be used based on active modes. - */ - public Gdk.CursorType? active_cursor_type () { - if (pan_mode != null) { - return pan_mode.cursor_type (); - } - - return active_mode != null ? active_mode.cursor_type () : null; - } - - public bool key_press_event (Gdk.EventKey event) { - if (pan_mode != null && pan_mode.key_press_event (event)) { - return false; - } - - return (active_mode != null) ? active_mode.key_press_event (event) : false; - } - - public bool key_release_event (Gdk.EventKey event) { - if (pan_mode != null && pan_mode.key_release_event (event)) { - return true; - } - - return (active_mode != null) ? active_mode.key_release_event (event) : false; - } - - public bool button_press_event (Gdk.EventButton event) { - if (pan_mode != null && pan_mode.button_press_event (event)) { - return true; - } - - return (active_mode != null) ? active_mode.button_press_event (event) : false; - } - - public bool button_release_event (Gdk.EventButton event) { - if (pan_mode != null && pan_mode.button_release_event (event)) { - return true; - } - - return (active_mode != null) ? active_mode.button_release_event (event) : false; - } - - public bool motion_notify_event (Gdk.EventMotion event) { - if (pan_mode != null && pan_mode.motion_notify_event (event)) { - return true; - } - - return (active_mode != null) ? active_mode.motion_notify_event (event) : false; - } - - private void on_deregistration_request (Lib.Modes.AbstractInteractionMode.ModeType type) { - deregister_mode (type); - } -} diff --git a/src/Lib/Managers/NobManager.vala b/src/Lib/Managers/NobManager.vala deleted file mode 100644 index 5747ea289..000000000 --- a/src/Lib/Managers/NobManager.vala +++ /dev/null @@ -1,172 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * - */ -public class Akira.Lib.Managers.NobManager : Object { - private const string STROKE_COLOR = "#666"; - private const double LINE_WIDTH = 1.0; - - public weak Lib.ViewCanvas view_canvas { get; construct; } - - private Utils.Nobs.NobSet nobs; - private ViewLayers.ViewLayerNobs nob_layer = null; - public int? anchor_point_node_id; - - // Tracks if an artboard is part of the current selection. - private int last_id = -1; - - public NobManager (Lib.ViewCanvas canvas) { - Object (view_canvas: canvas); - } - - construct { - nobs = new Utils.Nobs.NobSet (); - - view_canvas.window.event_bus.selection_geometry_modified.connect (on_update_select_effect); - view_canvas.mode_manager.mode_changed.connect (on_update_select_effect); - nob_layer = new ViewLayers.ViewLayerNobs (); - nob_layer.add_to_canvas (ViewLayers.ViewLayer.NOBS_LAYER_ID, view_canvas); - } - - public Utils.Nobs.Nob hit_test (double x, double y) { - double scale = view_canvas.current_scale; - return nobs.hit_test (x, y, scale); - } - - private void on_update_select_effect () { - unowned var sm = view_canvas.selection_manager; - if (sm.is_empty ()) { - remove_select_effect (); - remove_anchor_point_effect (); - anchor_point_node_id = null; - return; - } - - int new_id = sm.selection.first_node ().id; - last_id = new_id; - update_nob_positions (sm.selection); - update_nob_layer (); - - // Set the nob layer visible after is has been set non-visible by remove_select_effect - nob_layer.set_visible (true); - } - - /* - * Resets all selection and nob items. - */ - private void remove_select_effect () { - nobs.set_active (false); - update_nob_layer (); - nob_layer.set_visible (false); - last_id = -1; - } - - /** - * Update the position of all nobs of selected items. It will show or hide - * them based on the properties of the selection. - */ - private void update_nob_positions (Lib.Items.NodeSelection selection) { - var nob_size = Utils.Nobs.NobData.NOB_SIZE / view_canvas.current_scale; - - var rect = selection.area ().quad (); - - var width = rect.width; - var height = rect.height; - - bool show_h_centers = height > nob_size * 3; - bool show_v_centers = width > nob_size * 3; - - var active_nob_id = view_canvas.mode_manager.active_mode_nob; - - foreach (var nob in nobs.data) { - bool set_visible = true; - - if (!show_h_centers && Utils.Nobs.is_horizontal_center (nob.handle_id)) { - set_visible = false; - } else if (!show_v_centers && Utils.Nobs.is_vertical_center (nob.handle_id)) { - set_visible = false; - } - - update_nob (ref nob, rect, set_visible && !nob_masked (nob, active_nob_id)); - } - } - - private bool nob_masked (Utils.Nobs.NobData nob, Utils.Nobs.Nob nob_id) { - if (nob_id == Utils.Nobs.Nob.NONE) { - return true; - } else if (nob_id == Utils.Nobs.Nob.ALL) { - return false; - } - - return nob.handle_id != nob_id; - } - - private void update_nob ( - ref Utils.Nobs.NobData nob, - Geometry.Quad rect, - bool show - ) { - double sc = view_canvas.current_scale; - var n0 = nob.handle_id; - double cx = 0; - double cy = 0; - Utils.Nobs.nob_xy_from_coordinates (n0, rect, sc, ref cx, ref cy); - - nob.center_x = cx; - nob.center_y = cy; - nob.active = show; - } - - private void update_nob_layer () { - nob_layer.update_nob_data (nobs); - } - - public void toggle_anchor_point (int id) { - remove_anchor_point_effect (); - - if (anchor_point_node_id == id) { - anchor_point_node_id = null; - return; - } - - anchor_point_node_id = id; - - maybe_create_anchor_point_effect (); - } - - private void remove_anchor_point_effect () { - nob_layer.add_anchor_point (null); - } - - private void maybe_create_anchor_point_effect () { - var node = view_canvas.items_manager.node_from_id (anchor_point_node_id); - if (node == null) { - assert (node != null); - return; - } - - nob_layer.add_anchor_point (node.instance.drawable); - } - -} diff --git a/src/Lib/Managers/SelectionManager.vala b/src/Lib/Managers/SelectionManager.vala deleted file mode 100644 index b0f15e951..000000000 --- a/src/Lib/Managers/SelectionManager.vala +++ /dev/null @@ -1,211 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Lib.Managers.SelectionManager : Object { - // Signal triggered only when an item is added or removed from the selection - // map exclusively via click event from the ViewCanvas. This is necessary in - // order to only update the Layers panel without triggering a selection loop. - public signal void selection_modified_external (bool go_to_layer = false); - - public unowned ViewCanvas view_canvas { get; construct; } - - protected enum ChangeType { - NONE = 0, - TOPOLOGY = 1, - GEOMETRY = 2, - ALL = TOPOLOGY | GEOMETRY; - } - - /* - * Blocks notifications until class is destructed. - */ - public class ChangeSignalBlocker { - private unowned SelectionManager manager; - - public ChangeSignalBlocker (SelectionManager sm) { - this.manager = sm; - this.manager.block_change_notifications += 1; - } - - ~ChangeSignalBlocker () { - manager.block_change_notifications -= 1; - manager.inner_selection_changed (-1, manager.change_blocked); - } - } - - public Lib.Items.NodeSelection selection; - protected int block_change_notifications = 0; - protected ChangeType change_blocked = ChangeType.NONE; - - public SelectionManager (ViewCanvas canvas) { - Object (view_canvas : canvas); - } - - construct { - selection = new Lib.Items.NodeSelection (null); - - view_canvas.window.event_bus.flip_item.connect (on_flip_selected); - view_canvas.window.event_bus.delete_selected_items.connect (delete_selected); - view_canvas.window.event_bus.change_z_selected.connect (change_z_order); - } - - public bool is_empty () { - return selection.is_empty (); - } - - public int count () { - return selection.count (); - } - - public void reset_selection () { - if (is_empty ()) { - return; - } - - selection = new Lib.Items.NodeSelection (null); - inner_selection_changed (-1, ChangeType.TOPOLOGY); - } - - public void add_to_selection (int id) { - var node = view_canvas.items_manager.node_from_id (id); - if (node == null) { - return; - } - selection.add_node (node); - inner_selection_changed (-1, ChangeType.TOPOLOGY); - } - - /* - * Remove a specific node from the current selection, if present. - */ - public void remove_from_selection (int id) { - if (!item_selected (id)) { - return; - } - - selection.remove_node (id); - inner_selection_changed (-1, ChangeType.TOPOLOGY); - } - - public bool item_selected (int id) { - return selection.has_id (id, true); - } - - /* - * Check if a selection or hover actions are triggered on a sibling of - * a currently selected item of the same group. - */ - public bool item_is_sibling (int id) { - foreach (var node_id in selection.nodes.keys) { - var node = view_canvas.items_manager.node_from_id (node_id); - if (node == null || node.parent == null || node.parent.id == Lib.Items.Model.ORIGIN_ID) { - continue; - } - node = Utils.ModelUtil.recursive_get_parent_target (node); - if (node.has_child (id, true)) { - return true; - } - } - - return false; - } - - public void ensure_correct_target (ref Items.ModelNode target) { - if ( - (!item_selected (target.id) && !view_canvas.ctrl_is_pressed) - ) { - var old_target = target; - target = Utils.ModelUtil.recursive_get_parent_target (target); - - if ( - !is_empty () && item_is_sibling (old_target.id) - ) { - target = old_target; - } - old_target = null; - } - } - - /* - * Called whenever the selection is changed, including adding and removing - * items, and modifying the selection's geometry. - */ - public void on_selection_changed (int id) { - inner_selection_changed (id, ChangeType.GEOMETRY); - } - - public void delete_selected () { - var to_delete = new GLib.Array (); - foreach (var node_id in selection.nodes.keys) { - to_delete.append_val (node_id); - } - - reset_selection (); - - if (to_delete.length > 0) { - view_canvas.window.event_bus.create_model_snapshot ("delete items"); - view_canvas.items_manager.remove_items (to_delete); - } - - } - - public void change_z_order (bool up, bool to_end) { - var to_shift = new GLib.Array (); - foreach (var node_id in selection.nodes.keys) { - to_shift.append_val (node_id); - } - - int amount = up ? 1 : -1; - if (to_shift.length > 0 && amount != 0) { - view_canvas.items_manager.shift_items (to_shift, amount, to_end); - // Regenerate the layers list. - view_canvas.window.main_window.regenerate_list (true); - } - } - - public void on_flip_selected (bool vertical) { - var to_flip = new GLib.Array (); - foreach (var node_id in selection.nodes.keys) { - to_flip.append_val (node_id); - } - - if (to_flip.length > 0) { - view_canvas.window.event_bus.create_model_snapshot ("flip items"); - view_canvas.items_manager.flip_items (to_flip, vertical); - } - } - - protected void inner_selection_changed (int id, ChangeType change_type) { - if (block_change_notifications == 0) { - if (id < 0 || selection.has_id (id, false)) { - view_canvas.window.event_bus.selection_geometry_modified (); - if (ChangeType.TOPOLOGY in change_type) { - view_canvas.window.event_bus.selection_modified (); - } - } - - change_blocked = ChangeType.NONE; - return; - } - change_blocked |= change_type; - } -} diff --git a/src/Lib/Managers/SnapManager.vala b/src/Lib/Managers/SnapManager.vala deleted file mode 100644 index ec510015c..000000000 --- a/src/Lib/Managers/SnapManager.vala +++ /dev/null @@ -1,181 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Lib.Managers.SnapManager : Object { - public unowned ViewCanvas view_canvas { get; construct; } - - // Decorator items to be drawn in the Canvas. - private ViewLayers.ViewLayerSnaps v_decorators; - private ViewLayers.ViewLayerSnaps h_decorators; - - /* - * Type of snap guides to show (could be a selection or just a point). - */ - public enum SnapGuideType { - NONE, - SELECTION, - POINT - } - - /* - * Data that can be used to tell the SnapManager details on how to show snap guides. - */ - public class SnapGuideData { - public SnapGuideType type = SnapGuideType.NONE; - public double x = 0.0; - public double y = 0.0; - } - - private bool any_decorators_visible = false; - - public SnapManager (ViewCanvas canvas) { - Object (view_canvas: canvas); - } - - construct { - view_canvas.window.event_bus.update_snaps_color.connect (on_update_snaps_color); - } - - /* - * Generate guides as indicated by the data. - */ - public void generate_decorators (SnapGuideData new_data) { - switch (new_data.type) { - case SnapGuideType.NONE: - reset_decorators (); - break; - case SnapGuideType.SELECTION: - unowned var selection = view_canvas.selection_manager.selection; - var sensitivity = Utils.Snapping.adjusted_sensitivity (view_canvas.current_scale); - var selection_area = selection.bounding_box (); - - var snap_grid = Utils.Snapping.generate_best_snap_grid ( - view_canvas, - selection, - selection_area, - sensitivity - ); - - var matches = Utils.Snapping.generate_snap_matches ( - snap_grid, - selection, - selection_area, - sensitivity - ); - - populate_decorators_from_data (matches, snap_grid); - break; - case SnapGuideType.POINT: - // TODO - break; - } - } - - /* - * Returns true if the manager has active decorators - */ - public bool is_active () { - return any_decorators_visible; - } - - /* - * Makes all decorators invisible, and ready to be reused - */ - public void reset_decorators () { - if (any_decorators_visible) { - if (v_decorators != null) { - v_decorators.hide_drawable (); - } - - if (h_decorators != null) { - h_decorators.hide_drawable (); - } - } - - any_decorators_visible = false; - } - - /* - * Populates decorators (if applicable) based on match data and the snap grid. - * Reuses decorator Goo.CanvasItems if possible, otherwise constructs new ones. - */ - public void populate_decorators_from_data (Utils.Snapping.SnapMatchData data, Utils.Snapping.SnapGrid grid) { - reset_decorators (); - - if (data.v_data.snap_found () || data.h_data.snap_found ()) { - if (v_decorators == null) { - v_decorators = new ViewLayers.ViewLayerSnaps ( - 0, - 0, - Layouts.MainViewCanvas.CANVAS_SIZE, - Layouts.MainViewCanvas.CANVAS_SIZE, - false - ); - - v_decorators.add_to_canvas (ViewLayers.ViewLayer.VSNAPS_LAYER_ID, view_canvas); - on_update_snaps_color (); - } - - if (h_decorators == null) { - h_decorators = new ViewLayers.ViewLayerSnaps ( - 0, - 0, - Layouts.MainViewCanvas.CANVAS_SIZE, - Layouts.MainViewCanvas.CANVAS_SIZE, - true - ); - - h_decorators.add_to_canvas (ViewLayers.ViewLayer.HSNAPS_LAYER_ID, view_canvas); - on_update_snaps_color (); - } - - - v_decorators.update_data (data.v_data, grid.v_snaps); - h_decorators.update_data (data.h_data, grid.h_snaps); - - if (!any_decorators_visible) { - v_decorators.set_visible (true); - h_decorators.set_visible (true); - } - - any_decorators_visible = true; - } - } - - /* - * Update decorator colors - */ - private void on_update_snaps_color () { - var color = Gdk.RGBA (); - if (!color.parse (settings.snaps_color)) { - return; - } - - if (v_decorators != null) { - v_decorators.update_color (color); - } - - if (h_decorators != null) { - h_decorators.update_color (color); - } - } -} diff --git a/src/Lib/Modes/AbstractInteractionMode.vala b/src/Lib/Modes/AbstractInteractionMode.vala deleted file mode 100644 index 7e567b68f..000000000 --- a/src/Lib/Modes/AbstractInteractionMode.vala +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - - -/* - * InteractionMode is an abstract definition. It abstracts a canvas interaction mode that can absorb mouse and key - * events, as well as having a well defined beginning and end. How these things are defined is up to a higher - * class such as the ModeManager. - * - * In general only one InteractionMode will be active at a time. There are some exceptions where a mode may - * be masked by another, but this should be handled with a Manager with strong invariant management. - * - * To create a new mode: - * 1. Add a new ModeType - * 2. Create a new class that inherits from Object and InteractionMode - * 3. Implement all abstract methods, and return the correct mode_type - * 4. Create the new mode with the right trigger in Canvas, and ModeManager will automatically handle it - * based on the abstract methods below. Sometimes the same event that creates the mode should be passed - * to the mode_manager after the creation of the mode in order to guarantee correct behavior. - * 5. For now, modes should take mode_manager on construction in order to be able to stop themselves. In - * the future this should be built into the api in a more abstract way. - */ -public abstract class Akira.Lib.Modes.AbstractInteractionMode : Object { - /* - * Mode type that is used for introspection. - */ - public enum ModeType { - NONE, - TRANSFORM, - TRANSLATE, - SCALE, - ROTATE, - ITEM_INSERT, - EXPORT, - PAN, - PATH_EDIT, - MULTI_SELECT - } - - public signal void request_deregistration (ModeType type); - - /* - * Override to define ModeType associated to mode. - */ - public abstract ModeType mode_type (); - - /* - * Override to define a sub ModeType associated to mode. - */ - public virtual Utils.Nobs.Nob active_nob () { - return Utils.Nobs.Nob.ALL; - } - - /* - * Override to add startup behavior to the mode. - */ - public virtual void mode_begin () {} - - /* - * Override to add shutdown behavior to mode. - */ - public virtual void mode_end () {} - - /* - * Override to define cursor associated to mode. - */ - public virtual Gdk.CursorType? cursor_type () { - return Gdk.CursorType.ARROW; - } - - /* - * Override to define key press event. Return true to absorb. - */ - public virtual bool key_press_event (Gdk.EventKey event) { - return false; - } - - /* - * Override to define key release event. Return true to absorb. - */ - public virtual bool key_release_event (Gdk.EventKey event) { - return false; - } - - /* - * Override to define button press event. Return true to absorb. - */ - public virtual bool button_press_event (Gdk.EventButton event) { - return false; - } - - /* - * Override to define button release event. Return true to absorb. - */ - public virtual bool button_release_event (Gdk.EventButton event) { - return false; - } - - /* - * Override to define mouse motion event. Return true to absorb. - */ - public virtual bool motion_notify_event (Gdk.EventMotion event) { - return false; - } - - /* - * Optionally override to provide some extra context that may be used - * further up to know how to update other managers based on this mode. - * - * This context should not be relied upon for vital operations or anything - * that requires a specific order of operations. It is generally meant for - * more cosmetic features. - */ - public virtual Object? extra_context () { - return null; - } -} diff --git a/src/Lib/Modes/ExportMode.vala b/src/Lib/Modes/ExportMode.vala deleted file mode 100644 index d1abcd65b..000000000 --- a/src/Lib/Modes/ExportMode.vala +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Copyright (c) 2023 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Lib.Modes.ExportMode : AbstractInteractionMode { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - public class DragItemData : Object { - public Lib.Components.CompiledGeometry item_geometry; - } - - public class InitialDragState : Object { - public double press_x; - public double press_y; - - // initial_selection_data - public Geometry.Quad area; - - public Gee.HashMap item_data_map; - - construct { - item_data_map = new Gee.HashMap (); - } - } - - private InitialDragState initial_drag_state; - private ViewLayers.ViewLayerExportArea export_area_layer; - - public ExportMode (Akira.Lib.ViewCanvas canvas) { - Object (view_canvas: canvas); - - initial_drag_state = new InitialDragState (); - } - - construct { - export_area_layer = new ViewLayers.ViewLayerExportArea (); - } - - public override void mode_begin () { - export_area_layer.add_to_canvas (ViewLayers.ViewLayer.EXPORT_AREA_LAYER_ID, view_canvas); - } - - public override void mode_end () { - export_area_layer.remove_region (); - } - - public override AbstractInteractionMode.ModeType mode_type () { - return AbstractInteractionMode.ModeType.EXPORT; - } - - public override Gdk.CursorType? cursor_type () { - return Gdk.CursorType.CROSSHAIR; - } - - public override bool key_press_event (Gdk.EventKey event) { - return true; - } - - public override bool key_release_event (Gdk.EventKey event) { - return false; - } - - public override bool button_press_event (Gdk.EventButton event) { - initial_drag_state.press_x = event.x; - initial_drag_state.press_y = event.y; - - export_area_layer.create_region (event); - - return true; - } - - public override bool button_release_event (Gdk.EventButton event) { - var area = export_area_layer.get_region_bounds (); - view_canvas.export_area.begin (area); - - export_area_layer.remove_region (); - - request_deregistration (mode_type ()); - return true; - } - - public override bool motion_notify_event (Gdk.EventMotion event) { - var width = event.x - initial_drag_state.press_x; - var height = event.y - initial_drag_state.press_y; - - export_area_layer.update_region (width, height); - - return true; - } - - public override Object? extra_context () { - return null; - } -} diff --git a/src/Lib/Modes/ItemInsertMode.vala b/src/Lib/Modes/ItemInsertMode.vala deleted file mode 100644 index 0fd82aab9..000000000 --- a/src/Lib/Modes/ItemInsertMode.vala +++ /dev/null @@ -1,269 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - - -/* - * ItemInsertMode handles item insertion. After the first click, this mode will use static methods - * in the TransformMode to transform the inserted items. - * - * In the future, this mode can be kept alive during multiple clicks when inserting items like polylines. - */ -public class Akira.Lib.Modes.ItemInsertMode : AbstractInteractionMode { - public weak Lib.ViewCanvas view_canvas { get; construct; } - - private string item_insert_type; - - private Lib.Modes.TransformMode transform_mode; - private Lib.Modes.PathEditMode path_edit_mode; - - public ItemInsertMode (Lib.ViewCanvas canvas, string item_type) { - Object (view_canvas: canvas); - item_insert_type = item_type; - } - - construct { - transform_mode = null; - path_edit_mode = null; - } - - public override AbstractInteractionMode.ModeType mode_type () { - return AbstractInteractionMode.ModeType.ITEM_INSERT; - } - - public override void mode_end () { - if (transform_mode != null) { - transform_mode.mode_end (); - } - - if (path_edit_mode != null) { - path_edit_mode.mode_end (); - } - } - - public override Gdk.CursorType? cursor_type () { - if (transform_mode != null) { - return transform_mode.cursor_type (); - } - - return Gdk.CursorType.CROSSHAIR; - } - - public override bool key_press_event (Gdk.EventKey event) { - if (transform_mode != null) { - return transform_mode.key_press_event (event); - } - - if (path_edit_mode != null) { - return path_edit_mode.key_press_event (event); - } - - return false; - } - - public override bool key_release_event (Gdk.EventKey event) { - if (transform_mode != null) { - return transform_mode.key_press_event (event); - } - return false; - } - - public override bool button_press_event (Gdk.EventButton event) { - if (transform_mode != null) { - return transform_mode.button_press_event (event); - } - - if (path_edit_mode != null) { - return path_edit_mode.button_press_event (event); - } - - if (event.button == Gdk.BUTTON_PRIMARY) { - view_canvas.window.event_bus.create_model_snapshot ("add item"); - - bool is_artboard; - var instance = construct_item (item_insert_type, event.x, event.y, out is_artboard); - - var group_id = Lib.Items.Model.ORIGIN_ID; - if (!is_artboard) { - group_id = view_canvas.items_manager.first_group_at (event.x, event.y).id; - } - - view_canvas.items_manager.add_item_to_group (group_id, instance, false); - - view_canvas.selection_manager.reset_selection (); - view_canvas.selection_manager.add_to_selection (instance.id); - - // If a path is being inserted, then start the PathEditMode. - if (item_insert_type == "path") { - path_edit_mode = new Lib.Modes.PathEditMode (view_canvas, instance); - path_edit_mode.mode_begin (); - path_edit_mode.button_press_event (event); - } else { - transform_mode = new Lib.Modes.TransformMode (view_canvas, Utils.Nobs.Nob.BOTTOM_LEFT, false); - transform_mode.mode_begin (); - transform_mode.button_press_event (event); - } - - // Defer the print of the layer UI after all items have been created. - view_canvas.window.main_window.show_added_layers (1); - view_canvas.selection_manager.selection_modified_external (true); - return true; - } - - return false; - } - - public override bool button_release_event (Gdk.EventButton event) { - if (transform_mode != null) { - transform_mode.button_release_event (event); - request_deregistration (mode_type ()); - } - - if (path_edit_mode != null) { - return path_edit_mode.button_release_event (event); - } - - return true; - } - - public override bool motion_notify_event (Gdk.EventMotion event) { - if (transform_mode != null) { - return transform_mode.motion_notify_event (event); - } - - if (path_edit_mode != null) { - return path_edit_mode.motion_notify_event (event); - } - - return true; - } - - public override Object? extra_context () { - if (transform_mode != null) { - return transform_mode.extra_context (); - } - - return null; - } - - private static Lib.Items.ModelInstance construct_item (string from_type, double x, double y, out bool is_artboard) { - double center_x = 0.0; - double center_y = 0.0; - double width = 1.0; - double height = 1.0; - is_artboard = false; - - // We use floor to align to the pixel that is clicked. - Utils.AffineTransform.geometry_from_top_left ( - GLib.Math.floor (x), - GLib.Math.floor (y), - ref center_x, - ref center_y, - ref width, - ref height - ); - - var coordinates = new Lib.Components.Coordinates (center_x, center_y); - var size = new Lib.Components.Size (width, height, false); - - Lib.Items.ModelInstance new_item = null; - switch (from_type) { - case "rectangle": - new_item = Lib.Items.ModelTypeRect.default_rect ( - coordinates, - size, - borders_from_settings (), - fills_from_settings () - ); - break; - - case "ellipse": - new_item = Lib.Items.ModelTypeEllipse.default_ellipse ( - coordinates, - size, - borders_from_settings (), - fills_from_settings () - ); - break; - - case "text": - new_item = Lib.Items.ModelTypeText.default_text ( - coordinates, - size, - new Components.Text ("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.") - ); - break; - - case "artboard": - is_artboard = true; - new_item = Lib.Items.ModelTypeArtboard.default_artboard ( - coordinates, - size - ); - break; - - case "image": - break; - - case "path": - new_item = Lib.Items.ModelTypePath.default_path ( - coordinates, - borders_from_settings (), - null - ); - - var test_path = new Geometry.PathSegment[1]; - test_path[0] = Geometry.PathSegment.line (Geometry.Point (0, 0)); - - new_item.components.path = new Lib.Components.Path.from_points (test_path, false); - break; - } - - if (new_item == null) { - new_item = Lib.Items.ModelTypeRect.default_rect ( - coordinates, - size, - borders_from_settings (), - fills_from_settings () - ); - } - - return new_item; - } - - private static Lib.Components.Fills fills_from_settings () { - var fill_rgba = Gdk.RGBA (); - fill_rgba.parse (settings.fill_color); - return new Lib.Components.Fills.with_color (Lib.Components.Color.from_rgba (fill_rgba)); - } - - private static Lib.Components.Borders? borders_from_settings () { - if (!settings.set_border) { - return null; - } - - var border_rgba = Gdk.RGBA (); - border_rgba.parse (settings.border_color); - return new Lib.Components.Borders.single_color ( - Lib.Components.Color.from_rgba (border_rgba), - settings.border_size - ); - } -} diff --git a/src/Lib/Modes/MultiSelectMode.vala b/src/Lib/Modes/MultiSelectMode.vala deleted file mode 100644 index b15ff72dc..000000000 --- a/src/Lib/Modes/MultiSelectMode.vala +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Giacomo "giacomoalbe" Alberini - * Alessandro "Alecaddd" Castellani - */ - -public class Akira.Lib.Modes.MultiSelectMode : AbstractInteractionMode { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - private Gee.ArrayList found_items; - - public class DragItemData : Object { - public Lib.Components.CompiledGeometry item_geometry; - } - - public class InitialDragState : Object { - public double press_x; - public double press_y; - - // initial_selection_data - public Geometry.Quad area; - - public Gee.HashMap item_data_map; - - construct { - item_data_map = new Gee.HashMap (); - } - } - - private InitialDragState initial_drag_state; - private ViewLayers.ViewLayerMultiSelect multi_select_layer; - - public MultiSelectMode (Akira.Lib.ViewCanvas canvas) { - Object (view_canvas: canvas); - - initial_drag_state = new InitialDragState (); - } - - construct { - multi_select_layer = new ViewLayers.ViewLayerMultiSelect (); - found_items = new Gee.ArrayList (); - } - - public override void mode_begin () { - multi_select_layer.add_to_canvas (ViewLayers.ViewLayer.MULTI_SELECT_LAYER_ID, view_canvas); - } - - public override void mode_end () {} - - public override AbstractInteractionMode.ModeType mode_type () { - return AbstractInteractionMode.ModeType.MULTI_SELECT; - } - - public override bool key_press_event (Gdk.EventKey event) { - return true; - } - - public override bool key_release_event (Gdk.EventKey event) { - return false; - } - - public override bool button_press_event (Gdk.EventButton event) { - initial_drag_state.press_x = event.x; - initial_drag_state.press_y = event.y; - - multi_select_layer.create_region (event); - - return true; - } - - public override bool button_release_event (Gdk.EventButton event) { - select_items_inside_region (); - multi_select_layer.remove_region (); - - request_deregistration (mode_type ()); - return true; - } - - public override bool motion_notify_event (Gdk.EventMotion event) { - var width = event.x - initial_drag_state.press_x; - var height = event.y - initial_drag_state.press_y; - - multi_select_layer.update_region (width, height); - - found_items = view_canvas.items_manager.nodes_in_bounded_region ( - multi_select_layer.get_region_bounds () - ); - - var drawables = new Gee.ArrayList (); - foreach (unowned var item in found_items) { - drawables.add (item.instance.drawable); - } - multi_select_layer.update_found_drawables (drawables); - - return true; - } - - public override Object? extra_context () { - return null; - } - - private void select_items_inside_region () { - // Block selection manager while selecting potentially many items - var blocker = new Lib.Managers.SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - // Get rid of unused var warning - (blocker); - - foreach (unowned var item in found_items) { - view_canvas.selection_manager.add_to_selection (item.instance.id); - } - - view_canvas.selection_manager.selection_modified_external (true); - } -} diff --git a/src/Lib/Modes/PanMode.vala b/src/Lib/Modes/PanMode.vala deleted file mode 100644 index 741ce11bd..000000000 --- a/src/Lib/Modes/PanMode.vala +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - - -/* - * PanMode handles panning. This will handle space or middle click panning. This mode should - * be used as a secondary mode that overrides masks other modes. See ModeManager. - */ -public class Akira.Lib.Modes.PanMode : AbstractInteractionMode { - public unowned Akira.Lib.ViewCanvas canvas { get; construct; } - - private bool space_held = false; - private bool panning = false; - private double origin_x = 0; - private double origin_y = 0; - - public PanMode (Akira.Lib.ViewCanvas canvas) { - Object (canvas: canvas); - } - - public override AbstractInteractionMode.ModeType mode_type () { return AbstractInteractionMode.ModeType.PAN; } - - - public override Gdk.CursorType? cursor_type () { - return panning ? Gdk.CursorType.HAND2 : Gdk.CursorType.HAND1; - } - - public override bool key_press_event (Gdk.EventKey event) { - if (event.keyval == Gdk.Key.space) { - space_held = true; - } - return true; - } - - public override bool key_release_event (Gdk.EventKey event) { - if (event.keyval == Gdk.Key.space) { - space_held = false; - - if (!panning) { - request_deregistration (mode_type ()); - } - } - return true; - } - - public override bool button_press_event (Gdk.EventButton event) { - if (!panning && (space_held || event.button == Gdk.BUTTON_MIDDLE)) { - origin_x = event.x; - origin_y = event.y; - canvas.canvas_scroll_set_origin (origin_x, origin_y); - - toggle_panning (true); - } - return true; - } - - public override bool button_release_event (Gdk.EventButton event) { - toggle_panning (false); - - if (!space_held) { - request_deregistration (mode_type ()); - } - - return true; - } - - public override bool motion_notify_event (Gdk.EventMotion event) { - if (panning) { - canvas.canvas_moved (event.x, event.y); - } - return true; - } - - private void toggle_panning (bool new_state) { - if (panning != new_state) { - panning = new_state; - canvas.interaction_mode_changed (); - } - } -} diff --git a/src/Lib/Modes/PathEditMode.vala b/src/Lib/Modes/PathEditMode.vala deleted file mode 100644 index 75d27f5bd..000000000 --- a/src/Lib/Modes/PathEditMode.vala +++ /dev/null @@ -1,441 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Ashish Shevale -*/ - -public class Akira.Lib.Modes.PathEditMode : AbstractInteractionMode { - public enum Type { - NONE, - LINE, - QUADRATIC_LEFT, - QUADRATIC_RIGHT, - // Represents cubic curves. These will only be used with compound curves. - CUBIC_SINGLE, - // Represents curves drawn with 2 seperate cubic beziers. - // These are easy to modify for user. - CUBIC_DOUBLE, - } - - // We are using this to check what kind of point was selected. - public enum PointType { - // This means no point was selected. - NONE=-1, - // This point signifies a simple line end. - LINE_END=0, - // This is the first point you draw in a curve. - CURVE_BEGIN=1, - // This denotes one end of the tangent. - TANGENT_FIRST=2, - // This is the other end of the tangent. - TANGENT_SECOND=3, - // This is the last point of the curve. - CURVE_END=4 - } - - public weak Lib.ViewCanvas view_canvas { get; construct; } - public Lib.Items.ModelInstance instance { get; construct; } - private Models.PathEditModel edit_model; - - // Flag to track click and drag events. - private bool is_click = false; - - // The points in live command will be drawn every time user moves cursor. - // Also acts as buffer for curves. - private Geometry.PathSegment live_segment; - private PointType live_pnt_type; - - // This flag tells if we are adding a path or editing an existing one. - // Basically decides is we are in "edit" mode or "append" mode. - private enum Submode { - APPEND, - EDIT - } - - private Submode mode; - - private const int MIN_TANGENT_ALLOWED_LENGTH = 5; - - public PathEditMode (Lib.ViewCanvas canvas, Lib.Items.ModelInstance instance) { - Object ( - view_canvas: canvas, - instance: instance - ); - edit_model = new Models.PathEditModel (instance, view_canvas); - live_segment = Geometry.PathSegment (); - live_pnt_type = PointType.NONE; - mode = Submode.APPEND; - } - - public void toggle_functionality (bool is_append_path) { - mode = is_append_path ? Submode.APPEND : Submode.EDIT; - - // If we are editing the path, we need to set the first point in edit_model - if (mode == Submode.EDIT) { - double width = instance.compiled_geometry.source_width; - double height = instance.compiled_geometry.source_height; - - var first_point = Geometry.Point (-width / 2.0, -height / 2.0); - var tr = instance.drawable.transform; - tr.transform_point (ref first_point.x, ref first_point.y); - - edit_model.set_first_point (first_point); - } - } - - public override AbstractInteractionMode.ModeType mode_type () { - return AbstractInteractionMode.ModeType.PATH_EDIT; - } - - public override Utils.Nobs.Nob active_nob () { - return Utils.Nobs.Nob.NONE; - } - - public override void mode_begin () { - // Hide the nobs and show the path layer. - view_canvas.toggle_layer_visibility (ViewLayers.ViewLayer.NOBS_LAYER_ID, false); - view_canvas.toggle_layer_visibility (ViewLayers.ViewLayer.PATH_LAYER_ID, true); - } - - public override void mode_end () { - // Hide the path layer and show nobs. - view_canvas.toggle_layer_visibility (ViewLayers.ViewLayer.NOBS_LAYER_ID, true); - view_canvas.toggle_layer_visibility (ViewLayers.ViewLayer.PATH_LAYER_ID, false); - } - - public override Gdk.CursorType? cursor_type () { - return Gdk.CursorType.CROSSHAIR; - } - - public override bool key_press_event (Gdk.EventKey event) { - uint uppercase_keyval = Gdk.keyval_to_upper (event.keyval); - - if (mode == Submode.EDIT) { - if (uppercase_keyval == Gdk.Key.C) { - // If C is pressed in edit_mode, we enter back to append mode. - mode = Submode.APPEND; - edit_model.selected_pts.clear (); - return true; - } - - return false; - } - - if (uppercase_keyval == Gdk.Key.BackSpace) { - handle_backspace_event (); - return true; - } else if (uppercase_keyval == Gdk.Key.Z) { - edit_model.make_path_closed (); - - // We are triggering the escape signal because after joining the path, - // no more points can be added. So this mode must end. - view_canvas.window.event_bus.request_escape (); - return true; - } - - return false; - } - - public override bool key_release_event (Gdk.EventKey event) { - return false; - } - - public override bool button_press_event (Gdk.EventButton event) { - // If button is clicked in edit mode, check if some point was clicked. - if (mode == Submode.EDIT) { - return handle_button_press_in_edit_mode (event); - } - - handle_button_press_in_append_mode (event); - return true; - } - - public override bool button_release_event (Gdk.EventButton event) { - if (mode == Submode.EDIT) { - edit_model.tangents_inline = false; - - // If the user modified the last point and placed on top of first point, - // make the path closed. - if (edit_model.check_can_path_close ()) { - view_canvas.window.event_bus.request_escape (); - return true; - } - } - - if (is_curr_command_done ()) { - edit_model.add_live_points_to_path (live_segment); - - if (live_segment.type == Type.CUBIC_SINGLE) { - live_segment = Geometry.PathSegment.quadratic_bezier_right ( - live_segment.curve_end, - reflection (live_segment.tangent_2, live_segment.curve_end) - ); - } else { - live_segment = Geometry.PathSegment (); - live_pnt_type = PointType.LINE_END; - } - } - - is_click = false; - - return true; - } - - public override bool motion_notify_event (Gdk.EventMotion event) { - Geometry.Point point = Geometry.Point (event.x, event.y); - - if (mode == Submode.EDIT) { - if (!edit_model.selected_pts.is_empty && is_click) { - // If user selected a point and clicked and dragged it, change its position. - edit_model.modify_point_value (point); - } - return true; - } - - // If there is click and drag, we are dealing with some kind of curve. - if (is_click) { - handle_click_and_drag_in_append_mode (point); - } else { - // If we are hovering in CURVE mode, current position could be our third curve point. - if (live_segment.type == Type.CUBIC_DOUBLE) { - live_segment.curve_end = point; - live_pnt_type = PointType.CURVE_END; - } else if (live_segment.type == Type.QUADRATIC_LEFT) { - live_segment.curve_begin = point; - live_pnt_type = PointType.TANGENT_SECOND; - } else if (live_segment.type == Type.QUADRATIC_RIGHT) { - live_segment.curve_end = point; - live_pnt_type = PointType.TANGENT_SECOND; - } else { - // If we are hovering in LINE mode, this could be a potential line point. - live_segment.line_end = point; - live_segment.type = Type.LINE; - live_pnt_type = PointType.LINE_END; - } - } - - edit_model.set_live_points (live_segment, live_pnt_type); - - return true; - } - - public override Object? extra_context () { - return null; - } - - private bool is_curr_command_done () { - if (live_segment.type == Type.NONE) { - return false; - } - - if (live_segment.type == Type.LINE && live_pnt_type != PointType.LINE_END) { - return false; - } - - if (live_segment.type == Type.CUBIC_DOUBLE && live_pnt_type != PointType.CURVE_END) { - return false; - } - - if (live_segment.type == Type.CUBIC_SINGLE && live_pnt_type != PointType.TANGENT_SECOND) { - return false; - } - - return true; - } - - private Geometry.Point reflection (Geometry.Point pt1, Geometry.Point pt2) { - var x = pt2.x + (pt2.x - pt1.x); - var y = pt2.y + (pt2.y - pt1.y); - - return Geometry.Point (x, y); - } - - private void handle_backspace_event () { - - if (live_segment.type == Type.LINE || live_segment.type == Type.NONE) { - live_segment = edit_model.delete_point (); - - if (live_segment.type == Type.LINE) { - live_pnt_type = PointType.LINE_END; - } else { - live_pnt_type = PointType.CURVE_END; - } - } else if (live_segment.type == Type.CUBIC_SINGLE) { - live_segment.type = Type.QUADRATIC_LEFT; - live_pnt_type = PointType.CURVE_END; - } else if (live_segment.type == Type.CUBIC_DOUBLE) { - // Here we dont include the CURVE_BEGIN case because - // after both tangents are deleted, we convert segment from curve to line. - // And TANGENT_FIRST is not included because it gets deleted - // automatically after TANGENT_SECOND is deleted. - if (live_pnt_type == PointType.TANGENT_SECOND) { - live_segment.type = Type.LINE; - live_pnt_type = PointType.LINE_END; - } else if (live_pnt_type == PointType.CURVE_END) { - live_pnt_type = PointType.TANGENT_SECOND; - } - } else if (live_segment.type == Type.QUADRATIC_LEFT || live_segment.type == Type.QUADRATIC_RIGHT) { - live_segment.type = Type.LINE; - live_pnt_type = PointType.LINE_END; - } - - edit_model.set_live_points (live_segment, live_pnt_type); - - if (instance.components.path.data.length == 0) { - // If there are no points in the path, no point to stay in PathEditMode. - view_canvas.window.event_bus.delete_selected_items (); - view_canvas.mode_manager.deregister_active_mode (); - } - } - - private bool handle_button_press_in_edit_mode (Gdk.EventButton event) { - is_click = true; - - var sel_point = Geometry.SelectedPoint (); - var underlying_pt = Geometry.SelectedPoint (); - underlying_pt.sel_index = -1; - - bool is_selected = edit_model.hit_test (event.x, event.y, ref sel_point, ref underlying_pt); - if (!is_selected) { - return false; - } - - // If this point has already been selected before, make it the reference. - foreach (var segment in edit_model.selected_pts) { - if (segment.sel_index == sel_point.sel_index && segment.sel_type == sel_point.sel_type) { - edit_model.reference_point = sel_point; - return true; - } - } - - if (view_canvas.shift_is_pressed) { - if (sel_point.sel_type != PointType.TANGENT_FIRST && sel_point.sel_type != PointType.TANGENT_SECOND) { - edit_model.set_selected_points (sel_point, true); - return true; - } - } else if (view_canvas.alt_is_pressed && !view_canvas.ctrl_is_pressed) { - if (sel_point.sel_type == PointType.TANGENT_FIRST || sel_point.sel_type == PointType.TANGENT_SECOND) { - sel_point.tangents_staggered = true; - edit_model.set_selected_points (sel_point, false); - return true; - } - } else { - edit_model.set_selected_points (sel_point, false); - - if (underlying_pt.sel_index != -1) { - edit_model.set_selected_points (underlying_pt, true); - edit_model.reference_point = sel_point; - } - - return true; - } - - return false; - } - - private void handle_button_press_in_append_mode (Gdk.EventButton event) { - // If we are not in edit mode (we are creating the path), then - // everytime the user presses the mouse button, a new point needs to be created and added to the path. - if (edit_model.first_point.x == -1) { - edit_model.set_first_point (Geometry.Point (event.x, event.y)); - return; - } - - Geometry.Point point = Geometry.Point (event.x, event.y); - - // If this is the first point we are adding, make it a line. - if (live_segment.type == Type.LINE) { - // Check if we are clicking on the first point. If yes, then close the path. - var sel_point = Geometry.SelectedPoint (); - var underlying_pt = Geometry.SelectedPoint (); - if (edit_model.hit_test (event.x, event.y, ref sel_point, ref underlying_pt, 0)) { - edit_model.make_path_closed (); - // We are triggering the escape signal because after joining the path, - // no more points can be added. So this mode must end. - view_canvas.window.event_bus.request_escape (); - return; - } - - live_segment = Geometry.PathSegment.line (point); - live_pnt_type = PointType.LINE_END; - } else { - live_segment.curve_end = point; - live_pnt_type = PointType.CURVE_END; - } - - is_click = true; - edit_model.set_live_points (live_segment, live_pnt_type); - } - - private void handle_click_and_drag_in_append_mode (Geometry.Point point) { - // If we clicked and dragged when inserting last point of double cubic bezier. - // It means we are inserting a compound bezier curve. - if (live_pnt_type == PointType.CURVE_END && live_segment.type == Type.CUBIC_DOUBLE) { - // Make the first half of the live segment as a quadratic curve and add to path. - var new_segment = Geometry.PathSegment.quadratic_bezier_left ( - live_segment.curve_begin, - live_segment.tangent_1 - ); - - edit_model.add_live_points_to_path (new_segment); - - // Use remaining points to make the single cubic bezier. - live_segment = Geometry.PathSegment.cubic_bezier_single ( - edit_model.get_last_point_from_path (), - live_segment.tangent_2, - point, - live_segment.curve_end - ); - - live_pnt_type = PointType.TANGENT_SECOND; - } else if (live_pnt_type == PointType.CURVE_END && live_segment.type == Type.QUADRATIC_RIGHT) { - // If we clicked and dragged when inserting a quadratic curve, - // Turn this quadratic curve into a single bezier curve. - live_segment = Geometry.PathSegment.cubic_bezier_single ( - edit_model.get_last_point_from_path (), - live_segment.tangent_2, - point, - live_segment.curve_end - ); - - live_pnt_type = PointType.TANGENT_SECOND; - } else { - - if (live_segment.type == Type.LINE) { - // Clicking and dragging a line should turn it into a bezier curve. - live_segment.type = Type.CUBIC_DOUBLE; - } - - if (Utils.GeometryMath.compare_points (point, live_segment.curve_begin, MIN_TANGENT_ALLOWED_LENGTH)) { - // Prevent user from drawing really small curves due to mouse glitches. - live_segment.type = Type.LINE; - live_pnt_type = PointType.LINE_END; - } else { - // Points at index 1 and 2 are the two tangents required by the 2 curves. - if (live_segment.type == Type.CUBIC_SINGLE) { - live_segment.tangent_2 = reflection (point, live_segment.curve_end); - } else { - live_segment.tangent_1 = reflection (point, live_segment.curve_begin); - live_segment.tangent_2 = point; - } - - live_pnt_type = PointType.TANGENT_SECOND; - } - } - } -} diff --git a/src/Lib/Modes/TransformMode.vala b/src/Lib/Modes/TransformMode.vala deleted file mode 100644 index 7f14f2aa5..000000000 --- a/src/Lib/Modes/TransformMode.vala +++ /dev/null @@ -1,544 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * TransformMode handles mouse-activated transformations. Static methods can - * be used to apply the underlying code on top of other modes that may need to - * use the functionality. - */ -public class Akira.Lib.Modes.TransformMode : AbstractInteractionMode { - private const double ROTATION_FIXED_STEP = 15.0; - - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - public Utils.Nobs.Nob nob = Utils.Nobs.Nob.NONE; - - private bool standalone = false; - private bool snapshot_taken = false; - - // Keeps track of the currently used nob to quickly change selection when - // an item is scaled below its sizing, causing a "flip" in the transformation. - public Utils.Nobs.Nob effective_nob = Utils.Nobs.Nob.NONE; - - public class DragItemData : Object { - public Lib.Components.CompiledGeometry item_geometry; - } - - public class InitialDragState : Object { - public double press_x; - public double press_y; - - // initial_selection_data - public Geometry.TransformedRectangle start_area; - - public Gee.HashMap item_data_map; - - construct { - item_data_map = new Gee.HashMap (); - } - } - - // Simply defines whether the drag threshold was met to start transforming the object - - public class TransformExtraContext : Object { - public Lib.Managers.SnapManager.SnapGuideData snap_guide_data; - } - - private Lib.Items.NodeSelection selection; - private InitialDragState initial_drag_state; - public TransformExtraContext transform_extra_context; - - - public TransformMode (Akira.Lib.ViewCanvas canvas, Utils.Nobs.Nob selected_nob, bool standalone) { - Object (view_canvas: canvas); - // Set the effective_nob when the transform mode is first initialized in - // order to get the correct first clicked nob to show when scaling. - nob = effective_nob = selected_nob; - initial_drag_state = new InitialDragState (); - this.standalone = standalone; - } - - construct { - transform_extra_context = new TransformExtraContext (); - transform_extra_context.snap_guide_data = new Lib.Managers.SnapManager.SnapGuideData (); - } - - public override void mode_begin () { - if (view_canvas.selection_manager.selection.is_empty ()) { - request_deregistration (mode_type ()); - return; - } - - view_canvas.toggle_layer_visibility (ViewLayers.ViewLayer.NOBS_LAYER_ID, true); - selection = view_canvas.selection_manager.selection; - initial_drag_state.start_area = selection.area (); - - foreach (var node in selection.nodes.values) { - collect_geometries (node.node, ref initial_drag_state); - } - } - - private static void collect_geometries (Lib.Items.ModelNode subtree, ref InitialDragState state) { - if (state.item_data_map.has_key (subtree.id)) { - return; - } - - var data = new DragItemData (); - data.item_geometry = subtree.instance.compiled_geometry.copy (); - state.item_data_map[subtree.id] = data; - - if (subtree.children == null || subtree.children.length == 0) { - return; - } - - foreach (unowned var child in subtree.children.data) { - collect_geometries (child, ref state); - } - } - - public override void mode_end () { - transform_extra_context = null; - view_canvas.window.event_bus.update_snap_decorators (); - } - - public override AbstractInteractionMode.ModeType mode_type () { - return AbstractInteractionMode.ModeType.TRANSFORM; - } - - /* - * Returns the currently active nob the user is holding to resize the item. - */ - public override Utils.Nobs.Nob active_nob () { - return effective_nob; - } - - public override Gdk.CursorType? cursor_type () { - return Utils.Nobs.cursor_from_nob (nob); - } - - public override bool key_press_event (Gdk.EventKey event) { - return true; - } - - public override bool key_release_event (Gdk.EventKey event) { - return false; - } - - public override bool button_press_event (Gdk.EventButton event) { - initial_drag_state.press_x = event.x; - initial_drag_state.press_y = event.y; - return true; - } - - public override bool button_release_event (Gdk.EventButton event) { - request_deregistration (mode_type ()); - return true; - } - - public override bool motion_notify_event (Gdk.EventMotion event) { - - if (standalone && !snapshot_taken) { - view_canvas.window.event_bus.create_model_snapshot ("transform items"); - snapshot_taken = true; - } - - switch (nob) { - case Utils.Nobs.Nob.NONE: - move_from_event ( - view_canvas, - selection, - initial_drag_state, - event.x, - event.y, - ref transform_extra_context.snap_guide_data - ); - break; - case Utils.Nobs.Nob.ROTATE: - rotate_from_event ( - view_canvas, - selection, - initial_drag_state, - event.x, - event.y - ); - break; - default: - effective_nob = scale_from_event ( - view_canvas, - selection, - initial_drag_state, - nob, - event.x, - event.y - ); - break; - } - - return true; - } - - public override Object? extra_context () { - return transform_extra_context; - } - - public static void move_from_event ( - ViewCanvas view_canvas, - Lib.Items.NodeSelection selection, - InitialDragState initial_drag_state, - double event_x, - double event_y, - ref Lib.Managers.SnapManager.SnapGuideData guide_data - ) { - var blocker = new Lib.Managers.SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - - var delta_x = event_x - initial_drag_state.press_x; - var delta_y = event_y - initial_drag_state.press_y; - - double top = 0.0; - double left = 0.0; - double bottom = 0.0; - double right = 0.0; - - var start_quad = initial_drag_state.start_area.quad (); - start_quad.top_bottom (ref top, ref bottom); - start_quad.left_right (ref left, ref right); - - Utils.AffineTransform.add_grid_snap_delta (top, left, ref delta_x, ref delta_y); - - int snap_offset_x = 0; - int snap_offset_y = 0; - - if (settings.enable_snaps) { - guide_data.type = Akira.Lib.Managers.SnapManager.SnapGuideType.NONE; - var sensitivity = Utils.Snapping.adjusted_sensitivity (view_canvas.current_scale); - var selection_area = Geometry.Rectangle () { - left = left + delta_x, - top = top + delta_y, - right = right + delta_x, - bottom = bottom + delta_y - }; - - var snap_grid = Utils.Snapping.generate_best_snap_grid ( - view_canvas, - selection, - selection_area, - sensitivity - ); - - if (!snap_grid.is_empty ()) { - var matches = Utils.Snapping.generate_snap_matches ( - snap_grid, - selection, - selection_area, - sensitivity - ); - - - if (matches.h_data.snap_found ()) { - snap_offset_x = matches.h_data.snap_offset (); - guide_data.type = Akira.Lib.Managers.SnapManager.SnapGuideType.SELECTION; - } - - if (matches.v_data.snap_found ()) { - snap_offset_y = matches.v_data.snap_offset (); - guide_data.type = Akira.Lib.Managers.SnapManager.SnapGuideType.SELECTION; - } - } - } - - unowned var items_manager = view_canvas.items_manager; - foreach (var sel_node in selection.nodes.values) { - unowned var item = sel_node.node.instance; - - if (item.is_group) { - translate_group ( - view_canvas, - sel_node.node, - initial_drag_state, - delta_x, delta_y, - snap_offset_x, - snap_offset_y - ); - - if (item.components.center == null) { - continue; - } - } - - var item_drag_data = initial_drag_state.item_data_map[sel_node.node.id]; - var new_center_x = item_drag_data.item_geometry.area.center_x + delta_x + snap_offset_x; - var new_center_y = item_drag_data.item_geometry.area.center_y + delta_y + snap_offset_y; - item.components.center = new Lib.Components.Coordinates (new_center_x, new_center_y); - items_manager.item_model.alert_node_changed ( - sel_node.node, - Lib.Components.Component.Type.COMPILED_GEOMETRY - ); - } - - items_manager.compile_model (); - view_canvas.window.event_bus.update_snap_decorators (); - } - - private static void translate_group ( - ViewCanvas view_canvas, - Lib.Items.ModelNode group, - InitialDragState initial_drag_state, - double delta_x, - double delta_y, - double snap_offset_x, - double snap_offset_y - ) { - if (group.children == null) { - return; - } - - unowned var model = view_canvas.items_manager.item_model; - - foreach (unowned var child in group.children.data) { - if (child.instance.is_group) { - translate_group ( - view_canvas, - child, - initial_drag_state, - delta_x, - delta_y, - snap_offset_x, - snap_offset_y - ); - continue; - } - - unowned var item = child.instance; - var item_drag_data = initial_drag_state.item_data_map[child.id]; - var new_center_x = item_drag_data.item_geometry.area.center_x + delta_x + snap_offset_x; - var new_center_y = item_drag_data.item_geometry.area.center_y + delta_y + snap_offset_y; - item.components.center = new Lib.Components.Coordinates (new_center_x, new_center_y); - model.alert_node_changed (child, Lib.Components.Component.Type.COMPILED_GEOMETRY); - } - } - - public static Utils.Nobs.Nob scale_from_event ( - ViewCanvas view_canvas, - Lib.Items.NodeSelection selection, - InitialDragState initial_drag_state, - Utils.Nobs.Nob nob, - double event_x, - double event_y - ) { - var blocker = new Lib.Managers.SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - - var start_quad = initial_drag_state.start_area.quad (); - double rot_center_x = start_quad.center_x; - double rot_center_y = start_quad.center_y; - - var itr = start_quad.transformation; - itr.invert (); - - var local_area = start_quad; - Utils.GeometryMath.transform_quad (itr, ref local_area); - - var adjusted_event_x = event_x - rot_center_x; - var adjusted_event_y = event_y - rot_center_y; - itr.transform_distance (ref adjusted_event_x, ref adjusted_event_y); - adjusted_event_x += rot_center_x; - adjusted_event_y += rot_center_y; - - var start_width = double.max (1.0, local_area.width); - var start_height = double.max (1.0, local_area.height); - - double nob_x = 0.0; - double nob_y = 0.0; - - Utils.Nobs.nob_xy_from_coordinates ( - nob, - local_area, - 1.0, - ref nob_x, - ref nob_y - ); - - double inc_width = 0; - double inc_height = 0; - double inc_x = 0; - double inc_y = 0; - - var tr = Cairo.Matrix.identity (); - var updated_nob = Utils.AffineTransform.calculate_size_adjustments2 ( - nob, - start_width, - start_height, - adjusted_event_x - nob_x, - adjusted_event_y - nob_y, - start_width / start_height, - view_canvas.ctrl_is_pressed, - view_canvas.shift_is_pressed, - tr, - ref inc_x, - ref inc_y, - ref inc_width, - ref inc_height - ); - - double size_off_x = inc_width / 2.0; - double size_off_y = inc_height / 2.0; - tr.transform_distance (ref size_off_x, ref size_off_y); - - var local_offset_x = inc_x + size_off_x; - var local_offset_y = inc_y + size_off_y; - - var new_area = Geometry.Quad.from_components ( - rot_center_x + local_offset_x, - rot_center_y + local_offset_y, - start_width + inc_width, - start_height + inc_height, - tr - ); - - var global_offset_x = local_offset_x; - var global_offset_y = local_offset_y; - initial_drag_state.start_area.matrix.transform_distance (ref global_offset_x, ref global_offset_y); - - var local_sx = new_area.bounding_box.width / local_area.bounding_box.width; - var local_sy = new_area.bounding_box.height / local_area.bounding_box.height; - - unowned var item_model = view_canvas.items_manager.item_model; - foreach (var node in selection.nodes.values) { - node.node.instance.type.apply_scale_transform ( - item_model, - node.node, - initial_drag_state, - itr, - global_offset_x, - global_offset_y, - local_sx, - local_sy - ); - } - - view_canvas.items_manager.compile_model (); - - return updated_nob; - } - - public static void rotate_from_event ( - ViewCanvas view_canvas, - Lib.Items.NodeSelection selection, - InitialDragState initial_drag_state, - double event_x, - double event_y - ) { - var blocker = new Lib.Managers.SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - - var start_quad = initial_drag_state.start_area.quad (); - double original_center_x = start_quad.center_x; - double original_center_y = start_quad.center_y; - - var radians = GLib.Math.atan2 ( - event_x - original_center_x, - original_center_y - event_y - ); - - var added_rotation = radians * (180 / Math.PI); - - if (view_canvas.ctrl_is_pressed) { - var step_num = GLib.Math.round (added_rotation / 15.0); - added_rotation = 15.0 * step_num; - } - - var rot = Utils.GeometryMath.matrix_rotation_component (initial_drag_state.start_area.matrix); - - foreach (var node in selection.nodes.values) { - rotate_node ( - view_canvas, - node.node, - initial_drag_state, - added_rotation * Math.PI / 180 - rot, - original_center_x, - original_center_y - ); - } - - view_canvas.items_manager.compile_model (); - } - - private static void rotate_node ( - ViewCanvas view_canvas, - Lib.Items.ModelNode node, - InitialDragState initial_drag_state, - double added_rotation, - double rotation_center_x, - double rotation_center_y - ) { - unowned var item = node.instance; - if (item.components.transform != null) { - var item_drag_data = initial_drag_state.item_data_map[item.id]; - - var old_center_x = item_drag_data.item_geometry.area.center_x; - var old_center_y = item_drag_data.item_geometry.area.center_y; - - var new_transform = item_drag_data.item_geometry.transformation_matrix; - - var tr = Cairo.Matrix.identity (); - tr.rotate (added_rotation); - - if (old_center_x != rotation_center_x || old_center_y != rotation_center_y) { - var new_center_delta_x = old_center_x - rotation_center_x; - var new_center_delta_y = old_center_y - rotation_center_y; - tr.transform_point (ref new_center_delta_x, ref new_center_delta_y); - - item.components.center = new Lib.Components.Coordinates ( - rotation_center_x + new_center_delta_x, - rotation_center_y + new_center_delta_y - ); - } - - new_transform = Utils.GeometryMath.multiply_matrices (new_transform, tr); - - double new_rotation = Utils.GeometryMath.matrix_rotation_component (new_transform); - - if (item.components.transform != null) { - new_rotation = GLib.Math.fmod (new_rotation + GLib.Math.PI * 2, GLib.Math.PI * 2); - item.components.transform = item.components.transform.with_main_rotation (new_rotation); - } - - view_canvas.items_manager.item_model.alert_node_changed ( - node, - Lib.Components.Component.Type.COMPILED_GEOMETRY - ); - } - - if (node.children != null && node.children.length > 0) { - foreach (unowned var child in node.children.data) { - rotate_node ( - view_canvas, - child, - initial_drag_state, - added_rotation, - rotation_center_x, - rotation_center_y - ); - } - } - } -} diff --git a/src/Lib/ViewCanvas.vala b/src/Lib/ViewCanvas.vala deleted file mode 100644 index a4cd6334a..000000000 --- a/src/Lib/ViewCanvas.vala +++ /dev/null @@ -1,812 +0,0 @@ -/** - * Copyright (c) 2019-2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Giacomo "giacomoalbe" Alberini - * Alessandro "alecaddd" Castellani - */ - -public class Akira.Lib.ViewCanvas : ViewLayers.BaseCanvas { - private const int SIZE = 30; - public const double MIN_SCALE = 0.02; - public const double MAX_SCALE = 50.0; - public unowned Akira.Window window { get; construct; } - - public Geometry.Quad to_draw_1; - public Geometry.Quad to_draw_2; - public Geometry.Quad to_draw_3; - public double debug_point1_x = 0; - public double debug_point1_y = 0; - public double debug_point2_x = 0; - public double debug_point2_y = 0; - - public Lib.Managers.ItemsManager items_manager; - public Lib.Managers.SelectionManager selection_manager; - public Lib.Managers.ModeManager mode_manager; - public Lib.Managers.HoverManager hover_manager; - public Lib.Managers.NobManager nob_manager; - public Lib.Managers.SnapManager snap_manager; - public Lib.Managers.CopyManager copy_manager; - public Lib.Managers.HistoryManager history_manager; - private Lib.Managers.ExportManager? export_manager = null; - - private bool is_modifier_pressed (Gdk.ModifierIntent type) { - Gdk.ModifierType state; - Gdk.ModifierType mask; - - if (!Gtk.get_current_event_state (out state)) { - return false; - } - - mask = get_modifier_mask (type); - return (state & mask) == mask; - } - - public bool ctrl_is_pressed { - get { - return is_modifier_pressed (Gdk.ModifierIntent.MODIFY_SELECTION); - } - } - public bool shift_is_pressed { - get { - return is_modifier_pressed (Gdk.ModifierIntent.EXTEND_SELECTION); - } - } - public bool alt_is_pressed { - get { - return is_modifier_pressed (Gdk.ModifierIntent.SHIFT_GROUP); - } - } - - public double current_scale = 1.0; - - // RAIIify this? - public bool holding = false; - - private Utils.Nobs.Nob hovered_nob = Utils.Nobs.Nob.NONE; - private Gdk.CursorType current_cursor = Gdk.CursorType.ARROW; - - private ViewLayers.ViewLayerGrid grid_layout; - - // Keep track of the initial coords of the press event. - private double initial_event_x; - private double initial_event_y; - - // Keep track of a double clicked child item inside a group if we need to - // enfoce the selection of a specific target. - private int? enforced_target = null; - - public ViewCanvas (Akira.Window window) { - Object ( - window: window, - hadjustment : new Gtk.Adjustment (0.0, 0.0, 0.0, 0.0, 0.0, 0.0), - vadjustment : new Gtk.Adjustment (0.0, 0.0, 0.0, 0.0, 0.0, 0.0) - ); - - set_can_focus (true); - } - - construct { - events |= Gdk.EventMask.KEY_PRESS_MASK; - events |= Gdk.EventMask.BUTTON_PRESS_MASK; - events |= Gdk.EventMask.BUTTON_RELEASE_MASK; - events |= Gdk.EventMask.POINTER_MOTION_MASK; - events |= Gdk.EventMask.SCROLL_MASK; - events |= Gdk.EventMask.SMOOTH_SCROLL_MASK; - events |= Gdk.EventMask.TOUCHPAD_GESTURE_MASK; - events |= Gdk.EventMask.TOUCH_MASK; - - items_manager = new Lib.Managers.ItemsManager (this); - selection_manager = new Lib.Managers.SelectionManager (this); - mode_manager = new Lib.Managers.ModeManager (this); - hover_manager = new Lib.Managers.HoverManager (this); - nob_manager = new Lib.Managers.NobManager (this); - snap_manager = new Lib.Managers.SnapManager (this); - copy_manager = new Lib.Managers.CopyManager (this); - history_manager = new Lib.Managers.HistoryManager (this); - - grid_layout = new ViewLayers.ViewLayerGrid ( - 0, - 0, - Layouts.MainViewCanvas.CANVAS_SIZE, - Layouts.MainViewCanvas.CANVAS_SIZE - ); - - grid_layout.add_to_canvas (ViewLayers.ViewLayer.GRID_LAYER_ID, this); - grid_layout.set_visible (true); - - set_model_to_render (items_manager.item_model); - - window.event_bus.toggle_presentation_mode.connect (on_toggle_presentation_mode); - - window.event_bus.adjust_zoom.connect (trigger_adjust_zoom); - - window.event_bus.set_focus_on_canvas.connect (focus_canvas); - window.event_bus.insert_item.connect (start_insert_mode); - window.event_bus.update_snap_decorators.connect (on_update_snap_decorators); - - mode_manager.mode_changed.connect (interaction_mode_changed); - items_manager.items_removed.connect (on_items_removed); - } - - public bool block_ui = false; - private void on_toggle_presentation_mode () { - block_ui = !block_ui; - } - - public signal void canvas_moved (double delta_x, double delta_y); - public signal void canvas_scroll_set_origin (double origin_x, double origin_y); - - public void visible_bounds ( - ref double top, - ref double left, - ref double bottom, - ref double right - ) { - top = vadjustment.value / current_scale; - left = hadjustment.value / current_scale; - bottom = top + get_allocated_height () / current_scale; - right = left + get_allocated_width () / current_scale; - } - - public void start_insert_mode (string insert_item_type) { - var new_mode = new Akira.Lib.Modes.ItemInsertMode (this, insert_item_type); - mode_manager.register_mode (new_mode); - } - - public void interaction_mode_changed () { - set_cursor_by_interaction_mode (); - } - - public void set_cursor_by_interaction_mode () { - hover_manager.remove_hover_effect (); - Gdk.CursorType? new_cursor = mode_manager.active_cursor_type (); - - if (new_cursor == null) { - var hover_cursor = Utils.Nobs.cursor_from_nob (hovered_nob); - new_cursor = (hover_cursor == null) ? Gdk.CursorType.ARROW : hover_cursor; - } - - if (current_cursor != new_cursor) { - // debug (@"Changing cursor. $new_cursor"); - set_cursor (new_cursor); - } - } - - private void trigger_adjust_zoom (double new_scale, bool absolute, Geometry.Point? reference) { - var initial_hx = hadjustment.get_value (); - var initial_hy = vadjustment.get_value (); - - var local_hx = initial_hx / scale; - var local_hy = initial_hy / scale; - - if (!absolute) { - // Force the zoom value to 8% if we're currently at a 2% scale in order - // to go back to 10% and increase from there. - if (current_scale == MIN_SCALE && new_scale == 0.1) { - new_scale = 0.08; - } - - new_scale += current_scale; - } - - new_scale = Utils.GeometryMath.clamp (new_scale, Lib.ViewCanvas.MIN_SCALE, Lib.ViewCanvas.MAX_SCALE); - var zoom_diff = scale / new_scale; - - current_scale = new_scale; - this.scale = new_scale; - window.event_bus.zoom_changed (new_scale); - - if (reference == null) { - hadjustment.set_value (local_hx * scale); - vadjustment.set_value (local_hy * scale); - return; - } - - var ref_x = reference.x - initial_hx; - var ref_y = reference.y - initial_hy; - var offset_x = ref_x - ref_x * zoom_diff; - var offset_y = ref_y - ref_y * zoom_diff; - hadjustment.set_value (local_hx * scale + offset_x); - vadjustment.set_value (local_hy * scale + offset_y); - } - - public void focus_canvas () { - grab_focus (); - } - - public override bool key_press_event (Gdk.EventKey event) { - if (mode_manager.key_press_event (event)) { - return true; - } - - switch (event.keyval) { - case Gdk.Key.space: - mode_manager.start_panning_mode (); - if (mode_manager.key_press_event (event)) { - return true; - } - break; - - case Gdk.Key.Up: - case Gdk.Key.Down: - case Gdk.Key.Right: - case Gdk.Key.Left: - //window.event_bus.move_item_from_canvas (event); - //window.event_bus.detect_artboard_change (); - return true; - - case Gdk.Key.g: - if (ctrl_is_pressed) { - items_manager.create_group_from_selection (); - } - break; - default: - break; - } - - // TODO: Debuggging features, move this behind a pref. - // uint uppercase_keyval = Gdk.keyval_to_upper (event.keyval); - // if (uppercase_keyval == Gdk.Key.J) { - // window.event_bus.create_model_snapshot ("add debug items"); - // items_manager.debug_add_rectangles (10000, true); - // return true; - // } - // if (uppercase_keyval == Gdk.Key.G) { - // window.event_bus.create_model_snapshot ("add debug group"); - // items_manager.add_debug_group (300, 300, true); - // return true; - // } - - return false; - } - - public override bool key_release_event (Gdk.EventKey event) { - return mode_manager.key_release_event (event); - } - - public override bool button_press_event (Gdk.EventButton event) { - // Temporarily grab the focus when clicking on the canvas. This is a - // workaround fix for the listbox stealing focus. To be removed. - focus_canvas (); - - base.button_press_event (event); - - hover_manager.remove_hover_effect (); - - event.x = event.x / current_scale; - event.y = event.y / current_scale; - - // Handle a double click event. - if (event.type == Gdk.EventType.@2BUTTON_PRESS) { - handle_double_click_event (event); - return true; - } - - // Handle a mouse wheel/middle button press event. - if (event.button == Gdk.BUTTON_MIDDLE) { - mode_manager.start_panning_mode (); - if (mode_manager.button_press_event (event)) { - return true; - } - } - - if (mode_manager.button_press_event (event)) { - return true; - } - - if (handle_selection_press_event (event)) { - return true; - } - - var new_mode = new Lib.Modes.MultiSelectMode (this); - mode_manager.register_mode (new_mode); - - mode_manager.button_press_event (event); - - return false; - } - - /* - * Check if a selection exists, and transform it appropriately, return true if - * the event should be absorbed. - */ - private bool handle_selection_press_event (Gdk.EventButton event) { - // Register the initial click event coordinates. - initial_event_x = event.x; - initial_event_y = event.y; - - Lib.Items.ModelNode? target = null; - var nob_clicked = nob_manager.hit_test (event.x, event.y); - - if (nob_clicked == Utils.Nobs.Nob.NONE) { - // If no nob is selected, we test for an item. - target = items_manager.node_at_canvas_position ( - event.x, - event.y, - Drawables.Drawable.HitTestType.SELECT - ); - - if (target != null) { - selection_manager.ensure_correct_target (ref target); - - // Check if the clicked item is not already selected. - if (!selection_manager.item_selected (target.id)) { - // Reset the selection if SHIFT isn't pressed. - if (!shift_is_pressed) { - selection_manager.reset_selection (); - } - - selection_manager.add_to_selection (target.id); - selection_manager.selection_modified_external (true); - } else if (shift_is_pressed) { - // Remove the item fom the current selection if SHIFT is pressed. - selection_manager.remove_from_selection (target.id); - selection_manager.selection_modified_external (true); - } else if (ctrl_is_pressed) { - // If we already have a selection but CTRL is pressed, we should - // reset the selection and allow selecting the targeted element. - // AKA, we ignore a group selection. - selection_manager.reset_selection (); - selection_manager.add_to_selection (target.id); - selection_manager.selection_modified_external (true); - } - } else if ( - !selection_manager.selection.area ().contains (event.x, event.y) && - !selection_manager.selection.is_empty () && - !shift_is_pressed - ) { - // Selection area was not clicked, so we reset the selection if we have some. - selection_manager.reset_selection (); - selection_manager.selection_modified_external (true); - } - } - - // Enter transform mode if we have selected items and SHIFT is not pressed. - if (!selection_manager.is_empty () && !shift_is_pressed) { - var new_mode = new Lib.Modes.TransformMode (this, nob_clicked, true); - mode_manager.register_mode (new_mode); - - if (mode_manager.button_press_event (event)) { - return true; - } - } - - return false; - } - - private void handle_double_click_event (Gdk.EventButton event) { - enforced_target = null; - Lib.Items.ModelNode? target = null; - var nob_clicked = nob_manager.hit_test (event.x, event.y); - - // Bail out if the double click happened on a nob. - if (nob_clicked != Utils.Nobs.Nob.NONE) { - return; - } - - // If no nob is selected, we test for an item. - target = items_manager.node_at_canvas_position ( - event.x, - event.y, - Drawables.Drawable.HitTestType.SELECT - ); - - // Bail out if the double click happened on an empty area. - if (target == null) { - return; - } - - if (target.instance.type is Lib.Items.ModelTypePath) { - // If path edit mode is already active, propogate the event. - if (mode_manager.active_mode_type == Modes.AbstractInteractionMode.ModeType.PATH_EDIT) { - mode_manager.button_press_event (event); - } else { - var path_edit_mode = new Lib.Modes.PathEditMode (this, target.instance); - path_edit_mode.toggle_functionality (false); - mode_manager.register_mode (path_edit_mode); - } - return; - } - - // If the double click happened on an item that is already selected and - // all otehr previous conditions are false, check if this item is part - // of a group and enforce its selection, meaning the user wants to access - // the group's child nodes. - if (selection_manager.item_selected (target.id)) { - var old_target = target; - target = Utils.ModelUtil.recursive_get_parent_target (target); - - if (target.instance.is_group) { - enforced_target = old_target.id; - } - } - } - - public override bool button_release_event (Gdk.EventButton event) { - // Enforce the selection of a specific target if it was registered - // during the double click event on a group. - if (enforced_target != null) { - selection_manager.reset_selection (); - selection_manager.add_to_selection (enforced_target); - enforced_target = null; - if (mode_manager.button_release_event (event)) { - return true; - } - } - - event.x = event.x / current_scale; - event.y = event.y / current_scale; - - // Check if the there's no delta between the pressed and released event - // and the SHIFT modifier is not pressed. If the SHIFT modifier is pressed - // we're adding items to the selection so we don't need to do anything else. - if ( - initial_event_x == event.x && - initial_event_y == event.y && - !shift_is_pressed - ) { - var count = selection_manager.count (); - var target = items_manager.node_at_canvas_position ( - event.x, - event.y, - Drawables.Drawable.HitTestType.SELECT - ); - - // If the click happened on an item, we have multiple selected - // items, and the clicked items is part of the selection, we need to - // handle a few scenarios. - if ( - target != null && - selection_manager.item_selected (target.id) && - count > 1 && - alt_is_pressed && - !ctrl_is_pressed - ) { - nob_manager.toggle_anchor_point (target.id); - } - - // If the target is not null, shift is not pressed and the target is - // not an artboard, check if the item belongs to an artboard which is - // currently selected, and if so reset the selections and add that item. - if ( - target != null && - !shift_is_pressed && - !target.instance.is_artboard - ) { - var artboard = Utils.ModelUtil.recursive_get_target_parent_artboard (target); - if (artboard != null && selection_manager.item_selected (artboard.id)) { - selection_manager.reset_selection (); - selection_manager.add_to_selection (target.id); - selection_manager.selection_modified_external (true); - } - } - - // If the target is null and only 1 item is currently selected - // check if the selected item is an artboard and deselected it if so. - if (target == null && count == 1) { - var selected = selection_manager.selection.first_node (); - if (selected != null && selected.instance.is_artboard) { - selection_manager.reset_selection (); - selection_manager.selection_modified_external (true); - } - } - - // If the click happened on an empty area and we have multiple - // selected items, deselect them all. - if (target == null && count > 1) { - selection_manager.reset_selection (); - selection_manager.selection_modified_external (true); - } - } - - if (mode_manager.button_release_event (event)) { - return true; - } - - return false; - } - - public override bool motion_notify_event (Gdk.EventMotion event) { - event.x = event.x / current_scale; - event.y = event.y / current_scale; - - if (mode_manager.motion_notify_event (event)) { - return true; - } - - var target_nob = nob_manager.hit_test (event.x, event.y); - - if (target_nob != Utils.Nobs.Nob.NONE) { - hover_manager.remove_hover_effect (); - if (hovered_nob != target_nob) { - hovered_nob = target_nob; - set_cursor_by_interaction_mode (); - } - return true; - } else if (hovered_nob != Utils.Nobs.Nob.NONE) { - hovered_nob = Utils.Nobs.Nob.NONE; - set_cursor_by_interaction_mode (); - } - - hover_manager.on_mouse_over (event.x, event.y); - - return false; - } - - private void set_cursor (Gdk.CursorType? cursor_type) { - current_cursor = (cursor_type == null ? Gdk.CursorType.ARROW : cursor_type); - var cursor = new Gdk.Cursor.for_display (Gdk.Display.get_default (), current_cursor); - get_window ().set_cursor (cursor); - } - - // #TODO temporary - public override bool draw (Cairo.Context ctx) { - base.draw (ctx); - - // Draw damage - //var r = GLib.Random.double_range (0, 1.0); - //var g = GLib.Random.double_range (0, 1.0); - //var b = GLib.Random.double_range (0, 1.0); - //var col = Gdk.RGBA () { red = r, green = g, blue = b, alpha = 0.3}; - //var xadj = hadjustment.value; - //var yadj = vadjustment.value; - - //var cs = current_scale; - - //ctx.save (); - //ctx.rectangle (xadj + 0, xadj + 0, xadj + 3000, xadj + 3000); - //ctx.set_source_rgba (r, g, b, 0.3); - //ctx.fill (); - - //ctx.restore (); - - //draw_debug_rect (ctx, to_draw_1.bounding_box, Gdk.RGBA () { red = 1.0, green = 0.0, blue = 0.0, alpha = 1.0}); - draw_debug_rotated_rect (ctx, to_draw_1, Gdk.RGBA () { red = 0.0, green = 1.0, blue = 0.5, alpha = 1.0}); - - //draw_debug_rect (ctx, to_draw_2.bounding_box, Gdk.RGBA () { red = 5.0, green = 0.0, blue = 0.0, alpha = 1.0}); - draw_debug_rotated_rect (ctx, to_draw_2, Gdk.RGBA () { red = 1.0, green = 0.0, blue = 0.0, alpha = 1.0}); - - draw_debug_rotated_rect (ctx, to_draw_3, Gdk.RGBA () { red = 0.0, green = 0.0, blue = 1.0, alpha = 1.0}); - - if (debug_point1_x > 0 && debug_point1_y > 0) { - draw_debug_point ( - ctx, - debug_point1_x, - debug_point1_y, - Gdk.RGBA () { red = 0.0, green = 1.0, blue = 0.5, alpha = 1.0} - ); - } - - if (debug_point2_x > 0 && debug_point2_y > 0) { - draw_debug_point ( - ctx, - debug_point2_x, - debug_point2_y, - Gdk.RGBA () { red = 1.0, green = 0.0, blue = 0.0, alpha = 1.0} - ); - } - - return false; - } - - public void draw_debug_point (Cairo.Context ctx, double point_x, double point_y, Gdk.RGBA color) { - var xadj = hadjustment.value; - var yadj = vadjustment.value; - - var cs = current_scale; - - ctx.save (); - point_x *= cs; - point_y *= cs; - - ctx.move_to (point_x, point_y); - ctx.arc (point_x - xadj, point_y - yadj, 5, 0, 2.0 * GLib.Math.PI); - ctx.set_source_rgba (color.red, color.green, color.blue, color.alpha); - ctx.fill (); - ctx.restore (); - } - - public void draw_debug_rect (Cairo.Context ctx, Geometry.Rectangle rect, Gdk.RGBA color) { - var xadj = hadjustment.value; - var yadj = vadjustment.value; - - var cs = current_scale; - - ctx.save (); - var top = rect.top * cs; - var left = rect.left * cs; - var bottom = rect.bottom * cs; - var right = rect.right * cs; - - var width = right - left; - var height = bottom - top; - ctx.move_to (left - xadj, top - yadj); - ctx.rel_line_to (width, 0); - ctx.rel_line_to (0, height); - ctx.rel_line_to (-width, 0); - ctx.close_path (); - ctx.set_source_rgba (color.red, color.green, color.blue, color.alpha); - ctx.stroke (); - - ctx.restore (); - } - - public void draw_debug_rotated_rect (Cairo.Context ctx, Geometry.Quad rect, Gdk.RGBA color) { - var xadj = hadjustment.value; - var yadj = vadjustment.value; - - var cs = current_scale; - - var x0 = rect.tl_x * cs - xadj; - var y0 = rect.tl_y * cs - yadj; - var x1 = rect.tr_x * cs - xadj; - var y1 = rect.tr_y * cs - yadj; - var x2 = rect.bl_x * cs - xadj; - var y2 = rect.bl_y * cs - yadj; - var x3 = rect.br_x * cs - xadj; - var y3 = rect.br_y * cs - yadj; - - ctx.save (); - ctx.move_to (x0, y0); - ctx.set_source_rgba (color.red, color.green, color.blue, color.alpha); - ctx.line_to (x1, y1); - ctx.line_to (x3, y3); - ctx.line_to (x2, y2); - ctx.close_path (); - ctx.stroke (); - ctx.restore (); - } - - public void draw_debug_info (Cairo.Context ctx, Lib.Items.ModelInstance instance) { - /* - var xadj = hadjustment.value; - var yadj = vadjustment.value; - - var cs = current_scale; - - ctx.save (); - var cg = item.components.compiled_geometry; - var top = cg.bb_top () * cs; - var left = cg.bb_left () * cs; - var bottom = cg.bb_bottom () * cs; - var right = cg.bb_right () * cs; - - var width = right - left; - var height = bottom - top; - ctx.move_to (left - xadj, top - yadj); - ctx.set_source_rgba (1.0, 0.0, 0.0, 1.0); - ctx.rel_line_to (width, 0); - ctx.rel_line_to (0, height); - ctx.rel_line_to (-width, 0); - ctx.close_path (); - ctx.stroke (); - - ctx.arc (cg.x0 () * cs - xadj, cg.y0 () * cs - yadj, 5, 0, 2.0 * GLib.Math.PI); - ctx.fill (); - ctx.arc (cg.x1 () * cs - xadj, cg.y1 () * cs - yadj, 5, 0, 2.0 * GLib.Math.PI); - ctx.fill (); - ctx.arc (cg.x2 () * cs - xadj, cg.y2 () * cs - yadj, 5, 0, 2.0 * GLib.Math.PI); - ctx.fill (); - ctx.arc (cg.x3 () * cs - xadj, cg.y3 () * cs - yadj, 5, 0, 2.0 * GLib.Math.PI); - ctx.fill (); - - ctx.restore (); - */ - } - - public void draw_debug_selection (Cairo.Context ctx) { - /* - if (selection_manager.selection.is_empty ()) { - return; - } - var cs = current_scale; - - var xadj = hadjustment.value; - var yadj = vadjustment.value; - - double x0 = 0; - double y0 = 0; - double x1 = 0; - double y1 = 0; - double x2 = 0; - double y2 = 0; - double x3 = 0; - double y3 = 0; - double rotation = 0; - - selection_manager.selection.coordinates ( - out x0, - out y0, - out x1, - out y1, - out x2, - out y2, - out x3, - out y3, - out rotation - ); - x0 = x0 * cs - xadj; - y0 = y0 * cs - yadj; - x1 = x1 * cs - xadj; - y1 = y1 * cs - yadj; - x2 = x2 * cs - xadj; - y2 = y2 * cs - yadj; - x3 = x3 * cs - xadj; - y3 = y3 * cs - yadj; - - ctx.save (); - ctx.move_to (x0, y0); - ctx.set_source_rgba (1.0, 0.0, 0.0, 1.0); - ctx.line_to (x1, y1); - ctx.line_to (x3, y3); - ctx.line_to (x2, y2); - ctx.close_path (); - ctx.stroke (); - ctx.restore (); - */ - } - - /* - * Will update snap decorators if necessary. - */ - private void on_update_snap_decorators () { - var extra_context = mode_manager.active_mode_extra_context (); - if (extra_context is Akira.Lib.Modes.TransformMode.TransformExtraContext) { - snap_manager.generate_decorators ( - ((Lib.Modes.TransformMode.TransformExtraContext) extra_context).snap_guide_data); - } else if (snap_manager.is_active ()) { - snap_manager.reset_decorators (); - } - } - - /* - * Helper method to interact with the layers panel without publicly exposing it. - */ - private void on_items_removed (GLib.Array ids) { - window.main_window.remove_layers (ids); - } - - /* EXPORT METHODS */ - - private void init_export_manager () { - if (export_manager == null) { - export_manager = new Lib.Managers.ExportManager (this); - } - } - - public async void export_selection () { - if (selection_manager.selection.is_empty ()) { - window.main_window.main_view_canvas.trigger_notification (_("Nothing selected to export!")); - return; - } - - init_export_manager (); - yield export_manager.export_selection (); - } - - public async void export_area (Geometry.Rectangle area) { - if (area.width == 0 || area.height == 0) { - window.main_window.main_view_canvas.trigger_notification (_("Unable to export the selected area!")); - return; - } - - init_export_manager (); - yield export_manager.export_area (area); - } -} diff --git a/src/Main.vala b/src/Main.vala deleted file mode 100644 index f195bfd88..000000000 --- a/src/Main.vala +++ /dev/null @@ -1,33 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public static bool verbose = false; - -public static int main (string[] args) { - verbose = "-d" in args; - - Environment.set_application_name (Constants.APP_NAME); - Environment.set_prgname (Constants.APP_NAME); - - var application = new Akira.Application (); - - return application.run (args); -} diff --git a/src/Middlewares/CoordinatesMiddleware.vala b/src/Middlewares/CoordinatesMiddleware.vala deleted file mode 100644 index 9144466b7..000000000 --- a/src/Middlewares/CoordinatesMiddleware.vala +++ /dev/null @@ -1,177 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/** - * Middleware handling the currently selected objects coordinates with the Transform Panel. - * This is used to guarantee correct values in the Transform Panel no matter if one or - * multiple items are selected, and to always return the true items' coordinates which - * are held by the GooCanvasItem. - */ -public class Akira.StateManagers.CoordinatesMiddleware : Object { - public weak Akira.Window window { get; construct; } - private weak Akira.Lib.Canvas canvas; - - // Store the initial coordinates of the item before the values are edited by - // the user interacting with the Transform Panel fields. - private double initial_x; - private double initial_y; - - // These attributes represent only the primary X & Y coordinates of the selected shapes. - // These are not the origin points of each selected shape, but only the TOP-LEFT values - // of the bounding box selection. - private double? _x = null; - public double x { - get { - return _x != null ? _x : 0; - } - set { - if (value == _x) { - return; - } - - _x = Utils.AffineTransform.fix_size (value); - move_from_panel (); - } - } - - private double? _y = null; - public double y { - get { - return _y != null ? _y : 0; - } - set { - if (value == _y) { - return; - } - - _y = Utils.AffineTransform.fix_size (value); - move_from_panel (); - } - } - - // Allow or deny updating the items position. - private bool do_update = true; - - public CoordinatesMiddleware (Akira.Window window) { - Object ( - window: window - ); - } - - construct { - // Get the canvas on construct as we will need to use its methods. - canvas = window.main_window.main_canvas.canvas; - - // Initialize event listeners. - window.event_bus.init_state_coords.connect (on_init_state_coords); - window.event_bus.reset_state_coords.connect (on_reset_state_coords); - window.event_bus.update_state_coords.connect (on_update_state_coords); - } - - private void get_coordinates_from_items () { - // Reset the selected coordinates to always get correct values. - initial_x = 0; - initial_y = 0; - - var nob_data = new Akira.Lib.Managers.NobManager.ItemNobData (); - Lib.Managers.NobManager.populate_nob_bounds_from_items ( - canvas.selected_bound_manager.selected_items, - ref nob_data - ); - - initial_x = nob_data.selected_x; - initial_y = nob_data.selected_y; - } - - /** - * Initialize the manager coordinates with the selected items coordinates. - * The coordinates change comes from a canvas action that already moved the items, - * therefore we set the do_update to false to prevent updating the selected - * items' Cairo Matrix. - */ - private void on_init_state_coords () { - do_update = false; - - // Get the items X & Y coordinates. - get_coordinates_from_items (); - - x = initial_x; - y = initial_y; - - do_update = true; - } - - /** - * Update the coordinates to trigger the shapes transformation. - * This action comes from an arrow keypress event from the Canvas. - */ - private void on_update_state_coords (double moved_x, double moved_y) { - x += moved_x; - y += moved_y; - - window.event_bus.file_edited (); - } - - /** - * Reset the coordinates to get the newly updated coordinates from the selected items. - * This method is called when items are moved from the canvas, so we only need to update - * the X and Y values for the Transform Panel without triggering the update_items_*(). - */ - private void on_reset_state_coords () { - on_init_state_coords (); - - window.event_bus.item_value_changed (); - window.event_bus.file_edited (); - } - - /** - * Update the position of all selected items. - */ - private void move_from_panel () { - if (_x == null || _y == null || !do_update) { - return; - } - - // Get the current item X & Y coordinates before translating. - get_coordinates_from_items (); - - // Loop through all the selected items to update their position. - foreach (Lib.Items.CanvasItem item in canvas.selected_bound_manager.selected_items) { - // Set the ignore_offset attribute to true to avoid the forced - // respositioning of the item (magnetic offset snapping). - - var drag_state = new Akira.Lib.Modes.TransformMode.InitialDragState (); - var tmp = new GLib.List (); - tmp.append (item); - if (Akira.Lib.Modes.TransformMode.initialize_items_drag_state (tmp, ref drag_state)) { - drag_state.wants_snapping = false; - drag_state.press_x = initial_x; - drag_state.press_y = initial_y; - drag_state.nob_x = initial_x; - drag_state.nob_y = initial_y; - var guide_data = new Akira.Lib.Managers.SnapManager.SnapGuideData (); - Akira.Lib.Modes.TransformMode.move_from_event (canvas, tmp, drag_state, x, y, ref guide_data); - } - } - - window.event_bus.item_value_changed (); - } -} diff --git a/src/Middlewares/SizeMiddleware.vala b/src/Middlewares/SizeMiddleware.vala deleted file mode 100644 index d2e67b8e0..000000000 --- a/src/Middlewares/SizeMiddleware.vala +++ /dev/null @@ -1,153 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/** - * Middleware handling the currently selected objects sizes with the Transform Panel. - * This is used to guarantee correct values in the Transform Panel no matter if one or - * multiple items are selected, and to always return the true items' sizes which - * are held by the GooCanvasItem. - */ -public class Akira.StateManagers.SizeMiddleware : Object { - public weak Akira.Window window { get; construct; } - private weak Akira.Lib.Canvas canvas; - - // Store the initial size of the item before the values are edited by - // the user interacting with the Transform Panel fields. - private double initial_width; - private double initial_height; - - // Allow or deny updating the items size. - private bool do_update = true; - - // These attributes represent only the primary WIDTH & HEIGHT coordinates of the selected shapes. - // These are not the original sizes of each selected shape, but only the BOTTOM-RIGHT values - // of the bounding box selection. - private double? _width = null; - public double width { - get { - return _width != null ? _width : 0; - } - set { - if (value == _width) { - return; - } - - _width = Utils.AffineTransform.fix_size (value); - scale_from_panel (); - } - } - - private double? _height = null; - public double height { - get { - return _height != null ? _height : 0; - } - set { - if (value == _height) { - return; - } - - _height = Utils.AffineTransform.fix_size (value); - scale_from_panel (); - } - } - - public SizeMiddleware (Akira.Window window) { - Object ( - window: window - ); - } - - construct { - // Get the canvas on construct as we will need to use its methods. - canvas = window.main_window.main_canvas.canvas; - - // Initialize event listeners. - window.event_bus.init_state_coords.connect (on_init_state_coords); - window.event_bus.reset_state_coords.connect (on_reset_state_coords); - } - - private void get_size_from_items () { - // Reset the selected coordinates to always get correct values. - initial_width = 0; - initial_height = 0; - - var nob_data = new Akira.Lib.Managers.NobManager.ItemNobData (); - Lib.Managers.NobManager.populate_nob_bounds_from_items ( - canvas.selected_bound_manager.selected_items, - ref nob_data - ); - - initial_width = nob_data.bb_width; - initial_height = nob_data.bb_height; - } - - /** - * Initialize the manager sizes with the selected items sizes. - * The sizes change comes from a canvas action that already moved the items, - * therefore we set the do_update to false to prevent updating the selected - * items' Cairo Matrix. - */ - private void on_init_state_coords () { - do_update = false; - - // Get the items WIDTH & HEIGHT. - get_size_from_items (); - - width = initial_width; - height = initial_height; - - do_update = true; - } - - /** - * Reset the sizes to get the newly updated sizes from the selected items. - * This method is called when items are resized from the canvas, so we only need to update - * the WIDTH & HEIGHT values for the Transform Panel without triggering the update_items_size(). - */ - private void on_reset_state_coords () { - on_init_state_coords (); - - window.event_bus.item_value_changed (); - window.event_bus.file_edited (); - } - - /** - * Update the size of all selected items. - */ - private void scale_from_panel () { - if (_width == null || _height == null || !do_update) { - return; - } - - // Loop through all the selected items to update their size. - foreach (Lib.Items.CanvasItem item in canvas.selected_bound_manager.selected_items) { - // TODO: We're temporarily applying the exact same size to all selected items. - // This will change once we implement the multi select and the ability to resize - // and translate multiple items relative to their position. - var delta_h = height - item.size.height; - var delta_w = width - item.size.width; - - item.size.width += delta_w; - item.size.height += delta_h; - } - } -} diff --git a/src/Models/ColorModel.vala b/src/Models/ColorModel.vala deleted file mode 100644 index 4364d3df0..000000000 --- a/src/Models/ColorModel.vala +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Model to keep track of Fills and Borders colors of an item. We use this - * model to easily bind the ListBox UI to the Fills and Borders Components. - */ -public class Akira.Models.ColorModel : GLib.Object { - public signal void value_changed (); - - public class SignalBlocker { - private unowned ColorModel item; - - public SignalBlocker (ColorModel fill_item) { - item = fill_item; - item.block_signal += 1; - } - - ~SignalBlocker () { - item.block_signal -= 1; - } - } - - protected int block_signal = 0; - - private Gdk.RGBA _color; - public Gdk.RGBA color { - get { - return _color; - } - set { - if (value == _color) { - return; - } - - _color = value; - on_value_changed (); - value_changed (); - } - } - - private bool _hidden; - public bool hidden { - get { - return _hidden; - } - set { - if (value == _hidden) { - return; - } - - _hidden = value; - on_value_changed (); - value_changed (); - } - } - - private int _size; - public int size { - get { - return _size; - } - set { - if (value == _size) { - return; - } - - _size = value; - on_value_changed (); - value_changed (); - } - } - - public virtual void on_value_changed () {} - public virtual void delete () {} -} diff --git a/src/Models/ExportModel.vala b/src/Models/ExportModel.vala deleted file mode 100644 index 35b772a37..000000000 --- a/src/Models/ExportModel.vala +++ /dev/null @@ -1,85 +0,0 @@ -/* -* Copyright (c) 2020-2022 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "alecaddd" Castellani -*/ - -public class Akira.Models.ExportModel : GLib.Object { - private unowned Akira.Lib.ViewCanvas _view_canvas; - private Lib.Items.ModelInstance? _cached_instance = null; - - private Gdk.Pixbuf _pixbuf; - public Gdk.Pixbuf pixbuf { - get { return _pixbuf; } - } - - private int id { - get { - return _cached_instance.id; - } - } - - private string name { - get { - return _cached_instance.components.name.name; - } - } - - // When exporting an arbitrary area, we don't have a model instance to update - // so let's use a temporary string for this model. - private string _area_filename = _("Selected area"); - public string filename { - owned get { - if (_cached_instance != null) { - return _cached_instance.components.name.filename; - } - - return _area_filename; - } - set { - if (_cached_instance == null) { - _area_filename = value; - return; - } - - if (_cached_instance.components.name.filename == value) { - return; - } - - unowned var im = _view_canvas.items_manager; - var node = im.item_model.node_from_id (_cached_instance.id); - assert (node != null); - - node.instance.components.name = new Lib.Components.Name (name, id.to_string (), value); - im.item_model.alert_node_changed (node, Lib.Components.Component.Type.COMPILED_NAME); - im.compile_model (); - } - } - - public ExportModel (Lib.ViewCanvas view_canvas, Lib.Items.ModelNode? node, Gdk.Pixbuf pixbuf) { - _view_canvas = view_canvas; - _pixbuf = pixbuf; - if (node != null) { - _cached_instance = node.instance; - } - } - - public void toggle_export_button (bool sensitive) { - _view_canvas.window.event_bus.toggle_export_button (sensitive); - } -} diff --git a/src/Models/ListModel.vala b/src/Models/ListModel.vala deleted file mode 100644 index 01fc8855e..000000000 --- a/src/Models/ListModel.vala +++ /dev/null @@ -1,130 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Giacomo "giacomoalbe" Alberini -* Authored by: Alessandro "alecaddd" Castellani -*/ - -public class Akira.Models.ListModel : GLib.Object, GLib.ListModel { - private GLib.List list; - - construct { - list = new GLib.List (); - } - - public uint get_n_items () { - return (uint) list.length (); - } - - public Object? get_item (uint position) { - return list.nth_data (position) as Object; - } - - public new Model get (uint index) { - return list.nth_data (index); - } - - public Type get_item_type () { - return typeof (Model); - } - - public Model? find_item (Model item) { - for (var i = 0; i < list.length (); i++) { - if (list.nth_data (i) == item) { - return get_item (i); - } - } - - return null; - } - - public int index (Model item) { - return (int) list.index (find_item (item)); - } - - public async void add_item (Model model_item) { - list.prepend (model_item); - items_changed (0, 0, 1); - } - - public async void remove_item (Model? model) { - if (model == null) { - return; - } - - var position = list.index (model); - - list.remove (model); - items_changed (position, 1, 0); - } - - public void swap_items (int source_index, int target_index) { - // Remove item at source position - var item_to_swap = remove_at (source_index); - // Insert item at target position - insert_at (target_index, item_to_swap); - } - - public void insert_at (int position, Model item) { - list.insert (item, position); - items_changed (position, 0, 1); - } - - public Model? remove_at (int position) { - var item = list.nth_data (position); - list.remove (item); - - items_changed (position, 1, 0); - - return item; - } - - public async void clear () { - list.foreach ((item) => { - remove_item.begin (item); - }); - } - - public void sort (CompareFunc sort_fn) { - list.sort (sort_fn); - items_changed (0, list.length (), list.length ()); - } - - public Iterator iterator () { - return new Iterator (this); - } - - public class Iterator { - private int index; - private int length; - private ListModel model; - - public Iterator (ListModel model) { - this.model = model; - this.length = (int) model.list.length (); - } - - public bool next () { - return index < length; - } - - public Model get () { - return model.list.nth_data (this.index++); - } - } -} diff --git a/src/Models/PathEditModel.vala b/src/Models/PathEditModel.vala deleted file mode 100644 index 683b9be35..000000000 --- a/src/Models/PathEditModel.vala +++ /dev/null @@ -1,546 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Ashish Shevale -*/ - -public class Akira.Models.PathEditModel : Object { - - public Lib.Items.ModelInstance instance { get; construct; } - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - private ViewLayers.ViewLayerPath path_layer; - - private Geometry.PathSegment[] points; - - public Geometry.Point first_point; - - private Geometry.PathSegment live_segment; - private Lib.Modes.PathEditMode.PointType live_point_type; - - public Gee.HashSet selected_pts; - public Geometry.SelectedPoint reference_point; - - public bool tangents_inline = false; - - // This is the diameter of the blue points drawn in ViewLayerPath. - // It is used for checking if user clicked within the region. - public const int HIT_SIZE = 4; - - public PathEditModel (Lib.Items.ModelInstance instance, Lib.ViewCanvas view_canvas) { - Object ( - view_canvas: view_canvas, - instance: instance - ); - - first_point = Geometry.Point (-1, -1); - - points = instance.components.path.data; - - // Layer to show when editing paths. - path_layer = new ViewLayers.ViewLayerPath (); - path_layer.add_to_canvas (ViewLayers.ViewLayer.PATH_LAYER_ID, view_canvas); - - // The selected_pts will contain the list of all points that we want to modify. - selected_pts = new Gee.HashSet (); - - live_segment = Geometry.PathSegment (); - live_point_type = Lib.Modes.PathEditMode.PointType.NONE; - - update_view (); - } - - public void set_first_point (Geometry.Point first_point) { - this.first_point = first_point; - update_view (); - } - - public void add_live_points_to_path (Geometry.PathSegment live_pts) { - var transform_matrix = instance.components.transform.transformation_matrix; - var orig_first_pt = Utils.GeometryMath.transform_point_around_item_origin (first_point, transform_matrix, true); - - live_pts.transform (transform_matrix, true); - live_pts.translate (orig_first_pt.x, orig_first_pt.y); - live_pts.snap_points (); - - add_point_to_path (live_pts); - - live_segment = Geometry.PathSegment (); - live_point_type = Lib.Modes.PathEditMode.PointType.NONE; - - recompute_components (); - } - - /* - * This method shift all points in path such that none of them are in negative space. - */ - private void add_point_to_path (Geometry.PathSegment point, int index = -1) { - index = (index == -1) ? index = points.length : index; - - points.resize (points.length + 1); - - // Add the given segment at the correct position and shift rest of the elements. - for (int i = index; i < points.length; ++i) { - var temp = points[i]; - points[i] = point; - point = temp; - } - - points = recalculate_points (points); - bool close = instance.components.path.close; - instance.components.path = new Lib.Components.Path.from_points (points, close); - } - - public void set_live_points (Geometry.PathSegment live_segment, Lib.Modes.PathEditMode.PointType type) { - this.live_segment = live_segment; - this.live_point_type = type; - - update_view (); - } - - public Geometry.PathSegment delete_point (int index = -1) { - if (index == -1) { - index = points.length - 1; - } - - var last_segment = points[index]; - var new_live_pts = Geometry.PathSegment (); - - var orig_first_pt = Utils.GeometryMath.transform_point_around_item_origin ( - first_point, - instance.components.transform.transformation_matrix, - true - ); - - var transform_matrix = instance.components.transform.transformation_matrix; - - // If the last segment from path is a line, - if (last_segment.type == Lib.Modes.PathEditMode.Type.LINE) { - var line_end = points[points.length - 2].line_end; - line_end.x += orig_first_pt.x; - line_end.y += orig_first_pt.y; - line_end = Utils.GeometryMath.transform_point_around_item_origin (line_end, transform_matrix); - - new_live_pts.line_end = line_end; - new_live_pts.type = Lib.Modes.PathEditMode.Type.LINE; - } else if (last_segment.type == Lib.Modes.PathEditMode.Type.CUBIC_DOUBLE) { - new_live_pts = last_segment.copy (); - new_live_pts.translate (-orig_first_pt.x, -orig_first_pt.y); - new_live_pts.transform (transform_matrix); - } else if (last_segment.type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE) { - new_live_pts = last_segment.copy (); - new_live_pts.translate (-orig_first_pt.x, -orig_first_pt.y); - new_live_pts.transform (transform_matrix); - } else if ( - last_segment.type == Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT || - last_segment.type == Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT - ) { - new_live_pts = last_segment.copy (); - new_live_pts.translate (-orig_first_pt.x, -orig_first_pt.y); - new_live_pts.transform (transform_matrix); - } - - var new_points = new Geometry.PathSegment[points.length - 1]; - for (int i = 0, seg_idx = 0; i < points.length; ++i) { - if (i == index) { - continue; - } - - new_points[seg_idx] = points[i]; - ++seg_idx; - } - - points = recalculate_points (new_points); - instance.components.path = new Lib.Components.Path.from_points (points, false); - recompute_components (); - - return new_live_pts; - } - - /* - * This method is used to check if user clicked on a point in the path. - * Returns true if clicked, false otherwise. - * If a point was clicked, index refers to its location. - * If check_idx is -1, do hit test with all the points. Otherwise - * only with the given point. - */ - public bool hit_test ( - double x, - double y, - ref Geometry.SelectedPoint sel_pnt, - ref Geometry.SelectedPoint underlying_pt, - int check_idx = -1 - ) { - // In order to check if user clicked on a point, we need to rotate the first point and the event - // around the item center. Then the difference between these values gives the location - // event in the same coordinate system as the points. - var transform_matrix = instance.components.transform.transformation_matrix; - var orig_first_pt = Utils.GeometryMath.transform_point_around_item_origin (first_point, transform_matrix, true); - - Geometry.Point point = Geometry.Point (x, y); - point = Utils.GeometryMath.transform_point_around_item_origin (point, transform_matrix, true); - point = Geometry.Point (point.x - orig_first_pt.x, point.y - orig_first_pt.y); - - tangents_inline = false; - double thresh = HIT_SIZE / view_canvas.scale; - - if (check_idx != -1) { - if (Utils.GeometryMath.compare_points (points[check_idx].last_point, point, thresh)) { - sel_pnt.sel_type = Lib.Modes.PathEditMode.PointType.LINE_END; - sel_pnt.sel_index = check_idx; - return true; - } - - sel_pnt.sel_type = Lib.Modes.PathEditMode.PointType.NONE; - sel_pnt.sel_index = -1; - return false; - } - - for (int i = 0; i < points.length; ++i) { - var hit_type = points[i].hit_test (point, thresh); - - if (hit_type == Lib.Modes.PathEditMode.PointType.NONE) { - continue; - } - - if ( - hit_type == Lib.Modes.PathEditMode.PointType.TANGENT_FIRST || - hit_type == Lib.Modes.PathEditMode.PointType.TANGENT_SECOND - ) { - if (!points[i].check_tangents_inline ()) { - sel_pnt.tangents_staggered = true; - } - - if ( - points[i].type == Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT || - points[i].type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE - ) { - sel_pnt.tangents_staggered = true; - } - } - - // Following code checks the current segment, segment and the hit type to find overlapping points. - if (i != points.length - 1 && points[i].type != Lib.Modes.PathEditMode.Type.LINE) { - if ( - points[i + 1].type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE || - points[i + 1].type == Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT - ) { - if (hit_type == Lib.Modes.PathEditMode.PointType.CURVE_BEGIN) { - underlying_pt.sel_index = i + 1; - underlying_pt.sel_type = Lib.Modes.PathEditMode.PointType.CURVE_BEGIN; - } else if (hit_type == Lib.Modes.PathEditMode.PointType.CURVE_END) { - if (points[i + 1].type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE) { - underlying_pt.sel_type = Lib.Modes.PathEditMode.PointType.CURVE_BEGIN; - } else if (points[i + 1].type == Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT) { - underlying_pt.sel_type = Lib.Modes.PathEditMode.PointType.CURVE_BEGIN; - } - - underlying_pt.sel_index = i + 1; - } - } - } - - sel_pnt.sel_type = hit_type; - sel_pnt.sel_index = i; - return true; - } - - // return Lib.Modes.PathEditMode.PointType.NONE; - sel_pnt.sel_type = Lib.Modes.PathEditMode.PointType.NONE; - sel_pnt.sel_index = -1; - return false; - } - - /* - * This method will be used when editing paths to update the position of a point. - */ - public void modify_point_value (Geometry.Point new_pos) { - var transform_matrix = instance.components.transform.transformation_matrix; - var orig_first_pt = Utils.GeometryMath.transform_point_around_item_origin (first_point, transform_matrix, true); - new_pos = Utils.GeometryMath.transform_point_around_item_origin (new_pos, transform_matrix, true); - - new_pos.x -= orig_first_pt.x; - new_pos.y -= orig_first_pt.y; - - if (selected_pts.size == 1) { - // If only one point is selected, it will act as reference point. - reference_point = selected_pts.to_array ()[0]; - } - - Geometry.Point original_ref = points[reference_point.sel_index].get_by_type (reference_point.sel_type); - - // Calculate by how much the reference point changed, then move other points by this amount. - // We are rounding this value to the nearest integer. This is the spacing used in ViewLayerGrid. - double delta_x = Math.round (original_ref.x - new_pos.x); - double delta_y = Math.round (original_ref.y - new_pos.y); - - foreach (var sel_pnt in selected_pts) { - switch (sel_pnt.sel_type) { - case Lib.Modes.PathEditMode.PointType.LINE_END: - var old = points[sel_pnt.sel_index].line_end; - points[sel_pnt.sel_index].line_end = Geometry.Point (old.x - delta_x, old.y - delta_y); - break; - case Lib.Modes.PathEditMode.PointType.CURVE_BEGIN: - // When this points moves, tangents must be moved with it too. - // To make this easier, move the whole segment then return - // CURVE_BEGIN to its original position. - points[sel_pnt.sel_index].translate (delta_x, delta_y); - var old = points[sel_pnt.sel_index].curve_end; - points[sel_pnt.sel_index].curve_end = Geometry.Point (old.x + delta_x, old.y + delta_y); - - if (points[sel_pnt.sel_index].type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE) { - // For single cubic curve, when CURVE_BEGIN moves, the second tangent should not move with it. - old = points[sel_pnt.sel_index].tangent_2; - points[sel_pnt.sel_index].tangent_2 = Geometry.Point (old.x + delta_x, old.y + delta_y); - } - break; - case Lib.Modes.PathEditMode.PointType.TANGENT_FIRST: - if (sel_pnt.tangents_staggered) { - var old = points[sel_pnt.sel_index].tangent_1; - points[sel_pnt.sel_index].tangent_1 = Geometry.Point (old.x - delta_x, old.y - delta_y); - } else { - points[sel_pnt.sel_index].move_tangents (delta_x, delta_y, true); - } - break; - case Lib.Modes.PathEditMode.PointType.TANGENT_SECOND: - if (sel_pnt.tangents_staggered) { - var old = points[sel_pnt.sel_index].tangent_2; - points[sel_pnt.sel_index].tangent_2 = Geometry.Point (old.x - delta_x, old.y - delta_y); - } else { - points[sel_pnt.sel_index].move_tangents (delta_x, delta_y, false); - } - break; - case Lib.Modes.PathEditMode.PointType.CURVE_END: - var old = points[sel_pnt.sel_index].curve_end; - points[sel_pnt.sel_index].curve_end = Geometry.Point (old.x - delta_x, old.y - delta_y); - - if (points[sel_pnt.sel_index].type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE) { - // For single cubic curve, when curve end is moved, move the second tangent too. - old = points[sel_pnt.sel_index].tangent_2; - points[sel_pnt.sel_index].tangent_2 = Geometry.Point (old.x - delta_x, old.y - delta_y); - } - break; - } - } - - points = recalculate_points (points); - bool close = instance.components.path.close; - instance.components.path = new Lib.Components.Path.from_points (points, close); - recompute_components (); - } - - /* - * This method is used to change the selected points. - * idx is index of point to be added to selection. if -1, it is not added. - * If append is true, add the item to the list, otherwise, clear the list then add. - */ - public void set_selected_points (Geometry.SelectedPoint sel_pnt, bool append = false) { - if (!append) { - selected_pts.clear (); - } - - if (sel_pnt.sel_index != -1) { - selected_pts.add (sel_pnt); - } - - update_view (); - } - - /* - * This method is used to join the first and last point of path - * to make it a closed curve. - */ - public void make_path_closed () { - instance.components.path = new Lib.Components.Path.from_points (points, true); - recompute_components (); - } - - public bool check_can_path_close () { - int last = points.length - 1; - - if (last == 0) { - return false; - } - - double thresh = HIT_SIZE / view_canvas.scale; - if (Utils.GeometryMath.compare_points (points[0].last_point, points[last].last_point, thresh)) { - make_path_closed (); - return true; - } - - return false; - } - - /* - * This method shift all points in path such that none of them are in negative space. - */ - private Geometry.PathSegment[] recalculate_points (Geometry.PathSegment[] points) { - double min_x = double.MAX, min_y = double.MAX; - - var path = new Lib.Components.Path.from_points (points); - var ext = path.calculate_extents (); - - min_x = ext.left; - min_y = ext.top; - - // Shift all the points. - for (int i = 0; i < points.length; ++i) { - points[i].translate (min_x, min_y); - } - - // The amount by which the first point changed must be rotated before adding to first point. - Geometry.Point delta = Geometry.Point (min_x, min_y); - - var transform_matrix = instance.components.transform.transformation_matrix; - var rotated_delta = Utils.GeometryMath.transform_point_around_item_origin (delta, transform_matrix); - - first_point.x += rotated_delta.x; - first_point.y += rotated_delta.y; - - return points; - } - - private void recompute_components () { - var bounds = instance.components.path.calculate_extents (); - - double center_x = bounds.width / 2.0; - double center_y = bounds.height / 2.0; - - var tr = instance.components.transform.transformation_matrix; - tr.transform_point (ref center_x, ref center_y); - - center_x += first_point.x; - center_y += first_point.y; - - instance.components.center = new Lib.Components.Coordinates (center_x, center_y); - instance.components.size = new Lib.Components.Size (bounds.width, bounds.height, false); - - // Update the component. - unowned var im = view_canvas.items_manager; - im.item_model.alert_item_changed (instance.id, Lib.Components.Component.Type.COMPILED_GEOMETRY); - im.compile_model (); - - update_view (); - } - - /* - * Recalculates the extents and updates the ViewLayerPath - */ - public void update_view () { - // Since the bounding box for the instance may not include the tangents, - // we need to calculate the bounding box for all points. - var tr = instance.components.transform.transformation_matrix; - - var extents_from_pts = Utils.GeometryMath.bounds_from_points (points); - var extents_from_path = instance.components.path.calculate_extents (); - - double offset_x = extents_from_path.center_x - extents_from_pts.center_x; - double offset_y = extents_from_path.center_y - extents_from_pts.center_y; - tr.transform_point (ref offset_x, ref offset_y); - - double pts_center_x = instance.components.center.x - offset_x; - double pts_center_y = instance.components.center.y - offset_y; - - var quad = Geometry.Quad.from_components ( - pts_center_x, - pts_center_y, - extents_from_pts.width, - extents_from_pts.height, - tr - ); - - var new_ext = quad.bounding_box; - - double radius = ViewLayers.ViewLayerPath.UI_NOB_SIZE / view_canvas.scale; - new_ext.left -= radius; - new_ext.top -= radius; - new_ext.right += radius; - new_ext.bottom += radius; - - PathDataModel path_data = PathDataModel (); - path_data.points = points; - path_data.live_segment = live_segment; - path_data.live_point_type = live_point_type; - path_data.extents = new_ext; - path_data.transform = instance.drawable.transform; - path_data.selected_pts = selected_pts; - path_data.last_point = get_last_point_from_path (); - - path_data.live_extents = get_extents_using_live_pts (extents_from_pts); - - double center_x = -instance.compiled_geometry.source_width / 2.0; - double center_y = -instance.compiled_geometry.source_height / 2.0; - path_data.center = Geometry.Point (center_x, center_y); - - path_layer.update_path_data (path_data); - } - - private Geometry.Rectangle get_extents_using_live_pts (Geometry.Rectangle extents) { - if (points.length == 0 || live_point_type == Lib.Modes.PathEditMode.PointType.NONE) { - return extents; - } - - var live_pnts = new Geometry.PathSegment[2]; - live_pnts[0] = Geometry.PathSegment.line ( get_last_point_from_path ()); - live_pnts[1] = live_segment; - - var live_extents = Utils.GeometryMath.bounds_from_points (live_pnts); - - double radius = ViewLayers.ViewLayerPath.UI_NOB_SIZE / view_canvas.scale; - live_extents.left -= radius; - live_extents.top -= radius; - live_extents.right += radius; - live_extents.bottom += radius; - - return live_extents; - } - - public Geometry.Point get_last_point_from_path () { - Cairo.Matrix transform_matrix = instance.components.transform.transformation_matrix; - var orig_first_pt = Utils.GeometryMath.transform_point_around_item_origin (first_point, transform_matrix, true); - - if (instance.components.path.data.length == 0) { - return orig_first_pt; - } - - Geometry.Point last_point = points[points.length - 1].last_point; - - last_point.x += orig_first_pt.x; - last_point.y += orig_first_pt.y; - last_point = Utils.GeometryMath.transform_point_around_item_origin (last_point, transform_matrix); - - return last_point; - } -} - -public struct Akira.Models.PathDataModel { - public Geometry.PathSegment[] points; - - public Geometry.PathSegment live_segment; - public Lib.Modes.PathEditMode.PointType live_point_type; - - public Geometry.Point last_point; - - public Geometry.Rectangle extents; - public Geometry.Rectangle live_extents; - - public Geometry.Point center; - - public Cairo.Matrix transform; - public Gee.HashSet selected_pts; -} diff --git a/src/Services/ActionManager.vala b/src/Services/ActionManager.vala deleted file mode 100644 index c78b33d46..000000000 --- a/src/Services/ActionManager.vala +++ /dev/null @@ -1,592 +0,0 @@ -/* -* Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -* Authored by: Ivan "isneezy" Vilanculo -*/ - -public class Akira.Services.ActionManager : Object { - public weak Akira.Application app { get; construct; } - public weak Akira.Window window { get; construct; } - - private const int PREVIEW_SIZE = 300; - private const int PREVIEW_PADDING = 3; - - private Gtk.FileChooserNative dialog; - private Gtk.Image preview_image; - - public SimpleActionGroup actions { get; construct; } - - public const string ACTION_PREFIX = "win."; - public const string ACTION_NEW_WINDOW = "action_new_window"; - public const string ACTION_OPEN = "action_open"; - public const string ACTION_SAVE = "action_save"; - public const string ACTION_SAVE_AS = "action_save_as"; - public const string ACTION_LOAD_FIRST = "action_load_first"; - public const string ACTION_LOAD_SECOND = "action_load_second"; - public const string ACTION_LOAD_THIRD = "action_load_third"; - public const string ACTION_TOGGLE_PIXEL_GRID = "action-show-pixel-grid"; - public const string ACTION_PRESENTATION = "action_presentation"; - public const string ACTION_PREFERENCES = "action_preferences"; - public const string ACTION_EXPORT_SELECTION = "action_export_selection"; - public const string ACTION_EXPORT_ARTBOARDS = "action_export_artboards"; - public const string ACTION_EXPORT_GRAB = "action_export_grab"; - public const string ACTION_QUIT = "action_quit"; - public const string ACTION_ZOOM_IN = "action_zoom_in"; - public const string ACTION_ZOOM_IN_2 = "action_zoom_in_2"; - public const string ACTION_ZOOM_OUT = "action_zoom_out"; - public const string ACTION_ZOOM_RESET = "action_zoom_reset"; - public const string ACTION_MOVE_UP = "action_move_up"; - public const string ACTION_MOVE_DOWN = "action_move_down"; - public const string ACTION_MOVE_TOP = "action_move_top"; - public const string ACTION_MOVE_BOTTOM = "action_move_bottom"; - public const string ACTION_ARTBOARD_TOOL = "action_artboard_tool"; - public const string ACTION_RECT_TOOL = "action_rect_tool"; - public const string ACTION_ELLIPSE_TOOL = "action_ellipse_tool"; - public const string ACTION_TEXT_TOOL = "action_text_tool"; - public const string ACTION_IMAGE_TOOL = "action_image_tool"; - public const string ACTION_PATH_TOOL = "action_path_tool"; - public const string ACTION_DELETE = "action_delete"; - public const string ACTION_FLIP_H = "action_flip_h"; - public const string ACTION_FLIP_V = "action_flip_v"; - public const string ACTION_ESCAPE = "action_escape"; - public const string ACTION_SHORTCUTS = "action_shortcuts"; - public const string ACTION_PICK_COLOR = "action_pick_color"; - public const string ACTION_DUPLICATE = "action_duplicate"; - public const string ACTION_COPY = "action_copy"; - public const string ACTION_PASTE = "action_paste"; - public const string ACTION_ALIGN_LEFT = "action_align_left"; - public const string ACTION_ALIGN_RIGHT = "action_align_right"; - public const string ACTION_ALIGN_TOP = "action_align_top"; - public const string ACTION_ALIGN_BOTTOM = "action_align_bottom"; - public const string ACTION_ALIGN_VCENTER = "action_align_vcenter"; - public const string ACTION_ALIGN_HCENTER = "action_align_hcenter"; - public const string ACTION_UNDO = "action_undo"; - public const string ACTION_REDO = "action_redo"; - - public static Gee.MultiMap action_accelerators = new Gee.HashMultiMap (); - public static Gee.MultiMap typing_accelerators = new Gee.HashMultiMap (); - - private const ActionEntry[] ACTION_ENTRIES = { - { ACTION_NEW_WINDOW, action_new_window }, - { ACTION_OPEN, action_open }, - { ACTION_SAVE, action_save }, - { ACTION_SAVE_AS, action_save_as }, - { ACTION_LOAD_FIRST, action_load_first }, - { ACTION_LOAD_SECOND, action_load_second }, - { ACTION_LOAD_THIRD, action_load_third }, - { ACTION_TOGGLE_PIXEL_GRID, action_toggle_pixel_grid }, - { ACTION_PRESENTATION, action_presentation }, - { ACTION_PREFERENCES, action_preferences }, - { ACTION_EXPORT_SELECTION, action_export_selection }, - { ACTION_EXPORT_ARTBOARDS, action_export_artboards }, - { ACTION_EXPORT_GRAB, action_export_grab }, - { ACTION_QUIT, action_quit }, - { ACTION_ZOOM_IN, action_zoom_in }, - { ACTION_ZOOM_IN_2, action_zoom_in_2 }, - { ACTION_ZOOM_OUT, action_zoom_out }, - { ACTION_MOVE_UP, action_move_up }, - { ACTION_MOVE_DOWN, action_move_down }, - { ACTION_MOVE_TOP, action_move_top }, - { ACTION_MOVE_BOTTOM, action_move_bottom }, - { ACTION_ZOOM_RESET, action_zoom_reset }, - { ACTION_ARTBOARD_TOOL, action_artboard_tool }, - { ACTION_RECT_TOOL, action_rect_tool }, - { ACTION_ELLIPSE_TOOL, action_ellipse_tool }, - { ACTION_TEXT_TOOL, action_text_tool }, - { ACTION_IMAGE_TOOL, action_image_tool }, - { ACTION_PATH_TOOL, action_path_tool }, - { ACTION_DELETE, action_delete }, - { ACTION_FLIP_H, action_flip_h }, - { ACTION_FLIP_V, action_flip_v }, - { ACTION_ESCAPE, action_escape }, - { ACTION_SHORTCUTS, action_shortcuts }, - { ACTION_PICK_COLOR, action_pick_color }, - { ACTION_DUPLICATE, action_duplicate }, - { ACTION_COPY, action_copy }, - { ACTION_PASTE, action_paste }, - { ACTION_ALIGN_LEFT, action_align_left }, - { ACTION_ALIGN_RIGHT, action_align_right }, - { ACTION_ALIGN_TOP, action_align_top }, - { ACTION_ALIGN_BOTTOM, action_align_bottom }, - { ACTION_ALIGN_VCENTER, action_align_vcenter }, - { ACTION_ALIGN_HCENTER, action_align_hcenter }, - { ACTION_UNDO, action_undo }, - { ACTION_REDO, action_redo }, - }; - - public ActionManager (Akira.Application akira_app, Akira.Window window) { - Object ( - app: akira_app, - window: window - ); - } - - static construct { - action_accelerators.set (ACTION_NEW_WINDOW, "n"); - action_accelerators.set (ACTION_OPEN, "o"); - action_accelerators.set (ACTION_SAVE, "s"); - action_accelerators.set (ACTION_SAVE_AS, "s"); - action_accelerators.set (ACTION_LOAD_FIRST, "1"); - action_accelerators.set (ACTION_LOAD_SECOND, "2"); - action_accelerators.set (ACTION_LOAD_THIRD, "3"); - action_accelerators.set (ACTION_PRESENTATION, "period"); - action_accelerators.set (ACTION_PREFERENCES, "comma"); - action_accelerators.set (ACTION_EXPORT_SELECTION, "e"); - action_accelerators.set (ACTION_EXPORT_ARTBOARDS, "a"); - action_accelerators.set (ACTION_EXPORT_GRAB, "g"); - action_accelerators.set (ACTION_QUIT, "q"); - action_accelerators.set (ACTION_ZOOM_IN_2, "equal"); - action_accelerators.set (ACTION_ZOOM_IN, "plus"); - action_accelerators.set (ACTION_ZOOM_OUT, "minus"); - action_accelerators.set (ACTION_ZOOM_RESET, "0"); - action_accelerators.set (ACTION_MOVE_UP, "Up"); - action_accelerators.set (ACTION_MOVE_DOWN, "Down"); - action_accelerators.set (ACTION_MOVE_TOP, "Up"); - action_accelerators.set (ACTION_MOVE_BOTTOM, "Down"); - action_accelerators.set (ACTION_FLIP_H, "bracketleft"); - action_accelerators.set (ACTION_FLIP_V, "bracketright"); - action_accelerators.set (ACTION_SHORTCUTS, "F1"); - action_accelerators.set (ACTION_PICK_COLOR, "c"); - action_accelerators.set (ACTION_DUPLICATE, "d"); - action_accelerators.set (ACTION_COPY, "c"); - action_accelerators.set (ACTION_PASTE, "v"); - action_accelerators.set (ACTION_ESCAPE, "Escape"); - - typing_accelerators.set (ACTION_ARTBOARD_TOOL, "a"); - typing_accelerators.set (ACTION_RECT_TOOL, "r"); - typing_accelerators.set (ACTION_ELLIPSE_TOOL, "e"); - typing_accelerators.set (ACTION_TEXT_TOOL, "t"); - typing_accelerators.set (ACTION_IMAGE_TOOL, "i"); - typing_accelerators.set (ACTION_PATH_TOOL, "v"); - typing_accelerators.set (ACTION_DELETE, "Delete"); - typing_accelerators.set (ACTION_DELETE, "BackSpace"); - typing_accelerators.set (ACTION_TOGGLE_PIXEL_GRID, "Tab"); - - typing_accelerators.set (ACTION_ALIGN_LEFT, "1"); - typing_accelerators.set (ACTION_ALIGN_HCENTER, "2"); - typing_accelerators.set (ACTION_ALIGN_RIGHT, "3"); - typing_accelerators.set (ACTION_ALIGN_TOP, "4"); - typing_accelerators.set (ACTION_ALIGN_VCENTER, "5"); - typing_accelerators.set (ACTION_ALIGN_BOTTOM, "6"); - - typing_accelerators.set (ACTION_UNDO, "z"); - typing_accelerators.set (ACTION_REDO, "z"); - } - - construct { - actions = new SimpleActionGroup (); - actions.add_action_entries (ACTION_ENTRIES, this); - window.insert_action_group ("win", actions); - - var iter = action_accelerators.map_iterator (); - while (iter.next ()) { - app.set_accels_for_action (ACTION_PREFIX + iter.get_key (), { iter.get_value () }); - } - - enable_typing_accels (); - - window.event_bus.disconnect_typing_accel.connect (disable_typing_accels); - window.event_bus.connect_typing_accel.connect (enable_typing_accels); - } - - // Temporarily disable all the accelerators that might interfere with input fields. - private void disable_typing_accels () { - var iter = typing_accelerators.map_iterator (); - while (iter.next ()) { - app.set_accels_for_action (ACTION_PREFIX + iter.get_key (), {}); - } - } - - // Enable all the accelerators that might interfere with input fields. - private void enable_typing_accels () { - var iter = typing_accelerators.map_iterator (); - while (iter.next ()) { - app.set_accels_for_action (ACTION_PREFIX + iter.get_key (), { iter.get_value () }); - } - } - - private void action_quit () { - window.before_destroy (); - } - - private void action_presentation () { - window.event_bus.toggle_presentation_mode (); - } - - private void action_new_window () { - app.new_window (); - } - - private void action_open () { - window.file_manager.open_file (); - } - - private void action_save () { - window.file_manager.save_file (); - } - - private void action_save_as () { - window.file_manager.save_file_as (); - } - - public void action_load_first () { - if (settings.recently_opened.length == 0 || settings.recently_opened[0] == null) { - window.event_bus.canvas_notification (_("No recently opened file available!")); - return; - } - - var file = File.new_for_path (settings.recently_opened[0]); - if (!file.query_exists ()) { - window.event_bus.canvas_notification ( - _("Unable to open file at '%s'").printf (settings.recently_opened[0]) - ); - return; - } - - File[] files = {}; - files += file; - window.app.open (files, ""); - } - - private void action_load_second () { - if (settings.recently_opened.length < 1 || settings.recently_opened[1] == null) { - window.event_bus.canvas_notification (_("No second most recently opened file available!")); - return; - } - - var file = File.new_for_path (settings.recently_opened[1]); - if (!file.query_exists ()) { - window.event_bus.canvas_notification ( - _("Unable to open file at '%s'").printf (settings.recently_opened[1]) - ); - return; - } - - File[] files = {}; - files += file; - window.app.open (files, ""); - } - - private void action_load_third () { - if (settings.recently_opened.length < 2 || settings.recently_opened[2] == null) { - window.event_bus.canvas_notification (_("No third most recently opened file available!")); - return; - } - - var file = File.new_for_path (settings.recently_opened[2]); - if (!file.query_exists ()) { - window.event_bus.canvas_notification ( - _("Unable to open file at '%s'").printf (settings.recently_opened[2]) - ); - return; - } - - File[] files = {}; - files += file; - window.app.open (files, ""); - } - - private void action_toggle_pixel_grid () { - window.event_bus.toggle_pixel_grid (); - } - - private void action_preferences () { - var settings_dialog = new Akira.Dialogs.SettingsDialog (window); - settings_dialog.show_all (); - settings_dialog.present (); - settings_dialog.close.connect (() => { - window.event_bus.set_focus_on_canvas (); - }); - } - - private void action_export_selection () { - unowned Akira.Lib.ViewCanvas canvas = window.main_window.main_view_canvas.canvas; - canvas.export_selection.begin (); - } - - private void action_export_artboards () { - // Check if at least an artboard is present. - window.main_window.main_view_canvas.trigger_notification (_("Export of Artboards currently unavailable…sorry 😑️")); - // TODO: Trigger artboards pixbuf generation. - } - - private void action_export_grab () { - unowned Akira.Lib.ViewCanvas canvas = window.main_window.main_view_canvas.canvas; - var new_mode = new Lib.Modes.ExportMode (canvas); - canvas.mode_manager.register_mode (new_mode); - } - - private void action_zoom_in () { - window.event_bus.adjust_zoom (0.1, false, null); - } - - private void action_zoom_in_2 () { - action_zoom_in (); - } - - private void action_zoom_out () { - window.event_bus.adjust_zoom (-0.1, false, null); - } - - private void action_zoom_reset () { - window.event_bus.adjust_zoom (1, true, null); - } - - private void action_move_up () { - window.event_bus.change_z_selected (true, false); - } - - private void action_move_down () { - window.event_bus.change_z_selected (false, false); - } - - private void action_move_top () { - window.event_bus.change_z_selected (true, true); - } - - private void action_move_bottom () { - window.event_bus.change_z_selected (false, true); - } - - private void action_artboard_tool () { - window.event_bus.insert_item ("artboard"); - } - - private void action_rect_tool () { - window.event_bus.insert_item ("rectangle"); - } - - // Delete the currently selected items. - private void action_delete () { - window.event_bus.delete_selected_items (); - } - - private void action_flip_h () { - window.event_bus.flip_item (); - } - - private void action_flip_v () { - window.event_bus.flip_item (true); - } - - private void action_ellipse_tool () { - window.event_bus.insert_item ("ellipse"); - } - - private void action_text_tool () { - window.event_bus.insert_item ("text"); - } - - private void action_image_tool () { - dialog = new Gtk.FileChooserNative ( - _("Choose image file"), window, Gtk.FileChooserAction.OPEN, _("Select"), _("Close")); - - preview_image = new Gtk.Image (); - dialog.preview_widget = preview_image; - dialog.update_preview.connect (on_update_preview); - - dialog.select_multiple = true; - - dialog.response.connect ((response_id) => on_choose_image_response (dialog, response_id)); - dialog.show (); - } - - private void action_path_tool () { - window.event_bus.insert_item ("path"); - } - - private void on_update_preview () { - string? filename = dialog.get_preview_filename (); - if (filename == null) { - dialog.set_preview_widget_active (false); - return; - } - - // Read the image format data first. - int width = 0; - int height = 0; - Gdk.PixbufFormat? format = Gdk.Pixbuf.get_file_info (filename, out width, out height); - - if (format == null) { - dialog.set_preview_widget_active (false); - return; - } - - // If the image is too big, resize it. - Gdk.Pixbuf pixbuf; - try { - pixbuf = new Gdk.Pixbuf.from_file_at_scale (filename, PREVIEW_SIZE, PREVIEW_SIZE, true); - } catch (Error e) { - dialog.set_preview_widget_active (false); - return; - } - - if (pixbuf == null) { - dialog.set_preview_widget_active (false); - return; - } - - pixbuf = pixbuf.apply_embedded_orientation (); - - // Distribute the extra space around the image. - int extra_space = PREVIEW_SIZE - pixbuf.width; - int smaller_half = extra_space / 2; - int larger_half = extra_space - smaller_half; - - // Pad the image manually and avoids rounding errors. - preview_image.set_margin_start (PREVIEW_PADDING + smaller_half); - preview_image.set_margin_end (PREVIEW_PADDING + larger_half); - - // Show the preview. - preview_image.set_from_pixbuf (pixbuf); - dialog.set_preview_widget_active (true); - } - - private void on_choose_image_response (Gtk.FileChooserNative dialog, int response_id) { - // switch (response_id) { - // case Gtk.ResponseType.ACCEPT: - // case Gtk.ResponseType.OK: - // SList files = dialog.get_files (); - // files.@foreach ((file) => { - // if (!Akira.Utils.Image.is_valid_image (file)) { - // window.event_bus.canvas_notification ( - // _("Error! .%s files are not supported!" - // ).printf (Akira.Utils.Image.get_extension (file))); - // return; - // } - - // var manager = new Akira.Lib.Managers.ImageManager (file, files.index (file)); - // window.items_manager.insert_image (manager); - // }); - // break; - // } - dialog.destroy (); - } - - private void action_escape () { - window.event_bus.request_escape (); - // If the layout is hidden, allow users to easily get out of presentation mode - // when they press Escape. - if (!window.headerbar.toggled) { - action_presentation (); - } - } - - private void action_shortcuts () { - var dialog = new Akira.Dialogs.ShortcutsDialog (window); - dialog.show_all (); - dialog.present (); - } - - private void action_pick_color () { - // weak Akira.Lib.Canvas canvas = window.main_window.main_canvas.canvas; - - // // Interrupt if no item is selected. - // if (canvas.selected_bound_manager.selected_items.length () == 0) { - // return; - // } - - // bool is_holding_shift = false; - // var color_picker = new Akira.Widgets.ColorPicker (); - // color_picker.show_all (); - - // color_picker.key_pressed.connect (e => { - // is_holding_shift = e.keyval == Gdk.Key.Shift_L; - // }); - - // color_picker.key_released.connect (e => { - // is_holding_shift = e.keyval == Gdk.Key.Shift_L; - // }); - - // color_picker.cancelled.connect (() => { - // color_picker.close (); - // }); - - // color_picker.picked.connect (color => { - // foreach (var item in canvas.selected_bound_manager.selected_items) { - // // Ignore the item if it doesn't have a fills or border component - // // based on the shift key pressed by the user. - // if ((item.fills == null && !is_holding_shift) || (item.borders == null && is_holding_shift)) { - // continue; - // } - - // if (is_holding_shift) { - // item.borders.update_color_from_action (color); - // continue; - // } - - // item.fills.update_color_from_action (color); - // } - - // color_picker.close (); - - // // Force a UI reload of the fills and borders panel since some items - // // had their properties changed. - // canvas.window.event_bus.selected_items_list_changed (canvas.selected_bound_manager.selected_items); - // }); - } - - private void action_duplicate () { - window.event_bus.request_duplicate (); - } - - private void action_copy () { - window.event_bus.request_copy (); - } - - private void action_paste () { - window.event_bus.request_paste (); - } - - private void action_align_left () { - window.event_bus.selection_align (Utils.ItemAlignment.AlignmentDirection.LEFT); - } - - private void action_align_right () { - window.event_bus.selection_align (Utils.ItemAlignment.AlignmentDirection.RIGHT); - } - - private void action_align_top () { - window.event_bus.selection_align (Utils.ItemAlignment.AlignmentDirection.TOP); - } - - private void action_align_bottom () { - window.event_bus.selection_align (Utils.ItemAlignment.AlignmentDirection.BOTTOM); - } - - private void action_align_vcenter () { - window.event_bus.selection_align (Utils.ItemAlignment.AlignmentDirection.VCENTER); - } - - private void action_align_hcenter () { - window.event_bus.selection_align (Utils.ItemAlignment.AlignmentDirection.HCENTER); - } - - private void action_undo () { - window.event_bus.undo (); - } - - private void action_redo () { - window.event_bus.redo (); - } - - public static void action_from_group (string action_name, ActionGroup? action_group) { - action_group.activate_action (action_name, null); - } -} diff --git a/src/Services/EventBus.vala b/src/Services/EventBus.vala deleted file mode 100644 index f26e46c13..000000000 --- a/src/Services/EventBus.vala +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA - * - * Authored by: Giacomo "giacomoalbe" Alberini - * Authored by: Alessandro "alecaddd" Castellani - */ - -public class Akira.Services.EventBus : Object { - // File signals. - public signal void file_edited (); - public signal void file_saved (string? file_name); - public signal void update_recent_files_list (); - - // Layout signals. - public signal void change_sensitivity (string type); - public signal void request_widget_redraw (); - public signal void change_theme (); - public signal void toggle_presentation_mode (); - - // Canvas signals. - public signal void coordinate_change (double x, double y); - public signal void insert_item (string type); - public signal void item_inserted (); - public signal void move_item_from_canvas (Gdk.EventKey event); - public signal void request_escape (); - public signal void set_focus_on_canvas (); - public signal void update_nob_size (); - public signal void canvas_notification (string message); - public signal void hide_select_effect (); - public signal void show_select_effect (); - public signal void toggle_pixel_grid (); - public signal void update_pixel_grid (); - public signal void update_snaps_color (); - public signal void update_snap_decorators (); - public signal void zoom_changed (double new_zoom); - - // Canvas triggers. - public signal void adjust_zoom (double zoom, bool absolute, Geometry.Point? reference); - - // Options panel signals. - public signal void align_items (string align_action); - public signal void init_state_coords (); - public signal void reset_state_coords (); - public signal void update_state_coords (double moved_x, double moved_y); - public signal void item_value_changed (); - - // Item signals. - public signal void change_z_selected (bool raise, bool total); - public signal void flip_item (bool vertical = false); - public signal void detect_artboard_change (); - public signal void detect_image_size_change (); - - // Lib signals. - // Signal triggered every time an item is added or removed from the selection - // map. Connect this signal when elements of the UI need to be updated based - // on the selected items. - public signal void selection_modified (); - // Signal triggered every time an item is added or removed from the selection - // map, as well as when a geometry change happens. This is mostly needed by - // the Nob Manager to properly update the select effect. - // INFO!!! DO NOT USE THIS to listen for simple selection changes as it's - // triggered at every geometry change. Use the simple selection_modified (); - public signal void selection_geometry_modified (); - public signal void request_copy (); - public signal void request_paste (bool in_place = false); - public signal void request_duplicate (); - public signal void delete_selected_items (); - - // Selection align signals - public signal void selection_align (Utils.ItemAlignment.AlignmentDirection type); - - // Others. - public signal void disconnect_typing_accel (); - public signal void connect_typing_accel (); - - // Export signals. - public signal void toggle_export_button (bool sensitive); - // History signals - public signal void create_model_snapshot (string description); - public signal void undo (); - public signal void redo (); -} diff --git a/src/Services/Settings.vala b/src/Services/Settings.vala deleted file mode 100644 index 50a643bd4..000000000 --- a/src/Services/Settings.vala +++ /dev/null @@ -1,165 +0,0 @@ -/* -* Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -* Bilal Elmoussaoui -*/ - -public class Akira.Services.Settings : GLib.Settings { - // Main window settings. - public string version { - owned get { return get_string ("version"); } - set { set_string ("version", value); } - } - public int pos_x { - get { return get_int ("pos-x"); } - set { set_int ("pos-x", value); } - } - public int pos_y { - get { return get_int ("pos-y"); } - set { set_int ("pos-y", value); } - } - public int window_width { - get { return get_int ("window-width"); } - set { set_int ("window-width", value); } - } - public int window_height { - get { return get_int ("window-height"); } - set { set_int ("window-height", value); } - } - public int right_paned { - get { return get_int ("right-paned"); } - set { set_int ("right-paned", value); } - } - public int left_paned { - get { return get_int ("left-paned"); } - set { set_int ("left-paned", value); } - } - - // Theme settings. - public bool dark_theme { - get { return get_boolean ("dark-theme"); } - set { set_boolean ("dark-theme", value); } - } - public bool follow_system_theme { - get { return get_boolean ("follow-system-theme"); } - set { set_boolean ("follow-system-theme", value); } - } - public bool show_label { - get { return get_boolean ("show-label"); } - set { set_boolean ("show-label", value); } - } - public bool use_symbolic { - get { return get_boolean ("use-symbolic"); } - set { set_boolean ("use-symbolic", value); } - } - - // Default canvas settings. - public string grid_color { - owned get { return get_string ("grid-color"); } - set { set_string ("grid-color", value); } - } - public bool enable_snaps { - get { return get_boolean ("enable-snaps"); } - set { set_boolean ("enable-snaps", value); } - } - public string snaps_color { - owned get { return get_string ("snaps-color"); } - set { set_string ("snaps-color", value); } - } - public int snaps_sensitivity { - get { return get_int ("snaps-sensitivity"); } - set { set_int ("snaps-sensitivity", value); } - } - - // Default shape settings. - public string fill_color { - owned get { return get_string ("fill-color"); } - set { set_string ("fill-color", value); } - } - public bool set_border { - get { return get_boolean ("set-border"); } - set { set_boolean ("set-border", value); } - } - public int border_size { - get { return get_int ("border-size"); } - set { set_int ("border-size", value); } - } - public string border_color { - owned get { return get_string ("border-color"); } - set { set_string ("border-color", value); } - } - - // File settings. - public bool open_quick { - get { return get_boolean ("open-quick"); } - set { set_boolean ("open-quick", value); } - } - public string[] recently_opened { - owned get { return get_strv ("recently-opened"); } - set { set_strv ("recently-opened", value); } - } - - // Export Settings. - public string export_folder { - owned get { return get_string ("export-folder"); } - set { set_string ("export-folder", value); } - } - public int export_width { - get { return get_int ("export-width"); } - set { set_int ("export-width", value); } - } - public int export_height { - get { return get_int ("export-height"); } - set { set_int ("export-height", value); } - } - public int export_paned { - get { return get_int ("export-paned"); } - set { set_int ("export-paned", value); } - } - public int export_quality { - get { return get_int ("export-quality"); } - set { set_int ("export-quality", value); } - } - public int export_compression { - get { return get_int ("export-compression"); } - set { set_int ("export-compression", value); } - } - public string export_format { - owned get { return get_string ("export-format"); } - set { set_string ("export-format", value); } - } - public int export_scale { - get { return get_int ("export-scale"); } - set { set_int ("export-scale", value); } - } - public bool export_alpha { - get { return get_boolean ("export-alpha"); } - set { set_boolean ("export-alpha", value); } - } - - // Colors library. - public string[] global_colors { - owned get { return get_strv ("global-colors"); } - set { set_strv ("global-colors", value); } - } - - public Settings () { - Object (schema_id: Constants.APP_ID); - } -} diff --git a/src/Utils/AffineTransform.vala b/src/Utils/AffineTransform.vala deleted file mode 100644 index a9ada514f..000000000 --- a/src/Utils/AffineTransform.vala +++ /dev/null @@ -1,512 +0,0 @@ -/** - * Copyright (c) 2020-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Giacomo "giacomoalbe" Alberini - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Utils.AffineTransform : Object { - private const int MIN_SIZE = 1; - private const int MIN_POS = 10; - - /* - * Scales a node and its children relative to a reference frame. - */ - public static void scale_node ( - Lib.Items.Model item_model, - Lib.Items.ModelNode node, - Lib.Modes.TransformMode.InitialDragState initial_drag_state, - Cairo.Matrix inverse_reference_matrix, - double global_offset_x, - double global_offset_y, - double reference_sx, - double reference_sy - ) { - // #TODO wip - unowned var item = node.instance; - - if ((item.components.center != null && item.components.size != null) || item.components.path != null) { - var item_drag_data = initial_drag_state.item_data_map[node.id]; - - var start_quad = initial_drag_state.start_area.quad (); - - var strf = Cairo.Matrix (reference_sx, 0, 0, reference_sy, 0, 0); - double center_offset_x = item_drag_data.item_geometry.area.center_x - start_quad.center_x; - double center_offset_y = item_drag_data.item_geometry.area.center_y - start_quad.center_y; - - var new_transform = Utils.GeometryMath.multiply_matrices ( - item_drag_data.item_geometry.transformation_matrix, - inverse_reference_matrix - ); - - new_transform = Utils.GeometryMath.multiply_matrices (new_transform, strf); - new_transform = Utils.GeometryMath.multiply_matrices ( - new_transform, - initial_drag_state.start_area.matrix - ); - - var new_width = item_drag_data.item_geometry.source_width; - var new_height = item_drag_data.item_geometry.source_height; - double scale_x = 0.0; - double scale_y = 0.0; - double shear_x = 0.0; - double angle = 0.0; - - Utils.GeometryMath.decompose_matrix (new_transform, ref scale_x, ref scale_y, ref shear_x, ref angle); - - var scale_transform = Cairo.Matrix (scale_x, 0, 0, scale_y, 0, 0); - scale_transform.transform_distance (ref new_width, ref new_height); - - strf.transform_distance (ref center_offset_x, ref center_offset_y); - var d_x = start_quad.center_x + global_offset_x + center_offset_x; - var d_y = start_quad.center_y + global_offset_y + center_offset_y; - - item.components.center = new Lib.Components.Coordinates (d_x, d_y); - - - if (item.type is Lib.Items.ModelTypePath) { - item.components.transform = new Lib.Components.Transform (angle, scale_x, scale_y, shear_x, 0); - } - else { - item.components.transform = new Lib.Components.Transform (angle, 1.0, 1.0, shear_x, 0); - item.components.size = new Lib.Components.Size (new_width, new_height, false); - } - - item_model.alert_node_changed (node, Lib.Components.Component.Type.COMPILED_GEOMETRY); - } - - unowned var layout = item.components.layout; - if ((layout == null || layout.dilated_resize) && node.children != null) { - foreach (unowned var child in node.children.data) { - child.instance.type.apply_scale_transform ( - item_model, - child, - initial_drag_state, - inverse_reference_matrix, - global_offset_x, - global_offset_y, - reference_sx, - reference_sy - ); - } - } - } - - /** - * Calculate adjustments necessary for a nob resize operation. All inputs - * should have already been transformed to the correct space. - */ - public static void calculate_size_adjustments ( - Utils.Nobs.Nob nob, - double item_width, - double item_height, - double delta_x, - double delta_y, - double size_ratio, - bool ratio_locked, - bool symmetric, - Cairo.Matrix transform, - ref double inc_x, - ref double inc_y, - ref double inc_width, - ref double inc_height - ) { - double local_x_adj = 0.0; - double local_y_adj = 0.0; - double perm_x_adj = 0.0; - double perm_y_adj = 0.0; - double perm_w_adj = 0; - double perm_h_adj = 0; - - nob = correct_nob ( - nob, - item_width, - item_height, - symmetric, - ref delta_x, - ref delta_y, - ref perm_x_adj, - ref perm_y_adj, - ref perm_w_adj, - ref perm_h_adj - ); - - double symmetry_offset_x = 0; - double symmetry_offset_y = 0; - - // Handle vertical adjustment. - if (Utils.Nobs.is_top_nob (nob)) { - inc_height = fix_size (-delta_y); - local_y_adj = -inc_height; - - if (symmetric) { - inc_height *= 2; - } - } else if (Utils.Nobs.is_bot_nob (nob)) { - inc_height = fix_size (inc_height + delta_y); - - if (symmetric) { - symmetry_offset_y = -delta_y; - local_y_adj = symmetry_offset_y; - inc_height += delta_y; - } - } - - // Handle horizontal adjustment. - if (Utils.Nobs.is_left_nob (nob)) { - inc_width = fix_size (inc_width - delta_x); - local_x_adj = -inc_width; - - if (symmetric) { - inc_width *= 2; - } - } else if (Utils.Nobs.is_right_nob (nob)) { - inc_width = fix_size (delta_x); - - if (symmetric) { - symmetry_offset_x = -delta_x; - local_x_adj = symmetry_offset_x; - inc_width += delta_x; - } - } - - if (ratio_locked) { - item_width += perm_w_adj; - item_height += perm_h_adj; - - bool pure_v = (nob == Utils.Nobs.Nob.TOP_CENTER || nob == Utils.Nobs.Nob.BOTTOM_CENTER); - bool pure_h = (nob == Utils.Nobs.Nob.RIGHT_CENTER || nob == Utils.Nobs.Nob.LEFT_CENTER); - - if (pure_v || (!pure_h && (item_width + inc_width) / (item_height + inc_height) < size_ratio)) { - inc_width = fix_size ((inc_height + perm_h_adj) * size_ratio - perm_w_adj); - if (symmetric) { - local_x_adj = -fix_size (inc_width / 2.0); - } else if (nob == Utils.Nobs.Nob.TOP_LEFT || nob == Utils.Nobs.Nob.BOTTOM_LEFT) { - local_x_adj = -inc_width; - } else if (pure_v) { - local_x_adj = - fix_size (inc_width / 2.0); - } - } else if (!pure_v) { - inc_height = fix_size ((inc_width + perm_w_adj) / size_ratio - perm_h_adj); - if (symmetric) { - local_y_adj = -fix_size (inc_height / 2.0); - } else if (nob == Utils.Nobs.Nob.TOP_LEFT || nob == Utils.Nobs.Nob.TOP_RIGHT) { - local_y_adj = -inc_height; - } else if (pure_h) { - local_y_adj = - fix_size (inc_height / 2.0); - } - } - } - - apply_transform_to_adjustment ( - transform, - local_x_adj + perm_x_adj, - local_y_adj - perm_y_adj, - ref inc_x, - ref inc_y - ); - - inc_width += perm_w_adj; - inc_height += perm_h_adj; - } - - /** - * Calculate adjustments necessary for a nob resize operation. All inputs - * should have already been transformed to the correct space. - */ - public static Utils.Nobs.Nob calculate_size_adjustments2 ( - Utils.Nobs.Nob nob, - double item_width, - double item_height, - double delta_x, - double delta_y, - double size_ratio, - bool ratio_locked, - bool symmetric, - Cairo.Matrix transform, - ref double inc_x, - ref double inc_y, - ref double inc_width, - ref double inc_height - ) { - double local_x_adj = 0.0; - double local_y_adj = 0.0; - double perm_x_adj = 0.0; - double perm_y_adj = 0.0; - double perm_w_adj = 0; - double perm_h_adj = 0; - - nob = correct_nob ( - nob, - item_width, - item_height, - symmetric, - ref delta_x, - ref delta_y, - ref perm_x_adj, - ref perm_y_adj, - ref perm_w_adj, - ref perm_h_adj - ); - - double symmetry_offset_x = 0; - double symmetry_offset_y = 0; - - // Handle vertical adjustment. - if (Utils.Nobs.is_top_nob (nob)) { - inc_height = -delta_y; - local_y_adj = -inc_height; - - if (symmetric) { - inc_height *= 2; - } - } else if (Utils.Nobs.is_bot_nob (nob)) { - inc_height = inc_height + delta_y; - - if (symmetric) { - symmetry_offset_y = -delta_y; - local_y_adj = symmetry_offset_y; - inc_height += delta_y; - } - } - - // Handle horizontal adjustment. - if (Utils.Nobs.is_left_nob (nob)) { - inc_width = inc_width - delta_x; - local_x_adj = -inc_width; - - if (symmetric) { - inc_width *= 2; - } - } else if (Utils.Nobs.is_right_nob (nob)) { - inc_width = delta_x; - - if (symmetric) { - symmetry_offset_x = -delta_x; - local_x_adj = symmetry_offset_x; - inc_width += delta_x; - } - } - - if (ratio_locked) { - item_width += perm_w_adj; - item_height += perm_h_adj; - - bool pure_v = (nob == Utils.Nobs.Nob.TOP_CENTER || nob == Utils.Nobs.Nob.BOTTOM_CENTER); - bool pure_h = (nob == Utils.Nobs.Nob.RIGHT_CENTER || nob == Utils.Nobs.Nob.LEFT_CENTER); - - if (pure_v || (!pure_h && (item_width + inc_width) / (item_height + inc_height) < size_ratio)) { - inc_width = (inc_height + perm_h_adj) * size_ratio - perm_w_adj; - if (symmetric) { - local_x_adj = -inc_width / 2.0; - } else if (nob == Utils.Nobs.Nob.TOP_LEFT || nob == Utils.Nobs.Nob.BOTTOM_LEFT) { - local_x_adj = -inc_width; - } else if (pure_v) { - local_x_adj = - inc_width / 2.0; - } - } else if (!pure_v) { - inc_height = (inc_width + perm_w_adj) / size_ratio - perm_h_adj; - if (symmetric) { - local_y_adj = -inc_height / 2.0; - } else if (nob == Utils.Nobs.Nob.TOP_LEFT || nob == Utils.Nobs.Nob.TOP_RIGHT) { - local_y_adj = -inc_height; - } else if (pure_h) { - local_y_adj = - inc_height / 2.0; - } - } - } - - apply_transform_to_adjustment ( - transform, - local_x_adj + perm_x_adj, - local_y_adj - perm_y_adj, - ref inc_x, - ref inc_y - ); - - inc_width += perm_w_adj; - inc_height += perm_h_adj; - - return nob; - } - /** - * Corrects which nob should be used for scaling depending on the delta change of the drag. - * The nob will be flipped in the vertical and horizontal directions if needed, and - * the necessary adjustments to delta_x, delta_y and other adjustments will be populated. - * - * h_flip will be true if a horizontal flip is required. - * v_flip will be true if a vertical flip is required. - * delta_x and delta_y are the delta positions from the start of the drag to the current position. - * perm_{x,y}_adj are permanent translation adjustments required on the bounding box. - * perm_{h,w}_adj are permanent scaling adjustments required on the bounding box. - * both _adj adjustments are in the items' local coordinates. - */ - private static Utils.Nobs.Nob correct_nob ( - Utils.Nobs.Nob nob, - double item_width, - double item_height, - bool symmetric, - ref double delta_x, - ref double delta_y, - ref double perm_x_adj, - ref double perm_y_adj, - ref double perm_w_adj, - ref double perm_h_adj - ) { - var height_to_check = symmetric ? item_height / 2.0 : item_height; - var width_to_check = symmetric ? item_width / 2.0 : item_width; - - if (Utils.Nobs.is_top_nob (nob)) { - if (fix_size (height_to_check - delta_y) == 0) { - delta_y -= 1; - } else if (height_to_check - delta_y < 0) { - delta_y -= height_to_check; - perm_y_adj = -item_height + (item_height - height_to_check); - perm_h_adj = -item_height; - - if (nob == Utils.Nobs.Nob.TOP_LEFT) { - nob = Utils.Nobs.Nob.BOTTOM_LEFT; - } else if (nob == Utils.Nobs.Nob.TOP_CENTER) { - // Nothing more to do. - return Utils.Nobs.Nob.BOTTOM_CENTER; - } else if (nob == Utils.Nobs.Nob.TOP_RIGHT) { - nob = Utils.Nobs.Nob.BOTTOM_RIGHT; - } - } - } else if (Utils.Nobs.is_bot_nob (nob)) { - if (fix_size (height_to_check + delta_y) == 0) { - delta_y += 1; - } else if (height_to_check + delta_y < 0) { - delta_y += height_to_check; - perm_y_adj = - (item_height - height_to_check); - perm_h_adj = -item_height; - if (nob == Utils.Nobs.Nob.BOTTOM_LEFT) { - nob = Utils.Nobs.Nob.TOP_LEFT; - } else if (nob == Utils.Nobs.Nob.BOTTOM_CENTER) { - // Nothing more to do. - return Utils.Nobs.Nob.TOP_CENTER; - } else if (nob == Utils.Nobs.Nob.BOTTOM_RIGHT) { - nob = Utils.Nobs.Nob.TOP_RIGHT; - } - } - } - - if (Utils.Nobs.is_left_nob (nob)) { - if (fix_size (width_to_check - delta_x) == 0) { - delta_x -= 1; - } else if (width_to_check - delta_x < 0) { - delta_x -= width_to_check; - perm_x_adj = item_width - (item_width - width_to_check); - perm_w_adj = -item_width; - - if (nob == Utils.Nobs.Nob.TOP_LEFT) { - nob = Utils.Nobs.Nob.TOP_RIGHT; - } else if (nob == Utils.Nobs.Nob.LEFT_CENTER) { - nob = Utils.Nobs.Nob.RIGHT_CENTER; - } else if (nob == Utils.Nobs.Nob.BOTTOM_LEFT) { - nob = Utils.Nobs.Nob.BOTTOM_RIGHT; - } - } - } else if (Utils.Nobs.is_right_nob (nob)) { - if (fix_size (width_to_check + delta_x) == 0) { - delta_x += 1; - } else if (width_to_check + delta_x < 0) { - delta_x += width_to_check; - perm_x_adj = (item_width - width_to_check); - perm_w_adj = -item_width; - - if (nob == Utils.Nobs.Nob.TOP_RIGHT) { - nob = Utils.Nobs.Nob.TOP_LEFT; - } else if (nob == Utils.Nobs.Nob.RIGHT_CENTER) { - nob = Utils.Nobs.Nob.LEFT_CENTER; - } else if (nob == Utils.Nobs.Nob.BOTTOM_RIGHT) { - nob = Utils.Nobs.Nob.BOTTOM_LEFT; - } - } - } - - return nob; - } - - /** - * Apply transform to a translation adjustment, and adjust the increment with it. - */ - private static void apply_transform_to_adjustment ( - Cairo.Matrix transform, - double adj_x, - double adj_y, - ref double inc_x, - ref double inc_y - ) { - transform.transform_distance (ref adj_x, ref adj_y); - inc_x += adj_x; - inc_y += adj_y; - } - - // public static void adjust_size (Lib.Items.CanvasItem item, double adj_x, double adj_y) { - // var new_width = item.size.width + adj_x; - // var new_height = item.size.height + adj_y; - - // // Prevent accidental negative values. - // if (new_width > 0) { - // item.size.width = new_width; - // } - - // if (new_height > 0) { - // item.size.height = new_height; - // } - // } - - public static double fix_size (double size) { - return GLib.Math.round (size); - } - - public static double deg_to_rad (double deg) { - return deg * Math.PI / 180.0; - } - - /* - * Rectifies and positions a center and size based on the top-left corner and a starting size. - */ - public static void geometry_from_top_left ( - double left, - double top, - ref double center_x, - ref double center_y, - ref double width, - ref double height - ) { - width = fix_size (width); - height = fix_size (height); - - center_x = fix_size (left) + width / 2.0; - center_y = fix_size (top) + height / 2.0; - } - - public static void add_grid_snap_delta ( - double x, - double y, - ref double delta_x, - ref double delta_y - ) { - var combined_x = x + delta_x; - var combined_y = y + delta_y; - delta_x += fix_size (combined_x) - combined_x; - delta_y += fix_size (combined_y) - combined_y; - } -} diff --git a/src/Utils/Array.vala b/src/Utils/Array.vala deleted file mode 100644 index 1b9f13081..000000000 --- a/src/Utils/Array.vala +++ /dev/null @@ -1,269 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (http://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/** - * Implements array methods that are useful. Some pertain to raw arrays and some to GLib.Array - */ -public class Akira.Utils.Array : Object { - /* - * Insert value in an int array. Return true on success. - */ - public static bool insert_at_iarray (ref int[] a, int pos, int value) { - if (pos > a.length || pos < 0) { - assert (false); - return false; - } - - if (pos == a.length) { - return append_to_iarray (ref a, value); - } - - a.resize (a.length + 1); - a.move (pos, pos + 1, a.length - pos - 1); - a[pos] = value; - return true; - } - - /* - * Insert an array of integers within another array at `pos`. - */ - public static bool insert_array_at_iarray (ref int[] a, int pos, int [] other) { - if (pos > a.length || pos < 0) { - assert (false); - return false; - } - - int start_length = a.length; - - a.resize (start_length + other.length); - a.move (pos, pos + other.length, start_length - pos); - - for (var i = 0; i < other.length; ++i) { - a[pos + i] = other[i]; - } - - return true; - } - - /* - * Appends value at the end of an int array. Return true on success. - */ - public static bool append_to_iarray (ref int[] a, int value) { - a.resize (a.length + 1); - a[a.length - 1] = value; - return true; - } - - /* - * Removes 'length' number of values at 'pos' from int array. - */ - public static bool remove_from_iarray (ref int[] a, int pos, int length) { - if (pos >= a.length || pos + length > a.length || pos < 0 || length < 0) { - assert (false); - return false; - } - - a.move (pos + length, pos, a.length - pos - length); - a.resize (a.length - length); - return true; - } - - /* - * Rotates an int array. - - * Ranges first->middle and middle->end must be valid index ranges within a - * middle will become the first int in the span. - */ - public static bool rotate_iarray (ref int[] arr, int first, int middle, int end) { - if (first < 0 || end > arr.length) { - assert (first >= 0); - assert (end < arr.length); - return false; - } - - if (first == middle || middle == end) { - // no-op - return true; - } - - var next = middle; - - while (first != next) { - swap_iarray (ref arr, first ++, next++); - if (next == end) { - next = middle; - } else if (first == middle) { - middle = next; - } - } - return true; - } - - /* - * Gets minimum and maximum value in an int array. - */ - public static void min_max_in_iarray (int[] positions, ref int min, ref int max) { - foreach (var pos in positions) { - if (pos < min) { - min = pos; - } - if (pos > max) { - max = pos; - } - } - - if (min == 0) { - min = max; - } - } - - /* - * Gets minimum and maximum value in an double array. - */ - public static void min_max_in_darray (double[] positions, out double min, out double max) { - min = double.MAX; - max = double.MIN; - - foreach (var pos in positions) { - if (pos < min) { - min = pos; - } - if (pos > max) { - max = pos; - } - } - - if (min == double.MAX) { - min = 0; - } - - if (max == double.MIN) { - max = 0; - } - } - - /* - * Rotates a GLib.Array. - */ - public static void rotate_garray (ref GLib.Array arr, int first, int middle, int end) { - if (first < 0 || end > arr.length) { - assert (first >= 0); - assert (end < arr.length); - return; - } - - assert (middle >= first); - assert (end >= middle); - - if (first == middle || middle == end) { - return; - } - - var next = middle; - - while (first != next) { - swap_garray (ref arr, first++, next++); - if (next == end) { - next = middle; - } else if (first == middle) { - middle = next; - } - } - } - - /* - * Rotates a GLib.Array with unowned values. - */ - public static void rotate_weak_garray (ref GLib.Array arr, int first, int middle, int end) { - if (first < 0 || end > arr.length) { - assert (first >= 0); - assert (end < arr.length); - return; - } - - assert (middle >= first); - assert (end >= middle); - - if (first == middle || middle == end) { - return; - } - - var next = middle; - - while (first != next) { - swap_weak_garray (ref arr, first++, next++); - if (next == end) { - next = middle; - } else if (first == middle) { - middle = next; - } - } - } - - /* - * Swaps 'a' and 'b' indices from an int array. - */ - public static void swap_iarray (ref int[] arr, int a, int b) { - var tmp = arr[a]; - arr[a] = arr[b]; - arr[b] = tmp; - } - - /* - * Swaps 'a' and 'b' indices from a double array. - */ - public static void swap_darray (ref double[] arr, int a, int b) { - var tmp = arr[a]; - arr[a] = arr[b]; - arr[b] = tmp; - } - - /* - * Swaps 'a' and 'b' indices from a GLib.Array. - */ - public static void swap_garray (ref GLib.Array arr, int a, int b) { - var tmp = arr.index (a); - arr.data[a] = arr.index (b); - arr.data[b] = tmp; - } - - /* - * Swaps 'a' and 'b' indices from a GLib.Array of unowned objects. - */ - public static void swap_weak_garray (ref GLib.Array arr, int a, int b) { - var tmp = arr.index (a); - arr.data[a] = arr.index (b); - arr.data[b] = tmp; - } - - public static int compare_arrays (int[] a, int[] b) { - int len_a = a.length; - int len_b = b.length; - - var res = Posix.memcmp (a, b, (size_t)int.min (len_a, len_b) * sizeof (int)); - - if (res == 0 && len_a != len_b) { - return len_a < len_b ? -1 : 1; - } - - return res; - } -} diff --git a/src/Utils/Bezier.vala b/src/Utils/Bezier.vala deleted file mode 100644 index e891ddeef..000000000 --- a/src/Utils/Bezier.vala +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Ashish Shevale - */ - -public class Akira.Utils.Bezier { - public static double[] get_extremes (Geometry.Point p1, Geometry.Point p2, Geometry.Point p3) { - // Return as[min_x, min_y, max_x, max_y] - double min_x = double.MAX; - double max_x = double.MIN; - double min_y = double.MAX; - double max_y = double.MIN; - - // Get the t parameter for the bezier where the curve would be extreme. - // The bounding box has to be enclosed completely within these points. - double tx = (p1.x - p2.x) / (p1.x - 2 * p2.x + p3.x); - double ty = (p1.y - p2.y) / (p1.y - 2 * p2.y + p3.y); - - // Temporary var used when calculating min and max. - double temp; - - if (tx.is_nan () || tx <= 0 || tx >= 1) { - temp = double.min (p1.x, p3.x); - min_x = double.min (min_x, temp); - - temp = double.max (p1.x, p3.x); - max_x = double.max (max_x, temp); - } else { - // Get the extreme point wrt x axis for the bezier. - var ex = point_on_curve (p1, p2, p3, tx); - - temp = double.min (p1.x, double.min (p3.x, ex.x)); - min_x = double.min (min_x, temp); - - temp = double.max (p1.x, double.max (p3.x, ex.x)); - max_x = double.max (max_x, temp); - - } - - if (ty.is_nan () || ty <= 0 || ty >= 1) { - temp = double.min (p1.y, p3.y); - min_y = double.min (min_y, temp); - - temp = double.max (p1.y, p3.y); - max_y = double.max (max_y, temp); - } else { - // Get the extreme point wrt y axis for the bezier. - var ey = point_on_curve (p1, p2, p3, ty); - temp = double.min (p1.y, double.min (p3.y, ey.y)); - min_y = double.min (min_y, temp); - - temp = double.max (p1.y, double.max (p3.y, ey.y)); - max_y = double.max (max_y, temp); - } - - double[] res = new double[4]; - res[0] = min_x; - res[1] = min_y; - res[2] = max_x; - res[3] = max_y; - - return res; - } - - public static Geometry.Point point_on_curve (Geometry.Point p1, Geometry.Point p2, Geometry.Point p3, double t) { - var c1 = Geometry.Point (p1.x + (p2.x - p1.x) * t, p1.y + (p2.y - p1.y) * t); - var c2 = Geometry.Point (p2.x + (p3.x - p2.x) * t, p2.y + (p3.y - p2.y) * t); - - var point = Geometry.Point (c1.x + (c2.x - c1.x) * t, c1.y + (c2.y - c1.y) * t); - return point; - } -} diff --git a/src/Utils/BlendingMode.vala b/src/Utils/BlendingMode.vala deleted file mode 100644 index abbc45c63..000000000 --- a/src/Utils/BlendingMode.vala +++ /dev/null @@ -1,70 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Giacomo "giacomoalbe" Alberini -*/ - -public enum Akira.Utils.BlendingMode { - NORMAL, - MULTIPLY, - OVERLAY, - SOFT_LIGHT, - HARD_LIGHT, - LIGHTEN, - DARKEN, - SCREEN, - DIFFERENCE, - LUMINOSITY, - HUE; - - public static BlendingMode[] all () { - return { - NORMAL, - MULTIPLY, - OVERLAY, - SOFT_LIGHT, - HARD_LIGHT, - LIGHTEN, - DARKEN, - SCREEN, - DIFFERENCE, - LUMINOSITY, - HUE - }; - } - - public string get_name () { - var blending_mode_tokens = this - .to_string () - .split ("_"); - - // Get everything but BLENDING_MODE - blending_mode_tokens = blending_mode_tokens[4:blending_mode_tokens.length]; - - var formatted_blending_mode = ""; - - foreach (var elem in blending_mode_tokens) { - elem = elem[0].toupper ().to_string () + - elem[1:elem.length].down (); - - formatted_blending_mode += elem; - } - - return formatted_blending_mode; - } -} diff --git a/src/Utils/Color.vala b/src/Utils/Color.vala deleted file mode 100644 index 274e5c59b..000000000 --- a/src/Utils/Color.vala +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Giacomo "giacomoalbe" Alberini - */ - -/** - * Helper object class containing all static methods for RGBA manipulation. - */ -public class Akira.Utils.Color : Object { - public static string rgba_to_hex (string rgba_string) { - var rgba = Gdk.RGBA (); - rgba.parse (rgba_string); - - return rgba_to_hex_string (rgba); - } - - public static string rgba_to_hex_string (Gdk.RGBA rgba) { - return "#%02x%02x%02x".printf ( - (int) (rgba.red * 255), - (int) (rgba.green * 255), - (int) (rgba.blue * 255) - ); - } - - public static Gdk.RGBA hex_to_rgba (string hex) { - var rgba = Gdk.RGBA (); - rgba.parse (hex); - - return rgba; - } - - public static bool is_valid_hex (string hex) { - if (hex == "") { - return false; - } - - // Interrupt if there is no '#' in the hex value. This prevents the app - // from crashing when the user deletes the '#' already present in a - // valid hex value. - if (!hex.contains ("#")) { - return false; - } - - var hex_values = hex.split ("#") [1]; - - if (hex_values.length != 3 && hex_values.length != 6) { - return false; - } - - // Since validation is done inside the insert-text - // we can assume that, if it's arrived here - // the content is only 0-9A-F - return true; - } - - public static uint rgba_to_uint (Gdk.RGBA rgba) { - uint uint_rgba = 0; - - uint_rgba |= ((uint) (rgba.red * 255)) << 24; - uint_rgba |= ((uint) (rgba.green * 255)) << 16; - uint_rgba |= ((uint) (rgba.blue * 255)) << 8; - uint_rgba |= ((uint) (rgba.alpha * 255)); - - return uint_rgba; - } - - public static Gdk.RGBA blend_colors (Gdk.RGBA base_color, Gdk.RGBA added_color) { - // If the newly added color alpha is 0 we don't need to do any color mixing - // as the added color won't alter the base color. - if (added_color.alpha == 0.0) { - return base_color; - } - - // If the newly added color alpha is 1 or the base color alpha is 0 - // we don't need to do any color mixing, as the added color will be - // the only one visible. - if (added_color.alpha == 1.0 || base_color.alpha == 0) { - return added_color; - } - - // Simple blend using Alpha channels. In the future we will support - // different blending modes. - double alpha = 1 - (1 - added_color.alpha) * (1 - base_color.alpha); - double ar1 = added_color.alpha / alpha; - double ar2 = (1 - added_color.alpha) / alpha; - - double red = added_color.red * ar1 + base_color.red * base_color.alpha * ar2; - double green = added_color.green * ar1 + base_color.green * base_color.alpha * ar2; - double blue = added_color.blue * ar1 + base_color.blue * base_color.alpha * ar2; - - var rgba = Gdk.RGBA (); - rgba.alpha = alpha; - rgba.red = red; - rgba.green = green; - rgba.blue = blue; - - return rgba; - } - - public static uint color_string_to_uint (string color) { - var rgba = Gdk.RGBA (); - rgba.parse (color); - - return rgba_to_uint (rgba); - } -} diff --git a/src/Utils/Delegates.vala b/src/Utils/Delegates.vala deleted file mode 100644 index a92309ab2..000000000 --- a/src/Utils/Delegates.vala +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2022 Alecaddd (http://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * A collection of useful delegate definitions - */ - -public delegate void Akira.Utils.TrivialDelegate (); diff --git a/src/Utils/Dialogs.vala b/src/Utils/Dialogs.vala deleted file mode 100644 index a43005828..000000000 --- a/src/Utils/Dialogs.vala +++ /dev/null @@ -1,56 +0,0 @@ -/* -* Copyright (c) 2019-2023 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.Utils.Dialogs : Object { - public weak Akira.Window window { get; construct; } - - public Dialogs (Akira.Window window) { - Object ( - window: window - ); - } - - public Granite.MessageDialog message_dialog ( - string title, - string description, - string icon, - string? primary_button = null, - string? secondary_button = null - ) { - var dialog = new Granite.MessageDialog.with_image_from_icon_name ( - title, description, icon, Gtk.ButtonsType.CANCEL); - dialog.transient_for = window; - - if (secondary_button != null) { - var button2 = new Gtk.Button.with_label (secondary_button); - button2.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); - dialog.add_action_widget (button2, 2); - } - - if (primary_button != null) { - var button = new Gtk.Button.with_label (primary_button); - button.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION); - dialog.add_action_widget (button, Gtk.ResponseType.ACCEPT); - } - - return dialog; - } -} diff --git a/src/Utils/GeometryMath.vala b/src/Utils/GeometryMath.vala deleted file mode 100644 index 1690ab992..000000000 --- a/src/Utils/GeometryMath.vala +++ /dev/null @@ -1,419 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (http://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Utils.GeometryMath : Object { - - public static double clamp (double value, double min, double max) { - return double.min (double.max (value, min), max); - } - - public static void min_max (ref double x0, ref double x1) { - if (x1 < x0) { - double t = x0; - x0 = x1; - x1 = t; - } - } - - public static void min_max_coords (double x0, double x1, double x2, double x3, ref double min, ref double max) { - min_max (ref x0, ref x1); - min_max (ref x2, ref x3); - - min = x0 < x2 ? x0 : x2; - max = x1 > x3 ? x1 : x3; - } - - public static double distance (double x0, double y0, double x1, double y1) { - var xx = (x1 - x0) * (x1 - x0); - var yy = (y1 - y0) * (y1 - y0); - - return GLib.Math.sqrt (xx + yy); - } - - public static void normalize (ref double dx, ref double dy) { - var dm = GLib.Math.sqrt (dx * dx + dy * dy); - dx = dm > 0 ? (dx / dm) : 0; - dy = dm > 0 ? (dy / dm) : 0; - } - - public static void to_local ( - double rotation_rad, - double rot_center_x, - double rot_center_y, - ref double x, - ref double y - ) { - var tr = Cairo.Matrix.identity (); - tr.rotate (rotation_rad); - to_local_from_matrix (tr, rot_center_x, rot_center_y, ref x, ref y); - } - - public static void to_local_from_matrix ( - Cairo.Matrix tr, - double rot_center_x, - double rot_center_y, - ref double x, - ref double y - ) { - double dx = x - rot_center_x; - double dy = y - rot_center_y; - - tr.transform_distance (ref dx, ref dy); - - x = rot_center_x + dx; - y = rot_center_y + dy; - } - - public static bool points_on_same_side_of_line ( - double l1_x, - double l1_y, - double l2_x, - double l2_y, - double p1_x, - double p1_y, - double p2_x, - double p2_y - ) { - double delta_x = l2_x - l1_x; - double delta_y = l2_y - l1_y; - - double one = delta_x * (p1_y - l1_y) - delta_y * (p1_x - l1_x); - double two = delta_x * (p2_y - l2_y) - delta_y * (p2_x - l2_x); - - return (one >= 0 && two >= 0) || (one <= 0 && two <= 0); - } - - public static bool is_normal_rotation (double rot_in_degrees) { - return GLib.Math.fmod (rot_in_degrees, 90) == 0; - } - - public static double vector2_dot_product (double x0, double y0, double x1, double y1) { - return x0 * x1 + y0 * y1; - } - - public static double vector2_cross_product (double x0, double y0, double x1, double y1) { - return x0 * y1 - y0 * x1; - } - - - public static double angle_between_vectors (double x0, double y0, double x1, double y1) { - return GLib.Math.atan2 ( - vector2_cross_product (x0, y0, x1, y1), - vector2_dot_product (x0, y0, x1, y1) - ); - } - - public static void matrix_skew_x (ref Cairo.Matrix mat, double factor) { - var skew_mat = Cairo.Matrix (1.0, 0.0, factor, 1.0, 0, 0); - mat = multiply_matrices (mat, skew_mat); - } - - public static void matrix_skew_y (ref Cairo.Matrix mat, double factor) { - var skew_mat = Cairo.Matrix (1.0, factor, 0.0, 1.0, 0, 0); - mat = multiply_matrices (mat, skew_mat); - } - - public static void matrix_rotate (ref Cairo.Matrix mat, double angle) { - var rot_mat = Cairo.Matrix.identity (); - rot_mat.rotate (angle); - mat = multiply_matrices (mat, rot_mat); - } - - public static Cairo.Matrix multiply_matrices (Cairo.Matrix a, Cairo.Matrix b) { - return Cairo.Matrix ( - a.xx * b.xx + a.yx * b.xy, - a.xx * b.yx + a.yx * b.yy, - a.xy * b.xx + a.yy * b.xy, - a.xy * b.yx + a.yy * b.yy, - a.x0 * b.xx + a.y0 * b.xy + b.x0, - a.x0 * b.yx + a.y0 * b.yy + b.y0); - } - - /* - * Returns the rotation component of a matrix. - */ - public static double matrix_rotation_component (Cairo.Matrix mat) { - return GLib.Math.atan2 (mat.yx, mat.xx); - } - - /* - * Decomposes a matrix to three operations (scale, shear and rotation) - * - * To recompose run two multiplications: - * var new_matrix = multiply_matrices (scale_matrix, shear_matrix); - * new_matrix = multiply_matrices (new_matrix, rotation_matrix); - */ - public static bool decompose_matrix ( - Cairo.Matrix mat, - ref double scale_x, - ref double scale_y, - ref double shear_x, - ref double angle - ) { - // https://math.stackexchange.com/questions/612006/decomposing-an-affine-transformation - var xx = mat.xx; - var xy = mat.xy; - var yx = mat.yx; - var yy = mat.yy; - - double det = xx * yy - xy * yx; - if (det.abs () < 0.000001) { - return false; - } - - scale_x = GLib.Math.sqrt (xx * xx + yx * yx); - - angle = GLib.Math.atan2 (yx, xx); - - var sin_th = GLib.Math.sin (angle); - var cos_th = GLib.Math.cos (angle); - - var msy = xy * cos_th + yy * sin_th; - - if (sin_th != 0) { - scale_y = (msy * cos_th - xy) / sin_th; - } else { - scale_y = (yy - sin_th * msy) / cos_th; - } - - // Not sure about this - //if (det < 0) { - // if (xx < yy) { - // scale_x = -scale_x; - // } else { - // scale_y = -scale_y; - // } - //} - - shear_x = msy / scale_y; - - return true; - } - - public static void recompose_matrix ( - out Cairo.Matrix mat, - double scale_x, - double scale_y, - double shear_x, - double angle - ) { - mat = Cairo.Matrix (scale_x, 0.0, 0.0, scale_y, 0.0, 0.0); - matrix_skew_x (ref mat, shear_x); - var rot = Cairo.Matrix.identity (); - rot.rotate (angle); - mat = multiply_matrices (mat, rot); - } - - public static void transform_quad ( - Cairo.Matrix transform, - ref Geometry.Quad area - ) { - var center_x = area.center_x; - var center_y = area.center_y; - area.translate (-center_x, -center_y); - area.transformation = multiply_matrices (area.transformation, transform); - - transform.transform_distance (ref area.tr_x, ref area.tr_y); - transform.transform_distance (ref area.tl_x, ref area.tl_y); - transform.transform_distance (ref area.br_x, ref area.br_y); - transform.transform_distance (ref area.bl_x, ref area.bl_y); - area.translate (center_x, center_y); - } - - public static Geometry.Quad apply_stretch ( - Cairo.Matrix stretch_mat, - Geometry.Quad area, - double offset_x, - double offset_y, - double center_offset_x, - double center_offset_y, - ref double width, - ref double height, - ref double rotation, - ref double xx, - ref double yy, - ref double xy, - ref double yx - ) { - stretch_mat.transform_distance (ref center_offset_x, ref center_offset_y); - - var dx = area.center_x; - var dy = area.center_y; - area.translate (-dx, -dy); - - stretch_mat.transform_distance (ref area.tl_x, ref area.tl_y); - stretch_mat.transform_distance (ref area.tr_x, ref area.tr_y); - stretch_mat.transform_distance (ref area.bl_x, ref area.bl_y); - stretch_mat.transform_distance (ref area.br_x, ref area.br_y); - - width = distance (area.tl_x, area.tl_y, area.tr_x, area.tr_y).abs (); - height = distance (area.tl_x, area.tl_y, area.bl_x, area.bl_y).abs (); - - var ltor_x = area.tr_x - area.tl_x; - var ltor_y = area.tr_y - area.tl_y; - - rotation = angle_between_vectors (1, 0, ltor_x, ltor_y); - - var extra_rot_mat = Cairo.Matrix.identity (); - extra_rot_mat.rotate (-rotation); - - extra_rot_mat.transform_distance (ref area.tl_x, ref area.tl_y); - extra_rot_mat.transform_distance (ref area.tr_x, ref area.tr_y); - extra_rot_mat.transform_distance (ref area.bl_x, ref area.bl_y); - extra_rot_mat.transform_distance (ref area.br_x, ref area.br_y); - - yy = (area.br_y - area.tr_y).abs () / height; - xy = (area.br_x - area.tr_x) / (area.br_y - area.tr_y) * yy; - - area.translate (dx + offset_x + center_offset_x, dy + offset_y + center_offset_y); - - return area; - } - - public static Geometry.Point rotate_point (Geometry.Point point, double rotation, Geometry.Point origin) { - double cos_theta = Math.cos (rotation); - double sin_theta = Math.sin (rotation); - - double rot_x = cos_theta * (point.x - origin.x) - sin_theta * (point.y - origin.y) + origin.x; - double rot_y = sin_theta * (point.x - origin.x) + cos_theta * (point.y - origin.y) + origin.y; - - return Geometry.Point (rot_x, rot_y); - } - - public static bool compare_points (Geometry.Point a, Geometry.Point b, double thresh) { - if (Utils.GeometryMath.distance (a.x, a.y, b.x, b.y) < thresh) { - return true; - } - - return false; - } - - public static Geometry.Rectangle bounds_from_points (Geometry.PathSegment[] points) { - Geometry.Rectangle bounds = Geometry.Rectangle (); - bounds.left = double.MAX; - bounds.top = double.MAX; - bounds.right = double.MIN; - bounds.bottom = double.MIN; - - foreach (var pt in points) { - // Create a list of all points we need to calculate bounds for. - Geometry.Point[] pts_in_segment = new Geometry.Point[0]; - - if (pt.type == Lib.Modes.PathEditMode.Type.LINE) { - pts_in_segment = new Geometry.Point[1]; - pts_in_segment[0] = pt.line_end; - } else if (pt.type == Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT) { - pts_in_segment = new Geometry.Point[2]; - pts_in_segment[0] = pt.curve_begin; - pts_in_segment[1] = pt.tangent_1; - } else if (pt.type == Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT) { - pts_in_segment = new Geometry.Point[2]; - pts_in_segment[0] = pt.curve_end; - pts_in_segment[1] = pt.tangent_2; - } else if (pt.type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE) { - pts_in_segment = new Geometry.Point[4]; - pts_in_segment[0] = pt.curve_begin; - pts_in_segment[1] = pt.tangent_1; - pts_in_segment[2] = pt.tangent_2; - pts_in_segment[3] = pt.curve_end; - } else if (pt.type == Lib.Modes.PathEditMode.Type.CUBIC_DOUBLE) { - pts_in_segment = new Geometry.Point[4]; - pts_in_segment[0] = pt.curve_begin; - pts_in_segment[1] = pt.tangent_1; - pts_in_segment[2] = pt.tangent_2; - pts_in_segment[3] = pt.curve_end; - } - - // Update bounds for all these points. - foreach (var point in pts_in_segment) { - bounds.left = double.min (bounds.left, point.x); - bounds.right = double.max (bounds.right, point.x); - bounds.top = double.min (bounds.top, point.y); - bounds.bottom = double.max (bounds.bottom, point.y); - } - } - - return bounds; - } - - public static Geometry.Rectangle calculate_bounds_for_curve (Geometry.PathSegment segment, Geometry.Point point_before) { - var p1 = segment.curve_begin; - var p2 = segment.tangent_1; - var p3 = segment.tangent_2; - var p4 = segment.curve_end; - - double min_x = double.MAX, min_y = double.MAX, max_x = double.MIN, max_y = double.MIN; - - if ( - segment.type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE || - segment.type == Lib.Modes.PathEditMode.Type.CUBIC_DOUBLE - ) { - double[] b1_extremes = Utils.Bezier.get_extremes (point_before, p2, p1); - double[] b2_extremes = Utils.Bezier.get_extremes (p1, p3, p4); - - double temp = double.min (b1_extremes[0], b2_extremes[0]); - min_x = double.min (min_x, temp); - - temp = double.min (b1_extremes[1], b2_extremes[1]); - min_y = double.min (min_y, temp); - - temp = double.max (b1_extremes[2], b2_extremes[2]); - max_x = double.max (max_x, temp); - - temp = double.max (b1_extremes[3], b2_extremes[3]); - max_y = double.max (max_y, temp); - } else if (segment.type == Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT) { - double[] b_extremes = Utils.Bezier.get_extremes (point_before, p2, p1); - - min_x = double.min (b_extremes[0], min_x); - min_y = double.min (b_extremes[1], min_y); - max_x = double.max (b_extremes[2], max_x); - max_y = double.max (b_extremes[3], max_y); - } else if (segment.type == Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT) { - double[] b_extremes = Utils.Bezier.get_extremes (point_before, p3, p4); - - min_x = double.min (b_extremes[0], min_x); - min_y = double.min (b_extremes[1], min_y); - max_x = double.max (b_extremes[2], max_x); - max_y = double.max (b_extremes[3], max_y); - } else { - assert (false); - } - - return Geometry.Rectangle.with_coordinates (min_x, min_y, max_x, max_y); - } - public static Geometry.Point transform_point_around_item_origin ( - Geometry.Point point, - Cairo.Matrix mat, - bool invert = false - ) { - var matrix = Utils.GeometryMath.multiply_matrices (Cairo.Matrix.identity (), mat); - - if (invert) { - matrix.invert (); - } - - var new_point = Geometry.Point (point.x, point.y); - matrix.transform_point (ref new_point.x, ref new_point.y); - return new_point; - } - -} diff --git a/src/Utils/Image.vala b/src/Utils/Image.vala deleted file mode 100644 index 03c7371b5..000000000 --- a/src/Utils/Image.vala +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2020 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Utils.Image : Object { - private const string[] ACCEPTED_TYPES = { - "image/jpeg", - "image/png", - "image/tiff", - "image/svg+xml", - "image/gif" - }; - - /** - * Check if the filename has a picture file extension. - */ - public static bool is_valid_image (GLib.File file) { - try { - var file_info = file.query_info ("standard::*", 0); - - // Check for correct file type, don't try to load directories. - if (file_info.get_file_type () != GLib.FileType.REGULAR) { - return false; - } - try { - var pixbuf = new Gdk.Pixbuf.from_file (file.get_path ()); - var width = pixbuf.get_width (); - var height = pixbuf.get_height (); - - if (width < 1 || height < 1) return false; - } catch (Error e) { - warning ("Invalid image loaded: %s", e.message); - return false; - } - - foreach (var type in ACCEPTED_TYPES) { - if (GLib.ContentType.equals (file_info.get_content_type (), type)) { - return true; - } - } - } catch (Error e) { - warning ("Could not get file info: %s", e.message); - } - - return false; - } - - /** - * Return only the file extension, PNG if not extension was found. - */ - public static string get_extension (GLib.File file) { - var parts = file.get_basename ().split ("."); - - return parts.length > 1 ? parts[parts.length - 1] : "png"; - } -} diff --git a/src/Utils/ItemAlignment.vala b/src/Utils/ItemAlignment.vala deleted file mode 100644 index 06436437a..000000000 --- a/src/Utils/ItemAlignment.vala +++ /dev/null @@ -1,289 +0,0 @@ - -/** - * Copyright (c) 2021 Alecaddd (http://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Authored by: Giacomo "giacomoalbe" Alberini - */ - -/** - * Utility providing functionality for aligning items - */ -public class Akira.Utils.ItemAlignment : Object { - /* - * Direction along which items should align. - */ - public enum AlignmentDirection { - RIGHT, - LEFT, - TOP, - BOTTOM, - VCENTER, - HCENTER, - } - - /* - * Type of alignment algorithm to use for choosing bounds to align to. - */ - public enum AlignmentType { - AUTO, - FIRST_SELECTED, - LAST_SELECTED, - ANCHOR, - } - - private class AlignOp { - public Lib.Items.ModelNode node; - public double dx; - public double dy; - - public AlignOp (Lib.Items.ModelNode n, double dx, double dy) { - this.node = n; - this.dx = dx; - this.dy = dy; - } - } - - /* - * Align a selection based on a direction and the type of alignment. - */ - public static void align_selection ( - Lib.Items.NodeSelection selection, - AlignmentDirection direction, - AlignmentType type, - Lib.Items.ModelNode? anchor, - Lib.ViewCanvas view_canvas, - Utils.TrivialDelegate? prep_for_op - ) { - if (selection.count () <= 1) { - return; - } - - var align_to = Geometry.Rectangle.empty (); - if (!populate_alignment (selection, type, anchor, ref align_to)) { - return; - } - - var blocker = new Lib.Managers.SelectionManager.ChangeSignalBlocker (view_canvas.selection_manager); - (blocker); - - unowned var items_manager = view_canvas.items_manager; - unowned var model = items_manager.item_model; - - var operations = new Gee.ArrayList (); - - switch (direction) { - case Utils.ItemAlignment.AlignmentDirection.LEFT: - align_selection_to_left (selection, align_to.left, operations); - break; - case Utils.ItemAlignment.AlignmentDirection.RIGHT: - align_selection_to_right (selection, align_to.right, operations); - break; - case Utils.ItemAlignment.AlignmentDirection.TOP: - align_selection_to_top (selection, align_to.top, operations); - break; - case Utils.ItemAlignment.AlignmentDirection.BOTTOM: - align_selection_to_bottom (selection, align_to.bottom, operations); - break; - case Utils.ItemAlignment.AlignmentDirection.VCENTER: - align_selection_to_vcenter (selection, align_to.center_y, operations); - break; - case Utils.ItemAlignment.AlignmentDirection.HCENTER: - align_selection_to_hcenter (selection, align_to.center_x, operations); - break; - default: - break; - } - - if (operations.size == 0) { - return; - } - - if (prep_for_op != null) { - prep_for_op (); - } - - foreach (var op in operations) { - translate_node (op.node, op.dx, op.dy, model); - } - - items_manager.compile_model (); - view_canvas.window.event_bus.update_snap_decorators (); - } - - private static bool populate_alignment ( - Lib.Items.NodeSelection selection, - AlignmentType type, - Lib.Items.ModelNode? anchor, - ref Geometry.Rectangle align_to - ) { - bool found_bounds = false; - - switch (type) { - case AlignmentType.AUTO: - align_to.left = double.MAX; - align_to.right = double.MIN; - align_to.top = double.MAX; - align_to.bottom = double.MIN; - - foreach (var node in selection.nodes.values) { - unowned var bb = node.node.instance.bounding_box; - align_to.left = double.min (align_to.left, bb.left); - align_to.right = double.max (align_to.right, bb.right); - align_to.top = double.min (align_to.top, bb.top); - align_to.bottom = double.max (align_to.bottom, bb.bottom); - found_bounds = true; - } - - break; - case AlignmentType.FIRST_SELECTED: - uint last_sid = uint.MAX; - foreach (var node in selection.nodes.values) { - if (node.sid < last_sid) { - align_to = node.node.instance.bounding_box; - last_sid = node.sid; - found_bounds = true; - } - } - - break; - case AlignmentType.LAST_SELECTED: - uint last_sid = uint.MIN; - foreach (var node in selection.nodes.values) { - if (node.sid > last_sid) { - align_to = node.node.instance.bounding_box; - last_sid = node.sid; - found_bounds = true; - } - } - - break; - case AlignmentType.ANCHOR: - unowned var bb = anchor.instance.bounding_box; - - align_to.left = bb.left; - align_to.right = bb.right; - align_to.top = bb.top; - align_to.bottom = bb.bottom; - found_bounds = true; - break; - default: - break; - } - - return found_bounds; - } - - private static void align_selection_to_left ( - Lib.Items.NodeSelection selection, - double align_to, - Gee.ArrayList operations - ) { - foreach (var node in selection.nodes.values) { - unowned var inst = node.node.instance; - var diff = align_to - inst.bounding_box.left; - if (diff != 0) { - operations.add (new AlignOp (node.node, diff, 0)); - } - } - } - - private static void align_selection_to_right ( - Lib.Items.NodeSelection selection, - double align_to, - Gee.ArrayList operations - ) { - foreach (var node in selection.nodes.values) { - unowned var inst = node.node.instance; - var diff = align_to - inst.bounding_box.right; - if (diff != 0) { - operations.add (new AlignOp (node.node, diff, 0)); - } - } - } - - private static void align_selection_to_top ( - Lib.Items.NodeSelection selection, - double align_to, - Gee.ArrayList operations - ) { - foreach (var node in selection.nodes.values) { - unowned var inst = node.node.instance; - var diff = align_to - inst.bounding_box.top; - if (diff != 0) { - operations.add (new AlignOp (node.node, 0, diff)); - } - } - } - - private static void align_selection_to_bottom ( - Lib.Items.NodeSelection selection, - double align_to, - Gee.ArrayList operations - ) { - foreach (var node in selection.nodes.values) { - unowned var inst = node.node.instance; - var diff = align_to - inst.bounding_box.bottom; - if (diff != 0) { - operations.add (new AlignOp (node.node, 0, diff)); - } - } - } - - private static void align_selection_to_vcenter ( - Lib.Items.NodeSelection selection, - double align_to, - Gee.ArrayList operations - ) { - foreach (var node in selection.nodes.values) { - unowned var inst = node.node.instance; - var diff = align_to - inst.bounding_box.center_y; - if (diff != 0) { - operations.add (new AlignOp (node.node, 0, diff)); - } - } - } - - private static void align_selection_to_hcenter ( - Lib.Items.NodeSelection selection, - double align_to, - Gee.ArrayList operations - ) { - foreach (var node in selection.nodes.values) { - unowned var inst = node.node.instance; - var diff = align_to - inst.bounding_box.center_x; - if (diff != 0) { - operations.add (new AlignOp (node.node, diff, 0)); - } - } - } - - // Maybe move this and combine with TransformMode's - private static void translate_node (Lib.Items.ModelNode node, double dx, double dy, Lib.Items.Model model) { - unowned var inst = node.instance; - inst.components.center = inst.components.center.translated (dx, dy); - - if (node.children != null && node.children.length > 0) { - foreach (unowned var child in node.children.data) { - translate_node (child, dx, dy, model); - } - } - - model.alert_node_changed (node, Lib.Components.Component.Type.COMPILED_GEOMETRY); - } -} diff --git a/src/Utils/ModelUtil.vala b/src/Utils/ModelUtil.vala deleted file mode 100644 index db83ed2fe..000000000 --- a/src/Utils/ModelUtil.vala +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (http://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Authored by: Alessandro "alecaddd" Castellani - */ - -/* - * Utility to handle some model operations - */ - public class Akira.Utils.ModelUtil : Object { - public delegate void OnSubtreeCloned (int id); - - public enum State { - COPY, - PASTE, - PASTE_IN_PLACE, - DUPLICATE - } - - /* - * Clones an instance with `source_id` from a source model, into a target - * model into a specific group with id `tagret_group_id`. - * Cloning is recursive, so all dependencies are copied over. - * Return 0 on success. - */ - public static int clone_from_model ( - Lib.Items.Model source_model, - int source_id, - Lib.Items.Model target_model, - int target_group_id, - OnSubtreeCloned? on_subtree_cloned = null, - State state = State.COPY - ) { - var target_node = target_model.node_from_id (target_group_id); - if (target_node == null || !target_node.instance.is_group) { - return -1; - } - - var source_node = source_model.node_from_id (source_id); - if (source_node == null) { - return -1; - } - - if (state == State.PASTE) { - // Regular paste action. Reset the position to -1 to let the cloned - // node be appended above all available child nodes. - source_node.pos_in_parent = -1; - } else if (state == State.PASTE_IN_PLACE || state == State.DUPLICATE) { - // Paste in place action. Increase the position by one to let the - // cloned node be appended above the source node. - source_node.pos_in_parent += 1; - } - var new_id = recursive_clone (source_node, target_node, target_model); - if (new_id >= Lib.Items.Model.GROUP_START_ID && on_subtree_cloned != null) { - on_subtree_cloned (new_id); - } - - return 0; - } - - private static int recursive_clone ( - Lib.Items.ModelNode source_node, - Lib.Items.ModelNode target_node, - Lib.Items.Model target_model - ) { - int new_id; - if (source_node.pos_in_parent != -1) { - // Splice the node into position if we have one set. - new_id = target_model.splice_new_item ( - target_node.id, - source_node.pos_in_parent, - source_node.instance.clone (false) - ); - } else { - new_id = target_model.append_new_item ( - target_node.id, - source_node.instance.clone (false) - ); - } - - if (source_node.instance.is_group) { - foreach (var child in source_node.children.data) { - recursive_clone (child, target_model.node_from_id (new_id), target_model); - } - } - - return new_id; - } - - public static Lib.Items.ModelNode recursive_get_parent_target (Lib.Items.ModelNode target) { - if ( - target.parent != null && - target.parent.id != Lib.Items.Model.ORIGIN_ID && - target.parent.instance.is_group && - !target.parent.instance.is_artboard - ) { - return recursive_get_parent_target (target.parent); - } - - return target; - } - - public static Lib.Items.ModelNode? recursive_get_target_parent_artboard (Lib.Items.ModelNode target) { - if ( - target.parent != null && - target.parent.id != Lib.Items.Model.ORIGIN_ID && - !target.parent.instance.is_artboard - ) { - return recursive_get_target_parent_artboard (target.parent); - } - - if (target.parent.instance.is_artboard) { - return target.parent; - } - - return null; - } - } diff --git a/src/Utils/Nobs.vala b/src/Utils/Nobs.vala deleted file mode 100644 index 9a2b4597b..000000000 --- a/src/Utils/Nobs.vala +++ /dev/null @@ -1,422 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (http://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.Utils.Nobs : Object { - public const double ROTATION_LINE_HEIGHT = 40.0; - - /* - Grabber Pos: - 8 - | - 0 1 2 - 7 3 - 6 5 4 - - // -1 if no nob is grabbed. - */ - public enum Nob { - NONE=-1, - TOP_LEFT, - TOP_CENTER, - TOP_RIGHT, - RIGHT_CENTER, - BOTTOM_RIGHT, - BOTTOM_CENTER, - BOTTOM_LEFT, - LEFT_CENTER, - ROTATE, - ALL - } - - public class NobData { - public const double NOB_SIZE = 10; - public const double LINE_WIDTH = 1; - - public Nob handle_id; - public double center_x; - public double center_y; - public bool active; - - public NobData (Nob id, double center_x, double center_y, bool active) { - this.handle_id = id; - this.center_x = center_x; - this.center_y = center_y; - this.active = active; - } - - public NobData copy () { - return new NobData (handle_id, center_x, center_y, active); - } - } - - public class NobSet { - public NobData[] data; - - public NobSet () { - data = new NobData[9]; - for (var i = 0; i < 9; i++) { - data[i] = new NobData ((Nob)i, 0, 0, false); - } - } - - public NobSet.clone (NobSet other) { - data = new NobData[9]; - for (var i = 0; i < 9; i++) { - data[i] = other.data[i].copy (); - } - } - - public bool any_active () { - foreach (unowned var nob in data) { - if (nob.active) { - return true; - } - } - - return false; - } - - public Nob hit_test (double x, double y, double scale) { - foreach (unowned var nob in data) { - if (!nob.active) { - continue; - } - - double xd = nob.center_x - x; - double yd = nob.center_y - y; - double dist = GLib.Math.sqrt (xd * xd + yd * yd); - if (dist <= NobData.NOB_SIZE / scale) { - return nob.handle_id; - } - } - - return Nob.NONE; - } - - public Geometry.Rectangle? extents (double scale, bool all) { - double left = double.MAX; - double right = double.MIN; - double top = double.MAX; - double bottom = double.MIN; - - foreach (unowned var nob in data) { - if (all || nob.active) { - left = double.min (left, nob.center_x); - right = double.max (right, nob.center_x); - top = double.min (top, nob.center_y); - bottom = double.max (bottom, nob.center_y); - } - } - - if (left == double.MAX || top == double.MAX) { - return null; - } - - double off = NobData.NOB_SIZE / scale; - return Geometry.Rectangle.with_coordinates (left - off, top - off, right + off, bottom + off); - } - - public void set_active (bool active) { - foreach (unowned var nob in data) { - nob.active = active; - } - } - } - - public static bool is_top_nob (Nob nob) { - return nob == Nob.TOP_LEFT || nob == Nob.TOP_CENTER || nob == Nob.TOP_RIGHT; - } - - public static bool is_bot_nob (Nob nob) { - return nob == Nob.BOTTOM_LEFT || nob == Nob.BOTTOM_CENTER || nob == Nob.BOTTOM_RIGHT; - } - - public static bool is_left_nob (Nob nob) { - return nob == Nob.TOP_LEFT || nob == Nob.LEFT_CENTER || nob == Nob.BOTTOM_LEFT; - } - - public static bool is_right_nob (Nob nob) { - return nob == Nob.TOP_RIGHT || nob == Nob.RIGHT_CENTER || nob == Nob.BOTTOM_RIGHT; - } - - public static bool is_corner_nob (Nob nob) { - return nob == Nob.TOP_RIGHT || nob == Nob.TOP_LEFT || nob == Nob.BOTTOM_RIGHT || nob == Nob.BOTTOM_LEFT; - } - - public static bool is_horizontal_center (Nob nob) { - return (nob == Utils.Nobs.Nob.RIGHT_CENTER || nob == Utils.Nobs.Nob.LEFT_CENTER); - } - - public static bool is_vertical_center (Nob nob) { - return (nob == Utils.Nobs.Nob.TOP_CENTER || nob == Utils.Nobs.Nob.BOTTOM_CENTER); - } - - /* - * Return a cursor type based of the type of nob. - */ - public static Gdk.CursorType? cursor_from_nob (Nob nob_id) { - Gdk.CursorType? result = null; - switch (nob_id) { - case Nob.NONE: - result = null; - break; - case Nob.TOP_LEFT: - result = Gdk.CursorType.TOP_LEFT_CORNER; - break; - case Nob.TOP_CENTER: - result = Gdk.CursorType.TOP_SIDE; - break; - case Nob.TOP_RIGHT: - result = Gdk.CursorType.TOP_RIGHT_CORNER; - break; - case Nob.RIGHT_CENTER: - result = Gdk.CursorType.RIGHT_SIDE; - break; - case Nob.BOTTOM_RIGHT: - result = Gdk.CursorType.BOTTOM_RIGHT_CORNER; - break; - case Nob.BOTTOM_CENTER: - result = Gdk.CursorType.BOTTOM_SIDE; - break; - case Nob.BOTTOM_LEFT: - result = Gdk.CursorType.BOTTOM_LEFT_CORNER; - break; - case Nob.LEFT_CENTER: - result = Gdk.CursorType.LEFT_SIDE; - break; - case Nob.ROTATE: - result = Gdk.CursorType.EXCHANGE; - break; - default: - break; - } - - return result; - } - - public static Nob opposite_nob (Nob nob_id) { - switch (nob_id) { - case Nob.TOP_LEFT: - return Nob.BOTTOM_RIGHT; - case Nob.TOP_CENTER: - return Nob.BOTTOM_CENTER; - case Nob.TOP_RIGHT: - return Nob.BOTTOM_LEFT; - case Nob.RIGHT_CENTER: - return Nob.LEFT_CENTER; - case Nob.BOTTOM_RIGHT: - return Nob.TOP_LEFT; - case Nob.BOTTOM_CENTER: - return Nob.TOP_CENTER; - case Nob.BOTTOM_LEFT: - return Nob.TOP_RIGHT; - case Nob.LEFT_CENTER: - return Nob.RIGHT_CENTER; - default: - break; - } - - return Nob.NONE; - } - - /* - * - */ - public static void rectify_nob ( - double top, - double left, - double bottom, - double right, - double ev_x, - double ev_y, - ref Nob nob - ) { - switch (nob) { - case Nob.TOP_LEFT: - rectify_top_nob (bottom, ev_y, ref nob); - rectify_left_nob (right, ev_x, ref nob); - return; - case Nob.TOP_CENTER: - rectify_top_nob (bottom, ev_y, ref nob); - return; - case Nob.TOP_RIGHT: - rectify_top_nob (bottom, ev_y, ref nob); - rectify_right_nob (left, ev_x, ref nob); - return; - case Nob.RIGHT_CENTER: - rectify_right_nob (left, ev_x, ref nob); - return; - case Nob.BOTTOM_RIGHT: - rectify_bottom_nob (top, ev_y, ref nob); - rectify_right_nob (left, ev_x, ref nob); - return; - case Nob.BOTTOM_CENTER: - rectify_bottom_nob (top, ev_y, ref nob); - return; - case Nob.BOTTOM_LEFT: - rectify_bottom_nob (top, ev_y, ref nob); - rectify_left_nob (right, ev_x, ref nob); - return; - case Nob.LEFT_CENTER: - rectify_left_nob (right, ev_x, ref nob); - return; - default: - break; - } - } - public static void rectify_left_nob (double right, double ev_x, ref Nob nob) { - if (ev_x <= right) { - return; - } - - if (nob == Nob.LEFT_CENTER) { - nob = Nob.RIGHT_CENTER; - } - else if (nob == Nob.TOP_LEFT) { - nob = Nob.TOP_RIGHT; - } - else if (nob == Nob.BOTTOM_LEFT) { - nob = Nob.BOTTOM_RIGHT; - } - } - - public static void rectify_right_nob (double left, double ev_x, ref Nob nob) { - if (ev_x >= left) { - return; - } - - if (nob == Nob.RIGHT_CENTER) { - nob = Nob.LEFT_CENTER; - } - else if (nob == Nob.TOP_RIGHT) { - nob = Nob.TOP_LEFT; - } - else if (nob == Nob.BOTTOM_RIGHT) { - nob = Nob.BOTTOM_LEFT; - } - } - - public static void rectify_top_nob (double bottom, double ev_y, ref Nob nob) { - if (ev_y <= bottom) { - return; - } - - if (nob == Nob.TOP_CENTER) { - nob = Nob.BOTTOM_CENTER; - } - else if (nob == Nob.TOP_RIGHT) { - nob = Nob.BOTTOM_RIGHT; - } - else if (nob == Nob.TOP_LEFT) { - nob = Nob.BOTTOM_LEFT; - } - } - - public static void rectify_bottom_nob (double top, double ev_y, ref Nob nob) { - if (ev_y >= top) { - return; - } - - if (nob == Nob.BOTTOM_CENTER) { - nob = Nob.TOP_CENTER; - } - else if (nob == Nob.BOTTOM_RIGHT) { - nob = Nob.TOP_RIGHT; - } - else if (nob == Nob.BOTTOM_LEFT) { - nob = Nob.TOP_LEFT; - } - } - - public static void nob_xy_from_coordinates ( - Utils.Nobs.Nob nob, - Geometry.Quad rect, - double scale, - ref double x, - ref double y - ) { - - x = 0.0; - y = 0.0; - - switch (nob) { - case Utils.Nobs.Nob.TOP_LEFT: - x = rect.tl_x; - y = rect.tl_y; - break; - case Utils.Nobs.Nob.TOP_CENTER: - x = (rect.tl_x + rect.tr_x) / 2.0; - y = (rect.tl_y + rect.tr_y) / 2.0; - break; - case Utils.Nobs.Nob.TOP_RIGHT: - x = rect.tr_x; - y = rect.tr_y; - break; - case Utils.Nobs.Nob.RIGHT_CENTER: - x = (rect.tr_x + rect.br_x) / 2.0; - y = (rect.tr_y + rect.br_y) / 2.0; - break; - case Utils.Nobs.Nob.BOTTOM_RIGHT: - x = rect.br_x; - y = rect.br_y; - break; - case Utils.Nobs.Nob.BOTTOM_CENTER: - x = (rect.br_x + rect.bl_x) / 2.0; - y = (rect.br_y + rect.bl_y) / 2.0; - break; - case Utils.Nobs.Nob.BOTTOM_LEFT: - x = rect.bl_x; - y = rect.bl_y; - break; - case Utils.Nobs.Nob.LEFT_CENTER: - x = (rect.tl_x + rect.bl_x) / 2.0; - y = (rect.tl_y + rect.bl_y) / 2.0; - break; - case Utils.Nobs.Nob.ROTATE: - var dx = rect.tl_x - rect.bl_x; - var dy = rect.tl_y - rect.bl_y; - Utils.GeometryMath.normalize (ref dx, ref dy); - - - x = (rect.tl_x + rect.tr_x) / 2.0 + dx * ROTATION_LINE_HEIGHT / scale; - y = (rect.tl_y + rect.tr_y) / 2.0 + dy * ROTATION_LINE_HEIGHT / scale; - break; - default: - break; - } - } - - /* - * Turns x or y values to zero if they are not affected by the nob. - * Assumes local x y coordinates. - */ - public static void rectify_nob_xy (Nob nob, ref double x, ref double y) { - if (is_horizontal_center (nob)) { - y = 0.0; - return; - } - - if (is_vertical_center (nob)) { - x = 0.0; - return; - } - } -} diff --git a/src/Utils/SVGUtil.vala b/src/Utils/SVGUtil.vala deleted file mode 100644 index ba78b626c..000000000 --- a/src/Utils/SVGUtil.vala +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (http://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/** - * Utility to manage small svg conversions. - */ - public class Akira.Utils.SVGUtil : Object { - public static string rect_to_svg_path ( - double shift_x, - double shift_y, - double top, - double left, - double bottom, - double right - ) { - var dx = right - left; - var dy = bottom - top; - - //var str = "m %f, %f h %f v %f h %f z".printf (shift_x + top, shift_y + left, dx, dy, -dx); - return "m %f, %f h %f v %f h %f z".printf (shift_x + top, shift_y + left, dx, dy, -dx); - } - } diff --git a/src/Utils/Snapping.vala b/src/Utils/Snapping.vala deleted file mode 100644 index 469a7e582..000000000 --- a/src/Utils/Snapping.vala +++ /dev/null @@ -1,334 +0,0 @@ -/** - * Copyright (c) 2021 Alecaddd (http://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/** - * Utility providing snap functionality between objects. - * For Lib - */ -public class Akira.Utils.Snapping : Object { - /** - * Metadata used in the cosmetic aspects of snap lines and dots. - */ - public class SnapMeta { - public int[] normals; - public int polarity; - } - - /** - * Grid snaps found for a given selection and set of candidates. - */ - public struct SnapGrid { - public bool is_empty () { - return (v_snaps.size == 0 && h_snaps.size == 0); - } - - public Gee.TreeMap v_snaps; - public Gee.TreeMap h_snaps; - } - - /** - * Type of match that was found for a snap. - */ - public enum MatchType { - NONE = -1, //< No match was found. - FUZZY, //< A match was found, but requires an offset. - EXACT, //< An exact match was found, no offset is necessary. - } - - /** - * Information used to define a match for a given selection. - * An instance of this class corresponds to a single direction (vertical or horizontal). - */ - public struct SnapMatch { - /** - * Returns true if a match was found - */ - public bool snap_found () { - return type != MatchType.NONE; - } - - /** - * Returns the offset necessary to bring the reference position to the selected items. - */ - public int snap_offset () { - if (snap_found ()) { - return snap_position - reference_position; - } - return 0; - } - - public MatchType type; - public int snap_position; //< Position of matched snap. - public int reference_position; //< Position relative to the selection used as a reference. - public Gee.Set exact_matches; //< map of exact matches. - } - - /** - * Couple of MatchData used for convenience. - */ - public struct SnapMatchData { - public bool snap_found () { - return h_data.snap_found () || v_data.snap_found (); - } - - SnapMatch h_data; - SnapMatch v_data; - } - - /* - * Returns a sensitivity adjusted to the given canvas scale. - */ - public static int adjusted_sensitivity (double canvas_scale) { - // Limit the sensitivity. This seems like a sensible default for now. - if (canvas_scale > settings.snaps_sensitivity) { - return 1; - } - - // Beyond 0.002, the snapping breaks down. Arguably, it does before. - return (int) (settings.snaps_sensitivity / double.max (0.002, canvas_scale)); - } - - /* - * Generates the best snap grid from selection. - */ - public static SnapGrid generate_best_snap_grid ( - Lib.ViewCanvas canvas, - Lib.Items.NodeSelection selection, - Geometry.Rectangle selection_area, - int sensitivity - ) { - selection_area.left -= sensitivity; - selection_area.right += sensitivity; - selection_area.top -= sensitivity; - selection_area.bottom += sensitivity; - - int group_id; - selection.spans_one_group (out group_id); - group_id = int.max (group_id, Lib.Items.Model.ORIGIN_ID); - - return snap_grid_from_canvas (canvas, group_id, selection, selection_area, sensitivity); - } - - /* - * Generates a snap grid from a canvas. - * If group_node is passed, then it will be used to generate snaps only within that group. - */ - public static SnapGrid snap_grid_from_canvas ( - Lib.ViewCanvas canvas, - int group_id, - Lib.Items.NodeSelection selection, - Geometry.Rectangle selection_area, - int sensitivity - ) { - var grid = SnapGrid (); - grid.v_snaps = new Gee.TreeMap (); - grid.h_snaps = new Gee.TreeMap (); - - double vis_x1 = 0; - double vis_x2 = 0; - double vis_y1 = 0; - double vis_y2 = 0; - canvas.visible_bounds (ref vis_y1, ref vis_x1, ref vis_y2, ref vis_x2); - - var candidate_list = canvas.items_manager.children_in_group (group_id); - int v_added = 0; - int h_added = 0; - - foreach (unowned var node in candidate_list.data) { - if (selection.has_id (node.id, false)) { - continue; - } - - unowned var inst = node.instance; - if ((inst.bounding_box.right < vis_x1 || inst.bounding_box.left > vis_x2) || - (inst.bounding_box.bottom < vis_y1 || inst.bounding_box.top > vis_y2)) { - // the candidate is not in view - continue; - } - - if (!(inst.bounding_box.right < selection_area.left || inst.bounding_box.left > selection_area.right)) { - populate_horizontal_snaps (inst.bounding_box, ref grid.h_snaps); - h_added++; - } - - if (!(inst.bounding_box.bottom < selection_area.top || inst.bounding_box.top > selection_area.bottom)) { - populate_vertical_snaps (inst.bounding_box, ref grid.v_snaps); - v_added++; - } - } - - return grid; - } - - /* - * Calculate snaps inside a grid that match the selection input. - */ - public static SnapMatchData generate_snap_matches ( - SnapGrid grid, - Lib.Items.NodeSelection selection, - Geometry.Rectangle selection_area, - int sensitivity - ) { - var matches = Utils.Snapping.default_match_data (); - - var v_sel_snaps = new Gee.TreeMap (); - var h_sel_snaps = new Gee.TreeMap (); - - populate_vertical_snaps (selection_area, ref v_sel_snaps); - populate_horizontal_snaps (selection_area, ref h_sel_snaps); - - populate_snap_matches_from_list (v_sel_snaps, grid.v_snaps, ref matches.v_data, sensitivity); - populate_snap_matches_from_list (h_sel_snaps, grid.h_snaps, ref matches.h_data, sensitivity); - - return matches; - } - - - /* - * Populates the horizontal snaps of an item. - */ - private static void populate_horizontal_snaps ( - Geometry.Rectangle rect, - ref Gee.TreeMap s_map - ) { - int x_1 = (int) Math.round (rect.left); - int x_2 = (int) Math.round (rect.right); - int y_1 = (int) Math.round (rect.top); - int y_2 = (int) Math.round (rect.bottom); - int cx = snap_ceil (rect.center_x); - int cy = snap_ceil (rect.center_y); - - add_to_map (x_1, y_1, y_2, cy, -1, ref s_map); - add_to_map (x_2, y_1, y_2, cy, 1, ref s_map); - add_to_map (cx, cy, cy, cy, 0, ref s_map); - } - - /* - * Populates the vertical snaps of an item. - */ - private static void populate_vertical_snaps ( - Geometry.Rectangle rect, - ref Gee.TreeMap s_map - ) { - int x_1 = (int) Math.round (rect.left); - int x_2 = (int) Math.round (rect.right); - int y_1 = (int) Math.round (rect.top); - int y_2 = (int) Math.round (rect.bottom); - int cx = snap_ceil (rect.center_x); - int cy = snap_ceil (rect.center_y); - - add_to_map (y_1, x_1, x_2, cx, -1, ref s_map); - add_to_map (y_2, x_1, x_2, cx, 1, ref s_map); - add_to_map (cy, cx, cx, cx, 0, ref s_map); - } - - /* - * Simple method to add information to a snap list. - */ - private static void add_to_map ( - int pos, - int n1, - int n2, - int n3, - int polarity, - ref Gee.TreeMap s_map - ) { - if (s_map.has_key (pos)) { - var k = s_map[pos]; - Utils.Array.append_to_iarray (ref k.normals, n1); - Utils.Array.append_to_iarray (ref k.normals, n2); - Utils.Array.append_to_iarray (ref k.normals, n3); - k.polarity += polarity; - return; - } - - var k = new SnapMeta (); - k.normals = new int[0]; - Utils.Array.append_to_iarray (ref k.normals, n1); - Utils.Array.append_to_iarray (ref k.normals, n2); - Utils.Array.append_to_iarray (ref k.normals, n3); - s_map.set (pos, k); - } - - - /* - * Matches in one direction (vertical / horizontal). - */ - private static void populate_snap_matches_from_list ( - Gee.TreeMap target_snap_list, - Gee.TreeMap grid_snap_list, - ref SnapMatch matches, - int sensitivity - ) { - int diff = 0; - var tmpdiff = sensitivity; - foreach (var target_snap in target_snap_list.keys) { - foreach (var cand in grid_snap_list.keys) { - diff = (int) (cand - target_snap); - diff = diff.abs (); - - if (diff < sensitivity) { - if ((int) (cand - target_snap) == 0) { - matches.type = MatchType.EXACT; - matches.snap_position = cand; - matches.reference_position = target_snap; - matches.exact_matches.add (cand); - tmpdiff = 0; - } else if (diff < tmpdiff) { - matches.type = MatchType.FUZZY; - matches.snap_position = cand; - matches.reference_position = target_snap; - tmpdiff = diff; - } - } - } - } - } - - /* - * finds the ceiling, making sure small epsilons don't cause instability - */ - private static int snap_ceil (double val) { - int res = (int) val; - if ((val - res) > 0.001) { - res += 1; - } - return res; - } - - /** - * Generate a default match data. - */ - public static SnapMatchData default_match_data () { - var matches = SnapMatchData (); - matches.v_data.type = MatchType.NONE; - matches.v_data.snap_position = 0; - matches.v_data.reference_position = 0; - matches.v_data.exact_matches = new Gee.TreeSet (); - - matches.h_data.type = MatchType.NONE; - matches.h_data.snap_position = 0; - matches.h_data.reference_position = 0; - matches.h_data.exact_matches = new Gee.TreeSet (); - - return matches; - } -} diff --git a/src/ViewLayers/BaseCanvas.vala b/src/ViewLayers/BaseCanvas.vala deleted file mode 100644 index 04a230d2c..000000000 --- a/src/ViewLayers/BaseCanvas.vala +++ /dev/null @@ -1,658 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * - * Note: This is transcribed to goocanvas. Not sure how copyright - * works in that case. But all credit to the original authors of - * goocanvas.c - */ - -/* - * Group optimized for Akira. - */ -public class Akira.ViewLayers.BaseCanvas : Gtk.Widget , Gtk.Scrollable { - private const double DEFAULT_WIDTH = 1000.0; - private const double DEFAULT_HEIGHT = 1000.0; - - private int window_x = 0; - private int window_y = 0; - // private bool automatic_bounds = false; - // private bool bounds_from_origin = true; - private bool clear_background = true; - - private int freeze_count = 0; - // private bool need_update = true; - // private bool need_entire_subtree_update_ = true; - private bool before_initial_draw = true; - private bool needs_reconfigure = false; - private Geometry.Rectangle bounds = Geometry.Rectangle.with_coordinates (0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT); - - public bool pause_redraw = false; - - // The main window that gets scrolled around - private Gdk.Window canvas_window; - - private unowned Lib.Items.Model? model_to_render = null; - - private double p_scale { get; set; default = 1.0; } - private double p_resolution_x { get; set; default = 96.0; } - private double p_resolution_y { get; set; default = 96.0; } - private Gtk.Adjustment p_hadjustment { get; set; default = new Gtk.Adjustment (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); } - private Gtk.Adjustment p_vadjustment { get; set; default = new Gtk.Adjustment (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); } - private Gtk.ScrollablePolicy p_hscroll_policy { get; set; } - private Gtk.ScrollablePolicy p_vscroll_policy { get; set; } - - private Gee.TreeMap overlays; - - public Drawables.Drawable.DrawType p_draw_type { get; set; default = Drawables.Drawable.DrawType.NORMAL; } - - public double scale { - get { return p_scale; } - set { this.internal_set_scale (value); } - } - - public double x1 { - get { return bounds.left; } - set { - bounds.left = value; - needs_reconfigure = true; - reconfigure (false); - queue_draw (); - } - } - public double y1 { - get { return bounds.top; } - set { - bounds.top = value; - needs_reconfigure = true; - reconfigure (false); - queue_draw (); - } - } - public double x2 { - get { return bounds.right; } - set { - bounds.right = value; - needs_reconfigure = true; - reconfigure (false); - queue_draw (); - } - } - public double y2 { - get { return bounds.bottom; } - set { - bounds.bottom = value; - needs_reconfigure = true; - reconfigure (false); - queue_draw (); - } - } - - public double resolution_x { - get { return p_resolution_x; } - set { p_resolution_x = value; needs_reconfigure = true; } - } - public double resolution_y { - get { return p_resolution_y; } - set { p_resolution_y = value; needs_reconfigure = true; } - } - - public Gtk.Adjustment hadjustment { - get { return p_hadjustment; } - set construct { internal_set_hadjustment (value); } - } - public Gtk.Adjustment vadjustment { - get { return p_vadjustment; } - set construct { internal_set_vadjustment (value); } - } - - public Gtk.ScrollablePolicy hscroll_policy { - get { return p_hscroll_policy; } - set { p_hscroll_policy = value; queue_resize (); } - } - - public Gtk.ScrollablePolicy vscroll_policy { - get { return p_vscroll_policy; } - set { p_vscroll_policy = value; queue_resize (); } - } - - BaseCanvas () { - hadjustment = new Gtk.Adjustment (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); - vadjustment = new Gtk.Adjustment (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); - } - - public void set_model_to_render (Lib.Items.Model model) { - model_to_render = model; - request_redraw (bounds); - queue_draw (); - } - - public void add_viewlayer_overlay (string id, ViewLayers.ViewLayer layer) { - if (overlays == null) { - overlays = new Gee.TreeMap (); - } - overlays[id] = layer; - if (layer.is_visible && !layer.is_masked) { - layer.update (); - } - } - - public ViewLayer.Mask? mask_viewlayer_overlay (string id) { - if (overlays == null) { - return null; - } - - return overlays.has_key (id) ? new ViewLayer.Mask (overlays[id]) : null; - } - - public bool get_border (out Gtk.Border border) { - border = Gtk.Border (); - return true; - } - - public override void realize () { - set_realized (true); - Gtk.Allocation allocation; - get_allocation (out allocation); - - var attributes = Gdk.WindowAttr (); - attributes.window_type = Gdk.WindowType.CHILD; - attributes.x = allocation.x; - attributes.y = allocation.y; - attributes.width = allocation.width; - attributes.height = allocation.height; - attributes.wclass = Gdk.WindowWindowClass.INPUT_OUTPUT; - attributes.visual = get_visual (); - attributes.event_mask = Gdk.EventMask.VISIBILITY_NOTIFY_MASK; - int attributes_mask = Gdk.WindowAttributesType.X | Gdk.WindowAttributesType.Y | Gdk.WindowAttributesType.VISUAL; - - var window = new Gdk.Window (get_parent_window (), attributes, (Gdk.WindowAttributesType)attributes_mask); - set_window (window); - window.set_user_data (this); - - int width_pixels = (int)((bounds.right - bounds.left) * scale) + 1; - int height_pixels = (int)((bounds.bottom - bounds.top) * scale) + 1; - attributes.x = (hadjustment == null) ? 0 : (int)hadjustment.get_value (); - attributes.y = (vadjustment == null) ? 0 : (int)vadjustment.get_value (); - attributes.width = int.max (width_pixels, allocation.width); - attributes.height = int.max (height_pixels, allocation.height); - attributes.event_mask = - Gdk.EventMask.EXPOSURE_MASK - | Gdk.EventMask.SCROLL_MASK - | Gdk.EventMask.BUTTON_PRESS_MASK - | Gdk.EventMask.BUTTON_RELEASE_MASK - | Gdk.EventMask.POINTER_MOTION_MASK - | Gdk.EventMask.POINTER_MOTION_HINT_MASK - | Gdk.EventMask.KEY_PRESS_MASK - | Gdk.EventMask.KEY_RELEASE_MASK - | Gdk.EventMask.ENTER_NOTIFY_MASK - | Gdk.EventMask.LEAVE_NOTIFY_MASK - | Gdk.EventMask.FOCUS_CHANGE_MASK - | get_events (); - - window_x = attributes.x; - window_y = attributes.y; - - canvas_window = new Gdk.Window (window, attributes, (Gdk.WindowAttributesType)attributes_mask); - canvas_window.set_user_data (this); - } - - public override void map () { - base.map (); - canvas_window.show (); - get_window ().show (); - } - - public override void unrealize () { - canvas_window.set_user_data (null); - base.unrealize (); - } - - public override void get_preferred_height (out int minimum_height, out int natural_height) { - minimum_height = 0; - natural_height = 0; - } - - public override void get_preferred_width (out int minimum_width, out int natural_width) { - minimum_width = 0; - natural_width = 0; - } - - public override void size_allocate (Gtk.Allocation allocation) { - set_allocation (allocation); - - if (get_realized ()) { - get_window ().move_resize (allocation.x, allocation.y, allocation.width, allocation.height); - //tmp_canvas.move_resize (allocation.x, allocation.y, allocation.width, allocation.height); - } - - reconfigure (true); - } - - public override bool scroll_event (Gdk.EventScroll event) { - Gtk.Adjustment adj; - if (event.direction == Gdk.ScrollDirection.UP || event.direction == Gdk.ScrollDirection.DOWN) { - adj = vadjustment; - } else { - adj = hadjustment; - } - - var delta = GLib.Math.pow (adj.get_page_size (), 2.0 / 3.0); - - if (event.direction == Gdk.ScrollDirection.UP || event.direction == Gdk.ScrollDirection.LEFT) { - delta = -delta; - } - - var maxv = adj.get_upper () - adj.get_page_size (); - var new_value = Utils.GeometryMath.clamp (adj.get_value () + delta, adj.get_lower (), maxv); - - adj.set_value (new_value); - return true; - } - - public void convert_to_pixels (ref double x, ref double y) { - x = (x - bounds.left) * scale; - y = (y - bounds.top) * scale; - } - - public void convert_from_pixels (ref double x, ref double y) { - x = x / scale + bounds.left; - y = y / scale + bounds.top; - } - - - public void convert_from_window_pixels (ref double x, ref double y) { - x -= window_x; - y -= window_y; - convert_from_pixels (ref x, ref y); - } - - public void setup_cairo_context (Cairo.Context* context) { - context->set_antialias (Cairo.Antialias.GRAY); - context->set_line_width (0.0); - } - - public Cairo.Context create_cairo_context () { - var surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, 1, 1); - var context = new Cairo.Context (surface); - setup_cairo_context (context); - return context; - } - - public void set_bounds (Geometry.Rectangle new_bounds) { - bounds = new_bounds; - reconfigure (false); - queue_draw (); - } - - /* - * Get viewport bounds in user coordinates. - */ - public Geometry.Rectangle viewport_bounds_in_user () { - var r = Geometry.Rectangle.empty (); - - convert_from_window_pixels (ref r.left, ref r.top); - - Gtk.Allocation allocation; - get_allocation (out allocation); - - double w = allocation.width; - double h = allocation.height; - - - convert_from_pixels (ref w, ref h); - - r.right = r.left + w; - r.bottom = r.top + h; - return r; - } - - public Geometry.Rectangle get_bounds () { - return bounds; - } - - public void internal_set_scale (double new_scale) { - var x = hadjustment.get_value () + hadjustment.get_page_size () / 2; - var y = vadjustment.get_value () + vadjustment.get_page_size () / 2; - - freeze_count++; - - p_scale = new_scale; - - reconfigure (false); - - x -= hadjustment.get_page_size () / scale / 2; - y -= vadjustment.get_page_size () / scale / 2; - - scroll_to (x, y); - - freeze_count--; - adjustment_value_changed (); - queue_draw (); - } - - public void scroll_to (double top, double left) { - double x = left; - double y = top; - - var xmax = hadjustment.get_upper () - hadjustment.get_page_size (); - var ymax = vadjustment.get_upper () - vadjustment.get_page_size (); - x = Utils.GeometryMath.clamp (x, hadjustment.get_lower (), xmax); - y = Utils.GeometryMath.clamp (y, vadjustment.get_lower (), ymax); - - freeze_count++; - hadjustment.set_value (x); - vadjustment.set_value (y); - freeze_count--; - - adjustment_value_changed (); - } - - public void reconfigure (bool redraw_if_needed) { - /* Make sure the bounds are sane. */ - if (bounds.right < bounds.left) { - bounds.right = bounds.left; - } - if (bounds.bottom < bounds.top) { - bounds.bottom = bounds.top; - } - - /* This is the natural size of the canvas window in pixels, rounded up to - the next pixel. */ - int width_pixels = (int)((bounds.right - bounds.left) * scale) + 1; - int height_pixels = (int)((bounds.bottom - bounds.top) * scale) + 1; - - Gtk.Allocation allocation; - get_allocation (out allocation); - var window_width = int.max (width_pixels, allocation.width); - var window_height = int.max (height_pixels, allocation.height); - - freeze_count++; - - int wx = 0; - int wy = 0; - - if (hadjustment != null) { - configure_hadjustment (window_width); - wx = (int)hadjustment.get_value (); - } - - if (vadjustment != null) { - configure_vadjustment (window_height); - wy = (int)vadjustment.get_value (); - } - - freeze_count--; - - if (get_realized ()) { - canvas_window.move_resize (wx, wy, window_width, window_height); - } - } - - public void internal_set_hadjustment (Gtk.Adjustment? new_hadj) { - if (new_hadj != null && hadjustment == new_hadj) { - return; - } - - if (hadjustment != null) { - hadjustment.value_changed.disconnect (adjustment_value_changed); - } - - var newadj = new_hadj; - if (newadj == null) { - newadj = new Gtk.Adjustment (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); - } - - newadj.value_changed.connect (adjustment_value_changed); - reconfigure (true); - p_hadjustment = newadj; - } - - public void internal_set_vadjustment (Gtk.Adjustment? new_vadj) { - - if (new_vadj != null && p_vadjustment == new_vadj) { - return; - } - - if (vadjustment != null) { - vadjustment.value_changed.disconnect (adjustment_value_changed); - } - - var newadj = new_vadj; - if (newadj == null) { - newadj = new Gtk.Adjustment (0.0, 0.0, 0.0, 0.0, 0.0, 0.0); - } - - newadj.value_changed.connect (adjustment_value_changed); - reconfigure (true); - p_vadjustment = newadj; - } - - private void configure_hadjustment (int window_width) { - var value = hadjustment.get_value (); - var lower = hadjustment.get_lower (); - var upper = hadjustment.get_upper (); - var step_inc = hadjustment.get_step_increment (); - var page_inc = hadjustment.get_page_increment (); - var page_size = hadjustment.get_page_size (); - - bool configure = false; - - if (upper != window_width) { - upper = window_width; - configure = true; - } - - Gtk.Allocation allocation; - get_allocation (out allocation); - - if (page_size != allocation.width) { - page_size = allocation.width; - page_inc = page_size * 0.9; - step_inc = page_size * 0.1; - configure = true; - } - - var max_value = double.max (0.0, upper - page_size); - if (value > max_value) { - value = max_value; - configure = true; - } - - if (configure) { - hadjustment.configure (value, lower, upper, step_inc, page_inc, page_size); - } - } - - private void configure_vadjustment (int window_height) { - bool configure = false; - var value = vadjustment.get_value (); - var lower = vadjustment.get_lower (); - var upper = vadjustment.get_upper (); - var step_inc = vadjustment.get_step_increment (); - var page_inc = vadjustment.get_page_increment (); - var page_size = vadjustment.get_page_size (); - - if (upper != window_height) { - upper = window_height; - configure = true; - } - - Gtk.Allocation allocation; - get_allocation (out allocation); - - if (page_size != allocation.height) { - page_size = allocation.height; - page_inc = page_size * 0.9; - step_inc = page_size * 0.1; - configure = true; - } - - var max_value = double.max (0.0, upper - page_size); - if (value > max_value) { - value = max_value; - configure = true; - } - - if (configure) { - vadjustment.configure (value, lower, upper, step_inc, page_inc, page_size); - } - } - - public void adjustment_value_changed () { - if (freeze_count == 0 && get_realized ()) { - int new_window_x = - (int)hadjustment.get_value (); - int new_window_y = - (int)vadjustment.get_value (); - - window_x = new_window_x; - window_y = new_window_y; - - canvas_window.move (new_window_x, new_window_y); - } - } - - /* - * Request a redraw of bounds `b` in the canvas coordinate space. - */ - public void request_redraw (Geometry.Rectangle b) { - if (before_initial_draw) { - return; - } - - if (!is_drawable () || b.left == b.right) { - return; - } - - var rect = Gdk.Rectangle (); - - // Extra one is for possible antialiasing requirements - rect.x = (int) ((b.left - bounds.left) * scale - 1.0); - rect.y = (int) ((b.top - bounds.top) * scale - 1.0); - - // Offset by one for same reasons. Keeping Goocanvas tradition and an extra 1 for luck. - rect.width = (int) ((b.right - bounds.left) * scale - rect.x + 2 + 1); - rect.height = (int) ((b.bottom - bounds.top) * scale - rect.y + 2 + 1); - - canvas_window.invalidate_rect (rect, false); - } - - public override bool draw (Cairo.Context context) { - if (!Gtk.cairo_should_draw_window (context, canvas_window)) { - return false; - } - - var clip_bounds = Geometry.Rectangle (); - context.clip_extents (out clip_bounds.left, out clip_bounds.top, out clip_bounds.right, out clip_bounds.bottom); - - context.save (); - - setup_cairo_context (context); - - if (clear_background) { - Gtk.Allocation allocation; - get_allocation (out allocation); - unowned var style_context = get_style_context (); - style_context.render_background (context, 0, 0, allocation.width, allocation.height); - context.set_source_rgb (0, 0, 0); - } - - var to_paint = clip_bounds; - - convert_from_window_pixels (ref to_paint.left, ref to_paint.top); - convert_from_window_pixels (ref to_paint.right, ref to_paint.bottom); - - context.translate (window_x, window_y); - - context.scale (scale, scale); - - // translate so that the top-left of the canvas becomes 0,0 - context.translate (-bounds.left, -bounds.top); - - // clip to the canvas bounds, if necessary. only necessary if model bounds are - // outside the canvas bounds, and the canvas bounds are less than the area being painted. - // var model_bounds = Geometry.Rectangle (); // TODO - // double top = 0; - // double left = 0; - // double bottom = 0; - // double right = 0; - // if ( - // (model_bounds.left < bounds.left && bounds.left > to_paint.left) - // || (model_bounds.right > bounds.right && bounds.right < to_paint.right) - // || (model_bounds.top < bounds.top && bounds.top > to_paint.top) - // || (model_bounds.bottom > bounds.bottom && bounds.bottom < to_paint.bottom) - // ) { - // left = double.max (bounds.left, to_paint.left); - // top = double.max (bounds.top, to_paint.top); - // bottom = double.min (bounds.bottom, to_paint.bottom); - // right = double.min (bounds.right, to_paint.right); - - // context.new_path (); - // context.move_to (left, top); - // context.line_to (right, top); - // context.line_to (right, bottom); - // context.line_to (left, bottom); - // context.close_path (); - // context.clip (); - // } - - draw_model (context, to_paint); - - if (overlays != null) { - foreach (var overlay in overlays.values) { - overlay.draw_layer (context, to_paint, scale); - } - } - - context.restore (); - - before_initial_draw = false; - return false; - } - - public void draw_model (Cairo.Context context, Geometry.Rectangle bounds) { - if (model_to_render == null) { - return; - } - - var origin = model_to_render.node_from_id (Lib.Items.Model.ORIGIN_ID); - if (origin == null || origin.children == null) { - return; - } - - foreach (unowned var root in origin.children.data) { - draw_model_node (root, context, bounds); - } - } - - public void draw_model_node (Lib.Items.ModelNode node, Cairo.Context context, Geometry.Rectangle bounds) { - if (node.instance.drawable != null) { - node.instance.drawable.paint (context, bounds, scale, p_draw_type); - } - - if (node.children != null) { - foreach (unowned var child in node.children.data) { - draw_model_node (child, context, bounds); - } - } - } - - public void toggle_layer_visibility (string layer_id, bool visibility) { - overlays[layer_id].set_visible (visibility); - } -} diff --git a/src/ViewLayers/ViewLayer.vala b/src/ViewLayers/ViewLayer.vala deleted file mode 100644 index fe97f545b..000000000 --- a/src/ViewLayers/ViewLayer.vala +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.ViewLayers.ViewLayer : Object { - public class Mask { - private ViewLayer view_layer; - - // Scoped mask implementation to hide masks temporarily during a scope (RAII) - public Mask (ViewLayer layer) { - view_layer = layer; - if (view_layer != null) { - view_layer.add_mask (); - } - } - - ~Mask () { - if (view_layer != null) { - view_layer.remove_mask (); - } - } - } - - // Higher numbers are higher on the stack - public const string VSNAPS_LAYER_ID = "99_vsnaps_layer"; - public const string HSNAPS_LAYER_ID = "99_hsnaps_layer"; - public const string GRID_LAYER_ID = "88_grid_layer"; - public const string ANCHOR_LAYER_ID = "78_anchor_layer"; - public const string HOVER_LAYER_ID = "77_hover_layer"; - public const string EXPORT_AREA_LAYER_ID = "76_export_layer"; - public const string MULTI_SELECT_LAYER_ID = "76_multiselect_layer"; - // at a time, only one of nobs and path layer will be shown. - // so they have equal priority - public const string NOBS_LAYER_ID = "66_nobs_layer"; - public const string PATH_LAYER_ID = "66_path_layer"; - - - private bool p_is_visible { get; set; default = false; } - private BaseCanvas? p_canvas { get; set; default = null; } - private int p_mask_counter { get; set; default = 0; } - - public BaseCanvas? canvas { get { return p_canvas; } } - public bool is_visible { get { return p_is_visible; } } - public bool is_masked { get { return p_mask_counter > 0; } } - - public void add_to_canvas (string layer_id, BaseCanvas canvas) { - p_canvas = canvas; - p_canvas.add_viewlayer_overlay (layer_id, this); - } - - public void set_visible (bool visible) { - if (p_is_visible == visible) { - return; - } - - p_is_visible = visible; - - update (); - } - - public void add_mask () { - p_mask_counter++; - if (is_visible && is_masked) { - update (); - } - } - - public void remove_mask () { - p_mask_counter = int.min (p_mask_counter - 1, 0); - - if (is_visible && !is_masked) { - update (); - } - } - - public virtual void draw_layer (Cairo.Context context, Geometry.Rectangle target_bounds, double scale) {} - public virtual void update () {} - -} diff --git a/src/ViewLayers/ViewLayerExportArea.vala b/src/ViewLayers/ViewLayerExportArea.vala deleted file mode 100644 index d23bfc04e..000000000 --- a/src/ViewLayers/ViewLayerExportArea.vala +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Copyright (c) 2023 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.ViewLayers.ViewLayerExportArea : ViewLayer { - private const double UI_LINE_WIDTH = 2.0; - private Gdk.RGBA fill { get; default = Gdk.RGBA () { red = 0.25, green = 0.79, blue = 0.98, alpha = 0.2 }; } - private Gdk.RGBA stroke { - get { - var color = fill; - color.alpha = 1; - return color; - } - } - - private Drawables.Drawable? drawable = null; - private Drawables.Drawable? old_drawable = null; - private Geometry.Rectangle last_drawn_bb = Geometry.Rectangle.empty (); - - private double initial_press_x; - private double initial_press_y; - - public void create_region (Gdk.EventButton event) { - initial_press_x = event.x; - initial_press_y = event.y; - - drawable = new Drawables.DrawableRect (event.x, event.y, 0, 0); - } - - public void update_region (double width, double height) { - // Bail out if we just entered the export mode but no click was registered - // on the canvas, meaning the drawable area hasn't been created yet. - if (drawable == null) { - return; - } - - var center_x = initial_press_x + width / 2; - var center_y = initial_press_y + height / 2; - - drawable.center_x = center_x; - drawable.center_y = center_y; - drawable.width = width; - drawable.height = height; - - old_drawable = drawable; - - drawable.bounds = Geometry.Rectangle.with_coordinates ( - initial_press_x, - initial_press_y, - initial_press_x + width, - initial_press_y + height - ); - - update (); - } - - public void remove_region () { - update (); - drawable = null; - } - - public Geometry.Rectangle? get_region_bounds () { - return drawable.bounds; - } - - public override void draw_layer (Cairo.Context context, Geometry.Rectangle target_bounds, double scale) { - if (canvas == null || drawable == null) { - return; - } - - drawable.fill_rgba = fill; - drawable.line_width = UI_LINE_WIDTH / scale; - drawable.stroke_rgba = stroke; - context.set_dash ({10 / scale, 5 / scale}, 10 / scale); - drawable.paint (context, target_bounds, scale, Drawables.Drawable.DrawType.NORMAL); - - last_drawn_bb = drawable.bounds; - } - - public override void update () { - if (canvas == null) { - return; - } - - if (old_drawable != null) { - canvas.request_redraw (last_drawn_bb); - } - - if (drawable != null) { - canvas.request_redraw (drawable.bounds); - } - } -} diff --git a/src/ViewLayers/ViewLayerGrid.vala b/src/ViewLayers/ViewLayerGrid.vala deleted file mode 100644 index 84f5fe69f..000000000 --- a/src/ViewLayers/ViewLayerGrid.vala +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.ViewLayers.ViewLayerGrid : ViewLayer { - private const double UI_LINE_WIDTH = 1.0; - - private Geometry.Rectangle bounds; - private Gdk.RGBA p_color { get; set; default = Gdk.RGBA () { alpha = 1.0 }; } - private double p_spacing { get; set; default = 1.0; } - - public double spacing { - get { return p_spacing; } - set { inner_set_spacing (value); } - } - - public Gdk.RGBA color { - get { return p_color; } - set { inner_set_color (value); } - } - - - public ViewLayerGrid (double x, double y, double width, double height) { - bounds = Geometry.Rectangle.with_coordinates (x, y, x + width, y + height); - var rgba = Gdk.RGBA (); - rgba.parse (settings.grid_color); - inner_set_color (rgba); - } - - public override void draw_layer (Cairo.Context context, Geometry.Rectangle target_bounds, double scale) { - if (canvas == null || scale < 5) { - return; - } - - context.save (); - - var viewport_bounds = canvas.viewport_bounds_in_user (); - - paint_horizontal_lines (context, target_bounds, viewport_bounds, scale); - paint_vertical_lines (context, target_bounds, viewport_bounds, scale); - - context.restore (); - context.new_path (); - } - - private void paint_horizontal_lines ( - Cairo.Context context, - Geometry.Rectangle target_bounds, - Geometry.Rectangle viewport_bounds, - double scale - ) { - if (spacing <= 0) { - return; - } - - context.save (); - context.set_line_width (UI_LINE_WIDTH / scale); - context.set_line_cap (Cairo.LineCap.BUTT); - context.set_source_rgba (color.red, color.green, color.blue, 0.2); - - var y = viewport_bounds.top * 0.00001; - - if (target_bounds.top - spacing > viewport_bounds.top) { - y += GLib.Math.floor ((target_bounds.top - viewport_bounds.top) / spacing) * spacing; - } - - y += spacing * 0.00001; - - var max_y = double.min (target_bounds.bottom + spacing, viewport_bounds.bottom); - - while (y <= max_y) { - context.move_to (viewport_bounds.left, y); - context.line_to (viewport_bounds.right, y); - context.stroke (); - y += spacing; - } - - context.restore (); - } - - private void paint_vertical_lines ( - Cairo.Context context, - Geometry.Rectangle target_bounds, - Geometry.Rectangle viewport_bounds, - double scale - ) { - if (spacing <= 0) { - return; - } - - context.save (); - context.set_line_width (UI_LINE_WIDTH / scale); - context.set_line_cap (Cairo.LineCap.BUTT); - context.set_source_rgba (color.red, color.green, color.blue, 0.2); - - var x = viewport_bounds.left * 0.00001; - - if (target_bounds.left - spacing > viewport_bounds.left) { - x += GLib.Math.floor ((target_bounds.left - viewport_bounds.left) / spacing) * spacing; - } - - x += spacing * 0.00001; - - var max_x = double.min (target_bounds.right + spacing, viewport_bounds.right); - - while (x <= max_x) { - context.move_to (x, viewport_bounds.top); - context.line_to (x, viewport_bounds.bottom); - context.stroke (); - x += spacing; - } - - context.restore (); - } - - public override void update () { - if (canvas == null) { - return; - } - - canvas.request_redraw (bounds); - } - - private void inner_set_spacing (double new_spacing) { - p_spacing = new_spacing; - update (); - } - - private void inner_set_color (Gdk.RGBA new_color) { - p_color = new_color; - update (); - } - -} diff --git a/src/ViewLayers/ViewLayerHover.vala b/src/ViewLayers/ViewLayerHover.vala deleted file mode 100644 index 212a50f21..000000000 --- a/src/ViewLayers/ViewLayerHover.vala +++ /dev/null @@ -1,64 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -public class Akira.ViewLayers.ViewLayerHover : ViewLayer { - public const double UI_LINE_WIDTH = 2.0; - - private Drawables.Drawable? drawable = null; - private Drawables.Drawable? old_drawable = null; - private Geometry.Rectangle last_drawn_bb = Geometry.Rectangle.empty (); - - public ViewLayerHover () {} - - public void add_drawable (Drawables.Drawable? new_drawable) { - if (new_drawable == drawable) { - return; - } - - old_drawable = drawable; - drawable = new_drawable; - update (); - } - - public override void draw_layer (Cairo.Context context, Geometry.Rectangle target_bounds, double scale) { - if (canvas == null || drawable == null) { - return; - } - var color = Gdk.RGBA () { red = 0.25, green = 0.79, blue = 0.98, alpha = 1.0 }; - drawable.paint_hover (context, color, UI_LINE_WIDTH, target_bounds, scale); - last_drawn_bb = drawable.bounds; - } - - public override void update () { - if (canvas == null) { - return; - } - - if (old_drawable != null) { - canvas.request_redraw (last_drawn_bb); - old_drawable = null; - } - - if (drawable != null) { - canvas.request_redraw (drawable.bounds); - } - } -} diff --git a/src/ViewLayers/ViewLayerMultiSelect.vala b/src/ViewLayers/ViewLayerMultiSelect.vala deleted file mode 100644 index 9620131d5..000000000 --- a/src/ViewLayers/ViewLayerMultiSelect.vala +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Copyright (c) 2021-2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Giacomo "giacomoalbe" Alberini - * Alessandro "Alecaddd" Castellani - */ - -public class Akira.ViewLayers.ViewLayerMultiSelect : ViewLayer { - private const double UI_LINE_WIDTH = 1.0; - private Gdk.RGBA fill { get; default = Gdk.RGBA () { red = 0.25, green = 0.79, blue = 0.98, alpha = 0.2 }; } - private Gdk.RGBA stroke { - get { - var color = fill; - color.alpha = 1; - return color; - } - } - - private Drawables.Drawable? drawable = null; - private Drawables.Drawable? old_drawable = null; - private Geometry.Rectangle last_drawn_bb = Geometry.Rectangle.empty (); - private Gee.ArrayList found_drawables; - - private double initial_press_x; - private double initial_press_y; - - public ViewLayerMultiSelect () { - found_drawables = new Gee.ArrayList (); - } - - public void create_region (Gdk.EventButton event) { - initial_press_x = event.x; - initial_press_y = event.y; - - drawable = new Drawables.DrawableRect (event.x, event.y, 0, 0); - } - - public void update_region (double width, double height) { - var center_x = initial_press_x + width / 2; - var center_y = initial_press_y + height / 2; - - drawable.center_x = center_x; - drawable.center_y = center_y; - drawable.width = width; - drawable.height = height; - - old_drawable = drawable; - - drawable.bounds = Geometry.Rectangle.with_coordinates ( - initial_press_x, - initial_press_y, - initial_press_x + width, - initial_press_y + height - ); - - update (); - } - - public void remove_region () { - update (); - drawable = null; - found_drawables.clear (); - } - - public Geometry.Rectangle? get_region_bounds () { - return drawable.bounds; - } - - public void update_found_drawables (Gee.ArrayList drawables) { - found_drawables = drawables; - update (); - } - - public override void draw_layer (Cairo.Context context, Geometry.Rectangle target_bounds, double scale) { - if (canvas == null || drawable == null) { - return; - } - - drawable.fill_rgba = fill; - drawable.line_width = UI_LINE_WIDTH / scale; - drawable.stroke_rgba = stroke; - drawable.paint (context, target_bounds, scale, Drawables.Drawable.DrawType.NORMAL); - - last_drawn_bb = drawable.bounds; - - foreach (unowned var d in found_drawables) { - d.paint_hover (context, stroke, UI_LINE_WIDTH, target_bounds, scale); - } - } - - public override void update () { - if (canvas == null) { - return; - } - - if (old_drawable != null) { - canvas.request_redraw (last_drawn_bb); - } - - if (drawable != null) { - canvas.request_redraw (drawable.bounds); - } - } -} diff --git a/src/ViewLayers/ViewLayerNobs.vala b/src/ViewLayers/ViewLayerNobs.vala deleted file mode 100644 index 58c1d5a64..000000000 --- a/src/ViewLayers/ViewLayerNobs.vala +++ /dev/null @@ -1,204 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - * Authored by: Giacomo "giacomoalbe" Alberini - */ - -public class Akira.ViewLayers.ViewLayerNobs : ViewLayer { - public const double UI_NOB_SIZE = 5; - public const double UI_LINE_WIDTH = 1.01; - public const double UI_ANCHOR_LINE_WIDTH = 1.01; - - private Gdk.RGBA? color = null; - private Utils.Nobs.NobSet? nobs = null; - private Utils.Nobs.NobSet? old_nobs = null; - - private Drawables.Drawable? anchor_point_drawable = null; - private Drawables.Drawable? old_anchor_point_drawable = null; - private Geometry.Rectangle anchor_point_last_bb_drawn = Geometry.Rectangle.empty (); - - public void update_nob_data (Utils.Nobs.NobSet? new_nobs) { - if (nobs != null) { - old_nobs = new Utils.Nobs.NobSet.clone (nobs); - } - - nobs = (new_nobs == null || !new_nobs.any_active ()) ? null : new Utils.Nobs.NobSet.clone (new_nobs); - update (); - } - - public void add_anchor_point (Drawables.Drawable? new_anchor_point_drawable) { - if (new_anchor_point_drawable == anchor_point_drawable) { - return; - } - - if (color == null) { - color = Gdk.RGBA (); - color.parse (settings.snaps_color); - } - - old_anchor_point_drawable = anchor_point_drawable; - anchor_point_drawable = new_anchor_point_drawable; - - update (); - - // Nullify the color if the sub selection is removed so we can always - // get the updated settings color if the user changes it. - if (new_anchor_point_drawable == null) { - color = null; - } - } - - public override void draw_layer (Cairo.Context context, Geometry.Rectangle target_bounds, double scale) { - if (is_visible == false) { - return; - } - - if (canvas == null || nobs == null || !nobs.any_active ()) { - return; - } - - var extents = nobs.extents (canvas.scale, false); - if (extents == null) { - return; - } - - if (extents.left > target_bounds.right || extents.right < target_bounds.left - || extents.top > target_bounds.bottom || extents.bottom < target_bounds.top) { - return; - } - - draw_rect (context, nobs, canvas.scale); - draw_nobs (context, nobs, canvas.scale); - - if (anchor_point_drawable != null) { - anchor_point_drawable.paint_anchor (context, color, UI_ANCHOR_LINE_WIDTH, scale); - anchor_point_last_bb_drawn = anchor_point_drawable.bounds; - } - - context.new_path (); - } - - public void draw_nobs (Cairo.Context context, Utils.Nobs.NobSet nobs, double scale) { - double radius = UI_NOB_SIZE / canvas.scale; - double line_width = UI_LINE_WIDTH / canvas.scale; - - foreach (var nob in nobs.data) { - if (!nob.active) { - continue; - } - context.save (); - - context.new_path (); - context.set_source_rgba (1, 1, 1, 1); - context.set_line_width (line_width); - context.translate (nob.center_x, nob.center_y); - - if (nob.handle_id == Utils.Nobs.Nob.ROTATE) { - context.arc (0, 0, radius, 0, 2.0 * GLib.Math.PI); - } - else { - double x = -radius; - double w = radius * 2; - double y = -radius; - double h = radius * 2; - context.rectangle (x, y, w, h); - } - - context.fill_preserve (); - context.set_source_rgba (0.25, 0.79, 0.98, 1); - context.stroke (); - - context.restore (); - } - } - - public void draw_rect (Cairo.Context context, Utils.Nobs.NobSet nobs, double scale) { - double line_width = UI_LINE_WIDTH / canvas.scale; - context.save (); - - context.new_path (); - context.set_source_rgba (0, 0, 0, 1); - context.set_line_width (line_width); - - var tl = nobs.data[Utils.Nobs.Nob.TOP_LEFT]; - var tr = nobs.data[Utils.Nobs.Nob.TOP_RIGHT]; - var bl = nobs.data[Utils.Nobs.Nob.BOTTOM_LEFT]; - var br = nobs.data[Utils.Nobs.Nob.BOTTOM_RIGHT]; - - context.move_to (tl.center_x, tl.center_y); - context.line_to (tr.center_x, tr.center_y); - context.line_to (br.center_x, br.center_y); - context.line_to (bl.center_x, bl.center_y); - context.close_path (); - context.stroke (); - - var rr = nobs.data[Utils.Nobs.Nob.ROTATE]; - if (rr.active) { - var tc = nobs.data[Utils.Nobs.Nob.TOP_CENTER]; - context.new_path (); - context.move_to (rr.center_x, rr.center_y); - context.line_to (tc.center_x, tc.center_y); - context.stroke (); - } - - context.new_path (); - - context.restore (); - } - - public override void update () { - if (canvas == null) { - return; - } - update_nobs (old_nobs); - update_nobs (nobs); - update_anchor_point (); - - old_nobs = null; - } - - private void update_anchor_point () { - if (canvas == null) { - return; - } - - if (old_anchor_point_drawable != null) { - canvas.request_redraw (anchor_point_last_bb_drawn); - old_anchor_point_drawable = null; - } - - if (anchor_point_drawable != null) { - canvas.request_redraw (anchor_point_drawable.bounds); - } - } - - private void update_nobs (Utils.Nobs.NobSet? nobs) { - if (canvas == null || nobs == null) { - return; - } - - var extents = nobs.extents (canvas.scale, true); - if (extents == null) { - return; - } - - canvas.request_redraw (extents); - } - -} diff --git a/src/ViewLayers/ViewLayerPath.vala b/src/ViewLayers/ViewLayerPath.vala deleted file mode 100644 index 3a197cf62..000000000 --- a/src/ViewLayers/ViewLayerPath.vala +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Ashish Shevale - */ - -public class Akira.ViewLayers.ViewLayerPath : ViewLayer { - public const double UI_NOB_SIZE = 4; - - private Models.PathDataModel path_data; - - private Geometry.Rectangle? old_live_extents = null; - private Geometry.Rectangle? old_extents = null; - - public void update_path_data (Models.PathDataModel _path_data) { - path_data = _path_data; - - if (old_live_extents == null) { - // Initial values for old extents of live effect will span the entire canvas. - old_live_extents = Geometry.Rectangle.empty (); - old_live_extents.right = old_live_extents.bottom = 1000.0; - } - - if (old_extents == null) { - old_extents = Geometry.Rectangle.empty (); - old_extents.right = old_extents.bottom = 1000.0; - } - - update (); - } - - public override void draw_layer (Cairo.Context context, Geometry.Rectangle target_bounds, double scale) { - if (is_visible == false) { - return; - } - - if (canvas == null || path_data.points == null) { - return; - } - - if (path_data.extents.left > target_bounds.right || path_data.extents.right < target_bounds.left - || path_data.extents.top > target_bounds.bottom || path_data.extents.bottom < target_bounds.top) { - - if (path_data.live_extents.left > target_bounds.right || path_data.live_extents.right < target_bounds.left - || path_data.live_extents.top > target_bounds.bottom || path_data.live_extents.bottom < target_bounds.top) { - return; - } - - draw_live_effect (context); - return; - } - - draw_points (context); - draw_live_effect (context); - - context.new_path (); - } - - public override void update () { - if (canvas == null) { - return; - } - - canvas.request_redraw (old_extents); - canvas.request_redraw (path_data.extents); - - canvas.request_redraw (old_live_extents); - canvas.request_redraw (path_data.live_extents); - - // print("LIve extents are %f %f %f %f\n", path_data.live_extents.top, path_data.live_extents.left, path_data.live_extents.bottom, path_data.live_extents.right); - - old_live_extents = path_data.live_extents; - old_extents = path_data.extents; - } - - private void draw_points (Cairo.Context context) { - if (path_data.points == null) { - return; - } - - double radius = UI_NOB_SIZE / canvas.scale; - - context.save (); - - // Apply transform matrix of drawable so we don't have to rotate or scale. - var tr = path_data.transform; - // For all path points, the origin is in top left corner. Move there. - tr.translate (path_data.center.x, path_data.center.y); - - context.new_path (); - context.set_source_rgba (0.1568, 0.4745, 0.9823, 1); - context.set_line_width (1.0 / canvas.scale); - - var points = path_data.points; - - // Draw circles for all points. - for (int i = 0; i < points.length; ++i) { - var curve_begin = points[i].curve_begin; - var tangent_1 = points[i].tangent_1; - var tangent_2 = points[i].tangent_2; - var curve_end = points[i].curve_end; - - tr.transform_point (ref curve_begin.x, ref curve_begin.y); - tr.transform_point (ref tangent_1.x, ref tangent_1.y); - tr.transform_point (ref tangent_2.x, ref tangent_2.y); - tr.transform_point (ref curve_end.x, ref curve_end.y); - - if (points[i].type == Lib.Modes.PathEditMode.Type.LINE) { - draw_control_point (context, curve_begin, radius); - context.fill (); - } else if (points[i].type == Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT) { - // Draw control point for curve begin and tangent. - draw_control_point (context, curve_begin, radius); - draw_control_point (context, tangent_1, radius); - context.fill (); - - draw_line (context, curve_begin, tangent_1); - - context.stroke (); - } else if (points[i].type == Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT) { - var pb = points[i - 1].last_point; - tr.transform_point (ref pb.x, ref pb.y); - - // Draw control point for curve begin and tangent. - draw_control_point (context, curve_end, radius); - draw_control_point (context, tangent_2, radius); - context.fill (); - draw_control_point (context, pb, radius); - context.fill (); - - draw_line (context, pb, tangent_2); - - context.stroke (); - } else if ( - points[i].type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE || - points[i].type == Lib.Modes.PathEditMode.Type.CUBIC_DOUBLE - ) { - // Draw control points. - draw_control_point (context, curve_begin, radius); - draw_control_point (context, tangent_1, radius); - context.fill (); - draw_control_point (context, tangent_2, radius); - draw_control_point (context, curve_end, radius); - context.fill (); - - draw_line (context, tangent_1, curve_begin); - - if (points[i].type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE) { - draw_line (context, curve_end, tangent_2); - } else { - draw_line (context, curve_begin, tangent_2); - } - - context.stroke (); - } - } - - foreach (var sel_pnt in path_data.selected_pts) { - context.set_source_rgba (0.7, 0, 0, 1); - - var segment = points[sel_pnt.sel_index]; - var pt = segment.get_by_type (sel_pnt.sel_type); - - draw_control_point (context, pt, radius); - } - - context.new_path (); - context.restore (); - } - - private void draw_live_effect (Cairo.Context context) { - context.save (); - - context.new_path (); - context.set_source_rgba (0, 0, 0, 1); - context.set_line_width (1.0 / canvas.scale); - - var live_segment = path_data.live_segment; - var live_point_type = path_data.live_point_type; - - context.move_to (path_data.last_point.x, path_data.last_point.y); - - draw_segment (context, live_segment, path_data.last_point, live_point_type); - - context.new_path (); - context.restore (); - } - - private void draw_segment (Cairo.Context context, Geometry.PathSegment segment, Geometry.Point point_before, Lib.Modes.PathEditMode.PointType upto) { - double radius = UI_NOB_SIZE / canvas.scale; - - // First draw the curve. - if (segment.type == Lib.Modes.PathEditMode.Type.LINE) { - // Line only contains 1 point so no need to check 'upto'. - context.line_to (segment.line_end.x, segment.line_end.y); - } else if (segment.type == Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT) { - // Quadratic will always have all 3 points, otherwise it just becomes a line. - context.curve_to ( - point_before.x, - point_before.y, - segment.tangent_1.x, - segment.tangent_1.y, - segment.curve_begin.x, - segment.curve_begin.y - ); - } else if (segment.type == Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT) { - context.move_to (point_before.x, point_before.y); - context.curve_to ( - segment.tangent_2.x, - segment.tangent_2.y, - segment.curve_end.x, - segment.curve_end.y, - segment.curve_end.x, - segment.curve_end.y - ); - } else if (segment.type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE) { - context.move_to (segment.curve_begin.x, segment.curve_begin.y); - context.curve_to ( - segment.tangent_1.x, - segment.tangent_1.y, - segment.tangent_2.x, - segment.tangent_2.y, - segment.curve_end.x, - segment.curve_end.y - ); - } else if (segment.type == Lib.Modes.PathEditMode.Type.CUBIC_DOUBLE) { - context.curve_to ( - path_data.last_point.x, - path_data.last_point.y, - segment.tangent_1.x, - segment.tangent_1.y, - segment.curve_begin.x, - segment.curve_begin.y - ); - - if (upto == Lib.Modes.PathEditMode.PointType.CURVE_END) { - context.curve_to ( - segment.curve_begin.x, - segment.curve_begin.y, - segment.tangent_2.x, - segment.tangent_2.y, - segment.curve_end.x, - segment.curve_end.y - ); - } - } - - // Now draw all the control points. - if (segment.type == Lib.Modes.PathEditMode.Type.LINE) { - context.stroke (); - } else if (segment.type == Lib.Modes.PathEditMode.Type.QUADRATIC_LEFT) { - draw_line (context, point_before, segment.tangent_1); - context.stroke (); - - draw_control_point (context, point_before, radius); - draw_control_point (context, segment.tangent_1, radius); - context.fill (); - } else if (segment.type == Lib.Modes.PathEditMode.Type.QUADRATIC_RIGHT) { - draw_line (context, point_before, segment.tangent_2); - context.stroke (); - - draw_control_point (context, point_before, radius); - draw_control_point (context, segment.tangent_2, radius); - context.fill (); - } else if (segment.type == Lib.Modes.PathEditMode.Type.CUBIC_SINGLE) { - draw_line (context, segment.tangent_1, segment.curve_begin); - draw_line (context, segment.tangent_2, segment.curve_end); - context.stroke (); - - draw_control_point (context, segment.curve_begin, radius); - context.fill (); - draw_control_point (context, segment.tangent_1, radius); - draw_control_point (context, segment.tangent_2, radius); - context.fill (); - } else if (segment.type == Lib.Modes.PathEditMode.Type.CUBIC_DOUBLE) { - draw_line (context, segment.tangent_1, segment.curve_begin); - draw_line (context, segment.tangent_2, segment.curve_begin); - context.stroke (); - - draw_control_point (context, segment.curve_begin, radius); - draw_control_point (context, segment.tangent_1, radius); - draw_control_point (context, segment.tangent_2, radius); - context.fill (); - } - - context.stroke (); - } - - private void draw_line (Cairo.Context context, Geometry.Point start, Geometry.Point end) { - context.move_to (start.x, start.y); - context.line_to (end.x, end.y); - } - - private void draw_control_point (Cairo.Context context, Geometry.Point point, double radius) { - context.arc (point.x, point.y, radius, 0, Math.PI * 2); - } -} diff --git a/src/ViewLayers/ViewLayerSnaps.vala b/src/ViewLayers/ViewLayerSnaps.vala deleted file mode 100644 index 9c85376dd..000000000 --- a/src/ViewLayers/ViewLayerSnaps.vala +++ /dev/null @@ -1,248 +0,0 @@ -/** - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -/* - * A drawable for handling snapping lines and dots. - */ -public class Akira.ViewLayers.ViewLayerSnaps : ViewLayers.ViewLayer { - private const double LINE_WIDTH = 0.5; - private const double DOT_RADIUS = 2; - - public double x { get; set; default = 0; } - public double y { get; set; default = 0; } - public double width { get; set; default = 0; } - public double height { get; set; default = 0; } - - private double[] line_pos; - private double[] dot_x; - private double[] dot_y; - - private bool vertical_lines = false; - private double last_min = 0; - private double last_max = 0; - - private Gdk.RGBA color; - - public ViewLayerSnaps ( - double x, - double y, - double width, - double height, - bool vertical_lines - ) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; - this.vertical_lines = vertical_lines; - } - - /* - * Updates drawable data. - * It shouldn't be hard to optimize this code. - */ - public void update_data ( - Utils.Snapping.SnapMatch match_data, - Gee.TreeMap grid_points - ) { - line_pos = new double[0]; - dot_x = new double[0]; - dot_y = new double[0]; - - if (match_data.snap_found ()) { - foreach (var match in match_data.exact_matches) { - var snap_value = grid_points.get (match); - if (snap_value == null) { - return; - } - add_decorator_line (match, snap_value); - } - } - - update (); - } - - public void hide_drawable () { - line_pos = new double[0]; - dot_x = new double[0]; - dot_y = new double[0]; - set_visible (false); - } - - /* - * Public method to update the color of decorators. - */ - public void update_color (Gdk.RGBA new_color) { - if (color == new_color) { - return; - } - - color = new_color; - update (); - } - - /* - * Adds decorator lines and corresponding dots for given matches. - */ - private void add_decorator_line ( - int pos, - Utils.Snapping.SnapMeta grid_snap_value - ) { - double actual_pos = (double) pos; - - add_to_darray (ref line_pos, actual_pos); - - foreach (var normal in grid_snap_value.normals) { - add_dot (actual_pos, normal); - } - } - - /* - * Adds dots to the array depending on whether or not the drawable is vertical. - * This can probably be improved by having a better data structure. - */ - private void add_dot (double pos, double normal) { - if (vertical_lines) { - add_to_darray (ref dot_x, pos); - add_to_darray (ref dot_y, normal); - } else { - add_to_darray (ref dot_y, pos); - add_to_darray (ref dot_x, normal); - } - } - - private void add_to_darray (ref double[] a, double value) { - a.resize (a.length + 1); - a[a.length - 1] = value; - } - - // CanvasItemSimple methods - - /* - * For now updates the entire screen. In the future this could be made smarter. - * Note that this gets called on changed(true), so simply figuring out the area needed for - * the extents of the lines is NOT enough. - */ - public override void update () { - if (canvas == null) { - return; - } - - double min; - double max; - Utils.Array.min_max_in_darray (line_pos, out min, out max); - - var ww = DOT_RADIUS / canvas.scale; - - if (vertical_lines) { - if (last_min > 0 || last_max > 0) { - canvas.request_redraw (Geometry.Rectangle () { - left = last_min - ww, right = last_max + ww, top = y, bottom = y + height - }); - last_min = 0; - last_max = 0; - } - - if (min > 0 || max > 0) { - canvas.request_redraw (Geometry.Rectangle () { - left = min - ww, right = max + ww, top = y, bottom = y + height - }); - last_min = min; - last_max = max; - } - } - else { - if (last_min > 0 || last_max > 0) { - canvas.request_redraw (Geometry.Rectangle () { - top = last_min - ww, bottom = last_max + ww, left = x, right = x + width - }); - last_min = 0; - last_max = 0; - } - - if (min > 0 || max > 0) { - canvas.request_redraw (Geometry.Rectangle () { - top = min - ww, bottom = max + ww, left = x, right = x + width - }); - last_min = min; - last_max = max; - } - } - } - - /* - * Draw layer. - */ - public override void draw_layer (Cairo.Context context, Geometry.Rectangle target_bounds, double scale) { - if (!is_visible) { - return; - } - draw_lines (context, target_bounds, scale); - draw_dots (context, target_bounds, scale); - } - - /* - * Draw lines. This could be improved to better render lines (more crisp). - */ - private void draw_lines (Cairo.Context cr, Geometry.Rectangle target_bounds, double scale) { - if (line_pos.length == 0) { - return; - } - - cr.save (); - cr.new_path (); - - cr.set_source_rgba (color.red, color.green, color.blue, color.alpha); - cr.set_line_width (1 / scale); - - foreach (var pos in line_pos) { - if (vertical_lines) { - cr.move_to (pos, y); - cr.line_to (pos, height); - } else { - cr.move_to (x, pos); - cr.line_to (width, pos); - } - cr.stroke (); - } - - cr.restore (); - } - - /* - * Draw dots. - */ - private void draw_dots (Cairo.Context cr, Geometry.Rectangle target_bounds, double scale) { - if (dot_x.length == 0 || dot_x.length != dot_y.length) { - return; - } - - cr.save (); - cr.new_path (); - cr.set_source_rgba (color.red, color.green, color.blue, color.alpha); - for (var i = 0; i < dot_x.length; ++i) { - cr.arc (dot_x[i], dot_y[i], DOT_RADIUS / scale, 0, 2.0 * GLib.Math.PI); - cr.fill (); - } - - cr.restore (); - } -} diff --git a/src/Widgets/AddColorButton.vala b/src/Widgets/AddColorButton.vala deleted file mode 100644 index 7f53c42f5..000000000 --- a/src/Widgets/AddColorButton.vala +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Abdallah "Abdallah-Moh" Mohammad - * Authored by: Alessandro "alecaddd" Castellani - */ - -/* - * Helper class to quickly create a simple style button with a + icon. - */ -public class Akira.Widgets.AddColorButton : Gtk.Button { - public AddColorButton () { - get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - width_request = height_request = 24; - can_focus = false; - valign = halign = Gtk.Align.CENTER; - image = new Gtk.Image.from_icon_name ("list-add-symbolic", Gtk.IconSize.MENU); - tooltip_text = _("Add the current color to the library"); - } -} diff --git a/src/Widgets/ButtonImage.vala b/src/Widgets/ButtonImage.vala deleted file mode 100644 index 2c263a92f..000000000 --- a/src/Widgets/ButtonImage.vala +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Bilal Elmoussaoui - */ - -/* - * Helper class to create a Gtk.Image that is aware of the symbolic preference - * change and updates itself. - */ -public class Akira.Widgets.ButtonImage: Gtk.Image { - private string icon; - private Gtk.IconSize size; - - public ButtonImage (string icon_name, Gtk.IconSize icon_size = Gtk.IconSize.LARGE_TOOLBAR) { - icon = icon_name; - size = icon_size; - margin = 0; - - settings.changed["use-symbolic"].connect (update_image); - update_image (); - } - - ~ButtonImage () { - settings.changed["use-symbolic"].disconnect (update_image); - } - - private void update_image () { - if (settings.use_symbolic) { - set_from_icon_name ("%s-symbolic".printf (icon), Gtk.IconSize.SMALL_TOOLBAR); - return; - } - - set_from_icon_name (icon.replace ("-symbolic", ""), size); - } -} diff --git a/src/Widgets/ColorButton.vala b/src/Widgets/ColorButton.vala deleted file mode 100644 index d989af932..000000000 --- a/src/Widgets/ColorButton.vala +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Widget to create a reusable color button that triggers a color chooser - * when clicked. -*/ -public class Akira.Widgets.ColorButton : Gtk.Button { - private unowned Models.ColorModel model; - - private Gtk.Popover color_popover; - private Widgets.ColorChooser? color_chooser = null; - - private string? current_color = null; - - public class SignalBlocker { - private unowned ColorButton item; - - public SignalBlocker (ColorButton fill_item) { - item = fill_item; - item.block_signal += 1; - } - - ~SignalBlocker () { - item.block_signal -= 1; - } - } - - protected int block_signal = 0; - - public ColorButton () { - get_style_context ().add_class ("selected-color"); - vexpand = true; - width_request = 40; - can_focus = false; - tooltip_text = _("Choose color"); - - color_popover = new Gtk.Popover (this) { - position = Gtk.PositionType.BOTTOM - }; - - clicked.connect (on_clicked); - } - - ~ColorButton () { - model.value_changed.disconnect (on_model_changed); - } - - public void assign (Models.ColorModel model) { - this.model = model; - model.value_changed.connect (on_model_changed); - on_model_changed (); - } - - /* - * Update the color of the button when the model changed. - */ - private void on_model_changed () { - sensitive = !model.hidden; - - var new_color = model.color.to_string (); - if (new_color == current_color) { - return; - } - - try { - var provider = new Gtk.CssProvider (); - var context = get_style_context (); - - var css = """.selected-color { - background-color: %s; - border-color: shade (%s, 0.75); - }""".printf (new_color, new_color); - - provider.load_from_data (css, css.length); - context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - current_color = new_color; - } catch (Error e) { - warning ("Style error: %s", e.message); - } - } - - private void init_color_chooser () { - if (color_chooser != null) { - return; - } - - color_chooser = new ColorChooser (); - color_chooser.color_changed.connect (color => { - if (block_signal > 0) { - return; - } - model.color = color; - }); - color_popover.add (color_chooser); - } - - private void on_clicked () { - if (color_chooser == null) { - init_color_chooser (); - } - - var blocker = new SignalBlocker (this); - (blocker); - color_chooser.set_color (model.color); - color_popover.popup (); - } -} diff --git a/src/Widgets/ColorChooser.vala b/src/Widgets/ColorChooser.vala deleted file mode 100644 index dea660910..000000000 --- a/src/Widgets/ColorChooser.vala +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Helper class to create a container for the GtkColorChooser. - */ -public class Akira.Widgets.ColorChooser : Gtk.Grid { - public signal void color_changed (Gdk.RGBA color); - - private Gtk.ColorChooserWidget chooser; - private Gtk.FlowBox global_flowbox; - - /* - * Type of color containers to add new colors to. We can potentially create - * an API to allow adding more containers to the color picker popup. - */ - private enum Container { - GLOBAL, - DOCUMENT - } - - public ColorChooser () { - margin_top = margin_bottom = 12; - margin_start = margin_end = 3; - row_spacing = 12; - get_style_context ().add_class ("color-picker"); - - chooser = new Gtk.ColorChooserWidget () { - hexpand = true, - show_editor = true - }; - chooser.notify["rgba"].connect (on_color_changed); - - attach (chooser, 0, 0, 1, 1); - - var global_label = new Gtk.Label (_("Global colors")) { - halign = Gtk.Align.START, - margin_start = margin_end = 6 - }; - attach (global_label, 0, 1, 1, 1); - - global_flowbox = new Gtk.FlowBox () { - selection_mode = Gtk.SelectionMode.NONE, - homogeneous = false, - column_spacing = row_spacing = 6, - margin_start = margin_end = 6, - // Large number to allow children to spread out the available space. - max_children_per_line = 100, - }; - global_flowbox.get_style_context ().add_class ("color-grid"); - global_flowbox.set_sort_func (sort_colors_function); - - var add_global_color_btn = new AddColorButton (); - add_global_color_btn.clicked.connect (() => { - on_save_color (Container.GLOBAL); - }); - global_flowbox.add (add_global_color_btn); - - foreach (string color in settings.global_colors) { - var btn = create_color_button (color); - global_flowbox.add (btn); - } - - attach (global_flowbox, 0, 2, 1, 1); - show_all (); - } - - /* - * Add the current color to the parent flowbox. - */ - private void on_save_color (Container parent) { - // Get the currently active color. - var color = chooser.rgba.to_string (); - - // Create the new color button and connect to its signal. - var btn = create_color_button (color); - - // Update the colors list and the schema based on the colors container. - switch (parent) { - case Container.GLOBAL: - global_flowbox.add (btn); - var array = settings.global_colors; - array += color; - settings.global_colors = array; - break; - - case Container.DOCUMENT: - // TODO... - break; - } - } - - private Gtk.FlowBoxChild create_color_button (string color) { - var child = new Gtk.FlowBoxChild () { - valign = halign = Gtk.Align.CENTER - }; - - var btn = new RoundedColorButton (color); - btn.set_color.connect ((color) => { - var rgba_color = Gdk.RGBA (); - rgba_color.parse (color); - chooser.set_rgba (rgba_color); - }); - - child.add (btn); - child.show_all (); - return child; - } - - private int sort_colors_function (Gtk.FlowBoxChild a, Gtk.FlowBoxChild b) { - return (a is AddColorButton) ? -1 : 1; - } - - public void set_color (Gdk.RGBA color) { - chooser.set_rgba (color); - } - - private void on_color_changed () { - color_changed (chooser.get_rgba ()); - } -} diff --git a/src/Widgets/ColorField.vala b/src/Widgets/ColorField.vala deleted file mode 100644 index aaa0aef3e..000000000 --- a/src/Widgets/ColorField.vala +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2019-2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Widgets.ColorField : Gtk.Entry { - private unowned Models.ColorModel model; - - public unowned Akira.Lib.ViewCanvas view_canvas { get; construct; } - - public class SignalBlocker { - private unowned ColorField item; - - public SignalBlocker (ColorField fill_item) { - item = fill_item; - item.block_signal += 1; - } - - ~SignalBlocker () { - item.block_signal -= 1; - } - } - - protected int block_signal = 0; - - public ColorField (Akira.Lib.ViewCanvas canvas) { - Object (view_canvas: canvas); - - margin_end = margin_start = 10; - width_chars = 8; - max_length = 7; - hexpand = true; - - changed.connect (on_changed); - focus_in_event.connect (on_focus_in); - focus_out_event.connect (on_focus_out); - insert_text.connect (on_insert_text); - key_press_event.connect (on_key_press); - } - - ~ColorField () { - focus_in_event.disconnect (on_focus_in); - focus_out_event.disconnect (on_focus_out); - insert_text.disconnect (on_insert_text); - key_press_event.disconnect (on_key_press); - model.value_changed.disconnect (on_model_changed); - } - - public void assign (Models.ColorModel model) { - this.model = model; - model.value_changed.connect (on_model_changed); - on_model_changed (); - } - - private void on_model_changed () { - var blocker = new SignalBlocker (this); - (blocker); - - text = Utils.Color.rgba_to_hex_string (model.color); - sensitive = !model.hidden; - } - - private void on_changed () { - if (block_signal > 0) { - return; - } - - // Interrupt if what's written is not a valid color value. - if (!Utils.Color.is_valid_hex (text)) { - return; - } - - var new_rgba = Utils.Color.hex_to_rgba (text); - model.color = new_rgba; - } - - private void on_insert_text (string text, int length, ref int position) { - string new_text = text.strip (); - - if (new_text.contains ("#")) { - new_text = new_text.substring (1, new_text.length - 1); - } else if (!this.text.contains ("#")) { - GLib.Signal.stop_emission_by_name (this, "insert-text"); - - var builder = new StringBuilder (); - builder.append (new_text); - builder.prepend ("#"); - this.text = builder.str; - - position = this.text.length; - } - - bool is_valid_hex = true; - bool char_is_numeric = true; - bool char_is_valid_alpha = true; - - char keyval; - - for (var i = 0; i < new_text.length; i++) { - keyval = new_text [i]; - - char_is_numeric = keyval >= Gdk.Key.@0 && keyval <= Gdk.Key.@9; - char_is_valid_alpha = keyval >= Gdk.Key.A && keyval <= Gdk.Key.F; - - is_valid_hex &= keyval.isxdigit (); - } - - if (!is_valid_hex) { - GLib.Signal.stop_emission_by_name (this, "insert-text"); - return; - } - } - - private bool on_focus_in (Gdk.EventFocus event) { - view_canvas.window.event_bus.disconnect_typing_accel (); - return false; - } - - private bool on_focus_out (Gdk.EventFocus event) { - view_canvas.window.event_bus.connect_typing_accel (); - return false; - } - - private bool on_key_press (Gdk.EventKey event) { - // Enter or Escape - if (event.keyval == Gdk.Key.Return || event.keyval == Gdk.Key.Escape) { - view_canvas.window.event_bus.set_focus_on_canvas (); - return true; - } - - return false; - } -} diff --git a/src/Widgets/ColorPicker.vala b/src/Widgets/ColorPicker.vala deleted file mode 100644 index f7a14fbce..000000000 --- a/src/Widgets/ColorPicker.vala +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright (c) 2020-2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Ivan "isneezy" Vilanculo - * Alessandro "Alecaddd" Castellani - * Ported from: https://github.com/ColorPicker/RonnyDo -*/ - -public class Akira.Widgets.ColorPicker : Gtk.Window { - public signal void picked (Gdk.RGBA color); - public signal void cancelled (); - public signal void moved (Gdk.RGBA color); - public signal void key_pressed (Gdk.EventKey e); - public signal void key_released (Gdk.EventKey e); - - const string DARK_BORDER_COLOR_STRING = "#333333"; - private Gdk.RGBA dark_border_color = Gdk.RGBA (); - - const string BRIGHT_BORDER_COLOR_STRING = "#FFFFFF"; - private Gdk.RGBA bright_border_color = Gdk.RGBA (); - - - // 1. Snapsize is the amount of pixel going to be magnified by the zoomlevel. - // 2. The snapsize must be odd to have a 1px magnifier center. - // 3. Assure that snapsize*max_zoomlevel+shadow_width*2 is smaller than 2 * get_screen ().get_display ().get_maximal_cursor_size() - // Valid: snapsize = 31, max_zoomlevel = 7, shadow_width = 15 --> 247px - // get_maximal_cursor_size = 128 --> 256px - // Otherwise the cursor starts to flicker. See https://github.com/stuartlangridge/ColourPicker/issues/6#issuecomment-277972290 - // and https://github.com/RonnyDo/ColorPicker/issues/19 - int snapsize = 31; - int min_zoomlevel = 2; - int max_zoomlevel = 7; - int zoomlevel = 6; - int shadow_width = 15; - - private Gdk.Cursor magnifier = null; - - construct { - app_paintable = true; - decorated = false; - resizable = false; - set_visual (get_screen ().get_rgba_visual ()); - type = Gtk.WindowType.POPUP; - } - - - public ColorPicker () { - stick (); - set_resizable (true); - set_deletable (false); - set_skip_taskbar_hint (true); - set_skip_pager_hint (true); - set_keep_above (true); - - dark_border_color.parse (DARK_BORDER_COLOR_STRING); - bright_border_color.parse (BRIGHT_BORDER_COLOR_STRING); - - var display = Gdk.Display.get_default (); - Gdk.Monitor monitor = display.get_primary_monitor (); - Gdk.Rectangle geom = monitor.get_geometry (); - set_default_size (geom.width, geom.height); - } - - public override bool button_release_event (Gdk.EventButton e) { - // button_1 is left mouse button - if (e.button == 1) { - Gdk.RGBA color = get_color_at ((int) e.x_root, (int) e.y_root); - picked (color); - // button_3 is right mouse button - } else if (e.button == 3) { - cancelled (); - } - - return true; - } - - public override bool draw (Cairo.Context cr) { - return false; - } - - public override bool motion_notify_event (Gdk.EventMotion e) { - Gdk.RGBA color = get_color_at ((int) e.x_root, (int) e.y_root); - moved (color); - set_magnifier_cursor (); - return true; - } - - public override bool scroll_event (Gdk.EventScroll e) { - switch (e.direction) { - case Gdk.ScrollDirection.UP: - if (zoomlevel < max_zoomlevel) { - zoomlevel++; - } - set_magnifier_cursor (); - break; - case Gdk.ScrollDirection.DOWN: - if (zoomlevel > min_zoomlevel) { - zoomlevel--; - } - set_magnifier_cursor (); - break; - default: - break; - } - - return true; - } - - public void set_magnifier_cursor () { - var manager = Gdk.Display.get_default ().get_default_seat (); - - // get cursor position - int px, py; - get_window ().get_device_position (manager.get_pointer (), out px, out py, null); - - var radius = snapsize * zoomlevel / 2; - - // get a small area (snap) meant to be zoomed - var snapped_pixbuf = snap (px - snapsize / 2, py - snapsize / 2, snapsize, snapsize); - - // Zoom that screenshot up, and grab a snapsize-sized piece from the middle - var scaled_pb = snapped_pixbuf.scale_simple ( - snapsize * zoomlevel + shadow_width * 2 , - snapsize * zoomlevel + shadow_width * 2 , - Gdk.InterpType.NEAREST - ); - - - // Create the base surface for our cursor - var base_surface = new Cairo.ImageSurface ( - Cairo.Format.ARGB32, - snapsize * zoomlevel + shadow_width * 2 , - snapsize * zoomlevel + shadow_width * 2 - ); - - var base_context = new Cairo.Context (base_surface); - // Create the circular path on our base surface - base_context.arc (radius + shadow_width, radius + shadow_width, radius, 0, 2 * Math.PI); - - // Paste in the screenshot - Gdk.cairo_set_source_pixbuf (base_context, scaled_pb, 0, 0); - - // Clip to that circular path, keeping the path around for later, and paint the pasted screenshot - base_context.save (); - base_context.clip_preserve (); - base_context.paint (); - base_context.restore (); - - // Draw a shadow as outside magnifier border - double shadow_alpha = 0.6; - base_context.set_line_width (1); - - for (int i = 0; i <= shadow_width; i++) { - base_context.arc ( - radius + shadow_width, radius + shadow_width, - radius + shadow_width - i, 0, 2 * Math.PI - ); - Gdk.RGBA shadow_color = Gdk.RGBA (); - shadow_color.parse (DARK_BORDER_COLOR_STRING); - shadow_color.alpha = shadow_alpha / ((shadow_width - i + 1) * (shadow_width - i + 1)); - Gdk.cairo_set_source_rgba (base_context, shadow_color); - base_context.stroke (); - } - - // Draw an outside bright magnifier border - Gdk.cairo_set_source_rgba (base_context, bright_border_color); - base_context.arc (radius + shadow_width, radius + shadow_width, radius - 1, 0, 2 * Math.PI); - base_context.stroke (); - - // Draw inside square - base_context.set_line_width (1); - - Gdk.cairo_set_source_rgba (base_context, dark_border_color); - base_context.move_to (radius + shadow_width - zoomlevel, radius + shadow_width - zoomlevel); - base_context.line_to (radius + shadow_width + zoomlevel, radius + shadow_width - zoomlevel); - base_context.line_to (radius + shadow_width + zoomlevel, radius + shadow_width + zoomlevel); - base_context.line_to (radius + shadow_width - zoomlevel, radius + shadow_width + zoomlevel); - base_context.close_path (); - base_context.stroke (); - - Gdk.cairo_set_source_rgba (base_context, bright_border_color); - base_context.move_to (radius + shadow_width - zoomlevel + 1, radius + shadow_width - zoomlevel + 1); - base_context.line_to (radius + shadow_width + zoomlevel - 1, radius + shadow_width - zoomlevel + 1); - base_context.line_to (radius + shadow_width + zoomlevel - 1, radius + shadow_width + zoomlevel - 1); - base_context.line_to (radius + shadow_width - zoomlevel + 1, radius + shadow_width + zoomlevel - 1); - base_context.close_path (); - base_context.stroke (); - - magnifier = new Gdk.Cursor.from_surface ( - get_screen ().get_display (), - base_surface, - base_surface.get_width () / 2, - base_surface.get_height () / 2 - ); - - // Set the cursor - manager.grab ( - get_window (), - Gdk.SeatCapabilities.ALL, - true, - magnifier, - new Gdk.Event (Gdk.EventType.BUTTON_PRESS | Gdk.EventType.MOTION_NOTIFY | Gdk.EventType.SCROLL), - null - ); - } - - public Gdk.Pixbuf? snap (int x, int y, int w, int h) { - var root = Gdk.get_default_root_window (); - var screenshot = Gdk.pixbuf_get_from_window (root, x, y, w, h); - return screenshot; - } - - public override bool key_press_event (Gdk.EventKey e) { - var manager = Gdk.Display.get_default ().get_default_seat (); - int px, py; - get_window ().get_device_position (manager.get_pointer (), out px, out py, null); - - switch (e.keyval) { - case Gdk.Key.Escape: - cancelled (); - break; - case Gdk.Key.Return: - Gdk.RGBA color = get_color_at (px, py); - picked (color); - break; - case Gdk.Key.Up: - manager.get_pointer ().warp (get_screen (), px, py - 1); - break; - case Gdk.Key.Down: - manager.get_pointer ().warp (get_screen (), px, py + 1); - break; - case Gdk.Key.Left: - manager.get_pointer ().warp (get_screen (), px - 1, py); - break; - case Gdk.Key.Right: - manager.get_pointer ().warp (get_screen (), px + 1, py); - break; - } - key_pressed (e); - return true; - } - - public override bool key_release_event (Gdk.EventKey e) { - key_released (e); - return true; - } - - public Gdk.RGBA get_color_at (int x, int y) { - var root = Gdk.get_default_root_window (); - Gdk.Pixbuf? pixbuf = Gdk.pixbuf_get_from_window (root, x, y, 1, 1); - - if (pixbuf != null) { - // see https://hackage.haskell.org/package/gtk3-0.14.6/docs/Graphics-UI-Gtk-Gdk-Pixbuf.html - uint8 red = pixbuf.get_pixels ()[0]; - uint8 green = pixbuf.get_pixels ()[1]; - uint8 blue = pixbuf.get_pixels ()[2]; - - Gdk.RGBA color = Gdk.RGBA (); - string spec = "rgb(" + red.to_string () + "," + green.to_string () + "," + blue.to_string () + ")"; - if (color.parse (spec)) { - return color; - } - stdout.printf ("ERROR: Parse pixel rgb values failed."); - } - - // fallback: default RGBA color - stdout.printf ("ERROR: Gdk.pixbuf_get_from_window failed"); - return Gdk.RGBA (); - } - - public override void show_all () { - base.show_all (); - - var manager = Gdk.Display.get_default ().get_default_seat (); - var window = get_window (); - - var status = manager.grab ( - window, - Gdk.SeatCapabilities.ALL, - false, - new Gdk.Cursor.for_display (window.get_display (), Gdk.CursorType.CROSSHAIR), - new Gdk.Event (Gdk.EventType.BUTTON_PRESS | Gdk.EventType.BUTTON_RELEASE | Gdk.EventType.MOTION_NOTIFY), - null - ); - - if (status != Gdk.GrabStatus.SUCCESS) { - manager.ungrab (); - } - - // show magnifier - set_magnifier_cursor (); - } - - public new void close () { - get_window ().set_cursor (null); - base.close (); - } -} diff --git a/src/Widgets/ExportWidget.vala b/src/Widgets/ExportWidget.vala deleted file mode 100644 index 27b095633..000000000 --- a/src/Widgets/ExportWidget.vala +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2020-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "alecaddd" Castellani - */ - -public class Akira.Widgets.ExportWidget : Gtk.Grid { - public Models.ExportModel model { get; set construct; } - - private Gtk.Entry input; - private Gtk.Label info; - private Gtk.Grid image_container; - private Gtk.Image image; - private uint8[]? imagedata; - - public ExportWidget (Models.ExportModel model) { - Object ( - orientation: Gtk.Orientation.VERTICAL, - model: model - ); - } - - construct { - halign = Gtk.Align.CENTER; - valign = Gtk.Align.CENTER; - row_spacing = 9; - margin_top = margin_bottom = 6; - expand = true; - var ctx = get_style_context (); - ctx.add_class ("export-widget"); - ctx.add_class (Granite.STYLE_CLASS_CARD); - - // Filename with editable entry. - input = new Gtk.Entry () { - placeholder_text = _("File name"), - width_chars = 10, - hexpand = true - }; - input.secondary_icon_activatable = false; - input.secondary_icon_tooltip_text = _("A file name is required to export this image"); - input.get_style_context ().add_class ("export-filename"); - input.changed.connect (on_input_changed); - input.text = model.filename; - input.bind_property ("text", model, "filename", BindingFlags.DEFAULT); - - // Image preview container with checker. - image_container = new Gtk.Grid () { - halign = Gtk.Align.CENTER - }; - var image_container_ctx = image_container.get_style_context (); - image_container_ctx.add_class (Granite.STYLE_CLASS_CHECKERBOARD); - image_container_ctx.add_class ("export-image"); - - image = new Gtk.Image (); - image_container.add (image); - - // Label for image size info. - info = new Gtk.Label (null) { - hexpand = true, - halign = Gtk.Align.END - }; - info.get_style_context ().add_class ("export-info"); - - // Fetch the image and its info after all the widgets have been created. - get_image.begin (); - - attach (input, 0, 0); - attach (image_container, 0, 1); - attach (info, 0, 2); - - show_all (); - - settings.changed["export-quality"].connect (() => { - update_file_size.begin (); - }); - settings.changed["export-compression"].connect (() => { - update_file_size.begin (); - }); - - // Trigger the detection of and empty file name filed on creation. - on_input_changed (); - } - - private void on_input_changed () { - bool empty = input.text.strip () == ""; - model.toggle_export_button (!empty); - if (empty) { - input.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, "process-error"); - return; - } - - if (input.get_icon_name (Gtk.EntryIconPosition.SECONDARY) != null) { - input.set_icon_from_icon_name (Gtk.EntryIconPosition.SECONDARY, null); - } - } - - /** - * Generate the image from the pixbuf model and resize it if bigger than - * half of the width of the export dialog. - */ - public async void get_image () { - var resized_image = model.pixbuf; - if (resized_image.width > (settings.export_width / 2)) { - // Keep the aspect ratio consistent. - var w = (settings.export_width / 2); - var h = (resized_image.height * w) / resized_image.width; - resized_image = resized_image.scale_simple (w, h, Gdk.InterpType.BILINEAR); - } - - image.set_from_pixbuf (resized_image); - - yield update_file_size (); - } - - public async void update_file_size () { - yield get_image_buffer_size (); - - info.label = _("%i × %i px · %s").printf ( - model.pixbuf.width, - model.pixbuf.height, - format_size (imagedata.length)); - } - - private async void get_image_buffer_size () { - unowned var image = model.pixbuf; - info.label = _("Fetching image size…"); - SourceFunc callback = get_image_buffer_size.callback; - - new Thread (null, () => { - try { - if (settings.export_format == "png") { - image.save_to_buffer ( - out imagedata, - "png", - "compression", - settings.export_compression.to_string (), - null); - } - - if (settings.export_format == "jpg") { - image.save_to_buffer ( - out imagedata, - "jpeg", - "quality", - settings.export_quality.to_string (), - null); - } - } catch (Error e) { - error ("Unable to create image buffer: %s", e.message); - } - - Idle.add ((owned) callback); - Thread.exit (null); - - return null; - }); - - yield; - } -} diff --git a/src/Widgets/EyeDropperButton.vala b/src/Widgets/EyeDropperButton.vala deleted file mode 100644 index 11ac5e5e4..000000000 --- a/src/Widgets/EyeDropperButton.vala +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Widget to create a reusable button that toggles the visibility of a color - * for the fill or border components. -*/ -public class Akira.Widgets.EyeDropperButton : Gtk.Button { - private unowned Models.ColorModel model; - - private Widgets.ColorPicker? eyedropper = null; - - public EyeDropperButton () { - can_focus = false; - valign = Gtk.Align.CENTER; - tooltip_text = _("Pick color"); - - get_style_context ().add_class ("color-picker-button"); - add (new Gtk.Image.from_icon_name ("color-select-symbolic", Gtk.IconSize.SMALL_TOOLBAR)); - - clicked.connect (on_clicked); - } - - public void assign (Models.ColorModel model) { - this.model = model; - model.value_changed.connect (on_model_changed); - on_model_changed (); - } - - private void on_model_changed () { - sensitive = !model.hidden; - } - - private void on_clicked () { - if (eyedropper == null) { - eyedropper = new ColorPicker (); - } - eyedropper.show_all (); - - eyedropper.picked.connect ((picked_color) => { - model.color = picked_color; - eyedropper.close (); - }); - - eyedropper.cancelled.connect (() => { - eyedropper.close (); - }); - } -} diff --git a/src/Widgets/HeaderBarButton.vala b/src/Widgets/HeaderBarButton.vala deleted file mode 100644 index 2cb668adc..000000000 --- a/src/Widgets/HeaderBarButton.vala +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Widgets.HeaderBarButton : Gtk.Grid { - public weak Akira.Window window; - public Gtk.Button button; - private Gtk.Label label_btn; - public ButtonImage image; - public string? sensitive_type; - - public HeaderBarButton (Akira.Window _window, string icon_name, string name, - string[]? accels = null, string? type = null) { - window = _window; - sensitive_type = type; - label_btn = new Gtk.Label (name); - label_btn.get_style_context ().add_class ("headerbar-label"); - - button = new Gtk.Button (); - button.can_focus = false; - button.halign = Gtk.Align.CENTER; - button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - button.tooltip_markup = Granite.markup_accel_tooltip (accels, name); - - image = new ButtonImage (icon_name); - button.add (image); - - attach (button, 0, 0, 1, 1); - attach (label_btn, 0, 1, 1, 1); - - valign = Gtk.Align.CENTER; - sensitive = false; - - update_label (); - build_signals (); - - settings.changed["show-label"].connect ( () => { - update_label (); - }); - } - - private void update_label () { - label_btn.visible = settings.show_label; - label_btn.no_show_all = !settings.show_label; - } - - private void build_signals () { - window.event_bus.change_sensitivity.connect ((type) => { - if (type == sensitive_type) { - sensitive = !sensitive; - } - }); - } -} diff --git a/src/Widgets/HideButton.vala b/src/Widgets/HideButton.vala deleted file mode 100644 index 6df20db4d..000000000 --- a/src/Widgets/HideButton.vala +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Widget to create a reusable button that toggles the visibility of a color - * for the fill or border components. -*/ -public class Akira.Widgets.HideButton : Gtk.Button { - private unowned Models.ColorModel model; - - private bool? current_state = null; - - public HideButton () { - valign = Gtk.Align.CENTER; - can_focus = false; - margin_start = 3; - - get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - get_style_context ().add_class ("button-rounded"); - - clicked.connect (on_clicked); - } - - ~HideButton () { - clicked.disconnect (on_clicked); - model.value_changed.disconnect (on_model_changed); - } - - public void assign (Models.ColorModel model) { - this.model = model; - model.value_changed.connect (on_model_changed); - on_model_changed (); - } - - private void on_model_changed () { - if (current_state == model.hidden) { - return; - } - - if (model.hidden) { - get_style_context ().add_class ("active"); - image = new Gtk.Image.from_icon_name ("layer-hidden-symbolic", Gtk.IconSize.MENU); - tooltip_text = _("Show color"); - } else { - get_style_context ().remove_class ("active"); - image = new Gtk.Image.from_icon_name ("layer-visible-symbolic", Gtk.IconSize.MENU); - tooltip_text = _("Hide color"); - } - - current_state = model.hidden; - } - - private void on_clicked () { - model.hidden = !model.hidden; - } -} diff --git a/src/Widgets/InputField.vala b/src/Widgets/InputField.vala deleted file mode 100644 index ee06c7e68..000000000 --- a/src/Widgets/InputField.vala +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2019-2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Widgets.InputField : Gtk.Grid { - public enum Unit { - PIXEL, - HASH, - PERCENTAGE, - DEGREES, - NONE - } - - public unowned Lib.ViewCanvas view_canvas { get; construct; } - public Gtk.SpinButton entry { get; construct set; } - - private double step { get; set; default = 1; } - - public InputField ( - Lib.ViewCanvas canvas, - Unit unit, - int chars, - bool icon_right = false, - bool rtl = false - ) { - Object (view_canvas: canvas); - - valign = Gtk.Align.CENTER; - - - Gtk.Adjustment adj = new Gtk.Adjustment (0, -double.MAX, double.MAX, 0.01, 0.1, 0.0); - double climb_rate = 0.01; - uint digits = 2; - if (unit == Unit.PERCENTAGE) { - digits = 0; - adj.configure (0, 0, 100, 1.0, 1.0, 0.0); - } - - entry = new Gtk.SpinButton (adj, climb_rate, digits) { - hexpand = true, - width_chars = chars, - sensitive = false - }; - - entry.key_press_event.connect (handle_key_press); - entry.scroll_event.connect (handle_scroll_event); - entry.focus_in_event.connect (handle_focus_in); - entry.focus_out_event.connect (handle_focus_out); - - string? icon = null; - switch (unit) { - case Unit.HASH: - icon = "input-hash-symbolic"; - break; - case Unit.PERCENTAGE: - icon = "input-percentage-symbolic"; - break; - case Unit.PIXEL: - icon = "input-pixel-symbolic"; - break; - case Unit.DEGREES: - icon = "input-degrees-symbolic"; - break; - case Unit.NONE: - // No icon needs to be shown. - break; - } - - if (icon != null) { - if (icon_right) { - entry.get_style_context ().add_class ("input-icon-right"); - entry.secondary_icon_name = icon; - entry.secondary_icon_sensitive = false; - entry.secondary_icon_activatable = false; - } else { - entry.get_style_context ().add_class ("input-icon-left"); - entry.primary_icon_name = icon; - entry.primary_icon_sensitive = false; - entry.primary_icon_activatable = false; - } - } - - if (rtl) { - entry.xalign = 1.0f; - } - - add (entry); - } - - public void set_range (double min_value, double max_value) { - entry.set_range (min_value, max_value); - } - - private bool handle_key_press (Gdk.EventKey event) { - // Arrow UP. - if (event.keyval == Gdk.Key.Up && view_canvas.shift_is_pressed) { - entry.spin (Gtk.SpinType.STEP_FORWARD, 10); - return true; - } - - // Arrow DOWN. - if (event.keyval == Gdk.Key.Down && view_canvas.shift_is_pressed) { - entry.spin (Gtk.SpinType.STEP_BACKWARD, 10); - return true; - } - - // Enter or Escape. - if (event.keyval == Gdk.Key.Return || event.keyval == Gdk.Key.Escape) { - view_canvas.window.event_bus.set_focus_on_canvas (); - return true; - } - - return false; - } - - private bool handle_scroll_event (Gdk.EventScroll event) { - // If the input field is not focused, don't change the value. - if (!entry.has_focus) { - return true; - } - return false; - } - - private bool handle_focus_in (Gdk.EventFocus event) { - view_canvas.window.event_bus.disconnect_typing_accel (); - return false; - } - - private bool handle_focus_out (Gdk.EventFocus event) { - view_canvas.window.event_bus.connect_typing_accel (); - return false; - } -} diff --git a/src/Widgets/LinkedInput.vala b/src/Widgets/LinkedInput.vala deleted file mode 100644 index 147596026..000000000 --- a/src/Widgets/LinkedInput.vala +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2019-2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Ana Gelez - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * A digit input with a label next to it. - */ -public class Akira.Widgets.LinkedInput : Gtk.Grid { - public unowned Lib.ViewCanvas view_canvas { get; construct; } - - public InputField input_field { get; set; } - - private bool dragging = false; - private double dragging_direction = 0; - - public LinkedInput ( - Lib.ViewCanvas canvas, - string label, - string tooltip = "", - InputField.Unit icon = InputField.Unit.PIXEL, - bool reversed = false - ) { - Object (view_canvas: canvas); - - valign = Gtk.Align.CENTER; - hexpand = true; - get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED); - - var entry_label = new Gtk.Label (label) { - halign = Gtk.Align.CENTER, - width_request = 20, - hexpand = false, - tooltip_text = tooltip - }; - entry_label.get_style_context ().add_class ("entry-label"); - - var event_box = new Gtk.EventBox (); - event_box.event.connect (handle_event); - event_box.add (entry_label); - - input_field = new Widgets.InputField (view_canvas, icon, 7, true, false); - - if (reversed) { - attach (input_field, 0, 0); - attach (event_box, 1, 0); - } else { - attach (event_box, 0, 0); - attach (input_field, 1, 0); - } - } - - public bool handle_event (Gdk.Event event) { - if (!input_field.entry.sensitive) { - return false; - } - - if (event.type == Gdk.EventType.ENTER_NOTIFY) { - set_cursor_from_name ("ew-resize"); - } - - if (event.type == Gdk.EventType.LEAVE_NOTIFY) { - set_cursor (Gdk.CursorType.ARROW); - } - - if (event.type == Gdk.EventType.BUTTON_PRESS) { - dragging = true; - } - - if (event.type == Gdk.EventType.BUTTON_RELEASE) { - dragging = false; - dragging_direction = 0; - } - - if (event.type == Gdk.EventType.MOTION_NOTIFY && dragging) { - if (dragging_direction == 0) { - dragging_direction = event.motion.x; - } - - if (dragging_direction > event.motion.x || event.motion.x_root == 0) { - input_field.entry.spin (Gtk.SpinType.STEP_BACKWARD, 1); - } else { - input_field.entry.spin (Gtk.SpinType.STEP_FORWARD, 1); - } - dragging_direction = event.motion.x; - } - - return false; - } - - private void set_cursor (Gdk.CursorType cursor_type) { - var cursor = new Gdk.Cursor.for_display (Gdk.Display.get_default (), cursor_type); - get_window ().set_cursor (cursor); - } - - private void set_cursor_from_name (string name) { - var cursor = new Gdk.Cursor.from_name (Gdk.Display.get_default (), name); - get_window ().set_cursor (cursor); - } -} diff --git a/src/Widgets/MenuButton.vala b/src/Widgets/MenuButton.vala deleted file mode 100644 index 9eb861b6b..000000000 --- a/src/Widgets/MenuButton.vala +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Widgets.MenuButton : Gtk.Grid { - public Gtk.MenuButton button; - private Gtk.Label label_btn; - public ButtonImage image; - - public MenuButton (string icon_name, string name, string[]? accels = null) { - label_btn = new Gtk.Label (name); - label_btn.get_style_context ().add_class ("headerbar-label"); - - button = new Gtk.MenuButton (); - button.can_focus = false; - button.halign = Gtk.Align.CENTER; - button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - button.tooltip_markup = Granite.markup_accel_tooltip (accels, name); - - image = new ButtonImage (icon_name); - button.add (image); - - attach (button, 0, 0, 1, 1); - attach (label_btn, 0, 1, 1, 1); - - valign = Gtk.Align.CENTER; - update_label (); - - settings.changed["show-label"].connect (() => { - update_label (); - }); - } - - private void update_label () { - label_btn.visible = settings.show_label; - label_btn.no_show_all = !settings.show_label; - } -} diff --git a/src/Widgets/OpacityField.vala b/src/Widgets/OpacityField.vala deleted file mode 100644 index 3855977c9..000000000 --- a/src/Widgets/OpacityField.vala +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Widget to handle the opacity field of fills. -*/ -public class Akira.Widgets.OpacityField : Gtk.Grid { - private unowned Models.ColorModel model; - private InputField field; - - public class SignalBlocker { - private unowned OpacityField item; - - public SignalBlocker (OpacityField fill_item) { - item = fill_item; - item.block_signal += 1; - } - - ~SignalBlocker () { - item.block_signal -= 1; - } - } - - protected int block_signal = 0; - - public new bool sensitive { - get { - return field.entry.sensitive; - } - set { - field.entry.sensitive = value; - } - } - - public OpacityField (Lib.ViewCanvas canvas) { - field = new InputField (canvas, Widgets.InputField.Unit.PERCENTAGE, 5, true, true); - field.entry.value_changed.connect (on_opacity_changed); - add (field); - } - - ~OpacityField () { - field.entry.value_changed.disconnect (on_opacity_changed); - model.value_changed.disconnect (on_model_changed); - } - - public void assign (Models.ColorModel model) { - sensitive = true; - this.model = model; - model.value_changed.connect (on_model_changed); - on_model_changed (); - } - - /* - * Triggered when the value is changed by the user. - */ - private void on_opacity_changed () { - if (block_signal > 0) { - return; - } - - var new_color = model.color; - new_color.alpha = field.entry.value / 100; - model.color = new_color; - } - - /* - * Update the entry value when the model changed. - */ - private void on_model_changed () { - sensitive = !model.hidden; - if (field.entry.value / 100 == model.color.alpha) { - return; - } - - var blocker = new SignalBlocker (this); - (blocker); - field.entry.value = Math.round (model.color.alpha * 100); - } -} diff --git a/src/Widgets/RoundedColorButton.vala b/src/Widgets/RoundedColorButton.vala deleted file mode 100644 index 63a87968e..000000000 --- a/src/Widgets/RoundedColorButton.vala +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Abdallah "Abdallah-Moh" Mohammad - * Authored by: Alessandro "alecaddd" Castellani - */ - -public class Akira.Widgets.RoundedColorButton : Gtk.Grid { - public signal void set_color (string color); - - public RoundedColorButton (string color) { - var context = get_style_context (); - context.add_class ("saved-color-button"); - context.add_class ("bg-pattern"); - valign = halign = Gtk.Align.CENTER; - - var btn = new Gtk.Button (); - var btn_context = btn.get_style_context (); - btn_context.add_class ("color-item"); - btn.width_request = btn.height_request = 24; - btn.valign = btn.halign = Gtk.Align.CENTER; - btn.can_focus = false; - btn.tooltip_text = _("Set color to " + color); - - try { - var provider = new Gtk.CssProvider (); - var css = """.color-item { - background-color: %s; - border-color: shade (%s, 0.75); - }""".printf (color, color); - - provider.load_from_data (css, css.length); - btn_context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - } catch (Error e) { - warning ("Style error: %s", e.message); - } - - // Emit the set_color signal when the button is clicked. - btn.clicked.connect (() => { - set_color (color); - }); - - add (btn); - } -} diff --git a/src/Widgets/VirtualizingListBox/VirtualizingListBox.vala b/src/Widgets/VirtualizingListBox/VirtualizingListBox.vala deleted file mode 100644 index 1648c78f2..000000000 --- a/src/Widgets/VirtualizingListBox/VirtualizingListBox.vala +++ /dev/null @@ -1,965 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - * Adapted from the elementary OS Mail's VirtualizingListBox source code created - * by David Hewitt - */ - -/* - * Widget component to create a scrollable listbox view. - */ -public class VirtualizingListBox : Gtk.Container, Gtk.Scrollable { - public delegate VirtualizingListBoxRow RowFactoryMethod (GLib.Object item, VirtualizingListBoxRow? old_widget); - - public RowFactoryMethod factory_func; - - public signal void row_activated (GLib.Object row); - public signal void row_hovered (GLib.Object? row); - public signal void row_edited (VirtualizingListBoxRow? row); - - // Signal triggered when the selection of the rows changes only after a - // click event. The bool `clear` is set to true only when all rows have been - // deselected. It's up to the implementation widget to fetch the currently - // selected rows to update the UI. - public signal void row_selection_changed (bool clear = false); - - private VirtualizingListBoxModel? _model; - public VirtualizingListBoxModel? model { - get { - return _model; - } - set { - if (_model != null) { - _model.items_changed.disconnect (on_items_changed); - } - - _model = value; - _model.items_changed.connect (on_items_changed); - queue_resize (); - } - } - - private Gtk.Adjustment? _vadjustment; - public Gtk.Adjustment? vadjustment { - set { - if (_vadjustment != null) { - _vadjustment.value_changed.disconnect (on_adjustment_value_changed); - _vadjustment.notify["page-size"].disconnect (on_adjustment_page_size_changed); - } - - _vadjustment = value; - if (_vadjustment != null) { - _vadjustment.value_changed.connect (on_adjustment_value_changed); - _vadjustment.notify["page-size"].connect (on_adjustment_page_size_changed); - configure_adjustment (); - } - } - get { - return _vadjustment; - } - } - - private int bin_y { - get { - int y = 0; - if (vadjustment != null) { - y = -(int)vadjustment.value; //vala-lint=space-before-paren - } - - return y + (int)bin_y_diff; - } - } - - private bool bin_window_full { - get { - int bin_height = 0; - if (get_realized ()) { - bin_height = bin_window.get_height (); - } - - var widget_height = get_allocated_height (); - return (bin_y + bin_height > widget_height) || (shown_to - shown_from == model.get_n_items ()); - } - } - - // The default height of a row, used to trigger an initial scroll adjustment. - private double? default_widget_height = null; - - public VirtualizingListBoxRow? selected_row_widget { - get { - var item = selected_row; - - foreach (var child in current_widgets) { - if (child.model_item == item) { - return (VirtualizingListBoxRow)child; - } - } - - return null; - } - } - - public Gtk.Adjustment hadjustment { get; set; } - public Gtk.ScrollablePolicy hscroll_policy { get; set; } - public Gtk.ScrollablePolicy vscroll_policy { get; set; } - public bool activate_on_single_click { get; set; } - public bool edit_on_double_click { get; set; } - public Gtk.SelectionMode selection_mode { get; set; default = Gtk.SelectionMode.SINGLE; } - private double bin_y_diff { get; private set; } - public GLib.Object? selected_row { get; private set; } - public VirtualizingListBoxRow? edited_row { get; set; } - - private Gee.ArrayList current_widgets = new Gee.ArrayList (); - private Gee.ArrayList recycled_widgets = new Gee.ArrayList (); - private Gdk.Window bin_window; - private uint shown_to; - private uint shown_from; - private bool block; - private int last_valid_widget_height = 1; - private VirtualizingListBoxRow? active_row; - private Gtk.GestureMultiPress multipress; - private VirtualizingListBoxRow? hovered_row; - private Gtk.EventControllerMotion motion; - - static construct { - set_css_name ("list"); - } - - construct { - multipress = new Gtk.GestureMultiPress (this); - multipress.set_propagation_phase (Gtk.PropagationPhase.BUBBLE); - multipress.touch_only = false; - multipress.button = Gdk.BUTTON_PRIMARY; - multipress.pressed.connect (on_multipress_pressed); - multipress.released.connect (on_multipress_released); - - motion = new Gtk.EventControllerMotion (this); - motion.set_propagation_phase (Gtk.PropagationPhase.BUBBLE); - motion.motion.connect (on_mouse_move); - motion.leave.connect (on_mouse_leave); - } - - public override void realize () { - set_realized (true); - Gtk.Allocation allocation; - get_allocation (out allocation); - - var attr = Gdk.WindowAttr (); - attr.x = allocation.x; - attr.y = allocation.y; - attr.width = allocation.width; - attr.height = allocation.height; - attr.window_type = Gdk.WindowType.CHILD; - attr.event_mask = Gdk.EventMask.ALL_EVENTS_MASK; - attr.wclass = Gdk.WindowWindowClass.INPUT_OUTPUT; - attr.visual = get_visual (); - - Gdk.WindowAttributesType attr_types; - attr_types = Gdk.WindowAttributesType.X | Gdk.WindowAttributesType.Y | Gdk.WindowAttributesType.VISUAL; - - var window = new Gdk.Window (get_parent_window (), attr, attr_types); - - set_window (window); - register_window (window); - - attr.height = 1; - bin_window = new Gdk.Window (window, attr, attr_types); - register_window (bin_window); - bin_window.show (); - } - - public override void size_allocate (Gtk.Allocation allocation) { - bool height_changed = allocation.height != get_allocated_height (); - bool width_changed = allocation.width != get_allocated_width (); - set_allocation (allocation); - position_children (); - - if (get_realized ()) { - get_window ().move_resize (allocation.x, - allocation.y, - allocation.width, - allocation.height); - update_bin_window (); - } - - if (vadjustment != null && height_changed || width_changed) { - configure_adjustment (); - } - - if (height_changed || width_changed) { - ensure_visible_widgets (); - } - } - - public override void map () { - base.map (); - ensure_visible_widgets (); - } - - public override void remove (Gtk.Widget w) { - assert (w.get_parent () == this); - } - - public override void forall_internal (bool include_internals, Gtk.Callback callback) { - foreach (var child in current_widgets) { - callback (child); - } - } - - public override GLib.Type child_type () { - return typeof (VirtualizingListBoxRow); - } - - private VirtualizingListBoxRow? get_widget (uint index) { - var item = model.get_object (index); - if (item == null) { - return null; - } - - VirtualizingListBoxRow? old_widget = null; - if (recycled_widgets.size > 0) { - old_widget = recycled_widgets[recycled_widgets.size - 1]; - recycled_widgets.remove (old_widget); - } - - VirtualizingListBoxRow new_widget = factory_func (item, old_widget); - if (model.get_item_selected (item)) { - new_widget.set_state_flags (Gtk.StateFlags.SELECTED, false); - } else { - new_widget.unset_state_flags (Gtk.StateFlags.SELECTED); - } - - new_widget.model_item = item; - new_widget.show (); - - return new_widget; - } - - private void on_items_changed (uint position, uint removed, uint added) { - if (position >= shown_to && bin_window_full) { - if (vadjustment == null) { - queue_resize (); - } else { - configure_adjustment (); - } - - return; - } - - remove_all_widgets (); - shown_to = shown_from; - update_bin_window (); - ensure_visible_widgets (removed > 0 || added > 0); - - if (vadjustment == null) { - queue_resize (); - } - } - - private inline int widget_y (int index) { - int y = 0; - for (int i = 0; i < index; i ++) { - y += get_widget_height (current_widgets[i]); - } - - return y; - } - - private int get_widget_height (Gtk.Widget w) { - if (default_widget_height != null) { - return (int) default_widget_height; - } - - int min; - w.get_preferred_height_for_width (get_allocated_width (), out min, null); - - // Store the height of a row widget as soon as we fetch the first one. - if (default_widget_height == null) { - default_widget_height = min; - } - return min; - } - - private void position_children () { - Gtk.Allocation allocation; - Gtk.Allocation child_allocation = {0}; - - get_allocation (out allocation); - - int y = 0; - if (vadjustment != null) { - y = allocation.y; - } - - child_allocation.x = 0; - if (allocation.width > 0) { - child_allocation.width = allocation.width; - } else { - child_allocation.width = 1; - } - - int? child_width = null; - var box_width = get_allocated_width (); - - foreach (var child in current_widgets) { - // Get the height of the row widget, which we won't fetch every time - // if we already did it one. - child_allocation.height = get_widget_height (child); - - // If the child_width is not defined, get it the first time. All other - // widgets will always have the same width. - if (child_width == null) { - child.get_preferred_width_for_height (child_allocation.height, out child_width, null); - } - - child_allocation.width = int.max (child_width, box_width); - child_allocation.y = y; - child.size_allocate (child_allocation); - - y += child_allocation.height; - } - } - - private void update_bin_window (int new_bin_height = -1) { - Gtk.Allocation allocation; - get_allocation (out allocation); - - var h = (new_bin_height == -1 ? 0 : new_bin_height); - - if (new_bin_height == -1) { - foreach (var w in current_widgets) { - h += get_widget_height (w); - } - } - - if (h == 0) { - h = 1; - } - - if (h != bin_window.get_height () || allocation.width != bin_window.get_width ()) { - bin_window.move_resize (0, bin_y, allocation.width, h); - } else { - bin_window.move (0, bin_y); - } - } - - private void remove_all_widgets () { - foreach (var w in current_widgets) { - w.unparent (); - } - - recycled_widgets.add_all (current_widgets); - current_widgets.clear (); - } - - private void remove_child_internal (VirtualizingListBoxRow widget) { - current_widgets.remove (widget); - widget.set_state_flags (Gtk.StateFlags.NORMAL, true); - widget.unparent (); - recycled_widgets.add (widget); - } - - private void on_adjustment_value_changed () { - ensure_visible_widgets (); - } - - private void on_adjustment_page_size_changed () { - if (!get_mapped ()) { - return; - } - - double max_value = vadjustment.upper - vadjustment.page_size; - - if (vadjustment.value > max_value) { - set_value (max_value); - } - - configure_adjustment (); - } - - private void insert_child_internal (VirtualizingListBoxRow widget, int index) { - widget.set_parent_window (bin_window); - widget.set_parent (this); - current_widgets.insert (index, widget); - } - - private bool remove_top_widgets (ref int bin_height) { - bool removed = false; - for (int i = 0; i < current_widgets.size; i++) { - var w = current_widgets[i]; - int w_height = get_widget_height (w); - if (bin_y + widget_y (i) + w_height < 0) { - bin_y_diff += w_height; - bin_height -= w_height; - remove_child_internal (w); - shown_from++; - removed = true; - } else { - break; - } - } - - return removed; - } - - private bool insert_top_widgets (ref int bin_height) { - bool added = false; - while (shown_from > 0 && bin_y >= 0) { - shown_from--; - var new_widget = get_widget (shown_from); - if (new_widget == null) { - continue; - } - - insert_child_internal (new_widget, 0); - var min = get_widget_height (new_widget); - - bin_y_diff -= min; - bin_height += min; - added = true; - } - - if (bin_y > 0) { - bin_y_diff = 0; - block = true; - set_value (0.0); - block = false; - } - - return added; - } - - private bool remove_bottom_widgets (ref int bin_height) { - for (int i = current_widgets.size - 1; i >= 0; i--) { - var w = current_widgets[i]; - - int widget_y = bin_y + widget_y (i); - if (widget_y > get_allocated_height ()) { - int w_height = get_widget_height (w); - remove_child_internal (w); - bin_height -= w_height; - shown_to--; - } else { - break; - } - } - - return false; - } - - private bool insert_bottom_widgets (ref int bin_height) { - bool added = false; - while (bin_y + bin_height <= get_allocated_height () && shown_to < model.get_n_items ()) { - var new_widget = get_widget (shown_to); - if (new_widget == null) { - shown_to++; - continue; - } - - insert_child_internal (new_widget, current_widgets.size); - - int min = get_widget_height (new_widget); - bin_height += min; - added = true; - shown_to ++; - } - - return added; - } - - private void ensure_visible_widgets (bool model_changed = false) { - if (!get_mapped () || model == null || block) { - return; - } - - var widget_height = get_allocated_height (); - var bin_height = bin_window.get_height (); - if (bin_height == 1) { - bin_height = 0; - } - - if (bin_y + bin_height < 0 || bin_y >= widget_height) { - int estimated_widget_height = estimated_widget_height (); - - remove_all_widgets (); - bin_height = 0; - - double percentage = vadjustment.value / vadjustment.upper; - uint top_widget_index = (uint)(model.get_n_items () * percentage); - - if (top_widget_index > model.get_n_items ()) { - shown_to = model.get_n_items (); - shown_from = model.get_n_items (); - bin_y_diff = vadjustment.value + vadjustment.page_size; - } else { - shown_from = top_widget_index; - shown_to = top_widget_index; - bin_y_diff = top_widget_index * estimated_widget_height; - } - } - - var top_removed = remove_top_widgets (ref bin_height); - var top_added = insert_top_widgets (ref bin_height); - var bottom_removed = remove_bottom_widgets (ref bin_height); - var bottom_added = insert_bottom_widgets (ref bin_height); - - var widgets_changed = top_removed || top_added || bottom_removed || bottom_added || model_changed; - - if (vadjustment != null && widgets_changed) { - uint top_part; - uint widget_part; - uint bottom_part; - - uint new_upper = estimated_list_height (out top_part, out bottom_part, out widget_part); - - if (new_upper > _vadjustment.upper) { - bin_y_diff = double.max (top_part, vadjustment.value); - } else { - bin_y_diff = double.min (top_part, vadjustment.value); - } - - configure_adjustment (); - - set_value (bin_y_diff - bin_y); - if (vadjustment.value < bin_y_diff) { - set_value (bin_y_diff); - } - - if (bin_y > 0) { - bin_y_diff = vadjustment.value; - } - } - - configure_adjustment (); - update_bin_window (bin_height); - position_children (); - queue_draw (); - } - - private int estimated_widget_height () { - int average_widget_height = 0; - int used_widgets = 0; - - foreach (var w in current_widgets) { - if (w.visible) { - average_widget_height += get_widget_height (w); - used_widgets ++; - } - } - - if (used_widgets > 0) { - average_widget_height /= used_widgets; - } else { - average_widget_height = last_valid_widget_height; - } - - last_valid_widget_height = average_widget_height; - - return average_widget_height; - } - - private void configure_adjustment () { - int widget_height = get_allocated_height (); - uint list_height = estimated_list_height (); - - if ((int)vadjustment.upper != uint.max (list_height, widget_height)) { - vadjustment.upper = uint.max (list_height, widget_height); - } else if (list_height == 0) { - vadjustment.upper = widget_height; - } - - if ((int)vadjustment.page_size != widget_height) { - vadjustment.page_size = widget_height; - } - - if (vadjustment.value > vadjustment.upper - vadjustment.page_size) { - double v = vadjustment.upper - vadjustment.page_size; - set_value (v); - } - } - - private void set_value (double v) { - if (v == vadjustment.value) { - return; - } - - block = true; - vadjustment.value = v; - block = false; - } - - private uint estimated_list_height (out uint top = null, out uint bottom = null, out uint visible_widgets = null) { - if (model == null) { - top = 0; - bottom = 0; - visible_widgets = 0; - return 0; - } - - int widget_height = estimated_widget_height (); - uint top_widgets = shown_from; - uint bottom_widgets = model.get_n_items () - shown_to; - - int exact_height = 0; - foreach (var w in current_widgets) { - int h = get_widget_height (w); - exact_height += h; - } - - top = top_widgets * widget_height; - bottom = bottom_widgets * widget_height; - visible_widgets = exact_height; - - uint h = top + bottom + visible_widgets; - return h; - } - - public unowned VirtualizingListBoxRow? get_row_at_y (int y) { - Gtk.Allocation alloc; - foreach (var row in current_widgets) { - row.get_allocation (out alloc); - if (y >= alloc.y + bin_y && y <= alloc.y + bin_y + alloc.height) { - unowned VirtualizingListBoxRow return_value = row; - return return_value; - } - } - - return null; - } - - private void on_multipress_pressed (int n_press, double x, double y) { - active_row = null; - var row = get_row_at_y ((int) y); - if (row != null && row.sensitive && row.selectable) { - active_row = row; - row.set_state_flags (Gtk.StateFlags.ACTIVE, false); - - if (n_press == 2 && !activate_on_single_click) { - row_activated (row.model_item); - } - - if (n_press == 2 && edit_on_double_click) { - row_edited (row); - } - } - } - - private void get_current_selection_modifiers (out bool modify, out bool extend) { - Gdk.ModifierType state; - Gdk.ModifierType mask; - - modify = false; - extend = false; - - if (Gtk.get_current_event_state (out state)) { - mask = get_modifier_mask (Gdk.ModifierIntent.MODIFY_SELECTION); - if ((state & mask) == mask) { - modify = true; - } - - mask = get_modifier_mask (Gdk.ModifierIntent.EXTEND_SELECTION); - if ((state & mask) == mask) { - extend = true; - } - } - } - - private void on_multipress_released (int n_press, double x, double y) { - if (active_row == null) { - unselect_all_internal (); - row_selection_changed (true); - return; - } - - active_row.unset_state_flags (Gtk.StateFlags.ACTIVE); - - bool modify, extend; - get_current_selection_modifiers (out modify, out extend); - var sequence = multipress.get_current_sequence (); - var event = multipress.get_last_event (sequence); - var source = event.get_source_device ().get_source (); - - if (source == Gdk.InputSource.TOUCHSCREEN) { - modify = !modify; - } - - update_selection (active_row, modify, extend); - row_selection_changed (); - if (edited_row != null && edited_row.model_item != selected_row) { - row_edited (null); - } - } - - private void update_selection (VirtualizingListBoxRow row, bool modify, bool extend) { - if (selection_mode == Gtk.SelectionMode.NONE || !row.selectable) { - return; - } - - if (selection_mode == Gtk.SelectionMode.BROWSE) { - select_row (row); - } else if (selection_mode == Gtk.SelectionMode.SINGLE) { - var was_selected = model.get_item_selected (row.model_item); - unselect_all_internal (); - var select = modify ? !was_selected : true; - model.set_item_selected (row.model_item, select); - selected_row = select ? row.model_item : null; - if (select) { - row.set_state_flags (Gtk.StateFlags.SELECTED, false); - } else { - row.unset_state_flags (Gtk.StateFlags.SELECTED); - } - } else { - if (extend) { - var selected = selected_row; - unselect_all_internal (); - if (selected == null) { - select_row (row); - } else { - select_all_between (selected, row.model_item, false); - } - } else { - if (modify) { - var selected = model.get_item_selected (row.model_item); - if (selected) { - row.unset_state_flags (Gtk.StateFlags.SELECTED); - } else { - row.set_state_flags (Gtk.StateFlags.SELECTED, false); - } - - model.set_item_selected (row.model_item, !selected); - } else { - unselect_all_internal (); - select_row (row); - } - } - } - } - - private void select_all_between (GLib.Object from, GLib.Object to, bool modify) { - var items = model.get_items_between (from, to); - foreach (var item in items) { - model.set_item_selected (item, true); - } - - foreach (VirtualizingListBoxRow row in current_widgets) { - if (row.model_item in items) { - row.set_state_flags (Gtk.StateFlags.SELECTED, false); - } - } - } - - protected void select_row_at_index (int index) { - // If multiple rows are being selected, just get the new widget row - // without scrolling the listbox and ensure its visibility. - var row = ensure_index_visible (index); - - if (row != null) { - select_and_activate (row); - } - } - - private void select_and_activate (VirtualizingListBoxRow row) { - select_row (row); - row_activated (row.model_item); - } - - private VirtualizingListBoxRow? ensure_index_visible (int index) { - var index_max = model.get_n_items () - 1; - - if (index < 0) { - return null; - } - - if (index > index_max) { - return null; - } - - if (index == 0) { - set_value (0.0); - ensure_visible_widgets (); - foreach (VirtualizingListBoxRow row in current_widgets) { - if (index == model.get_index_of (row.model_item)) { - return row; - } - } - } - - if (index == index_max) { - set_value (vadjustment.upper); - ensure_visible_widgets (); - foreach (VirtualizingListBoxRow row in current_widgets) { - if (index == model.get_index_of (row.model_item)) { - return row; - } - } - } - - if (index <= shown_from) { - var diff = ((shown_from - index) + 1) * get_widget_height (current_widgets[0]); - vadjustment.value -= diff; - } else if (index + 1 >= shown_to) { - var diff = ((index - shown_from) - 1) * get_widget_height (current_widgets[0]); - vadjustment.value += diff; - } - - foreach (VirtualizingListBoxRow row in current_widgets) { - if (index == model.get_index_of (row.model_item)) { - return row; - } - } - - return null; - } - - protected void select_row (VirtualizingListBoxRow row) { - if (model.get_item_selected (row) || selection_mode == Gtk.SelectionMode.NONE) { - return; - } - - if (selection_mode != Gtk.SelectionMode.MULTIPLE) { - unselect_all_internal (); - } - - model.set_item_selected (row.model_item, true); - row.set_state_flags (Gtk.StateFlags.SELECTED, false); - selected_row = row.model_item; - } - - protected void unselect_all () { - unselect_all_internal (); - } - - private bool unselect_all_internal () { - if (selection_mode == Gtk.SelectionMode.NONE) { - return false; - } - - foreach (var row in current_widgets) { - row.unset_state_flags (Gtk.StateFlags.SELECTED); - } - - model.unselect_all (); - selected_row = null; - - return true; - } - - public override bool focus (Gtk.DirectionType direction) { - var focus_child = get_focus_child () as VirtualizingListBoxRow; - int next_focus_index = -1; - - if (focus_child != null && focus_child.model_item != null) { - if (focus_child.child_focus (direction)) { - return true; - } - - if (direction == Gtk.DirectionType.UP || direction == Gtk.DirectionType.TAB_BACKWARD) { - next_focus_index = model.get_index_of_item_before (focus_child.model_item); - } else if (direction == Gtk.DirectionType.DOWN || direction == Gtk.DirectionType.TAB_FORWARD) { - next_focus_index = model.get_index_of_item_after (focus_child.model_item); - } - } else { - if (direction == Gtk.DirectionType.UP || direction == Gtk.DirectionType.TAB_BACKWARD) { - next_focus_index = model.get_index_of (focus_child.model_item); - if (next_focus_index == -1) { - next_focus_index = (int)model.get_n_items () - 1; - } - } else { - next_focus_index = model.get_index_of (focus_child); - if (next_focus_index == -1) { - next_focus_index = 0; - } - } - } - - if (next_focus_index == -1) { - if (keynav_failed (direction)) { - return true; - } - - return false; - } - - var widget = ensure_index_visible (next_focus_index); - if (widget != null) { - update_selection (widget, false, false); - return true; - } - - return false; - } - - public bool get_border (out Gtk.Border border) { - border = Gtk.Border (); - return false; - } - - public Gee.HashSet get_selected_rows () { - return model.get_selected_rows (); - } - - private void on_mouse_move (double x, double y) { - var row = get_row_at_y ((int) y); - - // No need to trigger any update if we're still hovering over the same - // row widget. - if (row != null && row == hovered_row) { - return; - } - - if (hovered_row != null) { - hovered_row.unset_state_flags (Gtk.StateFlags.PRELIGHT); - hovered_row = null; - row_hovered (null); - } - - if (row != null) { - row.set_state_flags (Gtk.StateFlags.PRELIGHT, false); - row_hovered (row.model_item); - hovered_row = row; - } - } - - // TODO: Fix this as it never gets triggered by the motion leave. - protected void on_mouse_leave () { - if (hovered_row != null) { - on_mouse_leave_internal (); - row_hovered (null); - } - } - - /* - * Same as on_mouse_leave, but it doesn't trigger the hovered signal. - */ - protected void on_mouse_leave_internal () { - if (hovered_row != null) { - hovered_row.unset_state_flags (Gtk.StateFlags.PRELIGHT); - hovered_row = null; - } - } - - protected void set_hover_on_row_from_model (GLib.Object model) { - foreach (VirtualizingListBoxRow row in current_widgets) { - if (model == row.model_item) { - row.set_state_flags (Gtk.StateFlags.PRELIGHT, false); - hovered_row = row; - } - } - } -} diff --git a/src/Widgets/VirtualizingListBox/VirtualizingListBoxModel.vala b/src/Widgets/VirtualizingListBox/VirtualizingListBoxModel.vala deleted file mode 100644 index 554be7592..000000000 --- a/src/Widgets/VirtualizingListBox/VirtualizingListBoxModel.vala +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - * Adapted from the elementary OS Mail's VirtualizingListBox source code created - * by David Hewitt - */ - -/* - * List model to manage all the rows added to the virtual listbox. - */ -public abstract class VirtualizingListBoxModel : GLib.ListModel, GLib.Object { - private Gee.HashSet selected_rows = new Gee.HashSet (); - - public GLib.Type get_item_type () { - return typeof (GLib.Object); - } - - public abstract uint get_n_items (); - public abstract GLib.Object? get_item (uint index); - public abstract GLib.Object? get_item_unfiltered (uint index); - - public void unselect_all () { - selected_rows.clear (); - } - - public void set_item_selected (GLib.Object item, bool selected) { - if (!selected) { - selected_rows.remove (item); - } else { - selected_rows.add (item); - } - } - - public bool get_item_selected (GLib.Object item) { - return selected_rows.contains (item); - } - - public Gee.ArrayList get_items_between (GLib.Object from, GLib.Object to) { - var items = new Gee.ArrayList (); - var start_found = false; - var ignore_next_break = false; - var length = get_n_items (); - for (int i = 0; i < length; i++) { - var item = get_item (i); - if ((item == from || item == to) && !start_found) { - start_found = true; - ignore_next_break = true; - } else if (!start_found) { - continue; - } - - if (item != null) { - items.add (item); - } - - if ((item == to || item == from) && !ignore_next_break) { - break; - } - - ignore_next_break = false; - } - - return items; - } - - public int get_index_of (GLib.Object? item) { - if (item == null) { - return -1; - } - - var length = get_n_items (); - for (int i = 0; i < length; i++) { - if (item == get_item (i)) { - return i; - } - } - - return -1; - } - - public int get_index_of_unfiltered (GLib.Object? item) { - if (item == null) { - return -1; - } - - var length = get_n_items (); - for (int i = 0; i < length; i++) { - if (item == get_item_unfiltered (i)) { - return i; - } - } - - return -1; - } - - public int get_index_of_item_before (GLib.Object item) { - if (item == get_item (0)) { - return -1; - } - - var length = get_n_items (); - for (int i = 1; i < length; i++) { - if (get_item (i) == item) { - if (get_item (i - 1) != null) { - return i - 1; - } - } - } - - return -1; - } - - public int get_index_of_item_after (GLib.Object item) { - if (item == get_item (get_n_items () - 1)) { - return -1; - } - - var length = get_n_items (); - for (int i = 0; i < length - 1; i++) { - if (get_item (i) == item) { - if (get_item (i + 1) != null) { - return i + 1; - } - } - } - - return -1; - } - - public Gee.HashSet get_selected_rows () { - return selected_rows; - } -} diff --git a/src/Widgets/VirtualizingListBox/VirtualizingListBoxRow.vala b/src/Widgets/VirtualizingListBox/VirtualizingListBoxRow.vala deleted file mode 100644 index 02a314420..000000000 --- a/src/Widgets/VirtualizingListBox/VirtualizingListBoxRow.vala +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - * Adapted from the elementary OS Mail's VirtualizingListBox source code created - * by David Hewitt - */ - -/* - * Widget component to create a simple listbox row. - */ -public class VirtualizingListBoxRow : Gtk.Bin { - public bool selectable { get; set; default = true; } - public weak GLib.Object model_item { get; set; } - - static construct { - set_css_name ("row"); - } - - construct { - can_focus = true; - set_redraw_on_allocate (true); - - get_style_context ().add_class ("activatable"); - } - - public override bool draw (Cairo.Context ct) { - var sc = this.get_style_context (); - // TODO: Replace this with fixed height and the width of the layers panel. - Gtk.Allocation alloc; - this.get_allocation (out alloc); - - sc.render_background (ct, 0, 0, alloc.width, alloc.height); - sc.render_frame (ct, 0, 0, alloc.width, alloc.height); - - return base.draw (ct); - } - - /* - * Virtual methods an implementation of this class can override in case it - * needs to trigger an edit state and change the UI. - */ - public virtual void edit () {} - public virtual void edit_end () {} -} diff --git a/src/Widgets/VirtualizingListBox/VirtualizingSimpleListBox.vala b/src/Widgets/VirtualizingListBox/VirtualizingSimpleListBox.vala deleted file mode 100644 index b7246b139..000000000 --- a/src/Widgets/VirtualizingListBox/VirtualizingSimpleListBox.vala +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (c) 2022 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -/* - * Widget component to create a simple non scrollable listbox view with a - * factory method to assign a model to a reusable widget. - */ -public class VirtualizingSimpleListBox : Gtk.Container { - public delegate VirtualizingListBoxRow RowFactoryMethod (GLib.Object item, VirtualizingListBoxRow? old_widget); - - public RowFactoryMethod factory_func; - - private VirtualizingListBoxModel? _model; - public VirtualizingListBoxModel? model { - get { - return _model; - } - set { - if (_model != null) { - _model.items_changed.disconnect (on_items_changed); - } - - _model = value; - _model.items_changed.connect (on_items_changed); - queue_resize (); - } - } - - // The default height of a row, used to trigger an initial scroll adjustment. - private double? default_widget_height = null; - - private Gee.ArrayList current_widgets = new Gee.ArrayList (); - private Gee.ArrayList recycled_widgets = new Gee.ArrayList (); - private Gdk.Window bin_window; - private uint shown; - - static construct { - set_css_name ("list"); - } - - construct { - margin_top = margin_bottom = 6; - } - - public override void realize () { - set_realized (true); - Gtk.Allocation allocation; - get_allocation (out allocation); - - var attr = Gdk.WindowAttr (); - attr.x = allocation.x; - attr.y = allocation.y; - attr.width = allocation.width; - attr.height = allocation.height; - attr.window_type = Gdk.WindowType.CHILD; - attr.event_mask = Gdk.EventMask.ALL_EVENTS_MASK; - attr.wclass = Gdk.WindowWindowClass.INPUT_OUTPUT; - attr.visual = get_visual (); - - Gdk.WindowAttributesType attr_types; - attr_types = Gdk.WindowAttributesType.X | Gdk.WindowAttributesType.Y | Gdk.WindowAttributesType.VISUAL; - - var window = new Gdk.Window (get_parent_window (), attr, attr_types); - - set_window (window); - register_window (window); - - attr.height = 1; - vexpand = false; - bin_window = new Gdk.Window (window, attr, attr_types); - register_window (bin_window); - bin_window.show (); - } - - public override void size_allocate (Gtk.Allocation allocation) { - set_allocation (allocation); - position_children (); - - if (get_realized ()) { - get_window ().move_resize (allocation.x, allocation.y, allocation.width, allocation.height); - update_bin_window (); - } - } - - public override void map () { - base.map (); - ensure_visible_widgets (); - } - - public override void remove (Gtk.Widget w) { - assert (w.get_parent () == this); - } - - public override void forall_internal (bool include_internals, Gtk.Callback callback) { - foreach (var child in current_widgets) { - callback (child); - } - } - - public override GLib.Type child_type () { - return typeof (VirtualizingListBoxRow); - } - - private VirtualizingListBoxRow? get_widget (uint index) { - var item = model.get_object (index); - if (item == null) { - return null; - } - - VirtualizingListBoxRow? old_widget = null; - if (recycled_widgets.size > 0) { - old_widget = recycled_widgets[recycled_widgets.size - 1]; - recycled_widgets.remove (old_widget); - } - - VirtualizingListBoxRow new_widget = factory_func (item, old_widget); - if (model.get_item_selected (item)) { - new_widget.set_state_flags (Gtk.StateFlags.SELECTED, false); - } else { - new_widget.unset_state_flags (Gtk.StateFlags.SELECTED); - } - - new_widget.model_item = item; - new_widget.show (); - - return new_widget; - } - - private void on_items_changed (uint position, uint removed, uint added) { - remove_all_widgets (); - shown = 0; - update_bin_window (); - ensure_visible_widgets (); - queue_resize (); - } - - private int get_widget_height (Gtk.Widget w) { - if (default_widget_height != null) { - return (int) default_widget_height; - } - - int min; - w.get_preferred_height_for_width (get_allocated_width (), out min, null); - - // Store the height of a row widget as soon as we fetch the first one. - if (default_widget_height == null) { - default_widget_height = min; - } - return min; - } - - private void position_children () { - Gtk.Allocation allocation; - Gtk.Allocation child_allocation = {0}; - - get_allocation (out allocation); - - int y = 0; - child_allocation.x = 0; - if (allocation.width > 0) { - child_allocation.width = allocation.width; - } else { - child_allocation.width = 1; - } - - int? child_width = null; - var box_width = get_allocated_width (); - - foreach (var child in current_widgets) { - // Get the height of the row widget, which we won't fetch every time - // if we already did it one. - child_allocation.height = get_widget_height (child); - - // If the child_width is not defined, get it the first time. All other - // widgets will always have the same width. - if (child_width == null) { - child.get_preferred_width_for_height (child_allocation.height, out child_width, null); - } - - child_allocation.width = int.max (child_width, box_width); - child_allocation.y = y; - child.size_allocate (child_allocation); - - y += child_allocation.height; - } - } - - private void update_bin_window (int new_bin_height = -1) { - Gtk.Allocation allocation; - get_allocation (out allocation); - - var h = 1; - foreach (var w in current_widgets) { - h += get_widget_height (w); - } - - bin_window.move_resize (0, 0, allocation.width, h); - height_request = h; - } - - private void remove_all_widgets () { - foreach (var w in current_widgets) { - w.unparent (); - } - - recycled_widgets.add_all (current_widgets); - current_widgets.clear (); - } - - private void insert_child_internal (VirtualizingListBoxRow widget, int index) { - widget.set_parent_window (bin_window); - widget.set_parent (this); - current_widgets.insert (index, widget); - } - - private void insert_widgets (ref int bin_height) { - while (shown < model.get_n_items ()) { - var new_widget = get_widget (shown); - if (new_widget == null) { - shown++; - continue; - } - - insert_child_internal (new_widget, current_widgets.size); - - int min = get_widget_height (new_widget); - bin_height += min; - shown++; - } - } - - private void ensure_visible_widgets () { - if (!get_mapped () || model == null) { - return; - } - - var bin_height = bin_window.get_height (); - insert_widgets (ref bin_height); - update_bin_window (bin_height); - position_children (); - queue_draw (); - } - - public unowned VirtualizingListBoxRow? get_row_at_y (int y) { - Gtk.Allocation alloc; - foreach (var row in current_widgets) { - row.get_allocation (out alloc); - if (y >= alloc.y && y <= alloc.y + alloc.height) { - unowned VirtualizingListBoxRow return_value = row; - return return_value; - } - } - - return null; - } - - public bool get_border (out Gtk.Border border) { - border = Gtk.Border (); - return false; - } - - public Gee.HashSet get_selected_rows () { - return model.get_selected_rows (); - } -} diff --git a/src/Widgets/ZoomButton.vala b/src/Widgets/ZoomButton.vala deleted file mode 100644 index a0e9b24c9..000000000 --- a/src/Widgets/ZoomButton.vala +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Alessandro "Alecaddd" Castellani - */ - -public class Akira.Widgets.ZoomButton : Gtk.Grid { - public weak Akira.Window window { get; set construct; } - - private Gtk.Label label_btn; - private Gtk.Button zoom_out_button; - private Gtk.Button zoom_in_button; - private Gtk.Button zoom_default_button; - private Gtk.Popover zoom_popover; - private Gtk.Entry zoom_input; - - public ZoomButton (Akira.Window window) { - this.window = window; - - // Grid specific attributes. - get_style_context ().add_class (Gtk.STYLE_CLASS_LINKED); - get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - valign = Gtk.Align.CENTER; - column_homogeneous = false; - width_request = 140; - hexpand = false; - - // Zoom out button. - zoom_out_button = new Gtk.Button.from_icon_name ("zoom-out-symbolic", Gtk.IconSize.MENU); - zoom_out_button.get_style_context ().add_class ("button-zoom"); - zoom_out_button.get_style_context ().add_class ("button-zoom-start"); - zoom_out_button.can_focus = false; - zoom_out_button.tooltip_markup = Granite.markup_accel_tooltip ({"minus"}, _("Zoom Out")); - - // Default centered zoom button. - zoom_default_button = new Gtk.Button.with_label ("100%"); - zoom_default_button.hexpand = true; - zoom_default_button.can_focus = false; - zoom_default_button.tooltip_markup = Granite.markup_accel_tooltip ( - {"0"}, - _("Reset Zoom. Ctrl+click to input value") - ); - - // Zoom popover containing the input field. - zoom_popover = new Gtk.Popover (zoom_default_button); - zoom_popover.position = Gtk.PositionType.BOTTOM; - - // The zoom input field. - zoom_input = new Gtk.Entry (); - zoom_input.text = "100"; - zoom_input.input_purpose = Gtk.InputPurpose.NUMBER; - zoom_input.get_style_context ().add_class ("input-zoom"); - zoom_input.get_style_context ().add_class ("input-icon-right"); - zoom_input.secondary_icon_name = "input-percentage-symbolic"; - zoom_input.secondary_icon_sensitive = false; - zoom_input.secondary_icon_activatable = false; - zoom_input.xalign = 1.0f; - zoom_input.width_chars = 8; - zoom_input.show_all (); - zoom_popover.add (zoom_input); - - // Zoom in button. - zoom_in_button = new Gtk.Button.from_icon_name ("zoom-in-symbolic", Gtk.IconSize.MENU); - zoom_in_button.get_style_context ().add_class ("button-zoom"); - zoom_in_button.get_style_context ().add_class ("button-zoom-end"); - zoom_in_button.can_focus = false; - zoom_in_button.tooltip_markup = Granite.markup_accel_tooltip ({"plus"}, _("Zoom In")); - - attach (zoom_out_button, 0, 0, 1, 1); - attach (zoom_default_button, 1, 0, 1, 1); - attach (zoom_in_button, 2, 0, 1, 1); - - // Headerbar button label. - label_btn = new Gtk.Label (_("Zoom")); - label_btn.get_style_context ().add_class ("headerbar-label"); - label_btn.margin_top = 4; - - attach (label_btn, 0, 1, 3, 1); - - // Mouse click signals. - zoom_out_button.clicked.connect (zoom_out); - zoom_default_button.button_press_event.connect (zoom_reset); - zoom_in_button.clicked.connect (zoom_in); - - // Keyboard press signals. - zoom_input.key_press_event.connect (handle_key_press); - zoom_input.focus_in_event.connect (handle_focus_in); - zoom_input.focus_out_event.connect (handle_focus_out); - - // Bind the visibility of the button label to the gsetting attribute. - settings.bind ("show-label", label_btn, "visible", SettingsBindFlags.DEFAULT); - settings.bind ("show-label", label_btn, "no-show-all", SettingsBindFlags.INVERT_BOOLEAN); - - // Event listeners. - window.event_bus.zoom_changed.connect (on_zoom_changed); - } - - /* - * Decrease the canvas scale by 50%. - */ - public void zoom_out () { - window.event_bus.adjust_zoom (-0.5, false, null); - } - - /* - * Increase the canvas scale by 50%. - */ - public void zoom_in () { - window.event_bus.adjust_zoom (0.5, false, null); - } - - /* - * Reset the zoom to 100%, or reveal a popover with the numeric - * input field for manual inputing if the user pressed the CTRL key - * while clicking on the button. - */ - public bool zoom_reset (Gdk.EventButton event) { - // If the CTRL key was pressed, show the popover with the input field. - if (window.main_window.main_view_canvas.canvas.ctrl_is_pressed) { - zoom_popover.popup (); - return true; - } - - // Otherwise reset the zoom to 100%. - zoom_in_button.sensitive = true; - zoom_out_button.sensitive = true; - window.event_bus.adjust_zoom (1.0, true, null); - - return true; - } - - /* - * Update the button and the input field when the canvas scale is changed. - */ - private void on_zoom_changed (double scale) { - var perc_scale = scale * 100; - zoom_default_button.label = "%.0f%%".printf (perc_scale); - zoom_input.text = perc_scale.to_string (); - } - - /* - * Key press events on the input field. - */ - private bool handle_key_press (Gdk.EventKey event) { - // Arrow UP pressed, increase value by 1. - if (event.keyval == Gdk.Key.Up) { - window.event_bus.adjust_zoom (0.1, true, null); - return true; - } - - // Arrow DOWN pressed, decreased value by 1. - if (event.keyval == Gdk.Key.Down) { - window.event_bus.adjust_zoom (-0.1, true, null); - return true; - } - - // Enter pressed, update the scale and move the focus back to the canvas. - if (event.keyval == Gdk.Key.Return) { - var text_value = double.parse (zoom_input.text) / 100; - window.event_bus.adjust_zoom (text_value, true, null); - window.event_bus.set_focus_on_canvas (); - return true; - } - - // Escape pressed, reset to the old value held by the zoom button. - if (event.keyval == Gdk.Key.Escape) { - zoom_input.text = zoom_default_button.label.replace ("%", ""); - window.event_bus.set_focus_on_canvas (); - return true; - } - - // Only allow arrows, delete, and backspace keys other than numbers. - if ( - event.keyval == Gdk.Key.Left || - event.keyval == Gdk.Key.Right || - event.keyval == Gdk.Key.Delete || - event.keyval == Gdk.Key.BackSpace - ) { - return false; - } - - // Gtk.Entry doesn't currently support the "number only" filter, so - // we need to intercept the keypress and prevent typing if the value - // is not a number, or the CTRL modifier is not pressed. - if ( - !(event.keyval >= Gdk.Key.@0 && event.keyval <= Gdk.Key.@9) && - !window.main_window.main_view_canvas.canvas.ctrl_is_pressed - ) { - return true; - } - - return false; - } - - /* - * When the input field gains focus. - */ - private bool handle_focus_in (Gdk.EventFocus event) { - window.event_bus.disconnect_typing_accel (); - return false; - } - - /* - * When the input field loses focus. - */ - private bool handle_focus_out (Gdk.EventFocus event) { - window.event_bus.connect_typing_accel (); - return false; - } -} diff --git a/src/Window.vala b/src/Window.vala deleted file mode 100644 index ffdef06be..000000000 --- a/src/Window.vala +++ /dev/null @@ -1,196 +0,0 @@ -/* -* Copyright (c) 2019-2020 Alecaddd (https://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.Window : Gtk.ApplicationWindow { - public FileFormat.AkiraFile? akira_file = null; - public FileFormat.FileManager file_manager; - - public weak Akira.Application app { get; construct; } - public Akira.Services.EventBus event_bus; - - public Akira.Services.ActionManager action_manager; - public Akira.Layouts.HeaderBar headerbar; - public Akira.Layouts.MainWindow main_window; - public Akira.Utils.Dialogs dialogs; - - public SimpleActionGroup actions { get; construct; } - public Gtk.AccelGroup accel_group { get; construct; } - - public bool edited { get; set; default = false; } - - public Window (Akira.Application akira_app) { - Object ( - application: akira_app, - app: akira_app, - icon_name: "com.github.akiraux.akira" - ); - } - - construct { - accel_group = new Gtk.AccelGroup (); - add_accel_group (accel_group); - - event_bus = new Akira.Services.EventBus (); - action_manager = new Akira.Services.ActionManager (app, this); - - headerbar = new Akira.Layouts.HeaderBar (this); - file_manager = new Akira.FileFormat.FileManager (this); - main_window = new Akira.Layouts.MainWindow (this); - dialogs = new Akira.Utils.Dialogs (this); - - build_ui (); - - move (settings.pos_x, settings.pos_y); - - show_app (); - - // Let the canvas grab the focus after the app is visible. - main_window.focus_canvas (); - - event_bus.file_edited.connect (on_file_edited); - event_bus.file_saved.connect (on_file_saved); - } - - private void build_ui () { - set_titlebar (headerbar); - set_border_width (0); - if (Constants.PROFILE == "development") { - headerbar.get_style_context ().add_class ("devel"); - } - - delete_event.connect ((e) => { - return before_destroy (); - }); - - add (main_window); - } - - /* - * Restore previously saved size and panels positions. - */ - private void apply_user_settings () { - resize (settings.window_width, settings.window_height); - main_window.pane.position = settings.left_paned; - main_window.pane2.position = settings.right_paned; - } - - private void on_file_edited () { - edited = true; - } - - private void on_file_saved () { - edited = false; - } - - public bool before_destroy () { - update_status (); - - if (!edited) { - close_current_file (); - app.get_active_window ().destroy (); - on_destroy (); - } - - if (edited) { - var dialog = dialogs.message_dialog ( - _("Are you sure you want to quit?"), - _("All unsaved data will be lost and impossible to recover."), - "system-shutdown", - _("Quit without saving!"), - _("Save file") - ); - - dialog.show_all (); - - dialog.response.connect ((id) => { - switch (id) { - case Gtk.ResponseType.ACCEPT: - dialog.destroy (); - close_current_file (); - app.get_active_window ().destroy (); - on_destroy (); - break; - case 2: - dialog.destroy (); - file_manager.save_file (); - break; - default: - dialog.destroy (); - break; - } - }); - - dialog.run (); - } - - return true; - } - - public void on_destroy () { - uint length = app.windows.length (); - - if (length == 0) { - app.quit (); - } - } - - private void update_status () { - int width, height, x, y; - - get_size (out width, out height); - get_position (out x, out y); - - settings.pos_x = x; - settings.pos_y = y; - settings.window_width = width; - settings.window_height = height; - settings.left_paned = main_window.pane.get_position (); - settings.right_paned = main_window.pane2.get_position (); - } - - public void show_app () { - apply_user_settings (); - show_all (); - show (); - present (); - } - - public void open_file (File file) { - akira_file = new FileFormat.AkiraFile (file, this); - - akira_file.prepare (); - akira_file.load_file (); - } - - public void save_new_file (File file, bool overwrite = false) { - akira_file = new FileFormat.AkiraFile (file, this); - akira_file.overwrite = overwrite; - - akira_file.prepare (); - akira_file.save_file (); - } - - private void close_current_file () { - if (akira_file != null) { - akira_file.close (); - } - } -} diff --git a/src/config.vala.in b/src/config.vala.in deleted file mode 100644 index 534329acf..000000000 --- a/src/config.vala.in +++ /dev/null @@ -1,13 +0,0 @@ -namespace Constants { - public const string DATADIR = "@DATADIR@"; - public const string PKGDATADIR = "@PKGDATADIR@"; - public const string GETTEXT_PACKAGE = "@GETTEXT_PACKAGE@"; - public const string PROJECT_NAME = "@PROJECT_NAME@"; - public const string VERSION = "@VERSION@"; - public const string INSTALL_PREFIX = "@PREFIX@"; - public const string APP_ID = "@APP_ID@"; - public const string PROFILE = "@PROFILE@"; - - public const string APP_NAME = "Akira"; - public const string TERMINAL_NAME = "akira"; -} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 000000000..24af03e87 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,43 @@ +/** + * This file is part of Akira. + * + * Copyright (c) 2024 Alessandro Castellani + * + * Akira is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * Akira is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Akira. If not, see . + */ +use gtk::prelude::*; +use gtk::{glib, Application}; + +mod window; + +use self::window::AppWindow; + +const APP_ID: &str = "com.github.akiraux.akira"; + +fn main() -> glib::ExitCode { + // Create a new application + let app = Application::builder().application_id(APP_ID).build(); + + // Connect to "activate" signal of `app` + app.connect_activate(build_ui); + + // Run the application + app.run() +} + +fn build_ui(app: &Application) { + // Create a window and set the title + let window = AppWindow::new(app); + + // Present window + window.present(); +} diff --git a/src/meson.build b/src/meson.build deleted file mode 100644 index 33362f459..000000000 --- a/src/meson.build +++ /dev/null @@ -1,218 +0,0 @@ -conf_data = configuration_data() -conf_data.set('PROJECT_NAME', meson.project_name()) -conf_data.set('PREFIX', akira_prefix) -conf_data.set('DATADIR', akira_datadir) -conf_data.set('PKGDATADIR',akira_pkgdatadir) -conf_data.set('GETTEXT_PACKAGE', gettext_package) -conf_data.set('VERSION', '0.0.15') -conf_data.set('PROFILE', profile) -conf_data.set('APP_ID', application_id) - -config_header = configure_file( - input: 'config.vala.in', - output: 'config.vala', - configuration: conf_data -) - -sources = files( - 'Application.vala', - 'Window.vala', - - 'FileFormat/AkiraFile.vala', - 'FileFormat/FileManager.vala', - 'FileFormat/JsonSerializer.vala', - 'FileFormat/JsonItemSerializer.vala', - 'FileFormat/JsonDeserializer.vala', - 'FileFormat/ZipArchiveHandler.vala', - - 'Services/Settings.vala', - 'Services/ActionManager.vala', - 'Services/EventBus.vala', - - 'Utils/Array.vala', - 'Utils/Dialogs.vala', - 'Utils/BlendingMode.vala', - 'Utils/AffineTransform.vala', - 'Utils/Color.vala', - 'Utils/Image.vala', - 'Utils/ItemAlignment.vala', - 'Utils/ModelUtil.vala', - 'Utils/Nobs.vala', - 'Utils/Snapping.vala', - 'Utils/SVGUtil.vala', - 'Utils/GeometryMath.vala', - 'Utils/Bezier.vala', - 'Utils/Delegates.vala', - - 'Layouts/HeaderBar.vala', - 'Layouts/MainViewCanvas.vala', - 'Layouts/MainWindow.vala', - - 'Layouts/Alignment/AlignmentPanel.vala', - - 'Layouts/BordersList/BorderItemModel.vala', - 'Layouts/BordersList/BorderListBox.vala', - 'Layouts/BordersList/BorderListItem.vala', - 'Layouts/BordersList/BorderListStore.vala', - 'Layouts/BordersList/BordersPanel.vala', - - 'Layouts/FillsList/FillItemModel.vala', - 'Layouts/FillsList/FillListBox.vala', - 'Layouts/FillsList/FillListItem.vala', - 'Layouts/FillsList/FillsPanel.vala', - 'Layouts/FillsList/FillListStore.vala', - - 'Layouts/LayersList/LayerItemModel.vala', - 'Layouts/LayersList/LayerListBox.vala', - 'Layouts/LayersList/LayerListItem.vala', - 'Layouts/LayersList/LayerListStore.vala', - - 'Layouts/Sidebars/LayersSidebar.vala', - 'Layouts/Sidebars/OptionsSidebar.vala', - - 'Layouts/Transforms/TransformPanel.vala', - - 'Widgets/AddColorButton.vala', - 'Widgets/ButtonImage.vala', - 'Widgets/ColorButton.vala', - 'Widgets/ColorChooser.vala', - 'Widgets/ColorField.vala', - 'Widgets/ColorPicker.vala', - 'Widgets/ExportWidget.vala', - 'Widgets/EyeDropperButton.vala', - 'Widgets/HeaderBarButton.vala', - 'Widgets/HideButton.vala', - 'Widgets/InputField.vala', - 'Widgets/LinkedInput.vala', - 'Widgets/MenuButton.vala', - 'Widgets/OpacityField.vala', - 'Widgets/RoundedColorButton.vala', - 'Widgets/ZoomButton.vala', - - 'Widgets/VirtualizingListBox/VirtualizingListBox.vala', - 'Widgets/VirtualizingListBox/VirtualizingListBoxModel.vala', - 'Widgets/VirtualizingListBox/VirtualizingListBoxRow.vala', - 'Widgets/VirtualizingListBox/VirtualizingSimpleListBox.vala', - - 'ViewLayers/BaseCanvas.vala', - 'ViewLayers/ViewLayer.vala', - 'ViewLayers/ViewLayerSnaps.vala', - 'ViewLayers/ViewLayerNobs.vala', - 'ViewLayers/ViewLayerHover.vala', - 'ViewLayers/ViewLayerExportArea.vala', - 'ViewLayers/ViewLayerGrid.vala', - 'ViewLayers/ViewLayerPath.vala', - 'ViewLayers/ViewLayerMultiSelect.vala', - - 'Models/ColorModel.vala', - 'Models/ExportModel.vala', - #'Models/ListModel.vala', - 'Models/PathEditModel.vala', - - 'Dialogs/ShortcutsDialog.vala', - 'Dialogs/SettingsDialog.vala', - 'Dialogs/ExportDialog.vala', - 'Dialogs/ReleaseDialog.vala', - - 'Drawables/Drawable.vala', - 'Drawables/DrawableArtboard.vala', - 'Drawables/DrawableEllipse.vala', - 'Drawables/DrawableGroup.vala', - 'Drawables/DrawablePath.vala', - 'Drawables/DrawableRect.vala', - 'Drawables/DrawableText.vala', - - 'Lib/Components/Borders.vala', - 'Lib/Components/BorderRadius.vala', - 'Lib/Components/Color.vala', - 'Lib/Components/CompiledBorder.vala', - 'Lib/Components/CompiledFill.vala', - 'Lib/Components/CompiledGeometry.vala', - 'Lib/Components/CompiledName.vala', - 'Lib/Components/Component.vala', - 'Lib/Components/Components.vala', - 'Lib/Components/Coordinates.vala', - 'Lib/Components/Fills.vala', - 'Lib/Components/Flipped.vala', - 'Lib/Components/Layer.vala', - 'Lib/Components/Layout.vala', - 'Lib/Components/Name.vala', - 'Lib/Components/Opacity.vala', - 'Lib/Components/Path.vala', - 'Lib/Components/Size.vala', - 'Lib/Components/Text.vala', - 'Lib/Components/Transform.vala', - - 'Lib/Items/Model.vala', - 'Lib/Items/ModelInstance.vala', - 'Lib/Items/ModelNode.vala', - 'Lib/Items/ItemSelection.vala', - 'Lib/Items/ModelType.vala', - 'Lib/Items/ModelTypeArtboard.vala', - 'Lib/Items/ModelTypeEllipse.vala', - 'Lib/Items/ModelTypeGroup.vala', - 'Lib/Items/ModelTypeRect.vala', - 'Lib/Items/ModelTypePath.vala', - 'Lib/Items/ModelTypeText.vala', - - 'Lib/Managers/CopyManager.vala', - 'Lib/Managers/ExportManager.vala', - 'Lib/Managers/HistoryManager.vala', - 'Lib/Managers/ItemsManager.vala', - 'Lib/Managers/ModeManager.vala', - 'Lib/Managers/NobManager.vala', - 'Lib/Managers/HoverManager.vala', - 'Lib/Managers/SelectionManager.vala', - 'Lib/Managers/SnapManager.vala', - - 'Lib/Modes/AbstractInteractionMode.vala', - 'Lib/Modes/TransformMode.vala', - 'Lib/Modes/ItemInsertMode.vala', - 'Lib/Modes/ExportMode.vala', - 'Lib/Modes/PanMode.vala', - 'Lib/Modes/PathEditMode.vala', - 'Lib/Modes/MultiSelectMode.vala', - - 'Lib/ViewCanvas.vala', - - 'Geometry/Point.vala', - 'Geometry/Rectangle.vala', - 'Geometry/TransformedRectangle.vala', - 'Geometry/Quad.vala', - 'Geometry/PathSegment.vala' - -) - -deps = [ - gtk_dependency, - granite_dependency, - gee_dependency, - libxml_dependency, - cairo_dependency, - libarchive_dependency, - json_glib_dependency, - m_dep -] - -akira_library = library( - 'akira-library-1.0', - sources, - asresources, - config_header, - dependencies: deps -) - -akira_dep = declare_dependency( - dependencies: deps, - link_with: akira_library, - include_directories: include_directories('.') -) - -# Create a new executable, list the files we want to compile, list the dependencies we need, and install -executable( - application_id, - 'Main.vala', - asresources, - dependencies: deps + [akira_dep], - install: true -) diff --git a/src/window.rs b/src/window.rs new file mode 100644 index 000000000..e36acd5f2 --- /dev/null +++ b/src/window.rs @@ -0,0 +1,85 @@ +/** + * This file is part of Akira. + * + * Copyright (c) 2024 Alessandro Castellani + * + * Akira is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later version. + * + * Akira is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * Akira. If not, see . + */ +use gettextrs::gettext; +use gtk::subclass::prelude::*; +use gtk::{gio, gio::Settings, glib, prelude::*, ApplicationWindow}; +use once_cell::sync::OnceCell; + +mod imp { + use super::*; + + #[derive(Debug, Default)] + pub struct AppWindow { + pub settings: OnceCell, + } + + #[glib::object_subclass] + impl ObjectSubclass for AppWindow { + const NAME: &'static str = "AppWindow"; + type Type = super::AppWindow; + type ParentType = ApplicationWindow; + } + + impl ObjectImpl for AppWindow { + fn constructed(&self) { + self.parent_constructed(); + + let obj = self.obj(); + + let mode_switch = granite::ModeSwitch::builder() + .primary_icon_name("display-brightness-symbolic") + .secondary_icon_name("weather-clear-night-symbolic") + .primary_icon_tooltip_text(gettext("Light Background")) + .secondary_icon_tooltip_text(gettext("Dark Background")) + .valign(gtk::Align::Center) + .build(); + + let gtk_settings = gtk::Settings::default().expect("Unable to get GtkSettings object"); + mode_switch + .bind_property("active", >k_settings, "gtk-application-prefer-dark-theme") + .bidirectional() + .build(); + + let header_bar = gtk::HeaderBar::builder().show_title_buttons(true).build(); + + header_bar.style_context().add_class("default-decoration"); + header_bar.pack_end(&mode_switch); + + obj.set_titlebar(Some(&header_bar)); + } + } + + impl WidgetImpl for AppWindow {} + impl WindowImpl for AppWindow {} + impl ApplicationWindowImpl for AppWindow {} +} + +// Extend and implements the proper classes to make AppWindow and actual GtkObject +glib::wrapper! { + pub struct AppWindow(ObjectSubclass) + @extends gtk::Widget, gtk::Window, gtk::ApplicationWindow, + @implements gio::ActionGroup, gio::ActionMap; +} + +impl AppWindow { + pub fn new>(application: &P) -> Self { + glib::Object::builder() + .property("application", application) + .property("title", "Akira") + .build() + } +} diff --git a/tests/canvas/test-fills-item.vala b/tests/canvas/test-fills-item.vala deleted file mode 100644 index a50284a13..000000000 --- a/tests/canvas/test-fills-item.vala +++ /dev/null @@ -1,78 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public class Akira.FillsItemTest : Akira.TestSuite { - public FillsItemTest () { - this.add_test ("loops_through_items", this.loop_through_items); - } - - public override void setup () {} - - public override void teardown () {} - - // Unit test for Akira.Models.FillListModel.add () method. - // Check whether quickly selecting and deselecting multiple items causes a segfault. - public void loop_through_items () { - /* - app.activate.connect ((a) => { - var window = new Akira.Window (app); - app.add_window (window); - var canvas = window.main_window.main_canvas.canvas; - - // TRUE: The canvas was properly generated. - assert (canvas is Akira.Lib.Canvas); - - var list_model = window.main_window.left_sidebar.fills_panel.list_model; - - // Create 1000 Items and quickly select/deselect them to stress test the canvas. - for (var i = 0; i < 10; i++) { - window.items_manager.set_item_to_insert ("rectangle"); - var item = window.items_manager.insert_item (10, 10); - - // We don't need to set any other parameter or create other widgets like the layer - // panel since we're only interested in testing the selection effect and the fill model. - canvas.selected_bound_manager.add_item_to_selection (item as Akira.Lib.Items.CanvasItem); - - // TRUE: We selected the correct item. - assert (canvas.selected_bound_manager.selected_items.index (item) == 0); - assert ((item as Akira.Lib.Items.CanvasItem).selected == true); - - // TRUE: A fill model was created and listed. - assert (list_model.get_n_items () == 1); - - canvas.selected_bound_manager.delete_selection (); - - // TRUE: The previous fill model was deleted. - assert (list_model.get_n_items () == 0); - - // TRUE: We no item is selected. - assert (canvas.selected_bound_manager.selected_items.length () == 0); - } - - // Shut down the test. - app.quit (); - }); - - app.run (); - app = null; - */ - } -} diff --git a/tests/canvas/test-lib2-model.vala b/tests/canvas/test-lib2-model.vala deleted file mode 100644 index 0b44176a6..000000000 --- a/tests/canvas/test-lib2-model.vala +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (c) 2019-2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - - * Akira is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with Akira. If not, see . - * - * Authored by: Martin "mbfraga" Fraga - */ - -using Akira.Lib; - -public class Akira.LibModelTests : Akira.TestSuite { - public LibModelTests () { - this.add_test ("origin_splice_extripate", this.origin_splice_extripate); - this.add_test ("origin_move", this.origin_move); - this.add_test ("nested_ops", this.nested_ops); - } - - public override void setup () {} - - public override void teardown () {} - - void compare_instances ( - Items.Model model, - int group_id, GLib.Array expected_items, - GLib.Array expected_item_parents - ) { - assert (model.group_map.has_key (group_id)); - assert (model.group_nodes.has_key (group_id)); - assert (expected_items.length == expected_item_parents.length); - - var parent_group = model.group_nodes[group_id]; - - for (var i = 0; i < expected_items.length; ++i) { - var expected_id = expected_items.index (i); - var child = parent_group.children.index (i); - - assert (parent_group.instance.children[i] == expected_id); - assert (child.id == expected_id); - assert (child.instance.id == expected_id); - assert (child.parent.instance.id == group_id); - } - } - - public void origin_splice_extripate () { - var model = new Items.Model (); - var expected_items = new GLib.Array (); - var expected_item_parents = new GLib.Array (); - - // bad target parent - assert (-1 == model.splice_new_item (0, 1, Items.ModelInstance.dummy_item ())); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - var candidate = Items.ModelInstance.dummy_item (); - - // splice item at zero location in empty origin - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 0, candidate.clone ()) >= Items.Model.ITEM_START_ID); - expected_items.append_val (Items.Model.ITEM_START_ID + 1); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - // splice item after the previous one in the origin - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 1, candidate.clone ()) >= Items.Model.ITEM_START_ID); - expected_items.append_val (Items.Model.ITEM_START_ID + 2); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - // splice item at zero location in non-empty origin - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 0, candidate.clone ()) >= Items.Model.ITEM_START_ID); - expected_items.insert_val (0, Items.Model.ITEM_START_ID + 3); - expected_item_parents.insert_val (0, Items.Model.ORIGIN_ID); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - // invalid parent to extripate - assert (-1 == model.extripate (-1, 3, true)); - assert (-1 == model.extripate (Items.Model.ITEM_START_ID + 2, 3, true)); - assert (-1 == model.extripate (Items.Model.ORIGIN_ID, 3, true)); - assert (-1 == model.extripate (Items.Model.ORIGIN_ID, 4, true)); - - // extripate second item in origin - assert (0 == model.extripate (Items.Model.ORIGIN_ID, 1, true)); - expected_items.remove_index (1); - expected_item_parents.remove_index (1); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - // extripate second item in origin - assert (0 == model.extripate (Items.Model.ORIGIN_ID, 1, true)); - expected_items.remove_index (1); - expected_item_parents.remove_index (1); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - } - - public void origin_move () { - var model = new Items.Model (); - var expected_items = new GLib.Array (); - var expected_item_parents = new GLib.Array (); - - var candidate = Items.ModelInstance.dummy_item (); - - expected_items.append_val (Items.Model.ITEM_START_ID + 1); - expected_items.append_val (Items.Model.ITEM_START_ID + 2); - expected_items.append_val (Items.Model.ITEM_START_ID + 3); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 0, candidate.clone ()) >= Items.Model.ITEM_START_ID); - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 1, candidate.clone ()) >= Items.Model.ITEM_START_ID); - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 2, candidate.clone ()) >= Items.Model.ITEM_START_ID); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - // self move -- do nothing; - assert (0 == model.move_items (Items.Model.ORIGIN_ID, 0, 0, 1, true)); - - // moves that don't change the topology -- do nothing; - assert (0 == model.move_items (Items.Model.ORIGIN_ID, 0, 0, -1, true)); - assert (0 == model.move_items (Items.Model.ORIGIN_ID, 0, 0, 0, true)); - assert (0 == model.move_items (Items.Model.ORIGIN_ID, 0, 2, 2, true)); - - // invalid moves -- do nothing - assert (-1 == model.move_items (Items.Model.ORIGIN_ID, 4, 0, 1, true)); - assert (-1 == model.move_items (Items.Model.ORIGIN_ID, 2, 0, 4, true)); - assert (-1 == model.move_items (Items.Model.ORIGIN_ID, 3, 0, 1, true)); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - assert (1 == model.move_items (Items.Model.ORIGIN_ID, 0, 2, 1, true)); - expected_items.data[0] = (Items.Model.ITEM_START_ID + 2); - expected_items.data[1] = (Items.Model.ITEM_START_ID + 3); - expected_items.data[2] = (Items.Model.ITEM_START_ID + 1); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - assert (1 == model.move_items (Items.Model.ORIGIN_ID, 0, 2, 1, true)); - assert (1 == model.move_items (Items.Model.ORIGIN_ID, 0, 2, 1, true)); - expected_items.data[0] = (Items.Model.ITEM_START_ID + 1); - expected_items.data[1] = (Items.Model.ITEM_START_ID + 2); - expected_items.data[2] = (Items.Model.ITEM_START_ID + 3); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - // prepare for more complicated rotations - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 3, candidate.clone ()) >= Items.Model.ITEM_START_ID); - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 4, candidate.clone ()) >= Items.Model.ITEM_START_ID); - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 5, candidate.clone ()) >= Items.Model.ITEM_START_ID); - expected_items.append_val (Items.Model.ITEM_START_ID + 4); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - expected_items.append_val (Items.Model.ITEM_START_ID + 5); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - expected_items.append_val (Items.Model.ITEM_START_ID + 6); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - assert (1 == model.move_items (Items.Model.ORIGIN_ID, 0, 2, 3, true)); - expected_items.data[0] = (Items.Model.ITEM_START_ID + 4); - expected_items.data[1] = (Items.Model.ITEM_START_ID + 5); - expected_items.data[2] = (Items.Model.ITEM_START_ID + 1); - expected_items.data[3] = (Items.Model.ITEM_START_ID + 2); - expected_items.data[4] = (Items.Model.ITEM_START_ID + 3); - expected_items.data[5] = (Items.Model.ITEM_START_ID + 6); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - assert (1 == model.move_items (Items.Model.ORIGIN_ID, 2, 0, 3, true)); - expected_items.data[0] = (Items.Model.ITEM_START_ID + 1); - expected_items.data[1] = (Items.Model.ITEM_START_ID + 2); - expected_items.data[2] = (Items.Model.ITEM_START_ID + 3); - expected_items.data[3] = (Items.Model.ITEM_START_ID + 4); - expected_items.data[4] = (Items.Model.ITEM_START_ID + 5); - expected_items.data[5] = (Items.Model.ITEM_START_ID + 6); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - assert (1 == model.move_items (Items.Model.ORIGIN_ID, 2, 3, 3, true)); - expected_items.data[0] = (Items.Model.ITEM_START_ID + 1); - expected_items.data[1] = (Items.Model.ITEM_START_ID + 2); - expected_items.data[2] = (Items.Model.ITEM_START_ID + 6); - expected_items.data[3] = (Items.Model.ITEM_START_ID + 3); - expected_items.data[4] = (Items.Model.ITEM_START_ID + 4); - expected_items.data[5] = (Items.Model.ITEM_START_ID + 5); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - } - - public void nested_ops () { - var model = new Items.Model (); - var expected_items = new GLib.Array (); - var expected_item_parents = new GLib.Array (); - - var nested_items = new GLib.Array (); - var nested_item_parents = new GLib.Array (); - - var nested_items2 = new GLib.Array (); - var nested_item_parents2 = new GLib.Array (); - - var candidate = Items.ModelInstance.dummy_item (); - var group_candidate = Items.ModelInstance.dummy_group (); - - expected_items.append_val (Items.Model.ITEM_START_ID + 1); - expected_items.append_val (Items.Model.ITEM_START_ID + 2); - expected_items.append_val (Items.Model.ITEM_START_ID + 3); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - - // Three roots - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 0, candidate.clone ()) >= Items.Model.ITEM_START_ID); - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 1, candidate.clone ()) >= Items.Model.ITEM_START_ID); - assert (model.splice_new_item (Items.Model.ORIGIN_ID, 2, candidate.clone ()) >= Items.Model.ITEM_START_ID); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - expected_items.insert_val (2, Items.Model.GROUP_START_ID + 1); - expected_item_parents.append_val (Items.Model.ORIGIN_ID); - - assert (model.splice_new_item ( - Items.Model.ORIGIN_ID, 2, group_candidate.clone ()) >= Items.Model.GROUP_START_ID); - - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - nested_items.append_val (Items.Model.ITEM_START_ID + 4); - nested_items.append_val (Items.Model.ITEM_START_ID + 5); - nested_items.append_val (Items.Model.ITEM_START_ID + 6); - nested_item_parents.append_val (Items.Model.GROUP_START_ID + 1); - nested_item_parents.append_val (Items.Model.GROUP_START_ID + 1); - nested_item_parents.append_val (Items.Model.GROUP_START_ID + 1); - - assert (model.splice_new_item ( - Items.Model.GROUP_START_ID + 1, 0, candidate.clone ()) >= Items.Model.ITEM_START_ID); - assert (model.splice_new_item ( - Items.Model.GROUP_START_ID + 1, 1, candidate.clone ()) >= Items.Model.ITEM_START_ID); - assert (model.splice_new_item ( - Items.Model.GROUP_START_ID + 1, 2, candidate.clone ()) >= Items.Model.ITEM_START_ID); - - compare_instances (model, Items.Model.GROUP_START_ID + 1, nested_items, nested_item_parents); - - nested_items.remove_index (1); - nested_item_parents.remove_index (1); - assert (0 == model.extripate (Items.Model.GROUP_START_ID + 1, 1, true)); - - compare_instances (model, Items.Model.GROUP_START_ID + 1, nested_items, nested_item_parents); - - nested_items.append_val (Items.Model.ITEM_START_ID + 7); - nested_items.append_val (Items.Model.ITEM_START_ID + 8); - nested_items.append_val (Items.Model.ITEM_START_ID + 9); - nested_item_parents.append_val (Items.Model.GROUP_START_ID + 1); - nested_item_parents.append_val (Items.Model.GROUP_START_ID + 1); - nested_item_parents.append_val (Items.Model.GROUP_START_ID + 1); - assert (model.splice_new_item ( - Items.Model.GROUP_START_ID + 1, 2, candidate.clone ()) >= Items.Model.ITEM_START_ID); - assert (model.splice_new_item ( - Items.Model.GROUP_START_ID + 1, 3, candidate.clone ()) >= Items.Model.ITEM_START_ID); - assert (model.splice_new_item ( - Items.Model.GROUP_START_ID + 1, 4, candidate.clone ()) >= Items.Model.ITEM_START_ID); - - compare_instances (model, Items.Model.GROUP_START_ID + 1, nested_items, nested_item_parents); - - assert (1 == model.move_items (Items.Model.GROUP_START_ID + 1, 2, 0, 2, true)); - nested_items.data[0] = (Items.Model.ITEM_START_ID + 7); - nested_items.data[1] = (Items.Model.ITEM_START_ID + 8); - nested_items.data[2] = (Items.Model.ITEM_START_ID + 4); - nested_items.data[3] = (Items.Model.ITEM_START_ID + 6); - nested_items.data[4] = (Items.Model.ITEM_START_ID + 9); - compare_instances (model, Items.Model.GROUP_START_ID + 1, nested_items, nested_item_parents); - - nested_items.append_val (Items.Model.GROUP_START_ID + 2); - nested_item_parents.append_val (Items.Model.GROUP_START_ID + 1); - assert (model.splice_new_item ( - Items.Model.GROUP_START_ID + 1, 1, group_candidate.clone ()) >= Items.Model.GROUP_START_ID); - - nested_items2.append_val (Items.Model.ITEM_START_ID + 10); - nested_items2.append_val (Items.Model.ITEM_START_ID + 11); - nested_items2.append_val (Items.Model.ITEM_START_ID + 12); - nested_item_parents2.append_val (Items.Model.GROUP_START_ID + 2); - nested_item_parents2.append_val (Items.Model.GROUP_START_ID + 2); - nested_item_parents2.append_val (Items.Model.GROUP_START_ID + 2); - assert (model.append_new_item ( - Items.Model.GROUP_START_ID + 2, candidate.clone ()) >= Items.Model.GROUP_START_ID); - assert (model.append_new_item ( - Items.Model.GROUP_START_ID + 2, candidate.clone ()) >= Items.Model.GROUP_START_ID); - assert (model.append_new_item ( - Items.Model.GROUP_START_ID + 2, candidate.clone ()) >= Items.Model.GROUP_START_ID); - compare_instances (model, Items.Model.GROUP_START_ID + 2, nested_items2, nested_item_parents2); - - expected_items.remove_index (2); - expected_item_parents.remove_index (2); - assert (0 >= model.remove (Items.Model.GROUP_START_ID + 1, true)); - compare_instances (model, Items.Model.ORIGIN_ID, expected_items, expected_item_parents); - - assert (model.instance_from_id (Items.Model.ITEM_START_ID + 7) == null); - assert (model.instance_from_id (Items.Model.ITEM_START_ID + 8) == null); - assert (model.instance_from_id (Items.Model.ITEM_START_ID + 4) == null); - assert (model.instance_from_id (Items.Model.ITEM_START_ID + 6) == null); - assert (model.instance_from_id (Items.Model.ITEM_START_ID + 9) == null); - assert (model.instance_from_id (Items.Model.GROUP_START_ID + 1) == null); - assert (model.instance_from_id (Items.Model.GROUP_START_ID + 2) == null); - assert (model.instance_from_id (Items.Model.ITEM_START_ID + 10) == null); - assert (model.instance_from_id (Items.Model.ITEM_START_ID + 11) == null); - assert (model.instance_from_id (Items.Model.ITEM_START_ID + 12) == null); - - assert (model.node_from_id (Items.Model.ITEM_START_ID + 7) == null); - assert (model.node_from_id (Items.Model.ITEM_START_ID + 8) == null); - assert (model.node_from_id (Items.Model.ITEM_START_ID + 4) == null); - assert (model.node_from_id (Items.Model.ITEM_START_ID + 6) == null); - assert (model.node_from_id (Items.Model.ITEM_START_ID + 9) == null); - assert (model.node_from_id (Items.Model.GROUP_START_ID + 1) == null); - assert (model.node_from_id (Items.Model.GROUP_START_ID + 2) == null); - assert (model.node_from_id (Items.Model.ITEM_START_ID + 10) == null); - assert (model.node_from_id (Items.Model.ITEM_START_ID + 11) == null); - assert (model.node_from_id (Items.Model.ITEM_START_ID + 12) == null); - } -} diff --git a/tests/canvas/test-main.vala b/tests/canvas/test-main.vala deleted file mode 100644 index b36c53018..000000000 --- a/tests/canvas/test-main.vala +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -class Main : GLib.Object { - public static int main (string[] args) { - var exit_status = 0; - - Gtk.init (ref args); - Test.init (ref args); - - var tests = new Akira.TestRunner (); - tests.add (new Akira.FillsItemTest ()); - tests.add (new Akira.LibModelTests ()); - - GLib.Idle.add (() => { - exit_status = tests.run (); - Gtk.main_quit (); - - return false; - }); - - Gtk.main (); - - return exit_status; - } -} diff --git a/tests/meson.build b/tests/meson.build deleted file mode 100644 index 0351b04bf..000000000 --- a/tests/meson.build +++ /dev/null @@ -1,45 +0,0 @@ -# Define environment variables to run tests. -test_env = [ - 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), - 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), - 'GSETTINGS_BACKEND=memory', - 'GSETTINGS_SCHEMA_DIR=@0@/data/schemas'.format(meson.build_root()), -] - -# Set necessary C flags. -test_cflags = [ - '-I@0@/../src'.format(meson.current_source_dir()), - '-I@0@/../src'.format(meson.current_build_dir()), - '-DTEST_DATA_DIR="@0@/data/schemas"'.format(meson.current_source_dir()), -] - -# Canvas Tests ---------------------------------------- # -canvas_tests = executable ( - 'canvas_tests', - 'tests-model.vala', - - 'canvas/test-fills-item.vala', - 'canvas/test-lib2-model.vala', - 'canvas/test-main.vala', - c_args: test_cflags, - dependencies: [akira_dep] -) - -test ('canvas_tests', canvas_tests, env: test_env) - -# Utils Tests ---------------------------------------- # -utils_tests = executable ( - 'utils_tests', - 'tests-model.vala', - - 'utils/test-array.vala', - 'utils/test-main.vala', - c_args: test_cflags, - dependencies: [akira_dep] -) - -test ('utils_tests', utils_tests, env: test_env) - -# Settings Tests ---------------------------------------- # - -# File Format Tests ---------------------------------------- # diff --git a/tests/tests-model.vala b/tests/tests-model.vala deleted file mode 100644 index 8df9a98d4..000000000 --- a/tests/tests-model.vala +++ /dev/null @@ -1,215 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Alessandro "Alecaddd" Castellani -*/ - -public delegate void Akira.TestCaseFunc (); -public GLib.SettingsSchemaSource schema_source; - -private class Akira.TestSuiteAdaptor { - public string name; - - private Akira.TestCaseFunc func; - private Akira.TestSuite test_suite; - - public TestSuiteAdaptor (string name, owned Akira.TestCaseFunc test_case_func, - Akira.TestSuite test_suite) { - this.name = name; - this.func = (owned) test_case_func; - this.test_suite = test_suite; - } - - public void setup (void* fixture) { - this.test_suite.setup (); - } - - public void run (void* fixture) { - this.func (); - } - - public void teardown (void* fixture) { - this.test_suite.teardown (); - } - - public GLib.TestCase get_g_test_case () { - return new GLib.TestCase (this.name, - this.setup, - this.run, - this.teardown); - } -} - -public class Akira.TestSuite : GLib.Object { - private GLib.TestSuite g_test_suite; - private TestSuiteAdaptor[] adaptors = new TestSuiteAdaptor[0]; - public Akira.Application app; - - public TestSuite () { - var name = this.get_name (); - this.g_test_suite = new GLib.TestSuite (name); - app = new Akira.Application (); - } - - public string get_name () { - return this.get_type ().name (); - } - - public GLib.TestSuite get_g_test_suite () { - return this.g_test_suite; - } - - public void add_test (string name, owned Akira.TestCaseFunc func) { - var adaptor = new TestSuiteAdaptor (name, (owned) func, this); - this.adaptors += adaptor; - - this.g_test_suite.add (adaptor.get_g_test_case ()); - } - - public virtual void setup () {} - - public virtual void teardown () {} -} - -public class Akira.TestRunner : GLib.Object { - private GLib.TestSuite root_suite; - private GLib.File tmp_dir; - private const string SCHEMA_FILE_NAME = "com.github.akiraux.akira.gschema.xml.in"; - - public TestRunner (GLib.TestSuite? root_suite = null) { - if (root_suite == null) { - this.root_suite = GLib.TestSuite.get_root (); - } else { - this.root_suite = root_suite; - } - } - - public void add (Akira.TestSuite test_suite) { - this.root_suite.add_suite (test_suite.get_g_test_suite ()); - } - - private void setup_settings () { - Environment.set_variable ("GSETTINGS_BACKEND", "memory", true); - Environment.set_variable ("GSETTINGS_SCHEMA_DIR", this.tmp_dir.get_path (), true); - - /* prepare temporary settings */ - var target_schema_path = this.tmp_dir.get_path (); - - try { - var top_builddir = TestRunner.get_top_builddir (); - - var source_schema_file = GLib.File.new_for_path ( - Path.build_filename (top_builddir, "data/schemas", SCHEMA_FILE_NAME)); - - var target_schema_file = GLib.File.new_for_path ( - Path.build_filename (target_schema_path, SCHEMA_FILE_NAME)); - - source_schema_file.copy (target_schema_file, - GLib.FileCopyFlags.OVERWRITE); - } catch (GLib.Error error) { - GLib.error ("Error copying schema file: %s", error.message); - } - - var compile_schemas_result = 0; - try { - GLib.Process.spawn_command_line_sync ( - "glib-compile-schemas %s".printf (target_schema_path), - null, - null, - out compile_schemas_result); - } catch (GLib.SpawnError error) { - GLib.error (error.message); - } - - if (compile_schemas_result != 0) { - GLib.error ("Could not compile schemas '%s'.", target_schema_path); - } - } - - public virtual void global_setup () { - Environment.set_variable ("LANGUAGE", "C", true); - - try { - this.tmp_dir = GLib.File.new_for_path (GLib.DirUtils.make_tmp ("gnome-Akira-test-XXXXXX")); - } catch (GLib.Error error) { - GLib.error ("Error creating temporary directory for test files: %s".printf (error.message)); - } - - this.setup_settings (); - } - - public virtual void global_teardown () { - if (this.tmp_dir != null) { - var tmp_dir_path = this.tmp_dir.get_path (); - var delete_tmp_result = 0; - - try { - GLib.Process.spawn_command_line_sync ( - "rm -rf %s".printf (tmp_dir_path), - null, - null, - out delete_tmp_result); - } catch (GLib.SpawnError error) { - GLib.warning (error.message); - } - - if (delete_tmp_result != 0) { - GLib.warning ("Could not delete temporary directory '%s'", tmp_dir_path); - } - } - } - - public int run () { - /* TODO: spawn a child process to tun tests, if it fails than we - will be able to exit cleanly */ - - this.global_setup (); - var exit_status = GLib.Test.run (); - this.global_teardown (); - - return exit_status; - } - - private static string get_top_builddir () { - var builddir = Environment.get_variable ("top_builddir"); - - if (builddir == null) { - var dir = GLib.File.new_for_path (Environment.get_current_dir ()); - - while (dir != null) { - var schema_path = GLib.Path.build_filename (dir.get_path (), - "data/schemas", - SCHEMA_FILE_NAME); - - if (GLib.FileUtils.test (schema_path, GLib.FileTest.IS_REGULAR)) { - builddir = dir.get_path (); - break; - } - - dir = dir.get_parent (); - } - } - - if (builddir == null) { - /* fallback to parent dir, test should be ran from 'tests' dir */ - builddir = ".."; - } - - return builddir; - } -} diff --git a/tests/utils/test-array.vala b/tests/utils/test-array.vala deleted file mode 100644 index d772e1067..000000000 --- a/tests/utils/test-array.vala +++ /dev/null @@ -1,134 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Martin (mbfraga) Fraga -*/ - -using Akira.Utils; - -public class Akira.ArrayTests : Akira.TestSuite { - public ArrayTests () { - this.add_test ("iarray_insert", this.iarray_insert); - this.add_test ("iarray_append", this.iarray_append); - this.add_test ("iarray_remove", this.iarray_remove); - this.add_test ("iarray_rotate", this.iarray_rotate); - } - - public override void setup () {} - - public override void teardown () {} - - public void print_iarray (int[] a) { - print ("array: "); - foreach (var v in a) { - print ("%i ", v); - } - print ("\n"); - } - - public bool compare_iarrays (int[] a, int[] b) { - if (a.length != b.length) { - return false; - } - - for (var i = 0; i < a.length; ++i) { - if (a[i] != b[i]) { - return false; - } - } - - return true; - } - - public void iarray_insert () { - var test_case = new int[] {1, 2, 3, 4}; - - // Asserts? not sure how to handle these - // assert (Utils.Array.insert_at_iarray (ref test_case, -1, 5) == false); - // assert (Utils.Array.insert_at_iarray (ref test_case, 4, 5) == false); - // compare_iarrays (test_case, {1, 2, 3, 4}); - - assert (Utils.Array.insert_at_iarray (ref test_case, 0, 5) == true); - compare_iarrays (test_case, {5, 1, 2, 3, 4}); - - assert (Utils.Array.insert_at_iarray (ref test_case, 2, 5) == true); - compare_iarrays (test_case, {5, 1, 5, 2, 3, 4}); - - assert (Utils.Array.insert_at_iarray (ref test_case, 5, 5) == true); - compare_iarrays (test_case, {5, 1, 5, 2, 3, 5, 4}); - } - - public void iarray_append () { - var test_case = new int[] {}; - - compare_iarrays (test_case, {}); - - assert (Utils.Array.append_to_iarray (ref test_case, 5) == true); - compare_iarrays (test_case, {5}); - - assert (Utils.Array.append_to_iarray (ref test_case, 7) == true); - compare_iarrays (test_case, {5, 7}); - } - - public void iarray_remove () { - var test_case = new int[] {1, 2, 3, 4, 5}; - - assert (Utils.Array.remove_from_iarray (ref test_case, 0, 1) == true); - compare_iarrays (test_case, {2, 3, 4, 5}); - - assert (Utils.Array.remove_from_iarray (ref test_case, 2, 1) == true); - compare_iarrays (test_case, {2, 3, 5}); - - assert (Utils.Array.remove_from_iarray (ref test_case, 2, 1) == true); - compare_iarrays (test_case, {2, 3}); - - assert (Utils.Array.remove_from_iarray (ref test_case, 0, 2) == true); - compare_iarrays (test_case, {2, 3}); - - test_case = new int[] {1, 2, 3, 4, 5}; - assert (Utils.Array.remove_from_iarray (ref test_case, 0, 5) == true); - compare_iarrays (test_case, {}); - } - - public void iarray_rotate () { - var test_case = new int[] {1, 2, 3, 4, 5}; - - // test no-ops - assert (Utils.Array.rotate_iarray (ref test_case, 0, 0, 2) == true); - assert (Utils.Array.rotate_iarray (ref test_case, 3, 3, 5) == true); - assert (Utils.Array.rotate_iarray (ref test_case, 0, 3, 3) == true); - assert (Utils.Array.rotate_iarray (ref test_case, 0, 5, 5) == true); - - compare_iarrays (test_case, {1, 2, 3, 4, 5}); - - assert (Utils.Array.rotate_iarray (ref test_case, 0, 1, 2) == true); - compare_iarrays (test_case, {3, 1, 2, 4, 5}); - - assert (Utils.Array.rotate_iarray (ref test_case, 0, 1, 2) == true); - compare_iarrays (test_case, {2, 3, 1, 4, 5}); - - test_case = new int[] {1, 2, 3, 4, 5}; - assert (Utils.Array.rotate_iarray (ref test_case, 1, 4, 5) == true); - compare_iarrays (test_case, {1, 5, 2, 3, 4}); - - test_case = new int[] {1, 2, 3, 4, 5}; - assert (Utils.Array.rotate_iarray (ref test_case, 0, 1, 5) == true); - compare_iarrays (test_case, {2, 3, 4, 5, 1}); - } - -} diff --git a/tests/utils/test-main.vala b/tests/utils/test-main.vala deleted file mode 100644 index 5749235a8..000000000 --- a/tests/utils/test-main.vala +++ /dev/null @@ -1,43 +0,0 @@ -/* -* Copyright (c) 2019 Alecaddd (http://alecaddd.com) -* -* This file is part of Akira. -* -* Akira is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. - -* Akira is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. - -* You should have received a copy of the GNU General Public License -* along with Akira. If not, see . -* -* Authored by: Martin (mbfraga) Fraga -*/ - -class Main : GLib.Object { - public static int main (string[] args) { - var exit_status = 0; - - Gtk.init (ref args); - Test.init (ref args); - - var tests = new Akira.TestRunner (); - tests.add (new Akira.ArrayTests ()); - - GLib.Idle.add (() => { - exit_status = tests.run (); - Gtk.main_quit (); - - return false; - }); - - Gtk.main (); - - return exit_status; - } -} diff --git a/uncrustify.cfg b/uncrustify.cfg deleted file mode 100644 index 6b7558b25..000000000 --- a/uncrustify.cfg +++ /dev/null @@ -1,2807 +0,0 @@ -# Uncrustify-0.69.0_f - -# -# General options -# - -# The type of line endings. -# -# Default: auto -newlines = auto # lf/crlf/cr/auto - -# The original size of tabs in the input. -# -# Default: 8 -input_tab_size = 8 # unsigned number - -# The size of tabs in the output (only used if align_with_tabs=true). -# -# Default: 8 -output_tab_size = 4 # unsigned number - -# The ASCII value of the string escape char, usually 92 (\) or (Pawn) 94 (^). -# -# Default: 92 -string_escape_char = 92 # unsigned number - -# Alternate string escape char (usually only used for Pawn). -# Only works right before the quote char. -string_escape_char2 = 0 # unsigned number - -# Replace tab characters found in string literals with the escape sequence \t -# instead. -string_replace_tab_chars = false # true/false - -# Allow interpreting '>=' and '>>=' as part of a template in code like -# 'void f(list>=val);'. If true, 'assert(x<0 && y>=3)' will be broken. -# Improvements to template detection may make this option obsolete. -tok_split_gte = false # true/false - -# Specify the marker used in comments to disable processing of part of the -# file. -# -# Default: *INDENT-OFF* -disable_processing_cmt = " *INDENT-OFF*" # string - -# Specify the marker used in comments to (re)enable processing in a file. -# -# Default: *INDENT-ON* -enable_processing_cmt = " *INDENT-ON*" # string - -# Enable parsing of digraphs. -enable_digraphs = false # true/false - -# Add or remove the UTF-8 BOM (recommend 'remove'). -utf8_bom = ignore # ignore/add/remove/force - -# If the file contains bytes with values between 128 and 255, but is not -# UTF-8, then output as UTF-8. -utf8_byte = false # true/false - -# Force the output encoding to UTF-8. -utf8_force = false # true/false - -# -# Spacing options -# - -# Add or remove space around non-assignment symbolic operators ('+', '/', '%', -# '<<', and so forth). -sp_arith = force # ignore/add/remove/force - -# Add or remove space around arithmetic operators '+' and '-'. -# -# Overrides sp_arith. -sp_arith_additive = ignore # ignore/add/remove/force - -# Add or remove space around assignment operator '=', '+=', etc. -sp_assign = force # ignore/add/remove/force - -# Add or remove space around '=' in C++11 lambda capture specifications. -# -# Overrides sp_assign. -sp_cpp_lambda_assign = force # ignore/add/remove/force - -# Add or remove space after the capture specification in C++11 lambda. -sp_cpp_lambda_paren = force # ignore/add/remove/force - -# Add or remove space around assignment operator '=' in a prototype. -# -# If set to ignore, use sp_assign. -sp_assign_default = force # ignore/add/remove/force - -# Add or remove space before assignment operator '=', '+=', etc. -# -# Overrides sp_assign. -sp_before_assign = force # ignore/add/remove/force - -# Add or remove space after assignment operator '=', '+=', etc. -# -# Overrides sp_assign. -sp_after_assign = force # ignore/add/remove/force - -# Add or remove space in 'NS_ENUM ('. -sp_enum_paren = ignore # ignore/add/remove/force - -# Add or remove space around assignment '=' in enum. -sp_enum_assign = force # ignore/add/remove/force - -# Add or remove space before assignment '=' in enum. -# -# Overrides sp_enum_assign. -sp_enum_before_assign = ignore # ignore/add/remove/force - -# Add or remove space after assignment '=' in enum. -# -# Overrides sp_enum_assign. -sp_enum_after_assign = force # ignore/add/remove/force - -# Add or remove space around assignment ':' in enum. -sp_enum_colon = ignore # ignore/add/remove/force - -# Add or remove space around preprocessor '##' concatenation operator. -# -# Default: add -sp_pp_concat = add # ignore/add/remove/force - -# Add or remove space after preprocessor '#' stringify operator. -# Also affects the '#@' charizing operator. -sp_pp_stringify = ignore # ignore/add/remove/force - -# Add or remove space before preprocessor '#' stringify operator -# as in '#define x(y) L#y'. -sp_before_pp_stringify = ignore # ignore/add/remove/force - -# Add or remove space around boolean operators '&&' and '||'. -sp_bool = force # ignore/add/remove/force - -# Add or remove space around compare operator '<', '>', '==', etc. -sp_compare = force # ignore/add/remove/force - -# Add or remove space inside '(' and ')'. -sp_inside_paren = remove # ignore/add/remove/force - -# Add or remove space between nested parentheses, i.e. '((' vs. ') )'. -sp_paren_paren = remove # ignore/add/remove/force - -# Add or remove space between back-to-back parentheses, i.e. ')(' vs. ') ('. -sp_cparen_oparen = remove # ignore/add/remove/force - -# Whether to balance spaces inside nested parentheses. -sp_balance_nested_parens = false # true/false - -# Add or remove space between ')' and '{'. -sp_paren_brace = force # ignore/add/remove/force - -# Add or remove space between nested braces, i.e. '{{' vs '{ {'. -sp_brace_brace = ignore # ignore/add/remove/force - -# Add or remove space before pointer star '*'. -sp_before_ptr_star = force # ignore/add/remove/force - -# Add or remove space before pointer star '*' that isn't followed by a -# variable name. If set to 'ignore', sp_before_ptr_star is used instead. -sp_before_unnamed_ptr_star = force # ignore/add/remove/force - -# Add or remove space between pointer stars '*'. -sp_between_ptr_star = force # ignore/add/remove/force - -# Add or remove space after pointer star '*', if followed by a word. -sp_after_ptr_star = force # ignore/add/remove/force - -# Add or remove space after pointer caret '^', if followed by a word. -sp_after_ptr_block_caret = ignore # ignore/add/remove/force - -# Add or remove space after pointer star '*', if followed by a qualifier. -sp_after_ptr_star_qualifier = ignore # ignore/add/remove/force - -# Add or remove space after a pointer star '*', if followed by a function -# prototype or function definition. -sp_after_ptr_star_func = force # ignore/add/remove/force - -# Add or remove space after a pointer star '*', if followed by an open -# parenthesis, as in 'void* (*)(). -sp_ptr_star_paren = force # ignore/add/remove/force - -# Add or remove space before a pointer star '*', if followed by a function -# prototype or function definition. -sp_before_ptr_star_func = force # ignore/add/remove/force - -# Add or remove space before a reference sign '&'. -sp_before_byref = force # ignore/add/remove/force - -# Add or remove space before a reference sign '&' that isn't followed by a -# variable name. If set to 'ignore', sp_before_byref is used instead. -sp_before_unnamed_byref = ignore # ignore/add/remove/force - -# Add or remove space after reference sign '&', if followed by a word. -sp_after_byref = ignore # ignore/add/remove/force - -# Add or remove space after a reference sign '&', if followed by a function -# prototype or function definition. -sp_after_byref_func = remove # ignore/add/remove/force - -# Add or remove space before a reference sign '&', if followed by a function -# prototype or function definition. -sp_before_byref_func = force # ignore/add/remove/force - -# Add or remove space between type and word. -# -# Default: force -sp_after_type = force # ignore/add/remove/force - -# Add or remove space between 'decltype(...)' and word. -sp_after_decltype = ignore # ignore/add/remove/force - -# (D) Add or remove space before the parenthesis in the D constructs -# 'template Foo(' and 'class Foo('. -sp_before_template_paren = ignore # ignore/add/remove/force - -# Add or remove space between 'template' and '<'. -# If set to ignore, sp_before_angle is used. -sp_template_angle = remove # ignore/add/remove/force - -# Add or remove space before '<'. -sp_before_angle = remove # ignore/add/remove/force - -# Add or remove space inside '<' and '>'. -sp_inside_angle = remove # ignore/add/remove/force - -# Add or remove space inside '<>'. -sp_inside_angle_empty = ignore # ignore/add/remove/force - -# Add or remove space between '>' and ':'. -sp_angle_colon = ignore # ignore/add/remove/force - -# Add or remove space after '<>'. -sp_after_angle = remove # ignore/add/remove/force - -# Add or remove space between '>' and '(' as found in 'new List(foo);'. -sp_angle_paren = force # ignore/add/remove/force - -# Add or remove space between '>' and '()' as found in 'new List();'. -sp_angle_paren_empty = ignore # ignore/add/remove/force - -# Add or remove space between '>' and a word as in 'List m;' or -# 'template static ...'. -sp_angle_word = force # ignore/add/remove/force - -# Add or remove space between '>' and '>' in '>>' (template stuff). -# -# Default: add -sp_angle_shift = add # ignore/add/remove/force - -# (C++11) Permit removal of the space between '>>' in 'foo >'. Note -# that sp_angle_shift cannot remove the space without this option. -sp_permit_cpp11_shift = false # true/false - -# Add or remove space before '(' of control statements ('if', 'for', 'switch', -# 'while', etc.). -sp_before_sparen = force # ignore/add/remove/force - -# Add or remove space inside '(' and ')' of control statements. -sp_inside_sparen = remove # ignore/add/remove/force - -# Add or remove space after '(' of control statements. -# -# Overrides sp_inside_sparen. -sp_inside_sparen_open = ignore # ignore/add/remove/force - -# Add or remove space before ')' of control statements. -# -# Overrides sp_inside_sparen. -sp_inside_sparen_close = ignore # ignore/add/remove/force - -# Add or remove space after ')' of control statements. -sp_after_sparen = remove # ignore/add/remove/force - -# Add or remove space between ')' and '{' of of control statements. -sp_sparen_brace = force # ignore/add/remove/force - -# (D) Add or remove space between 'invariant' and '('. -sp_invariant_paren = ignore # ignore/add/remove/force - -# (D) Add or remove space after the ')' in 'invariant (C) c'. -sp_after_invariant_paren = ignore # ignore/add/remove/force - -# Add or remove space before empty statement ';' on 'if', 'for' and 'while'. -sp_special_semi = remove # ignore/add/remove/force - -# Add or remove space before ';'. -# -# Default: remove -sp_before_semi = remove # ignore/add/remove/force - -# Add or remove space before ';' in non-empty 'for' statements. -sp_before_semi_for = force # ignore/add/remove/force - -# Add or remove space before a semicolon of an empty part of a for statement. -sp_before_semi_for_empty = force # ignore/add/remove/force - -# Add or remove space after ';', except when followed by a comment. -# -# Default: add -sp_after_semi = add # ignore/add/remove/force - -# Add or remove space after ';' in non-empty 'for' statements. -# -# Default: force -sp_after_semi_for = force # ignore/add/remove/force - -# Add or remove space after the final semicolon of an empty part of a for -# statement, as in 'for ( ; ; )'. -sp_after_semi_for_empty = force # ignore/add/remove/force - -# Add or remove space before '[' (except '[]'). -sp_before_square = remove # ignore/add/remove/force - -# Add or remove space before '[]'. -sp_before_squares = remove # ignore/add/remove/force - -# Add or remove space before C++17 structured bindings. -sp_cpp_before_struct_binding = ignore # ignore/add/remove/force - -# Add or remove space inside a non-empty '[' and ']'. -sp_inside_square = remove # ignore/add/remove/force - -# (OC) Add or remove space inside a non-empty Objective-C boxed array '@[' and -# ']'. If set to ignore, sp_inside_square is used. -sp_inside_square_oc_array = ignore # ignore/add/remove/force - -# Add or remove space after ',', i.e. 'a,b' vs. 'a, b'. -sp_after_comma = force # ignore/add/remove/force - -# Add or remove space before ','. -# -# Default: remove -sp_before_comma = remove # ignore/add/remove/force - -# (C#) Add or remove space between ',' and ']' in multidimensional array type -# like 'int[,,]'. -sp_after_mdatype_commas = ignore # ignore/add/remove/force - -# (C#) Add or remove space between '[' and ',' in multidimensional array type -# like 'int[,,]'. -sp_before_mdatype_commas = ignore # ignore/add/remove/force - -# (C#) Add or remove space between ',' in multidimensional array type -# like 'int[,,]'. -sp_between_mdatype_commas = ignore # ignore/add/remove/force - -# Add or remove space between an open parenthesis and comma, -# i.e. '(,' vs. '( ,'. -# -# Default: force -sp_paren_comma = force # ignore/add/remove/force - -# Add or remove space before the variadic '...' when preceded by a -# non-punctuator. -sp_before_ellipsis = remove # ignore/add/remove/force - -# Add or remove space between a type and '...'. -sp_type_ellipsis = ignore # ignore/add/remove/force - -# (D) Add or remove space between a type and '?'. -sp_type_question = ignore # ignore/add/remove/force - -# Add or remove space between ')' and '...'. -sp_paren_ellipsis = ignore # ignore/add/remove/force - -# Add or remove space between ')' and a qualifier such as 'const'. -sp_paren_qualifier = ignore # ignore/add/remove/force - -# Add or remove space between ')' and 'noexcept'. -sp_paren_noexcept = ignore # ignore/add/remove/force - -# Add or remove space after class ':'. -sp_after_class_colon = force # ignore/add/remove/force - -# Add or remove space before class ':'. -sp_before_class_colon = force # ignore/add/remove/force - -# Add or remove space after class constructor ':'. -sp_after_constr_colon = ignore # ignore/add/remove/force - -# Add or remove space before class constructor ':'. -sp_before_constr_colon = ignore # ignore/add/remove/force - -# Add or remove space before case ':'. -# -# Default: remove -sp_before_case_colon = remove # ignore/add/remove/force - -# Add or remove space between 'operator' and operator sign. -sp_after_operator = force # ignore/add/remove/force - -# Add or remove space between the operator symbol and the open parenthesis, as -# in 'operator ++('. -sp_after_operator_sym = ignore # ignore/add/remove/force - -# Overrides sp_after_operator_sym when the operator has no arguments, as in -# 'operator *()'. -sp_after_operator_sym_empty = ignore # ignore/add/remove/force - -# Add or remove space after C/D cast, i.e. 'cast(int)a' vs. 'cast(int) a' or -# '(int)a' vs. '(int) a'. -sp_after_cast = force # ignore/add/remove/force - -# Add or remove spaces inside cast parentheses. -sp_inside_paren_cast = remove # ignore/add/remove/force - -# Add or remove space between the type and open parenthesis in a C++ cast, -# i.e. 'int(exp)' vs. 'int (exp)'. -sp_cpp_cast_paren = ignore # ignore/add/remove/force - -# Add or remove space between 'sizeof' and '('. -sp_sizeof_paren = force # ignore/add/remove/force - -# Add or remove space between 'sizeof' and '...'. -sp_sizeof_ellipsis = ignore # ignore/add/remove/force - -# Add or remove space between 'sizeof...' and '('. -sp_sizeof_ellipsis_paren = ignore # ignore/add/remove/force - -# Add or remove space between 'decltype' and '('. -sp_decltype_paren = ignore # ignore/add/remove/force - -# (Pawn) Add or remove space after the tag keyword. -sp_after_tag = ignore # ignore/add/remove/force - -# Add or remove space inside enum '{' and '}'. -sp_inside_braces_enum = force # ignore/add/remove/force - -# Add or remove space inside struct/union '{' and '}'. -sp_inside_braces_struct = force # ignore/add/remove/force - -# (OC) Add or remove space inside Objective-C boxed dictionary '{' and '}' -sp_inside_braces_oc_dict = ignore # ignore/add/remove/force - -# Add or remove space after open brace in an unnamed temporary -# direct-list-initialization. -sp_after_type_brace_init_lst_open = ignore # ignore/add/remove/force - -# Add or remove space before close brace in an unnamed temporary -# direct-list-initialization. -sp_before_type_brace_init_lst_close = ignore # ignore/add/remove/force - -# Add or remove space inside an unnamed temporary direct-list-initialization. -sp_inside_type_brace_init_lst = ignore # ignore/add/remove/force - -# Add or remove space inside '{' and '}'. -sp_inside_braces = force # ignore/add/remove/force - -# Add or remove space inside '{}'. -sp_inside_braces_empty = remove # ignore/add/remove/force - -# Add or remove space between return type and function name. A minimum of 1 -# is forced except for pointer return types. -sp_type_func = remove # ignore/add/remove/force - -# Add or remove space between type and open brace of an unnamed temporary -# direct-list-initialization. -sp_type_brace_init_lst = ignore # ignore/add/remove/force - -# Add or remove space between function name and '(' on function declaration. -sp_func_proto_paren = force # ignore/add/remove/force - -# Add or remove space between function name and '()' on function declaration -# without parameters. -sp_func_proto_paren_empty = ignore # ignore/add/remove/force - -# Add or remove space between function name and '(' on function definition. -sp_func_def_paren = force # ignore/add/remove/force - -# Add or remove space between function name and '()' on function definition -# without parameters. -sp_func_def_paren_empty = ignore # ignore/add/remove/force - -# Add or remove space inside empty function '()'. -sp_inside_fparens = remove # ignore/add/remove/force - -# Add or remove space inside function '(' and ')'. -sp_inside_fparen = remove # ignore/add/remove/force - -# Add or remove space inside the first parentheses in a function type, as in -# 'void (*x)(...)'. -sp_inside_tparen = remove # ignore/add/remove/force - -# Add or remove space between the ')' and '(' in a function type, as in -# 'void (*x)(...)'. -sp_after_tparen_close = remove # ignore/add/remove/force - -# Add or remove space between ']' and '(' when part of a function call. -sp_square_fparen = remove # ignore/add/remove/force - -# Add or remove space between ')' and '{' of function. -sp_fparen_brace = force # ignore/add/remove/force - -# Add or remove space between ')' and '{' of s function call in object -# initialization. -# -# Overrides sp_fparen_brace. -sp_fparen_brace_initializer = ignore # ignore/add/remove/force - -# (Java) Add or remove space between ')' and '{{' of double brace initializer. -sp_fparen_dbrace = ignore # ignore/add/remove/force - -# Add or remove space between function name and '(' on function calls. -sp_func_call_paren = force # ignore/add/remove/force - -# Add or remove space between function name and '()' on function calls without -# parameters. If set to 'ignore' (the default), sp_func_call_paren is used. -sp_func_call_paren_empty = force # ignore/add/remove/force - -# Add or remove space between the user function name and '(' on function -# calls. You need to set a keyword to be a user function in the config file, -# like: -# set func_call_user tr _ i18n -sp_func_call_user_paren = ignore # ignore/add/remove/force - -# Add or remove space inside user function '(' and ')'. -sp_func_call_user_inside_fparen = ignore # ignore/add/remove/force - -# Add or remove space between nested parentheses with user functions, -# i.e. '((' vs. '( ('. -sp_func_call_user_paren_paren = ignore # ignore/add/remove/force - -# Add or remove space between a constructor/destructor and the open -# parenthesis. -sp_func_class_paren = force # ignore/add/remove/force - -# Add or remove space between a constructor without parameters or destructor -# and '()'. -sp_func_class_paren_empty = ignore # ignore/add/remove/force - -# Add or remove space between 'return' and '('. -sp_return_paren = force # ignore/add/remove/force - -# Add or remove space between 'return' and '{'. -sp_return_brace = ignore # ignore/add/remove/force - -# Add or remove space between '__attribute__' and '('. -sp_attribute_paren = remove # ignore/add/remove/force - -# Add or remove space between 'defined' and '(' in '#if defined (FOO)'. -sp_defined_paren = force # ignore/add/remove/force - -# Add or remove space between 'throw' and '(' in 'throw (something)'. -sp_throw_paren = force # ignore/add/remove/force - -# Add or remove space between 'throw' and anything other than '(' as in -# '@throw [...];'. -sp_after_throw = force # ignore/add/remove/force - -# Add or remove space between 'catch' and '(' in 'catch (something) { }'. -# If set to ignore, sp_before_sparen is used. -sp_catch_paren = force # ignore/add/remove/force - -# (OC) Add or remove space between '@catch' and '(' -# in '@catch (something) { }'. If set to ignore, sp_catch_paren is used. -sp_oc_catch_paren = ignore # ignore/add/remove/force - -# (OC) Add or remove space between class name and '(' -# in '@interface className(categoryName):BaseClass' -sp_oc_classname_paren = ignore # ignore/add/remove/force - -# (D) Add or remove space between 'version' and '(' -# in 'version (something) { }'. If set to ignore, sp_before_sparen is used. -sp_version_paren = ignore # ignore/add/remove/force - -# (D) Add or remove space between 'scope' and '(' -# in 'scope (something) { }'. If set to ignore, sp_before_sparen is used. -sp_scope_paren = ignore # ignore/add/remove/force - -# Add or remove space between 'super' and '(' in 'super (something)'. -# -# Default: remove -sp_super_paren = remove # ignore/add/remove/force - -# Add or remove space between 'this' and '(' in 'this (something)'. -# -# Default: remove -sp_this_paren = remove # ignore/add/remove/force - -# Add or remove space between a macro name and its definition. -sp_macro = ignore # ignore/add/remove/force - -# Add or remove space between a macro function ')' and its definition. -sp_macro_func = ignore # ignore/add/remove/force - -# Add or remove space between 'else' and '{' if on the same line. -sp_else_brace = force # ignore/add/remove/force - -# Add or remove space between '}' and 'else' if on the same line. -sp_brace_else = force # ignore/add/remove/force - -# Add or remove space between '}' and the name of a typedef on the same line. -sp_brace_typedef = force # ignore/add/remove/force - -# Add or remove space before the '{' of a 'catch' statement, if the '{' and -# 'catch' are on the same line, as in 'catch (decl) {'. -sp_catch_brace = force # ignore/add/remove/force - -# (OC) Add or remove space before the '{' of a '@catch' statement, if the '{' -# and '@catch' are on the same line, as in '@catch (decl) {'. -# If set to ignore, sp_catch_brace is used. -sp_oc_catch_brace = ignore # ignore/add/remove/force - -# Add or remove space between '}' and 'catch' if on the same line. -sp_brace_catch = force # ignore/add/remove/force - -# (OC) Add or remove space between '}' and '@catch' if on the same line. -# If set to ignore, sp_brace_catch is used. -sp_oc_brace_catch = ignore # ignore/add/remove/force - -# Add or remove space between 'finally' and '{' if on the same line. -sp_finally_brace = force # ignore/add/remove/force - -# Add or remove space between '}' and 'finally' if on the same line. -sp_brace_finally = force # ignore/add/remove/force - -# Add or remove space between 'try' and '{' if on the same line. -sp_try_brace = force # ignore/add/remove/force - -# Add or remove space between get/set and '{' if on the same line. -sp_getset_brace = force # ignore/add/remove/force - -# Add or remove space between a variable and '{' for C++ uniform -# initialization. -# -# Default: add -sp_word_brace = add # ignore/add/remove/force - -# Add or remove space between a variable and '{' for a namespace. -# -# Default: add -sp_word_brace_ns = add # ignore/add/remove/force - -# Add or remove space before the '::' operator. -sp_before_dc = remove # ignore/add/remove/force - -# Add or remove space after the '::' operator. -sp_after_dc = remove # ignore/add/remove/force - -# (D) Add or remove around the D named array initializer ':' operator. -sp_d_array_colon = ignore # ignore/add/remove/force - -# Add or remove space after the '!' (not) unary operator. -# -# Default: remove -sp_not = remove # ignore/add/remove/force - -# Add or remove space after the '~' (invert) unary operator. -# -# Default: remove -sp_inv = remove # ignore/add/remove/force - -# Add or remove space after the '&' (address-of) unary operator. This does not -# affect the spacing after a '&' that is part of a type. -# -# Default: remove -sp_addr = remove # ignore/add/remove/force - -# Add or remove space around the '.' or '->' operators. -# -# Default: remove -sp_member = remove # ignore/add/remove/force - -# Add or remove space after the '*' (dereference) unary operator. This does -# not affect the spacing after a '*' that is part of a type. -# -# Default: remove -sp_deref = remove # ignore/add/remove/force - -# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'. -# -# Default: remove -sp_sign = remove # ignore/add/remove/force - -# Add or remove space between '++' and '--' the word to which it is being -# applied, as in '(--x)' or 'y++;'. -# -# Default: remove -sp_incdec = remove # ignore/add/remove/force - -# Add or remove space before a backslash-newline at the end of a line. -# -# Default: add -sp_before_nl_cont = add # ignore/add/remove/force - -# (OC) Add or remove space after the scope '+' or '-', as in '-(void) foo;' -# or '+(int) bar;'. -sp_after_oc_scope = ignore # ignore/add/remove/force - -# (OC) Add or remove space after the colon in message specs, -# i.e. '-(int) f:(int) x;' vs. '-(int) f: (int) x;'. -sp_after_oc_colon = ignore # ignore/add/remove/force - -# (OC) Add or remove space before the colon in message specs, -# i.e. '-(int) f: (int) x;' vs. '-(int) f : (int) x;'. -sp_before_oc_colon = ignore # ignore/add/remove/force - -# (OC) Add or remove space after the colon in immutable dictionary expression -# 'NSDictionary *test = @{@"foo" :@"bar"};'. -sp_after_oc_dict_colon = ignore # ignore/add/remove/force - -# (OC) Add or remove space before the colon in immutable dictionary expression -# 'NSDictionary *test = @{@"foo" :@"bar"};'. -sp_before_oc_dict_colon = ignore # ignore/add/remove/force - -# (OC) Add or remove space after the colon in message specs, -# i.e. '[object setValue:1];' vs. '[object setValue: 1];'. -sp_after_send_oc_colon = ignore # ignore/add/remove/force - -# (OC) Add or remove space before the colon in message specs, -# i.e. '[object setValue:1];' vs. '[object setValue :1];'. -sp_before_send_oc_colon = ignore # ignore/add/remove/force - -# (OC) Add or remove space after the (type) in message specs, -# i.e. '-(int)f: (int) x;' vs. '-(int)f: (int)x;'. -sp_after_oc_type = ignore # ignore/add/remove/force - -# (OC) Add or remove space after the first (type) in message specs, -# i.e. '-(int) f:(int)x;' vs. '-(int)f:(int)x;'. -sp_after_oc_return_type = ignore # ignore/add/remove/force - -# (OC) Add or remove space between '@selector' and '(', -# i.e. '@selector(msgName)' vs. '@selector (msgName)'. -# Also applies to '@protocol()' constructs. -sp_after_oc_at_sel = ignore # ignore/add/remove/force - -# (OC) Add or remove space between '@selector(x)' and the following word, -# i.e. '@selector(foo) a:' vs. '@selector(foo)a:'. -sp_after_oc_at_sel_parens = ignore # ignore/add/remove/force - -# (OC) Add or remove space inside '@selector' parentheses, -# i.e. '@selector(foo)' vs. '@selector( foo )'. -# Also applies to '@protocol()' constructs. -sp_inside_oc_at_sel_parens = ignore # ignore/add/remove/force - -# (OC) Add or remove space before a block pointer caret, -# i.e. '^int (int arg){...}' vs. ' ^int (int arg){...}'. -sp_before_oc_block_caret = ignore # ignore/add/remove/force - -# (OC) Add or remove space after a block pointer caret, -# i.e. '^int (int arg){...}' vs. '^ int (int arg){...}'. -sp_after_oc_block_caret = ignore # ignore/add/remove/force - -# (OC) Add or remove space between the receiver and selector in a message, -# as in '[receiver selector ...]'. -sp_after_oc_msg_receiver = ignore # ignore/add/remove/force - -# (OC) Add or remove space after '@property'. -sp_after_oc_property = ignore # ignore/add/remove/force - -# (OC) Add or remove space between '@synchronized' and the open parenthesis, -# i.e. '@synchronized(foo)' vs. '@synchronized (foo)'. -sp_after_oc_synchronized = ignore # ignore/add/remove/force - -# Add or remove space around the ':' in 'b ? t : f'. -sp_cond_colon = force # ignore/add/remove/force - -# Add or remove space before the ':' in 'b ? t : f'. -# -# Overrides sp_cond_colon. -sp_cond_colon_before = force # ignore/add/remove/force - -# Add or remove space after the ':' in 'b ? t : f'. -# -# Overrides sp_cond_colon. -sp_cond_colon_after = force # ignore/add/remove/force - -# Add or remove space around the '?' in 'b ? t : f'. -sp_cond_question = force # ignore/add/remove/force - -# Add or remove space before the '?' in 'b ? t : f'. -# -# Overrides sp_cond_question. -sp_cond_question_before = force # ignore/add/remove/force - -# Add or remove space after the '?' in 'b ? t : f'. -# -# Overrides sp_cond_question. -sp_cond_question_after = force # ignore/add/remove/force - -# In the abbreviated ternary form '(a ?: b)', add or remove space between '?' -# and ':'. -# -# Overrides all other sp_cond_* options. -sp_cond_ternary_short = force # ignore/add/remove/force - -# Fix the spacing between 'case' and the label. Only 'ignore' and 'force' make -# sense here. -sp_case_label = force # ignore/add/remove/force - -# (D) Add or remove space around the D '..' operator. -sp_range = ignore # ignore/add/remove/force - -# Add or remove space after ':' in a Java/C++11 range-based 'for', -# as in 'for (Type var : expr)'. -sp_after_for_colon = ignore # ignore/add/remove/force - -# Add or remove space before ':' in a Java/C++11 range-based 'for', -# as in 'for (Type var : expr)'. -sp_before_for_colon = ignore # ignore/add/remove/force - -# (D) Add or remove space between 'extern' and '(' as in 'extern (C)'. -sp_extern_paren = ignore # ignore/add/remove/force - -# Add or remove space after the opening of a C++ comment, -# i.e. '// A' vs. '//A'. -sp_cmt_cpp_start = force # ignore/add/remove/force - -# If true, space is added with sp_cmt_cpp_start will be added after doxygen -# sequences like '///', '///<', '//!' and '//!<'. -sp_cmt_cpp_doxygen = false # true/false - -# If true, space is added with sp_cmt_cpp_start will be added after Qt -# translator or meta-data comments like '//:', '//=', and '//~'. -sp_cmt_cpp_qttr = false # true/false - -# Add or remove space between #else or #endif and a trailing comment. -sp_endif_cmt = remove # ignore/add/remove/force - -# Add or remove space after 'new', 'delete' and 'delete[]'. -sp_after_new = force # ignore/add/remove/force - -# Add or remove space between 'new' and '(' in 'new()'. -sp_between_new_paren = ignore # ignore/add/remove/force - -# Add or remove space between ')' and type in 'new(foo) BAR'. -sp_after_newop_paren = ignore # ignore/add/remove/force - -# Add or remove space inside parenthesis of the new operator -# as in 'new(foo) BAR'. -sp_inside_newop_paren = ignore # ignore/add/remove/force - -# Add or remove space after the open parenthesis of the new operator, -# as in 'new(foo) BAR'. -# -# Overrides sp_inside_newop_paren. -sp_inside_newop_paren_open = ignore # ignore/add/remove/force - -# Add or remove space before the close parenthesis of the new operator, -# as in 'new(foo) BAR'. -# -# Overrides sp_inside_newop_paren. -sp_inside_newop_paren_close = ignore # ignore/add/remove/force - -# Add or remove space before a trailing or embedded comment. -sp_before_tr_emb_cmt = force # ignore/add/remove/force - -# Number of spaces before a trailing or embedded comment. -sp_num_before_tr_emb_cmt = 0 # unsigned number - -# (Java) Add or remove space between an annotation and the open parenthesis. -sp_annotation_paren = ignore # ignore/add/remove/force - -# If true, vbrace tokens are dropped to the previous token and skipped. -sp_skip_vbrace_tokens = false # true/false - -# Add or remove space after 'noexcept'. -sp_after_noexcept = ignore # ignore/add/remove/force - -# Add or remove space after '_'. -sp_vala_after_translation = remove # ignore/add/remove/force - -# If true, a is inserted after #define. -force_tab_after_define = false # true/false - -# -# Indenting options -# - -# The number of columns to indent per level. Usually 2, 3, 4, or 8. -# -# Default: 8 -indent_columns = 4 # unsigned number - -# The continuation indent. If non-zero, this overrides the indent of '(', '[' -# and '=' continuation indents. Negative values are OK; negative value is -# absolute and not increased for each '(' or '[' level. -# -# For FreeBSD, this is set to 4. -indent_continue = 0 # number - -# The continuation indent, only for class header line(s). If non-zero, this -# overrides the indent of 'class' continuation indents. -indent_continue_class_head = 0 # unsigned number - -# Whether to indent empty lines (i.e. lines which contain only spaces before -# the newline character). -indent_single_newlines = false # true/false - -# The continuation indent for func_*_param if they are true. If non-zero, this -# overrides the indent. -indent_param = 0 # unsigned number - -# How to use tabs when indenting code. -# -# 0: Spaces only -# 1: Indent with tabs to brace level, align with spaces (default) -# 2: Indent and align with tabs, using spaces when not on a tabstop -# -# Default: 1 -indent_with_tabs = 0 # unsigned number - -# Whether to indent comments that are not at a brace level with tabs on a -# tabstop. Requires indent_with_tabs=2. If false, will use spaces. -indent_cmt_with_tabs = false # true/false - -# Whether to indent strings broken by '\' so that they line up. -indent_align_string = false # true/false - -# The number of spaces to indent multi-line XML strings. -# Requires indent_align_string=true. -indent_xml_string = 0 # unsigned number - -# Spaces to indent '{' from level. -indent_brace = 0 # unsigned number - -# Whether braces are indented to the body level. -indent_braces = false # true/false - -# Whether to disable indenting function braces if indent_braces=true. -indent_braces_no_func = false # true/false - -# Whether to disable indenting class braces if indent_braces=true. -indent_braces_no_class = false # true/false - -# Whether to disable indenting struct braces if indent_braces=true. -indent_braces_no_struct = false # true/false - -# Whether to indent based on the size of the brace parent, -# i.e. 'if' => 3 spaces, 'for' => 4 spaces, etc. -indent_brace_parent = false # true/false - -# Whether to indent based on the open parenthesis instead of the open brace -# in '({\n'. -indent_paren_open_brace = false # true/false - -# (C#) Whether to indent the brace of a C# delegate by another level. -indent_cs_delegate_brace = false # true/false - -# (C#) Whether to indent a C# delegate (to handle delegates with no brace) by -# another level. -indent_cs_delegate_body = false # true/false - -# Whether to indent the body of a 'namespace'. -indent_namespace = true # true/false - -# Whether to indent only the first namespace, and not any nested namespaces. -# Requires indent_namespace=true. -indent_namespace_single_indent = false # true/false - -# The number of spaces to indent a namespace block. -# If set to zero, use the value indent_columns -indent_namespace_level = 0 # unsigned number - -# If the body of the namespace is longer than this number, it won't be -# indented. Requires indent_namespace=true. 0 means no limit. -indent_namespace_limit = 0 # unsigned number - -# Whether the 'extern "C"' body is indented. -indent_extern = false # true/false - -# Whether the 'class' body is indented. -indent_class = true # true/false - -# Whether to indent the stuff after a leading base class colon. -indent_class_colon = false # true/false - -# Whether to indent based on a class colon instead of the stuff after the -# colon. Requires indent_class_colon=true. -indent_class_on_colon = false # true/false - -# Whether to indent the stuff after a leading class initializer colon. -indent_constr_colon = false # true/false - -# Virtual indent from the ':' for member initializers. -# -# Default: 2 -indent_ctor_init_leading = 2 # unsigned number - -# Additional indent for constructor initializer list. -# Negative values decrease indent down to the first column. -indent_ctor_init = 0 # number - -# Whether to indent 'if' following 'else' as a new block under the 'else'. -# If false, 'else\nif' is treated as 'else if' for indenting purposes. -indent_else_if = false # true/false - -# Amount to indent variable declarations after a open brace. -# -# <0: Relative -# >=0: Absolute -indent_var_def_blk = 0 # number - -# Whether to indent continued variable declarations instead of aligning. -indent_var_def_cont = false # true/false - -# Whether to indent continued shift expressions ('<<' and '>>') instead of -# aligning. Set align_left_shift=false when enabling this. -indent_shift = false # true/false - -# Whether to force indentation of function definitions to start in column 1. -indent_func_def_force_col1 = false # true/false - -# Whether to indent continued function call parameters one indent level, -# rather than aligning parameters under the open parenthesis. -indent_func_call_param = false # true/false - -# Same as indent_func_call_param, but for function definitions. -indent_func_def_param = false # true/false - -# Same as indent_func_call_param, but for function prototypes. -indent_func_proto_param = false # true/false - -# Same as indent_func_call_param, but for class declarations. -indent_func_class_param = false # true/false - -# Same as indent_func_call_param, but for class variable constructors. -indent_func_ctor_var_param = false # true/false - -# Same as indent_func_call_param, but for template parameter lists. -indent_template_param = false # true/false - -# Double the indent for indent_func_xxx_param options. -# Use both values of the options indent_columns and indent_param. -indent_func_param_double = false # true/false - -# Indentation column for standalone 'const' qualifier on a function -# prototype. -indent_func_const = 0 # unsigned number - -# Indentation column for standalone 'throw' qualifier on a function -# prototype. -indent_func_throw = 0 # unsigned number - -# The number of spaces to indent a continued '->' or '.'. -# Usually set to 0, 1, or indent_columns. -indent_member = 1 # unsigned number - -# Whether lines broken at '.' or '->' should be indented by a single indent. -# The indent_member option will not be effective if this is set to true. -indent_member_single = false # true/false - -# Spaces to indent single line ('//') comments on lines before code. -indent_sing_line_comments = 0 # unsigned number - -# Whether to indent trailing single line ('//') comments relative to the code -# instead of trying to keep the same absolute column. -indent_relative_single_line_comments = false # true/false - -# Spaces to indent 'case' from 'switch'. Usually 0 or indent_columns. -indent_switch_case = 0 # unsigned number - -# Whether to indent preprocessor statements inside of switch statements. -# -# Default: true -indent_switch_pp = true # true/false - -# Spaces to shift the 'case' line, without affecting any other lines. -# Usually 0. -indent_case_shift = 0 # unsigned number - -# Spaces to indent '{' from 'case'. By default, the brace will appear under -# the 'c' in case. Usually set to 0 or indent_columns. Negative values are OK. -indent_case_brace = 0 # number - -# Whether to indent comments found in first column. -indent_col1_comment = false # true/false - -# Whether to indent multi string literal in first column. -indent_col1_multi_string_literal = false # true/false - -# How to indent goto labels. -# -# >0: Absolute column where 1 is the leftmost column -# <=0: Subtract from brace indent -# -# Default: 1 -indent_label = 1 # number - -# Same as indent_label, but for access specifiers that are followed by a -# colon. -# -# Default: 1 -indent_access_spec = 1 # number - -# Whether to indent the code after an access specifier by one level. -# If true, this option forces 'indent_access_spec=0'. -indent_access_spec_body = false # true/false - -# If an open parenthesis is followed by a newline, whether to indent the next -# line so that it lines up after the open parenthesis (not recommended). -indent_paren_nl = false # true/false - -# How to indent a close parenthesis after a newline. -# -# 0: Indent to body level (default) -# 1: Align under the open parenthesis -# 2: Indent to the brace level -indent_paren_close = 0 # unsigned number - -# Whether to indent the open parenthesis of a function definition, -# if the parenthesis is on its own line. -indent_paren_after_func_def = false # true/false - -# Whether to indent the open parenthesis of a function declaration, -# if the parenthesis is on its own line. -indent_paren_after_func_decl = false # true/false - -# Whether to indent the open parenthesis of a function call, -# if the parenthesis is on its own line. -indent_paren_after_func_call = false # true/false - -# Whether to indent a comma when inside a parenthesis. -# If true, aligns under the open parenthesis. -indent_comma_paren = false # true/false - -# Whether to indent a Boolean operator when inside a parenthesis. -# If true, aligns under the open parenthesis. -indent_bool_paren = false # true/false - -# Whether to indent a semicolon when inside a for parenthesis. -# If true, aligns under the open for parenthesis. -indent_semicolon_for_paren = false # true/false - -# Whether to align the first expression to following ones -# if indent_bool_paren=true. -indent_first_bool_expr = false # true/false - -# Whether to align the first expression to following ones -# if indent_semicolon_for_paren=true. -indent_first_for_expr = false # true/false - -# If an open square is followed by a newline, whether to indent the next line -# so that it lines up after the open square (not recommended). -indent_square_nl = false # true/false - -# (ESQL/C) Whether to preserve the relative indent of 'EXEC SQL' bodies. -indent_preserve_sql = false # true/false - -# Whether to align continued statements at the '='. If false or if the '=' is -# followed by a newline, the next line is indent one tab. -# -# Default: true -indent_align_assign = true # true/false - -# Whether to align continued statements at the '('. If false or the '(' is -# followed by a newline, the next line indent is one tab. -# -# Default: true -indent_align_paren = true # true/false - -# (OC) Whether to indent Objective-C blocks at brace level instead of usual -# rules. -indent_oc_block = false # true/false - -# (OC) Indent for Objective-C blocks in a message relative to the parameter -# name. -# -# =0: Use indent_oc_block rules -# >0: Use specified number of spaces to indent -indent_oc_block_msg = 0 # unsigned number - -# (OC) Minimum indent for subsequent parameters -indent_oc_msg_colon = 0 # unsigned number - -# (OC) Whether to prioritize aligning with initial colon (and stripping spaces -# from lines, if necessary). -# -# Default: true -indent_oc_msg_prioritize_first_colon = true # true/false - -# (OC) Whether to indent blocks the way that Xcode does by default -# (from the keyword if the parameter is on its own line; otherwise, from the -# previous indentation level). Requires indent_oc_block_msg=true. -indent_oc_block_msg_xcode_style = true # true/false - -# (OC) Whether to indent blocks from where the brace is, relative to a -# message keyword. Requires indent_oc_block_msg=true. -indent_oc_block_msg_from_keyword = true # true/false - -# (OC) Whether to indent blocks from where the brace is, relative to a message -# colon. Requires indent_oc_block_msg=true. -indent_oc_block_msg_from_colon = true # true/false - -# (OC) Whether to indent blocks from where the block caret is. -# Requires indent_oc_block_msg=true. -indent_oc_block_msg_from_caret = true # true/false - -# (OC) Whether to indent blocks from where the brace caret is. -# Requires indent_oc_block_msg=true. -indent_oc_block_msg_from_brace = true # true/false - -# When indenting after virtual brace open and newline add further spaces to -# reach this minimum indent. -indent_min_vbrace_open = 0 # unsigned number - -# Whether to add further spaces after regular indent to reach next tabstop -# when identing after virtual brace open and newline. -indent_vbrace_open_on_tabstop = false # true/false - -# How to indent after a brace followed by another token (not a newline). -# true: indent all contained lines to match the token -# false: indent all contained lines to match the brace -# -# Default: true -indent_token_after_brace = true # true/false - -# Whether to indent the body of a C++11 lambda. -indent_cpp_lambda_body = false # true/false - -# (C#) Whether to indent a 'using' block if no braces are used. -# -# Default: true -indent_using_block = true # true/false - -# How to indent the continuation of ternary operator. -# -# 0: Off (default) -# 1: When the `if_false` is a continuation, indent it under `if_false` -# 2: When the `:` is a continuation, indent it under `?` -indent_ternary_operator = 0 # unsigned number - -# If true, the indentation of the chunks after a `return new` sequence will be set at return indentation column. -indent_off_after_return_new = false # true/false - -# If true, the tokens after return are indented with regular single indentation. By default (false) the indentation is after the return token. -indent_single_after_return = false # true/false - -# Whether to ignore indent and alignment for 'asm' blocks (i.e. assume they -# have their own indentation). -indent_ignore_asm_block = false # true/false - -# -# Newline adding and removing options -# - -# Whether to collapse empty blocks between '{' and '}'. -nl_collapse_empty_body = false # true/false - -# Don't split one-line braced assignments, as in 'foo_t f = { 1, 2 };'. -nl_assign_leave_one_liners = true # true/false - -# Don't split one-line braced statements inside a 'class xx { }' body. -nl_class_leave_one_liners = false # true/false - -# Don't split one-line enums, as in 'enum foo { BAR = 15 };' -nl_enum_leave_one_liners = false # true/false - -# Don't split one-line get or set functions. -nl_getset_leave_one_liners = false # true/false - -# (C#) Don't split one-line property get or set functions. -nl_cs_property_leave_one_liners = false # true/false - -# Don't split one-line function definitions, as in 'int foo() { return 0; }'. -nl_func_leave_one_liners = false # true/false - -# Don't split one-line C++11 lambdas, as in '[]() { return 0; }'. -nl_cpp_lambda_leave_one_liners = false # true/false - -# Don't split one-line if/else statements, as in 'if(...) b++;'. -nl_if_leave_one_liners = false # true/false - -# Don't split one-line while statements, as in 'while(...) b++;'. -nl_while_leave_one_liners = false # true/false - -# Don't split one-line for statements, as in 'for(...) b++;'. -nl_for_leave_one_liners = false # true/false - -# (OC) Don't split one-line Objective-C messages. -nl_oc_msg_leave_one_liner = false # true/false - -# (OC) Add or remove newline between method declaration and '{'. -nl_oc_mdef_brace = ignore # ignore/add/remove/force - -# (OC) Add or remove newline between Objective-C block signature and '{'. -nl_oc_block_brace = ignore # ignore/add/remove/force - -# (OC) Add or remove newline between '@interface' and '{'. -nl_oc_interface_brace = ignore # ignore/add/remove/force - -# (OC) Add or remove newline between '@implementation' and '{'. -nl_oc_implementation_brace = ignore # ignore/add/remove/force - -# Add or remove newlines at the start of the file. -nl_start_of_file = ignore # ignore/add/remove/force - -# The minimum number of newlines at the start of the file (only used if -# nl_start_of_file is 'add' or 'force'). -nl_start_of_file_min = 0 # unsigned number - -# Add or remove newline at the end of the file. -nl_end_of_file = ignore # ignore/add/remove/force - -# The minimum number of newlines at the end of the file (only used if -# nl_end_of_file is 'add' or 'force'). -nl_end_of_file_min = 0 # unsigned number - -# Add or remove newline between '=' and '{'. -nl_assign_brace = ignore # ignore/add/remove/force - -# (D) Add or remove newline between '=' and '['. -nl_assign_square = ignore # ignore/add/remove/force - -# Add or remove newline between '[]' and '{'. -nl_tsquare_brace = ignore # ignore/add/remove/force - -# (D) Add or remove newline after '= ['. Will also affect the newline before -# the ']'. -nl_after_square_assign = ignore # ignore/add/remove/force - -# Add or remove newline between a function call's ')' and '{', as in -# 'list_for_each(item, &list) { }'. -nl_fcall_brace = ignore # ignore/add/remove/force - -# Add or remove newline between 'enum' and '{'. -nl_enum_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'enum' and 'class'. -nl_enum_class = ignore # ignore/add/remove/force - -# Add or remove newline between 'enum class' and the identifier. -nl_enum_class_identifier = ignore # ignore/add/remove/force - -# Add or remove newline between 'enum class' type and ':'. -nl_enum_identifier_colon = ignore # ignore/add/remove/force - -# Add or remove newline between 'enum class identifier :' and type. -nl_enum_colon_type = ignore # ignore/add/remove/force - -# Add or remove newline between 'struct and '{'. -nl_struct_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'union' and '{'. -nl_union_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'if' and '{'. -nl_if_brace = remove # ignore/add/remove/force - -# Add or remove newline between '}' and 'else'. -nl_brace_else = remove # ignore/add/remove/force - -# Add or remove newline between 'else if' and '{'. If set to ignore, -# nl_if_brace is used instead. -nl_elseif_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'else' and '{'. -nl_else_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'else' and 'if'. -nl_else_if = remove # ignore/add/remove/force - -# Add or remove newline before 'if'/'else if' closing parenthesis. -nl_before_if_closing_paren = ignore # ignore/add/remove/force - -# Add or remove newline between '}' and 'finally'. -nl_brace_finally = remove # ignore/add/remove/force - -# Add or remove newline between 'finally' and '{'. -nl_finally_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'try' and '{'. -nl_try_brace = remove # ignore/add/remove/force - -# Add or remove newline between get/set and '{'. -nl_getset_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'for' and '{'. -nl_for_brace = remove # ignore/add/remove/force - -# Add or remove newline before the '{' of a 'catch' statement, as in -# 'catch (decl) {'. -nl_catch_brace = remove # ignore/add/remove/force - -# (OC) Add or remove newline before the '{' of a '@catch' statement, as in -# '@catch (decl) {'. If set to ignore, nl_catch_brace is used. -nl_oc_catch_brace = ignore # ignore/add/remove/force - -# Add or remove newline between '}' and 'catch'. -nl_brace_catch = remove # ignore/add/remove/force - -# (OC) Add or remove newline between '}' and '@catch'. If set to ignore, -# nl_brace_catch is used. -nl_oc_brace_catch = ignore # ignore/add/remove/force - -# Add or remove newline between '}' and ']'. -nl_brace_square = remove # ignore/add/remove/force - -# Add or remove newline between '}' and ')' in a function invocation. -nl_brace_fparen = remove # ignore/add/remove/force - -# Add or remove newline between 'while' and '{'. -nl_while_brace = remove # ignore/add/remove/force - -# (D) Add or remove newline between 'scope (x)' and '{'. -nl_scope_brace = ignore # ignore/add/remove/force - -# (D) Add or remove newline between 'unittest' and '{'. -nl_unittest_brace = ignore # ignore/add/remove/force - -# (D) Add or remove newline between 'version (x)' and '{'. -nl_version_brace = ignore # ignore/add/remove/force - -# (C#) Add or remove newline between 'using' and '{'. -nl_using_brace = remove # ignore/add/remove/force - -# Add or remove newline between two open or close braces. Due to general -# newline/brace handling, REMOVE may not work. -nl_brace_brace = ignore # ignore/add/remove/force - -# Add or remove newline between 'do' and '{'. -nl_do_brace = remove # ignore/add/remove/force - -# Add or remove newline between '}' and 'while' of 'do' statement. -nl_brace_while = remove # ignore/add/remove/force - -# Add or remove newline between 'switch' and '{'. -nl_switch_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'synchronized' and '{'. -nl_synchronized_brace = ignore # ignore/add/remove/force - -# Add a newline between ')' and '{' if the ')' is on a different line than the -# if/for/etc. -# -# Overrides nl_for_brace, nl_if_brace, nl_switch_brace, nl_while_switch and -# nl_catch_brace. -nl_multi_line_cond = false # true/false - -# Force a newline in a define after the macro name for multi-line defines. -nl_multi_line_define = false # true/false - -# Whether to add a newline before 'case', and a blank line before a 'case' -# statement that follows a ';' or '}'. -nl_before_case = false # true/false - -# Whether to add a newline after a 'case' statement. -nl_after_case = false # true/false - -# Add or remove newline between a case ':' and '{'. -# -# Overrides nl_after_case. -nl_case_colon_brace = ignore # ignore/add/remove/force - -# Add or remove newline between ')' and 'throw'. -nl_before_throw = remove # ignore/add/remove/force - -# Add or remove newline between 'namespace' and '{'. -nl_namespace_brace = remove # ignore/add/remove/force - -# Add or remove newline between 'template<>' and whatever follows. -nl_template_class = ignore # ignore/add/remove/force - -# Add or remove newline between 'class' and '{'. -nl_class_brace = remove # ignore/add/remove/force - -# Add or remove newline before or after (depending on pos_class_comma, -# may not be IGNORE) each',' in the base class list. -nl_class_init_args = remove # ignore/add/remove/force - -# Add or remove newline after each ',' in the constructor member -# initialization. Related to nl_constr_colon, pos_constr_colon and -# pos_constr_comma. -nl_constr_init_args = ignore # ignore/add/remove/force - -# Add or remove newline before first element, after comma, and after last -# element, in 'enum'. -nl_enum_own_lines = ignore # ignore/add/remove/force - -# Add or remove newline between return type and function name in a function -# definition. -nl_func_type_name = remove # ignore/add/remove/force - -# Add or remove newline between return type and function name inside a class -# definition. If set to ignore, nl_func_type_name or nl_func_proto_type_name -# is used instead. -nl_func_type_name_class = remove # ignore/add/remove/force - -# Add or remove newline between class specification and '::' -# in 'void A::f() { }'. Only appears in separate member implementation (does -# not appear with in-line implementation). -nl_func_class_scope = ignore # ignore/add/remove/force - -# Add or remove newline between function scope and name, as in -# 'void A :: f() { }'. -nl_func_scope_name = ignore # ignore/add/remove/force - -# Add or remove newline between return type and function name in a prototype. -nl_func_proto_type_name = remove # ignore/add/remove/force - -# Add or remove newline between a function name and the opening '(' in the -# declaration. -nl_func_paren = remove # ignore/add/remove/force - -# Overrides nl_func_paren for functions with no parameters. -nl_func_paren_empty = ignore # ignore/add/remove/force - -# Add or remove newline between a function name and the opening '(' in the -# definition. -nl_func_def_paren = remove # ignore/add/remove/force - -# Overrides nl_func_def_paren for functions with no parameters. -nl_func_def_paren_empty = ignore # ignore/add/remove/force - -# Add or remove newline between a function name and the opening '(' in the -# call. -nl_func_call_paren = ignore # ignore/add/remove/force - -# Overrides nl_func_call_paren for functions with no parameters. -nl_func_call_paren_empty = ignore # ignore/add/remove/force - -# Add or remove newline after '(' in a function declaration. -nl_func_decl_start = remove # ignore/add/remove/force - -# Add or remove newline after '(' in a function definition. -nl_func_def_start = remove # ignore/add/remove/force - -# Overrides nl_func_decl_start when there is only one parameter. -nl_func_decl_start_single = ignore # ignore/add/remove/force - -# Overrides nl_func_def_start when there is only one parameter. -nl_func_def_start_single = ignore # ignore/add/remove/force - -# Whether to add a newline after '(' in a function declaration if '(' and ')' -# are in different lines. If false, nl_func_decl_start is used instead. -nl_func_decl_start_multi_line = false # true/false - -# Whether to add a newline after '(' in a function definition if '(' and ')' -# are in different lines. If false, nl_func_def_start is used instead. -nl_func_def_start_multi_line = false # true/false - -# Add or remove newline after each ',' in a function declaration. -nl_func_decl_args = ignore # ignore/add/remove/force - -# Add or remove newline after each ',' in a function definition. -nl_func_def_args = ignore # ignore/add/remove/force - -# Whether to add a newline after each ',' in a function declaration if '(' -# and ')' are in different lines. If false, nl_func_decl_args is used instead. -nl_func_decl_args_multi_line = false # true/false - -# Whether to add a newline after each ',' in a function definition if '(' -# and ')' are in different lines. If false, nl_func_def_args is used instead. -nl_func_def_args_multi_line = false # true/false - -# Add or remove newline before the ')' in a function declaration. -nl_func_decl_end = remove # ignore/add/remove/force - -# Add or remove newline before the ')' in a function definition. -nl_func_def_end = remove # ignore/add/remove/force - -# Overrides nl_func_decl_end when there is only one parameter. -nl_func_decl_end_single = ignore # ignore/add/remove/force - -# Overrides nl_func_def_end when there is only one parameter. -nl_func_def_end_single = ignore # ignore/add/remove/force - -# Whether to add a newline before ')' in a function declaration if '(' and ')' -# are in different lines. If false, nl_func_decl_end is used instead. -nl_func_decl_end_multi_line = false # true/false - -# Whether to add a newline before ')' in a function definition if '(' and ')' -# are in different lines. If false, nl_func_def_end is used instead. -nl_func_def_end_multi_line = false # true/false - -# Add or remove newline between '()' in a function declaration. -nl_func_decl_empty = remove # ignore/add/remove/force - -# Add or remove newline between '()' in a function definition. -nl_func_def_empty = remove # ignore/add/remove/force - -# Add or remove newline between '()' in a function call. -nl_func_call_empty = ignore # ignore/add/remove/force - -# Whether to add a newline after '(' in a function call, -# has preference over nl_func_call_start_multi_line. -nl_func_call_start = ignore # ignore/add/remove/force - -# Whether to add a newline after '(' in a function call if '(' and ')' are in -# different lines. -nl_func_call_start_multi_line = false # true/false - -# Whether to add a newline after each ',' in a function call if '(' and ')' -# are in different lines. -nl_func_call_args_multi_line = false # true/false - -# Whether to add a newline before ')' in a function call if '(' and ')' are in -# different lines. -nl_func_call_end_multi_line = false # true/false - -# (OC) Whether to put each Objective-C message parameter on a separate line. -# See nl_oc_msg_leave_one_liner. -nl_oc_msg_args = false # true/false - -# Add or remove newline between function signature and '{'. -nl_fdef_brace = remove # ignore/add/remove/force - -# Add or remove newline between function signature and '{', -# if signature ends with ')'. Overrides nl_fdef_brace. -nl_fdef_brace_cond = ignore # ignore/add/remove/force - -# Add or remove newline between C++11 lambda signature and '{'. -nl_cpp_ldef_brace = ignore # ignore/add/remove/force - -# Add or remove newline between 'return' and the return expression. -nl_return_expr = remove # ignore/add/remove/force - -# Whether to add a newline after semicolons, except in 'for' statements. -nl_after_semicolon = false # true/false - -# (Java) Add or remove newline between the ')' and '{{' of the double brace -# initializer. -nl_paren_dbrace_open = ignore # ignore/add/remove/force - -# Whether to add a newline after the type in an unnamed temporary -# direct-list-initialization. -nl_type_brace_init_lst = ignore # ignore/add/remove/force - -# Whether to add a newline after the open brace in an unnamed temporary -# direct-list-initialization. -nl_type_brace_init_lst_open = ignore # ignore/add/remove/force - -# Whether to add a newline before the close brace in an unnamed temporary -# direct-list-initialization. -nl_type_brace_init_lst_close = ignore # ignore/add/remove/force - -# Whether to add a newline after '{'. This also adds a newline before the -# matching '}'. -nl_after_brace_open = false # true/false - -# Whether to add a newline between the open brace and a trailing single-line -# comment. Requires nl_after_brace_open=true. -nl_after_brace_open_cmt = false # true/false - -# Whether to add a newline after a virtual brace open with a non-empty body. -# These occur in un-braced if/while/do/for statement bodies. -nl_after_vbrace_open = false # true/false - -# Whether to add a newline after a virtual brace open with an empty body. -# These occur in un-braced if/while/do/for statement bodies. -nl_after_vbrace_open_empty = false # true/false - -# Whether to add a newline after '}'. Does not apply if followed by a -# necessary ';'. -nl_after_brace_close = false # true/false - -# Whether to add a newline after a virtual brace close, -# as in 'if (foo) a++; return;'. -nl_after_vbrace_close = false # true/false - -# Add or remove newline between the close brace and identifier, -# as in 'struct { int a; } b;'. Affects enumerations, unions and -# structures. If set to ignore, uses nl_after_brace_close. -nl_brace_struct_var = ignore # ignore/add/remove/force - -# Whether to alter newlines in '#define' macros. -nl_define_macro = false # true/false - -# Whether to alter newlines between consecutive parenthesis closes. The number -# of closing parentheses in a line will depend on respective open parenthesis -# lines. -nl_squeeze_paren_close = false # true/false - -# Whether to remove blanks after '#ifxx' and '#elxx', or before '#elxx' and -# '#endif'. Does not affect top-level #ifdefs. -nl_squeeze_ifdef = false # true/false - -# Makes the nl_squeeze_ifdef option affect the top-level #ifdefs as well. -nl_squeeze_ifdef_top_level = false # true/false - -# Add or remove blank line before 'if'. -nl_before_if = ignore # ignore/add/remove/force - -# Add or remove blank line after 'if' statement. Add/Force work only if the -# next token is not a closing brace. -nl_after_if = ignore # ignore/add/remove/force - -# Add or remove blank line before 'for'. -nl_before_for = ignore # ignore/add/remove/force - -# Add or remove blank line after 'for' statement. -nl_after_for = ignore # ignore/add/remove/force - -# Add or remove blank line before 'while'. -nl_before_while = ignore # ignore/add/remove/force - -# Add or remove blank line after 'while' statement. -nl_after_while = ignore # ignore/add/remove/force - -# Add or remove blank line before 'switch'. -nl_before_switch = ignore # ignore/add/remove/force - -# Add or remove blank line after 'switch' statement. -nl_after_switch = ignore # ignore/add/remove/force - -# Add or remove blank line before 'synchronized'. -nl_before_synchronized = ignore # ignore/add/remove/force - -# Add or remove blank line after 'synchronized' statement. -nl_after_synchronized = ignore # ignore/add/remove/force - -# Add or remove blank line before 'do'. -nl_before_do = ignore # ignore/add/remove/force - -# Add or remove blank line after 'do/while' statement. -nl_after_do = ignore # ignore/add/remove/force - -# Whether to put a blank line before 'return' statements, unless after an open -# brace. -nl_before_return = false # true/false - -# Whether to put a blank line after 'return' statements, unless followed by a -# close brace. -nl_after_return = false # true/false - -# Whether to double-space commented-entries in 'struct'/'union'/'enum'. -nl_ds_struct_enum_cmt = false # true/false - -# Whether to force a newline before '}' of a 'struct'/'union'/'enum'. -# (Lower priority than eat_blanks_before_close_brace.) -nl_ds_struct_enum_close_brace = false # true/false - -# Add or remove newline before or after (depending on pos_class_colon) a class -# colon, as in 'class Foo : public Bar'. -nl_class_colon = ignore # ignore/add/remove/force - -# Add or remove newline around a class constructor colon. The exact position -# depends on nl_constr_init_args, pos_constr_colon and pos_constr_comma. -nl_constr_colon = ignore # ignore/add/remove/force - -# Whether to collapse a two-line namespace, like 'namespace foo\n{ decl; }' -# into a single line. If true, prevents other brace newline rules from turning -# such code into four lines. -nl_namespace_two_to_one_liner = false # true/false - -# Whether to remove a newline in simple unbraced if statements, turning them -# into one-liners, as in 'if(b)\n i++;' => 'if(b) i++;'. -nl_create_if_one_liner = false # true/false - -# Whether to remove a newline in simple unbraced for statements, turning them -# into one-liners, as in 'for (...)\n stmt;' => 'for (...) stmt;'. -nl_create_for_one_liner = false # true/false - -# Whether to remove a newline in simple unbraced while statements, turning -# them into one-liners, as in 'while (expr)\n stmt;' => 'while (expr) stmt;'. -nl_create_while_one_liner = false # true/false - -# Whether to collapse a function definition whose body (not counting braces) -# is only one line so that the entire definition (prototype, braces, body) is -# a single line. -nl_create_func_def_one_liner = false # true/false - -# Whether to split one-line simple unbraced if statements into two lines by -# adding a newline, as in 'if(b) i++;'. -nl_split_if_one_liner = false # true/false - -# Whether to split one-line simple unbraced for statements into two lines by -# adding a newline, as in 'for (...) stmt;'. -nl_split_for_one_liner = false # true/false - -# Whether to split one-line simple unbraced while statements into two lines by -# adding a newline, as in 'while (expr) stmt;'. -nl_split_while_one_liner = false # true/false - -# -# Blank line options -# - -# The maximum number of consecutive newlines (3 = 2 blank lines). -nl_max = 0 # unsigned number - -# The maximum number of consecutive newlines in a function. -nl_max_blank_in_func = 0 # unsigned number - -# The number of newlines before a function prototype. -nl_before_func_body_proto = 0 # unsigned number - -# The number of newlines before a multi-line function definition. -nl_before_func_body_def = 0 # unsigned number - -# The number of newlines before a class constructor/destructor prototype. -nl_before_func_class_proto = 0 # unsigned number - -# The number of newlines before a class constructor/destructor definition. -nl_before_func_class_def = 0 # unsigned number - -# The number of newlines after a function prototype. -nl_after_func_proto = 0 # unsigned number - -# The number of newlines after a function prototype, if not followed by -# another function prototype. -nl_after_func_proto_group = 2 # unsigned number - -# The number of newlines after a class constructor/destructor prototype. -nl_after_func_class_proto = 0 # unsigned number - -# The number of newlines after a class constructor/destructor prototype, -# if not followed by another constructor/destructor prototype. -nl_after_func_class_proto_group = 0 # unsigned number - -# Whether one-line method definitions inside a class body should be treated -# as if they were prototypes for the purposes of adding newlines. -# -# Requires nl_class_leave_one_liners=true. Overrides nl_before_func_body_def -# and nl_before_func_class_def for one-liners. -nl_class_leave_one_liner_groups = false # true/false - -# The number of newlines after '}' of a multi-line function body. -nl_after_func_body = 2 # unsigned number - -# The number of newlines after '}' of a multi-line function body in a class -# declaration. Also affects class constructors/destructors. -# -# Overrides nl_after_func_body. -nl_after_func_body_class = 2 # unsigned number - -# The number of newlines after '}' of a single line function body. Also -# affects class constructors/destructors. -# -# Overrides nl_after_func_body and nl_after_func_body_class. -nl_after_func_body_one_liner = 0 # unsigned number - -# The number of blank lines after a block of variable definitions at the top -# of a function body. -# -# 0 = No change (default). -nl_func_var_def_blk = 0 # unsigned number - -# The number of newlines before a block of typedefs. If nl_after_access_spec -# is non-zero, that option takes precedence. -# -# 0 = No change (default). -nl_typedef_blk_start = 0 # unsigned number - -# The number of newlines after a block of typedefs. -# -# 0 = No change (default). -nl_typedef_blk_end = 0 # unsigned number - -# The maximum number of consecutive newlines within a block of typedefs. -# -# 0 = No change (default). -nl_typedef_blk_in = 0 # unsigned number - -# The number of newlines before a block of variable definitions not at the top -# of a function body. If nl_after_access_spec is non-zero, that option takes -# precedence. -# -# 0 = No change (default). -nl_var_def_blk_start = 0 # unsigned number - -# The number of newlines after a block of variable definitions not at the top -# of a function body. -# -# 0 = No change (default). -nl_var_def_blk_end = 0 # unsigned number - -# The maximum number of consecutive newlines within a block of variable -# definitions. -# -# 0 = No change (default). -nl_var_def_blk_in = 0 # unsigned number - -# The minimum number of newlines before a multi-line comment. -# Doesn't apply if after a brace open or another multi-line comment. -nl_before_block_comment = 0 # unsigned number - -# The minimum number of newlines before a single-line C comment. -# Doesn't apply if after a brace open or other single-line C comments. -nl_before_c_comment = 0 # unsigned number - -# The minimum number of newlines before a CPP comment. -# Doesn't apply if after a brace open or other CPP comments. -nl_before_cpp_comment = 0 # unsigned number - -# Whether to force a newline after a multi-line comment. -nl_after_multiline_comment = false # true/false - -# Whether to force a newline after a label's colon. -nl_after_label_colon = false # true/false - -# The number of newlines after '}' or ';' of a struct/enum/union definition. -nl_after_struct = 0 # unsigned number - -# The number of newlines before a class definition. -nl_before_class = 0 # unsigned number - -# The number of newlines after '}' or ';' of a class definition. -nl_after_class = 0 # unsigned number - -# The number of newlines before an access specifier label. This also includes -# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count -# if after a brace open. -# -# 0 = No change (default). -nl_before_access_spec = 0 # unsigned number - -# The number of newlines after an access specifier label. This also includes -# the Qt-specific 'signals:' and 'slots:'. Will not change the newline count -# if after a brace open. -# -# 0 = No change (default). -# -# Overrides nl_typedef_blk_start and nl_var_def_blk_start. -nl_after_access_spec = 0 # unsigned number - -# The number of newlines between a function definition and the function -# comment, as in '// comment\n void foo() {...}'. -# -# 0 = No change (default). -nl_comment_func_def = 0 # unsigned number - -# The number of newlines after a try-catch-finally block that isn't followed -# by a brace close. -# -# 0 = No change (default). -nl_after_try_catch_finally = 0 # unsigned number - -# (C#) The number of newlines before and after a property, indexer or event -# declaration. -# -# 0 = No change (default). -nl_around_cs_property = 0 # unsigned number - -# (C#) The number of newlines between the get/set/add/remove handlers. -# -# 0 = No change (default). -nl_between_get_set = 0 # unsigned number - -# (C#) Add or remove newline between property and the '{'. -nl_property_brace = ignore # ignore/add/remove/force - -# The number of newlines after '{' of a namespace. This also adds newlines -# before the matching '}'. -# -# 0 = Apply eat_blanks_after_open_brace or eat_blanks_before_close_brace if -# applicable, otherwise no change. -# -# Overrides eat_blanks_after_open_brace and eat_blanks_before_close_brace. -nl_inside_namespace = 0 # unsigned number - -# Whether to remove blank lines after '{'. -eat_blanks_after_open_brace = false # true/false - -# Whether to remove blank lines before '}'. -eat_blanks_before_close_brace = false # true/false - -# How aggressively to remove extra newlines not in preprocessor. -# -# 0: No change (default) -# 1: Remove most newlines not handled by other config -# 2: Remove all newlines and reformat completely by config -nl_remove_extra_newlines = 0 # unsigned number - -# (Java) Add or remove newline after an annotation statement. Only affects -# annotations that are after a newline. -nl_after_annotation = ignore # ignore/add/remove/force - -# (Java) Add or remove newline between two annotations. -nl_between_annotation = ignore # ignore/add/remove/force - -# -# Positioning options -# - -# The position of arithmetic operators in wrapped expressions. -pos_arith = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of assignment in wrapped expressions. Do not affect '=' -# followed by '{'. -pos_assign = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of Boolean operators in wrapped expressions. -pos_bool = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of comparison operators in wrapped expressions. -pos_compare = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of conditional operators, as in the '?' and ':' of -# 'expr ? stmt : stmt', in wrapped expressions. -pos_conditional = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of the comma in wrapped expressions. -pos_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of the comma in enum entries. -pos_enum_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of the comma in the base class list if there is more than one -# line. Affects nl_class_init_args. -pos_class_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of the comma in the constructor initialization list. -# Related to nl_constr_colon, nl_constr_init_args and pos_constr_colon. -pos_constr_comma = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of trailing/leading class colon, between class and base class -# list. Affects nl_class_colon. -pos_class_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# The position of colons between constructor and member initialization. -# Related to nl_constr_colon, nl_constr_init_args and pos_constr_comma. -pos_constr_colon = ignore # ignore/break/force/lead/trail/join/lead_break/lead_force/trail_break/trail_force - -# -# Line splitting options -# - -# Try to limit code width to N columns. -code_width = 0 # unsigned number - -# Whether to fully split long 'for' statements at semi-colons. -ls_for_split_full = false # true/false - -# Whether to fully split long function prototypes/calls at commas. -# The option ls_code_width has priority over the option ls_func_split_full. -ls_func_split_full = false # true/false - -# Whether to split lines as close to code_width as possible and ignore some -# groupings. -# The option ls_code_width has priority over the option ls_func_split_full. -ls_code_width = false # true/false - -# -# Code alignment options (not left column spaces/tabs) -# - -# Whether to keep non-indenting tabs. -align_keep_tabs = false # true/false - -# Whether to use tabs for aligning. -align_with_tabs = false # true/false - -# Whether to bump out to the next tab when aligning. -align_on_tabstop = false # true/false - -# Whether to right-align numbers. -align_number_right = false # true/false - -# Whether to keep whitespace not required for alignment. -align_keep_extra_space = true # true/false - -# Whether to align variable definitions in prototypes and functions. -align_func_params = false # true/false - -# The span for aligning parameter definitions in function on parameter name. -# -# 0 = Don't align (default). -align_func_params_span = 0 # unsigned number - -# The threshold for aligning function parameter definitions. -# Use a negative number for absolute thresholds. -# -# 0 = No limit (default). -align_func_params_thresh = 0 # number - -# The gap for aligning function parameter definitions. -align_func_params_gap = 0 # unsigned number - -# The span for aligning constructor value. -# -# 0 = Don't align (default). -align_constr_value_span = 0 # unsigned number - -# The threshold for aligning constructor value. -# Use a negative number for absolute thresholds. -# -# 0 = No limit (default). -align_constr_value_thresh = 0 # number - -# The gap for aligning constructor value. -align_constr_value_gap = 0 # unsigned number - -# Whether to align parameters in single-line functions that have the same -# name. The function names must already be aligned with each other. -align_same_func_call_params = false # true/false - -# The span for aligning function-call parameters for single line functions. -# -# 0 = Don't align (default). -align_same_func_call_params_span = 0 # unsigned number - -# The threshold for aligning function-call parameters for single line -# functions. -# Use a negative number for absolute thresholds. -# -# 0 = No limit (default). -align_same_func_call_params_thresh = 0 # number - -# The span for aligning variable definitions. -# -# 0 = Don't align (default). -align_var_def_span = 0 # unsigned number - -# How to consider (or treat) the '*' in the alignment of variable definitions. -# -# 0: Part of the type 'void * foo;' (default) -# 1: Part of the variable 'void *foo;' -# 2: Dangling 'void *foo;' -# Dangling: the '*' will not be taken into account when aligning. -align_var_def_star_style = 0 # unsigned number - -# How to consider (or treat) the '&' in the alignment of variable definitions. -# -# 0: Part of the type 'long & foo;' (default) -# 1: Part of the variable 'long &foo;' -# 2: Dangling 'long &foo;' -# Dangling: the '&' will not be taken into account when aligning. -align_var_def_amp_style = 0 # unsigned number - -# The threshold for aligning variable definitions. -# Use a negative number for absolute thresholds. -# -# 0 = No limit (default). -align_var_def_thresh = 0 # number - -# The gap for aligning variable definitions. -align_var_def_gap = 0 # unsigned number - -# Whether to align the colon in struct bit fields. -align_var_def_colon = false # true/false - -# The gap for aligning the colon in struct bit fields. -align_var_def_colon_gap = 0 # unsigned number - -# Whether to align any attribute after the variable name. -align_var_def_attribute = false # true/false - -# Whether to align inline struct/enum/union variable definitions. -align_var_def_inline = false # true/false - -# The span for aligning on '=' in assignments. -# -# 0 = Don't align (default). -align_assign_span = 0 # unsigned number - -# The span for aligning on '=' in function prototype modifier. -# -# 0 = Don't align (default). -align_assign_func_proto_span = 0 # unsigned number - -# The threshold for aligning on '=' in assignments. -# Use a negative number for absolute thresholds. -# -# 0 = No limit (default). -align_assign_thresh = 0 # number - -# How to apply align_assign_span to function declaration "assignments", i.e. -# 'virtual void foo() = 0' or '~foo() = {default|delete}'. -# -# 0: Align with other assignments (default) -# 1: Align with each other, ignoring regular assignments -# 2: Don't align -align_assign_decl_func = 0 # unsigned number - -# The span for aligning on '=' in enums. -# -# 0 = Don't align (default). -align_enum_equ_span = 0 # unsigned number - -# The threshold for aligning on '=' in enums. -# Use a negative number for absolute thresholds. -# -# 0 = no limit (default). -align_enum_equ_thresh = 0 # number - -# The span for aligning class member definitions. -# -# 0 = Don't align (default). -align_var_class_span = 0 # unsigned number - -# The threshold for aligning class member definitions. -# Use a negative number for absolute thresholds. -# -# 0 = No limit (default). -align_var_class_thresh = 0 # number - -# The gap for aligning class member definitions. -align_var_class_gap = 0 # unsigned number - -# The span for aligning struct/union member definitions. -# -# 0 = Don't align (default). -align_var_struct_span = 0 # unsigned number - -# The threshold for aligning struct/union member definitions. -# Use a negative number for absolute thresholds. -# -# 0 = No limit (default). -align_var_struct_thresh = 0 # number - -# The gap for aligning struct/union member definitions. -align_var_struct_gap = 0 # unsigned number - -# The span for aligning struct initializer values. -# -# 0 = Don't align (default). -align_struct_init_span = 0 # unsigned number - -# The span for aligning single-line typedefs. -# -# 0 = Don't align (default). -align_typedef_span = 0 # unsigned number - -# The minimum space between the type and the synonym of a typedef. -align_typedef_gap = 0 # unsigned number - -# How to align typedef'd functions with other typedefs. -# -# 0: Don't mix them at all (default) -# 1: Align the open parenthesis with the types -# 2: Align the function type name with the other type names -align_typedef_func = 0 # unsigned number - -# How to consider (or treat) the '*' in the alignment of typedefs. -# -# 0: Part of the typedef type, 'typedef int * pint;' (default) -# 1: Part of type name: 'typedef int *pint;' -# 2: Dangling: 'typedef int *pint;' -# Dangling: the '*' will not be taken into account when aligning. -align_typedef_star_style = 0 # unsigned number - -# How to consider (or treat) the '&' in the alignment of typedefs. -# -# 0: Part of the typedef type, 'typedef int & intref;' (default) -# 1: Part of type name: 'typedef int &intref;' -# 2: Dangling: 'typedef int &intref;' -# Dangling: the '&' will not be taken into account when aligning. -align_typedef_amp_style = 0 # unsigned number - -# The span for aligning comments that end lines. -# -# 0 = Don't align (default). -align_right_cmt_span = 0 # unsigned number - -# Minimum number of columns between preceding text and a trailing comment in -# order for the comment to qualify for being aligned. Must be non-zero to have -# an effect. -align_right_cmt_gap = 0 # unsigned number - -# If aligning comments, whether to mix with comments after '}' and #endif with -# less than three spaces before the comment. -align_right_cmt_mix = false # true/false - -# Whether to only align trailing comments that are at the same brace level. -align_right_cmt_same_level = false # true/false - -# Minimum column at which to align trailing comments. Comments which are -# aligned beyond this column, but which can be aligned in a lesser column, -# may be "pulled in". -# -# 0 = Ignore (default). -align_right_cmt_at_col = 0 # unsigned number - -# The span for aligning function prototypes. -# -# 0 = Don't align (default). -align_func_proto_span = 0 # unsigned number - -# The threshold for aligning function prototypes. -# Use a negative number for absolute thresholds. -# -# 0 = No limit (default). -align_func_proto_thresh = 0 # number - -# Minimum gap between the return type and the function name. -align_func_proto_gap = 0 # unsigned number - -# Whether to align function prototypes on the 'operator' keyword instead of -# what follows. -align_on_operator = false # true/false - -# Whether to mix aligning prototype and variable declarations. If true, -# align_var_def_XXX options are used instead of align_func_proto_XXX options. -align_mix_var_proto = false # true/false - -# Whether to align single-line functions with function prototypes. -# Uses align_func_proto_span. -align_single_line_func = false # true/false - -# Whether to align the open brace of single-line functions. -# Requires align_single_line_func=true. Uses align_func_proto_span. -align_single_line_brace = false # true/false - -# Gap for align_single_line_brace. -align_single_line_brace_gap = 0 # unsigned number - -# (OC) The span for aligning Objective-C message specifications. -# -# 0 = Don't align (default). -align_oc_msg_spec_span = 0 # unsigned number - -# Whether to align macros wrapped with a backslash and a newline. This will -# not work right if the macro contains a multi-line comment. -align_nl_cont = false # true/false - -# Whether to align macro functions and variables together. -align_pp_define_together = false # true/false - -# The span for aligning on '#define' bodies. -# -# =0: Don't align (default) -# >0: Number of lines (including comments) between blocks -align_pp_define_span = 0 # unsigned number - -# The minimum space between label and value of a preprocessor define. -align_pp_define_gap = 0 # unsigned number - -# Whether to align lines that start with '<<' with previous '<<'. -# -# Default: true -align_left_shift = true # true/false - -# Whether to align text after 'asm volatile ()' colons. -align_asm_colon = false # true/false - -# (OC) Span for aligning parameters in an Objective-C message call -# on the ':'. -# -# 0 = Don't align. -align_oc_msg_colon_span = 0 # unsigned number - -# (OC) Whether to always align with the first parameter, even if it is too -# short. -align_oc_msg_colon_first = false # true/false - -# (OC) Whether to align parameters in an Objective-C '+' or '-' declaration -# on the ':'. -align_oc_decl_colon = false # true/false - -# -# Comment modification options -# - -# Try to wrap comments at N columns. -cmt_width = 0 # unsigned number - -# How to reflow comments. -# -# 0: No reflowing (apart from the line wrapping due to cmt_width) (default) -# 1: No touching at all -# 2: Full reflow -cmt_reflow_mode = 0 # unsigned number - -# Whether to convert all tabs to spaces in comments. If false, tabs in -# comments are left alone, unless used for indenting. -cmt_convert_tab_to_spaces = false # true/false - -# Whether to apply changes to multi-line comments, including cmt_width, -# keyword substitution and leading chars. -# -# Default: true -cmt_indent_multi = true # true/false - -# Whether to group c-comments that look like they are in a block. -cmt_c_group = false # true/false - -# Whether to put an empty '/*' on the first line of the combined c-comment. -cmt_c_nl_start = false # true/false - -# Whether to add a newline before the closing '*/' of the combined c-comment. -cmt_c_nl_end = false # true/false - -# Whether to change cpp-comments into c-comments. -cmt_cpp_to_c = false # true/false - -# Whether to group cpp-comments that look like they are in a block. Only -# meaningful if cmt_cpp_to_c=true. -cmt_cpp_group = false # true/false - -# Whether to put an empty '/*' on the first line of the combined cpp-comment -# when converting to a c-comment. -# -# Requires cmt_cpp_to_c=true and cmt_cpp_group=true. -cmt_cpp_nl_start = false # true/false - -# Whether to add a newline before the closing '*/' of the combined cpp-comment -# when converting to a c-comment. -# -# Requires cmt_cpp_to_c=true and cmt_cpp_group=true. -cmt_cpp_nl_end = false # true/false - -# Whether to put a star on subsequent comment lines. -cmt_star_cont = false # true/false - -# The number of spaces to insert at the start of subsequent comment lines. -cmt_sp_before_star_cont = 0 # unsigned number - -# The number of spaces to insert after the star on subsequent comment lines. -cmt_sp_after_star_cont = 0 # unsigned number - -# For multi-line comments with a '*' lead, remove leading spaces if the first -# and last lines of the comment are the same length. -# -# Default: true -cmt_multi_check_last = true # true/false - -# For multi-line comments with a '*' lead, remove leading spaces if the first -# and last lines of the comment are the same length AND if the length is -# bigger as the first_len minimum. -# -# Default: 4 -cmt_multi_first_len_minimum = 4 # unsigned number - -# Path to a file that contains text to insert at the beginning of a file if -# the file doesn't start with a C/C++ comment. If the inserted text contains -# '$(filename)', that will be replaced with the current file's name. -cmt_insert_file_header = "" # string - -# Path to a file that contains text to insert at the end of a file if the -# file doesn't end with a C/C++ comment. If the inserted text contains -# '$(filename)', that will be replaced with the current file's name. -cmt_insert_file_footer = "" # string - -# Path to a file that contains text to insert before a function definition if -# the function isn't preceded by a C/C++ comment. If the inserted text -# contains '$(function)', '$(javaparam)' or '$(fclass)', these will be -# replaced with, respectively, the name of the function, the javadoc '@param' -# and '@return' stuff, or the name of the class to which the member function -# belongs. -cmt_insert_func_header = "" # string - -# Path to a file that contains text to insert before a class if the class -# isn't preceded by a C/C++ comment. If the inserted text contains '$(class)', -# that will be replaced with the class name. -cmt_insert_class_header = "" # string - -# Path to a file that contains text to insert before an Objective-C message -# specification, if the method isn't preceded by a C/C++ comment. If the -# inserted text contains '$(message)' or '$(javaparam)', these will be -# replaced with, respectively, the name of the function, or the javadoc -# '@param' and '@return' stuff. -cmt_insert_oc_msg_header = "" # string - -# Whether a comment should be inserted if a preprocessor is encountered when -# stepping backwards from a function name. -# -# Applies to cmt_insert_oc_msg_header, cmt_insert_func_header and -# cmt_insert_class_header. -cmt_insert_before_preproc = false # true/false - -# Whether a comment should be inserted if a function is declared inline to a -# class definition. -# -# Applies to cmt_insert_func_header. -# -# Default: true -cmt_insert_before_inlines = true # true/false - -# Whether a comment should be inserted if the function is a class constructor -# or destructor. -# -# Applies to cmt_insert_func_header. -cmt_insert_before_ctor_dtor = false # true/false - -# -# Code modifying options (non-whitespace) -# - -# Add or remove braces on a single-line 'do' statement. -mod_full_brace_do = ignore # ignore/add/remove/force - -# Add or remove braces on a single-line 'for' statement. -mod_full_brace_for = ignore # ignore/add/remove/force - -# (Pawn) Add or remove braces on a single-line function definition. -mod_full_brace_function = ignore # ignore/add/remove/force - -# Add or remove braces on a single-line 'if' statement. Braces will not be -# removed if the braced statement contains an 'else'. -mod_full_brace_if = ignore # ignore/add/remove/force - -# Whether to enforce that all blocks of an 'if'/'else if'/'else' chain either -# have, or do not have, braces. If true, braces will be added if any block -# needs braces, and will only be removed if they can be removed from all -# blocks. -# -# Overrides mod_full_brace_if. -mod_full_brace_if_chain = false # true/false - -# Whether to add braces to all blocks of an 'if'/'else if'/'else' chain. -# If true, mod_full_brace_if_chain will only remove braces from an 'if' that -# does not have an 'else if' or 'else'. -mod_full_brace_if_chain_only = false # true/false - -# Add or remove braces on single-line 'while' statement. -mod_full_brace_while = ignore # ignore/add/remove/force - -# Add or remove braces on single-line 'using ()' statement. -mod_full_brace_using = ignore # ignore/add/remove/force - -# Don't remove braces around statements that span N newlines -mod_full_brace_nl = 0 # unsigned number - -# Whether to prevent removal of braces from 'if'/'for'/'while'/etc. blocks -# which span multiple lines. -# -# Affects: -# mod_full_brace_for -# mod_full_brace_if -# mod_full_brace_if_chain -# mod_full_brace_if_chain_only -# mod_full_brace_while -# mod_full_brace_using -# -# Does not affect: -# mod_full_brace_do -# mod_full_brace_function -mod_full_brace_nl_block_rem_mlcond = false # true/false - -# Add or remove unnecessary parenthesis on 'return' statement. -mod_paren_on_return = ignore # ignore/add/remove/force - -# (Pawn) Whether to change optional semicolons to real semicolons. -mod_pawn_semicolon = false # true/false - -# Whether to fully parenthesize Boolean expressions in 'while' and 'if' -# statement, as in 'if (a && b > c)' => 'if (a && (b > c))'. -mod_full_paren_if_bool = false # true/false - -# Whether to remove superfluous semicolons. -mod_remove_extra_semicolon = false # true/false - -# If a function body exceeds the specified number of newlines and doesn't have -# a comment after the close brace, a comment will be added. -mod_add_long_function_closebrace_comment = 0 # unsigned number - -# If a namespace body exceeds the specified number of newlines and doesn't -# have a comment after the close brace, a comment will be added. -mod_add_long_namespace_closebrace_comment = 0 # unsigned number - -# If a class body exceeds the specified number of newlines and doesn't have a -# comment after the close brace, a comment will be added. -mod_add_long_class_closebrace_comment = 0 # unsigned number - -# If a switch body exceeds the specified number of newlines and doesn't have a -# comment after the close brace, a comment will be added. -mod_add_long_switch_closebrace_comment = 0 # unsigned number - -# If an #ifdef body exceeds the specified number of newlines and doesn't have -# a comment after the #endif, a comment will be added. -mod_add_long_ifdef_endif_comment = 0 # unsigned number - -# If an #ifdef or #else body exceeds the specified number of newlines and -# doesn't have a comment after the #else, a comment will be added. -mod_add_long_ifdef_else_comment = 0 # unsigned number - -# Whether to sort consecutive single-line 'import' statements. -mod_sort_import = false # true/false - -# (C#) Whether to sort consecutive single-line 'using' statements. -mod_sort_using = false # true/false - -# Whether to sort consecutive single-line '#include' statements (C/C++) and -# '#import' statements (Objective-C). Be aware that this has the potential to -# break your code if your includes/imports have ordering dependencies. -mod_sort_include = false # true/false - -# Whether to move a 'break' that appears after a fully braced 'case' before -# the close brace, as in 'case X: { ... } break;' => 'case X: { ... break; }'. -mod_move_case_break = false # true/false - -# Add or remove braces around a fully braced case statement. Will only remove -# braces if there are no variable declarations in the block. -mod_case_brace = ignore # ignore/add/remove/force - -# Whether to remove a void 'return;' that appears as the last statement in a -# function. -mod_remove_empty_return = false # true/false - -# Add or remove the comma after the last value of an enumeration. -mod_enum_last_comma = ignore # ignore/add/remove/force - -# (OC) Whether to organize the properties. If true, properties will be -# rearranged according to the mod_sort_oc_property_*_weight factors. -mod_sort_oc_properties = false # true/false - -# (OC) Weight of a class property modifier. -mod_sort_oc_property_class_weight = 0 # number - -# (OC) Weight of 'atomic' and 'nonatomic'. -mod_sort_oc_property_thread_safe_weight = 0 # number - -# (OC) Weight of 'readwrite' when organizing properties. -mod_sort_oc_property_readwrite_weight = 0 # number - -# (OC) Weight of a reference type specifier ('retain', 'copy', 'assign', -# 'weak', 'strong') when organizing properties. -mod_sort_oc_property_reference_weight = 0 # number - -# (OC) Weight of getter type ('getter=') when organizing properties. -mod_sort_oc_property_getter_weight = 0 # number - -# (OC) Weight of setter type ('setter=') when organizing properties. -mod_sort_oc_property_setter_weight = 0 # number - -# (OC) Weight of nullability type ('nullable', 'nonnull', 'null_unspecified', -# 'null_resettable') when organizing properties. -mod_sort_oc_property_nullability_weight = 0 # number - -# -# Preprocessor options -# - -# Add or remove indentation of preprocessor directives inside #if blocks -# at brace level 0 (file-level). -pp_indent = ignore # ignore/add/remove/force - -# Whether to indent #if/#else/#endif at the brace level. If false, these are -# indented from column 1. -pp_indent_at_level = false # true/false - -# Specifies the number of columns to indent preprocessors per level -# at brace level 0 (file-level). If pp_indent_at_level=false, also specifies -# the number of columns to indent preprocessors per level -# at brace level > 0 (function-level). -# -# Default: 1 -pp_indent_count = 1 # unsigned number - -# Add or remove space after # based on pp_level of #if blocks. -pp_space = ignore # ignore/add/remove/force - -# Sets the number of spaces per level added with pp_space. -pp_space_count = 0 # unsigned number - -# The indent for '#region' and '#endregion' in C# and '#pragma region' in -# C/C++. Negative values decrease indent down to the first column. -pp_indent_region = 0 # number - -# Whether to indent the code between #region and #endregion. -pp_region_indent_code = false # true/false - -# If pp_indent_at_level=true, sets the indent for #if, #else and #endif when -# not at file-level. Negative values decrease indent down to the first column. -# -# =0: Indent preprocessors using output_tab_size -# >0: Column at which all preprocessors will be indented -pp_indent_if = 0 # number - -# Whether to indent the code between #if, #else and #endif. -pp_if_indent_code = false # true/false - -# Whether to indent '#define' at the brace level. If false, these are -# indented from column 1. -pp_define_at_level = false # true/false - -# Whether to ignore the '#define' body while formatting. -pp_ignore_define_body = false # true/false - -# Whether to indent case statements between #if, #else, and #endif. -# Only applies to the indent of the preprocessor that the case statements -# directly inside of. -# -# Default: true -pp_indent_case = true # true/false - -# Whether to indent whole function definitions between #if, #else, and #endif. -# Only applies to the indent of the preprocessor that the function definition -# is directly inside of. -# -# Default: true -pp_indent_func_def = true # true/false - -# Whether to indent extern C blocks between #if, #else, and #endif. -# Only applies to the indent of the preprocessor that the extern block is -# directly inside of. -# -# Default: true -pp_indent_extern = true # true/false - -# Whether to indent braces directly inside #if, #else, and #endif. -# Only applies to the indent of the preprocessor that the braces are directly -# inside of. -# -# Default: true -pp_indent_brace = true # true/false - -# -# Sort includes options -# - -# The regex for include category with priority 0. -include_category_0 = "" # string - -# The regex for include category with priority 1. -include_category_1 = "" # string - -# The regex for include category with priority 2. -include_category_2 = "" # string - -# -# Use or Do not Use options -# - -# true: indent_func_call_param will be used (default) -# false: indent_func_call_param will NOT be used -# -# Default: true -use_indent_func_call_param = true # true/false - -# The value of the indentation for a continuation line is calculated -# differently if the statement is: -# - a declaration: your case with QString fileName ... -# - an assignment: your case with pSettings = new QSettings( ... -# -# At the second case the indentation value might be used twice: -# - at the assignment -# - at the function call (if present) -# -# To prevent the double use of the indentation value, use this option with the -# value 'true'. -# -# true: indent_continue will be used only once -# false: indent_continue will be used every time (default) -use_indent_continue_only_once = false # true/false - -# The value might be used twice: -# - at the assignment -# - at the opening brace -# -# To prevent the double use of the indentation value, use this option with the -# value 'true'. -# -# true: indentation will be used only once -# false: indentation will be used every time (default) -indent_cpp_lambda_only_once = false # true/false - -# Whether to apply special formatting for Qt SIGNAL/SLOT macros. Essentially, -# this tries to format these so that they match Qt's normalized form (i.e. the -# result of QMetaObject::normalizedSignature), which can slightly improve the -# performance of the QObject::connect call, rather than how they would -# otherwise be formatted. -# -# See options_for_QT.cpp for details. -# -# Default: true -use_options_overriding_for_qt_macros = true # true/false - -# -# Warn levels - 1: error, 2: warning (default), 3: note -# - -# (C#) Warning is given if doing tab-to-\t replacement and we have found one -# in a C# verbatim string literal. -# -# Default: 2 -warn_level_tabs_found_in_verbatim_string_literals = 2 # unsigned number - -# Meaning of the settings: -# Ignore - do not do any changes -# Add - makes sure there is 1 or more space/brace/newline/etc -# Force - makes sure there is exactly 1 space/brace/newline/etc, -# behaves like Add in some contexts -# Remove - removes space/brace/newline/etc -# -# -# - Token(s) can be treated as specific type(s) with the 'set' option: -# `set tokenType tokenString [tokenString...]` -# -# Example: -# `set BOOL __AND__ __OR__` -# -# tokenTypes are defined in src/token_enum.h, use them without the -# 'CT_' prefix: 'CT_BOOL' => 'BOOL' -# -# -# - Token(s) can be treated as type(s) with the 'type' option. -# `type tokenString [tokenString...]` -# -# Example: -# `type int c_uint_8 Rectangle` -# -# This can also be achieved with `set TYPE int c_uint_8 Rectangle` -# -# -# To embed whitespace in tokenStrings use the '\' escape character, or quote -# the tokenStrings. These quotes are supported: "'` -# -# -# - Support for the auto detection of languages through the file ending can be -# added using the 'file_ext' command. -# `file_ext langType langString [langString..]` -# -# Example: -# `file_ext CPP .ch .cxx .cpp.in` -# -# langTypes are defined in uncrusify_types.h in the lang_flag_e enum, use -# them without the 'LANG_' prefix: 'LANG_CPP' => 'CPP' -# -# -# - Custom macro-based indentation can be set up using 'macro-open', -# 'macro-else' and 'macro-close'. -# `(macro-open | macro-else | macro-close) tokenString` -# -# Example: -# `macro-open BEGIN_TEMPLATE_MESSAGE_MAP` -# `macro-open BEGIN_MESSAGE_MAP` -# `macro-close END_MESSAGE_MAP` -# -# -# option(s) with 'not default' value: 151 -#