616 Commits

Author SHA1 Message Date
Byson94
39a67a4564 chore: run cargo fmt 2026-01-22 20:14:34 +05:30
Byson94
4b80630b7e Merge pull request #24 from Square-face/main
Fix: make nix flake up to date
2026-01-18 16:37:21 +05:30
Linus Michelsson
dee7979cd5 fix: updated flake lock and switched to gtk4 2026-01-18 07:04:34 +01:00
Byson94
8709371e4e Fix typo in README.md for Improved Interface 2026-01-07 21:18:31 +05:30
Byson94
e4ab87bc2a feat: touch support to scale widget 2026-01-04 15:26:56 +05:30
Byson94
37b57aee60 feat: implement orientation for scale widget 2026-01-02 13:08:53 +05:30
Byson94
33ef1720e3 feat: return data early if mutations is empty 2026-01-01 12:55:40 +05:30
Byson94
c41a495ee0 localsignal: fix no compiled ast warning returning early 2026-01-01 12:49:39 +05:30
Byson94
47f93e9cab chore: run cargo fmt 2026-01-01 12:46:56 +05:30
Byson94
9e91ae61a5 Merge pull request #19 from BinaryHarbinger/main
chore: Change source of Binarydots example
2026-01-01 11:06:58 +05:30
BinaryHarbinger
87cc157055 chore: Change source of Binarydots example 2025-12-31 20:43:19 +03:00
Byson94
29983ab9da feat: add eval_ignore prop to all widgets 2025-12-30 09:25:00 +05:30
Byson94
ff9db50831 feat: add mutations property to localsignal 2025-12-28 19:41:01 +05:30
Byson94
4cb6ac05d3 docs: remove unnecessary feat in changelog 2025-12-28 14:25:55 +05:30
Byson94
73a64944b8 docs(changelog): fix removed section in unreleased 2025-12-25 10:54:16 +05:30
Byson94
d25c2db420 chore: cargo fmt 2025-12-24 11:19:09 +05:30
Byson94
216775f55a feat(img wdgt): custom rendering + new feats 2025-12-24 11:18:33 +05:30
Byson94
ad79e81c50 feat: new image widget features & fully remove icon 2025-12-23 14:57:52 +05:30
Byson94
df7226d06c feat: remove icon widget 2025-12-23 14:50:16 +05:30
Byson94
6e03473133 feat: replace image widget rendering 2025-12-22 19:17:27 +05:30
Byson94
36c58e211d feat: update props of icon widget 2025-12-22 18:18:26 +05:30
Byson94
70de347bcf fix: clockwise prop not working on circ progress 2025-12-10 14:52:56 +05:30
Byson94
2cbf64e250 feat: add text and show_text prop to progressbar widget 2025-12-09 18:34:44 +05:30
Byson94
a14e559c80 feat: rename WidgetNode::Slider to WidgetNode::Scale 2025-12-09 17:04:32 +05:30
Byson94
59fb1b85eb feat: remove ewwii_anims from cargo.toml 2025-12-08 21:32:06 +05:30
Byson94
4197a863e5 feat: change doccomment description of rhai_impl crate 2025-12-08 19:49:09 +05:30
Byson94
4293c6877d feat: migrate most legacycontroller to gestureclick
This provides touch support to widgets
2025-12-07 14:14:35 +05:30
Byson94
f393627932 feat: parse widget_action ucontainer actions like shell 2025-12-06 16:14:53 +05:30
Byson94
c54ce27505 feat: add features section in readme 2025-12-02 19:01:32 +05:30
Byson94
97518eb49c chore: run cargo fmt 2025-11-29 20:45:31 +05:30
Byson94
ddce15481f feat: remove remove action from widget_action utility 2025-11-29 19:49:52 +05:30
Byson94
43721426e8 feat: proptotype widgetaction utility widget 2025-11-28 20:25:18 +05:30
Byson94
6baa9c7858 feat: add transition_duration prop to stack widget 2025-11-26 20:18:28 +05:30
Byson94
8ec080a290 feat: add add/remove-class subcommand to wc command 2025-11-26 19:15:28 +05:30
Byson94
166c440978 chore: cargo fmt 2025-11-25 21:05:24 +05:30
Byson94
6e9dca9d42 feat: add placeholder property to input widget 2025-11-25 21:04:32 +05:30
Byson94
b50f41b1e0 feat: add propety-update argument to widget control command 2025-11-25 20:49:26 +05:30
Byson94
357dcaacbc fix: doc comment of epapi register_function 2025-11-24 19:33:49 +05:30
Byson94
61e681e6bd chore: run cargo fmt 2025-11-24 19:26:30 +05:30
Byson94
ebd4264621 fix: localbind not finding properties of range subclasses 2025-11-23 17:49:22 +05:30
Byson94
4167c64fde feat: fix register_function docs in epapi 2025-11-22 17:41:24 +05:30
Byson94
6456b2998d feat: add link to documentation in readme 2025-11-22 17:39:16 +05:30
Byson94
4de5ab3c59 chore: commit change in cargo.lock 2025-11-22 12:08:07 +05:30
Byson94
04ca79a5af feat: improve epapi; bump epapi to 0.7.0; 2025-11-22 12:05:30 +05:30
Byson94
0d803fd962 chore: run cargo fmt 2025-11-22 11:13:24 +05:30
Byson94
8406c86117 feat: bump ewwii_plugin_api version 2025-11-21 21:53:41 +05:30
Byson94
1aee3163e0 feat: make register_function on ewwii_plugin_api register directly 2025-11-21 21:53:19 +05:30
Byson94
9aec974e9e feat: add warning on ewwii_plugin_api until it is fixed 2025-11-21 18:06:52 +05:30
Byson94
4de148be58 feat: remove debug in action_with_engine 2025-11-20 21:02:23 +05:30
Byson94
3f48178333 feat: matching rhai features across all crates 2025-11-19 14:35:55 +05:30
Byson94
8af01e44f2 feat: improve plugin loading order 2025-11-17 20:05:26 +05:30
Byson94
a76440f242 feat: add trace log in action_with_engine 2025-11-16 20:29:14 +05:30
Byson94
49c0d14ace feat: update wc actions to take vec of strings 2025-11-13 19:27:46 +05:30
Byson94
6a6856192c feat: make wc add eval rhai code instead of .ui 2025-11-08 18:47:09 +05:30
Byson94
b821d8bb6a feat: add widget-control command 2025-11-08 17:09:51 +05:30
Byson94
e12d5f7fb9 feat: add gtk_ui function for loading .ui 2025-11-07 20:22:56 +05:30
Byson94
26ee4e5560 chore: cargo fmt 2025-11-01 19:38:27 +05:30
Byson94
622a9c1b06 feat: bump to ewwii 0.3.1 2025-11-01 19:37:36 +05:30
Byson94
6b0e94698b fix: localsignal not working for non-gchararray props 2025-11-01 18:43:41 +05:30
Byson94
08e1f2d5f3 fix: circularprogress not updating to dyn vars 2025-11-01 18:30:43 +05:30
Byson94
b53431d861 chore: run cargo fmt 2025-11-01 12:22:30 +05:30
Byson94
327b223998 chore: add 0.3.0 release in changelog 2025-11-01 12:21:27 +05:30
Byson94
e26cd16ef9 fix: ensure full teardown of signals in reload 2025-11-01 10:29:04 +05:30
Byson94
669e7e9566 fix: minor issues with localsignals 2025-10-31 21:51:57 +05:30
Byson94
9bb8a9e3dd feat: turn localbind from a widget to a utility 2025-10-30 21:40:14 +05:30
Byson94
249cacdd0a chore: run cargo fmt 2025-10-30 19:47:28 +05:30
Byson94
167fe26f30 chore: notedown changes in changelog 2025-10-30 19:47:15 +05:30
Byson94
44a86e0937 feat: make localsignal simpler through localbind container 2025-10-30 19:45:43 +05:30
Byson94
f5e1b61dcf Revert "wip: adding localsignal support for all widget"
This reverts commit 7dc64014fd.
2025-10-30 15:11:08 +05:30
Byson94
1ca23373e1 Revert "wip: add localsignal support to eventbox"
This reverts commit 7095cb6637.
2025-10-30 15:11:06 +05:30
Byson94
78dafcc5b3 Revert "wip: add localsignal handling for basic props"
This reverts commit 74718b064f.
2025-10-30 15:11:05 +05:30
Byson94
e92ccab3d1 Revert "wip: adding more support to localsignal"
This reverts commit 19b790d4fa.
2025-10-30 15:11:03 +05:30
Byson94
8820a0f274 Revert "wip: making localsignal only bind once"
This reverts commit 8f15274fb9.
2025-10-30 15:11:02 +05:30
Byson94
9c15f8aed1 Revert "feat: make localsignal id relative to its props"
This reverts commit 9458d95222.
2025-10-30 15:11:00 +05:30
Byson94
f5ad63ed33 Revert "feat: moving initial of localsignal to a different place"
This reverts commit b3043afe04.
2025-10-30 15:10:59 +05:30
Byson94
7abc39d051 Revert "feat: add clear fn for localsignal store"
This reverts commit 60af15fb8d.
2025-10-30 15:10:58 +05:30
Byson94
47745fa501 Revert "feat: mvoe from widget binding to notify_local"
This reverts commit 2ac527bcbc.
2025-10-30 15:10:56 +05:30
Byson94
4c2e460127 Revert "feat: add localsignal support to many more widgets"
This reverts commit 902ca67c58.
2025-10-30 15:10:55 +05:30
Byson94
fa567b06d0 Revert "feat: add localsignal support to even moer widgets"
This reverts commit bfe1d248a4.
2025-10-30 15:10:53 +05:30
Byson94
892c09512c Revert "feat: add default text/markup values for gtk_label"
This reverts commit b369f648db.
2025-10-30 15:10:47 +05:30
Byson94
8be2f01058 Revert "fix: gtk_label default text/markup value being &str"
This reverts commit 91e7a86e7a.
2025-10-30 15:10:44 +05:30
Byson94
673ef2e09d Revert "feat: set gtk box space evenly to true"
This reverts commit 425ef5020b.
2025-10-30 15:10:36 +05:30
Byson94
cd271ed283 Revert "feat: moving all localsignal into a localbind wrapper"
This reverts commit 98e370ac60.
2025-10-30 15:10:19 +05:30
Byson94
98e370ac60 feat: moving all localsignal into a localbind wrapper 2025-10-30 15:00:00 +05:30
Byson94
425ef5020b feat: set gtk box space evenly to true 2025-10-30 14:12:10 +05:30
Byson94
91e7a86e7a fix: gtk_label default text/markup value being &str 2025-10-30 14:09:14 +05:30
Byson94
b369f648db feat: add default text/markup values for gtk_label 2025-10-30 14:07:18 +05:30
Byson94
bfe1d248a4 feat: add localsignal support to even moer widgets 2025-10-30 13:39:55 +05:30
Byson94
902ca67c58 feat: add localsignal support to many more widgets 2025-10-29 20:07:26 +05:30
Byson94
2ac527bcbc feat: mvoe from widget binding to notify_local 2025-10-29 16:16:58 +05:30
Byson94
60af15fb8d feat: add clear fn for localsignal store 2025-10-29 14:51:57 +05:30
Byson94
b3043afe04 feat: moving initial of localsignal to a different place 2025-10-29 14:23:26 +05:30
Byson94
9458d95222 feat: make localsignal id relative to its props 2025-10-29 13:56:25 +05:30
Byson94
8f15274fb9 wip: making localsignal only bind once 2025-10-29 13:33:41 +05:30
Byson94
19b790d4fa wip: adding more support to localsignal 2025-10-28 22:17:12 +05:30
Byson94
74718b064f wip: add localsignal handling for basic props 2025-10-28 21:51:46 +05:30
Byson94
7095cb6637 wip: add localsignal support to eventbox 2025-10-28 20:52:16 +05:30
Byson94
7dc64014fd wip: adding localsignal support for all widget 2025-10-28 20:14:32 +05:30
Byson94
66bc9f6d74 wip: localsignal for fast widget update 2025-10-27 22:25:49 +05:30
Byson94
4b3240b9b9 fix: example in ewii_plugin_api 2025-10-27 18:52:15 +05:30
Byson94
3803141f31 chore: run cargo fmt (again) 2025-10-27 18:13:21 +05:30
Byson94
2ed91786a3 chore: fix merge conflicts 2025-10-27 18:10:51 +05:30
Byson94
5e827a73c8 chore: run cargo fmt 2025-10-27 18:09:26 +05:30
Byson94
58957ec597 fix: poll/listen variables not working in other files 2025-10-27 18:08:56 +05:30
Byson94
abafe1b6fd fix: poll/listen variables not working in other files 2025-10-27 18:05:55 +05:30
Byson94
6536035e19 feat: add list_fns func to slib 2025-10-26 20:49:52 +05:30
Byson94
187a367977 feat: add support for circular-progress widget 2025-10-26 14:05:54 +05:30
Byson94
e0ae5c97d4 feat: add lifetime flag to update command 2025-10-25 15:47:08 +05:30
Byson94
59b3cdd0dc feat: implement recv drain in plugin load func 2025-10-24 21:00:03 +05:30
Byson94
5cf8659f92 feat: add default_select property to flowbox 2025-10-24 19:57:40 +05:30
Byson94
0b14629dd7 feat: move to rhai_trace 0.3.1 to not panic on certain err 2025-10-24 19:02:28 +05:30
Byson94
726093f534 fix: requiring child-index property on children of flowbox 2025-10-24 18:56:23 +05:30
Byson94
39a389b90c feat: add widget_name property to all widgets 2025-10-23 20:14:12 +05:30
Byson94
140643d4ec feat: add focusable property to all widget 2025-10-23 19:43:14 +05:30
Byson94
f52164da87 chore: run cargo fmt 2025-10-23 18:44:22 +05:30
Byson94
926c5bae7e feat: add flowbox widget 2025-10-22 22:11:51 +05:30
Byson94
ac8375bf47 fix: dont print error if message is '' 2025-10-22 18:03:21 +05:30
Byson94
58667c77ed fix: signals not exposed to other mod on first launch 2025-10-21 19:45:27 +05:30
Byson94
b06c3e0e3f feat: add new properties to eventbox 2025-10-21 18:52:30 +05:30
Byson94
21d50ed7e6 chore: fix one small comment 2025-10-20 22:23:24 +05:30
Byson94
5f576315fe chore: document change in changelog 2025-10-20 12:11:40 +05:30
Byson94
da57afb395 feat: change fnonce of register_function to fn 2025-10-20 12:06:01 +05:30
Byson94
c0ef865920 feat: add slib module for handling shared libs 2025-10-20 11:43:14 +05:30
Byson94
3afc8fa9ca fix: few eventbox drop target issue 2025-10-18 14:43:42 +05:30
Byson94
7a4191df95 chore(doc): improve ewwii_plugin_api doc comments 2025-10-14 21:32:24 +05:30
Byson94
18832c2956 feat(opt): add --with-plugin flag to daemon command 2025-10-14 19:58:46 +05:30
Byson94
4974df29d6 chore: feature 'Binary Dots' in readme 2025-10-14 17:58:20 +05:30
Byson94
b72700fbd2 Merge pull request #9 from BinaryHarbinger/main
Setting style provider priority to 900 still uses global theme as fallback just like GTK3 version.
2025-10-14 17:43:40 +05:30
BinaryHarbinger
361fe49001 fix: Style provider priority 'APPLICATION >> 900' 2025-10-13 20:57:24 +03:00
Byson94
db5e2055e1 chore: run cargofmt 2025-10-13 20:25:59 +05:30
Byson94
3ef6861b62 fix: remove VALBEF println clutter 2025-10-13 20:25:27 +05:30
Byson94
3156b2b85a Merge pull request #8 from Cyclic007/patch-1
add activateLinux example
2025-10-13 19:30:53 +05:30
Byson94
d2f8d3dfe3 Merge branch 'main' into iidev 2025-10-13 19:26:42 +05:30
Byson94
fc6f154021 Merge pull request #6 from BinaryHarbinger/main
Add additional support for dash
2025-10-13 19:24:39 +05:30
Byson94
f3b2f4bce7 fix(shell): move code to avoid repetetion 2025-10-13 19:14:58 +05:30
Byson94
edad7fb3b7 fix: inconsistencies between rhai_impl and ewwii_plugin_api 2025-10-13 19:02:22 +05:30
Cyclic
3631b67496 Create ewwii.scss 2025-10-12 14:47:54 +00:00
Cyclic
b118409e83 setup new example rhai 2025-10-12 14:47:12 +00:00
Byson94
34706b1ae8 fix: fix dep inconsistency through re-export 2025-10-12 18:50:40 +05:30
BinaryHarbinger
8927256f39 Add additional support for dash
Automatically detect dash and use it instead of sh if available
2025-10-12 16:11:05 +03:00
Byson94
6d667538db chore(remove): LICENSE-MIT which came after rebase 2025-10-12 15:18:38 +05:30
Byson94
54145617b5 fix(ci): incomplete 'check no-backend' step 2025-10-12 14:44:09 +05:30
Byson94
49057eec5d fix: all doctest err in ewwii_plugin_api 2025-10-12 14:36:23 +05:30
Byson94
b144571c9a fix: .gitignore conflict on merge 2025-10-12 14:26:49 +05:30
Byson94
30a4b63f00 fix: solve more cargo test issus 2025-10-12 14:11:59 +05:30
Byson94
0e2307ea03 fix(ci): Satisfying doctest 2025-10-12 14:11:59 +05:30
Byson94
dcdcc2dbc5 fix: fixing doctest issues with auto_plugin macro 2025-10-12 14:11:59 +05:30
Byson94
9a37ab6e7b fix(ci): using arch linux docker container 2025-10-12 14:11:59 +05:30
Byson94
b398ea4749 feat: adding panic handling 2025-10-12 14:11:59 +05:30
Byson94
c29cc74de0 feat: added onkeypress and onkeyrelease props 2025-10-12 14:11:59 +05:30
Byson94
f571c406c7 fix: fixed old widget creeping in issue 2025-10-12 14:11:59 +05:30
Byson94
517b31d62a fix(ci): fixing packages 2025-10-12 14:11:59 +05:30
Byson94
a6953310b1 chore: cargo fmt 2025-10-12 14:11:59 +05:30
Byson94
46591b1b8a feat: making examples in readme look good 2025-10-12 14:11:58 +05:30
Byson94
67c789ae41 fix(ci): Fixing indentation 2025-10-12 14:11:58 +05:30
Byson94
5ce4cedd3e fix(ci): Working on fixing the ci not running issue 2025-10-12 14:11:58 +05:30
Byson94
df5c4a0678 chore: added info in changelog 2025-10-12 14:11:58 +05:30
Byson94
29176aacf0 chore: fixing ewwii_plugin_api versioning issue 2025-10-12 14:11:58 +05:30
Byson94
345a57c465 feat: added max docs and 1 feat in ewwii_plugin_api 2025-10-12 14:11:58 +05:30
Byson94
bf1e1622ac fix: fixing feature issue in widget_backend.rs 2025-10-12 14:11:58 +05:30
Byson94
b9ce839f83 style: fixing ewwii_plugin_api Cargo.toml style 2025-10-12 14:11:58 +05:30
Byson94
8d025d1958 feat: improving the ewwii_plugin_api crate and fixing issues 2025-10-12 14:11:58 +05:30
Byson94
732acbdf5c feat: more api changes in ewwii_plugin_api 2025-10-12 14:11:58 +05:30
Byson94
975ebc7ee5 feat: improving docs and comments on ewwii_plugin_api 2025-10-12 14:11:58 +05:30
Byson94
03baaf3099 chore: fixing ewwii_plguin_api version issue 2025-10-12 14:11:58 +05:30
Byson94
7ba9d95f96 feat: added the ability to modify widgets 2025-10-12 14:11:58 +05:30
Byson94
3d08b3e873 chore: added change in changelog 2025-10-12 14:11:58 +05:30
Byson94
fa31aa9299 fix(rhai): fixing poll/listen scope not available on all modules 2025-10-12 14:11:58 +05:30
Byson94
7f72d0805e chore: Updating Cargo.lock 2025-10-12 14:11:58 +05:30
Byson94
ac5432c93c fix: fixing ewwii_plugin_api version 2025-10-12 14:11:58 +05:30
Byson94
19db669204 feat: expanding ewwii_plugin_api 2025-10-12 14:11:58 +05:30
Byson94
e13bb1f551 feat: added tools for exporting plugins 2025-10-12 14:11:58 +05:30
Byson94
8fbad0c9be feat: added option to list all widget ids in plugin sys 2025-10-12 14:11:58 +05:30
Byson94
994ee6de29 feat: added documentation for ewwii_plugin_api 2025-10-12 14:11:58 +05:30
Byson94
0bd437603b fix(ci): fixing dependencies on gtk4 2025-10-12 14:11:58 +05:30
Byson94
1891165d50 feat: updating changelog 2025-10-12 14:11:58 +05:30
Byson94
45657e145c feat: added readme and docs to plugin_api 2025-10-12 14:11:58 +05:30
Byson94
ca63ebe504 feat: fixing few errors and improving other stuff 2025-10-12 14:11:58 +05:30
Byson94
66951f8fba chore: cargo fmt 2025-10-12 14:11:58 +05:30
Byson94
609e023f9b fix: fixing issue templates 2025-10-12 14:11:58 +05:30
Byson94
294ae868a6 feat: Updating changelog 2025-10-12 14:11:58 +05:30
Byson94
0e15ffa23a feat: getting rhai mod working via plugin 2025-10-12 14:11:58 +05:30
Byson94
5f62a00c60 feat: got library system loading working 2025-10-12 14:11:58 +05:30
Byson94
bf1b24bb95 wip: bin level plugin system 2025-10-12 14:11:58 +05:30
Byson94
27dacde798 fix: fixed focusable not working 2025-10-12 14:11:58 +05:30
Byson94
9004f186fa feat: adding the release date in changelog 2025-10-12 14:11:58 +05:30
Byson94
b9e6e8ba0c fix: fixing minor issues 2025-10-12 14:11:58 +05:30
Byson94
ed15ddfaaa feat: removed centerbox widget 2025-10-12 14:11:58 +05:30
Byson94
881910f1b3 GREATEST FEAT: Achived sticky windows in x11 2025-10-12 14:11:58 +05:30
Byson94
7936e4f881 fix: fixed gif images not working 2025-10-12 14:11:58 +05:30
Byson94
9072ff8525 fix: did a simple fix over the scale drag issue 2025-10-12 14:11:58 +05:30
Byson94
1c85310c22 chore: Cargo.lock update 2025-10-12 14:11:58 +05:30
Byson94
b65c1b5c23 feat: added deprecated section in changelog 2025-10-12 14:11:58 +05:30
Byson94
2840138464 feat: added information about alpha release in changelog 2025-10-12 14:11:58 +05:30
Byson94
205fe2f9bf fix: fixing all compiler warnings 2025-10-12 14:11:58 +05:30
Byson94
6a7e77029d feat: fixed image wdgt and added icon wdgt 2025-10-12 14:11:58 +05:30
Byson94
f36cb58237 fix: no classes to window to prevent x11 issues 2025-10-12 14:11:58 +05:30
Byson94
c14f2b4fc6 feat: fixing warnings & messin with x11 2025-10-12 14:11:58 +05:30
Byson94
243408d176 fix(x11): fixing widget not realized before getting surface 2025-10-12 14:11:58 +05:30
Byson94
b647eb36af fix: fixing the ewwii window close order 2025-10-12 14:11:58 +05:30
Byson94
4238b5fe9a feat: fixing application loop issues by doing manual one 2025-10-12 14:11:58 +05:30
Byson94
3120d7556e feat: fixing very single gtk4 migration error! yippee! 2025-10-12 14:11:58 +05:30
Byson94
a9ccb25cae fix: fixing one of the last few err (i think so) 2025-10-12 14:11:58 +05:30
Byson94
6d32f4f823 fix: even more fixing of gtk4 errors 2025-10-12 14:11:58 +05:30
Byson94
22f9e7e272 fix: fixing the drag thingy in eventbox 2025-10-12 14:11:58 +05:30
Byson94
e73173888c fix: fixing broken wifi gui manager screenshot 2025-10-12 14:11:58 +05:30
Byson94
faf8afdd65 feat: added name in 0.2.0 release changelog 2025-10-12 14:11:58 +05:30
Byson94
f2fc0ca891 fix: fixing more errors that i cant name of 2025-10-12 14:11:58 +05:30
Byson94
e7346cb28a fix: fixing many many more gtk4 migration errs 2025-10-12 14:11:58 +05:30
Byson94
bbc99df84d fix: added controlflow in gif render part 2025-10-12 14:11:58 +05:30
Byson94
cf0367e069 fix: fixing more gtk4 related err 2025-10-12 14:11:58 +05:30
Byson94
1f1b1b2b01 feat: added EventControllerKey in widget_definition.rs 2025-10-12 14:11:58 +05:30
Byson94
a6841935cc fix: fixing gtk_layer_shell naming issues 2025-10-12 14:11:58 +05:30
Byson94
96039a47aa fix: fixing glib weak reference issues 2025-10-12 14:11:58 +05:30
Byson94
2d30974f85 fix: fixing timeouts in eventbox being a borrow 2025-10-12 14:11:57 +05:30
Byson94
c5949be319 feat(rewrite): button and event_box widgets 2025-10-12 14:11:44 +05:30
Byson94
f21833b641 feat: rewriting eventbox to work with gtk4 2025-10-12 14:11:44 +05:30
Byson94
35cb12b2f2 fix: fixing even more errors in widget_definition 2025-10-12 14:11:44 +05:30
Byson94
4efd34f78b fix: fixing glib::clone! in widget_definitions.rust 2025-10-12 14:11:44 +05:30
Byson94
d35161d5d1 fix: fixed connect_monitor_added function 2025-10-12 14:11:44 +05:30
Byson94
fd73225688 fix: fixed style_provider reelated err 2025-10-12 14:11:44 +05:30
Byson94
b7b7f15420 fix: more errors and follow new gtk4 model 2025-10-12 14:11:22 +05:30
Byson94
b910eb741a feat: stubbing widget creation logic for easier migration 2025-10-12 14:11:22 +05:30
Byson94
fec83417f5 wip: migrate to gtk4 2025-10-12 14:11:10 +05:30
Byson94
b3f2c3f8a9 chore: a small rename :) 2025-10-12 14:11:10 +05:30
Byson94
1eaf773206 feat: removed monitor lib in favour of gtk4 2025-10-12 14:11:10 +05:30
Byson94
38222328c2 feat: fixed falure send & added print flag to engine-override 2025-10-12 14:11:10 +05:30
Byson94
dc04096587 feat: better management of rhai crate 2025-10-12 14:11:10 +05:30
Byson94
52182d3b4e feat: removed more code/dependencies 2025-10-12 14:11:10 +05:30
Byson94
c59f3f3683 feat: removed unnecessary dependencies 2025-10-12 14:11:10 +05:30
Byson94
348b4bcf98 chore: cargo fmt 2025-10-12 14:11:10 +05:30
Byson94
f811704e5e feat: added file path indicator in errors! 2025-10-12 14:11:10 +05:30
Byson94
c2867b6fc8 fix: resolver throwing err at import on p/e err 2025-10-12 14:11:10 +05:30
Byson94
972a5bb357 feat: even better err support with rhai_trace v3 2025-10-12 14:11:10 +05:30
Byson94
eb73c5b08f feat: renaming setup_for_rt to setup_dyn_ids 2025-10-12 14:11:10 +05:30
Byson94
53607bf019 feat: removed INPUT_VAL var support in input wdgt 2025-10-12 14:11:10 +05:30
Byson94
21216b642c feat: improved the module heading generation 2025-10-12 14:11:10 +05:30
Byson94
39c284682a fix: fixed doc error 2025-10-12 14:11:10 +05:30
Byson94
5d367195ed chore: removed lagacy support on focusable win prop 2025-10-12 14:11:10 +05:30
Byson94
b38ed83289 feat: added force_normal property for windows 2025-10-12 14:11:10 +05:30
Byson94
22ae76c2ce fix: m/min duration end & ewwii crash 2025-10-12 14:11:10 +05:30
Byson94
1ff85fef2f fix: fixed broken m value for min 2025-10-12 14:11:10 +05:30
Byson94
160ec69391 feat: improving the engine-override feature 2025-10-12 14:11:10 +05:30
Byson94
a97e5fb762 fix(typo): in 0.2.0 CHANGELOG 2025-10-12 14:11:10 +05:30
Byson94
98214786d8 feat: added engine-override command 2025-10-12 14:11:10 +05:30
Byson94
01e6f2d6b8 feat(stdlib): added std::regex for regex matching 2025-10-12 14:11:10 +05:30
Byson94
9a92276bd0 chore: removed added support for open-many in v0.2.0 2025-10-12 14:11:10 +05:30
Byson94
d491a76c43 feat: improved rhai docs generator 2025-10-12 14:11:10 +05:30
Byson94
9592f9333a fix(generate-rhai-docs): broken code for docusaurus 2025-10-12 14:10:50 +05:30
Byson94
fda4b68c56 feat: remove stuff in autogen 2025-10-12 14:10:20 +05:30
Byson94
317b6162ea feat(generate-rhai-docs): fix mdx issues 2025-10-12 14:10:07 +05:30
Byson94
5dc6f3be30 feat: renaming js => javascript 2025-10-12 14:08:30 +05:30
Byson94
a999cc8948 feat: remove docs/ and moving to docusarus 2025-10-12 14:08:21 +05:30
Byson94
ef700d9d85 feat: added m as another duration unit for minute 2025-10-12 14:08:21 +05:30
Byson94
bd6e540d04 feat: more renaming | eww => ewwii 2025-10-12 14:08:21 +05:30
Byson94
68e0f9e35a feat: removing a few comment of minee 2025-10-12 14:08:21 +05:30
Byson94
9e3fcf2e09 feat: fully renamed EwwPaths => EwwiiPaths 2025-10-12 14:08:20 +05:30
Byson94
34019e65ba feat: made eval_code fn use the compile_code fn to compile 2025-10-12 14:08:20 +05:30
Byson94
df3fb81b6a chore: renaming a few eww => ewwii 2025-10-12 14:08:20 +05:30
Byson94
4fabb49ed3 feat: added state command and fixed log issues 2025-10-12 14:08:20 +05:30
Byson94
7db5a1305c feat: added --preserve in the docs 2025-10-12 14:08:20 +05:30
Byson94
14b5cff081 feat: added date in 0.1.4 release 2025-10-12 14:08:20 +05:30
Byson94
89bb47e53e feat: added perserve flag to the update command which preserves the new updates 2025-10-12 14:08:20 +05:30
Byson94
14b54e7790 chore(cargo): building for 0.1.3 2025-10-12 14:08:20 +05:30
Byson94
b0044d6f0a feat: fixed image_width and height not working issue for image 2025-10-12 14:08:20 +05:30
Byson94
c0f1a2e1c8 feat: removed getting started section from docs 2025-10-12 14:08:20 +05:30
Byson94
50d95f1870 chore: fixing a comment... 2025-10-12 14:08:20 +05:30
Byson94
e4187a6d4c feat: reworking the inject-vars arg of update 2025-10-12 14:08:20 +05:30
Byson94
b5a639936b feat: made update cmd so that it will preserve current wdgt state 2025-10-12 14:08:20 +05:30
Byson94
4ca6716074 feat(docs): added exclusive true in config 2025-10-12 14:08:20 +05:30
Byson94
1937508781 fix(docs): fixed invalid config in configuration.md 2025-10-12 14:08:20 +05:30
Byson94
37be5104b2 feat: updating ewwii dark theme 2025-10-12 14:08:20 +05:30
Byson94
976f0b4e34 feat: improved parent-death sig on freebsd and linux 2025-10-12 14:08:20 +05:30
Byson94
ab1b2a8a96 feat: removed todo 2025-10-12 14:08:20 +05:30
Byson94
2081d13b81 chore: cargo formatting 2025-10-12 14:08:20 +05:30
Byson94
164b7858f7 feat: added date to 0.1.1 release in changelog 2025-10-12 14:08:20 +05:30
Byson94
fb528adeb9 feat: migrated to rhai_trace 0.2.0 2025-10-12 14:08:20 +05:30
Byson94
4aecfa43ab perf: improved poll handling and made it reusable 2025-10-12 14:08:20 +05:30
Byson94
6bc8822e04 feat: made update not require a window argument 2025-10-12 14:08:20 +05:30
Byson94
095e99bc0a feat: fix poll/listen not working for multiple window 2025-10-12 14:07:28 +05:30
Byson94
623a79da54 feat: removed unused deps 2025-10-12 14:07:16 +05:30
Byson94
9e9d57be8e feat: fixing documentation mistake which said main.rhai as main file 2025-10-12 14:07:16 +05:30
Byson94
cbe77b3b1f feat: adding release date of 0.1.0 2025-10-12 14:07:16 +05:30
Byson94
aff9a999b0 feat(theme): improved docs ewwii theme 2025-10-12 14:07:16 +05:30
Byson94
588f843e0c feat: updated wifi gui template image 2025-10-12 14:07:16 +05:30
Byson94
0957ef2804 chore: Update README.md 2025-10-12 14:07:06 +05:30
Byson94
c571bfb03b feat: removed exit on config error mechanism of daemon 2025-10-12 14:07:06 +05:30
Byson94
d7445dabb2 fix: fixed dyn var extractor not skipping comments issue 2025-10-12 14:07:06 +05:30
Byson94
1dac50f70a fix: fixed broken call-fns command 2025-10-12 14:07:06 +05:30
Byson94
3a04893caa fix: fixed default poll/listen variables not working in external modules 2025-10-12 14:07:06 +05:30
Byson94
83c292de6b feat: improved both resolver failed error 2025-10-12 14:07:06 +05:30
Byson94
a2e18ee7df feat: fixed mod resolver not printing error issue 2025-10-12 14:07:06 +05:30
Byson94
84c455f557 feat: many internal changes regarding enter(..)
1. Made it so that there wont be any error if user didnt return anything
2. Added support for defining multiple enter(..)
3. Added support for merging multiple enter(..)
2025-10-12 14:07:06 +05:30
Byson94
22981292cc feat: better errors with rhai_trace (lib built for ewwii)
With this commit, Ewwii now integrates rhai_trace, which is a rust library that I
built to generate better errors with rhai.

