diff --git a/scripts/gdb/lvglgdb/cmds/dashboard/data_collector.py b/scripts/gdb/lvglgdb/cmds/dashboard/data_collector.py index 22227468a3..3ed25f969f 100644 --- a/scripts/gdb/lvglgdb/cmds/dashboard/data_collector.py +++ b/scripts/gdb/lvglgdb/cmds/dashboard/data_collector.py @@ -122,7 +122,9 @@ def _collect_object_trees(lvgl) -> list: @Snapshot.fallback(layer_name=lambda s: addrs.get(int(s))) def _screen_snapshot(screen): - snap = screen.snapshot( + from lvglgdb.lvgl.core.lv_obj import LVObject + w = LVObject._wrap_as_widget(screen) + snap = w.snapshot( include_children=True, include_styles=True, ).as_dict() snap["layer_name"] = addrs.get(int(screen)) diff --git a/scripts/gdb/lvglgdb/cmds/dashboard/static/uinspy.html b/scripts/gdb/lvglgdb/cmds/dashboard/static/uinspy.html index 5bd4e37d6b..8066e28135 100644 --- a/scripts/gdb/lvglgdb/cmds/dashboard/static/uinspy.html +++ b/scripts/gdb/lvglgdb/cmds/dashboard/static/uinspy.html @@ -1249,6 +1249,24 @@ ui-topbar .topbar-search::placeholder { } color: var(--color-yellow); } +.detail-adv-toggle { + margin-top: calc(var(--spacing) * 1); +} +.detail-adv-summary { + cursor: pointer; + padding-block: calc(var(--spacing) * 0.5); + font-size: 10px; + --tw-font-weight: var(--font-weight-medium); + font-weight: var(--font-weight-medium); + color: var(--color-overlay0); + list-style: none; +} +.detail-adv-summary::before { + content: "▸ "; +} +.detail-adv-toggle[open] > .detail-adv-summary::before { + content: "▾ "; +} .scene-controls { margin-bottom: calc(var(--spacing) * 1); display: flex; @@ -2082,6 +2100,13 @@ function buildCard(item, config) { } // src/builders/obj-tree.ui.ts +function formatWdVal(v) { + if (v == null) + return "-"; + if (typeof v === "object") + return JSON.stringify(v); + return String(v); +} function renderObjTree(obj, depth = 0) { let det = document.createElement("details"); if (det.className = "obj-node", obj.addr) @@ -2200,6 +2225,43 @@ function renderObjDetail(addr, panel) { wrap.appendChild(el("span", "detail-flag-badge", "skip_trans")); intSec.appendChild(wrap), panel.appendChild(intSec); } + if (obj.widget_data && Object.keys(obj.widget_data).length) { + let wd = obj.widget_data, primary = { + lv_label: ["text", "long_mode", "recolor"], + lv_image: ["src", "w", "h", "rotation", "scale_x", "scale_y", "align"], + lv_bar: ["cur_value", "min_value", "max_value", "start_value", "mode"], + lv_slider: ["cur_value", "min_value", "max_value", "start_value", "mode", "dragging"], + lv_arc: ["value", "min_value", "max_value", "rotation", "type"], + lv_switch: ["anim_state", "orientation"], + lv_checkbox: ["txt"], + lv_dropdown: ["options", "option_cnt", "sel_opt_id", "dir"], + lv_textarea: ["placeholder_txt", "max_length", "pwd_show_time"], + lv_tabview: ["tab_cur", "tab_pos", "tab_bar_size"], + lv_roller: ["option_cnt", "sel_opt_id", "mode"], + lv_chart: ["point_cnt", "hdiv_cnt", "vdiv_cnt", "type"], + lv_scale: ["mode", "range_min", "range_max", "total_tick_count", "angle_range", "rotation"], + lv_spinner: ["duration", "angle"], + lv_keyboard: ["mode", "popovers"], + lv_led: ["color", "bright"], + lv_spinbox: ["value", "range_min", "range_max", "step", "digit_count", "dec_point_pos"], + lv_calendar: ["today", "showed_date"], + lv_table: ["col_cnt", "row_cnt"], + lv_buttonmatrix: ["btn_cnt", "row_cnt", "btn_id_sel", "one_check"] + }[obj.class_name] || [], allKeys = Object.keys(wd), priKeys = allKeys.filter((k) => primary.includes(k)), advKeys = allKeys.filter((k) => !primary.includes(k)), wdSec = el("div", "detail-section"); + wdSec.appendChild(el("div", "detail-section-title", "Widget · " + obj.class_name)); + for (let k of priKeys.length ? priKeys : allKeys.slice(0, 6)) + wdSec.appendChild(kvPair(k, formatWdVal(wd[k]))); + let rest = priKeys.length ? advKeys : allKeys.slice(6); + if (rest.length) { + let toggle = el("details", "detail-adv-toggle"); + toggle.appendChild(el("summary", "detail-adv-summary", `${rest.length} more fields`)); + let inner = el("div", ""); + for (let k of rest) + inner.appendChild(kvPair(k, formatWdVal(wd[k]))); + toggle.appendChild(inner), wdSec.appendChild(toggle); + } + panel.appendChild(wdSec); + } if (obj.styles?.length) { let styleSec = el("div", "detail-section"); styleSec.appendChild(el("div", "detail-section-title", "Styles (" + obj.styles.length + ")")), obj.styles.forEach((s) => { @@ -3173,7 +3235,7 @@ class UiDashboard extends BaseComponent { customElements.define("ui-dashboard", UiDashboard); // src/app.ts -document.getElementById("about").innerHTML = `uinspy v${"0.4.6"}·Built ${"2026-04-02 03:55 GMT+8"}·${"be336ae"}·${"Canvas2D"}·GitHub·LVGL·MIT`; +document.getElementById("about").innerHTML = `uinspy v${"0.4.6"}·Built ${"2026-04-02 13:52 GMT+8"}·${"07131c2"}·${"Canvas2D"}·GitHub·LVGL·MIT`; \ No newline at end of file diff --git a/scripts/gdb/lvglgdb/lvgl/core/lv_obj.py b/scripts/gdb/lvglgdb/lvgl/core/lv_obj.py index fc0f59cb13..fb8b53afdc 100644 --- a/scripts/gdb/lvglgdb/lvgl/core/lv_obj.py +++ b/scripts/gdb/lvglgdb/lvgl/core/lv_obj.py @@ -210,7 +210,8 @@ class LVObject(Value): @Snapshot.fallback() def _snap(c): - return c.snapshot( + w = self._wrap_as_widget(c) + return w.snapshot( include_children=True, include_styles=include_styles, ).as_dict() @@ -265,6 +266,15 @@ class LVObject(Value): return None return name.string() + @staticmethod + def _wrap_as_widget(obj): + """Try to wrap an LVObject as its specific widget type.""" + try: + from lvglgdb.lvgl.widgets import wrap_widget + return wrap_widget(obj) or obj + except ImportError: + return obj + def dump_obj_info(obj: LVObject): from lvglgdb.lvgl.formatter import print_info diff --git a/scripts/gdb/lvglgdb/lvgl/snapshot.py b/scripts/gdb/lvglgdb/lvgl/snapshot.py index 7b602623d4..38f1395085 100644 --- a/scripts/gdb/lvglgdb/lvgl/snapshot.py +++ b/scripts/gdb/lvglgdb/lvgl/snapshot.py @@ -77,6 +77,9 @@ class Snapshot: def __getitem__(self, key: str) -> Any: return self._data[key] + def __setitem__(self, key: str, value: Any) -> None: + self._data[key] = value + def __contains__(self, key: str) -> bool: return key in self._data diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/__init__.py b/scripts/gdb/lvglgdb/lvgl/widgets/__init__.py new file mode 100644 index 0000000000..1320d00c14 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/__init__.py @@ -0,0 +1,137 @@ +""" +Auto-generated LVGL widget wrappers. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from .lv_3dtexture import LV3dtexture +from .lv_image import LVImage +from .lv_animimg import LVAnimimg +from .lv_arc import LVArc +from .lv_arclabel import LVArclabel +from .lv_bar import LVBar +from .lv_button import LVButton +from .lv_buttonmatrix import LVButtonmatrix +from .lv_calendar import LVCalendar +from .lv_canvas import LVCanvas +from .lv_chart import LVChart +from .lv_checkbox import LVCheckbox +from .lv_dropdown import LVDropdown +from .lv_dropdown_list import LVDropdownList +from .lv_imagebutton import LVImagebutton +from .lv_ime_pinyin import LVImePinyin +from .lv_keyboard import LVKeyboard +from .lv_label import LVLabel +from .lv_led import LVLed +from .lv_line import LVLine +from .lv_menu import LVMenu +from .lv_menu_page import LVMenuPage +from .lv_msgbox import LVMsgbox +from .lv_roller import LVRoller +from .lv_scale import LVScale +from .lv_slider import LVSlider +from .lv_spangroup import LVSpangroup +from .lv_textarea import LVTextarea +from .lv_spinbox import LVSpinbox +from .lv_spinner import LVSpinner +from .lv_switch import LVSwitch +from .lv_table import LVTable +from .lv_tabview import LVTabview +from .lv_tileview import LVTileview +from .lv_tileview_tile import LVTileviewTile +from .lv_win import LVWin + +WIDGET_REGISTRY: dict[str, type] = { + "lv_3dtexture": LV3dtexture, + "lv_image": LVImage, + "lv_animimg": LVAnimimg, + "lv_arc": LVArc, + "lv_arclabel": LVArclabel, + "lv_bar": LVBar, + "lv_button": LVButton, + "lv_buttonmatrix": LVButtonmatrix, + "lv_calendar": LVCalendar, + "lv_canvas": LVCanvas, + "lv_chart": LVChart, + "lv_checkbox": LVCheckbox, + "lv_dropdown": LVDropdown, + "lv_dropdown_list": LVDropdownList, + "lv_imagebutton": LVImagebutton, + "lv_ime_pinyin": LVImePinyin, + "lv_keyboard": LVKeyboard, + "lv_label": LVLabel, + "lv_led": LVLed, + "lv_line": LVLine, + "lv_menu": LVMenu, + "lv_menu_page": LVMenuPage, + "lv_msgbox": LVMsgbox, + "lv_roller": LVRoller, + "lv_scale": LVScale, + "lv_slider": LVSlider, + "lv_spangroup": LVSpangroup, + "lv_textarea": LVTextarea, + "lv_spinbox": LVSpinbox, + "lv_spinner": LVSpinner, + "lv_switch": LVSwitch, + "lv_table": LVTable, + "lv_tabview": LVTabview, + "lv_tileview": LVTileview, + "lv_tileview_tile": LVTileviewTile, + "lv_win": LVWin, +} + + +import gdb + + +def wrap_widget(obj): + """Wrap an LVObject into its widget class if known.""" + cls = WIDGET_REGISTRY.get(obj.class_name) + if cls: + try: + return cls(obj) + except gdb.error: + pass # type not available in debug info + return None + +__all__ = [ + "LV3dtexture", + "LVImage", + "LVAnimimg", + "LVArc", + "LVArclabel", + "LVBar", + "LVButton", + "LVButtonmatrix", + "LVCalendar", + "LVCanvas", + "LVChart", + "LVCheckbox", + "LVDropdown", + "LVDropdownList", + "LVImagebutton", + "LVImePinyin", + "LVKeyboard", + "LVLabel", + "LVLed", + "LVLine", + "LVMenu", + "LVMenuPage", + "LVMsgbox", + "LVRoller", + "LVScale", + "LVSlider", + "LVSpangroup", + "LVTextarea", + "LVSpinbox", + "LVSpinner", + "LVSwitch", + "LVTable", + "LVTabview", + "LVTileview", + "LVTileviewTile", + "LVWin", + "WIDGET_REGISTRY", + "wrap_widget", +] diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/_helpers.py b/scripts/gdb/lvglgdb/lvgl/widgets/_helpers.py new file mode 100644 index 0000000000..f1982bda8a --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/_helpers.py @@ -0,0 +1,47 @@ +"""Shared field-reading helpers for widget wrappers. + +All helpers return a safe value (or None) without raising exceptions. +Protection is provided by Value.safe_field() and Value.string(fallback=). +""" + +from lvglgdb.lvgl.data_utils import ptr_or_none # noqa: F401 + + +def safe_string(obj, field_name): + """Read a char* field as string, or None.""" + val = obj.safe_field(field_name) + if val is None or not getattr(val, 'is_ok', True) or not int(val): + return None + return val.string(fallback=None) + + +def safe_color(obj, field_name): + """Read lv_color_t as hex string.""" + val = obj.safe_field(field_name) + if val is None or not getattr(val, 'is_ok', True): + return None + return f"#{int(val):06x}" + + +def safe_area(obj, field_name): + """Read lv_area_t as dict.""" + val = obj.safe_field(field_name) + if val is None or not getattr(val, 'is_ok', True): + return None + return { + "x1": int(val.safe_field("x1", 0)), + "y1": int(val.safe_field("y1", 0)), + "x2": int(val.safe_field("x2", 0)), + "y2": int(val.safe_field("y2", 0)), + } + + +def safe_point(obj, field_name): + """Read lv_point_t as dict.""" + val = obj.safe_field(field_name) + if val is None or not getattr(val, 'is_ok', True): + return None + return { + "x": int(val.safe_field("x", 0)), + "y": int(val.safe_field("y", 0)), + } diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_3dtexture.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_3dtexture.py new file mode 100644 index 0000000000..683cc0b3e7 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_3dtexture.py @@ -0,0 +1,38 @@ +""" +Auto-generated wrapper for lv_3dtexture_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LV3dtexture(LVObject): + """LVGL 3dtexture widget (lv_3dtexture_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_3dtexture_t", ptr=True) + + @property + def id(self): + return int(self._wv.safe_field("id", 0)) + + @property + def h_flip(self): + return int(self._wv.safe_field("h_flip", 0)) + + @property + def v_flip(self): + return int(self._wv.safe_field("v_flip", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["id"] = self.id + d["h_flip"] = self.h_flip + d["v_flip"] = self.v_flip + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_animimg.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_animimg.py new file mode 100644 index 0000000000..29f790ccfb --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_animimg.py @@ -0,0 +1,33 @@ +""" +Auto-generated wrapper for lv_animimg_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from .lv_image import LVImage + + +class LVAnimimg(LVImage): + """LVGL animimage widget (lv_animimg_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_animimg_t", ptr=True) + + @property + def anim(self): + return int(self._wv.safe_field("anim", 0)) + + @property + def pic_count(self): + return int(self._wv.safe_field("pic_count", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["anim"] = self.anim + d["pic_count"] = self.pic_count + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_arc.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_arc.py new file mode 100644 index 0000000000..be8e263b41 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_arc.py @@ -0,0 +1,112 @@ +""" +Auto-generated wrapper for lv_arc_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVArc(LVObject): + """LVGL arc widget (lv_arc_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_arc_t", ptr=True) + + @property + def rotation(self): + return int(self._wv.safe_field("rotation", 0)) + + @property + def indic_angle_start(self): + return int(self._wv.safe_field("indic_angle_start", 0)) + + @property + def indic_angle_end(self): + return int(self._wv.safe_field("indic_angle_end", 0)) + + @property + def bg_angle_start(self): + return int(self._wv.safe_field("bg_angle_start", 0)) + + @property + def bg_angle_end(self): + return int(self._wv.safe_field("bg_angle_end", 0)) + + @property + def value(self): + """Current value of the arc""" + return int(self._wv.safe_field("value", 0)) + + @property + def min_value(self): + """Minimum value of the arc""" + return int(self._wv.safe_field("min_value", 0)) + + @property + def max_value(self): + """Maximum value of the arc""" + return int(self._wv.safe_field("max_value", 0)) + + @property + def dragging(self): + return int(self._wv.safe_field("dragging", 0)) + + @property + def type(self): + return int(self._wv.safe_field("type", 0)) + + @property + def min_close(self): + """1: the last pressed angle was closer to minimum end""" + return int(self._wv.safe_field("min_close", 0)) + + @property + def in_out(self): + """1: The click was within the background arc angles. 0: Click outside""" + return int(self._wv.safe_field("in_out", 0)) + + @property + def chg_rate(self): + """Drag angle rate of change of the arc (degrees/sec)""" + return int(self._wv.safe_field("chg_rate", 0)) + + @property + def last_tick(self): + """Last dragging event timestamp of the arc""" + return int(self._wv.safe_field("last_tick", 0)) + + @property + def last_angle(self): + """Last dragging angle of the arc""" + return int(self._wv.safe_field("last_angle", 0)) + + @property + def knob_offset(self): + """knob offset from the main arc""" + return int(self._wv.safe_field("knob_offset", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["rotation"] = self.rotation + d["indic_angle_start"] = self.indic_angle_start + d["indic_angle_end"] = self.indic_angle_end + d["bg_angle_start"] = self.bg_angle_start + d["bg_angle_end"] = self.bg_angle_end + d["value"] = self.value + d["min_value"] = self.min_value + d["max_value"] = self.max_value + d["dragging"] = self.dragging + d["type"] = self.type + d["min_close"] = self.min_close + d["in_out"] = self.in_out + d["chg_rate"] = self.chg_rate + d["last_tick"] = self.last_tick + d["last_angle"] = self.last_angle + d["knob_offset"] = self.knob_offset + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_arclabel.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_arclabel.py new file mode 100644 index 0000000000..7ca9257db7 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_arclabel.py @@ -0,0 +1,101 @@ +""" +Auto-generated wrapper for lv_arclabel_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import safe_point, safe_string + + +class LVArclabel(LVObject): + """LVGL arclabel widget (lv_arclabel_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_arclabel_t", ptr=True) + + @property + def text(self): + return safe_string(self._wv, "text") + + @property + def dot_begin(self): + """Offset where bytes have been replaced with dots""" + return int(self._wv.safe_field("dot_begin", 0)) + + @property + def angle_start(self): + return int(self._wv.safe_field("angle_start", 0)) + + @property + def angle_size(self): + return int(self._wv.safe_field("angle_size", 0)) + + @property + def offset(self): + return int(self._wv.safe_field("offset", 0)) + + @property + def radius(self): + return int(self._wv.safe_field("radius", 0)) + + @property + def center_offset(self): + return safe_point(self._wv, "center_offset") + + @property + def dir(self): + return int(self._wv.safe_field("dir", 0)) + + @property + def text_align_v(self): + """Vertical text alignment""" + return int(self._wv.safe_field("text_align_v", 0)) + + @property + def text_align_h(self): + """Horizontal text alignment""" + return int(self._wv.safe_field("text_align_h", 0)) + + @property + def static_txt(self): + """Flag to indicate the text is static""" + return int(self._wv.safe_field("static_txt", 0)) + + @property + def recolor(self): + """Enable in-line letter re-coloring""" + return int(self._wv.safe_field("recolor", 0)) + + @property + def overflow(self): + """Overflow mode: 0=visible, 1=ellipsis, 2=clip""" + return int(self._wv.safe_field("overflow", 0)) + + @property + def end_overlap(self): + """End overlap flag, false if prevent end overlap""" + return int(self._wv.safe_field("end_overlap", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["text"] = self.text + d["dot_begin"] = self.dot_begin + d["angle_start"] = self.angle_start + d["angle_size"] = self.angle_size + d["offset"] = self.offset + d["radius"] = self.radius + d["center_offset"] = self.center_offset + d["dir"] = self.dir + d["text_align_v"] = self.text_align_v + d["text_align_h"] = self.text_align_h + d["static_txt"] = self.static_txt + d["recolor"] = self.recolor + d["overflow"] = self.overflow + d["end_overlap"] = self.end_overlap + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_bar.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_bar.py new file mode 100644 index 0000000000..d64fe3bc48 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_bar.py @@ -0,0 +1,82 @@ +""" +Auto-generated wrapper for lv_bar_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import safe_area + + +class LVBar(LVObject): + """LVGL bar widget (lv_bar_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_bar_t", ptr=True) + + @property + def cur_value(self): + """Current value of the bar""" + return int(self._wv.safe_field("cur_value", 0)) + + @property + def min_value(self): + """Minimum value of the bar""" + return int(self._wv.safe_field("min_value", 0)) + + @property + def max_value(self): + """Maximum value of the bar""" + return int(self._wv.safe_field("max_value", 0)) + + @property + def start_value(self): + """Start value of the bar""" + return int(self._wv.safe_field("start_value", 0)) + + @property + def indic_area(self): + """Save the indicator area. Might be used by derived types""" + return safe_area(self._wv, "indic_area") + + @property + def val_reversed(self): + """Whether value been reversed""" + return int(self._wv.safe_field("val_reversed", 0)) + + @property + def cur_value_anim(self): + return int(self._wv.safe_field("cur_value_anim", 0)) + + @property + def start_value_anim(self): + return int(self._wv.safe_field("start_value_anim", 0)) + + @property + def mode(self): + """Type of bar""" + return int(self._wv.safe_field("mode", 0)) + + @property + def orientation(self): + """Orientation of bar""" + return int(self._wv.safe_field("orientation", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["cur_value"] = self.cur_value + d["min_value"] = self.min_value + d["max_value"] = self.max_value + d["start_value"] = self.start_value + d["indic_area"] = self.indic_area + d["val_reversed"] = self.val_reversed + d["cur_value_anim"] = self.cur_value_anim + d["start_value_anim"] = self.start_value_anim + d["mode"] = self.mode + d["orientation"] = self.orientation + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_button.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_button.py new file mode 100644 index 0000000000..7b26b56042 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_button.py @@ -0,0 +1,21 @@ +""" +Auto-generated wrapper for lv_button_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVButton(LVObject): + """LVGL button widget (lv_button_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_button_t", ptr=True) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_buttonmatrix.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_buttonmatrix.py new file mode 100644 index 0000000000..cdfcc8d689 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_buttonmatrix.py @@ -0,0 +1,72 @@ +""" +Auto-generated wrapper for lv_buttonmatrix_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none, safe_string + + +class LVButtonmatrix(LVObject): + """LVGL buttonmatrix widget (lv_buttonmatrix_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_buttonmatrix_t", ptr=True) + + @property + def const(self): + """Pointer to the current map""" + return safe_string(self._wv, "const") + + @property + def button_areas(self): + """Array of areas of buttons""" + return ptr_or_none(self._wv.safe_field("button_areas")) + + @property + def ctrl_bits(self): + """Array of control bytes""" + return ptr_or_none(self._wv.safe_field("ctrl_bits")) + + @property + def btn_cnt(self): + """Number of button in 'map_p'(Handled by the library)""" + return int(self._wv.safe_field("btn_cnt", 0)) + + @property + def row_cnt(self): + """Number of rows in 'map_p'(Handled by the library)""" + return int(self._wv.safe_field("row_cnt", 0)) + + @property + def btn_id_sel(self): + """Index of the active button (being pressed/released etc) or LV_BUTTONMATRIX_BUTTON_NONE""" + return int(self._wv.safe_field("btn_id_sel", 0)) + + @property + def one_check(self): + """1: Single button toggled at once""" + return int(self._wv.safe_field("one_check", 0)) + + @property + def auto_free_map(self): + """1: Automatically free the map when the widget is deleted""" + return int(self._wv.safe_field("auto_free_map", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["const"] = self.const + d["button_areas"] = self.button_areas + d["ctrl_bits"] = self.ctrl_bits + d["btn_cnt"] = self.btn_cnt + d["row_cnt"] = self.row_cnt + d["btn_id_sel"] = self.btn_id_sel + d["one_check"] = self.one_check + d["auto_free_map"] = self.auto_free_map + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_calendar.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_calendar.py new file mode 100644 index 0000000000..000a4b67de --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_calendar.py @@ -0,0 +1,58 @@ +""" +Auto-generated wrapper for lv_calendar_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none + + +class LVCalendar(LVObject): + """LVGL calendar widget (lv_calendar_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_calendar_t", ptr=True) + + @property + def btnm(self): + return ptr_or_none(self._wv.safe_field("btnm")) + + @property + def today(self): + """Date of today""" + return int(self._wv.safe_field("today", 0)) + + @property + def showed_date(self): + """Currently visible month (day is ignored)""" + return int(self._wv.safe_field("showed_date", 0)) + + @property + def highlighted_dates(self): + """Apply different style on these days (pointer to user-defined array)""" + return ptr_or_none(self._wv.safe_field("highlighted_dates")) + + @property + def highlighted_dates_num(self): + """Number of elements in `highlighted_days`""" + return int(self._wv.safe_field("highlighted_dates_num", 0)) + + @property + def use_chinese_calendar(self): + return int(self._wv.safe_field("use_chinese_calendar", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["btnm"] = self.btnm + d["today"] = self.today + d["showed_date"] = self.showed_date + d["highlighted_dates"] = self.highlighted_dates + d["highlighted_dates_num"] = self.highlighted_dates_num + d["use_chinese_calendar"] = self.use_chinese_calendar + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_canvas.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_canvas.py new file mode 100644 index 0000000000..3052d7175f --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_canvas.py @@ -0,0 +1,34 @@ +""" +Auto-generated wrapper for lv_canvas_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from .lv_image import LVImage +from ._helpers import ptr_or_none + + +class LVCanvas(LVImage): + """LVGL canvas widget (lv_canvas_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_canvas_t", ptr=True) + + @property + def draw_buf(self): + return ptr_or_none(self._wv.safe_field("draw_buf")) + + @property + def static_buf(self): + return int(self._wv.safe_field("static_buf", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["draw_buf"] = self.draw_buf + d["static_buf"] = self.static_buf + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_chart.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_chart.py new file mode 100644 index 0000000000..4c521557e4 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_chart.py @@ -0,0 +1,69 @@ +""" +Auto-generated wrapper for lv_chart_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVChart(LVObject): + """LVGL chart widget (lv_chart_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_chart_t", ptr=True) + + @property + def series_ll(self): + """Linked list for series (stores lv_chart_series_t)""" + return int(self._wv.safe_field("series_ll", 0)) + + @property + def cursor_ll(self): + """Linked list for cursors (stores lv_chart_cursor_t)""" + return int(self._wv.safe_field("cursor_ll", 0)) + + @property + def pressed_point_id(self): + return int(self._wv.safe_field("pressed_point_id", 0)) + + @property + def hdiv_cnt(self): + """Number of horizontal division lines""" + return int(self._wv.safe_field("hdiv_cnt", 0)) + + @property + def vdiv_cnt(self): + """Number of vertical division lines""" + return int(self._wv.safe_field("vdiv_cnt", 0)) + + @property + def point_cnt(self): + """Number of points in all series""" + return int(self._wv.safe_field("point_cnt", 0)) + + @property + def type(self): + """Chart type""" + return int(self._wv.safe_field("type", 0)) + + @property + def update_mode(self): + return int(self._wv.safe_field("update_mode", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["series_ll"] = self.series_ll + d["cursor_ll"] = self.cursor_ll + d["pressed_point_id"] = self.pressed_point_id + d["hdiv_cnt"] = self.hdiv_cnt + d["vdiv_cnt"] = self.vdiv_cnt + d["point_cnt"] = self.point_cnt + d["type"] = self.type + d["update_mode"] = self.update_mode + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_checkbox.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_checkbox.py new file mode 100644 index 0000000000..ade7c08b75 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_checkbox.py @@ -0,0 +1,34 @@ +""" +Auto-generated wrapper for lv_checkbox_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import safe_string + + +class LVCheckbox(LVObject): + """LVGL checkbox widget (lv_checkbox_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_checkbox_t", ptr=True) + + @property + def txt(self): + return safe_string(self._wv, "txt") + + @property + def static_txt(self): + return int(self._wv.safe_field("static_txt", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["txt"] = self.txt + d["static_txt"] = self.static_txt + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_dropdown.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_dropdown.py new file mode 100644 index 0000000000..a69752117e --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_dropdown.py @@ -0,0 +1,96 @@ +""" +Auto-generated wrapper for lv_dropdown_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none, safe_string + + +class LVDropdown(LVObject): + """LVGL dropdown widget (lv_dropdown_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_dropdown_t", ptr=True) + + @property + def list(self): + """The dropped down list""" + return ptr_or_none(self._wv.safe_field("list")) + + @property + def text(self): + """Text to display on the dropdown's button""" + return safe_string(self._wv, "text") + + @property + def symbol(self): + """Arrow or other icon when the drop-down list is closed""" + return ptr_or_none(self._wv.safe_field("symbol")) + + @property + def options(self): + """Options in a '\n' separated list""" + return safe_string(self._wv, "options") + + @property + def option_cnt(self): + """Number of options""" + return int(self._wv.safe_field("option_cnt", 0)) + + @property + def sel_opt_id(self): + """Index of the currently selected option""" + return int(self._wv.safe_field("sel_opt_id", 0)) + + @property + def sel_opt_id_orig(self): + """Store the original index on focus""" + return int(self._wv.safe_field("sel_opt_id_orig", 0)) + + @property + def pr_opt_id(self): + """Index of the currently pressed option""" + return int(self._wv.safe_field("pr_opt_id", 0)) + + @property + def dir(self): + """Direction in which the list should open""" + return int(self._wv.safe_field("dir", 0)) + + @property + def static_options(self): + """1: Only a pointer is saved in `options`""" + return int(self._wv.safe_field("static_options", 0)) + + @property + def selected_highlight(self): + """1: Make the selected option highlighted in the list""" + return int(self._wv.safe_field("selected_highlight", 0)) + + @property + def static_text(self): + """1: Only a pointer is saved in `text`""" + return int(self._wv.safe_field("static_text", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["list"] = self.list + d["text"] = self.text + d["symbol"] = self.symbol + d["options"] = self.options + d["option_cnt"] = self.option_cnt + d["sel_opt_id"] = self.sel_opt_id + d["sel_opt_id_orig"] = self.sel_opt_id_orig + d["pr_opt_id"] = self.pr_opt_id + d["dir"] = self.dir + d["static_options"] = self.static_options + d["selected_highlight"] = self.selected_highlight + d["static_text"] = self.static_text + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_dropdown_list.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_dropdown_list.py new file mode 100644 index 0000000000..673edfac7a --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_dropdown_list.py @@ -0,0 +1,29 @@ +""" +Auto-generated wrapper for lv_dropdown_list_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none + + +class LVDropdownList(LVObject): + """LVGL dropdown widget (lv_dropdown_list_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_dropdown_list_t", ptr=True) + + @property + def dropdown(self): + return ptr_or_none(self._wv.safe_field("dropdown")) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["dropdown"] = self.dropdown + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_image.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_image.py new file mode 100644 index 0000000000..b8698503c8 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_image.py @@ -0,0 +1,107 @@ +""" +Auto-generated wrapper for lv_image_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none, safe_point + + +class LVImage(LVObject): + """LVGL image widget (lv_image_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_image_t", ptr=True) + + @property + def src(self): + """Image source: Pointer to an array or a file or a symbol""" + return ptr_or_none(self._wv.safe_field("src")) + + @property + def bitmap_mask_src(self): + """Pointer to an A8 bitmap mask""" + return ptr_or_none(self._wv.safe_field("bitmap_mask_src")) + + @property + def offset(self): + return safe_point(self._wv, "offset") + + @property + def w(self): + """Width of the image (Handled by the library)""" + return int(self._wv.safe_field("w", 0)) + + @property + def h(self): + """Height of the image (Handled by the library)""" + return int(self._wv.safe_field("h", 0)) + + @property + def rotation(self): + """Rotation angle of the image""" + return int(self._wv.safe_field("rotation", 0)) + + @property + def scale_x(self): + """256 means no zoom, 512 double size, 128 half size""" + return int(self._wv.safe_field("scale_x", 0)) + + @property + def scale_y(self): + """256 means no zoom, 512 double size, 128 half size""" + return int(self._wv.safe_field("scale_y", 0)) + + @property + def pivot(self): + """Rotation center of the image""" + return safe_point(self._wv, "pivot") + + @property + def src_type(self): + """See: lv_image_src_t""" + return int(self._wv.safe_field("src_type", 0)) + + @property + def cf(self): + """Color format from `lv_color_format_t`""" + return int(self._wv.safe_field("cf", 0)) + + @property + def antialias(self): + """Apply anti-aliasing in transformations (rotate, zoom)""" + return int(self._wv.safe_field("antialias", 0)) + + @property + def align(self): + """Image size mode when image size and object size is different. See lv_image_align_t""" + return int(self._wv.safe_field("align", 0)) + + @property + def blend_mode(self): + """Element of `lv_blend_mode_t`""" + return int(self._wv.safe_field("blend_mode", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["src"] = self.src + d["bitmap_mask_src"] = self.bitmap_mask_src + d["offset"] = self.offset + d["w"] = self.w + d["h"] = self.h + d["rotation"] = self.rotation + d["scale_x"] = self.scale_x + d["scale_y"] = self.scale_y + d["pivot"] = self.pivot + d["src_type"] = self.src_type + d["cf"] = self.cf + d["antialias"] = self.antialias + d["align"] = self.align + d["blend_mode"] = self.blend_mode + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_imagebutton.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_imagebutton.py new file mode 100644 index 0000000000..7a48efa4cf --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_imagebutton.py @@ -0,0 +1,21 @@ +""" +Auto-generated wrapper for lv_imagebutton_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVImagebutton(LVObject): + """LVGL imagebutton widget (lv_imagebutton_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_imagebutton_t", ptr=True) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_ime_pinyin.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_ime_pinyin.py new file mode 100644 index 0000000000..d0749ee631 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_ime_pinyin.py @@ -0,0 +1,92 @@ +""" +Auto-generated wrapper for lv_ime_pinyin_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none, safe_string + + +class LVImePinyin(LVObject): + """LVGL ime widget (lv_ime_pinyin_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_ime_pinyin_t", ptr=True) + + @property + def kb(self): + return ptr_or_none(self._wv.safe_field("kb")) + + @property + def cand_panel(self): + return ptr_or_none(self._wv.safe_field("cand_panel")) + + @property + def dict(self): + return ptr_or_none(self._wv.safe_field("dict")) + + @property + def k9_legal_py_ll(self): + return int(self._wv.safe_field("k9_legal_py_ll", 0)) + + @property + def cand_str(self): + """Candidate string""" + return safe_string(self._wv, "cand_str") + + @property + def k9_py_ll_pos(self): + """Current pinyin map pages(k9)""" + return int(self._wv.safe_field("k9_py_ll_pos", 0)) + + @property + def k9_legal_py_count(self): + """Count of legal Pinyin numbers(k9)""" + return int(self._wv.safe_field("k9_legal_py_count", 0)) + + @property + def k9_input_str_len(self): + """9-key input(k9) mode input string max len""" + return int(self._wv.safe_field("k9_input_str_len", 0)) + + @property + def ta_count(self): + """The number of characters entered in the text box this time""" + return int(self._wv.safe_field("ta_count", 0)) + + @property + def cand_num(self): + """Number of candidates""" + return int(self._wv.safe_field("cand_num", 0)) + + @property + def py_page(self): + """Current pinyin map pages(k26)""" + return int(self._wv.safe_field("py_page", 0)) + + @property + def mode(self): + """Set mode, 1: 26-key input(k26), 0: 9-key input(k9). Default: 1.""" + return int(self._wv.safe_field("mode", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["kb"] = self.kb + d["cand_panel"] = self.cand_panel + d["dict"] = self.dict + d["k9_legal_py_ll"] = self.k9_legal_py_ll + d["cand_str"] = self.cand_str + d["k9_py_ll_pos"] = self.k9_py_ll_pos + d["k9_legal_py_count"] = self.k9_legal_py_count + d["k9_input_str_len"] = self.k9_input_str_len + d["ta_count"] = self.ta_count + d["cand_num"] = self.cand_num + d["py_page"] = self.py_page + d["mode"] = self.mode + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_keyboard.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_keyboard.py new file mode 100644 index 0000000000..29c81bb15e --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_keyboard.py @@ -0,0 +1,42 @@ +""" +Auto-generated wrapper for lv_keyboard_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from .lv_buttonmatrix import LVButtonmatrix +from ._helpers import ptr_or_none + + +class LVKeyboard(LVButtonmatrix): + """LVGL keyboard widget (lv_keyboard_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_keyboard_t", ptr=True) + + @property + def ta(self): + """Pointer to the assigned text area""" + return ptr_or_none(self._wv.safe_field("ta")) + + @property + def mode(self): + """Key map type""" + return int(self._wv.safe_field("mode", 0)) + + @property + def popovers(self): + """Show button titles in popovers on press""" + return int(self._wv.safe_field("popovers", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["ta"] = self.ta + d["mode"] = self.mode + d["popovers"] = self.popovers + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_label.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_label.py new file mode 100644 index 0000000000..d039fed9ae --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_label.py @@ -0,0 +1,108 @@ +""" +Auto-generated wrapper for lv_label_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import safe_point, safe_string + + +class LVLabel(LVObject): + """LVGL label widget (lv_label_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_label_t", ptr=True) + + @property + def text(self): + return safe_string(self._wv, "text") + + @property + def translation_tag(self): + return safe_string(self._wv, "translation_tag") + + @property + def dot_begin(self): + """Offset where bytes have been replaced with dots""" + return int(self._wv.safe_field("dot_begin", 0)) + + @property + def hint(self): + return int(self._wv.safe_field("hint", 0)) + + @property + def sel_start(self): + return int(self._wv.safe_field("sel_start", 0)) + + @property + def sel_end(self): + return int(self._wv.safe_field("sel_end", 0)) + + @property + def size_cache(self): + """Text size cache""" + return safe_point(self._wv, "size_cache") + + @property + def offset(self): + """Text draw position offset""" + return safe_point(self._wv, "offset") + + @property + def long_mode(self): + """Determine what to do with the long texts""" + return int(self._wv.safe_field("long_mode", 0)) + + @property + def static_txt(self): + """Flag to indicate the text is static""" + return int(self._wv.safe_field("static_txt", 0)) + + @property + def recolor(self): + """Enable in-line letter re-coloring""" + return int(self._wv.safe_field("recolor", 0)) + + @property + def expand(self): + """Ignore real width (used by the library with LV_LABEL_LONG_MODE_SCROLL)""" + return int(self._wv.safe_field("expand", 0)) + + @property + def invalid_size_cache(self): + """1: Recalculate size and update cache""" + return int(self._wv.safe_field("invalid_size_cache", 0)) + + @property + def need_refr_text(self): + """1: Refresh text after layout update completion""" + return int(self._wv.safe_field("need_refr_text", 0)) + + @property + def text_size(self): + return safe_point(self._wv, "text_size") + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["text"] = self.text + d["translation_tag"] = self.translation_tag + d["dot_begin"] = self.dot_begin + d["hint"] = self.hint + d["sel_start"] = self.sel_start + d["sel_end"] = self.sel_end + d["size_cache"] = self.size_cache + d["offset"] = self.offset + d["long_mode"] = self.long_mode + d["static_txt"] = self.static_txt + d["recolor"] = self.recolor + d["expand"] = self.expand + d["invalid_size_cache"] = self.invalid_size_cache + d["need_refr_text"] = self.need_refr_text + d["text_size"] = self.text_size + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_led.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_led.py new file mode 100644 index 0000000000..0cbdf8cfc0 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_led.py @@ -0,0 +1,35 @@ +""" +Auto-generated wrapper for lv_led_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import safe_color + + +class LVLed(LVObject): + """LVGL led widget (lv_led_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_led_t", ptr=True) + + @property + def color(self): + return safe_color(self._wv, "color") + + @property + def bright(self): + """Current brightness of the LED (0..255)""" + return int(self._wv.safe_field("bright", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["color"] = self.color + d["bright"] = self.bright + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_line.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_line.py new file mode 100644 index 0000000000..1bc1c66d67 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_line.py @@ -0,0 +1,21 @@ +""" +Auto-generated wrapper for lv_line_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVLine(LVObject): + """LVGL line widget (lv_line_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_line_t", ptr=True) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_menu.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_menu.py new file mode 100644 index 0000000000..005a593027 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_menu.py @@ -0,0 +1,105 @@ +""" +Auto-generated wrapper for lv_menu_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none + + +class LVMenu(LVObject): + """LVGL menu widget (lv_menu_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_menu_t", ptr=True) + + @property + def storage(self): + """a pointer to obj that is the parent of all pages not displayed""" + return ptr_or_none(self._wv.safe_field("storage")) + + @property + def main(self): + return ptr_or_none(self._wv.safe_field("main")) + + @property + def main_page(self): + return ptr_or_none(self._wv.safe_field("main_page")) + + @property + def main_header(self): + return ptr_or_none(self._wv.safe_field("main_header")) + + @property + def main_header_title(self): + return ptr_or_none(self._wv.safe_field("main_header_title")) + + @property + def sidebar(self): + return ptr_or_none(self._wv.safe_field("sidebar")) + + @property + def sidebar_page(self): + return ptr_or_none(self._wv.safe_field("sidebar_page")) + + @property + def sidebar_header(self): + return ptr_or_none(self._wv.safe_field("sidebar_header")) + + @property + def sidebar_header_title(self): + return ptr_or_none(self._wv.safe_field("sidebar_header_title")) + + @property + def selected_tab(self): + return ptr_or_none(self._wv.safe_field("selected_tab")) + + @property + def history_ll(self): + return int(self._wv.safe_field("history_ll", 0)) + + @property + def cur_depth(self): + return int(self._wv.safe_field("cur_depth", 0)) + + @property + def prev_depth(self): + return int(self._wv.safe_field("prev_depth", 0)) + + @property + def sidebar_generated(self): + return int(self._wv.safe_field("sidebar_generated", 0)) + + @property + def mode_header(self): + return int(self._wv.safe_field("mode_header", 0)) + + @property + def mode_root_back_btn(self): + return int(self._wv.safe_field("mode_root_back_btn", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["storage"] = self.storage + d["main"] = self.main + d["main_page"] = self.main_page + d["main_header"] = self.main_header + d["main_header_title"] = self.main_header_title + d["sidebar"] = self.sidebar + d["sidebar_page"] = self.sidebar_page + d["sidebar_header"] = self.sidebar_header + d["sidebar_header_title"] = self.sidebar_header_title + d["selected_tab"] = self.selected_tab + d["history_ll"] = self.history_ll + d["cur_depth"] = self.cur_depth + d["prev_depth"] = self.prev_depth + d["sidebar_generated"] = self.sidebar_generated + d["mode_header"] = self.mode_header + d["mode_root_back_btn"] = self.mode_root_back_btn + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_menu_page.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_menu_page.py new file mode 100644 index 0000000000..2108b55e94 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_menu_page.py @@ -0,0 +1,34 @@ +""" +Auto-generated wrapper for lv_menu_page_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import safe_string + + +class LVMenuPage(LVObject): + """LVGL menu widget (lv_menu_page_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_menu_page_t", ptr=True) + + @property + def title(self): + return safe_string(self._wv, "title") + + @property + def static_title(self): + return int(self._wv.safe_field("static_title", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["title"] = self.title + d["static_title"] = self.static_title + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_msgbox.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_msgbox.py new file mode 100644 index 0000000000..bd9b090350 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_msgbox.py @@ -0,0 +1,44 @@ +""" +Auto-generated wrapper for lv_msgbox_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none + + +class LVMsgbox(LVObject): + """LVGL msgbox widget (lv_msgbox_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_msgbox_t", ptr=True) + + @property + def header(self): + return ptr_or_none(self._wv.safe_field("header")) + + @property + def content(self): + return ptr_or_none(self._wv.safe_field("content")) + + @property + def footer(self): + return ptr_or_none(self._wv.safe_field("footer")) + + @property + def title(self): + return ptr_or_none(self._wv.safe_field("title")) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["header"] = self.header + d["content"] = self.content + d["footer"] = self.footer + d["title"] = self.title + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_roller.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_roller.py new file mode 100644 index 0000000000..c0b0dd8c5f --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_roller.py @@ -0,0 +1,57 @@ +""" +Auto-generated wrapper for lv_roller_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVRoller(LVObject): + """LVGL roller widget (lv_roller_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_roller_t", ptr=True) + + @property + def option_cnt(self): + """Number of options""" + return int(self._wv.safe_field("option_cnt", 0)) + + @property + def sel_opt_id(self): + """Index of the current option""" + return int(self._wv.safe_field("sel_opt_id", 0)) + + @property + def sel_opt_id_ori(self): + """Store the original index on focus""" + return int(self._wv.safe_field("sel_opt_id_ori", 0)) + + @property + def inf_page_cnt(self): + """Number of extra pages added to make the roller look infinite""" + return int(self._wv.safe_field("inf_page_cnt", 0)) + + @property + def mode(self): + return int(self._wv.safe_field("mode", 0)) + + @property + def moved(self): + return int(self._wv.safe_field("moved", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["option_cnt"] = self.option_cnt + d["sel_opt_id"] = self.sel_opt_id + d["sel_opt_id_ori"] = self.sel_opt_id_ori + d["inf_page_cnt"] = self.inf_page_cnt + d["mode"] = self.mode + d["moved"] = self.moved + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_scale.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_scale.py new file mode 100644 index 0000000000..e7d8d3c3f4 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_scale.py @@ -0,0 +1,112 @@ +""" +Auto-generated wrapper for lv_scale_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVScale(LVObject): + """LVGL scale widget (lv_scale_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_scale_t", ptr=True) + + @property + def section_ll(self): + """Linked list for the sections (stores lv_scale_section_t)""" + return int(self._wv.safe_field("section_ll", 0)) + + @property + def mode(self): + """Orientation and layout of scale.""" + return int(self._wv.safe_field("mode", 0)) + + @property + def range_min(self): + """Scale's minimum value""" + return int(self._wv.safe_field("range_min", 0)) + + @property + def range_max(self): + """Scale's maximum value""" + return int(self._wv.safe_field("range_max", 0)) + + @property + def total_tick_count(self): + """Total number of ticks (major and minor)""" + return int(self._wv.safe_field("total_tick_count", 0)) + + @property + def major_tick_every(self): + """Frequency of major ticks to minor ticks""" + return int(self._wv.safe_field("major_tick_every", 0)) + + @property + def label_enabled(self): + """Draw labels for major ticks?""" + return int(self._wv.safe_field("label_enabled", 0)) + + @property + def post_draw(self): + return int(self._wv.safe_field("post_draw", 0)) + + @property + def draw_ticks_on_top(self): + """Draw ticks on top of main line?""" + return int(self._wv.safe_field("draw_ticks_on_top", 0)) + + @property + def angle_range(self): + """Degrees between low end and high end of scale""" + return int(self._wv.safe_field("angle_range", 0)) + + @property + def rotation(self): + """Clockwise angular offset from 3-o'clock position of low end of scale""" + return int(self._wv.safe_field("rotation", 0)) + + @property + def custom_label_cnt(self): + """Number of custom labels provided in `txt_src`""" + return int(self._wv.safe_field("custom_label_cnt", 0)) + + @property + def last_tick_width(self): + """Width of last tick in pixels""" + return int(self._wv.safe_field("last_tick_width", 0)) + + @property + def first_tick_width(self): + """Width of first tick in pixels""" + return int(self._wv.safe_field("first_tick_width", 0)) + + @property + def needles(self): + """Needle list of this scale""" + return int(self._wv.safe_field("needles", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["section_ll"] = self.section_ll + d["mode"] = self.mode + d["range_min"] = self.range_min + d["range_max"] = self.range_max + d["total_tick_count"] = self.total_tick_count + d["major_tick_every"] = self.major_tick_every + d["label_enabled"] = self.label_enabled + d["post_draw"] = self.post_draw + d["draw_ticks_on_top"] = self.draw_ticks_on_top + d["angle_range"] = self.angle_range + d["rotation"] = self.rotation + d["custom_label_cnt"] = self.custom_label_cnt + d["last_tick_width"] = self.last_tick_width + d["first_tick_width"] = self.first_tick_width + d["needles"] = self.needles + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_slider.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_slider.py new file mode 100644 index 0000000000..721c494947 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_slider.py @@ -0,0 +1,57 @@ +""" +Auto-generated wrapper for lv_slider_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from .lv_bar import LVBar +from ._helpers import ptr_or_none, safe_area, safe_point + + +class LVSlider(LVBar): + """LVGL slider widget (lv_slider_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_slider_t", ptr=True) + + @property + def left_knob_area(self): + return safe_area(self._wv, "left_knob_area") + + @property + def right_knob_area(self): + return safe_area(self._wv, "right_knob_area") + + @property + def pressed_point(self): + return safe_point(self._wv, "pressed_point") + + @property + def value_to_set(self): + """Which bar value to set""" + return ptr_or_none(self._wv.safe_field("value_to_set")) + + @property + def dragging(self): + """1: the slider is being dragged""" + return int(self._wv.safe_field("dragging", 0)) + + @property + def left_knob_focus(self): + """1: with encoder now the right knob can be adjusted""" + return int(self._wv.safe_field("left_knob_focus", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["left_knob_area"] = self.left_knob_area + d["right_knob_area"] = self.right_knob_area + d["pressed_point"] = self.pressed_point + d["value_to_set"] = self.value_to_set + d["dragging"] = self.dragging + d["left_knob_focus"] = self.left_knob_focus + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_spangroup.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_spangroup.py new file mode 100644 index 0000000000..0f3d1e8d8c --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_spangroup.py @@ -0,0 +1,63 @@ +""" +Auto-generated wrapper for lv_spangroup_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVSpangroup(LVObject): + """LVGL span widget (lv_spangroup_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_spangroup_t", ptr=True) + + @property + def lines(self): + return int(self._wv.safe_field("lines", 0)) + + @property + def indent(self): + """first line indent""" + return int(self._wv.safe_field("indent", 0)) + + @property + def cache_w(self): + """the cache automatically calculates the width""" + return int(self._wv.safe_field("cache_w", 0)) + + @property + def cache_h(self): + """similar cache_w""" + return int(self._wv.safe_field("cache_h", 0)) + + @property + def child_ll(self): + return int(self._wv.safe_field("child_ll", 0)) + + @property + def overflow(self): + """details see lv_span_overflow_t""" + return int(self._wv.safe_field("overflow", 0)) + + @property + def refresh(self): + """the spangroup need refresh cache_w and cache_h""" + return int(self._wv.safe_field("refresh", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["lines"] = self.lines + d["indent"] = self.indent + d["cache_w"] = self.cache_w + d["cache_h"] = self.cache_h + d["child_ll"] = self.child_ll + d["overflow"] = self.overflow + d["refresh"] = self.refresh + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_spinbox.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_spinbox.py new file mode 100644 index 0000000000..7b7b8ae44b --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_spinbox.py @@ -0,0 +1,66 @@ +""" +Auto-generated wrapper for lv_spinbox_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from .lv_textarea import LVTextarea + + +class LVSpinbox(LVTextarea): + """LVGL spinbox widget (lv_spinbox_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_spinbox_t", ptr=True) + + @property + def value(self): + return int(self._wv.safe_field("value", 0)) + + @property + def range_max(self): + return int(self._wv.safe_field("range_max", 0)) + + @property + def range_min(self): + return int(self._wv.safe_field("range_min", 0)) + + @property + def step(self): + return int(self._wv.safe_field("step", 0)) + + @property + def digit_count(self): + return int(self._wv.safe_field("digit_count", 0)) + + @property + def dec_point_pos(self): + """if 0, there is no separator and the number is an integer""" + return int(self._wv.safe_field("dec_point_pos", 0)) + + @property + def rollover(self): + """Set to true for rollover functionality""" + return int(self._wv.safe_field("rollover", 0)) + + @property + def digit_step_dir(self): + """the direction the digit will step on encoder button press when editing""" + return int(self._wv.safe_field("digit_step_dir", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["value"] = self.value + d["range_max"] = self.range_max + d["range_min"] = self.range_min + d["step"] = self.step + d["digit_count"] = self.digit_count + d["dec_point_pos"] = self.dec_point_pos + d["rollover"] = self.rollover + d["digit_step_dir"] = self.digit_step_dir + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_spinner.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_spinner.py new file mode 100644 index 0000000000..56cb197e0b --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_spinner.py @@ -0,0 +1,35 @@ +""" +Auto-generated wrapper for lv_spinner_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from .lv_arc import LVArc + + +class LVSpinner(LVArc): + """LVGL spinner widget (lv_spinner_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_spinner_t", ptr=True) + + @property + def duration(self): + """Anim duration in ms""" + return int(self._wv.safe_field("duration", 0)) + + @property + def angle(self): + """Anim angle in degrees""" + return int(self._wv.safe_field("angle", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["duration"] = self.duration + d["angle"] = self.angle + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_switch.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_switch.py new file mode 100644 index 0000000000..a6594f4720 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_switch.py @@ -0,0 +1,34 @@ +""" +Auto-generated wrapper for lv_switch_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVSwitch(LVObject): + """LVGL switch widget (lv_switch_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_switch_t", ptr=True) + + @property + def anim_state(self): + return int(self._wv.safe_field("anim_state", 0)) + + @property + def orientation(self): + """Orientation of switch""" + return int(self._wv.safe_field("orientation", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["anim_state"] = self.anim_state + d["orientation"] = self.orientation + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_table.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_table.py new file mode 100644 index 0000000000..81cc5de18a --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_table.py @@ -0,0 +1,54 @@ +""" +Auto-generated wrapper for lv_table_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none + + +class LVTable(LVObject): + """LVGL table widget (lv_table_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_table_t", ptr=True) + + @property + def col_cnt(self): + return int(self._wv.safe_field("col_cnt", 0)) + + @property + def row_cnt(self): + return int(self._wv.safe_field("row_cnt", 0)) + + @property + def row_h(self): + return ptr_or_none(self._wv.safe_field("row_h")) + + @property + def col_w(self): + return ptr_or_none(self._wv.safe_field("col_w")) + + @property + def col_act(self): + return int(self._wv.safe_field("col_act", 0)) + + @property + def row_act(self): + return int(self._wv.safe_field("row_act", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["col_cnt"] = self.col_cnt + d["row_cnt"] = self.row_cnt + d["row_h"] = self.row_h + d["col_w"] = self.col_w + d["col_act"] = self.col_act + d["row_act"] = self.row_act + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_tabview.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_tabview.py new file mode 100644 index 0000000000..5447f24f57 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_tabview.py @@ -0,0 +1,38 @@ +""" +Auto-generated wrapper for lv_tabview_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVTabview(LVObject): + """LVGL tabview widget (lv_tabview_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_tabview_t", ptr=True) + + @property + def tab_cur(self): + return int(self._wv.safe_field("tab_cur", 0)) + + @property + def tab_pos(self): + return int(self._wv.safe_field("tab_pos", 0)) + + @property + def tab_bar_size(self): + return int(self._wv.safe_field("tab_bar_size", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["tab_cur"] = self.tab_cur + d["tab_pos"] = self.tab_pos + d["tab_bar_size"] = self.tab_bar_size + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_textarea.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_textarea.py new file mode 100644 index 0000000000..62ef4857ab --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_textarea.py @@ -0,0 +1,66 @@ +""" +Auto-generated wrapper for lv_textarea_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none, safe_string + + +class LVTextarea(LVObject): + """LVGL textarea widget (lv_textarea_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_textarea_t", ptr=True) + + @property + def label(self): + """Label of the text area""" + return ptr_or_none(self._wv.safe_field("label")) + + @property + def placeholder_txt(self): + """Place holder label. only visible if text is an empty string""" + return safe_string(self._wv, "placeholder_txt") + + @property + def pwd_tmp(self): + """Used to store the original text in password mode""" + return safe_string(self._wv, "pwd_tmp") + + @property + def pwd_bullet(self): + """Replacement characters displayed in password mode""" + return safe_string(self._wv, "pwd_bullet") + + @property + def accepted_chars(self): + """Only these characters will be accepted. NULL: accept all""" + return safe_string(self._wv, "accepted_chars") + + @property + def max_length(self): + """The max. number of characters. 0: no limit""" + return int(self._wv.safe_field("max_length", 0)) + + @property + def pwd_show_time(self): + """Time to show characters in password mode before change them to '*'""" + return int(self._wv.safe_field("pwd_show_time", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["label"] = self.label + d["placeholder_txt"] = self.placeholder_txt + d["pwd_tmp"] = self.pwd_tmp + d["pwd_bullet"] = self.pwd_bullet + d["accepted_chars"] = self.accepted_chars + d["max_length"] = self.max_length + d["pwd_show_time"] = self.pwd_show_time + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_tileview.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_tileview.py new file mode 100644 index 0000000000..8cbaa32d16 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_tileview.py @@ -0,0 +1,29 @@ +""" +Auto-generated wrapper for lv_tileview_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject +from ._helpers import ptr_or_none + + +class LVTileview(LVObject): + """LVGL tileview widget (lv_tileview_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_tileview_t", ptr=True) + + @property + def tile_act(self): + return ptr_or_none(self._wv.safe_field("tile_act")) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["tile_act"] = self.tile_act + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_tileview_tile.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_tileview_tile.py new file mode 100644 index 0000000000..69ffc948ee --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_tileview_tile.py @@ -0,0 +1,28 @@ +""" +Auto-generated wrapper for lv_tileview_tile_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVTileviewTile(LVObject): + """LVGL tileview widget (lv_tileview_tile_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_tileview_tile_t", ptr=True) + + @property + def dir(self): + return int(self._wv.safe_field("dir", 0)) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + d = s.get('widget_data') or {} + d["dir"] = self.dir + s['widget_data'] = d + return s diff --git a/scripts/gdb/lvglgdb/lvgl/widgets/lv_win.py b/scripts/gdb/lvglgdb/lvgl/widgets/lv_win.py new file mode 100644 index 0000000000..ff58c0c66f --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/widgets/lv_win.py @@ -0,0 +1,21 @@ +""" +Auto-generated wrapper for lv_win_t. + +Do not edit manually. Regenerate from the GDB script root with: + python3 scripts/generate_all.py +""" + +from lvglgdb.lvgl.core.lv_obj import LVObject + + +class LVWin(LVObject): + """LVGL win widget (lv_win_t).""" + + def __init__(self, obj): + super().__init__(obj) + self._wv = self.cast("lv_win_t", ptr=True) + + def snapshot(self, include_children=False, include_styles=False): + """Snapshot with widget-specific fields in widget_data.""" + s = super().snapshot(include_children=include_children, include_styles=include_styles) + return s diff --git a/scripts/gdb/scripts/generators/gen_widget_wrappers.py b/scripts/gdb/scripts/generators/gen_widget_wrappers.py new file mode 100644 index 0000000000..e23759a512 --- /dev/null +++ b/scripts/gdb/scripts/generators/gen_widget_wrappers.py @@ -0,0 +1,431 @@ +#!/usr/bin/env python3 +""" +Generate widget wrapper classes from LVGL widget _private.h headers. + +Each widget gets its own Python file under lvglgdb/lvgl/widgets/, +with a class inheriting from LVObject (or its parent widget wrapper). + +Output structure: + lvglgdb/lvgl/widgets/ + __init__.py ← re-exports + WIDGET_REGISTRY + wrap_widget() + _helpers.py ← shared field-reading helpers + lv_label.py ← class LVLabel(LVObject) + lv_slider.py ← class LVSlider(LVBar) + ... + +Usage (from the GDB script root): + python3 scripts/generators/gen_widget_wrappers.py +""" + +import re +import sys +from pathlib import Path +from dataclasses import dataclass, field as dc_field + +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) + +LVGL_SRC = Path(__file__).parent.parent.parent.parent.parent / "src" +WIDGETS_DIR = LVGL_SRC / "widgets" +OUTPUT_DIR = Path(__file__).parent.parent.parent / "lvglgdb" / "lvgl" / "widgets" + +SIMPLE_INT_TYPES = { + "int8_t", "int16_t", "int32_t", "int64_t", + "uint8_t", "uint16_t", "uint32_t", "uint64_t", + "int", "bool", "size_t", + "lv_value_precise_t", +} + + +@dataclass +class StructField: + name: str + c_type: str + is_bitfield: bool = False + bitfield_width: int = 0 + is_pointer: bool = False + is_obj_pointer: bool = False + is_string: bool = False + is_array: bool = False + comment: str = "" + + +@dataclass +class WidgetDef: + struct_name: str + c_type: str + parent_type: str + fields: list[StructField] = dc_field(default_factory=list) + widget_dir: str = "" + + @property + def class_name(self) -> str: + inner = self.c_type.removeprefix("lv_").removesuffix("_t") + return "LV" + "".join(w.capitalize() for w in inner.split("_")) + + @property + def parent_class_name(self) -> str: + if self.parent_type == "lv_obj_t": + return "LVObject" + inner = self.parent_type.removeprefix("lv_").removesuffix("_t") + return "LV" + "".join(w.capitalize() for w in inner.split("_")) + + @property + def module_name(self) -> str: + """Python module filename without .py, e.g. 'lv_label'.""" + return self.c_type.removesuffix("_t") + + @property + def c_class_name(self) -> str: + """C class name for registry, e.g. 'lv_label'.""" + return self.c_type.removesuffix("_t") + + +def parse_struct_fields(body: str) -> list[StructField]: + fields = [] + depth = 0 + clean_lines = [] + for line in body.splitlines(): + stripped = line.strip() + if re.match(r"(struct|union)\s*\{", stripped): + depth += 1 + continue + if stripped.startswith("}") and depth > 0: + depth -= 1 + continue + if depth > 0: + continue + clean_lines.append(stripped) + + for line in clean_lines: + line = line.rstrip(";").strip() + if not line or line.startswith("/*") or line.startswith("//") or line.startswith("*") or line.startswith("#"): + continue + + comment = "" + cm = re.search(r"/\*\*? dict[str, WidgetDef]: + widgets = {} + for private_h in sorted(WIDGETS_DIR.glob("*/lv_*_private.h")): + text = private_h.read_text() + widget_dir = private_h.parent.name + + for m in re.finditer(r"struct\s+_lv_(\w+)_t\s*\{([^}]+)\}", text, re.DOTALL): + struct_name = f"lv_{m.group(1)}_t" + body = m.group(2) + + first_line = "" + for line in body.splitlines(): + line = line.strip() + if line and not line.startswith(("/*", "//", "*", "#")): + first_line = line.rstrip(";").strip() + break + + parent_match = re.match(r"(lv_\w+_t)\s+\w+", first_line) + if not parent_match: + continue + + parent_type = parent_match.group(1) + if parent_type == "lv_obj_t" or parent_type in widgets or parent_type in ( + "lv_bar_t", "lv_image_t", "lv_arc_t", "lv_textarea_t", "lv_buttonmatrix_t", + ): + all_fields = parse_struct_fields(body) + widgets[struct_name] = WidgetDef( + struct_name=struct_name, c_type=struct_name, + parent_type=parent_type, + fields=all_fields[1:] if all_fields else [], + widget_dir=widget_dir, + ) + return widgets + + +def _field_expr(f: StructField) -> str | None: + """Return snapshot expression for a field, or None to skip.""" + if f.is_array: + return None + if f.is_obj_pointer: + return f'ptr_or_none(self._wv.safe_field("{f.name}"))' + if f.is_string: + return f'safe_string(self._wv, "{f.name}")' + if f.is_pointer: + return f'ptr_or_none(self._wv.safe_field("{f.name}"))' + if f.c_type == "lv_color_t": + return f'safe_color(self._wv, "{f.name}")' + if f.c_type == "lv_area_t": + return f'safe_area(self._wv, "{f.name}")' + if f.c_type == "lv_point_t": + return f'safe_point(self._wv, "{f.name}")' + if f.is_bitfield or f.c_type in SIMPLE_INT_TYPES or f.c_type.startswith(("uint", "int")): + return f'int(self._wv.safe_field("{f.name}", 0))' + if f.c_type.startswith("lv_") and f.c_type.endswith("_t"): + return f'int(self._wv.safe_field("{f.name}", 0))' + return None + + +def _topo_sort(widgets: dict[str, WidgetDef]) -> list[WidgetDef]: + result, visited = [], set() + def visit(w): + if w.c_type in visited: + return + visited.add(w.c_type) + if w.parent_type in widgets: + visit(widgets[w.parent_type]) + result.append(w) + for w in widgets.values(): + visit(w) + return result + + +def gen_helpers() -> str: + return '''\ +"""Shared field-reading helpers for widget wrappers. + +All helpers return a safe value (or None) without raising exceptions. +Protection is provided by Value.safe_field() and Value.string(fallback=). +""" + +from lvglgdb.lvgl.data_utils import ptr_or_none # noqa: F401 + + +def safe_string(obj, field_name): + """Read a char* field as string, or None.""" + val = obj.safe_field(field_name) + if val is None or not getattr(val, 'is_ok', True) or not int(val): + return None + return val.string(fallback=None) + + +def safe_color(obj, field_name): + """Read lv_color_t as hex string.""" + val = obj.safe_field(field_name) + if val is None or not getattr(val, 'is_ok', True): + return None + return f"#{int(val):06x}" + + +def safe_area(obj, field_name): + """Read lv_area_t as dict.""" + val = obj.safe_field(field_name) + if val is None or not getattr(val, 'is_ok', True): + return None + return { + "x1": int(val.safe_field("x1", 0)), + "y1": int(val.safe_field("y1", 0)), + "x2": int(val.safe_field("x2", 0)), + "y2": int(val.safe_field("y2", 0)), + } + + +def safe_point(obj, field_name): + """Read lv_point_t as dict.""" + val = obj.safe_field(field_name) + if val is None or not getattr(val, 'is_ok', True): + return None + return { + "x": int(val.safe_field("x", 0)), + "y": int(val.safe_field("y", 0)), + } +''' + + +def gen_widget_file(wdef: WidgetDef, widgets: dict[str, WidgetDef]) -> str: + """Generate a single widget module file.""" + lines = [ + '"""', + f"Auto-generated wrapper for {wdef.c_type}.", + "", + "Do not edit manually. Regenerate from the GDB script root with:", + " python3 scripts/generate_all.py", + '"""', + "", + ] + + # Import parent + if wdef.parent_type == "lv_obj_t": + lines.append("from lvglgdb.lvgl.core.lv_obj import LVObject") + else: + parent_def = widgets[wdef.parent_type] + lines.append(f"from .{parent_def.module_name} import {parent_def.class_name}") + + # Import helpers only if needed + needs = set() + for f in wdef.fields: + expr = _field_expr(f) + if expr is None: + continue + if "ptr_or_none" in expr: + needs.add("ptr_or_none") + if "safe_string" in expr: + needs.add("safe_string") + if "safe_color" in expr: + needs.add("safe_color") + if "safe_area" in expr: + needs.add("safe_area") + if "safe_point" in expr: + needs.add("safe_point") + + if needs: + imports = ", ".join(sorted(needs)) + lines.append(f"from ._helpers import {imports}") + + lines.append("") + lines.append("") + + parent_cls = wdef.parent_class_name + lines.append(f"class {wdef.class_name}({parent_cls}):") + lines.append(f' """LVGL {wdef.widget_dir} widget ({wdef.c_type})."""') + lines.append("") + lines.append(f" def __init__(self, obj):") + lines.append(f" super().__init__(obj)") + lines.append(f' self._wv = self.cast("{wdef.c_type}", ptr=True)') + lines.append("") + + # Properties + snapshot_fields = [] + for f in wdef.fields: + expr = _field_expr(f) + if expr is None: + continue + lines.append(f" @property") + lines.append(f" def {f.name}(self):") + if f.comment: + lines.append(f' """{f.comment}"""') + lines.append(f" return {expr}") + lines.append("") + snapshot_fields.append(f.name) + + # snapshot — override to include widget-specific fields in widget_data + lines.append(f" def snapshot(self, include_children=False, include_styles=False):") + lines.append(f' """Snapshot with widget-specific fields in widget_data."""') + lines.append(f" s = super().snapshot(include_children=include_children, include_styles=include_styles)") + + if snapshot_fields: + lines.append(f" d = s.get('widget_data') or {{}}") + for fname in snapshot_fields: + lines.append(f' d["{fname}"] = self.{fname}') + lines.append(f" s['widget_data'] = d") + + lines.append(f" return s") + lines.append("") + + return "\n".join(lines) + + +def gen_init(ordered: list[WidgetDef]) -> str: + """Generate __init__.py with imports, registry, and wrap_widget().""" + lines = [ + '"""', + "Auto-generated LVGL widget wrappers.", + "", + "Do not edit manually. Regenerate from the GDB script root with:", + " python3 scripts/generate_all.py", + '"""', + "", + ] + + # Imports + for w in ordered: + lines.append(f"from .{w.module_name} import {w.class_name}") + lines.append("") + + # Registry + lines.append("WIDGET_REGISTRY: dict[str, type] = {") + for w in ordered: + lines.append(f' "{w.c_class_name}": {w.class_name},') + lines.append("}") + lines.append("") + lines.append("") + + # wrap_widget + lines.append("import gdb") + lines.append("") + lines.append("") + lines.append("def wrap_widget(obj):") + lines.append(' """Wrap an LVObject into its widget class if known."""') + lines.append(" cls = WIDGET_REGISTRY.get(obj.class_name)") + lines.append(" if cls:") + lines.append(" try:") + lines.append(" return cls(obj)") + lines.append(" except gdb.error:") + lines.append(" pass # type not available in debug info") + lines.append(" return None") + lines.append("") + + # __all__ + names = [w.class_name for w in ordered] + lines.append("__all__ = [") + for n in names: + lines.append(f' "{n}",') + lines.append(' "WIDGET_REGISTRY",') + lines.append(' "wrap_widget",') + lines.append("]") + lines.append("") + + return "\n".join(lines) + + +def main(): + widgets = parse_widgets() + ordered = _topo_sort(widgets) + print(f"Parsed {len(widgets)} widget types") + + for w in ordered: + print(f" {w.module_name}.py: {w.class_name}({w.parent_class_name}) — {len(w.fields)} fields") + + OUTPUT_DIR.mkdir(parents=True, exist_ok=True) + + # _helpers.py + (OUTPUT_DIR / "_helpers.py").write_text(gen_helpers()) + + # Per-widget files + for w in ordered: + src = gen_widget_file(w, widgets) + (OUTPUT_DIR / f"{w.module_name}.py").write_text(src) + + # __init__.py + (OUTPUT_DIR / "__init__.py").write_text(gen_init(ordered)) + + print(f"\nGenerated {len(ordered) + 2} files in {OUTPUT_DIR}/") + + +if __name__ == "__main__": + main()