app.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import os
  2. import sys
  3. from pathlib import Path
  4. from imgui_bundle import imgui, immapp, hello_imgui
  5. IMGUI_THEMES = {
  6. "dark": hello_imgui.ImGuiTheme_.imgui_colors_dark,
  7. "light": hello_imgui.ImGuiTheme_.imgui_colors_light,
  8. "classic": hello_imgui.ImGuiTheme_.imgui_colors_classic,
  9. "material_flat": hello_imgui.ImGuiTheme_.material_flat,
  10. "photoshop_style": hello_imgui.ImGuiTheme_.photoshop_style,
  11. "gray_variations": hello_imgui.ImGuiTheme_.gray_variations,
  12. "gray_variations_darker": hello_imgui.ImGuiTheme_.gray_variations_darker,
  13. "microsoft_style": hello_imgui.ImGuiTheme_.microsoft_style,
  14. "cherry": hello_imgui.ImGuiTheme_.cherry,
  15. "darcula": hello_imgui.ImGuiTheme_.darcula,
  16. "darcula_darker": hello_imgui.ImGuiTheme_.darcula_darker,
  17. "light_rounded": hello_imgui.ImGuiTheme_.light_rounded,
  18. "so_dark_accent_blue": hello_imgui.ImGuiTheme_.so_dark_accent_blue,
  19. "so_dark_accent_yellow": hello_imgui.ImGuiTheme_.so_dark_accent_yellow,
  20. "so_dark_accent_red": hello_imgui.ImGuiTheme_.so_dark_accent_red,
  21. "black_is_black": hello_imgui.ImGuiTheme_.black_is_black,
  22. "white_is_white": hello_imgui.ImGuiTheme_.white_is_white
  23. }
  24. class App:
  25. def __init__(self, title="New app", width=800, height=600):
  26. """Initialize the application.
  27. Args:
  28. title (str): Window title.
  29. width (int): Window width.
  30. height (int): Window height.
  31. """
  32. self.title = title
  33. self.width = width
  34. self.height = height
  35. self.font_path = None # None for default font
  36. self.font_size = 18
  37. self.theme = "dark"
  38. self._update_theme = True
  39. def load_font(self, font_path=None, font_size=18):
  40. """
  41. Loads a font for the application.
  42. Args:
  43. font_path (str, optional): The path to the font file. Defaults to None, which loads the default font.
  44. font_size (int, optional): The size of the font. Defaults to 18.
  45. """
  46. # If no font is specified, we use the default
  47. if self.font_path is None:
  48. if sys.platform == "win32":
  49. font_path = Path("C:/Windows/Fonts/segoeui.ttf")
  50. elif sys.platform == "darwin":
  51. font_path = Path("/System/Library/Fonts/SFNSDisplay.ttf")
  52. elif sys.platform == "linux":
  53. font_path = Path("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf")
  54. else:
  55. raise Exception(f"Unsupported platform {sys.platform}")
  56. else:
  57. font_path = Path(self.font_path)
  58. # Check if font file exists
  59. if not os.path.exists(font_path):
  60. raise Exception(f"Font file '{font_path}' does not exist")
  61. # Save font path and size
  62. self.font_path = str(font_path)
  63. self.font_size = font_size
  64. def load_default_font(self):
  65. """Loads the default imgui font for the application."""
  66. self.font_path = None
  67. self.font_size = 18
  68. def apply_theme(self, name: str):
  69. """
  70. Applies a theme to the application.
  71. Args:
  72. name (str): The name of the theme
  73. Available themes:
  74. - dark
  75. - light
  76. - classic
  77. - material_flat
  78. - photoshop_style
  79. - gray_variations
  80. - gray_variations_darker
  81. - microsoft_style
  82. - cherry
  83. - darcula
  84. - darcula_darker
  85. - light_rounded
  86. - so_dark_accent_blue
  87. - so_dark_accent_yellow
  88. - so_dark_accent_red
  89. - black_is_black
  90. - white_is_white
  91. Raises:
  92. ValueError: If the theme name is not found
  93. """
  94. if name in IMGUI_THEMES:
  95. self.theme = name
  96. self._update_theme = True
  97. else:
  98. raise ValueError(f"Theme '{name}' not found")
  99. def run(self, render=None, update=None, terminate=None):
  100. """Run main loop with dependency-resolved callbacks
  101. Args:
  102. render (function, optional): Render callback. Defaults to None.
  103. update (function, optional): Update callback. Defaults to None.
  104. terminate (function, optional): Terminate callback. Defaults to None.
  105. """
  106. # Load font before launch
  107. def _load_font():
  108. # Load the font and set it as default
  109. io = imgui.get_io()
  110. io.fonts.clear()
  111. if self.font_path is not None:
  112. custom_font = io.fonts.add_font_from_file_ttf(self.font_path, self.font_size)
  113. io.font_default = custom_font
  114. else:
  115. io.font_default = io.fonts.add_font_default()
  116. # Custom rendering callback
  117. def _render():
  118. if self._update_theme:
  119. hello_imgui.apply_theme(
  120. IMGUI_THEMES[self.theme]
  121. )
  122. # Update callback
  123. if update is not None:
  124. update()
  125. # Render callback
  126. viewport_size = imgui.get_main_viewport().size
  127. imgui.set_next_window_pos(imgui.ImVec2(0, 0))
  128. imgui.set_next_window_size(imgui.ImVec2(viewport_size.x, viewport_size.y))
  129. imgui.begin(
  130. f"##Main window",
  131. flags=imgui.WindowFlags_.no_decoration |
  132. imgui.WindowFlags_.no_move
  133. )
  134. if render is not None:
  135. render()
  136. imgui.end()
  137. # Initialize the application
  138. params = hello_imgui.RunnerParams()
  139. params.app_window_params.window_geometry.size = (self.width, self.height)
  140. params.callbacks.load_additional_fonts = _load_font
  141. params.app_window_params.window_title = self.title
  142. params.callbacks.show_gui = _render
  143. if terminate is not None:
  144. params.callbacks.before_exit = terminate
  145. # Run the application
  146. hello_imgui.run(params)