It is plugged into codespan reporting for providing awesome errors which
makes programming with ewwii much easier! It is a major UX update along
with the removal of `dyn_id` dependance.
2025-10-12 14:07:06 +05:30
Byson94
4d0d84c44d docs: improved the doc flow 2025-10-12 14:07:06 +05:30
Byson94
b9d5fd8e68 feat: added TODO.md 2025-10-12 14:07:06 +05:30
Byson94
826d560b84 feat: improved the removed dyn_id part in changelog 2025-10-12 14:07:06 +05:30
Byson94
5b47b67c83 feat(MAJOR): removed the need for dyn_id
This is a very very very big update for UX! Ewwii finally has support
for automatically assigning `dyn_id`.

This was actually not as hard as I thought! I just had to mutate the
widget AST and inject a `dyn_id` in based on its parent.

It works soooo well and the burden on the user just reduced sooo much!
2025-10-12 14:07:06 +05:30
Byson94
0561ecba3f feat(docs): added wifi_manager template 2025-10-12 14:07:06 +05:30
Byson94
c9631268bd feat(rename): renamed iirhai --> rhai_impl 2025-10-12 14:07:06 +05:30
Byson94
11510bd8b4 feat(github): added module request issue template 2025-10-12 14:06:39 +05:30
Byson94
a58694a04d feat: renamed widgetnode.rs to ast.rs in iirhai 2025-10-12 14:06:39 +05:30
Byson94
9667a73b05 feat: removed modules example 2025-10-12 14:06:39 +05:30
Byson94
24b57fb269 feat: updated readme contribewwtiing steps 2025-10-12 14:06:39 +05:30
Byson94
cf1dc459a2 feat: removed statictranspl docs 2025-10-12 14:06:39 +05:30
Byson94
306c4c542b style: remove pre_description having \t at start 2025-10-12 14:06:05 +05:30
Byson94
61bb98460d feat: added contributing.md 2025-10-12 14:03:22 +05:30
Byson94
53116df6a0 feat: added api::linux library for rhai 2025-10-12 14:03:16 +05:30
Byson94
29c70d26c7 feat: remove unused stuff and do namespace changes 2025-10-12 14:03:01 +05:30
Byson94
ee40a2265a fix: borken % based w/h in window def 2025-10-12 14:02:41 +05:30
Byson94
167df98182 style: fixed pre_description having \t at the start 2025-10-12 14:02:41 +05:30
Byson94
904ceb8f09 feat(ci): added gh-page publishment on changes in generate-rhai-docs/** 2025-10-12 14:02:41 +05:30
Byson94
307ba2fe61 feat: added feature for adding descriptions in generated mod docs 2025-10-12 14:02:41 +05:30
Byson94
87b615999d chore: ran cargo fmt 2025-10-12 14:02:41 +05:30
Byson94
1e8ab7f983 fix(ci): added necessary dependencies that need to be installed 2025-10-12 14:02:41 +05:30
Byson94
2293993865 fix(ci): fixed broken rust install 2025-10-12 14:02:41 +05:30
Byson94
69bf08729d fix(ci): outdated cache using v2 2025-10-12 14:01:47 +05:30
Byson94
4fa04a4b6e feat(ci): added module docs generation logic in workflow 2025-10-12 14:01:47 +05:30
Byson94
0572480239 feat: finished writing apilib docs 2025-10-12 14:01:47 +05:30
Byson94
092ecb407d wip: Massive doc automation and improvement. 2025-10-12 14:01:47 +05:30
Byson94
e63886b402 feat: improved poll/listen handler setup/shutdown in ewwii open/close cmd 2025-10-12 14:01:47 +05:30
Byson94
4b18b6c4f1 feat: DID MASSIVE improvements and changes that i cant summarize
So basically, i added sigint/sigterm catching to kill all children cleanly, then i fixed the std::monitor module as it returned tuple which didnt work with rhai much, and then i removed the deprecated attribute warning thingy. Yeah thats it.
2025-10-12 14:01:47 +05:30
Byson94
678c17c80f docs: fixed update docs 2025-10-12 14:01:47 +05:30
Byson94
076cba0c85 docs: moved advanced commands below examples 2025-10-12 14:01:47 +05:30
Byson94
f9beb589db docs: improved variables config documentation 2025-10-12 14:01:47 +05:30
Byson94
3f439a2aa0 docs: improved docs by adding commands/ section 2025-10-12 14:01:47 +05:30
Byson94
b8927722aa fix: removed kill_state_change_handler() from close_window bcz it causes issues 2025-10-12 14:01:47 +05:30
Byson94
a0945ecc84 feat: added rhai to workspace 2025-10-12 14:01:47 +05:30
Byson94
e51bdc3647 perf: replaced Arc<> with Rc<> in single threaded instances 2025-10-12 14:01:47 +05:30
Byson94
a6b87183e1 feat: added good syntax highlighting for ewwii theme 2025-10-12 14:01:47 +05:30
Byson94
a491077fca fix: fixed zombie process creation due to 100ms read time 2025-10-12 14:01:47 +05:30
Byson94
2a369d0532 feat: introduced 16ms (1 frame) batching for ewwii 2025-10-12 14:01:47 +05:30
Byson94
e83239af24 feat: fixed [NoBackend] not existing 2025-10-12 14:01:47 +05:30
Byson94
34a4664499 feat: set release date of 0.1.0-beta as today 2025-10-12 14:01:47 +05:30
Byson94
1606c61745 fix: fixed slider updating value while dragging issue 2025-10-12 14:01:47 +05:30
Byson94
ade3c45be5 feat: made listen similar to eww's model to avoid kill issues 2025-10-12 14:01:47 +05:30
Byson94
7efda1ba42 feat: added kill_state_change_handler call in stop_application 2025-10-12 14:01:47 +05:30
Byson94
25c9890fe3 fix: fixed warnings on child 2025-10-12 14:01:47 +05:30
Byson94
baf8c71909 fix: preventing early terminiation of listen child 2025-10-12 14:01:47 +05:30
Byson94
369d75af26 perf: improved perf in ewwii_config.rs by decreaasing amount of clone 2025-10-12 14:01:47 +05:30
Byson94
cf66eb8853 perf: moved from deep cloning/owning to borrowing data 2025-10-12 14:01:47 +05:30
Byson94
f714c9211d fix: removed rhai full optimization as it caused issues 2025-10-12 14:01:47 +05:30
Byson94
2d34db53fe style: made widget of template1 400 2025-10-12 14:01:47 +05:30
Byson94
a7f0065e85 feat: added templates section in README 2025-10-12 14:01:47 +05:30
Byson94
8fdb800dea docs: added proper site url to book.toml 2025-10-12 14:01:47 +05:30
Byson94
a747c5baba Stop tracking docs/book 2025-10-12 14:01:47 +05:30
Byson94
b4238e06b3 feat(license): make eww/ewwii licensing more clear 2025-10-12 14:01:33 +05:30
Byson94
2d2e288f5c perf: added full rhai optmization for speed 2025-10-12 13:59:49 +05:30
Byson94
1326716b0b feat: upgraded to rust 1.89.0, fixed new compiler warnings 2025-10-12 13:59:49 +05:30
Byson94
a6254b4308 docs(style): added ewwii (dark) theme that matches starlight theme 2025-10-12 13:59:49 +05:30
Byson94
f1e2e9561c docs(style): set navy as default dark theme 2025-10-12 13:59:49 +05:30
Byson94
1d5f3bbecd feat: replaced rust,ignore with js 2025-10-12 13:59:49 +05:30
Byson94
a435cb8a20 feat: replaced default theme with catuppuccin 2025-10-12 13:59:49 +05:30
Byson94
d3d0c59a80 docs: added approximation symbol to equations using pi (float num) 2025-10-12 13:59:49 +05:30
Byson94
f947c97b83 feat: improved wifi apilib and fixed prop conversion errors 2025-10-12 13:59:49 +05:30
Byson94
5d53c08fd7 feat: added parse error handling for simplefileresolver 2025-10-12 13:59:49 +05:30
Byson94
cb52e7047c feat: added INPUT_VAL env comamnd to props of input widget 2025-10-12 13:59:49 +05:30
Byson94
23a7d22062 feat: added std::command module to rhai 2025-10-12 13:59:49 +05:30
Byson94
af7cf437a3 fix: fixed stored_widget_node not existing on first run issue 2025-10-12 13:59:49 +05:30
Byson94
adfa2d9c58 feat: added update and call-fns command to ewwii 2025-10-12 13:59:49 +05:30
Byson94
62d6092956 feat: added pretty logging for rhai ParseError 2025-10-12 13:59:49 +05:30
Byson94
84bd33bfd6 docs: statictranspl --> staticscript 2025-10-12 13:59:49 +05:30
Byson94
9b13f4cea7 docs: added section for user defined modules in ewwii docs module section 2025-10-12 13:59:49 +05:30
Byson94
e2614a9832 feat: made ewwii print errors from external modules 2025-10-12 13:59:49 +05:30
Byson94
d1ecb16823 feat: added dyn_id property to hash props test fn 2025-10-12 13:59:49 +05:30
Byson94
e21d8fd836 pref: made WidgetInfo borrow data instead of owning it to improve perf 2025-10-12 13:59:49 +05:30
Byson94
2ffac9e6ca pref: removed .clone() of props from WindowInitiator::new() 2025-10-12 13:59:49 +05:30
Byson94
9de5181aaa perf: made root_node Arc<WidgetNode> to safe resources | ewwii_config.rs 2025-10-12 13:59:49 +05:30
Byson94
e35477aecc feat: removed rc wrapping form store as store was already wrapped in arc 2025-10-12 13:59:49 +05:30
Byson94
9930241970 perf: wrapped compiled_ast in arc to avoid data clone 2025-10-12 13:59:49 +05:30
Byson94
494a8da3f7 feat: removed instant::now() tracking on re-eval sys 2025-10-12 13:59:49 +05:30
Byson94
aa25c4735e perf: made store a rc to avoid clones | app.rs:371 2025-10-12 13:59:49 +05:30
Byson94
1d260f65bc perf: cached parser in re-eval system for speed 2025-10-12 13:59:49 +05:30
Byson94
3c6cbe1638 feat: improved runtime error handling of widgetnode casting 2025-10-12 13:59:49 +05:30
Byson94
fa63a99ae3 feat: reduced max_width to 100 and ran cargo fmt 2025-10-12 13:59:49 +05:30
Byson94
da1c22f525 perf: reusing compiled config to save performance and time 2025-10-12 13:59:49 +05:30
Byson94
70bbb630cc feat: stopped setting homogeneous in space_even prop is not provided 2025-10-12 13:59:49 +05:30
Byson94
44814071c8 feat: removed seen_widget_ids logic in diffing system 2025-10-12 13:59:49 +05:30
Byson94
d3a8f22bfb feat: added propagate_natural_height property to scrolledwindow 2025-10-12 13:59:49 +05:30
Byson94
43b31cb814 feat: added trace log lvel support 2025-10-12 13:59:49 +05:30
Byson94
40d5972533 feat: trace can be enabled if EWWII_TRACE env var exists 2025-10-12 13:59:49 +05:30
Byson94
26329aa75f feat: updated docs to be up-to-date with the latest changes 2025-10-12 13:59:49 +05:30
Byson94
4b698f48fa feat: made resolve_rhai_widget_attrs not rely on widgetnode -- less work for maintainers 2025-10-12 13:59:49 +05:30
Byson94
786ebf04d4 chore: ran cargo fmt 2025-10-12 13:59:49 +05:30
Byson94
9fbfcca1c2 feat: added std::math lib for rhai 2025-10-12 13:59:49 +05:30
Byson94
daf11c8d1a chore: ran cargo fmt 2025-10-12 13:59:49 +05:30
Byson94
28809ff783 fix: fixed reordering issues in dyn system
Fixed the reodering issue in the dynamic update system which was caused
by the use of `pack_end()` for adding a child to box_container in the create_widget() fn.

`pack_end()` is a horrible option as it would require hardcoding
"expanded", "fill" etc.

This fix uses the better option `add()` which fixes all the reodering
issues.

According to all the tests, (did 15+ tests in a dyn fn that would return 3
widgets) non of them had ordering issues. So, I will mark this as a fix.
2025-10-12 13:59:48 +05:30
Byson94
48dbdeb5c6 feat: made dyn sys a lil better by obliterating redundant wdgts 2025-10-12 13:59:48 +05:30
Byson94
09bba44229 feat: added better error handling for fnnotdefined 2025-10-12 13:59:48 +05:30
Byson94
6e8207cb56 feat: made window resizable by default. 2025-10-12 13:59:48 +05:30
Byson94
557254f74a refactor: removed unnecessary println! in app 530 2025-10-12 13:59:48 +05:30
Byson94
3a72ddf3d7 fix: fixed stdlib shadowed by apilib issue 2025-10-12 13:59:48 +05:30
Byson94
043892d23b feat: made x,y,widget,height props optional 2025-10-12 13:59:48 +05:30
Byson94
0490604277 feat: added get_adapter_connectivity() fn to api::wifi 2025-10-12 13:59:48 +05:30
Byson94
584a6e5911 chore: ran cargo fmt 2025-10-12 13:59:48 +05:30
Byson94
049a0337b2 feat: fixed broken current_connection_linux command 2025-10-12 13:59:48 +05:30
Byson94
a42cc5df37 chore: added new feats to changelog.md 2025-10-12 13:59:48 +05:30
Byson94
4d29933271 feat: added api module to rhai 2025-10-12 13:59:48 +05:30
Byson94
00ba7af473 feat: added json module to rhai 2025-10-12 13:59:48 +05:30
Byson94
f2a177bc79 feat: added fix in changelog.md 2025-10-12 13:59:48 +05:30
Byson94
04aff76ea4 chore: ran cargo fmt 2025-10-12 13:59:48 +05:30
Byson94
6ff1c07c42 fix: fixed window reopening issue after closing it. 2025-10-12 13:59:48 +05:30
Byson94
c23d0d29dd feat: added kill switch for poll/listen 2025-10-12 13:59:48 +05:30
Byson94
e8d08f8c43 style: removed redundant , in readme 2025-10-12 13:59:48 +05:30
Byson94
9b6f310d4f feat: added data struct example in readme 2025-10-12 13:59:48 +05:30
Byson94
f281396b6f feat: removed .yuck files from ewwii examples 2025-10-12 13:59:48 +05:30
Byson94
95ebf251a2 chore: ran cargo fmt 2025-10-12 13:59:48 +05:30
Byson94
a14163bfca feat: removed root_widget param of update_widget_tree() 2025-10-12 13:58:36 +05:30
Byson94
c64d4e5cb5 fix: removed unused id computation in get_id_to_widget_info() 2025-10-12 13:58:36 +05:30
Byson94
9bd70df8bf feat: did some stuff that could possible make create widget work 2025-10-12 13:58:36 +05:30
Byson94
8f68cc6abc chore: ran cargo fmt 2025-10-12 13:58:36 +05:30
Byson94
59709c3ddf feat: made diffing sys work | possibly
The diffing system works with updates -- as seen from tests but the widget removal/creation system is still untested and may still need more iterations.
2025-10-12 13:58:36 +05:30
Byson94
405e50effb fix: fixed widget.clone() errors 2025-10-12 13:58:36 +05:30
Byson94
631809af3c feat: added a better diffing system 2025-10-12 13:58:36 +05:30
Byson94
90f95c2963 feat: got a minimal prototype of the diffing system 2025-10-12 13:58:36 +05:30
Byson94
c252d2d554 feat: fixed broken get_home_dir() fn in std::env | rhai 2025-10-12 13:58:36 +05:30
Byson94
fdb1697ead feat: added example section and section for statctranspl 2025-10-12 13:58:36 +05:30
Byson94
045784f1f9 chore: ran cargo fmt 2025-10-12 13:58:36 +05:30
Byson94
ef13f128ed feat: fixed all compilation warnings 2025-10-12 13:58:36 +05:30
Byson94
ef46ac9d0e feat: added dyn prop support to all widgets i thnk 2025-10-12 13:58:36 +05:30
Byson94
b430e4929b feat: added kill_on_drop for listener 2025-10-12 13:58:36 +05:30
Byson94
831fe185e3 feat: added prop dyn support to more widgets 2025-10-12 13:58:36 +05:30
Byson94
fdb9c08895 feat: replaced byson94 -> Ewwii-sh 2025-10-12 13:58:36 +05:30
Byson94
abe0a37aca fix: fixed doc name and replaced eww with ewwii 2025-10-12 13:58:36 +05:30
Byson94
9f86286e57 feat: added home-button to docs 2025-10-12 13:58:36 +05:30
Byson94
9ada74d70b feat: added docs back in 2025-10-12 13:58:36 +05:30
Byson94
855f59b407 feat: replaced apache-2.0 with gplv3 2025-10-12 13:58:35 +05:30
Byson94
edcdbcc577 feat: apache-2.0 to gpl3. Making ewwii fully open source. 2025-10-12 13:58:35 +05:30
Byson94
a24daad15e fix: removed redundant argument from fn which caused errors 2025-10-12 13:58:35 +05:30
Byson94
203f5418fa feat: moved docs to Ewwii-sh/docs 2025-10-12 13:58:35 +05:30
Byson94
30c37a1fa4 chore: run cargo fmt 2025-10-12 13:58:35 +05:30
Byson94
863bfb5cf4 feat: added modules example 2025-10-12 13:58:35 +05:30
Byson94
f8bc0835d0 feat: Added monitor stdlib 2025-10-12 13:58:35 +05:30
Byson94
bef32197da feat: added data-structs example 2025-10-12 13:58:35 +05:30
Byson94
1b08627c44 Replaced example screenshot 2025-10-12 13:58:35 +05:30
Byson94
501cf8869d chore: ran cargo fmt 2025-10-12 13:58:35 +05:30
Byson94
5d272ce420 feat: added example, fixed small bugs 2025-10-12 13:58:35 +05:30
Byson94
e15762c725 docs: added dyn_id docs 2025-10-12 13:58:35 +05:30
Byson94
a8f54306aa hell: I AM SORRY! I CAUSED PAIN UPON ALL USERS
I MADE KEYS A REQUIRED FACTOR FOR DYNAMIC UPDATES.... I AM REALLY SORRY, I HAD NO OTHER OPTIONS OTHAT THAN THIS MAJOR UX FLAW...
2025-10-12 13:58:35 +05:30
Byson94
664412553d feat: Added dynamic prop update support 2025-10-12 13:58:35 +05:30
Byson94
b512a35e3d feat: added recursive support for get_id_to_props_map 2025-10-12 13:58:35 +05:30
Byson94
6e3268ca17 feat: implmented half working dynamic update system 2025-10-12 13:58:35 +05:30
Byson94
03a2bcf37e feat: Build custom module resolver for rhai 2025-10-12 13:58:35 +05:30
Byson94
6f65d127aa docs: rearranged expr_lang.md path 2025-10-12 13:58:35 +05:30
Byson94
1034c44ee3 docs: readded expression_language, fixed str interpolation eg 2025-10-12 13:58:35 +05:30
Byson94
4ec6fe308c fix: replaced include() fn in config doc as it got removed 2025-10-12 13:58:35 +05:30
Byson94
01b05b0bda fix: fixed first window example in config::configuration.md 2025-10-12 13:58:35 +05:30
Byson94
d377fc409f feat: Added Widget Properties and widget param doc
Added widget properties (what they do & their signature), the parameters of the widget function call.

I may have also improved the docs on some other parts which I may have forgotten.
2025-10-12 13:58:35 +05:30
Byson94
c2c0c7e292 feat: removed include because rhai supports import/export 2025-10-12 13:58:35 +05:30
Byson94
8609a6acb7 feat: Added example 2025-10-12 13:58:35 +05:30
Byson94
7142567848 chore: ran cargo fmt 2025-10-12 13:58:35 +05:30
Byson94
58c93576b2 feat: Added support for stack widget 2025-10-12 13:58:35 +05:30
Byson94
5a4972f940 feat: Added transform widget support. 2025-10-12 13:58:35 +05:30
Byson94
64f94a11cd feat: Added tooltip, clrchooser, clrbttn widget support 2025-10-12 13:58:35 +05:30
Byson94
45745ed381 chore: ran cargo fmt 2025-10-12 13:58:35 +05:30
Byson94
6834b664fd feat: Added basic and fragile dyn sys for poll/listen 2025-10-12 13:58:35 +05:30
Byson94
f03fbbfafe refactor: Fixed many warnings 2025-10-12 13:58:35 +05:30
Byson94
ef52f691cf chore(rebrand): replaced eww to ewwii 2025-10-12 13:58:23 +05:30
Byson94
273fdfb082 feat: Added compile_code fn to parser 2025-10-12 13:58:23 +05:30
Byson94
1de8c6998a doc: Added modules documentation 2025-10-12 13:58:23 +05:30
Byson94
cc21ff1863 feat: Added std module with text and env submodule 2025-10-12 13:58:23 +05:30
Byson94
ea0f4d091a feat: added better dynamic update 2025-10-12 13:58:23 +05:30
Byson94
4a43eabed2 docs: fixed config & syntax file path 2025-10-12 13:58:23 +05:30
Byson94
9d18de1110 docs: improved docs and added nested chapters 2025-10-12 13:58:23 +05:30
Byson94
87984cdaa8 docs: improved docs by refactoring the configuration.md 2025-10-12 13:58:23 +05:30
Byson94
ab5d8ce28a feat: added gtk event box support 2025-10-12 13:58:23 +05:30
Byson94
118af53cc8 feat: added gtk scrolledwindow support 2025-10-12 13:58:23 +05:30
Byson94
d7564d716f feat: Added gtk calendar support 2025-10-12 13:58:23 +05:30
Byson94
69d8523b85 chore: ran cargo fmt 2025-10-12 13:58:23 +05:30
Byson94
535cf3b3ba feat: added gtk input support and changed optional logic 2025-10-12 13:58:23 +05:30
Byson94
ddaffd166a feat: added support for gtk image 2025-10-12 13:58:23 +05:30
Byson94
7bec8e42ce feat: added support for graph 2025-10-12 13:58:23 +05:30
Byson94
5e3f538674 feat: added support for circular progress bar 2025-10-12 13:58:23 +05:30
Byson94
530ccca1e4 feat: added support for gtk expander 2025-10-12 13:58:23 +05:30
Byson94
f1a7cfb48c feat: added support for gtk_combo_box_text 2025-10-12 13:58:23 +05:30
Byson94
6b9fec8ef7 chore: removed unnecessary test 2025-10-12 13:58:23 +05:30
Byson94
322311bda3 chore: fixed logo path 2025-10-12 13:58:23 +05:30
Byson94
643db859a3 chore: Changed logo 2025-10-12 13:58:23 +05:30
Byson94
e374a203ff chore: ran cargo fmt 2025-10-12 13:58:23 +05:30
Byson94
21658b19bc feat: Added support for gtk revealer widget 2025-10-12 13:58:23 +05:30
Byson94
d6b439f097 feat: added checkbox widget support 2025-10-12 13:58:23 +05:30
Byson94
74c6be70f7 feat: Added basic props support for all widgets 2025-10-12 13:58:23 +05:30
Byson94
8dd99376fd feat: Added semi dynamic support for rhai 2025-10-12 13:58:23 +05:30
Byson94
653bf17535 chore: run cargo fmt 2025-10-12 13:58:23 +05:30
Byson94
4b100d0073 feat: Added note section in error report 2025-10-12 13:58:23 +05:30
Byson94
5a0d267770 chore: ran cargo fmt to format code 2025-10-12 13:58:23 +05:30
Byson94
adb0442da5 feat: Improved err printing with help/hint and better UI 2025-10-12 13:58:23 +05:30
Byson94
674735ca65 feat: added dummy variables in rhai scope to fix eval 2025-10-12 13:58:23 +05:30
Byson94
ae31a360e9 feat: Added poll/listen IMPROVED error printing 2025-10-12 13:58:23 +05:30
Byson94
2188e9000e feat: Added polling (untested) 2025-10-12 13:58:23 +05:30
Byson94
1623d208f7 feat: starting the work on rhai signals 2025-10-12 13:58:22 +05:30
Byson94
18e9c91d69 fix: fixed license in Cargo.toml(s) 2025-10-12 13:58:22 +05:30
Byson94
2dd0850854 docs: Improved docs, added more files to fill in with content 2025-10-12 13:58:22 +05:30
Byson94
65f6e436f3 feat: Added support for buttons 2025-10-12 13:58:22 +05:30
Byson94
e07b15cd00 perf: Fixed calling get_window_rectangle in a loop 2025-10-12 13:58:22 +05:30
Byson94
7de16ec735 feat: added gtk scale support 2025-10-12 13:58:22 +05:30
Byson94
f18d4f1915 feat: Added better errors for rhai 2025-10-12 13:58:22 +05:30
Byson94
855393e137 feat: Added progress bar support 2025-10-12 13:58:22 +05:30
Byson94
7488330980 feat: Added center box widget support 2025-10-12 13:58:22 +05:30
Byson94
3ee3e1da5c feat: Removed ipc_server concept entirely 2025-10-12 13:58:22 +05:30
Byson94
ce48913e43 feat(style): Added scss/css styling support for rhai 2025-10-12 13:58:22 +05:30
Byson94
c9faec6c37 feat: Removed ipc server of rhai temporarely 2025-10-12 13:58:22 +05:30
Byson94
79041e5f40 feat: supported creating gtk labels in rhai 2025-10-12 13:58:22 +05:30
Byson94
5d03bdf561 fix: removed child of button and moved it to props 2025-10-12 13:58:22 +05:30
Byson94
8359d2191a fix: replaced ewwii.lua -> ewwii.rhai 2025-10-12 13:58:22 +05:30
Byson94
2f0874531e docs: Improved structure and moved installation to getting started 2025-10-12 13:58:22 +05:30
Byson94
b43cdabd46 Updated todo 2025-10-12 13:58:22 +05:30
Byson94
4aee3477a5 Added pretty_assertions to Cargo.toml 2025-10-12 13:58:22 +05:30
Byson94
2f027e5fa1 refactor: formatted code with cargo fmt 2025-10-12 13:58:22 +05:30
Byson94
b6df3aaf38 fix: Removed ParseError which was a duplicate of Error 2025-10-12 13:58:22 +05:30
Byson94
dace5d545a feat: fixed backend win opts to include fn for most structs 2025-10-12 13:58:22 +05:30
Byson94
0f07854917 fix: used resizable, stacking and backend_opts directly in win init 2025-10-12 13:58:22 +05:30
Byson94
8efaec8c6d feat: Added backend_options in windowdef struct 2025-10-12 13:58:22 +05:30
Byson94
ed5e388e7d feat(changelog): added new point in changelog 2025-10-12 13:58:22 +05:30
Byson94
11d1f3f1ce feat(ci): removed deno usage in gh-pages.yml 2025-10-12 13:58:22 +05:30
Byson94
0b5d69bf28 fix(ci): Fixed path (eww -> ewwii) 2025-10-12 13:58:22 +05:30
Byson94
636e926ece fix: Fixed monitoridentifier using index instead of numeric 2025-10-12 13:58:22 +05:30
Byson94
c57248363e feat: Added fromstr for anchorpoint 2025-10-12 13:58:22 +05:30
Byson94
4f88a2e554 feat: Added from fn to convert win_geo::coords to coords::Coords 2025-10-12 13:58:22 +05:30
Byson94
4b13c38c02 fix: Did many fixes that i forgot | 17 errors remaining 2025-10-12 13:58:22 +05:30
Byson94
c826822ea5 fix: removed .ok() from prop code in widget_def.rs 2025-10-12 13:58:22 +05:30
Byson94
ed204b9111 fix: used stm_enum_parse! in backend win opts instead of enum_parse! 2025-10-12 13:58:22 +05:30
Byson94
2f05508385 fix: fixed invalid use of diagerror & removed unnecessary arg in opts 2025-10-12 13:58:22 +05:30
Byson94
1108b33f7c fix: renamed window_geometry align_coord fn to work with app.rs 2025-10-12 13:58:22 +05:30
Byson94
31e8a8e302 feat: Removed open-many arg because we are pre-mature 2025-10-12 13:58:22 +05:30
Byson94
0eaa5f458b fix(warn): fixed all warnings related to imports 2025-10-12 13:58:22 +05:30
Byson94
d065e91626 feat(widgets): Made build_widget support both win_def and win_node 2025-10-12 13:58:22 +05:30
Byson94
eca6f74545 fix: changed fn in app.rs and fixed coords error 2025-10-12 13:58:22 +05:30
Byson94
39c08c8201 fix: removed old printstate and printgraph daemon commands 2025-10-12 13:58:22 +05:30
Byson94
01fbe1cf24 fix: removed semicolon form enum usage in backend win opts 2025-10-12 13:58:22 +05:30
Byson94
5d5d82b3d6 fix: added cstm_enum_parse to output errors in enumparserror 2025-10-12 13:58:22 +05:30
Byson94
d213e91260 docs: changed theme to navy (ayu -> navy) 2025-10-12 13:58:22 +05:30
Byson94
434cc3836a fix: naming error of anchor_point in window_geometry.rs 2025-10-12 13:58:22 +05:30
Byson94
3f3036c8cc fix: removed Eq derive from backend win opts to fix numwithunit error 2025-10-12 13:58:22 +05:30
Byson94
51a98c8e9f refactor: refactoring the code to fix the 75 errors that popped out of nowhere 2025-10-12 13:58:22 +05:30
Byson94
726e7c3ef1 fix: removed unennecessary impl in backend win opts 2025-10-12 13:58:22 +05:30
Byson94
cc7e931682 fix: fixed backend win opts and build_widget
fixed backend_window_options and build_widget codes. Removed unnecessary Error enum which used yuck internals and removed unnecessary children value in build_widget match.
2025-10-12 13:58:22 +05:30
Byson94
8c35ebdb2c fix: removed impl used by yuck in diag_error and fixed 1 compiler error 2025-10-12 13:58:22 +05:30
Byson94
00a4561a4b feat: added widget_definitions_helper file to help widget_definition codes 2025-10-12 13:58:22 +05:30
Byson94
181a5207e9 refactor: Refactored parse_geometry in window_initiator which was incomplete 2025-10-12 13:58:22 +05:30
Byson94
4814a552c7 refactor: Refactored backend_window_options and commented code related to yuck 2025-10-12 13:58:22 +05:30
Byson94
46b84fc6a8 fix: Fixed imports, lalrpop imports (not needed) and removed old yuck reference 2025-10-12 13:58:22 +05:30
Byson94
bc92ae8319 fix: uncommented error_handling_ctx to fix more compiler err 2025-10-12 13:58:22 +05:30
Byson94
d5e857f994 fix: Fixed more compiler errors (frgt what I fixed) 2025-10-12 13:58:22 +05:30
Byson94
bed41badbc fix: coord import in window_geometry 2025-10-12 13:58:15 +05:30
Byson94
c4e8692564 fix: Fixed compilation errors on WindowStacking 2025-10-12 13:58:15 +05:30
Byson94
0bef366685 fix(cargo): ewwii_tests warnings 2025-10-12 13:58:04 +05:30
Byson94
dc072e21af fix: Added proper imports (mod/use) to fix compilation errors 2025-10-12 13:58:04 +05:30
Byson94
fafb90d2d2 doc: updated changelog.md and added features and nt changes 2025-10-12 13:58:04 +05:30
Byson94
7222716957 docs(SUMMARY.md): improved sidebar layout 2025-10-12 13:58:04 +05:30
Byson94
ee172e50ed docs: Made few changes to configuration summary 2025-10-12 13:58:04 +05:30
Byson94
f6dc3dfc74 feat: Added & configuired backend_window_options a bit 2025-10-12 13:58:04 +05:30
Byson94
80b44941d0 feat: moved coords to window/ added window_geomtery from yuck/ crate 2025-10-12 13:58:04 +05:30
Byson94
73ecb64a9d feat: Added proper parse_geometry function in window_initiator.rs 2025-10-12 13:58:04 +05:30
Byson94
a8502b63b2 feat(window): Added window directory to rewrite yuck-win relation 2025-10-12 13:58:04 +05:30
Byson94
f120d12939 refactor: core window argument parser code to work with modern config parser (rhai) 2025-10-12 13:58:04 +05:30
Byson94
81abf8925b feat: adding back the files that were removed 2025-10-12 13:58:04 +05:30
Byson94
dc9aceb1cf docs(rebrand): change eww to ewwii 2025-10-12 13:57:50 +05:30
Byson94
e70685a166 fix(ci): Fixed ci to work with main branch as it used master 2025-10-12 13:57:50 +05:30
Byson94
850f322dff doc: updated docs (changed github repo) 2025-10-12 13:57:50 +05:30
Byson94
50d6e0dc1d feat(widgets): Added window.rs & fixed small compilation errs 2025-10-12 13:57:50 +05:30
Byson94
48bf133e46 feat(iirhai): Improved lable to accept props instead of string 2025-10-12 13:57:50 +05:30
Byson94
002f024926 feat(readme): Changed dependency status to ewwii's github | removed cargo_out.txt 2025-10-12 13:57:50 +05:30
Byson94
d86c0a8ba8 feat: Added test files to test build_gtk_widget() | rewriting widgets/ 2025-10-12 13:57:50 +05:30
Byson94
7603ea0371 fix: removed widget_def*.rs and fixed invalid root_widget var name in ewwii_config.rs 2025-10-12 13:57:50 +05:30
Byson94
c97ffbb99e fix(macro): Added gen_diagnostic_macro.rs to fix 15+ build errors 2025-10-12 13:57:50 +05:30
Byson94
dee74fbe03 fix(code): fixed about 10 errors due to dynval not imported 2025-10-12 13:57:50 +05:30
Byson94
4cf3a53b4f fix: Fixing more build errors that is caused by foundational scripts 2025-10-12 13:57:50 +05:30
Byson94
2b72e5ea0b fix: added root widget value to window def 2025-10-12 13:57:50 +05:30
Byson94
76c3de4ace fix(ipc): Fixed iirhai daemon to not start if it is already running 2025-10-12 13:57:50 +05:30
Byson94
a89fa7afb0 feat(nuke): removing unnecessary files which use yuck 2025-10-12 13:57:50 +05:30
Byson94
424c388ca3 style(comments): added/removed comments 2025-10-12 13:57:50 +05:30
Byson94
5f1859fff5 feat(kill): Killed state/ directory as well as files using yuck 2025-10-12 13:57:50 +05:30
Byson94
5af552721c feat(kill): killed widget_definitions which used yuck heavily 2025-10-12 13:57:50 +05:30
Byson94
3818cbc7cb feat(rm): removed yuck and simplexpr | note: you will get 444 errors 2025-10-12 13:57:50 +05:30
Byson94
31e5a695d7 fix: eww compile errors 2025-10-12 13:56:55 +05:30
Byson94
b7470581a9 feat(rename): renamed eww && eww_shared_util to be ewwii 2025-10-12 13:56:32 +05:30
Byson94
2a36c6ea6e feat(rename): Renamed eww_config to ewwii_config 2025-10-12 13:56:32 +05:30
Byson94
99fefbfb44 style(eww_config.rs): removed unnecessary whitespace 2025-10-12 13:56:32 +05:30
Byson94
f045f4eb38 feat(ipc): Improved iirhai daemon && added read/write 2025-10-12 13:56:32 +05:30
Byson94
2f130502cc feat(ipc): added mpsc to read messages from iirhai 2025-10-12 13:56:32 +05:30
Byson94
4b0f123313 feat(source): removing ALL yuck reference | NOTE: compilation will fail 2025-10-12 13:56:32 +05:30
Byson94
f69edff927 feat(ipc): Added ipc socket to paths.rs 2025-10-12 13:56:32 +05:30
Byson94
246535f3f1 fix(ipc): Fixed errors in ipc_server.rs related to iirhai 2025-10-12 13:56:32 +05:30
Byson94
efaab0c83b feat(ewwii): added functions to read iirhai ipc server 2025-10-12 13:56:32 +05:30
Byson94
669660a49c feat(ipc): added ipc daemon to iirhai 2025-10-12 13:56:32 +05:30
Byson94
3651e58631 feat(config): changed Cargo.toml files and added iirhai-daemon bin crate 2025-10-12 13:56:32 +05:30
Byson94
2ba90838e4 feat(iirhai): added ipc_manager (transpiler) 2025-10-12 13:56:32 +05:30
Byson94
72ded26393 style: just some comment ig 2025-10-12 13:56:32 +05:30
Byson94
111e0914b5 refactor: replacing yuck references with rhai 2025-10-12 13:56:32 +05:30
Byson94
2bfa24e72c rm: removed random duck/ crate 2025-10-12 13:56:32 +05:30
Byson94
bf61dd030a chore: replaced iirhai with the latest code from rhai-dlt 2025-10-12 13:56:32 +05:30
Byson94
592143137f chore(rename): rename iirhai crate 2025-10-12 13:55:58 +05:30
Byson94
999ad82e22 chore(license): rename and improve eww license 2025-10-12 13:55:30 +05:30
Byson94
1f95368168 chore: change few things and add comments 2025-10-12 13:54:49 +05:30
Byson94
bce8d05170 fix: SCREW IT! I AM DOING THIS COMMIT BECAUSE THERE WAS A MAJOR DEPENDENCY HELL 2025-10-12 13:54:49 +05:30
Byson94
7d72d4cc9c Create LICENSE 2025-10-12 13:54:49 +05:30
Byson94
3285b20d98 feat: add a basic rhai yuck replacement 2025-10-12 13:54:38 +05:30
Byson94
8cd92cc8c3 chore(rebrand): replace instance of eww with ewwii 2025-10-12 13:54:11 +05:30
Byson94
6a993f765e chore(credits): add credits in readme 2025-10-12 13:53:54 +05:30
Byson94
565fb896bd chore: mark things to change 2025-10-12 13:53:33 +05:30
Byson94
d6cff70840 chore(rebrand): replace eww with ewwii 2025-10-12 13:51:47 +05:30
Byson94
56f57e2ad6 fix: solve more cargo test issus 2025-10-12 13:24:39 +05:30
Byson94
961f6059b7 Merge branch 'main' into iidev 2025-10-12 13:15:06 +05:30
Byson94
2f34b6271e fix(ci): Satisfying doctest 2025-10-12 13:14:56 +05:30
Byson94
2c97bce3c0 Merge branch 'main' into iidev 2025-10-12 13:08:44 +05:30
Byson94
ed8cad319d fix: fixing doctest issues with auto_plugin macro 2025-10-12 13:08:20 +05:30
Byson94
8e39fe29ba fix(ci): using arch linux docker container 2025-10-12 12:59:08 +05:30
Byson94
1ee72b03b4 feat: adding panic handling 2025-10-12 12:48:31 +05:30
Byson94
92ad2b4a0d feat: added onkeypress and onkeyrelease props 2025-10-12 12:48:31 +05:30
Byson94
61d500142c fix: fixed old widget creeping in issue 2025-10-12 12:48:31 +05:30
Byson94
cf361902c2 fix(ci): fixing packages 2025-10-12 12:48:21 +05:30
Byson94
07d6293173 chore: cargo fmt 2025-10-11 15:35:17 +05:30
Byson94
c446321173 feat: making examples in readme look good 2025-10-11 15:34:14 +05:30
Byson94
17d59c1e15 fix(ci): Fixing indentation 2025-10-11 15:08:05 +05:30
Byson94
097f4c90fd fix(ci): Working on fixing the ci not running issue 2025-10-11 15:06:01 +05:30
45 changed files with 2270 additions and 777 deletions

View File

@@ -26,5 +26,4 @@ Please make sure you can check all the boxes that apply to this PR.
- [ ] All widgets I've added are correctly documented.
- [ ] I added my changes to CHANGELOG.md, if appropriate.
- [ ] The documentation in the `docs/content/main` directory has been adjusted to reflect my changes.
- [ ] I used `cargo fmt` to automatically format all code before committing

Binary file not shown.

Before

Width:  |  Height:  |  Size: 500 KiB

View File

@@ -1,51 +1,56 @@
name: build
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
push:
branches:
- main
pull_request:
branches:
- main
env:
CARGO_TERM_COLOR: always
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Install GTK4 dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libgtk-4-dev \
libgtk-layer-shell-dev \
pkg-config \
build-essential
build:
runs-on: ubuntu-latest
container:
image: archlinux:latest
- uses: actions/checkout@v4
steps:
- name: Install dependencies
run: |
pacman -Syu --noconfirm
pacman -S --noconfirm base-devel gtk4 gtk4-layer-shell pkgconf git
- name: Setup rust
uses: dtolnay/rust-toolchain@stable
with:
components: clippy,rustfmt
- uses: actions/checkout@v4
- name: Load rust cache
uses: Swatinem/rust-cache@v2
- name: Setup rust
uses: dtolnay/rust-toolchain@stable
with:
components: clippy,rustfmt
- name: Setup problem matchers
uses: r7kamura/rust-problem-matchers@v1
- name: Load rust cache
uses: Swatinem/rust-cache@v2
- name: Check formatting
run: cargo fmt -- --check
- name: Check with default features
run: cargo check
- name: Setup problem matchers
uses: r7kamura/rust-problem-matchers@v1
- name: Run tests
run: cargo test
- name: Check formatting
run: cargo fmt -- --check
- name: Check x11 only
run: cargo check --no-default-features --features=x11
- name: Check wayland only
run: cargo check --no-default-features --features=wayland
- name: Check no-backend
run: cargo check --no-default-features
- name: Check with default features
run: cargo check
- name: Run tests
run: cargo test
- name: Check x11 only
run: cargo check --no-default-features --features=x11
- name: Check wayland only
run: cargo check --no-default-features --features=wayland
- name: Check no-backend
run: cargo check --no-default-features

View File

@@ -5,6 +5,68 @@ All notable changes to `ewwii` are documented here.
This changelog follows the [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format,
and this project adheres to [Semantic Versioning](https://semver.org/).
## [UNRELEASED]
### Added
- `gtk_ui` function for loading .ui files.
- `widget-control` (`wc` in short) command for controlling widgets.
- `placeholder` property to input widget.
- `transition_duration` property to stack widget.
- `widget_control` utility function for dynamic widget handling.
- `text` and `show_text` property to progressbar widget.
- `content_fit` property to image widget.
- `can_shrink` property to image widget.
- `mutations` property to localsignal.
- `eval_ignore` property to all widgets.
- Touch support to scale widget.
### Fixed
- `clockwise` property not working on circular_progress.
### Removed
- icon widget.
## [0.3.1] - 2025-11-01
## Fixed
- Circular progress bar not updating dynamically.
- LocalSignal values not getting transformed to suite property type.
- LocalBind not finding properties of range subclasses.
## [0.3.0] - 2025-11-01
### Added
- `localsignal` signal for fast and cheap property update.
- `localbind` utility for binding `localsignal` to a widget property.
- `onkeypress` property to eventbox.
- `onkeyrelease` property to eventbox.
- Selection of dash as shell if it installed.
- `--with-plugin` flag for `daemon` command.
- `register_function` API in ewwii_plugin_api for registering functions that rhai can call to.
- `slib` rhai module for calling functions registered via `register_function`.
- `orientation` property to eventbox.
- `spacing` property to eventbox.
- `space_evenly` property to eventbox.
- An advanced widget named `flowbox`.
- `focusable` property to all widget.
- `widget_name` property to all widget.
- `lifetime` flag for update command.
- `circular-progress` widget back.
### Fixed
- Old widget creeping into new ones after hot reload.
- Ewwii defaulting to default gtk4 theme. #9
- Few issues with eventbox drop target.
- Poll/Listen variables not exposed in other modules on first launch.
- Not able to define poll/listen variables in other files.
- Overlay and Tooltip widgets not being reactive.
## [0.3.0-beta] - 2025-10-11
### Added

39
Cargo.lock generated
View File

@@ -486,7 +486,7 @@ dependencies = [
[[package]]
name = "ewwii"
version = "0.3.0"
version = "0.4.0"
dependencies = [
"anyhow",
"bincode",
@@ -515,6 +515,7 @@ dependencies = [
"serde",
"serde_json",
"shared_utils",
"shell-words",
"simple-signal",
"smart-default",
"static_assertions",
@@ -527,7 +528,7 @@ dependencies = [
[[package]]
name = "ewwii_plugin_api"
version = "0.4.0"
version = "0.7.0"
dependencies = [
"gtk4",
"rhai",
@@ -1636,9 +1637,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.37"
version = "1.0.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
dependencies = [
"proc-macro2",
]
@@ -1719,9 +1720,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
[[package]]
name = "rhai"
version = "1.23.4"
version = "1.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "527390cc333a8d2cd8237890e15c36518c26f8b54c903d86fc59f42f08d25594"
checksum = "f4e35aaaa439a5bda2f8d15251bc375e4edfac75f9865734644782c9701b5709"
dependencies = [
"ahash",
"bitflags 2.9.4",
@@ -1766,6 +1767,7 @@ dependencies = [
"ahash",
"anyhow",
"codespan-reporting",
"gtk4",
"libc",
"log",
"nix",
@@ -1773,6 +1775,7 @@ dependencies = [
"regex",
"rhai",
"rhai_trace",
"scan_prop_proc",
"serde",
"shared_utils",
"tokio",
@@ -1780,9 +1783,9 @@ dependencies = [
[[package]]
name = "rhai_trace"
version = "0.3.0"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90093b2d5beff618cbf5698c4952ecca7eca5c5a6d9a892c0d19d9046d8329e4"
checksum = "4415c698df298d65e46e6d73905afc1b08e2fb60e68b1850c1af9e7dc499d467"
dependencies = [
"rhai",
]
@@ -1830,6 +1833,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scan_prop_proc"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
@@ -1909,10 +1921,17 @@ name = "shared_utils"
version = "0.1.0"
dependencies = [
"anyhow",
"once_cell",
"rhai",
"serde",
]
[[package]]
name = "shell-words"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
@@ -2003,9 +2022,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.106"
version = "2.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
checksum = "2a26dbd934e5451d21ef060c018dae56fc073894c5a7896f882928a76e6d081b"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -1,12 +1,13 @@
[workspace]
members = ["crates/*", "tools/*"]
members = ["crates/*", "tools/*", "proc_macros/*"]
resolver = "2"
[workspace.dependencies]
shared_utils = { version = "0.1.0", path = "crates/shared_utils" }
rhai_impl = { version = "0.1.0", path = "crates/rhai_impl" }
ewwii_plugin_api = { version = "0.4.0", path = "crates/ewwii_plugin_api" }
scan_prop_proc = { version = "0.1.0", path = "proc_macros/scan_prop_proc" }
ewwii_plugin_api = { version = "0.7.0", path = "crates/ewwii_plugin_api" }
anyhow = "1.0.86"
ahash = "0.8.12"
@@ -25,7 +26,7 @@ derive_more = { version = "1", features = [
extend = "1.2"
futures = "0.3.30"
grass = "0.13.4"
gtk4 = "0.10.1"
gtk4 = { version = "0.10.1", features = ["v4_8"] }
itertools = "0.13.0"
libc = "0.2"
log = "0.4"
@@ -35,7 +36,7 @@ once_cell = "1.19"
pretty_assertions = "1.4.0"
pretty_env_logger = "0.5.0"
regex = "1.10.5"
rhai = { version = "1.22.2" }
rhai = "1.23.6"
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
simple-signal = "1.1"
@@ -45,6 +46,10 @@ thiserror = "1.0"
tokio = { version = "1.39.2", features = ["full"] }
unescape = "0.1"
wait-timeout = "0.2"
syn = "2.0.107"
quote = "1.0.41"
proc-macro2 = "1.0.101"
shell-words = "1.1.0"
[profile.dev]
split-debuginfo = "unpacked"

View File

@@ -1,25 +1,31 @@
[![dependency status](https://deps.rs/repo/github/byson94/ewwii/status.svg)](https://deps.rs/repo/github/byson94/ewwii)
[![docs link](https://img.shields.io/badge/documentation-link-blue)](https://ewwii-sh.github.io/docs)
# Ewwii
<img src="./.github/EwwiiLogo.png" height="100" align="left"/>
Elkowars Wacky Widgets Imporved Interface is a fork of Elkowars Wacky Widgets which is a standalone widget system made in Rust that allows you to implement your own, custom widgets in any window manager.
Elkowars Wacky Widgets Improved Interface is a fork of Elkowars Wacky Widgets which is a standalone widget system made in Rust that allows you to implement your own, custom widgets in any window manager.
## Examples
All examples are in the [examples directory](./examples/).
Examples of projects powered by ewwii.
- A basic bar [CLICK TO SEE](./examples/ewwii-bar) <br>
![Example 1](./examples/ewwii-bar/ewwii-bar.png)
| Project | Preview |
|---------|---------|
| **Basic Bar**<br>[- View Example](./examples/ewwii-bar) | [![Basic Bar](./examples/ewwii-bar/ewwii-bar.png)](./examples/ewwii-bar) |
| **Data Structures**<br>[- View Example](./examples/data-structures) | [![Data Structures](./examples/data-structures/data-structures-preview.png)](./examples/data-structures) |
| **Wi-Fi GUI Template**<br>[- View on GitHub](https://github.com/Ewwii-sh/ewifi_gui_template) | ![Wi-Fi GUI Template](https://raw.githubusercontent.com/Ewwii-sh/ewifi_gui_template/main/.github/wifi_manager_template.png) |
| **Obsidian Bar Template**<br>[- View on GitHub](https://github.com/Ewwii-sh/obsidian-bar) | [![Obsidian Bar](https://raw.githubusercontent.com/Ewwii-sh/obsidian-bar/main/.github/screenshot.png)](https://github.com/Ewwii-sh/obsidian-bar) |
| **Binary Dots by [@BinaryHarbinger](https://github.com/BinaryHarbinger)**<br>[- View on GitHub](https://github.com/BinaryHarbinger/binarydots/) | [![Binary Dots](https://raw.githubusercontent.com/BinaryHarbinger/binarydots/main/preview/Desktop.png)](https://github.com/BinaryHarbinger/binarydots)
| **Astatine Dots (Linux Rice with Ewwii)**<br>[- View on GitHub](https://github.com/Ewwii-sh/astatine-dots) | [![Astatine Dots](https://github.com/user-attachments/assets/f028ca1f-e403-476d-a7d9-cadce47691b7)](https://github.com/Ewwii-sh/astatine-dots) |
- Data structures [CLICK TO SEE](./examples/data-structures) <br>
![Example 2](./examples/data-structures/data-structures-preview.png)
## Features
## Templates
- A wifi gui template [CLICK TO SEE](https://github.com/Ewwii-sh/ewifi_gui_template) <br>
<img src="https://raw.githubusercontent.com/Ewwii-sh/ewwii/main/.github/screenshots/wifi_manager_template.png" width="400" />
- Powered by Gtk4
- Supports Hot reload
- Extensibility via plugins and rhai modules
- X11 + Wayland support
## Contribewwtiing

View File

@@ -1,6 +1,6 @@
[package]
name = "ewwii"
version = "0.3.0"
version = "0.4.0"
authors = ["byson94 <byson94wastaken@gmail.com>"]
description = "Widgets for everyone made better!"
license = "GPL-3.0-or-later"
@@ -17,7 +17,7 @@ wayland = ["gtk4-layer-shell"]
[dependencies]
shared_utils.workspace = true
rhai_impl.workspace = true
ewwii_plugin_api = { workspace = true }
ewwii_plugin_api.workspace = true
gtk4-layer-shell = { version = "0.6.3", optional = true }
gdk4-x11 = { version = "0.10.1", optional = true }
@@ -49,7 +49,8 @@ simple-signal.workspace = true
tokio = { workspace = true, features = ["full"] }
unescape.workspace = true
wait-timeout.workspace = true
rhai.workspace = true
rhai = { workspace = true, features = ["internals"] }
shell-words.workspace = true
# Plugin loading
libloading = "0.8.9"

View File

@@ -23,6 +23,7 @@ use crate::{
*,
};
use anyhow::{anyhow, bail};
use ewwii_plugin_api as epapi;
use gdk::Monitor;
use gtk4::Window;
use gtk4::{gdk, glib};
@@ -84,9 +85,14 @@ pub enum DaemonCommand {
ShowState(DaemonResponseSender),
ListWindows(DaemonResponseSender),
ListActiveWindows(DaemonResponseSender),
WidgetControl {
action: crate::opts::WidgetControlAction,
sender: DaemonResponseSender,
},
TriggerUpdateUI {
inject_vars: Option<HashMap<String, String>>,
should_preserve_state: bool,
lifetime: Option<String>,
sender: DaemonResponseSender,
},
CallRhaiFns {
@@ -153,6 +159,7 @@ pub struct App<B: DisplayBackend> {
/// When reloading the config, these should be opened again.
pub failed_windows: HashSet<String>,
pub css_provider: gtk4::CssProvider,
pub reloading: bool,
/// Sender to send [`DaemonCommand`]s
pub app_evt_send: UnboundedSender<DaemonCommand>,
@@ -165,6 +172,7 @@ pub struct App<B: DisplayBackend> {
// The cached store of poll/listen handlers
pub pl_handler_store: rhai_impl::updates::ReactiveVarStore,
pub clear_pl_onclose: HashMap<String, String>,
pub rt_engine_config: EngineConfValues,
pub config_parser: Rc<RefCell<ParseConfig>>,
@@ -348,8 +356,19 @@ impl<B: DisplayBackend> App<B> {
let output = format!("{:#?}", &self.pl_handler_store.read().unwrap());
sender.send_success(output)?
}
DaemonCommand::TriggerUpdateUI { inject_vars, should_preserve_state, sender } => {
match self.trigger_ui_update_with(inject_vars, should_preserve_state) {
DaemonCommand::TriggerUpdateUI {
inject_vars,
should_preserve_state,
lifetime,
sender,
} => {
match self.trigger_ui_update_with(inject_vars, should_preserve_state, lifetime) {
Ok(_) => sender.send_success(String::new())?,
Err(e) => sender.send_failure(e.to_string())?,
};
}
DaemonCommand::WidgetControl { action, sender } => {
match self.perform_widget_control(action) {
Ok(_) => sender.send_success(String::new())?,
Err(e) => sender.send_failure(e.to_string())?,
};
@@ -404,6 +423,9 @@ impl<B: DisplayBackend> App<B> {
// let scope_index = ewwii_window.scope_index;
ewwii_window.close();
if let Some(var_name) = self.clear_pl_onclose.remove(instance_id) {
self.pl_handler_store.write().unwrap().remove(&var_name);
}
if auto_reopen {
self.failed_windows.insert(instance_id.to_string());
@@ -418,7 +440,7 @@ impl<B: DisplayBackend> App<B> {
}
// stop poll/listen handlers if no windows are open
if self.open_windows.is_empty() {
if self.open_windows.is_empty() || self.reloading {
rhai_impl::updates::kill_state_change_handler();
}
@@ -504,7 +526,7 @@ impl<B: DisplayBackend> App<B> {
}
let stored_parser_clone = self.config_parser.clone();
if self.open_windows.is_empty() {
if self.open_windows.is_empty() || self.reloading {
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<String>();
let widget_reg_store = self.widget_reg_store.clone();
@@ -518,6 +540,12 @@ impl<B: DisplayBackend> App<B> {
let store = self.pl_handler_store.clone();
let b_interval = self.rt_engine_config.batching_interval;
// kick start the localsignal
rhai_impl::updates::handle_localsignal_changes(
stored_parser_clone.clone(),
compiled_ast.clone(),
);
glib::MainContext::default().spawn_local(async move {
let mut pending_updates = HashSet::new();
@@ -538,10 +566,11 @@ impl<B: DisplayBackend> App<B> {
let vars = store.read().unwrap().clone();
let mut parser_rc = stored_parser_clone.borrow_mut();
let compiled_ast_ref = compiled_ast.as_ref().map(|rc| rc.borrow());
match generate_new_widgetnode(
&vars,
&config_path,
compiled_ast.as_deref(),
compiled_ast_ref.as_deref(),
&mut *parser_rc,
)
.await
@@ -572,13 +601,17 @@ impl<B: DisplayBackend> App<B> {
let widget_reg_store = self.widget_reg_store.clone();
let store = self.pl_handler_store.clone();
// notifiy localsignals
rhai_impl::updates::notify_all_localsignals();
glib::MainContext::default().spawn_local(async move {
let vars = store.read().unwrap().clone();
let mut parser_rc = stored_parser_clone.borrow_mut();
let compiled_ast_ref = compiled_ast.as_ref().map(|rc| rc.borrow());
match generate_new_widgetnode(
&vars,
&config_path,
compiled_ast.as_deref(),
compiled_ast_ref.as_deref(),
&mut *parser_rc,
)
.await
@@ -696,27 +729,123 @@ impl<B: DisplayBackend> App<B> {
log::info!("Reloading windows");
log::trace!("loading config: {:#?}", config);
self.ewwii_config = config;
self.reloading = true;
let result = (|| -> Result<()> {
self.ewwii_config.replace_data(config);
let open_window_ids: Vec<String> = self
.open_windows
.keys()
.cloned()
.chain(self.failed_windows.iter().cloned())
.dedup()
.collect();
for instance_id in &open_window_ids {
let window_arguments = self.instance_id_to_args.get(instance_id).with_context(|| {
format!("Cannot reopen window, initial parameters were not saved correctly for {instance_id}")
})?;
self.open_window(&window_arguments.clone())?;
}
Ok(())
})();
self.reloading = false;
result
}
/// Load a given CSS string into the gtk css provider
pub fn load_css(&mut self, _file_id: usize, css: &str) -> Result<()> {
self.css_provider.load_from_data(&css);
let open_window_ids: Vec<String> = self
.open_windows
.keys()
.cloned()
.chain(self.failed_windows.iter().cloned())
.dedup()
.collect();
for instance_id in &open_window_ids {
let window_arguments = self.instance_id_to_args.get(instance_id).with_context(|| {
format!("Cannot reopen window, initial parameters were not saved correctly for {instance_id}")
})?;
self.open_window(&window_arguments.clone())?;
}
Ok(())
}
/// Load a given CSS string into the gtk css provider, returning a nicely formatted [`DiagError`] when GTK errors out
pub fn load_css(&mut self, _file_id: usize, css: &str) -> Result<()> {
self.css_provider.load_from_data(&css);
/// Perform widget control based on the action
pub fn perform_widget_control(
&mut self,
action: crate::opts::WidgetControlAction,
) -> Result<()> {
match action {
crate::opts::WidgetControlAction::Remove { names } => {
if let Ok(mut maybe_registry) = self.widget_reg_store.lock() {
if let Some(widget_registry) = maybe_registry.as_mut() {
for name in names {
widget_registry.remove_widget_by_name(&name);
}
} else {
log::error!("Widget registry is empty");
}
} else {
log::error!("Failed to acquire lock on widget registry");
}
}
crate::opts::WidgetControlAction::Create { rhai_codes, parent_name } => {
let mut parser = self.config_parser.borrow_mut();
for rhai_code in rhai_codes {
let widget_node = parser.eval_code_snippet(&rhai_code)?;
let wid = rhai_impl::ast::hash_props(widget_node.props().ok_or_else(|| {
anyhow::anyhow!("Failed to retreive the properties of this widget.")
})?);
if let Ok(mut maybe_registry) = self.widget_reg_store.lock() {
if let Some(widget_registry) = maybe_registry.as_mut() {
let pid =
widget_registry.get_widget_id_by_name(&parent_name).ok_or_else(
|| anyhow::anyhow!("Widget '{}' not found", parent_name),
)?;
widget_registry.create_widget(&widget_node, wid, pid)?;
} else {
log::error!("Widget registry is empty");
}
} else {
log::error!("Failed to acquire lock on widget registry");
}
}
}
crate::opts::WidgetControlAction::PropertyUpdate {
property_and_value,
widget_name,
} => {
if let Ok(mut maybe_registry) = self.widget_reg_store.lock() {
if let Some(widget_registry) = maybe_registry.as_mut() {
for (key, value) in &property_and_value {
widget_registry.update_property_by_name(
&widget_name,
(key.clone(), value.clone()),
);
}
} else {
log::error!("Widget registry is empty");
}
} else {
log::error!("Failed to acquire lock on widget registry");
}
}
crate::opts::WidgetControlAction::AddClass { class, widget_name } => {
if let Ok(mut maybe_registry) = self.widget_reg_store.lock() {
if let Some(widget_registry) = maybe_registry.as_mut() {
widget_registry.update_class_of_widget_by_name(&widget_name, &class, false);
} else {
log::error!("Widget registry is empty");
}
} else {
log::error!("Failed to acquire lock on widget registry");
}
}
crate::opts::WidgetControlAction::RemoveClass { class, widget_name } => {
if let Ok(mut maybe_registry) = self.widget_reg_store.lock() {
if let Some(widget_registry) = maybe_registry.as_mut() {
widget_registry.update_class_of_widget_by_name(&widget_name, &class, true);
} else {
log::error!("Widget registry is empty");
}
} else {
log::error!("Failed to acquire lock on widget registry");
}
}
}
Ok(())
}
@@ -724,9 +853,10 @@ impl<B: DisplayBackend> App<B> {
/// Trigger a UI update with the given flags.
/// Even if there are no flags, the UI will still be updated.
pub fn trigger_ui_update_with(
&self,
&mut self,
inject_vars: Option<HashMap<String, String>>,
should_preserve_state: bool,
lifetime: Option<String>,
) -> Result<()> {
let compiled_ast = self.ewwii_config.get_owned_compiled_ast();
let config_path = self.paths.get_rhai_path();
@@ -749,6 +879,7 @@ impl<B: DisplayBackend> App<B> {
if let Some(vars) = inject_vars {
for (name, val) in vars {
scope.set_value(name.clone(), Dynamic::from(val.clone()));
let name_clone = name.clone();
// Preserving the new state.
// ---
@@ -756,14 +887,19 @@ impl<B: DisplayBackend> App<B> {
// in the poll/listen variable store (or the `pl_handler_store` in self)
if should_preserve_state {
self.pl_handler_store.write().unwrap().insert(name, val);
if let Some(win_name) = &lifetime {
self.clear_pl_onclose.insert(win_name.clone(), name_clone);
}
}
}
}
let compiled_ast_ref = compiled_ast.as_ref().map(|rc| rc.borrow());
let new_root_widget = reeval_parser.eval_code_with(
&rhai_code,
Some(scope),
compiled_ast.as_deref(),
compiled_ast_ref.as_deref(),
config_path.to_str(),
)?;
@@ -789,9 +925,9 @@ impl<B: DisplayBackend> App<B> {
let mut scope = ParseConfig::initial_poll_listen_scope(&rhai_code)?;
// unwrap Rc<AST>
// unwrap Rc<RefCell<AST>>
let ast_ref: &rhai::AST =
compiled_ast.as_ref().ok_or_else(|| anyhow!("AST not compiled yet"))?.as_ref();
&*compiled_ast.as_ref().ok_or_else(|| anyhow!("AST not compiled yet"))?.borrow();
for fn_call in calls {
reeval_parser.call_rhai_fn(ast_ref, &fn_call, Some(&mut scope))?;
@@ -824,55 +960,70 @@ impl<B: DisplayBackend> App<B> {
unsafe {
// Each plugin exposes: extern "C" fn create_plugin() -> Box<dyn Plugin>
let constructor: libloading::Symbol<
unsafe extern "C" fn() -> Box<dyn ewwii_plugin_api::Plugin>,
> = lib
.get(b"create_plugin")
.map_err(|e| anyhow!("Failed to find create_plugin: {}", e))?;
let constructor: libloading::Symbol<unsafe extern "C" fn() -> Box<dyn epapi::Plugin>> =
lib.get(b"create_plugin")
.map_err(|e| anyhow!("Failed to find create_plugin: {}", e))?;
let plugin = constructor(); // instantiate plugin
let host = crate::plugin::EwwiiImpl { requestor: tx.clone() };
plugin.init(&host); // call init immediately
set_active_plugin(lib)?; // keep library alive
let host = crate::plugin::EwwiiImpl { requestor: tx.clone() };
plugin.init(&host); // call init immediately
}
let cp = self.config_parser.clone();
let wgs = self.widget_reg_store.clone();
glib::MainContext::default().spawn_local(async move {
while let Ok(req) = rx.recv() {
match req {
PluginRequest::RhaiEngineAct(func) => {
let mut cp = cp.borrow_mut();
cp.action_with_engine(func);
}
PluginRequest::ListWidgetIds(res_tx) => {
let wgs_guard = wgs.lock().unwrap();
if let Some(wgs_brw) = wgs_guard.as_ref() {
let output: Vec<u64> = wgs_brw.widgets.keys().cloned().collect();
if let Err(e) = res_tx.send(output) {
log::error!("Failed to send window list to host: {}", e);
}
}
}
PluginRequest::WidgetRegistryAct(func) => {
let mut wgs_guard = wgs.lock().unwrap();
if let Some(ref mut registry) = *wgs_guard {
let repr_map: HashMap<u64, &mut gtk4::Widget> = registry
.widgets
.iter_mut()
.map(|(id, entry)| (*id, &mut entry.widget))
.collect();
func(&mut ewwii_plugin_api::widget_backend::WidgetRegistryRepr {
widgets: repr_map,
});
}
}
let handle_request = move |req: PluginRequest| match req {
PluginRequest::RhaiEngineAct(func) => {
func(&mut cp.borrow_mut().engine);
}
PluginRequest::RegisterFunc((name, namespace, func)) => match namespace {
epapi::rhai_backend::RhaiFnNamespace::Custom(ns) => {
let mut module = rhai::Module::new();
module.set_native_fn(name, func);
cp.borrow_mut().engine.register_static_module(&ns, module.into());
}
epapi::rhai_backend::RhaiFnNamespace::Global => {
cp.borrow_mut().engine.register_fn(name, func);
}
},
PluginRequest::ListWidgetIds(res_tx) => {
let wgs_guard = wgs.lock().unwrap();
if let Some(wgs_brw) = wgs_guard.as_ref() {
let output: Vec<u64> = wgs_brw.widgets.keys().cloned().collect();
let _ = res_tx.send(output);
}
}
PluginRequest::WidgetRegistryAct(func) => {
let mut wgs_guard = wgs.lock().unwrap();
if let Some(ref mut registry) = *wgs_guard {
let repr_map: HashMap<u64, &mut gtk4::Widget> = registry
.widgets
.iter_mut()
.map(|(id, entry)| (*id, &mut entry.widget))
.collect();
func(&mut ewwii_plugin_api::widget_backend::WidgetRegistryRepr {
widgets: repr_map,
});
}
}
};
// quick drain
while let Ok(req) = rx.try_recv() {
handle_request(req);
}
// handling requests that arrive later
glib::MainContext::default().spawn_local(async move {
let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
while let Ok(req) = rx.recv() {
handle_request(req);
}
}));
});
Ok(())
@@ -1027,6 +1178,10 @@ async fn generate_new_widgetnode(
compiled_ast: Option<&rhai::AST>,
parser: &mut ParseConfig,
) -> Result<WidgetNode> {
if !code_path.exists() {
bail!("The configuration file `{}` does not exist", code_path.display());
}
let rhai_code = parser.code_from_file(&code_path)?;
let mut scope = ParseConfig::initial_poll_listen_scope(&rhai_code)?;
@@ -1034,10 +1189,6 @@ async fn generate_new_widgetnode(
scope.set_value(name.clone(), Dynamic::from(val.clone()));
}
if !code_path.exists() {
bail!("The configuration file `{}` does not exist", code_path.display());
}
let new_root_widget =
parser.eval_code_with(&rhai_code, Some(scope), compiled_ast, code_path.to_str())?;

View File

@@ -5,6 +5,7 @@ use crate::{
window::backend_window_options::BackendWindowOptionsDef,
};
use anyhow::{bail, Context, Result};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
@@ -27,7 +28,7 @@ pub fn read_from_ewwii_paths(
pub struct EwwiiConfig {
windows: HashMap<String, WindowDefinition>,
root_node: Option<Rc<WidgetNode>>,
compiled_ast: Option<Rc<AST>>,
compiled_ast: Option<Rc<RefCell<AST>>>,
}
#[derive(Debug, Clone)]
@@ -87,7 +88,7 @@ impl EwwiiConfig {
Ok(EwwiiConfig {
windows: window_definitions,
root_node: Some(Rc::new(config_tree)),
compiled_ast: Some(Rc::new(compiled_ast)),
compiled_ast: Some(Rc::new(RefCell::new(compiled_ast))),
})
}
@@ -109,7 +110,18 @@ impl EwwiiConfig {
self.root_node.clone().ok_or_else(|| anyhow::anyhow!("root_node is missing"))
}
pub fn get_owned_compiled_ast(&self) -> Option<Rc<AST>> {
pub fn get_owned_compiled_ast(&self) -> Option<Rc<RefCell<AST>>> {
self.compiled_ast.clone()
}
pub fn replace_data(&mut self, new_dat: Self) {
if let (Some(old_ast_rc), Some(new_ast_rc)) =
(self.compiled_ast.as_ref(), new_dat.compiled_ast.as_ref())
{
*old_ast_rc.borrow_mut() = new_ast_rc.borrow().clone();
}
self.windows = new_dat.windows;
self.root_node = new_dat.root_node;
}
}

View File

@@ -148,7 +148,7 @@ fn run<B: DisplayBackend>(opts: opts::Opt, ewwii_binary_name: String) -> Result<
let should_restart = match &opts.action {
opts::Action::ShellCompletions { .. } => unreachable!(),
opts::Action::Daemon => opts.restart,
opts::Action::Daemon { .. } => opts.restart,
opts::Action::WithServer(action) => opts.restart && action.can_start_daemon(),
opts::Action::ClientOnly(_) => false,
};
@@ -168,11 +168,11 @@ fn run<B: DisplayBackend>(opts: opts::Opt, ewwii_binary_name: String) -> Result<
}
// make sure that there isn't already a Ewwii daemon running.
opts::Action::Daemon if check_server_running(paths.get_ipc_socket_file()) => {
opts::Action::Daemon { .. } if check_server_running(paths.get_ipc_socket_file()) => {
eprintln!("Ewwii server already running.");
true
}
opts::Action::Daemon => {
opts::Action::Daemon { with_plugin } => {
log::info!("Initializing Ewwii server. ({})", paths.get_ipc_socket_file().display());
let _ = std::fs::remove_file(paths.get_ipc_socket_file());
@@ -182,8 +182,12 @@ fn run<B: DisplayBackend>(opts: opts::Opt, ewwii_binary_name: String) -> Result<
ewwii_binary_name
);
}
let fork_result =
server::initialize_server::<B>(paths.clone(), None, !opts.no_daemonize)?;
let fork_result = server::initialize_server::<B>(
paths.clone(),
None,
!opts.no_daemonize,
with_plugin,
)?;
opts.no_daemonize || fork_result == ForkResult::Parent
}
@@ -223,7 +227,7 @@ fn run<B: DisplayBackend>(opts: opts::Opt, ewwii_binary_name: String) -> Result<
let (command, response_recv) = action.into_daemon_command();
// start the daemon and give it the command
let fork_result =
server::initialize_server::<B>(paths.clone(), Some(command), true)?;
server::initialize_server::<B>(paths.clone(), Some(command), true, None)?;
let is_parent = fork_result == ForkResult::Parent;
if let (Some(recv), true) = (response_recv, is_parent) {
listen_for_daemon_response(recv);

View File

@@ -67,7 +67,10 @@ pub enum Action {
/// Start the Ewwii daemon.
#[command(name = "daemon", alias = "d")]
Daemon,
Daemon {
#[arg(long)]
with_plugin: Option<String>,
},
#[command(flatten)]
ClientOnly(ActionClientOnly),
@@ -184,6 +187,13 @@ pub enum ActionWithServer {
// /// Print out the scope graph structure in graphviz dot format.
// #[command(name = "graph")]
// ShowGraph,
/// Control widgets through CLI.
#[command(name = "widget-control", alias = "wc")]
WidgetControl {
#[command(subcommand)]
action: WidgetControlAction,
},
/// Update the widgets of a particular window. Poll/Listen variables will be cleared
#[command(name = "update", alias = "u")]
TriggerUpdateUI {
@@ -194,9 +204,13 @@ pub enum ActionWithServer {
#[arg(long = "inject", short = 'i', value_parser = parse_inject_var_map)]
inject_vars: Option<HashMap<String, String>>,
/// Preserve the new updates. Only meaningful if used with inject.
/// Preserve the new updates.
#[arg(long = "preserve", short = 'p')]
should_preserve_state: bool,
/// Tie the variable lifetime to a window lifetime.
#[arg(long = "lifetime", short = 'l')]
lifetime: Option<String>,
},
/// Call rhai functions. (NOTE: All poll/listen will default to their initial value)
@@ -227,6 +241,59 @@ pub enum ActionWithServer {
},
}
/// Subcommands for widget control
#[derive(Subcommand, Debug, Serialize, Deserialize, PartialEq)]
pub enum WidgetControlAction {
/// Remove widget by name
Remove {
/// Names of the widgets to remove
names: Vec<String>,
},
/// Create widgets
Create {
/// Rhai code to create widgets from
rhai_codes: Vec<String>,
/// Name of the widget to add these widgets as a child to
#[arg(long = "parent", short = 'p')]
parent_name: String,
},
/// Update properties of a widget by name
PropertyUpdate {
/// Properties and its value
///
/// Format: value="val1" widget_name="val2"
#[arg(value_parser = parse_inject_var_map)]
property_and_value: HashMap<String, String>,
/// Name of the widget to update the property of
#[arg(long = "widget", short = 'w')]
widget_name: String,
},
/// Add a class to a widget with given name
AddClass {
/// The class to add to the widget
class: String,
/// Name of the widget to add class to
#[arg(long = "widget", short = 'w')]
widget_name: String,
},
/// Remove a class to a widget with given name
RemoveClass {
/// The class to remove from the widget
class: String,
/// Name of the widget to remove class from
#[arg(long = "widget", short = 'w')]
widget_name: String,
},
}
impl Opt {
pub fn from_env() -> Self {
let raw: RawOpt = RawOpt::parse();
@@ -286,10 +353,17 @@ impl ActionWithServer {
self,
) -> (app::DaemonCommand, Option<daemon_response::DaemonResponseReceiver>) {
let command = match self {
ActionWithServer::TriggerUpdateUI { inject_vars, should_preserve_state } => {
ActionWithServer::WidgetControl { action } => {
return with_response_channel(|sender| app::DaemonCommand::WidgetControl {
action,
sender,
})
}
ActionWithServer::TriggerUpdateUI { inject_vars, should_preserve_state, lifetime } => {
return with_response_channel(|sender| app::DaemonCommand::TriggerUpdateUI {
inject_vars,
should_preserve_state,
lifetime,
sender,
})
}

View File

@@ -1,5 +1,5 @@
use ewwii_plugin_api::{widget_backend, EwwiiAPI};
use rhai::Engine;
use ewwii_plugin_api::{rhai_backend, widget_backend, EwwiiAPI};
use rhai::{Array, Dynamic, Engine, EvalAltResult};
use std::sync::mpsc::{channel as mpsc_channel, Receiver, Sender};
pub(crate) struct EwwiiImpl {
@@ -33,6 +33,20 @@ impl EwwiiAPI for EwwiiImpl {
Ok(())
}
fn register_function(
&self,
name: String,
namespace: rhai_backend::RhaiFnNamespace,
f: Box<dyn Fn(Array) -> Result<Dynamic, Box<EvalAltResult>> + Send + Sync>,
) -> Result<(), String> {
let func_info = (name, namespace, f);
self.requestor
.send(PluginRequest::RegisterFunc(func_info))
.map_err(|_| "Failed to send request to host".to_string())?;
Ok(())
}
// Widget Rendering & Logic
fn list_widget_ids(&self) -> Result<Vec<u64>, String> {
let (tx, rx): (Sender<Vec<u64>>, Receiver<Vec<u64>>) = mpsc_channel();
@@ -60,6 +74,13 @@ impl EwwiiAPI for EwwiiImpl {
pub(crate) enum PluginRequest {
RhaiEngineAct(Box<dyn FnOnce(&mut Engine) + Send>),
RegisterFunc(
(
String,
rhai_backend::RhaiFnNamespace,
Box<dyn Fn(Array) -> Result<Dynamic, Box<EvalAltResult>> + Send + Sync>,
),
),
ListWidgetIds(Sender<Vec<u64>>),
WidgetRegistryAct(Box<dyn FnOnce(&mut widget_backend::WidgetRegistryRepr) + Send>),
}

View File

@@ -22,6 +22,7 @@ pub fn initialize_server<B: DisplayBackend>(
paths: EwwiiPaths,
action: Option<DaemonCommand>,
should_daemonize: bool,
ewwii_plugin_path: Option<String>,
) -> Result<ForkResult> {
let (ui_send, mut ui_recv) = tokio::sync::mpsc::unbounded_channel();
@@ -36,23 +37,6 @@ pub fn initialize_server<B: DisplayBackend>(
let config_parser =
Rc::new(RefCell::new(rhai_impl::parser::ParseConfig::new(Some(pl_handler_store.clone()))));
let mut config_parser_mut = config_parser.borrow_mut();
let read_config = config::read_from_ewwii_paths(&paths, &mut *config_parser_mut);
// free the temporary parser borrow
drop(config_parser_mut);
let ewwii_config = match read_config {
Ok(config) => config,
Err(err) => {
error_handling_ctx::print_error(err);
config::EwwiiConfig::default()
// TODO: Maybe do something so that we can exit if user wants.
// std::process::exit(1);
}
};
cleanup_log_dir(paths.get_log_dir())?;
@@ -92,15 +76,17 @@ pub fn initialize_server<B: DisplayBackend>(
let main_loop = gtk4::glib::MainLoop::new(None, false);
let mut app: App<B> = app::App {
ewwii_config,
ewwii_config: config::EwwiiConfig::default(),
open_windows: HashMap::new(),
failed_windows: HashSet::new(),
instance_id_to_args: HashMap::new(),
css_provider: gtk4::CssProvider::new(),
reloading: false,
app_evt_send: ui_send.clone(),
window_close_timer_abort_senders: HashMap::new(),
widget_reg_store: std::rc::Rc::new(std::sync::Mutex::new(None)),
pl_handler_store,
clear_pl_onclose: HashMap::new(),
rt_engine_config: EngineConfValues::default(),
config_parser,
paths,
@@ -108,12 +94,33 @@ pub fn initialize_server<B: DisplayBackend>(
phantom: PhantomData,
};
// start up plugins
if let Some(ewwii_plugin) = ewwii_plugin_path {
if let Err(e) = app.set_ewwii_plugin(ewwii_plugin) {
error_handling_ctx::print_error(e);
}
}
let mut config_parser_mut = app.config_parser.borrow_mut();
let read_config = config::read_from_ewwii_paths(&app.paths, &mut *config_parser_mut);
// free the temporary parser borrow
drop(config_parser_mut);
match read_config {
Ok(new_config) => {
app.ewwii_config = new_config;
}
Err(err) => {
error_handling_ctx::print_error(err);
// TODO: Maybe do something so that we can exit if user wants.
// std::process::exit(1);
}
};
if let Some(display) = gtk4::gdk::Display::default() {
gtk4::style_context_add_provider_for_display(
&display,
&app.css_provider,
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
gtk4::style_context_add_provider_for_display(&display, &app.css_provider, 900);
}
if let Ok((file_id, css)) = config::scss::parse_scss_from_config(app.paths.get_config_dir()) {

View File

@@ -41,21 +41,30 @@ fn build_gtk_widget_from_node(
let gtk_widget = match root_node {
WidgetNode::Box { props, children } => build_gtk_box(props, children, widget_reg)?.upcast(),
WidgetNode::FlowBox { props, children } => {
build_gtk_flowbox(props, children, widget_reg)?.upcast()
}
WidgetNode::EventBox { props, children } => {
build_event_box(props, children, widget_reg)?.upcast()
}
WidgetNode::ToolTip { props, children } => {
build_tooltip(props, children, widget_reg)?.upcast()
}
// WidgetNode::CircularProgress { props } => {
// build_circular_progress_bar(props, widget_reg)?.upcast()
// }
WidgetNode::LocalBind { props, children } => {
build_localbind_util(props, children, widget_reg)?.upcast()
}
WidgetNode::WidgetAction { props, children } => {
build_widgetaction_util(props, children, widget_reg)?.upcast()
}
WidgetNode::CircularProgress { props } => {
build_circular_progress_bar(props, widget_reg)?.upcast()
}
WidgetNode::GtkUI { props } => build_gtk_ui_file(props)?.upcast(),
// WidgetNode::Graph { props } => build_graph(props, widget_reg)?.upcast(),
// WidgetNode::Transform { props } => build_transform(props, widget_reg)?.upcast(),
WidgetNode::Slider { props } => build_gtk_scale(props, widget_reg)?.upcast(),
WidgetNode::Scale { props } => build_gtk_scale(props, widget_reg)?.upcast(),
WidgetNode::Progress { props } => build_gtk_progress(props, widget_reg)?.upcast(),
WidgetNode::Image { props } => build_image(props, widget_reg)?.upcast(),
WidgetNode::Icon { props } => build_icon(props, widget_reg)?.upcast(),
WidgetNode::Button { props } => build_gtk_button(props, widget_reg)?.upcast(),
WidgetNode::Label { props } => build_gtk_label(props, widget_reg)?.upcast(),
// WIDGET_NAME_LITERAL => build_gtk_literal(node)?.upcast(),

View File

@@ -1,273 +1,199 @@
// use anyhow::{anyhow, Result};
// use gtk4::glib::{self, object_subclass, prelude::*, wrapper, Properties};
// use gtk4::{cairo, gdk, prelude::*, subclass::prelude::*};
// use std::cell::RefCell;
use glib::Object;
use gtk4::glib;
use gtk4::prelude::*;
use gtk4::subclass::prelude::*;
use gtk4::{cairo, gdk, graphene};
use std::cell::Cell;
// use crate::error_handling_ctx;
mod imp {
use super::*;
// wrapper! {
// pub struct CircProg(ObjectSubclass<CircProgPriv>)
// @extends gtk4::Bin, gtk4::Container, gtk4::Widget;
// }
pub struct CircProg {
pub value: Cell<f64>,
pub start_at: Cell<f64>,
pub thickness: Cell<f64>,
pub clockwise: Cell<bool>,
pub fg_color: Cell<gdk::RGBA>,
pub bg_color: Cell<gdk::RGBA>,
}
// #[derive(Properties)]
// #[properties(wrapper_type = CircProg)]
// pub struct CircProgPriv {
// #[property(
// get,
// set,
// nick = "Starting at",
// blurb = "Starting at",
// minimum = 0f64,
// maximum = 100f64,
// default = 0f64
// )]
// start_at: RefCell<f64>,
impl Default for CircProg {
fn default() -> Self {
Self {
value: Cell::new(0.0),
start_at: Cell::new(0.0),
thickness: Cell::new(8.0),
clockwise: Cell::new(true),
fg_color: Cell::new(gdk::RGBA::new(1.0, 0.0, 0.0, 1.0)),
bg_color: Cell::new(gdk::RGBA::new(0.0, 0.0, 0.0, 0.1)),
}
}
}
// #[property(
// get,
// set,
// nick = "Value",
// blurb = "The value",
// minimum = 0f64,
// maximum = 100f64,
// default = 0f64
// )]
// value: RefCell<f64>,
#[glib::object_subclass]
impl ObjectSubclass for CircProg {
const NAME: &'static str = "CircProg";
type Type = super::CircProg;
type ParentType = gtk4::Widget;
}
// #[property(
// get,
// set,
// nick = "Thickness",
// blurb = "Thickness",
// minimum = 0f64,
// maximum = 100f64,
// default = 1f64
// )]
// thickness: RefCell<f64>,
impl ObjectImpl for CircProg {
fn constructed(&self) {
self.parent_constructed();
// #[property(get, set, nick = "Clockwise", blurb = "Clockwise", default = true)]
// clockwise: RefCell<bool>,
let obj = self.obj();
obj.add_css_class("circular-progress");
}
// content: RefCell<Option<gtk4::Widget>>,
// }
fn properties() -> &'static [glib::ParamSpec] {
use once_cell::sync::Lazy;
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
vec![
glib::ParamSpecDouble::builder("value")
.minimum(0.0)
.maximum(100.0)
.default_value(0.0)
.build(),
glib::ParamSpecDouble::builder("start-at")
.minimum(0.0)
.maximum(100.0)
.default_value(0.0)
.build(),
glib::ParamSpecDouble::builder("thickness")
.minimum(1.0)
.maximum(50.0)
.default_value(8.0)
.build(),
glib::ParamSpecBoolean::builder("clockwise").default_value(true).build(),
glib::ParamSpecBoxed::builder::<gdk::RGBA>("fg-color").build(),
glib::ParamSpecBoxed::builder::<gdk::RGBA>("bg-color").build(),
]
});
PROPERTIES.as_ref()
}
// // This should match the default values from the ParamSpecs
// impl Default for CircProgPriv {
// fn default() -> Self {
// CircProgPriv {
// start_at: RefCell::new(0.0),
// value: RefCell::new(0.0),
// thickness: RefCell::new(1.0),
// clockwise: RefCell::new(true),
// content: RefCell::new(None),
// }
// }
// }
fn set_property(&self, _: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"value" => self.value.set(value.get().unwrap()),
"start-at" => self.start_at.set(value.get().unwrap()),
"thickness" => self.thickness.set(value.get().unwrap()),
"clockwise" => self.clockwise.set(value.get().unwrap()),
"fg-color" => self.fg_color.set(value.get().unwrap()),
"bg-color" => self.bg_color.set(value.get().unwrap()),
x => panic!("Tried to set inexistant property of CircProg: {}", x,),
}
self.obj().queue_draw();
}
// impl ObjectImpl for CircProgPriv {
// fn properties() -> &'static [glib::ParamSpec] {
// Self::derived_properties()
// }
fn property(&self, _: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"value" => self.value.get().to_value(),
"start-at" => self.start_at.get().to_value(),
"thickness" => self.thickness.get().to_value(),
"clockwise" => self.clockwise.get().to_value(),
"fg-color" => self.fg_color.get().to_value(),
"bg-color" => self.bg_color.get().to_value(),
x => panic!("Tried to get inexistant property of CircProg: {}", x,),
}
}
}
// fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
// match pspec.name() {
// "value" => {
// self.value.replace(value.get().unwrap());
// self.obj().queue_draw(); // Queue a draw call with the updated value
// }
// "thickness" => {
// self.thickness.replace(value.get().unwrap());
// }
// "start-at" => {
// self.start_at.replace(value.get().unwrap());
// }
// "clockwise" => {
// self.clockwise.replace(value.get().unwrap());
// }
// x => panic!("Tried to set inexistant property of CircProg: {}", x,),
// }
// }
impl WidgetImpl for CircProg {
fn measure(&self, _orientation: gtk4::Orientation, _for_size: i32) -> (i32, i32, i32, i32) {
let min_size = 32;
let natural_size = 64;
(min_size, natural_size, -1, -1)
}
// fn property(&self, id: usize, pspec: &glib::ParamSpec) -> glib::Value {
// self.derived_property(id, pspec)
// }
// }
fn snapshot(&self, snapshot: &gtk4::Snapshot) {
let value = self.value.get();
let start_at = self.start_at.get();
let thickness = self.thickness.get();
let clockwise = self.clockwise.get();
let fg_color = self.fg_color.get();
let bg_color = self.bg_color.get();
// #[object_subclass]
// impl ObjectSubclass for CircProgPriv {
// type ParentType = gtk4::Bin;
// type Type = CircProg;
let margin_start = self.obj().margin_start() as f64;
let margin_end = self.obj().margin_end() as f64;
let margin_top = self.obj().margin_top() as f64;
let margin_bottom = self.obj().margin_bottom() as f64;
// Padding is not supported yet
// const NAME: &'static str = "CircProg";
let (start_angle, end_angle) = if clockwise {
(0.0, perc_to_rad(value))
} else {
(perc_to_rad(100.0 - value), 2f64 * std::f64::consts::PI)
};
// fn class_init(klass: &mut Self::Class) {
// klass.set_css_name("circular-progress");
// }
// }
let total_width = self.obj().allocated_width() as f64;
let total_height = self.obj().allocated_height() as f64;
let center = (total_width / 2.0, total_height / 2.0);
// impl Default for CircProg {
// fn default() -> Self {
// Self::new()
// }
// }
let circle_width = total_width - margin_start - margin_end;
let circle_height = total_height - margin_top - margin_bottom;
let outer_ring = f64::min(circle_width, circle_height) / 2.0;
let inner_ring = (f64::min(circle_width, circle_height) / 2.0) - thickness;
// impl CircProg {
// pub fn new() -> Self {
// glib::Object::new::<Self>()
// }
// }
// Snapshot Cairo node
let cr = snapshot.append_cairo(&graphene::Rect::new(
0.0_f32,
0.0_f32,
total_width as f32,
total_height as f32,
));
// impl ContainerImpl for CircProgPriv {
// fn add(&self, widget: &gtk4::Widget) {
// if let Some(content) = &*self.content.borrow() {
// // TODO: Handle this error when populating children widgets instead
// error_handling_ctx::print_error(anyhow!(
// "Error, trying to add multiple children to a circular-progress widget"
// ));
// self.parent_remove(content);
// }
// self.parent_add(widget);
// self.content.replace(Some(widget.clone()));
// }
// }
cr.save().unwrap();
// fn calc_widget_lowest_preferred_dimension(widget: &gtk4::Widget) -> (i32, i32) {
// let preferred_width = widget.preferred_width();
// let preferred_height = widget.preferred_height();
// let min_lowest = i32::min(preferred_width.0, preferred_height.0);
// let natural_lowest = i32::min(preferred_width.1, preferred_height.1);
// (min_lowest, natural_lowest)
// }
// Centering
cr.translate(center.0, center.1);
cr.rotate(perc_to_rad(start_at));
cr.translate(-center.0, -center.1);
// impl BinImpl for CircProgPriv {}
// Background Ring
cr.move_to(center.0, center.1);
cr.arc(center.0, center.1, outer_ring, 0.0, perc_to_rad(100.0));
cr.set_source_rgba(
bg_color.red().into(),
bg_color.green().into(),
bg_color.blue().into(),
bg_color.alpha().into(),
);
cr.move_to(center.0, center.1);
cr.arc(center.0, center.1, inner_ring, 0.0, perc_to_rad(100.0));
cr.set_fill_rule(cairo::FillRule::EvenOdd); // Substract one circle from the other
cr.fill().unwrap();
// impl WidgetImpl for CircProgPriv {
// // We overwrite preferred_* so that overflowing content from the children gets cropped
// // We return min(child_width, child_height)
// fn preferred_width(&self) -> (i32, i32) {
// let styles = self.obj().style_context();
// let margin = styles.margin(gtk4::StateFlags::NORMAL);
// Foreground Ring
cr.move_to(center.0, center.1);
cr.arc(center.0, center.1, outer_ring, start_angle, end_angle);
cr.set_source_rgba(
fg_color.red().into(),
fg_color.green().into(),
fg_color.blue().into(),
fg_color.alpha().into(),
);
cr.move_to(center.0, center.1);
cr.arc(center.0, center.1, inner_ring, start_angle, end_angle);
cr.set_fill_rule(cairo::FillRule::EvenOdd); // Substract one circle from the other
cr.fill().unwrap();
// if let Some(child) = &*self.content.borrow() {
// let (min_child, natural_child) = calc_widget_lowest_preferred_dimension(child);
// (
// min_child + margin.right as i32 + margin.left as i32,
// natural_child + margin.right as i32 + margin.left as i32,
// )
// } else {
// let empty_width =
// (2 * *self.thickness.borrow() as i32) + margin.right as i32 + margin.left as i32;
// (empty_width, empty_width)
// }
// }
cr.restore().unwrap();
}
}
}
// fn preferred_width_for_height(&self, _height: i32) -> (i32, i32) {
// self.preferred_width()
// }
glib::wrapper! {
pub struct CircProg(ObjectSubclass<imp::CircProg>)
@extends gtk4::Widget,
@implements gtk4::Accessible, gtk4::Actionable, gtk4::Buildable, gtk4::ConstraintTarget;
}
// fn preferred_height(&self) -> (i32, i32) {
// let styles = self.obj().style_context();
// let margin = styles.margin(gtk4::StateFlags::NORMAL);
impl CircProg {
pub fn new() -> Self {
Object::builder().build()
}
}
// if let Some(child) = &*self.content.borrow() {
// let (min_child, natural_child) = calc_widget_lowest_preferred_dimension(child);
// (
// min_child + margin.bottom as i32 + margin.top as i32,
// natural_child + margin.bottom as i32 + margin.top as i32,
// )
// } else {
// let empty_height =
// (2 * *self.thickness.borrow() as i32) + margin.right as i32 + margin.left as i32;
// (empty_height, empty_height)
// }
// }
// fn preferred_height_for_width(&self, _width: i32) -> (i32, i32) {
// self.preferred_height()
// }
// fn draw(&self, cr: &cairo::Context) -> glib::Propagation {
// let res: Result<()> = (|| {
// let value = *self.value.borrow();
// let start_at = *self.start_at.borrow();
// let thickness = *self.thickness.borrow();
// let clockwise = *self.clockwise.borrow();
// let styles = self.obj().style_context();
// let margin = styles.margin(gtk4::StateFlags::NORMAL);
// // Padding is not supported yet
// let fg_color: gdk::RGBA = styles.color(gtk4::StateFlags::NORMAL);
// let bg_color: gdk::RGBA = styles
// .style_property_for_state("background-color", gtk4::StateFlags::NORMAL)
// .get()?;
// let (start_angle, end_angle) = if clockwise {
// (0.0, perc_to_rad(value))
// } else {
// (perc_to_rad(100.0 - value), 2f64 * std::f64::consts::PI)
// };
// let total_width = self.obj().allocated_width() as f64;
// let total_height = self.obj().allocated_height() as f64;
// let center = (total_width / 2.0, total_height / 2.0);
// let circle_width = total_width - margin.left as f64 - margin.right as f64;
// let circle_height = total_height - margin.top as f64 - margin.bottom as f64;
// let outer_ring = f64::min(circle_width, circle_height) / 2.0;
// let inner_ring = (f64::min(circle_width, circle_height) / 2.0) - thickness;
// cr.save()?;
// // Centering
// cr.translate(center.0, center.1);
// cr.rotate(perc_to_rad(start_at));
// cr.translate(-center.0, -center.1);
// // Background Ring
// cr.move_to(center.0, center.1);
// cr.arc(center.0, center.1, outer_ring, 0.0, perc_to_rad(100.0));
// cr.set_source_rgba(bg_color.red(), bg_color.green(), bg_color.blue(), bg_color.alpha());
// cr.move_to(center.0, center.1);
// cr.arc(center.0, center.1, inner_ring, 0.0, perc_to_rad(100.0));
// cr.set_fill_rule(cairo::FillRule::EvenOdd); // Substract one circle from the other
// cr.fill()?;
// // Foreground Ring
// cr.move_to(center.0, center.1);
// cr.arc(center.0, center.1, outer_ring, start_angle, end_angle);
// cr.set_source_rgba(fg_color.red(), fg_color.green(), fg_color.blue(), fg_color.alpha());
// cr.move_to(center.0, center.1);
// cr.arc(center.0, center.1, inner_ring, start_angle, end_angle);
// cr.set_fill_rule(cairo::FillRule::EvenOdd); // Substract one circle from the other
// cr.fill()?;
// cr.restore()?;
// // Draw the children widget, clipping it to the inside
// if let Some(child) = &*self.content.borrow() {
// cr.save()?;
// // Center circular clip
// cr.arc(center.0, center.1, inner_ring + 1.0, 0.0, perc_to_rad(100.0));
// cr.set_source_rgba(bg_color.red(), 0.0, 0.0, bg_color.alpha());
// cr.clip();
// // Children widget
// self.obj().propagate_draw(child, cr);
// cr.reset_clip();
// cr.restore()?;
// }
// Ok(())
// })();
// if let Err(error) = res {
// error_handling_ctx::print_error(error)
// };
// glib::Propagation::Proceed
// }
// }
// fn perc_to_rad(n: f64) -> f64 {
// (n / 100f64) * 2f64 * std::f64::consts::PI
// }
fn perc_to_rad(n: f64) -> f64 {
(n / 100f64) * 2f64 * std::f64::consts::PI
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,10 @@
use anyhow::{anyhow, Result};
use gtk4::glib;
use gtk4::glib::gobject_ffi;
use gtk4::glib::translate::{FromGlibPtrNone, IntoGlib};
use gtk4::glib::Value;
use gtk4::pango;
use gtk4::prelude::{Cast, ObjectExt, RangeExt, StaticType, ToValue};
use rhai::Map;
use std::process::Command;
@@ -159,6 +164,17 @@ pub(super) fn parse_position_type(s: &str) -> Result<gtk4::PositionType> {
}
}
/// Gtk flow box
pub(super) fn parse_selection_model(s: &str) -> Result<gtk4::SelectionMode> {
match s.to_ascii_lowercase().as_str() {
"none" => Ok(gtk4::SelectionMode::None),
"single" => Ok(gtk4::SelectionMode::Single),
"browse" => Ok(gtk4::SelectionMode::Browse),
"multiple" => Ok(gtk4::SelectionMode::Multiple),
_ => Err(anyhow!("Invalid position type: '{}'", s)),
}
}
/// Helper of helpers
fn replace_placeholders<T>(cmd: &str, args: &[T]) -> String
where
@@ -215,3 +231,105 @@ pub(super) fn parse_stack_transition(t: &str) -> Result<gtk4::StackTransitionTyp
_ => Err(anyhow!("Invalid stack transition: '{}'", t)),
}
}
// For localbind
pub(super) fn set_property_from_string_anywhere(
widget: &gtk4::Widget,
prop_name: &str,
value_str: &str,
) {
fn convert(pspec: &glib::ParamSpec, value_str: &str) -> Option<Value> {
let value_type = pspec.value_type();
if value_type == f64::static_type() {
value_str.parse::<f64>().ok().map(|v| v.to_value())
} else if value_type == i32::static_type() {
value_str.parse::<i32>().ok().map(|v| v.to_value())
} else if value_type == bool::static_type() {
value_str.parse::<bool>().ok().map(|v| v.to_value())
} else if value_type == String::static_type() {
Some(value_str.to_value())
} else {
None
}
}
let obj: &glib::Object = widget.upcast_ref();
if let Some(pspec) = obj.find_property(prop_name) {
if let Some(gv) = convert(&pspec, value_str) {
obj.set_property(prop_name, &gv);
}
return;
}
unsafe {
for iface_type in obj.type_().interfaces() {
for pspec in list_interface_properties(iface_type) {
if pspec.name() == prop_name {
if let Some(v) = convert(&pspec, value_str) {
obj.set_property(prop_name, &v);
}
return;
}
}
}
}
if let Some(range) = widget.downcast_ref::<gtk4::Range>() {
let range_obj: &glib::Object = range.upcast_ref();
if let Some(pspec) = range_obj.find_property(prop_name) {
if let Some(gv) = convert(&pspec, value_str) {
range_obj.set_property(prop_name, &gv);
}
return;
}
let adj = range.adjustment();
let adj_obj: &glib::Object = adj.upcast_ref();
if let Some(pspec) = adj_obj.find_property(prop_name) {
if let Some(gv) = convert(&pspec, value_str) {
adj_obj.set_property(prop_name, &gv);
}
return;
}
}
log::error!("Property '{}' not found on widget {}", prop_name, obj.type_().name());
}
unsafe fn list_interface_properties(iface_type: glib::Type) -> Vec<glib::ParamSpec> {
let mut n_props = 0;
let iface_ptr = gobject_ffi::g_type_default_interface_ref(iface_type.into_glib());
if iface_ptr.is_null() {
return vec![];
}
let props_ptr =
gobject_ffi::g_object_interface_list_properties(iface_ptr as *mut _, &mut n_props);
let props = (0..n_props)
.map(|i| {
let p = *props_ptr.add(i as usize);
glib::ParamSpec::from_glib_none(p)
})
.collect::<Vec<_>>();
gobject_ffi::g_type_default_interface_unref(iface_ptr);
props
}
/// Picture widget
pub(super) fn parse_content_fit(cf: &str) -> Result<gtk4::ContentFit> {
match cf.to_ascii_lowercase().as_str() {
"fill" => Ok(gtk4::ContentFit::Fill),
"contain" => Ok(gtk4::ContentFit::Contain),
"cover" => Ok(gtk4::ContentFit::Cover),
"scaledown" => Ok(gtk4::ContentFit::ScaleDown),
_ => Err(anyhow!("Invalid content fit: '{}'", cf)),
}
}

View File

@@ -1,6 +1,6 @@
[package]
name = "ewwii_plugin_api"
version = "0.4.0"
version = "0.7.0"
authors = ["byson94 <byson94wastaken@gmail.com>"]
edition = "2021"
license = "GPL-3.0-or-later"
@@ -18,5 +18,6 @@ include-gtk4 = ["dep:gtk4"]
include-rhai = ["dep:rhai"]
[dependencies]
rhai = { workspace = true, optional = true }
# rhai crate features should exactly match that of rhai_impl
rhai = { workspace = true, optional = true, features = ["internals"] }
gtk4 = { workspace = true, optional = true }

View File

@@ -9,58 +9,32 @@
/// The following example shows how you can use this macro to
/// easily make plugins in a single step.
///
/// ```rust
/// ```rust,ignore
/// use ewwii_plugin_api::auto_plugin;
///
/// auto_plugin!(MyPluginName, {
/// // host variable is passed in automatically
/// host.log("Easy, huh?");
/// })
///
/// });
/// ```
///
/// That's it! The plugin is ready.
///
/// ## When not to use it
///
/// This macro shall not be used if you want to have
/// fields in your plugin.
///
/// ```rust
/// struct MyPluginName {
/// awesome_field: String
/// }
/// ```
///
/// For a structure like the above, you should do this instead:
///
/// ```rust
/// use ewwii_plugin_api::{EwwiiAPI, Plugin, export_plugin};
///
/// pub struct DummyStructure;
///
/// impl Plugin for DummyStructure {
/// // critical for ewwii to launch the plugin
/// fn init(&self, host: &dyn EwwiiAPI) {
/// // will be printed by the host
/// host.log("Plugin says Hello!");
/// }
/// }
///
/// // Critical for ewwii to load the plugin
/// export_plugin!(DummyStructure);
/// ```
/// This macro shall not be used if you prefer flexibility and safety.
/// The manual approach is verbose, but is way safer and flexible than using this macro.
#[macro_export]
macro_rules! auto_plugin {
($struct_name:ident, $init_block:block) => {
pub struct $struct_name;
// Implement the Plugin trait
impl crate::Plugin for $struct_name {
fn init(&self, host: &dyn crate::EwwiiAPI) {
impl $crate::Plugin for $struct_name {
fn init(&self, host: &dyn $crate::EwwiiAPI) {
$init_block
}
}
export_plugin!($struct_name);
$crate::export_plugin!($struct_name);
};
}

View File

@@ -1,7 +1,9 @@
//! # ewwii_plugin_api - A plugin interface for ewwii
//!
//! `ewwii_plguin_api` is a shared list of traits
//! that both ewwii and its plugins can use.
//! This is a **must-have** for building plugins for ewwii
//! as this explicit layout is what ewwii requires a plugin to have.
//! This crate simplifies and provides a safe way for building
//! plugins for ewwii.
//!
//! ## Example
//!
@@ -27,10 +29,14 @@
mod export_macros;
pub mod example;
pub mod rhai_backend;
pub mod widget_backend;
#[cfg(feature = "include-rhai")]
use rhai::Engine;
pub use rhai;
#[cfg(feature = "include-gtk4")]
pub use gtk4;
/// The shared trait defining the Ewwii plugin API
pub trait EwwiiAPI: Send + Sync {
@@ -48,15 +54,76 @@ pub trait EwwiiAPI: Send + Sync {
/// _(include-rhai)_ Perform actions on the latest rhai engine.
///
/// # Example
///
///
/// ```rust
/// host.rhai_engine_action(Box::new(|eng| {
/// // eng = rhai::Engine
/// eng.set_max_expr_depths(128, 128);
/// }));
/// use ewwii_plugin_api::{EwwiiAPI, Plugin};
///
/// pub struct DummyStructure;
///
/// impl Plugin for DummyStructure {
/// fn init(&self, host: &dyn EwwiiAPI) {
/// host.rhai_engine_action(Box::new(|eng| {
/// // eng = rhai::Engine
/// eng.set_max_expr_depths(128, 128);
/// }));
/// }
/// }
/// ```
#[cfg(feature = "include-rhai")]
fn rhai_engine_action(&self, f: Box<dyn FnOnce(&mut Engine) + Send>) -> Result<(), String>;
fn rhai_engine_action(
&self,
f: Box<dyn FnOnce(&mut rhai::Engine) + Send>,
) -> Result<(), String>;
/// _(include-rhai)_ Expose a function that rhai configuration can call.
///
/// **NOTE:***
///
/// Due to TypeID mismatches, methods like `register_type`, `register_fn`,
/// etc. won't work on the engine and may cause a crash. It is recommended
/// to use the `register_function` API to register a funtion which `api::slib`
/// can call to in rhai.
///
/// # Example
///
/// ```rust
/// use ewwii_plugin_api::{EwwiiAPI, Plugin, rhai_backend::RhaiFnNamespace};
/// use rhai::Dynamic;
///
/// pub struct DummyStructure;
///
/// impl Plugin for DummyStructure {
/// fn init(&self, host: &dyn EwwiiAPI) {
/// host.register_function(
/// "my_func".to_string(),
/// RhaiFnNamespace::Global,
/// Box::new(|args| {
/// // Do stuff
/// // - Perform things on the args (if needed)
/// // - And return a value
///
/// Ok(Dynamic::default()) // return empty
/// }));
/// }
/// }
/// ```
///
/// This example will register a function with signature "my_func(Array)" in rhai.
///
/// ## Example use in rhai
///
/// ```js
/// print(my_func(["param1", "param2"]));
/// ```
#[cfg(feature = "include-rhai")]
fn register_function(
&self,
name: String,
namespace: rhai_backend::RhaiFnNamespace,
f: Box<
dyn Fn(rhai::Array) -> Result<rhai::Dynamic, Box<rhai::EvalAltResult>> + Send + Sync,
>,
) -> Result<(), String>;
// == Widget Rendering & Logic == //
/// Get the list of all widget id's
@@ -65,12 +132,20 @@ pub trait EwwiiAPI: Send + Sync {
/// _(include-gtk4)_ Perform actions on the latest widget registry.
///
/// # Example
///
///
/// ```rust
/// host.widget_reg_action(Box::new(|wrg| {
/// // wrg = widget_backend::WidgetRegistryRepr
/// // The gtk4::Widget can be modified here.
/// }));
/// use ewwii_plugin_api::{EwwiiAPI, Plugin};
///
/// pub struct DummyStructure;
///
/// impl Plugin for DummyStructure {
/// fn init(&self, host: &dyn EwwiiAPI) {
/// host.widget_reg_action(Box::new(|wrg| {
/// // wrg = widget_backend::WidgetRegistryRepr
/// // The gtk4::Widget can be modified here.
/// }));
/// }
/// }
/// ```
#[cfg(feature = "include-gtk4")]
fn widget_reg_action(
@@ -86,12 +161,14 @@ pub trait EwwiiAPI: Send + Sync {
/// ## Example
///
/// ```rust
/// use ewwii_plugin_api::{Plugin, export_plugin};
/// use ewwii_plugin_api::{Plugin, EwwiiAPI, export_plugin};
///
/// struct MyStruct;
///
/// sturct MyStruct;
///
/// impl Plugin for MyStruct {
/// /* Implementation Skipped */
/// fn init(&self, host: &dyn EwwiiAPI) {
/// /* Implementation Skipped */
/// }
/// }
///
/// // Automatically does all the FFI related exports

