A themed, configurable imgui file/folder open dialog widget built on imgui-bundle.
Project description
imgui_data_loader
A themed, configurable file / folder open dialog for
imgui-bundle. Drop it into a
hello_imgui / immapp app, or use the
one-shot helper to pop up a launcher window and get back the path the user
picked.
It's a small, styled launcher window — a title, your help/info content, and
buttons that open the OS-native file picker (via
portable_file_dialogs). Everything is configurable: buttons, file types,
theme, the info card, and an options popup.
Install
pip install imgui_data_loader
The only dependency is imgui-bundle (which provides imgui, hello_imgui,
immapp, portable_file_dialogs and the FontAwesome icon font).
Quick start
from imgui_data_loader import run_file_dialog, FileDialogConfig
result = run_file_dialog(FileDialogConfig()) # default Open File(s) / Select Folder
if result: # truthy only for a real selection
print(result.paths) # list[str]
print(result.path) # first path, or None
else:
print("cancelled")
run_file_dialog opens the window, blocks until the user picks something or
quits, and returns a DialogResult.
Examples
Full runnable scripts are in examples/ — a ladder from the
one-liner above to a full embedded app; each adds options the previous one
didn't. The snippets below show the essential config; the screenshots are
captured from the real dialogs by python scripts/capture_docs.py
(pip install -e ".[docs]", needs a desktop session).
Buttons & file types
Branding, a hand-built buttons list covering every PickKind, per-button
FileType filters (overriding the dialog-wide default), and a default_dir.
result.kind tells you which button produced the selection.
examples/02_buttons_filetypes.py
from imgui_bundle import icons_fontawesome_6 as fa
from imgui_data_loader import (
run_file_dialog, FileDialogConfig, ButtonSpec, PickKind, FileType,
)
tiff = [FileType("TIFF", "*.tif *.tiff"), FileType("All Files", "*")]
result = run_file_dialog(FileDialogConfig(
title="Importer",
subtitle="open anything",
buttons=[
ButtonSpec("Open one image", PickKind.OPEN_FILE, icon=fa.ICON_FA_FILE_IMAGE,
filetypes=tiff),
ButtonSpec("Open many images", PickKind.OPEN_FILE, icon=fa.ICON_FA_CLONE,
multiselect=True, filetypes=tiff),
ButtonSpec("Open a folder", PickKind.SELECT_FOLDER, icon=fa.ICON_FA_FOLDER_OPEN),
ButtonSpec("Export as…", PickKind.SAVE_FILE, icon=fa.ICON_FA_FLOPPY_DISK,
filetypes=[FileType("Zarr", "*.zarr")]),
],
))
print(result.kind, result.paths) # which button fired + what it returned
Theme & info card
A custom Theme (start from dark()/light() and .replace() colors) and an
info card. info is one callback or a list of them — each drawn as its own
section — using the library's themed helpers (center_text,
text_wrapped_colored, icon_button). Each callback may take the FileDialog
or nothing. examples/03_theme_info.py
from imgui_bundle import imgui
from imgui_data_loader import (
run_file_dialog, FileDialogConfig, Theme, center_text, text_wrapped_colored,
)
def formats(dlg):
center_text("Supported formats", dlg.theme.accent)
imgui.bullet_text("TIFF / Zarr / HDF5")
def help_note(dlg):
text_wrapped_colored(dlg.theme.text_dim,
"Folders load every supported file inside, sorted by name.")
run_file_dialog(FileDialogConfig(
title="Themed Loader",
theme=Theme.dark().replace(accent=(0.20, 0.75, 0.70, 1.0)),
info=[formats, help_note], # two sections in the card
))
Content slots & options popup
top_draw puts a widget row between the header and the buttons; options_draw
adds an Options button that opens a popup (shown open below); on_select /
on_cancel react to the outcome without inspecting the return value. Each
imgui widget returns (changed, new_value) — keep the value.
examples/04_slots_options.py
from imgui_bundle import imgui
from imgui_data_loader import run_file_dialog, FileDialogConfig
state = {"mode": 0, "recurse": True, "downsample": 1}
MODES = ["2D", "3D volume", "Time series"]
def mode_row(dlg):
imgui.set_next_item_width(imgui.get_content_region_avail().x)
_, state["mode"] = imgui.combo("##mode", state["mode"], MODES)
def options(dlg):
_, state["recurse"] = imgui.checkbox("Recurse into subfolders", state["recurse"])
_, state["downsample"] = imgui.slider_int("Downsample", state["downsample"], 1, 8)
run_file_dialog(FileDialogConfig(
title="Volume Loader",
top_draw=mode_row,
options_draw=options,
options_label="Load options",
quit_label="Close",
on_select=lambda r: print(MODES[state["mode"]], r.paths),
on_cancel=lambda: print("user quit"),
))
Recent files
Pass a PreferenceStore; the included JsonPreferenceStore seeds the picker's
start directory from the last-used one and records selections to a JSON file.
Draw the recents wherever you like — here in the info card.
examples/05_recent_files.py
from imgui_bundle import imgui
from imgui_data_loader import run_file_dialog, FileDialogConfig, JsonPreferenceStore
store = JsonPreferenceStore() # ~/.config/imgui_data_loader/recent.json
def recents(dlg):
imgui.text_colored(dlg.theme.accent, "Recent")
for path in store.recent()[:6]:
imgui.bullet_text(path)
run_file_dialog(FileDialogConfig(title="Recent Files", persistence=store, info=recents))
print(store.recent())
Embed in your own app
Render the FileDialog widget inside your own hello_imgui / immapp loop as
one panel of a bigger UI. Set close_on_select=False and poll take_result()
each frame (or use on_select); header_draw / footer_draw replace the
default header/footer; ensure_assets() makes the icon font available in your
runner. examples/06_embedded_app.py
from imgui_bundle import hello_imgui, imgui, immapp
from imgui_data_loader import FileDialog, FileDialogConfig, ensure_assets
ensure_assets()
dlg = FileDialog(FileDialogConfig(close_on_select=False, show_quit_button=False))
loaded = []
def gui():
dlg.render() # the dialog is one panel…
result = dlg.take_result() # None until the user picks
if result:
loaded.extend(result.paths)
imgui.separator() # …the rest of your app follows
for p in loaded[-8:]:
imgui.bullet_text(p)
params = hello_imgui.RunnerParams()
params.callbacks.show_gui = gui
immapp.run(params)
More specific cases
Things you may want that the examples above don't cover.
Your own PreferenceStore
persistence is just a three-method protocol (default_dir / recent /
record_selection), so back "recent files" with anything — a database, your
app's settings, a project-local file:
from pathlib import Path
import json
class ProjectStore: # implements the PreferenceStore protocol
def __init__(self, project_dir):
self.dir = Path(project_dir)
self.file = self.dir / ".loader_history.json"
self._recent = json.loads(self.file.read_text()) if self.file.exists() else []
def default_dir(self): return str(self.dir) # always start in the project
def recent(self): return list(self._recent)
def record_selection(self, result):
self._recent = (result.paths + self._recent)[:10]
self.file.write_text(json.dumps(self._recent))
run_file_dialog(FileDialogConfig(title="Project Loader", persistence=ProjectStore(".")))
Persist options across launches
hello_imgui ships a key/value preference store that writes into the same
layout .ini this library already manages, so an Options toggle survives
across runs with no extra files. It stores strings, and the calls must run
in the runner's post_init (load) and before_exit (save) callbacks — pass
your own RunnerParams and run_file_dialog fills in the title/size/ini
around them:
from imgui_bundle import hello_imgui, imgui
state = {"recursive": True}
load = lambda: state.update(recursive=hello_imgui.load_user_pref("recursive") == "1")
save = lambda: hello_imgui.save_user_pref("recursive", "1" if state["recursive"] else "0")
def options(dlg):
_, state["recursive"] = imgui.checkbox("Search subfolders", state["recursive"])
params = hello_imgui.RunnerParams()
params.callbacks.post_init = load
params.callbacks.before_exit = save
run_file_dialog(FileDialogConfig(title="Loader", options_draw=options), runner_params=params)
This is separate from PreferenceStore: use PreferenceStore for recent-files
history that your code reads back, and load_user_pref / save_user_pref for
small UI settings the dialog owns.
Fancier widgets from imgui-bundle
The callback slots run inside a live imgui frame, so any widget bundled with
imgui-bundle works — not just base imgui. A few worth reaching for from an
options_draw / info callback:
from imgui_bundle import imgui_toggle, imgui_knobs, imspinner, imgui_md, imgui
def options(dlg):
_, opts["recursive"] = imgui_toggle.toggle( # animated on/off switch
"Search subfolders", opts["recursive"], imgui_toggle.ToggleFlags_.animated)
_, opts["gain"] = imgui_knobs.knob("Gain", opts["gain"], 0.0, 4.0) # rotary knob
if opts["busy"]: # busy indicator
imspinner.spinner_ang("scan", 12.0, 4.0, color=imgui.ImColor(*dlg.theme.accent))
def formats(dlg):
imgui_md.render("**Supported**: TIFF · Zarr · HDF5") # markdown in the info card
imgui_command_palette, im_cool_bar, and the rest of the bundle work the same
way. Pair them with the library's helpers (center_text, icon_button,
push_button_style, …) and dlg.theme to match the styling.
Where the layout .ini goes
hello_imgui persists window layout to a small .ini. By default run_file_dialog
writes it to an absolute path under your config dir —
~/.config/imgui_data_loader/file_dialog.ini (honoring $XDG_CONFIG_HOME) — so it
never lands in the current working directory. Change it with
FileDialogConfig(ini_path="/path/to/my_dialog.ini") (the parent dir is created).
When you embed the dialog with your own runner, set params.ini_filename
(and optionally params.ini_folder_type) yourself — run_file_dialog only fills
it in when you leave it unset.
Configuration reference
FileDialogConfig fields:
| field | default | purpose |
|---|---|---|
title, subtitle |
"Open Data", "" |
header text |
buttons |
Open File(s) + Select Folder | list of ButtonSpec |
filetypes |
[All Files] |
default filters for file/save buttons |
default_dir |
"" |
picker start dir (else persistence, else ~) |
theme |
Theme.dark() |
colors |
header_draw |
None |
replace the title/subtitle block |
top_draw |
None |
content between header and buttons |
info |
None |
callback(s) drawn in the info card |
options_draw |
None |
Options popup content (also toggles the button) |
footer_draw |
None |
replace the Options/Quit row |
options_label |
"Options" |
popup + button label |
show_options_button |
True |
show Options (needs options_draw) |
show_quit_button, quit_label |
True, "Quit" |
Quit button |
quit_on_escape |
True |
Esc cancels |
close_on_select |
True |
exit the run loop after a pick (one-shot mode) |
window_title, window_size, resizable |
— | OS window (one-shot) |
ini_path |
~/.config/imgui_data_loader/… |
where the layout .ini is saved |
assets_folder |
imgui-bundle's | folder providing the icon font |
persistence |
None |
a PreferenceStore |
on_select, on_cancel |
None |
result callbacks |
Notes
- Buttons open the OS-native dialog, so a desktop session is required (no in-window file browser).
- Icons come from FontAwesome 6, which ships inside imgui-bundle;
run_file_dialogpoints hello_imgui at that font automatically. When embedding, make sure your app's assets folder provides it (or passassets_folder). The bundled build is Solid only, so a few glyphs (e.g.ICON_FA_IMAGES,ICON_FA_LAYER_GROUP) render as a blank box — pick a solid icon if one shows empty. - Draw callbacks run inside an active imgui frame — only call imgui from them.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file imgui_data_loader-0.1.0.tar.gz.
File metadata
- Download URL: imgui_data_loader-0.1.0.tar.gz
- Upload date:
- Size: 25.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b083ab47dd6e46a02cfca5c5cd0b7eb454d21f96c5f53af89180f2329dfdd4c9
|
|
| MD5 |
a91e5be64dfc4f3e79e6ac108b26b537
|
|
| BLAKE2b-256 |
cc20d34c70312488db8d01df407a85ec2d612f16d913d86d6d3374f777248b33
|
File details
Details for the file imgui_data_loader-0.1.0-py3-none-any.whl.
File metadata
- Download URL: imgui_data_loader-0.1.0-py3-none-any.whl
- Upload date:
- Size: 20.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa68dc36561ed60ea8576fe73511ad5d8402d6dc5f651bce55d8e639c4351ee0
|
|
| MD5 |
ab398affd02738b9667af7dcc6075b85
|
|
| BLAKE2b-256 |
f753ae94da150a91448e3be1cca943ab8681adcf94d216c828965fdfa627f538
|