Skip to content
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,13 @@
"**/__pycache__": true,
"*.egg-info": true,
".pytest_cache": true
},
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit",
"source.organizeImports": "explicit"
},
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
29 changes: 24 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
# Changelog

## [UNRELEASED]
- Updated construct-typing dependency to v0.8.1+ and updated the DataClass definitions to reflect the breaking changes.
- Bumped minimum required Python version to 3.10 (previously: 3.8 which has reached end-of-life).
- Updated `typing_extensions` dependency to >=4.12.0 for Python 3.13 compatibility.
- Removed `version.py`, use `importlib.metadata` instead to get the version number.
- Fixed a bug where multiple instances of `WxConstructHexEditor` might share the same default dict, leading to potentially unexpected behavior.
**Breaking changes:**
- Updated construct-typing dependency to v0.8.1+ and updated the DataClass definitions to reflect the breaking changes. ([#43](https://github.com/timrid/construct-editor/pull/43), [#42](https://github.com/timrid/construct-editor/pull/42))
- Bumped minimum required Python version to 3.10 (previously: 3.8 which has reached end-of-life). ([#39](https://github.com/timrid/construct-editor/pull/39))
- Removed `version.py`, use `importlib.metadata` instead to get the version number. ([#39](https://github.com/timrid/construct-editor/pull/39))

**New features:**
- Optimized Tooltip handling when hovering over a construct in the ConstructEditor. The text is now selectable in the hover tooltip and the tooltip does not automatically disappear after 5s on Windows. ([#46](https://github.com/timrid/construct-editor/pull/46))

**Changes:**
- Updated `wxPython` dependency to >=4.2.2. ([#39](https://github.com/timrid/construct-editor/pull/39))
- Updated `typing_extensions` dependency to >=4.12.0 for Python 3.13 compatibility. ([#39](https://github.com/timrid/construct-editor/pull/39))
- Updated `wrapt` dependency to >=2.2.2 for better typing support. ([#40](https://github.com/timrid/construct-editor/pull/40))
- Fix many typing related issues. ([#42](https://github.com/timrid/construct-editor/pull/42), [#44](https://github.com/timrid/construct-editor/pull/44))

**Bugfixes:**
- Fixed a bug where multiple instances of `WxConstructHexEditor` might share the same default dict, leading to potentially unexpected behavior. ([#42](https://github.com/timrid/construct-editor/pull/42))

**Organizational changes:**
- Switch from `setup.py` to `pyproject.toml`. ([#39](https://github.com/timrid/construct-editor/pull/39))
- Use `uv` as a project management tool and `poe` as a task runner. ([#39](https://github.com/timrid/construct-editor/pull/39))
- Add `pyright`, `ty` and `mypy` for static type checking. ([#39](https://github.com/timrid/construct-editor/pull/39), [#41](https://github.com/timrid/construct-editor/pull/41))
- Add `ruff` for linting. ([#39](https://github.com/timrid/construct-editor/pull/39))
- Add basic unit and integration tests with `pytest`. ([#40](https://github.com/timrid/construct-editor/pull/40))
- Add a CI Pipeline to perform linting, static type checking and unit/integration testing. ([#40](https://github.com/timrid/construct-editor/pull/40))

-------------------------------------------------------------------------------

Expand Down
68 changes: 36 additions & 32 deletions construct_editor/wx_widgets/wx_construct_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from construct_editor.core.model import ConstructEditorColumn, ConstructEditorModel
from construct_editor.wx_widgets.wx_context_menu import WxContextMenu
from construct_editor.wx_widgets.wx_exception_dialog import WxExceptionDialog
from construct_editor.wx_widgets.wx_hover_tooltip import WxHoverToolTip
from construct_editor.wx_widgets.wx_obj_view import (
WxObjEditor,
WxObjRendererHelper,
Expand Down Expand Up @@ -42,9 +43,7 @@ def __init__(self):

def SetValue(self, value: EntryConstruct):
self.entry = value
self.entry_renderer_helper = create_obj_renderer_helper(
self.entry.obj_view_settings
)
self.entry_renderer_helper = create_obj_renderer_helper(self.entry.obj_view_settings)
return True

def GetValue(self):
Expand Down Expand Up @@ -111,9 +110,7 @@ def ActivateCell(
) -> bool:
if self.entry_renderer_helper is None:
raise ValueError("`entry_renderer_helper` not set")
return self.entry_renderer_helper.activate_cell(
self, cell, model, item, col, mouseEvent
)
return self.entry_renderer_helper.activate_cell(self, cell, model, item, col, mouseEvent)

# The HasEditorCtrl, CreateEditorCtrl and GetValueFromEditorCtrl
# methods need to be implemented if this renderer is going to
Expand All @@ -123,9 +120,7 @@ def ActivateCell(
def HasEditorCtrl(self):
return True

def CreateEditorCtrl(
self, parent, labelRect: wx.Rect, value: EntryConstruct
) -> WxObjEditor:
def CreateEditorCtrl(self, parent, labelRect: wx.Rect, value: EntryConstruct) -> WxObjEditor:
view_settings = value.obj_view_settings
editor: WxObjEditor = create_obj_editor(parent, view_settings)
editor.SetPosition(labelRect.GetPosition())
Expand Down Expand Up @@ -308,18 +303,14 @@ def _init_gui(self):
self._parse_error_info_bar = wx.InfoBar(self)
btn_id = wx.NewIdRef()
self._parse_error_info_bar.AddButton(btn_id, "Exception Infos")
self._parse_error_info_bar.Bind(
wx.EVT_BUTTON, self._parse_error_info_bar_btn_clicked, id=btn_id
)
self._parse_error_info_bar.Bind(wx.EVT_BUTTON, self._parse_error_info_bar_btn_clicked, id=btn_id)
self._parse_error_ex: Exception | None = None
vsizer.Add(self._parse_error_info_bar, 0, wx.EXPAND)

self._build_error_info_bar = wx.InfoBar(self)
btn_id = wx.NewIdRef()
self._build_error_info_bar.AddButton(btn_id, "Exception Infos")
self._build_error_info_bar.Bind(
wx.EVT_BUTTON, self._build_error_info_bar_btn_clicked, id=btn_id
)
self._build_error_info_bar.Bind(wx.EVT_BUTTON, self._build_error_info_bar_btn_clicked, id=btn_id)
self._build_error_ex: Exception | None = None
vsizer.Add(self._build_error_info_bar, 0, wx.EXPAND)

Expand All @@ -329,9 +320,7 @@ def _init_gui(self):
style=wx.STB_SHOW_TIPS | wx.STB_ELLIPSIZE_END | wx.FULL_REPAINT_ON_RESIZE,
)
self._status_bar.SetFieldsCount(2)
self._status_bar.SetStatusStyles(
[wx.SB_NORMAL, wx.SB_FLAT]
) # remove vertical line after the last field
self._status_bar.SetStatusStyles([wx.SB_NORMAL, wx.SB_FLAT]) # remove vertical line after the last field
self._status_bar.SetStatusWidths([-2, -1])
vsizer.Add(self._status_bar, 0, wx.ALL | wx.EXPAND, 0)

Expand All @@ -353,7 +342,9 @@ def _init_gui(self):
self._dvc_main_window.Bind(wx.EVT_MOTION, self._on_dvc_motion)
self._dvc_main_window.Bind(wx.EVT_KEY_DOWN, self._on_dvc_key_down)
self._dvc_main_window.Bind(wx.EVT_CHAR, self._on_dvc_char)
self._last_tooltip: t.Tuple[EntryConstruct, ConstructEditorColumn] | None = None
self._dvc_main_window.Bind(wx.EVT_SCROLLWIN, self._on_dvc_scroll)
self._dvc_main_window.Bind(wx.EVT_MOUSEWHEEL, self._on_dvc_scroll)
self._hover_tooltip = WxHoverToolTip(self._dvc_main_window)

def reload(self):
"""
Expand All @@ -362,6 +353,8 @@ def reload(self):
try:
self.Freeze()

self._hover_tooltip.hide()

# reload dvc columns
self._reload_dvc_columns()

Expand Down Expand Up @@ -522,6 +515,8 @@ def _on_dvc_selection_changed(self, event):

Then the infos of the new selected entry is shown.
"""
self._hover_tooltip.hide()

item = self._dvc.GetSelection()
if item.ID is not None:
entry = self._model.dvc_item_to_entry(item)
Expand Down Expand Up @@ -551,25 +546,34 @@ def _on_dvc_motion(self, event: wx.MouseEvent):
pos += self._dvc_main_window.GetPosition() # correct the dvc header
item, col = self._dvc.HitTest(pos)
if item.GetID() is None:
self._dvc_main_window.SetToolTip("")
return
Comment thread
timrid marked this conversation as resolved.
entry = self._model.dvc_item_to_entry(item)

if col.ModelColumn == ConstructEditorColumn.Name:
# only set tooltip if the obj changed. this prevents flickering
if self._last_tooltip != (entry, ConstructEditorColumn.Name):
self._dvc_main_window.SetToolTip(
textwrap.dedent(entry.docs or entry.name).strip()
)
self._last_tooltip = (entry, ConstructEditorColumn.Name)
text = textwrap.dedent(entry.docs or entry.name).strip()
elif col.ModelColumn == ConstructEditorColumn.Type:
# only set tooltip if the obj changed. this prevents flickering
if self._last_tooltip != (entry, ConstructEditorColumn.Type):
self._dvc_main_window.SetToolTip(str(entry.construct))
self._last_tooltip = (entry, ConstructEditorColumn.Type)
text = str(entry.construct)
else:
self._dvc_main_window.SetToolTip("")
self._last_tooltip = None
return

if not text:
return

cell_rect: wx.Rect = self._dvc.GetItemRect(item, col)
# `GetItemRect` returns a rect in the same coordinate space as
# `HitTest` above (relative to the whole dvc control, including the
# header) - so convert via `self._dvc`, not `self._dvc_main_window`
# (which would double-count the header offset and shift the
# tooltip down by roughly one row).
anchor_screen_rect = wx.Rect(
self._dvc.ClientToScreen(cell_rect.GetPosition()),
cell_rect.GetSize(),
)
self._hover_tooltip.notify_hover(text, anchor_screen_rect)

def _on_dvc_scroll(self, event):
self._hover_tooltip.hide()
event.Skip()

def _on_dvc_right_clicked(self, event: dv.DataViewEvent):
"""
Expand Down
Loading