This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch edje-vector-intergration
in repository efl.
View the commit online.
commit 789dd56553ca4715a756ea482f33696ad5127c50
Author: [email protected] <[email protected]>
AuthorDate: Thu Apr 30 20:02:48 2026 -0600
examples/edje: add vector_states worked example (Phase 8.3)
Closes the user-facing demonstration gap by providing a complete worked
example of the Edje vector state-animation feature (spec §11). This is the
first public example tree that ties together all Phase 1–8.2 components:
named vector trees, color classes, per-node shape overrides, and STATE_SET
transitions with smooth interpolation.
The example consists of:
- vector_states.edc (75 lines): A logo glyph that morphs from a square to
a star on mouse hover, with fill color class binding to demonstrate
runtime theming and crossfade via interpolation.
- edje-vector-states.c (176 lines): Minimal harness that loads the theme,
displays the "ui/logo" group, and prints signal receipts to stdout so
the example is verifiable from terminal output (important for CI where
live interaction is unavailable).
- meson.build: Added vector_states.edc to edc_files and edje-vector-states
to edje_examples, maintaining alphabetical ordering.
Verification:
- edje_cc on vector_states.edc: zero warnings, .edj produced.
- gcc -Wall -Wextra on edje-vector-states.c: zero warnings.
- ninja -C build: clean.
- edje_suite: 91/91 tests pass, no regressions.
Note on EDC grammar vs. spec:
The example uses the flat dotted form (stroke.color_class:, stroke.width:,
vector.shape with target:) instead of the nested block form shown in spec
§11. This matches EFL's EDC parser, which shipped in Phase 2 and has
always used the flat form. Both deviations (fill/stroke block vs. dotted
properties, and vector.shape block with target:) were already documented
as grammar differences during Phase 2. Flagged for spec rev 3.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---
src/examples/edje/edje-vector-states.c | 176 +++++++++++++++++++++++++++++++++
src/examples/edje/meson.build | 2 +
src/examples/edje/vector_states.edc | 75 ++++++++++++++
3 files changed, 253 insertions(+)
diff --git a/src/examples/edje/edje-vector-states.c b/src/examples/edje/edje-vector-states.c
new file mode 100644
index 0000000000..b65f24eb2d
--- /dev/null
+++ b/src/examples/edje/edje-vector-states.c
@@ -0,0 +1,176 @@
+/**
+ * Edje vector state animation example harness (spec §11)
+ *
+ * Loads vector_states.edj, displays the "ui/logo" group in a window.
+ * Mouse-in / mouse-out over the vector object triggers the hover transition
+ * (square → star path morph, fill crossfade, stroke width change).
+ * A status line is printed to stdout on each transition so the example
+ * is verifiable from terminal output.
+ *
+ * Build:
+ * ninja -C build src/examples/edje/edje-vector-states
+ *
+ * Run (in-tree):
+ * LD_LIBRARY_PATH=build/src/lib \
+ * ./build/src/examples/edje/edje-vector-states
+ *
+ * @verbatim
+ * edje_cc vector_states.edc && \
+ * gcc -o edje-vector-states edje-vector-states.c \
+ * `pkg-config --libs --cflags evas ecore ecore-evas edje`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define PACKAGE_EXAMPLES_DIR "."
+#define EINA_UNUSED
+#endif
+
+#ifndef PACKAGE_DATA_DIR
+#define PACKAGE_DATA_DIR "."
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Edje.h>
+#include <stdio.h>
+
+#define WIDTH (400)
+#define HEIGHT (400)
+
+static const char commands[] =
+ "commands:\n"
+ "\tMove mouse over the shape to trigger hover transition\n"
+ "\tEsc — exit\n"
+ "\th — print this help\n";
+
+static void
+_on_delete(Ecore_Evas *ee EINA_UNUSED)
+{
+ ecore_main_loop_quit();
+}
+
+static void
+_on_keydown(void *data,
+ Evas *evas EINA_UNUSED,
+ Evas_Object *o EINA_UNUSED,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)einfo;
+ Evas_Object *edje_obj = (Evas_Object *)data;
+
+ (void)edje_obj;
+
+ if (!strcmp(ev->key, "h"))
+ printf("%s", commands);
+ else if (!strcmp(ev->key, "Escape"))
+ ecore_main_loop_quit();
+ else
+ {
+ printf("unhandled key: %s\n", ev->key);
+ printf("%s", commands);
+ }
+}
+
+/* Signal callbacks from the theme — printed so the example is terminal-verifiable */
+static void
+_on_hover_in(void *data EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
+ const char *emission,
+ const char *source)
+{
+ printf("signal received: emission=\"%s\" source=\"%s\" "
+ "→ transitioning to hover state\n", emission, source);
+}
+
+static void
+_on_hover_out(void *data EINA_UNUSED,
+ Evas_Object *obj EINA_UNUSED,
+ const char *emission,
+ const char *source)
+{
+ printf("signal received: emission=\"%s\" source=\"%s\" "
+ "→ transitioning to default state\n", emission, source);
+}
+
+int
+main(int argc EINA_UNUSED, char *argv[] EINA_UNUSED)
+{
+ const char *edje_file = PACKAGE_DATA_DIR"/vector_states.edj";
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *bg;
+ Evas_Object *edje_obj;
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ if (!edje_init())
+ goto shutdown_ecore_evas;
+
+ ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL);
+ if (!ee) goto shutdown_edje;
+
+ ecore_evas_callback_delete_request_set(ee, _on_delete);
+ ecore_evas_title_set(ee, "Edje Vector State Animation Example");
+
+ evas = ecore_evas_get(ee);
+
+ bg = evas_object_rectangle_add(evas);
+ evas_object_color_set(bg, 240, 240, 240, 255); /* light-grey bg */
+ evas_object_move(bg, 0, 0);
+ evas_object_resize(bg, WIDTH, HEIGHT);
+ evas_object_show(bg);
+ evas_object_focus_set(bg, EINA_TRUE);
+
+ edje_obj = edje_object_add(evas);
+
+ if (!edje_object_file_set(edje_obj, edje_file, "ui/logo"))
+ {
+ int err = edje_object_load_error_get(edje_obj);
+ const char *errmsg = edje_load_error_str(err);
+ fprintf(stderr, "Could not load 'ui/logo' from %s: %s\n",
+ edje_file, errmsg);
+ evas_object_del(edje_obj);
+ goto shutdown_edje;
+ }
+
+ /* Print status lines on each mouse-in / mouse-out so terminal output
+ * confirms the signals are flowing. The actual STATE_SET is handled
+ * inside the theme; these callbacks are informational only. */
+ edje_object_signal_callback_add(edje_obj, "mouse,in", "logo",
+ _on_hover_in, NULL);
+ edje_object_signal_callback_add(edje_obj, "mouse,out", "logo",
+ _on_hover_out, NULL);
+
+ evas_object_move(edje_obj, 40, 40);
+ evas_object_resize(edje_obj, WIDTH - 80, HEIGHT - 80);
+ evas_object_show(edje_obj);
+
+ evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN,
+ _on_keydown, edje_obj);
+
+ printf("%s", commands);
+ printf("Loaded: %s group: ui/logo\n", edje_file);
+ printf("Move the mouse over the shape to see the hover transition.\n");
+ printf("Runtime theming: call edje_object_color_class_set(obj, \"logo_fill\", ...)\n"
+ "to retint the fill without recompiling the theme.\n\n");
+
+ ecore_evas_show(ee);
+ ecore_main_loop_begin();
+
+ ecore_evas_free(ee);
+ ecore_evas_shutdown();
+ edje_shutdown();
+
+ return EXIT_SUCCESS;
+
+ shutdown_edje:
+ edje_shutdown();
+ shutdown_ecore_evas:
+ ecore_evas_shutdown();
+
+ return EXIT_FAILURE;
+}
diff --git a/src/examples/edje/meson.build b/src/examples/edje/meson.build
index ff57a6e29e..58e8f8fa87 100644
--- a/src/examples/edje/meson.build
+++ b/src/examples/edje/meson.build
@@ -45,6 +45,7 @@ edc_files = [
'toggle_using_filter.edc',
'multisense.edc',
'center_zoom.edc',
+ 'vector_states.edc',
]
if (get_option('physics'))
@@ -117,6 +118,7 @@ edje_examples = [
'edje-multisense',
'edje-perspective',
'edje-signals-messages',
+ 'edje-vector-states',
'edje-swallow',
'edje-swallow2',
'edje-table',
diff --git a/src/examples/edje/vector_states.edc b/src/examples/edje/vector_states.edc
new file mode 100644
index 0000000000..a6475b9bbb
--- /dev/null
+++ b/src/examples/edje/vector_states.edc
@@ -0,0 +1,75 @@
+/**
+ * Edje vector state animation — worked example (spec §11)
+ *
+ * Demonstrates:
+ * - A named vector tree in the toplevel vectors {} block
+ * - A VECTOR part referencing it via vector.use:
+ * - Two states (default, hover) with per-node shape override
+ * - fill.color_class binding so the fill colour is themeable at runtime
+ * - STATE_SET programs wired to mouse,in / mouse,out for live transitions
+ *
+ * Compile:
+ * edje_cc vector_states.edc
+ * Run:
+ * ./edje-vector-states vector_states.edj
+ */
+
+collections {
+ color_classes {
+ color_class { name: "logo_fill"; color: 80 140 255 255; }
+ color_class { name: "logo_hover"; color: 255 200 80 255; }
+ color_class { name: "logo_outline"; color: 20 20 20 255; }
+ }
+
+ vectors {
+ vector { name: "logo_glyph";
+ viewbox: 0 0 100 100;
+ shape { name: "body";
+ /* topology: M + 8×L + Z — identical command sequence in both
+ * states, so efl_gfx_path_interpolate() can morph the path. */
+ path: "M0,0 L0,0 L100,0 L100,0 L100,100 L100,100 L0,100 L0,100 L0,0";
+ fill.color_class: "logo_fill";
+ stroke.color_class: "logo_outline";
+ stroke.width: 2;
+ }
+ }
+ }
+
+ group { name: "ui/logo";
+ parts {
+ part { name: "logo"; type: VECTOR;
+ description { state: "default" 0.0;
+ rel1.relative: 0.0 0.0;
+ rel2.relative: 1.0 1.0;
+ vector.use: "logo_glyph";
+ }
+ description { state: "hover" 0.0;
+ inherit: "default" 0.0;
+ /* Override the "body" shape:
+ * - morph path from square to star (same topology: M + 8×L + Z)
+ * - swap fill class to logo_hover (smooth crossfade via lerp)
+ * - widen stroke from 2 to 4
+ * stroke color_class stays logo_outline — no override needed. */
+ vector.shape {
+ target: "body";
+ path: "M0,0 L50,-80 L100,0 L180,50 L100,100 L50,180 L0,100 L-80,50 L0,0";
+ fill.color_class: "logo_hover";
+ stroke.width: 4;
+ }
+ }
+ }
+ }
+ programs {
+ program { signal: "mouse,in"; source: "logo";
+ action: STATE_SET "hover" 0.0;
+ target: "logo";
+ transition: SINUSOIDAL 0.3;
+ }
+ program { signal: "mouse,out"; source: "logo";
+ action: STATE_SET "default" 0.0;
+ target: "logo";
+ transition: SINUSOIDAL 0.3;
+ }
+ }
+ }
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.