~mil/mepo

488af33251bfec33e19d5000097de132a6839f48 — Miles Alan 1 year, 7 months ago 9aa3a72 transfer-all-button-hold
Implement holding of UI button / transfer all pins in group
M src/Mepo.zig => src/Mepo.zig +8 -5
@@ 690,8 690,6 @@ fn event_mousebuttonup(mepo: *@This(), e: sdl.SDL_Event) types.Pending {
        utildbg.log("Clicked on button: {} with clicks {}\n", .{clicked_btn, e.button.clicks});
        if (e.button.clicks == 1) {
            mepo.mepolang_execute(clicked_btn.mepolang_click_single) catch unreachable;
        } else if (e.button.clicks == 2) {
            mepo.mepolang_execute(clicked_btn.mepolang_click_double) catch unreachable;
        }
        
        return .Redraw;


@@ 951,13 949,18 @@ fn dispatch_check_click_hold(mepo: *@This()) void {
    const threshold_hit_hold_ms = sdl.SDL_GetTicks() >= mepo.drag.?.begin_ticks + config.DragThresholdTicks;
    const threshold_hit_distance = mepo.drag.?.delta_x + mepo.drag.?.delta_y <= config.DragThresholdDelta;

    // E.g ignore hold on ui buttons
    // Dispatch held action
    if (threshold_hit_distance) {
        if (mepo.blit_uibuttons(mepo.drag.?.point) catch null) |_| return;
        if (mepo.blit_uibuttons(mepo.drag.?.point) catch null) |held_btn| {
            if (threshold_hit_hold_ms) {
                utildbg.log("Held on button: {}\n", .{held_btn});
                mepo.mepolang_execute(held_btn.mepolang_click_hold) catch unreachable;
            }
            return;
        }
    }

    if (threshold_hit_hold_ms and threshold_hit_distance) {

        mepo.drag = null;
        // TODO: hold support for right click as well?
        if (mepo.table_clicks.get(.{ .button = sdl.SDL_BUTTON_LEFT, .clicks = -1 })) |run_expression| {

M src/api/bind_button.zig => src/api/bind_button.zig +7 -7
@@ 22,19 22,19 @@ fn execute(mepo: *Mepo, args: [types.MepoFnNargs]types.MepoArg) !void {
    const group_number = if (args[1].Number < 0) null else @floatToInt(u8, args[1].Number);
    const text = args[2].Text;
    const expression_click_single = args[3].Text;
    const expression_click_double = args[4].Text;
    try bind_button(mepo, visible_only_when_has_pins, group_number, text, expression_click_single, expression_click_double);
    const expression_click_hold = args[4].Text;
    try bind_button(mepo, visible_only_when_has_pins, group_number, text, expression_click_single, expression_click_hold);
}

fn bind_button(mepo: *Mepo, visible_only_when_has_pins: bool, group_number: ?u8, text: []const u8, expression_click_single: []const u8, expression_click_double: []const u8) !void {
    utildbg.log("Binding button: text=<{s}> 1 click=<{s}> 2 clicks=<{s}>\n", .{ text, expression_click_single, expression_click_double });
fn bind_button(mepo: *Mepo, visible_only_when_has_pins: bool, group_number: ?u8, text: []const u8, expression_click_single: []const u8, expression_click_hold: []const u8) !void {
    utildbg.log("Binding button: text=<{s}> 1 click=<{s}> 2 clicks=<{s}>\n", .{ text, expression_click_single, expression_click_hold });

    for (mepo.uibuttons.items) |*btn| {
        if (std.mem.eql(u8, text, btn.text)) {
            mepo.allocator.free(btn.mepolang_click_single);
            mepo.allocator.free(btn.mepolang_click_double);
            mepo.allocator.free(btn.mepolang_click_hold);
            btn.mepolang_click_single = try mepo.allocator.dupeZ(u8, expression_click_single);
            btn.mepolang_click_double = try mepo.allocator.dupeZ(u8, expression_click_double);
            btn.mepolang_click_hold = try mepo.allocator.dupeZ(u8, expression_click_hold);
            btn.only_visible_when_has_pins = visible_only_when_has_pins;
            return;
        }


@@ 44,7 44,7 @@ fn bind_button(mepo: *Mepo, visible_only_when_has_pins: bool, group_number: ?u8,
        .text = try mepo.allocator.dupeZ(u8, text),
        .group_number = group_number,
        .mepolang_click_single = try mepo.allocator.dupeZ(u8, expression_click_single),
        .mepolang_click_double = try mepo.allocator.dupeZ(u8, expression_click_double),
        .mepolang_click_hold = try mepo.allocator.dupeZ(u8, expression_click_hold),
        .only_visible_when_has_pins = visible_only_when_has_pins,
    });
}

M src/api/filedump.zig => src/api/filedump.zig +1 -1
@@ 148,7 148,7 @@ fn filedump(mepo: *Mepo, save_types: []const u8, filepath: []const u8) !void {
            const statement_button = try std.fmt.allocPrint(
                arena.allocator(),
                "bind_button {d} {d} [{s}] [{s}] [{s}];",
                .{ pins_only_btn, btn.group_number, btn.text, btn.mepolang_click_single, btn.mepolang_click_double },
                .{ pins_only_btn, btn.group_number, btn.text, btn.mepolang_click_single, btn.mepolang_click_hold },
            );
            try lines.append(statement_button);
        }

M src/api/pin_transfer.zig => src/api/pin_transfer.zig +28 -14
@@ 7,7 7,7 @@ pub const spec = .{
    .desc = "Transfer a pin from one group to another.",
    .args = (&[_]types.MepoFnSpecArg{
        .{ .tag = .Number, .name = "from_group_number", .desc = "Group number, or -1 for the current group number" },
        .{ .tag = .Text, .name = "pin_handle", .desc = "Handle of the pin to transfer; if empty will transfer the current pin." },
        .{ .tag = .Text, .name = "pin_handle", .desc = "Handle of the pin to transfer; if empty will transfer the current pin; or all for all pins in group." },
        .{ .tag = .Number, .name = "to_group_number", .desc = "Group number" },
    })[0..],
    .execute = execute,


@@ 22,16 22,18 @@ fn execute(mepo: *Mepo, args: [types.MepoFnNargs]types.MepoArg) !void {

fn pin_transfer(mepo: *Mepo, from_group_number: i32, target_pin_handle: [:0]const u8, to_group: usize) !void {
    const from_group = if (from_group_number < 0) mepo.pin_group_active else @intCast(usize, from_group_number);
    const from_pin_i = from_pin_i: {
    const from_pin_i_opt = from_pin_i_opt: {
        if (target_pin_handle.len == 0) {
            if (mepo.pin_group_active_item) |active_item| {
                break :from_pin_i active_item;
                break :from_pin_i_opt active_item;
            }
        } else if (std.mem.eql(u8, target_pin_handle, "all")) {
            break :from_pin_i_opt null;
        } else {
            for (mepo.pin_groups[from_group].items) |pin, pin_i| {
                if (pin.handle) |handle| {
                    if (std.mem.eql(u8, handle, target_pin_handle)) {
                        break :from_pin_i pin_i;
                        break :from_pin_i_opt pin_i;
                    }
                }
            }


@@ 39,18 41,30 @@ fn pin_transfer(mepo: *Mepo, from_group_number: i32, target_pin_handle: [:0]cons
        return;
    };

    if (from_pin_i_opt) |from_pin_i| {
        try mepo.pin_groups[to_group].append(mepo.pin_groups[from_group].items[from_pin_i]);
        _ = mepo.pin_groups[from_group].orderedRemove(from_pin_i);

    try mepo.pin_groups[to_group].append(mepo.pin_groups[from_group].items[from_pin_i]);
    _ = mepo.pin_groups[from_group].orderedRemove(from_pin_i);
        // If pin to transfer is the currently active pin we
        // re-activate it afterward (switch group and current pin index)
        if (
            from_group == mepo.pin_group_active and
            mepo.pin_group_active_item != null and
            mepo.pin_group_active_item.? == from_pin_i
        ) {
            mepo.pin_group_active = @intCast(u8, to_group);
            mepo.pin_group_active_item = @intCast(u32, mepo.pin_groups[mepo.pin_group_active].items.len - 1);
        }
    } else {
        for (mepo.pin_groups[from_group].items) |_, pin_i| {
            try mepo.pin_groups[to_group].append(mepo.pin_groups[from_group].items[pin_i]);
        }
        for (mepo.pin_groups[from_group].items) |_| {
            _ = mepo.pin_groups[from_group].orderedRemove(0);
        }

    // If pin to transfer is the currently active pin we
    // re-activate it afterward (switch group and current pin index)
    if (
        from_group == mepo.pin_group_active and
        mepo.pin_group_active_item != null and
        mepo.pin_group_active_item.? == from_pin_i
    ) {
        //_ = mepo.pin_groups[from_group].clearAndFree;
        mepo.pin_group_active = @intCast(u8, to_group);
        mepo.pin_group_active_item = @intCast(u32, mepo.pin_groups[mepo.pin_group_active].items.len - 1);
        mepo.pin_group_active_item = null;
    }
}

M src/config.zig => src/config.zig +10 -10
@@ 32,16 32,16 @@ pub const DefaultBaseConfig =
    \\ bind_button 1 -1 [Del] [pin_delete -1 []; pin_cycle 0 1; center_on_pin] [];
    \\ bind_button 1 -1 [>] [pin_cycle 0 1; center_on_pin] [];
    \\ bind_button 1 -1 [<] [pin_cycle 0 -1; center_on_pin] [];
    \\ bind_button 1 9 [9] [pin_transfer -1 [] 9] [];
    \\ bind_button 1 8 [8] [pin_transfer -1 [] 8] [];
    \\ bind_button 1 7 [7] [pin_transfer -1 [] 7] [];
    \\ bind_button 1 6 [6] [pin_transfer -1 [] 6] [];
    \\ bind_button 1 5 [5] [pin_transfer -1 [] 5] [];
    \\ bind_button 1 4 [4] [pin_transfer -1 [] 4] [];
    \\ bind_button 1 3 [3] [pin_transfer -1 [] 3] [];
    \\ bind_button 1 2 [2] [pin_transfer -1 [] 2] [];
    \\ bind_button 1 1 [1] [pin_transfer -1 [] 1] [];
    \\ bind_button 1 0 [0] [pin_transfer -1 [] 0] [];
    \\ bind_button 1 9 [9] [pin_transfer -1 [] 9] [pin_transfer -1 [all] 9];
    \\ bind_button 1 8 [8] [pin_transfer -1 [] 8] [pin_transfer -1 [all] 8];
    \\ bind_button 1 7 [7] [pin_transfer -1 [] 7] [pin_transfer -1 [all] 7];
    \\ bind_button 1 6 [6] [pin_transfer -1 [] 6] [pin_transfer -1 [all] 6];
    \\ bind_button 1 5 [5] [pin_transfer -1 [] 5] [pin_transfer -1 [all] 5];
    \\ bind_button 1 4 [4] [pin_transfer -1 [] 4] [pin_transfer -1 [all] 4];
    \\ bind_button 1 3 [3] [pin_transfer -1 [] 3] [pin_transfer -1 [all] 3];
    \\ bind_button 1 2 [2] [pin_transfer -1 [] 2] [pin_transfer -1 [all] 2];
    \\ bind_button 1 1 [1] [pin_transfer -1 [] 1] [pin_transfer -1 [all] 1];
    \\ bind_button 1 0 [0] [pin_transfer -1 [] 0] [pin_transfer -1 [all] 0];
    \\
    \\ # Gestures;
    \\ bind_gesture pan 2 1 [zoom_relative 1];

M src/types.zig => src/types.zig +1 -1
@@ 21,7 21,7 @@ pub const PinGroup = struct {
pub const UIButton = struct {
    text: [:0]const u8,
    mepolang_click_single: [:0]const u8,
    mepolang_click_double: [:0]const u8,
    mepolang_click_hold: [:0]const u8,
    only_visible_when_has_pins: bool,
    group_number: ?u8,
};