Phase C: Split process_clicks into 6 focused sub-functions
handle_nav_clicks — sidebar + pipeline stepper navigation handle_field_clicks — input field focus detection handle_format_clicks — PDF/PNG/CBZ + Local/DS toggle handle_action_clicks — all pipeline/file/log action buttons handle_workspace_nav — prev/next for Script/Panels/Layout/Bubbles handle_detail_clicks — panel regen, layout regen, bubble editor ops process_clicks: 269 → 30 lines (orchestration only) runtime.odin: 806 → 806 lines (delegation replaced inline logic) All 156 tests pass.
This commit is contained in:
parent
be0ccc1539
commit
8b044e3ac1
@ -349,33 +349,31 @@ run_gui_app :: proc(state: ^core.Comic_State) -> shared.App_Error {
|
||||
return shared.ok()
|
||||
}
|
||||
|
||||
// ─── Click Processing ──────────────────────────────────────────────
|
||||
process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_export, proj_ok, export_ok, has_deepseek: bool, pages_count: int, shift_down: bool, autosave_secs: int, compact_mode: bool) {
|
||||
// Navigation
|
||||
// ─── Click Handlers (called by process_clicks) ───────────────────
|
||||
|
||||
handle_nav_clicks :: proc(app: ^GUI_App_State) {
|
||||
nav_screen := []ui.App_Screen{.Story, .Script, .Characters, .Panels, .Layout, .Bubbles, .Export, .Community}
|
||||
for i in 0 ..< len(nav_screen) {
|
||||
if clicked(clay.ID("Nav", u32(i))) {
|
||||
push_status(&app.status_msg, &app.action_log, navigate_screen_with_status(&app.controller, nav_screen[i]))
|
||||
}
|
||||
}
|
||||
|
||||
// Pipeline stepper clicks → navigate to corresponding screen
|
||||
pipeline_screens := []ui.App_Screen{.Script, .Panels, .Layout, .Export}
|
||||
for i in 0 ..< len(pipeline_screens) {
|
||||
if clicked(clay.ID("PStep", u32(i))) {
|
||||
push_status(&app.status_msg, &app.action_log, navigate_screen_with_status(&app.controller, pipeline_screens[i]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Input field focus
|
||||
handle_field_clicks :: proc(app: ^GUI_App_State) {
|
||||
input_ids := []string{"field_idea", "field_genre", "field_audience", "field_export", "field_pages", "field_project"}
|
||||
for i in 0 ..< len(input_ids) {
|
||||
if clicked(clay.ID(input_ids[i])) {
|
||||
app.selected_field = i
|
||||
}
|
||||
if clicked(clay.ID(input_ids[i])) { app.selected_field = i }
|
||||
}
|
||||
}
|
||||
|
||||
// Format buttons
|
||||
handle_format_clicks :: proc(app: ^GUI_App_State, has_deepseek: bool) {
|
||||
if clicked(clay.ID("btn_pdf")) { push_status(&app.status_msg, &app.action_log, set_export_format_with_message(&app.export_format, &app.export_path, .PDF, &app.is_dirty)) }
|
||||
if clicked(clay.ID("btn_png")) { push_status(&app.status_msg, &app.action_log, set_export_format_with_message(&app.export_format, &app.export_path, .PNG, &app.is_dirty)) }
|
||||
if clicked(clay.ID("btn_cbz")) { push_status(&app.status_msg, &app.action_log, set_export_format_with_message(&app.export_format, &app.export_path, .CBZ, &app.is_dirty)) }
|
||||
@ -384,8 +382,9 @@ process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_expo
|
||||
if !has_deepseek { push_status(&app.status_msg, &app.action_log, "DeepSeek key missing") }
|
||||
else { app.use_deepseek_script = true; push_status(&app.status_msg, &app.action_log, "Script source: DeepSeek") }
|
||||
}
|
||||
}
|
||||
|
||||
// Action buttons
|
||||
handle_action_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_export: bool, pages_count: int, shift_down: bool, proj_ok, export_ok: bool, autosave_secs: int) {
|
||||
if clicked(clay.ID("btn_new")) {
|
||||
if app.is_dirty && !shift_down { push_status(&app.status_msg, &app.action_log, request_confirmation(&app.show_confirm_overlay, &app.show_help_overlay, &app.pending_confirm, .Reset_Project, "Confirm reset?")) }
|
||||
else { push_status(&app.status_msg, &app.action_log, reset_project_session(&app.controller, &app.is_dirty, &app.last_autosave_at, false)) }
|
||||
@ -405,7 +404,6 @@ process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_expo
|
||||
}
|
||||
if clicked(clay.ID("btn_next")) { push_status(&app.status_msg, &app.action_log, run_next_action(&app.controller, &app.export_path, app.export_format, pages_count, app.use_deepseek_script, &app.is_dirty, &app.last_export_at)) }
|
||||
if clicked(clay.ID("btn_auto")) { push_status(&app.status_msg, &app.action_log, run_auto_all_action(&app.controller, &app.export_path, app.export_format, pages_count, app.use_deepseek_script, &app.is_dirty, &app.last_export_at)) }
|
||||
if clicked(clay.ID("btn_autosave")) { push_status(&app.status_msg, &app.action_log, run_auto_all_save_action(&app.controller, &app.project_path, &app.export_path, app.export_format, pages_count, app.use_deepseek_script, &app.is_dirty, &app.last_export_at, &app.last_autosave_at, &app.last_save_at)) }
|
||||
if clicked(clay.ID("btn_save")) { push_status(&app.status_msg, &app.action_log, save_project_session_with_message(&app.project_path, app.controller.state, &app.is_dirty, &app.last_autosave_at, &app.last_save_at, "Saved project")) }
|
||||
if clicked(clay.ID("btn_open")) {
|
||||
if app.is_dirty && !shift_down { push_status(&app.status_msg, &app.action_log, request_confirmation(&app.show_confirm_overlay, &app.show_help_overlay, &app.pending_confirm, .Open_Project, "Confirm open?")) }
|
||||
@ -422,10 +420,10 @@ process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_expo
|
||||
if clicked(clay.ID("btn_log_diag")) { push_status(&app.status_msg, &app.action_log, write_diagnostics_with_message(diag_ctx)) }
|
||||
if clicked(clay.ID("btn_log_status_copy")) { push_status(&app.status_msg, &app.action_log, copy_text_with_status(app.status_msg, "Copied status to clipboard")) }
|
||||
if clicked(clay.ID("btn_log_diag_copy")) { push_status(&app.status_msg, &app.action_log, copy_diagnostics_with_message(diag_ctx)) }
|
||||
}
|
||||
|
||||
handle_workspace_nav :: proc(app: ^GUI_App_State) {
|
||||
screen := app.controller.active_screen
|
||||
|
||||
// Workspace navigation buttons
|
||||
if screen == .Script {
|
||||
page_count := len(app.controller.state.script.pages)
|
||||
if clicked(clay.ID("btn_script_prev")) && page_count > 0 {
|
||||
@ -489,18 +487,18 @@ process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_expo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handle_detail_clicks :: proc(app: ^GUI_App_State) {
|
||||
screen := app.controller.active_screen
|
||||
|
||||
// Panels detail buttons
|
||||
screen = app.controller.active_screen
|
||||
if screen == .Panels {
|
||||
if clicked(clay.ID("btn_panel_regenerate")) {
|
||||
panel_count := count_script_panels(app.controller.state.script)
|
||||
if panel_count > 0 {
|
||||
idx := clamp_panel_cursor(panel_count, app.summary_opts.panel_cursor)
|
||||
panel, _, ok := panel_by_flat_index(app.controller.state.script, idx)
|
||||
if ok {
|
||||
push_status(&app.status_msg, &app.action_log, action_regenerate_panel(&app.controller, panel.panel_id))
|
||||
}
|
||||
if ok { push_status(&app.status_msg, &app.action_log, action_regenerate_panel(&app.controller, panel.panel_id)) }
|
||||
}
|
||||
}
|
||||
panel_count := count_script_panels(app.controller.state.script)
|
||||
@ -514,7 +512,6 @@ process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_expo
|
||||
}
|
||||
}
|
||||
|
||||
// Layout detail buttons
|
||||
if screen == .Layout {
|
||||
if clicked(clay.ID("btn_layout_regen")) {
|
||||
push_status(&app.status_msg, &app.action_log, action_regenerate_page_layout(&app.controller, app.summary_opts.layout_page_cursor))
|
||||
@ -529,7 +526,6 @@ process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_expo
|
||||
}
|
||||
}
|
||||
|
||||
// Bubbles detail buttons
|
||||
if screen == .Bubbles {
|
||||
layout_count := len(app.controller.state.page_layouts)
|
||||
if layout_count > 0 {
|
||||
@ -554,8 +550,6 @@ process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_expo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bubble row clicks
|
||||
if layout_count > 0 {
|
||||
page_idx := clamp_layout_cursor(layout_count, app.summary_opts.bubble_page_cursor)
|
||||
layout_val := app.controller.state.page_layouts[page_idx]
|
||||
@ -570,13 +564,9 @@ process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_expo
|
||||
if clicked(clay.ID(fmt.tprintf("btn_bubble_delete_%d", i))) {
|
||||
push_status(&app.status_msg, &app.action_log, action_delete_bubble(&app.controller, panel_id, i))
|
||||
app.is_dirty = true
|
||||
if app.summary_opts.bubble_edit_cursor > 0 {
|
||||
app.summary_opts.bubble_edit_cursor -= 1
|
||||
}
|
||||
if app.summary_opts.bubble_edit_cursor > 0 { app.summary_opts.bubble_edit_cursor -= 1 }
|
||||
}
|
||||
}
|
||||
|
||||
// Type selector buttons
|
||||
bubble_count := count_bubbles_for_panel(app.controller.state.speech_bubbles, panel_id)
|
||||
if bubble_count > 0 && app.summary_opts.bubble_edit_cursor < bubble_count {
|
||||
types := []core.Bubble_Type{.Normal, .Thought, .Shout, .Whisper, .Narration, .Sound_Effect}
|
||||
@ -591,21 +581,37 @@ process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_expo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
process_clicks :: proc(app: ^GUI_App_State, can_gen_panels, can_layout, can_export, proj_ok, export_ok, has_deepseek: bool, pages_count: int, shift_down: bool, autosave_secs: int, compact_mode: bool) {
|
||||
handle_nav_clicks(app)
|
||||
handle_field_clicks(app)
|
||||
handle_format_clicks(app, has_deepseek)
|
||||
handle_action_clicks(app, can_gen_panels, can_layout, can_export, pages_count, shift_down, proj_ok, export_ok, autosave_secs)
|
||||
handle_workspace_nav(app)
|
||||
handle_detail_clicks(app)
|
||||
|
||||
// Confirm overlay buttons
|
||||
if clicked(clay.ID("confirm_yes")) && app.show_confirm_overlay {
|
||||
action := app.pending_confirm
|
||||
app.show_confirm_overlay = false
|
||||
app.pending_confirm = .None
|
||||
push_status(&app.status_msg, &app.action_log, resolve_confirm_action_with_message(action, &app.controller, &app.project_path, &app.export_path, app.export_format, &app.is_dirty, &app.last_autosave_at))
|
||||
// Overlay clicks
|
||||
if app.show_confirm_overlay {
|
||||
confirm_yes := rl.IsKeyPressed(.ENTER) || rl.IsKeyPressed(.Y) || clicked(clay.ID("confirm_yes"))
|
||||
confirm_no := rl.IsKeyPressed(.ESCAPE) || rl.IsKeyPressed(.N) || clicked(clay.ID("confirm_no"))
|
||||
if confirm_no {
|
||||
app.show_confirm_overlay = false
|
||||
app.pending_confirm = .None
|
||||
push_status(&app.status_msg, &app.action_log, "Cancelled destructive action")
|
||||
} else if confirm_yes {
|
||||
app.show_confirm_overlay = false
|
||||
msg := resolve_confirm_action_with_message(app.pending_confirm, &app.controller, &app.project_path, &app.export_path, app.export_format, &app.is_dirty, &app.last_autosave_at)
|
||||
push_status(&app.status_msg, &app.action_log, msg)
|
||||
app.pending_confirm = .None
|
||||
}
|
||||
}
|
||||
if clicked(clay.ID("confirm_no")) && app.show_confirm_overlay {
|
||||
app.show_confirm_overlay = false
|
||||
app.pending_confirm = .None
|
||||
push_status(&app.status_msg, &app.action_log, "Cancelled destructive action")
|
||||
if app.show_help_overlay {
|
||||
if rl.IsKeyPressed(.ESCAPE) || rl.IsKeyPressed(.SLASH) {
|
||||
app.show_help_overlay = false
|
||||
push_status(&app.status_msg, &app.action_log, "Closed help overlay")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Clay UI Primitives ───────────────────────────────────────────
|
||||
declare_nav_chip :: proc(id: string, label: string, active: bool) {
|
||||
bg: clay.Color = clay.Color{0, 0, 0, 0}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user