Skip to content

Commit 6e0d737

Browse files
committed
Loading indicator is now a context manager
1 parent a3e2ea3 commit 6e0d737

5 files changed

Lines changed: 51 additions & 68 deletions

File tree

hkb_editor/gui/beh_editor.py

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
from .widgets.graph_widget import GraphWidget, HorizontalGraphLayout, Node
5454
from .widgets.attributes_widget import AttributesWidget
5555
from .widgets.graphmap import GraphMap # TODO
56+
from .widgets import loading_indicator
5657
from .dialogs import (
5758
about_dialog,
5859
open_file_dialog,
@@ -81,7 +82,7 @@
8182
from .workflows.duplicate_clipcat import duplicate_clipcat_dialog
8283
from .workflows.fix_common_problems import fix_common_problems_dialog
8384
from .workflows.verify_behavior import verify_behavior
84-
from .helpers import make_copy_menu, center_window, common_loading_indicator
85+
from .helpers import make_copy_menu, center_window
8586
from . import style
8687

8788

@@ -104,7 +105,6 @@ def emit(this, record):
104105
logging.root.addHandler(LogHandler())
105106

106107
self.beh: HavokBehavior = None
107-
self._busy = False
108108
self.alias_manager = AliasManager()
109109
self.attributes_widget: AttributesWidget = None
110110
self.pinned_objects_table: str = None
@@ -300,21 +300,12 @@ def file_save_as(self) -> bool:
300300
return False
301301

302302
def _do_write_to_file(self, file_path):
303-
if self._busy:
304-
return
305-
306-
self._busy = True
307-
loading = common_loading_indicator("Saving")
308-
309-
try:
303+
with loading_indicator("Saving"):
310304
if self.config.save_backups:
311305
shutil.copy(self.beh.file, self.beh.file + ".backup")
312306

313307
self.beh.save_to_file(file_path)
314308
self.logger.info(f"Saved to {file_path}")
315-
finally:
316-
dpg.delete_item(loading)
317-
self._busy = False
318309

319310
def _locate_witchy(self) -> str:
320311
if not self.config.witchy_exe or not os.path.isfile(self.config.witchy_exe):
@@ -343,14 +334,8 @@ def _locate_hklib(self) -> str:
343334
return self.config.hklib_exe
344335

345336
def _reload_character(self) -> None:
346-
if self._busy:
347-
return
348-
349-
self._busy = True
350337
chr = self.beh.get_character_id()
351-
loading = common_loading_indicator(f"Reloading {chr}...")
352-
353-
try:
338+
with loading_indicator(f"Reloading {chr}..."):
354339
if not self.chr_reloader:
355340
if ChrReloader:
356341
game_config = detect_game_config()
@@ -359,33 +344,20 @@ def _reload_character(self) -> None:
359344
raise RuntimeError("ChrReloader is not available")
360345

361346
self.chr_reloader.reload_character(chr)
362-
finally:
363-
dpg.delete_item(loading)
364-
self._busy = False
365347

366348
def _repack_binder(self) -> None:
367-
if self._busy:
368-
return
369-
370-
self._busy = True
371-
372349
# Locate external tools
373350
self._locate_witchy()
374351
self._locate_hklib()
375352

376-
loading = common_loading_indicator("Repacking binder...")
377-
378-
try:
353+
with loading_indicator("Repacking binder..."):
379354
self.logger.info("Saving XML...")
380355
self.file_save()
381356
self.logger.info("Converting XML to HKX...")
382357
xml_to_hkx(self.beh.file)
383358
self.logger.info("Repacking Binder...")
384359
pack_binder(self.beh.file)
385360
self.logger.info("Done!")
386-
finally:
387-
dpg.delete_item(loading)
388-
self._busy = False
389361

390362
def exit_app(self):
391363
if not self.beh or self.beh.top_undo_id() == self.last_save_undo_id:
@@ -2217,19 +2189,10 @@ def open_mirror_skeleton_dialog(self):
22172189
skeleton_mirror_dialog(self.loaded_skeleton_path, tag=tag)
22182190

22192191
def verify_behavior(self):
2220-
if self._busy:
2221-
return
2222-
2223-
self._busy = True
2224-
loading = common_loading_indicator("Validating behavior...")
2225-
2226-
try:
2192+
with loading_indicator("Validating behavior...")
22272193
verify_behavior(self.beh)
22282194
# TODO summary dialog?
22292195
logging.info("Validation complete, check log for results!")
2230-
finally:
2231-
dpg.delete_item(loading)
2232-
self._busy = False
22332196

22342197
def open_apply_template_dialog(self, template_file: str):
22352198
tag = f"{self.tag}_apply_template_dialog"

hkb_editor/gui/widgets/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from .attributes_widget import AttributesWidget
22
from .graph_widget import GraphWidget
3+
from .loading_indicator import loading_indicator
34
from .multilist import add_multilist
45
from .rotation_knob import RotationKnob
56
from .editable_table import add_widget_table, add_simple_items_table, add_filepaths_table
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from typing import Generator
2+
from contextlib import contextmanager
3+
from dearpygui import dearpygui as dpg
4+
5+
from hkb_editor.gui import style
6+
7+
8+
@contextmanager
9+
def loading_indicator(
10+
label: str, color: style.RGBA = style.red
11+
) -> Generator[str, None, None]:
12+
try:
13+
dpg.split_frame()
14+
15+
with dpg.window(
16+
modal=True,
17+
min_size=(50, 20),
18+
no_close=True,
19+
no_move=True,
20+
no_collapse=True,
21+
no_title_bar=True,
22+
no_resize=True,
23+
no_scroll_with_mouse=True,
24+
no_scrollbar=True,
25+
no_saved_settings=True,
26+
) as dialog:
27+
with dpg.group(horizontal=True):
28+
dpg.add_loading_indicator(color=color)
29+
with dpg.group():
30+
dpg.add_spacer(height=5)
31+
dpg.add_text(label, tag=f"{dialog}_label")
32+
33+
yield dialog
34+
finally:
35+
if dpg.does_item_exist(dialog):
36+
dpg.delete_item(dialog)

hkb_editor/gui/workflows/clone_hierarchy.py

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Callable, Generic, TypeVar
1+
from typing import Callable, Generic, TypeVar
22
import logging
33
from dataclasses import dataclass, field
44
import re
@@ -12,7 +12,6 @@
1212
from hkb_editor.hkb.xml import (
1313
xml_from_str,
1414
add_type_comments,
15-
make_element,
1615
make_subelement,
1716
)
1817
from hkb_editor.hkb.behavior import HavokBehavior, HkbVariable
@@ -25,7 +24,8 @@
2524
from hkb_editor.hkb import HkbPointer, HkbRecord, HkbArray, XmlValueHandler
2625
from hkb_editor.hkb.type_registry import TypeMismatch
2726
from hkb_editor.gui import style
28-
from hkb_editor.gui.helpers import common_loading_indicator, add_paragraphs
27+
from hkb_editor.gui.widgets import loading_indicator
28+
from hkb_editor.gui.helpers import add_paragraphs
2929

3030

3131
T = TypeVar("T")
@@ -352,11 +352,8 @@ def paste_hierarchy(
352352
f"Could not map object type {root_type} ({root_type_name}) to a known type ID"
353353
)
354354

355-
loading = common_loading_indicator("Analyzing hierarchy")
356-
try:
355+
with loading_indicator("Analyzing hierarchy"):
357356
results = find_conflicts(behavior, xmldoc, target_record)
358-
finally:
359-
dpg.delete_item(loading)
360357

361358
def add_objects():
362359
new_root: HkbRecord = results.objects[results.root_id].result
@@ -462,12 +459,9 @@ def add_children():
462459
raise ValueError("Not a valid behavior hierarchy")
463460

464461
# Search for conflicts
465-
loading = common_loading_indicator("Analyzing hierarchy")
466-
try:
462+
with loading_indicator("Analyzing hierarchy"):
467463
results = find_conflicts(behavior, xmldoc, target_record)
468464
results.objects[results.root_id].action = MergeAction.IGNORE
469-
finally:
470-
dpg.delete_item(loading)
471465

472466
# Let the user decide what to transfer, or just transfer everything
473467
if interactive:
@@ -1028,15 +1022,11 @@ def update_action(sender: str, action: str, resolution: Resolution):
10281022
resolution.action = MergeAction[action]
10291023

10301024
def resolve():
1031-
loading = common_loading_indicator("Merging Hierarchy")
1032-
try:
1025+
with loading_indicator("Merging Hierarchy"):
10331026
with behavior.transaction():
10341027
resolve_conflicts(behavior, target_record, results)
10351028
results.pin_objects = dpg.get_value(f"{tag}_pin_objects")
10361029
callback()
1037-
finally:
1038-
dpg.delete_item(loading)
1039-
close()
10401030

10411031
def close():
10421032
if graph_preview:

hkb_editor/gui/workflows/fix_common_problems.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
from hkb_editor.hkb import HavokBehavior, HkbArray, HkbPointer
66
from hkb_editor.templates.common import Animation
7+
from hkb_editor.gui.widgets import loading_indicator
78
from hkb_editor.gui.helpers import (
89
center_window,
910
add_paragraphs,
10-
common_loading_indicator,
1111
)
1212
from hkb_editor.gui import style
1313

@@ -116,9 +116,7 @@ def show_message(msg: str = None, color: style.RGBA = style.red) -> None:
116116

117117
def on_okay():
118118
show_message()
119-
loading = common_loading_indicator("Fixing")
120-
121-
try:
119+
with loading_indicator("Fixing"):
122120
with behavior.transaction():
123121
fixes = 0
124122
if dpg.get_value(f"{tag}_array_null_pointers"):
@@ -139,11 +137,6 @@ def on_okay():
139137

140138
if callback:
141139
callback(tag, fixes, user_data)
142-
except Exception:
143-
show_message("Error fixing behavior, check terminal!")
144-
raise
145-
finally:
146-
dpg.delete_item(loading)
147140

148141
# Dialog content
149142
with dpg.window(

0 commit comments

Comments
 (0)