View File

@@ -0,0 +1,14 @@
//! Module exposing extra utilities for rhai.
#[cfg(feature = "include-rhai")]
mod rhai_included {
/// _(include-rhai)_ An enumrate providing options for
/// function registaration namespaces.
pub enum RhaiFnNamespace {
Custom(String),
Global,
}
}
#[cfg(feature = "include-rhai")]
pub use rhai_included::*;

View File

@@ -18,4 +18,4 @@ mod gtk4_included {
}
#[cfg(feature = "include-gtk4")]
pub use gtk4_included::*;
pub use gtk4_included::*;

View File

@@ -10,6 +10,7 @@ homepage = "https://github.com/byson94/ewwii"
[dependencies]
shared_utils.workspace = true
scan_prop_proc.workspace = true
rhai = { workspace = true, features = ["internals"] }
anyhow.workspace = true
@@ -21,6 +22,7 @@ ahash.workspace = true
nix = { workspace = true, features = ["process", "fs", "signal"] }
libc.workspace = true
# error handling
rhai_trace = "0.3.0"
rhai_trace = "0.3.1"
codespan-reporting.workspace = true
regex.workspace = true
regex.workspace = true
gtk4.workspace = true

View File

@@ -1,20 +1,22 @@
use ahash::AHasher;
use anyhow::Result;
use rhai::Map;
use scan_prop_proc::scan_prop;
use std::collections::HashMap;
use std::hash::{Hash, Hasher};
#[derive(Debug, Clone)]
#[scan_prop]
pub enum WidgetNode {
Label { props: Map },
Box { props: Map, children: Vec<WidgetNode> },
FlowBox { props: Map, children: Vec<WidgetNode> },
Button { props: Map },
Image { props: Map },
Icon { props: Map },
Input { props: Map },
Progress { props: Map },
ComboBoxText { props: Map },
Slider { props: Map },
Scale { props: Map },
Checkbox { props: Map },
Expander { props: Map, children: Vec<WidgetNode> },
Revealer { props: Map, children: Vec<WidgetNode> },
@@ -30,6 +32,11 @@ pub enum WidgetNode {
EventBox { props: Map, children: Vec<WidgetNode> },
ToolTip { props: Map, children: Vec<WidgetNode> },
// Special
LocalBind { props: Map, children: Vec<WidgetNode> },
WidgetAction { props: Map, children: Vec<WidgetNode> },
GtkUI { props: Map },
// Top-level macros
DefWindow { name: String, props: Map, node: Box<WidgetNode> },
// Poll { var: String, interval: String, cmd: String, initial: String },
@@ -72,6 +79,13 @@ pub fn get_id_to_widget_info<'a>(
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::FlowBox { props, children } => {
let id = hash_props_and_type(props, "FlowBox");
insert_wdgt_info(node, props, "FlowBox", children.as_slice(), parent_id, id_to_props)?;
for child in children {
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::EventBox { props, children } => {
let id = hash_props_and_type(props, "EventBox");
insert_wdgt_info(node, props, "EventBox", children.as_slice(), parent_id, id_to_props)?;
@@ -91,9 +105,9 @@ pub fn get_id_to_widget_info<'a>(
// let id = hash_props_and_type(props, "Transform");
insert_wdgt_info(node, props, "Transform", &[], parent_id, id_to_props)?;
}
WidgetNode::Slider { props } => {
// let id = hash_props_and_type(props, "Slider");
insert_wdgt_info(node, props, "Slider", &[], parent_id, id_to_props)?;
WidgetNode::Scale { props } => {
// let id = hash_props_and_type(props, "Scale");
insert_wdgt_info(node, props, "Scale", &[], parent_id, id_to_props)?;
}
WidgetNode::Progress { props } => {
// let id = hash_props_and_type(props, "Progress");
@@ -103,10 +117,6 @@ pub fn get_id_to_widget_info<'a>(
// let id = hash_props_and_type(props, "Image");
insert_wdgt_info(node, props, "Image", &[], parent_id, id_to_props)?;
}
WidgetNode::Icon { props } => {
// let id = hash_props_and_type(props, "Icon");
insert_wdgt_info(node, props, "Icon", &[], parent_id, id_to_props)?;
}
WidgetNode::Button { props } => {
// let id = hash_props_and_type(props, "Button");
insert_wdgt_info(node, props, "Button", &[], parent_id, id_to_props)?;
@@ -141,6 +151,37 @@ pub fn get_id_to_widget_info<'a>(
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::LocalBind { props, children } => {
let id = hash_props_and_type(props, "LocalBind");
insert_wdgt_info(
node,
props,
"LocalBind",
children.as_slice(),
parent_id,
id_to_props,
)?;
for child in children {
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::WidgetAction { props, children } => {
let id = hash_props_and_type(props, "WidgetAction");
insert_wdgt_info(
node,
props,
"WidgetAction",
children.as_slice(),
parent_id,
id_to_props,
)?;
for child in children {
get_id_to_widget_info(child, id_to_props, Some(id))?;
}
}
WidgetNode::GtkUI { props } => {
insert_wdgt_info(node, props, "GtkUI", &[], parent_id, id_to_props)?;
}
WidgetNode::ColorChooser { props } => {
// let id = hash_props_and_type(props, "ColorChooser");
insert_wdgt_info(node, props, "ColorChooser", &[], parent_id, id_to_props)?;
@@ -217,6 +258,14 @@ pub fn hash_props_and_type(props: &Map, widget_type_str: &str) -> u64 {
hasher.finish()
}
pub fn hash_props(props: &Map) -> u64 {
let mut hasher = AHasher::default();
props.hash(&mut hasher);
hasher.finish()
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -1,7 +1,9 @@
use crate::ast::WidgetNode;
use crate::ast::{hash_props, WidgetNode};
use crate::updates::{register_signal, LocalDataBinder, LocalSignal};
use rhai::{Array, Engine, EvalAltResult, Map, NativeCallContext};
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;
/// Converts a Dynamic array into a Vec<WidgetNode>, returning proper errors with position.
fn children_to_vec(
@@ -22,8 +24,13 @@ fn children_to_vec(
.collect()
}
pub fn register_all_widgets(engine: &mut Engine, all_nodes: &Rc<RefCell<Vec<WidgetNode>>>) {
pub fn register_all_widgets(
engine: &mut Engine,
all_nodes: &Rc<RefCell<Vec<WidgetNode>>>,
keep_signal: &Rc<RefCell<Vec<u64>>>,
) {
engine.register_type::<WidgetNode>();
engine.register_type::<LocalSignal>();
// == Primitive widgets ==
macro_rules! register_primitive {
@@ -37,11 +44,10 @@ pub fn register_all_widgets(engine: &mut Engine, all_nodes: &Rc<RefCell<Vec<Widg
register_primitive!("label", Label);
register_primitive!("button", Button);
register_primitive!("image", Image);
register_primitive!("icon", Icon);
register_primitive!("input", Input);
register_primitive!("progress", Progress);
register_primitive!("combo_box_text", ComboBoxText);
register_primitive!("scale", Slider);
register_primitive!("scale", Scale);
register_primitive!("checkbox", Checkbox);
register_primitive!("calendar", Calendar);
register_primitive!("graph", Graph);
@@ -67,6 +73,7 @@ pub fn register_all_widgets(engine: &mut Engine, all_nodes: &Rc<RefCell<Vec<Widg
}
register_with_children!("box", Box);
register_with_children!("flowbox", FlowBox);
register_with_children!("expander", Expander);
register_with_children!("revealer", Revealer);
register_with_children!("scroll", Scroll);
@@ -74,6 +81,35 @@ pub fn register_all_widgets(engine: &mut Engine, all_nodes: &Rc<RefCell<Vec<Widg
register_with_children!("stack", Stack);
register_with_children!("eventbox", EventBox);
register_with_children!("tooltip", ToolTip);
register_with_children!("localbind", LocalBind);
register_with_children!("widget_action", WidgetAction);
// == Special widget
engine.register_fn(
"gtk_ui",
|path: &str, load: &str| -> Result<WidgetNode, Box<EvalAltResult>> {
let mut props = Map::new();
props.insert("file".into(), path.into());
props.insert("id".into(), load.into());
Ok(WidgetNode::GtkUI { props })
},
);
// == Special signal
let keep_signal_clone = keep_signal.clone();
engine.register_fn(
"localsignal",
move |props: Map| -> Result<LocalSignal, Box<EvalAltResult>> {
let id = hash_props(&props);
let signal = Rc::new(LocalSignal { id, props, data: Arc::new(LocalDataBinder::new()) });
let signal_rc = register_signal(id, signal);
keep_signal_clone.borrow_mut().push(id);
Ok((*signal_rc).clone())
},
);
// == Top-level macros ==
engine.register_fn(

View File

@@ -39,6 +39,10 @@ impl WidgetNode {
props: with_dyn_id(props.clone(), parent_path),
children: process_children(children, parent_path, "box"),
},
WidgetNode::FlowBox { props, children } => WidgetNode::FlowBox {
props: with_dyn_id(props.clone(), parent_path),
children: process_children(children, parent_path, "flowbox"),
},
WidgetNode::Expander { props, children } => WidgetNode::Expander {
props: with_dyn_id(props.clone(), parent_path),
children: process_children(children, parent_path, "expander"),
@@ -67,6 +71,14 @@ impl WidgetNode {
props: with_dyn_id(props.clone(), parent_path),
children: process_children(children, parent_path, "tooltip"),
},
WidgetNode::LocalBind { props, children } => WidgetNode::LocalBind {
props: with_dyn_id(props.clone(), parent_path),
children: process_children(children, parent_path, "localbind"),
},
WidgetNode::WidgetAction { props, children } => WidgetNode::WidgetAction {
props: with_dyn_id(props.clone(), parent_path),
children: process_children(children, parent_path, "widget_action"),
},
// == Top-level container for multiple widgets ==
WidgetNode::Enter(children) => {
@@ -87,30 +99,29 @@ impl WidgetNode {
node @ WidgetNode::Label { props }
| node @ WidgetNode::Button { props }
| node @ WidgetNode::Image { props }
| node @ WidgetNode::Icon { props }
| node @ WidgetNode::Input { props }
| node @ WidgetNode::Progress { props }
| node @ WidgetNode::ComboBoxText { props }
| node @ WidgetNode::Slider { props }
| node @ WidgetNode::Scale { props }
| node @ WidgetNode::Checkbox { props }
| node @ WidgetNode::Calendar { props }
| node @ WidgetNode::ColorButton { props }
| node @ WidgetNode::ColorChooser { props }
| node @ WidgetNode::CircularProgress { props }
| node @ WidgetNode::Graph { props }
| node @ WidgetNode::GtkUI { props }
| node @ WidgetNode::Transform { props } => {
let new_props = with_dyn_id(props.clone(), parent_path);
match node {
WidgetNode::Label { .. } => WidgetNode::Label { props: new_props },
WidgetNode::Button { .. } => WidgetNode::Button { props: new_props },
WidgetNode::Image { .. } => WidgetNode::Image { props: new_props },
WidgetNode::Icon { .. } => WidgetNode::Icon { props: new_props },
WidgetNode::Input { .. } => WidgetNode::Input { props: new_props },
WidgetNode::Progress { .. } => WidgetNode::Progress { props: new_props },
WidgetNode::ComboBoxText { .. } => {
WidgetNode::ComboBoxText { props: new_props }
}
WidgetNode::Slider { .. } => WidgetNode::Slider { props: new_props },
WidgetNode::Scale { .. } => WidgetNode::Scale { props: new_props },
WidgetNode::Checkbox { .. } => WidgetNode::Checkbox { props: new_props },
WidgetNode::Calendar { .. } => WidgetNode::Calendar { props: new_props },
WidgetNode::ColorButton { .. } => WidgetNode::ColorButton { props: new_props },
@@ -121,6 +132,7 @@ impl WidgetNode {
WidgetNode::CircularProgress { props: new_props }
}
WidgetNode::Graph { .. } => WidgetNode::Graph { props: new_props },
WidgetNode::GtkUI { .. } => WidgetNode::GtkUI { props: new_props },
WidgetNode::Transform { .. } => WidgetNode::Transform { props: new_props },
_ => unreachable!(),
}

View File

@@ -11,9 +11,15 @@ pub fn format_eval_error(
engine: &Engine,
file_id: Option<&str>,
) -> String {
let error_str = error.to_string();
if error_str == "" || error_str == "module_eval_failed" || error_str == "module_parse_failed" {
return String::new();
}
let better_error =
BetterError::improve_eval_error(error, code, engine, None).unwrap_or(BetterError {
message: error.to_string(),
message: error_str,
help: None,
hint: None,
note: None,
@@ -24,8 +30,14 @@ pub fn format_eval_error(
/// Return a formatted Rhai parse error.
pub fn format_parse_error(error: &ParseError, code: &str, file_id: Option<&str>) -> String {
let error_str = error.to_string();
if error_str == "" || error_str == "module_eval_failed" || error_str == "module_parse_failed" {
return String::new();
}
let better_error = BetterError::improve_parse_error(error, code).unwrap_or(BetterError {
message: error.to_string(),
message: error_str,
help: None,
hint: None,
note: None,
@@ -52,12 +64,15 @@ pub fn format_codespan_error(be: BetterError, code: &str, file_id: Option<&str>)
}
// build the diagnostic error
let diagnostic = Diagnostic::error()
.with_message(&be.message)
.with_labels(vec![
Label::primary(file_id, be.span.start()..be.span.end()).with_message(&be.message)
])
.with_notes(notes);
let mut labels = Vec::new();
if be.span.start() != be.span.end() {
labels.push(
Label::primary(file_id, be.span.start()..be.span.end()).with_message(&be.message),
);
}
let diagnostic =
Diagnostic::error().with_message(&be.message).with_labels(labels).with_notes(notes);
let mut buffer = Buffer::ansi();
let config = term::Config::default();

View File

@@ -1,13 +1,44 @@
use crate::error::format_eval_error;
use anyhow::Result;
use rhai::Engine;
use std::{
collections::HashSet,
fs,
path::{Path, PathBuf},
};
pub fn extract_poll_and_listen_vars(code: &str) -> Result<Vec<(String, Option<String>)>> {
extract_poll_and_listen_vars_inner(code, &mut HashSet::new())
}
fn extract_poll_and_listen_vars_inner(
code: &str,
visited: &mut HashSet<PathBuf>,
) -> Result<Vec<(String, Option<String>)>> {
let mut results = Vec::new();
let mut engine = Engine::new();
register_temp_poll_listen(&mut engine);
// Handle imports manually
for import_path in extract_import_paths(code)? {
let resolved = resolve_import_path(&import_path)?;
// Prevent infinite recursion
let canonical = fs::canonicalize(&resolved).unwrap_or(resolved.clone());
if visited.contains(&canonical) {
continue;
}
visited.insert(canonical.clone());
if resolved.exists() {
let imported_code = fs::read_to_string(&resolved)?;
let inner = extract_poll_and_listen_vars_inner(&imported_code, visited)?;
results.extend(inner);
}
}
// Process this files own poll/listen calls
for expr in extract_poll_listen_exprs(code) {
match engine.eval_expression::<TempSignal>(&expr) {
Ok(sig) => {
@@ -23,6 +54,38 @@ pub fn extract_poll_and_listen_vars(code: &str) -> Result<Vec<(String, Option<St
Ok(results)
}
/// Extract import paths from the Rhai source code
fn extract_import_paths(code: &str) -> Result<Vec<String>> {
let mut imports = Vec::new();
for line in code.lines() {
let trimmed = line.trim_start();
if trimmed.starts_with("import ") {
if let Some(start) = trimmed.find('"') {
if let Some(end_rel) = trimmed[start + 1..].find('"') {
let end = start + 1 + end_rel;
let path = &trimmed[start + 1..end];
imports.push(path.to_string());
}
}
}
}
Ok(imports)
}
/// Resolve relative and absolute import paths.
fn resolve_import_path(import_path: &str) -> Result<PathBuf> {
let path = Path::new(import_path);
let abs =
if path.is_absolute() { path.to_path_buf() } else { std::env::current_dir()?.join(path) };
let abs = if abs.extension().is_none() { abs.with_extension("rhai") } else { abs };
Ok(abs)
}
pub fn extract_poll_listen_exprs(code: &str) -> Vec<String> {
let mut exprs = Vec::new();
let mut i = 0;
@@ -35,7 +98,7 @@ pub fn extract_poll_listen_exprs(code: &str) -> Vec<String> {
while i < len && code_bytes[i] as char != '\n' {
i += 1;
}
i += 1; // skipp a full line
i += 1; // skip a full line
continue;
}

View File

@@ -1,4 +1,4 @@
//! IIRhai is a simple crate which configures rhai for the `ewwii` widget system.
//! rhai_impl is a simple crate which configures rhai for the `ewwii` widget system.
//!
//! This crate supports parsing, error handling, and has a custom module_resolver.

View File

@@ -1,6 +1,7 @@
use crate::error::{format_eval_error, format_parse_error};
use crate::parser::ParseConfig;
use crate::updates::ReactiveVarStore;
use rhai::Scope;
use rhai::{Dynamic, Engine, EvalAltResult, Module, ModuleResolver, Position, AST};
use std::collections::HashMap;
use std::fs;
@@ -55,16 +56,31 @@ impl ModuleResolver for SimpleFileResolver {
))
})?;
let mut scope = ParseConfig::initial_poll_listen_scope(&script).map_err(|e| {
EvalAltResult::ErrorSystem(
format!("error setting up default variables: {full_path:?}"),
e.into(),
)
})?;
let parent_script: Option<String> = if let Some(parent_path) = source_path {
match fs::read_to_string(parent_path) {
Ok(s) => Some(s),
Err(err) => {
log::error!("Could not read parent script {parent_path:?}: {err}");
None
}
}
} else {
None
};
let mut scope = if let Some(ref script) = parent_script {
ParseConfig::initial_poll_listen_scope(script).map_err(|e| {
EvalAltResult::ErrorSystem(
format!("error setting up default variables from {source_path:?}"),
e.into(),
)
})?
} else {
Scope::new()
};
match &self.pl_handler_store {
Some(val) => {
println!("VALBEF: {:#?}", val);
let name_to_val: &HashMap<String, String> = &*val.read().unwrap();
for (name, val) in name_to_val {

View File

@@ -8,36 +8,42 @@ use crate::{
updates::ReactiveVarStore,
};
use anyhow::{anyhow, Result};
use rhai::{Dynamic, Engine, OptimizationLevel, Scope, AST};
use rhai::{Dynamic, Engine, ImmutableString, OptimizationLevel, Scope, AST};
use std::cell::RefCell;
use std::fs;
use std::path::Path;
use std::rc::Rc;
pub struct ParseConfig {
engine: Engine,
pub engine: Engine,
all_nodes: Rc<RefCell<Vec<WidgetNode>>>,
keep_signal: Rc<RefCell<Vec<u64>>>,
}
impl ParseConfig {
pub fn new(pl_handler_store: Option<ReactiveVarStore>) -> Self {
let mut engine = Engine::new();
let all_nodes = Rc::new(RefCell::new(Vec::new()));
let keep_signal = Rc::new(RefCell::new(Vec::new()));
engine.set_max_expr_depths(128, 128);
engine
.set_module_resolver(SimpleFileResolver { pl_handler_store: pl_handler_store.clone() });
register_all_widgets(&mut engine, &all_nodes);
register_all_widgets(&mut engine, &all_nodes, &keep_signal);
register_all_providers(&mut engine, pl_handler_store);
Self { engine, all_nodes }
Self { engine, all_nodes, keep_signal }
}
pub fn compile_code(&mut self, code: &str, file_path: &str) -> Result<AST> {
self.engine
let mut ast = self
.engine
.compile(code)
.map_err(|e| anyhow!(format_parse_error(&e, code, Some(file_path))))
.map_err(|e| anyhow!(format_parse_error(&e, code, Some(file_path))))?;
ast.set_source(ImmutableString::from(file_path));
Ok(ast)
}
pub fn eval_code_with(
@@ -65,6 +71,9 @@ impl ParseConfig {
.map_err(|e| anyhow!(format_eval_error(&e, code, &self.engine, file_id)))?;
};
// Retain signals
crate::updates::retain_signals(&self.keep_signal.borrow());
// Merge all nodes in all_nodes (`enter([])`) into a single root node
let merged_node = {
let mut all_nodes_vec = self.all_nodes.borrow_mut();
@@ -86,6 +95,24 @@ impl ParseConfig {
Ok(merged_node.setup_dyn_ids("root"))
}
pub fn eval_code_snippet(&mut self, code: &str) -> Result<WidgetNode> {
let mut scope = Scope::new();
// Just eval as node will be in `all_nodes`
let node = self
.engine
.eval_with_scope::<WidgetNode>(&mut scope, code)
.map_err(|e| anyhow!(format_eval_error(&e, code, &self.engine, Some("<dyn eval>"))))?;
// Retain signals
crate::updates::retain_signals(&self.keep_signal.borrow());
// Clear all nodes
self.all_nodes.borrow_mut().clear();
Ok(node)
}
pub fn code_from_file<P: AsRef<Path>>(&mut self, file_path: P) -> Result<String> {
Ok(fs::read_to_string(&file_path)
.map_err(|e| anyhow!("Failed to read {:?}: {}", file_path.as_ref(), e))?)

View File

@@ -30,6 +30,7 @@ use tokio::sync::watch;
pub fn handle_listen(
var_name: String,
props: &Map,
shell: String,
store: ReactiveVarStore,
tx: tokio::sync::mpsc::UnboundedSender<String>,
) {
@@ -76,7 +77,7 @@ pub fn handle_listen(
tokio::spawn(async move {
let mut child = unsafe {
Command::new("/bin/sh")
Command::new(&shell)
.arg("-c")
.arg(&cmd)
// .kill_on_drop(true)

View File

@@ -0,0 +1,249 @@
use super::{get_prefered_shell, handle_listen, handle_poll};
use crate::parser::ParseConfig;
use gtk4::glib;
use gtk4::prelude::*;
use gtk4::subclass::prelude::*;
use once_cell::sync::Lazy;
use rhai::Map;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::{Arc, RwLock};
mod imp {
use super::*;
#[derive(Default)]
pub struct LocalDataBinder {
pub value: RefCell<String>,
}
#[glib::object_subclass]
impl ObjectSubclass for LocalDataBinder {
const NAME: &'static str = "LocalDataBinder";
type Type = super::LocalDataBinder;
type ParentType = glib::Object;
}
impl ObjectImpl for LocalDataBinder {
fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: once_cell::sync::Lazy<Vec<glib::ParamSpec>> =
once_cell::sync::Lazy::new(|| {
vec![glib::ParamSpecString::builder("value")
.nick("Value")
.blurb("The bound value")
.default_value(None)
.build()]
});
PROPERTIES.as_ref()
}
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
match pspec.name() {
"value" => self.value.borrow().to_value(),
_ => unimplemented!(),
}
}
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
match pspec.name() {
"value" => {
let val: Option<String> = value.get().unwrap();
self.set_value(&self.obj(), val.unwrap_or_default());
}
_ => unimplemented!(),
}
}
}
impl LocalDataBinder {
pub fn set_value(&self, obj: &super::LocalDataBinder, val: String) {
*self.value.borrow_mut() = val;
obj.notify("value");
}
}
}
glib::wrapper! {
pub struct LocalDataBinder(ObjectSubclass<imp::LocalDataBinder>);
}
impl LocalDataBinder {
pub fn new() -> Self {
glib::Object::new::<Self>()
}
pub fn value(&self) -> String {
self.imp().value.borrow().clone()
}
pub fn set_value(&self, val: &str) {
self.set_property("value", val);
}
}
#[derive(Debug, Clone)]
pub struct LocalSignal {
pub id: u64,
pub props: Map,
pub data: Arc<LocalDataBinder>,
}
thread_local! {
pub static LOCAL_SIGNALS: Lazy<RefCell<HashMap<u64, Rc<LocalSignal>>>> =
Lazy::new(|| RefCell::new(HashMap::new()));
}
pub fn register_signal(id: u64, signal: Rc<LocalSignal>) -> Rc<LocalSignal> {
LOCAL_SIGNALS.with(|registry| {
let mut map = registry.borrow_mut();
map.entry(id).or_insert_with(|| signal.clone()).clone()
})
}
pub fn retain_signals(ids: &Vec<u64>) {
LOCAL_SIGNALS.with(|registry| {
let mut map = registry.borrow_mut();
map.retain(|id, _| ids.contains(id));
});
}
pub fn notify_all_localsignals() {
LOCAL_SIGNALS.with(|registry| {
let registry_ref = registry.borrow();
for (_, signal) in registry_ref.iter() {
signal.data.notify("value");
}
});
}
pub fn handle_localsignal_changes(
parser: Rc<RefCell<ParseConfig>>,
ast: Option<Rc<RefCell<rhai::AST>>>,
) {
let shell = get_prefered_shell();
let get_string_fn = shared_utils::extract_props::get_string_prop;
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<String>();
let store = Arc::new(RwLock::new(HashMap::new()));
LOCAL_SIGNALS.with(|registry| {
let registry_ref = registry.borrow();
for (id, signal) in registry_ref.iter() {
let props = &signal.props;
if let Ok(initial_str) = get_string_fn(&props, "initial", None) {
signal.data.set_value(&initial_str);
}
match get_string_fn(&props, "type", None) {
Ok(signal_type) => match signal_type.to_ascii_lowercase().as_str() {
"poll" => handle_poll(
id.to_string(),
&props,
shell.clone(),
store.clone(),
tx.clone(),
),
"listen" => handle_listen(
id.to_string(),
&props,
shell.clone(),
store.clone(),
tx.clone(),
),
o => log::error!("Invalid type: '{}'", o),
},
Err(_) => {
log::error!(
"Unable to handle localsignal {}: 'type' property missing or invalid.",
id
);
}
}
}
});
glib::MainContext::default().spawn_local(async move {
while let Some(id_str) = rx.recv().await {
let value_opt = {
let guard = store.read().unwrap();
guard.get(&id_str).cloned()
};
if let Some(value) = value_opt {
if let Ok(id) = id_str.parse::<u64>() {
LOCAL_SIGNALS.with(|registry| {
let mut registry_ref = registry.borrow_mut();
if let Some(signal) = registry_ref.get_mut(&id) {
let original = value.to_string();
let mut current = original.clone();
let mutations: Vec<rhai::FnPtr> = match signal.props.get("mutations") {
Some(v) => {
if let Ok(arr) = v.as_array_ref() {
arr.iter()
.filter_map(|item| {
item.clone().try_cast::<rhai::FnPtr>().or_else(|| {
log::warn!("Non-function found in signal.props.mutations");
None
})
})
.collect()
} else {
log::warn!("Localsignal mutations property is not an array");
Vec::new()
}
}
None => Vec::new(),
};
if mutations.is_empty() {
signal.data.set_value(&current);
return;
}
let parser_rc = parser.borrow_mut();
let compiled_ast = match ast.as_ref() {
Some(rc) => rc.borrow(),
None => {
log::warn!("No compiled AST available");
signal.data.set_value(&current);
return;
}
};
for mutation in mutations {
match mutation.call::<String>(&parser_rc.engine, &compiled_ast, (current.clone(),)) {
Ok(v) => {
current = v;
}
Err(e) => {
log::warn!(
"Signal {} mutation failed ({}), reverting to original value",
id,
e
);
current = original.clone();
break;
}
}
}
signal.data.set_value(&current);
} else {
log::warn!("No LocalSignal found for id {}", id);
}
});
} else {
log::error!("Invalid id_str '{}': cannot parse to u64", id_str);
}
} else {
log::warn!("No value found in store for id '{}'", id_str);
}
}
});
}

View File

@@ -15,12 +15,16 @@
*/
mod listen;
mod localsignal;
mod poll;
pub use localsignal::*;
use crate::ast::WidgetNode;
use listen::handle_listen;
use once_cell::sync::Lazy;
use poll::handle_poll;
use std::process::Command;
use std::sync::Mutex;
use std::{collections::HashMap, sync::Arc, sync::RwLock};
use tokio::sync::mpsc::UnboundedSender;
@@ -30,19 +34,30 @@ pub type ReactiveVarStore = Arc<RwLock<HashMap<String, String>>>;
pub static SHUTDOWN_REGISTRY: Lazy<Mutex<Vec<watch::Sender<bool>>>> =
Lazy::new(|| Mutex::new(Vec::new()));
pub fn get_prefered_shell() -> String {
// Check Dash and prefer if dash is installed.
let dash_installed: bool =
Command::new("which").arg("dash").output().map(|o| o.status.success()).unwrap_or(false);
let shell = if dash_installed { String::from("/bin/dash") } else { String::from("/bin/sh") };
shell
}
pub fn handle_state_changes(
root_node: &WidgetNode,
tx: UnboundedSender<String>,
store: ReactiveVarStore,
) {
let shell = get_prefered_shell();
if let WidgetNode::Enter(children) = root_node {
for child in children {
match child {
WidgetNode::Poll { var, props } => {
handle_poll(var.to_string(), props, store.clone(), tx.clone());
handle_poll(var.to_string(), props, shell.clone(), store.clone(), tx.clone());
}
WidgetNode::Listen { var, props } => {
handle_listen(var.to_string(), props, store.clone(), tx.clone());
handle_listen(var.to_string(), props, shell.clone(), store.clone(), tx.clone());
}
_ => {}
}

View File

@@ -26,6 +26,7 @@ use tokio::time::sleep;
pub fn handle_poll(
var_name: String,
props: &Map,
shell: String,
store: ReactiveVarStore,
tx: tokio::sync::mpsc::UnboundedSender<String>,
) {
@@ -57,7 +58,7 @@ pub fn handle_poll(
tokio::spawn(async move {
// Spawn a persistent shell
let mut child = match Command::new("/bin/sh")
let mut child = match Command::new(&shell)
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.spawn()

View File

@@ -10,5 +10,6 @@ homepage = "https://github.com/ewwii-sh/ewwii"
[dependencies]
serde.workspace = true
rhai.workspace = true
anyhow.workspace = true
rhai = { workspace = true, features = ["internals"] }
anyhow.workspace = true
once_cell.workspace = true

View File

@@ -0,0 +1,20 @@
enter([
defwindow(
"activate linux",
#{
monitor: 0,
focusable: "none",
stacking: "overlay",
wm_ignore: false,
geometry: #{
x: "50px",
y: "20px",
width: "50px",
height: "30px",
anchor: "bottom right",
},
reserve: #{ distance: "40px", side: "top" },
},
label(#{ markup: "<big>Activate linux</big>\nGo to Settings to activate Linux", justify: "left",class: "activate"})
),
]);

View File

@@ -0,0 +1,9 @@
* {
all: unset;
}
.activate {
background: transparent;
color: gray;
}

View File

@@ -66,7 +66,7 @@ fn metric(props) {
space_evenly: false,
}, [
box(#{ class: "label" }, [ label(#{ text: label_prop }) ]),
slider(#{
scale(#{
min: 0,
max: 101,
active: onchange_prop != "",

12
flake.lock generated
View File

@@ -18,11 +18,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1725534445,
"narHash": "sha256-Yd0FK9SkWy+ZPuNqUgmVPXokxDgMJoGuNpMEtkfcf84=",
"lastModified": 1768569498,
"narHash": "sha256-bB6Nt99Cj8Nu5nIUq0GLmpiErIT5KFshMQJGMZwgqUo=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "9bb1e7571aadf31ddb4af77fc64b2d59580f9a39",
"rev": "be5afa0fcb31f0a96bf9ecba05a516c66fcd8114",
"type": "github"
},
"original": {
@@ -46,11 +46,11 @@
]
},
"locked": {
"lastModified": 1725675754,
"narHash": "sha256-hXW3csqePOcF2e/PYnpXj72KEYyNj2HzTrVNmS/F7Ug=",
"lastModified": 1768704795,
"narHash": "sha256-Y33TAp2BHEcuspYvcmBXXD0qdvjftv73PwyKTDOjoSY=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "8cc45e678e914a16c8e224c3237fb07cf21e5e54",
"rev": "4b7472a78857ac789fb26616040f55cfcbd36c6e",
"type": "github"
},
"original": {

View File

@@ -56,13 +56,12 @@
nativeBuildInputs = with pkgs; [
pkg-config
wrapGAppsHook
wrapGAppsHook4
];
buildInputs = with pkgs; [
gtk3
gtk4
librsvg
gtk-layer-shell
libdbusmenu-gtk3
gtk4-layer-shell
];
};

View File

@@ -0,0 +1,17 @@
[package]
name = "scan_prop_proc"
version = "0.1.0"
authors = ["byson94 <byson94wastaken@gmail.com>"]
edition = "2021"
license = "GPL-3.0-or-later"
description = "A procedual macro for generating properties on a WidgetNode"
repository = "https://github.com/byson94/ewwii"
homepage = "https://github.com/byson94/ewwii"
[lib]
proc-macro = true
[dependencies]
syn.workspace = true
quote.workspace = true
proc-macro2.workspace = true

View File

@@ -0,0 +1,47 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Fields};
#[proc_macro_attribute]
pub fn scan_prop(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as DeriveInput);
let name = &input.ident;
let props_matches = if let Data::Enum(data_enum) = &input.data {
data_enum
.variants
.iter()
.filter_map(|v| match &v.fields {
Fields::Named(fields) => {
for f in &fields.named {
if f.ident.as_ref().map(|id| id == "props").unwrap_or(false) {
let vname = &v.ident;
return Some(quote! {
#name::#vname { props, .. } => Some(props)
});
}
}
None
}
_ => None,
})
.collect::<Vec<_>>()
} else {
vec![]
};
let expanded = quote! {
#input
impl #name {
pub fn props(&self) -> Option<&Map> {
match self {
#(#props_matches),*,
_ => None
}
}
}
};
TokenStream::from(expanded)
}

View File

@@ -5,5 +5,5 @@ edition = "2024"
[dependencies]
rhai_impl.workspace = true
rhai = "1.22.2"
rhai.workspace = true
rhai-autodocs = "0.9.0"