This commit is contained in:
dimitar committed 2026-05-22 00:45:17 +02:00
1 parent 1e85df5193
commit 33c70e776a
4 files changed
+265 -203

No files matched your search

+49
View File
@@ -130,6 +130,55 @@ action_layout_auto :: proc(controller: ^ui.App_Controller) -> string {
return "Auto layout generated"
}
action_regenerate_page_layout :: proc(controller: ^ui.App_Controller, page_num: int) -> string {
if page_num < 0 || page_num >= len(controller.state.page_layouts) {
return "Invalid layout page"
}
layout := &controller.state.page_layouts[page_num]
panel_count := len(layout.panels)
if panel_count == 0 {
return "Page has no panels"
}
// For a simple visible regenerate effect, pick a random pattern that fits
pattern_ids := []string{
"single-splash", "grid-2x2", "grid-3x3", "dynamic-action",
"manga-spread", "dialogue-heavy", "cinematic-widescreen",
}
// Just pick the next valid pattern in the list (or wrap around)
start_idx := 0
for id, i in pattern_ids {
if id == layout.pattern_id {
start_idx = i
break
}
}
new_pattern_id := layout.pattern_id
for i in 1..=len(pattern_ids) {
idx := (start_idx + i) % len(pattern_ids)
candidate := pattern_ids[idx]
if core.pattern_max_panels(candidate) >= panel_count {
new_pattern_id = candidate
break
}
}
pattern := core.get_layout_pattern_by_id(new_pattern_id)
layout.pattern_id = new_pattern_id
for i in 0..<panel_count {
cell_index := i
if cell_index >= len(pattern.cells) {
cell_index = len(pattern.cells) - 1
}
layout.panels[i].layout_cell = pattern.cells[cell_index]
}
return "Layout page regenerated"
}
export_format_name :: proc(f: core.Export_Format) -> string {
switch f {
case .PDF: return "PDF"
+68 -3
View File
@@ -331,6 +331,26 @@ run_gui_app :: proc(state: ^core.Comic_State) -> shared.App_Error {
push_status(&status_msg, &action_log, fmt.tprintf("Viewing panel %d/%d", summary_opts.panel_cursor+1, panel_count))
}
}
if controller.active_screen == .Layout && button_clicked(summary_prev_btn) {
layout_page_count := len(controller.state.page_layouts)
if layout_page_count > 0 {
summary_opts.layout_page_cursor -= 1
if summary_opts.layout_page_cursor < 0 {
summary_opts.layout_page_cursor = layout_page_count - 1
}
push_status(&status_msg, &action_log, fmt.tprintf("Viewing layout page %d/%d", summary_opts.layout_page_cursor+1, layout_page_count))
}
}
if controller.active_screen == .Layout && button_clicked(summary_next_btn) {
layout_page_count := len(controller.state.page_layouts)
if layout_page_count > 0 {
summary_opts.layout_page_cursor += 1
if summary_opts.layout_page_cursor >= layout_page_count {
summary_opts.layout_page_cursor = 0
}
push_status(&status_msg, &action_log, fmt.tprintf("Viewing layout page %d/%d", summary_opts.layout_page_cursor+1, layout_page_count))
}
}
if button_clicked(new_btn) {
if is_dirty && !shift_down {
@@ -519,6 +539,26 @@ run_gui_app :: proc(state: ^core.Comic_State) -> shared.App_Error {
push_status(&status_msg, &action_log, fmt.tprintf("Viewing panel %d/%d", summary_opts.panel_cursor+1, panel_count))
}
}
if controller.active_screen == .Layout && ctrl_down && rl.IsKeyPressed(.LEFT_BRACKET) {
layout_page_count := len(controller.state.page_layouts)
if layout_page_count > 0 {
summary_opts.layout_page_cursor -= 1
if summary_opts.layout_page_cursor < 0 {
summary_opts.layout_page_cursor = layout_page_count - 1
}
push_status(&status_msg, &action_log, fmt.tprintf("Viewing layout page %d/%d", summary_opts.layout_page_cursor+1, layout_page_count))
}
}
if controller.active_screen == .Layout && ctrl_down && rl.IsKeyPressed(.RIGHT_BRACKET) {
layout_page_count := len(controller.state.page_layouts)
if layout_page_count > 0 {
summary_opts.layout_page_cursor += 1
if summary_opts.layout_page_cursor >= layout_page_count {
summary_opts.layout_page_cursor = 0
}
push_status(&status_msg, &action_log, fmt.tprintf("Viewing layout page %d/%d", summary_opts.layout_page_cursor+1, layout_page_count))
}
}
if ctrl_down && rl.IsKeyPressed(.MINUS) {
push_dirty_status(&is_dirty, &status_msg, &action_log, set_autosave_interval_text(&autosave_interval_text, autosave_secs-5))
}
@@ -889,12 +929,12 @@ run_gui_app :: proc(state: ^core.Comic_State) -> shared.App_Error {
} else if controller.active_screen == .Panels {
draw_small_button(summary_prev_btn, "< Pn")
draw_small_button(summary_next_btn, "Pn >")
} else if controller.active_screen == .Layout {
draw_small_button(summary_prev_btn, "< Ly")
draw_small_button(summary_next_btn, "Ly >")
}
if !compact_mode {
hint_label := "Ctrl+[ / Ctrl+]"
if controller.active_screen == .Script || controller.active_screen == .Layout {
hint_label = "Ctrl+H / Ctrl+J"
}
draw_hint_pill(rl.Rectangle{x = f32(282 + status_w_loop - 186), y = f32(lower_y_loop + 46), width = 172, height = 20}, hint_label, false)
}
}
@@ -935,6 +975,31 @@ run_gui_app :: proc(state: ^core.Comic_State) -> shared.App_Error {
}
draw_text_fitted("Ctrl+[ / Ctrl+] panel nav", log_x_loop+18, lower_y_loop+8, 13, int(main_w_loop-status_w_loop-34), 7, TEXT_TERTIARY)
} else if controller.active_screen == .Layout {
regen, new_layout_cursor := draw_layout_detail_panel(controller, log_x_loop, lower_y_loop, main_w_loop-status_w_loop-2, 200, summary_opts.layout_page_cursor)
layout_page_count := len(controller.state.page_layouts)
if summary_opts.layout_page_cursor != new_layout_cursor {
summary_opts.layout_page_cursor = new_layout_cursor
push_status(&status_msg, &action_log, fmt.tprintf("Viewing layout page %d/%d", summary_opts.layout_page_cursor+1, layout_page_count))
}
if regen {
msg := action_regenerate_page_layout(&controller, summary_opts.layout_page_cursor)
push_status(&status_msg, &action_log, msg)
}
wheel := rl.GetMouseWheelMove()
if wheel != 0 && layout_page_count > 0 {
summary_opts.layout_page_cursor -= int(wheel)
if summary_opts.layout_page_cursor < 0 {
summary_opts.layout_page_cursor = 0
}
if summary_opts.layout_page_cursor >= layout_page_count {
summary_opts.layout_page_cursor = layout_page_count - 1
}
push_status(&status_msg, &action_log, fmt.tprintf("Viewing layout page %d/%d", summary_opts.layout_page_cursor+1, layout_page_count))
}
draw_text_fitted("Ctrl+H / Ctrl+J layout nav", log_x_loop+18, lower_y_loop+8, 13, int(main_w_loop-status_w_loop-34), 7, TEXT_TERTIARY)
} else {
draw_card(rl.Rectangle{x = f32(log_x_loop), y = f32(lower_y_loop), width = f32(main_w_loop-status_w_loop-2), height = 200})
draw_section_title(log_x_loop+18, lower_y_loop+6, "Action Log")
+134
View File
@@ -441,3 +441,137 @@ draw_panels_detail_panel :: proc(controller: ui.App_Controller, x, y, w, h: i32,
}
return
}
clamp_layout_cursor :: proc(layout_count, cursor: int) -> int {
if layout_count <= 0 {
return 0
}
if cursor < 0 {
return 0
}
if cursor >= layout_count {
return layout_count - 1
}
return cursor
}
draw_layout_detail_panel :: proc(controller: ui.App_Controller, x, y, w, h: i32, cursor: int) -> (regen_clicked: bool, new_cursor: int) {
new_cursor = cursor
regen_clicked = false
draw_card(rl.Rectangle{x = f32(x), y = f32(y), width = f32(w), height = f32(h)})
draw_section_title(x+18, y+6, "Layout Detail")
draw_subtle_strip(rl.Rectangle{x = f32(x+12), y = f32(y), width = f32(w-24), height = 34})
layout_count := len(controller.state.page_layouts)
if layout_count == 0 {
draw_summary_line(x+18, y+46, "No layouts yet. Use Layout Auto after panels.", SUMMARY_HINT)
return
}
idx := clamp_layout_cursor(layout_count, cursor)
layout := controller.state.page_layouts[idx]
// Header line with status
draw_summary_line(x+18, y+46, fmt.tprintf("Page %d/%d • pattern: %s • %d panels", idx+1, layout_count, layout.pattern_id, len(layout.panels)), SUMMARY_ACCENT)
// Regenerate button
btn_rec := rl.Rectangle{x = f32(x + w - 100), y = f32(y+42), width = 80, height = 24}
draw_small_button_state(btn_rec, "Regen", true)
if button_clicked(btn_rec) {
regen_clicked = true
}
// Layout dimensions
draw_summary_subline(x+18, y+68, fmt.tprintf("size: %d x %d", layout.width, layout.height), SUMMARY_SUBLINE)
// ── Mini wireframe preview ─────────────────────────────────
preview_x := x + 18
preview_y := y + 88
preview_max_w: f32 = f32(w) * 0.4
preview_max_h: f32 = f32(h - 100)
if preview_max_h < 40 {
preview_max_h = 40
}
// Scale to fit
lw := f32(layout.width)
lh := f32(layout.height)
if lw < 1 { lw = 1 }
if lh < 1 { lh = 1 }
scale_x := preview_max_w / lw
scale_y := preview_max_h / lh
scale := scale_x
if scale_y < scale {
scale = scale_y
}
pw := lw * scale
ph := lh * scale
// Draw page outline
page_rec := rl.Rectangle{x = f32(preview_x), y = f32(preview_y), width = pw, height = ph}
rl.DrawRectangleRounded(page_rec, 0.02, 4, BG_STRIP)
rl.DrawRectangleRoundedLinesEx(page_rec, 0.02, 4, 1.0, BORDER_CARD)
// Draw each panel cell
for i in 0..<len(layout.panels) {
cell := layout.panels[i].layout_cell
cx := f32(preview_x) + cell.x * pw
cy := f32(preview_y) + cell.y * ph
cw := cell.w * pw
ch := cell.h * ph
// Inset slightly for gutter
inset: f32 = 1.5
cell_rec := rl.Rectangle{x = cx + inset, y = cy + inset, width = cw - inset*2, height = ch - inset*2}
rl.DrawRectangleRounded(cell_rec, 0.06, 4, ACCENT_SURFACE)
rl.DrawRectangleRoundedLinesEx(cell_rec, 0.06, 4, 1.0, ACCENT_MUTED)
// Panel number label
num_label := fmt.tprintf("%d", layout.panels[i].panel_number)
label_sz: i32 = 10
if cw > 30 && ch > 14 {
draw_text_fitted(num_label, i32(cx + inset + 3), i32(cy + inset + 2), label_sz, int(cw - inset*2 - 4), 5, TEXT_SECONDARY)
}
}
// ── Page list (right side) ─────────────────────────────────
list_x := x + i32(preview_max_w) + 36
list_y := y + 88
list_w := w - i32(preview_max_w) - 54
row_h: i32 = 18
rows: i32 = (h - 100) / row_h
if rows < 1 {
rows = 1
}
start := idx - int(rows/2)
if start < 0 {
start = 0
}
end := start + int(rows)
if end > layout_count {
end = layout_count
start = end - int(rows)
if start < 0 {
start = 0
}
}
line: i32 = 0
for i in start..<end {
l := controller.state.page_layouts[i]
mark := " "
row_color := TEXT_TERTIARY
if i == idx {
mark = ">"
row_color = TEXT_PRIMARY
}
row_rec := rl.Rectangle{x = f32(list_x), y = f32(list_y + line*row_h), width = f32(list_w), height = f32(row_h)}
if rl.CheckCollisionPointRec(rl.GetMousePosition(), row_rec) && rl.IsMouseButtonPressed(.LEFT) {
new_cursor = i
}
if rl.CheckCollisionPointRec(rl.GetMousePosition(), row_rec) && row_color == TEXT_TERTIARY {
row_color = TEXT_SECONDARY
}
draw_summary_subline(list_x, list_y+line*row_h+2, fit_text_for_width(fmt.tprintf("%s %02d %s (%d)", mark, l.page_number, l.pattern_id, len(l.panels)), int(list_w), 7), row_color)
line += 1
}
return
}