~mil/mepo

866e0692d49102af388a3f4d91edda088078f07f — Miles Alan a month ago 17d316a
Rework prefrences system to use enum keys rather then string / loop lookup

Gives O(1) rather then O(n) perf for preference lookups
M src/Mepo.zig => src/Mepo.zig +42 -42
@@ 7,7 7,7 @@ const TileCache = @import("./TileCache.zig");
const utilconversion = @import("./util/utilconversion.zig");
const utilmepolang = @import("util/utilmepolang.zig");
const utilplatform = @import("util/utilplatform.zig");
const utilprefs = @import("util/utilprefs.zig");
const p = @import("util/utilprefs.zig");
const utildbg = @import("util/utildbg.zig");
const utilsdl = @import("util/utilsdl.zig");
const zoom_relative = @import("./api/zoom_relative.zig").zoom_relative;


@@ 49,23 49,23 @@ fn blit_crosshair(mepo: *@This()) errors.SDLError!void {
    try utilsdl.sdl_renderer_set_draw_color(mepo.renderer, .{ .value = 0x000000 });
    try utilsdl.errorcheck(sdl.SDL_RenderDrawLine(
        mepo.renderer,
        @intCast(c_int, mepo.win_w / 2 - (utilprefs.get("crosshair_size").u / 2)),
        @intCast(c_int, mepo.win_w / 2 - (p.get(p.pref.crosshair_size).u / 2)),
        @intCast(c_int, mepo.win_h / 2),
        @intCast(c_int, mepo.win_w / 2 + (utilprefs.get("crosshair_size").u / 2)),
        @intCast(c_int, mepo.win_w / 2 + (p.get(p.pref.crosshair_size).u / 2)),
        @intCast(c_int, mepo.win_h / 2),
    ));
    try utilsdl.errorcheck(sdl.SDL_RenderDrawLine(
        mepo.renderer,
        @intCast(c_int, mepo.win_w / 2),
        @intCast(c_int, mepo.win_h / 2 - (utilprefs.get("crosshair_size").u / 2)),
        @intCast(c_int, mepo.win_h / 2 - (p.get(p.pref.crosshair_size).u / 2)),
        @intCast(c_int, mepo.win_w / 2),
        @intCast(c_int, mepo.win_h / 2 + (utilprefs.get("crosshair_size").u / 2)),
        @intCast(c_int, mepo.win_h / 2 + (p.get(p.pref.crosshair_size).u / 2)),
    ));
}

pub fn blit_tiles_all(mepo: *@This(), bbox: sdl.SDL_Rect, zoom: u8) !void {
    const vpx = utilconversion.lon_to_px_x(utilprefs.get("lon").f, zoom) - @divTrunc(@intCast(i32, mepo.win_w), 2);
    const vpy = utilconversion.lat_to_px_y(utilprefs.get("lat").f, zoom) - @divTrunc(@intCast(i32, mepo.win_h), 2);
    const vpx = utilconversion.lon_to_px_x(p.get(p.pref.lon).f, zoom) - @divTrunc(@intCast(i32, mepo.win_w), 2);
    const vpy = utilconversion.lat_to_px_y(p.get(p.pref.lat).f, zoom) - @divTrunc(@intCast(i32, mepo.win_h), 2);
    const begx = vpx - config.Tsize;
    const begy = vpy - config.Tsize;
    const endx = vpx + @intCast(i32, bbox.w) + config.Tsize;


@@ 99,7 99,7 @@ pub fn blit_tiles_all(mepo: *@This(), bbox: sdl.SDL_Rect, zoom: u8) !void {
}

pub fn blit_tile_text(mepo: *@This(), tile_x: u32, tile_y: u32, zoom: u8, x_off: i32, y_off: i32) !void {
    if (!utilprefs.get("debug_tiles").b) return;
    if (!p.get(p.pref.debug_tiles).b) return;
    var dl_now: c_long = 0;
    var dl_total: c_long = 0;



@@ 188,9 188,9 @@ pub fn blit_tile_surface(mepo: *@This(), tile_x: u32, tile_y: u32, zoom: u8, x_o
}

fn blit_overlay_pindetails(mepo: *@This()) !void {
    if (!utilprefs.get("overlay_pindetails").b) return;
    if (!p.get(p.pref.overlay_pindetails).b) return;

    const d_unit_km = utilprefs.get("distance_unit_tf_km_mi").b;
    const d_unit_km = p.get(p.pref.distance_unit_tf_km_mi).b;
    const d_unit = if (d_unit_km) "km" else "mi";

    var arena = std.heap.ArenaAllocator.init(mepo.allocator);


@@ 203,8 203,8 @@ fn blit_overlay_pindetails(mepo: *@This()) !void {
        const distance_str = try std.fmt.allocPrintZ(arena.allocator(), "{d:.2}{s} away", .{
            utilconversion.distance_haversine(
                if (d_unit_km) .Km else .Mi,
                utilprefs.get("lat").f,
                utilprefs.get("lon").f,
                p.get(p.pref.lat).f,
                p.get(p.pref.lon).f,
                pin.lat,
                pin.lon,
            ),


@@ 238,8 238,8 @@ fn blit_overlay_pindetails(mepo: *@This()) !void {
}

fn blit_debugmessage(mepo: *@This()) !void {
    if (utilprefs.get("debug_message_enabled").b and mepo.debug_message != null) {
        const bottom_off: u32 = if (utilprefs.get("overlay_debugbar").b) utilprefs.get("fontsize_ui").u + 10 else 5;
    if (p.get(p.pref.debug_message_enabled).b and mepo.debug_message != null) {
        const bottom_off: u32 = if (p.get(p.pref.overlay_debugbar).b) p.get(p.pref.fontsize_ui).u + 10 else 5;
        try mepo.blit_multiline_text(
            0xff0000,
            null,


@@ 284,7 284,7 @@ fn blit_pin(mepo: *@This(), pin: types.Pin, prev_pin: ?types.Pin, pin_group: u8,
            .{},
            x,
            y,
            config.ZoomLevelToPinFontSize[utilprefs.get("zoom").u],
            config.ZoomLevelToPinFontSize[p.get(p.pref.zoom).u],
            "{s}",
            .{pin.name},
        );


@@ 345,8 345,8 @@ fn blit_pins(mepo: *@This()) !void {
}

fn blit_overlay_debugbar(mepo: *@This()) !void {
    if (!utilprefs.get("overlay_debugbar").b) return;
    const bottombar_height = utilprefs.get("fontsize_ui").u + 5;
    if (!p.get(p.pref.overlay_debugbar).b) return;
    const bottombar_height = p.get(p.pref.fontsize_ui).u + 5;

    const bg: types.Color = color: {
        if (mepo.tile_cache.thread_download == null) {


@@ 393,9 393,9 @@ fn blit_overlay_debugbar(mepo: *@This()) !void {
        null,
        "{d:.3} {d:.3} Z:{d} O:{d}, Q:{d}, B:{d}, D:{d}, M:{d}",
        .{
            utilprefs.get("lat").f,
            utilprefs.get("lon").f,
            utilprefs.get("zoom").u,
            p.get(p.pref.lat).f,
            p.get(p.pref.lon).f,
            p.get(p.pref.zoom).u,
            @boolToInt(mepo.tile_cache.thread_download != null),
            mepo.tile_cache.queue_lifo_ui.count(),
            mepo.tile_cache.queue_lifo_bg.count(),


@@ 406,7 406,7 @@ fn blit_overlay_debugbar(mepo: *@This()) !void {
}

fn blit_help(mepo: *@This()) !void {
    if (!utilprefs.get("help").b) return;
    if (!p.get(p.pref.help).b) return;

    var msg = msg: {
        var acc = std.ArrayList([]const u8).init(mepo.allocator);


@@ 452,7 452,7 @@ fn blit_uibuttons(mepo: *@This(), determine_click_target: ?sdl.SDL_MouseButtonEv
    var btn_i = mepo.uibuttons.items.len;
    const pad: c_int = 5;
    var right_pad: c_int = 10;
    const pad_bottom: c_int = utilprefs.get("fontsize_ui").u + 10;
    const pad_bottom: c_int = p.get(p.pref.fontsize_ui).u + 10;

    while (btn_i > 0) {
        btn_i -= 1;


@@ 462,7 462,7 @@ fn blit_uibuttons(mepo: *@This(), determine_click_target: ?sdl.SDL_MouseButtonEv

        const surf = try utilsdl.errorcheck_ptr(
            sdl.SDL_Surface,
            sdl.TTF_RenderText_Blended(mepo.fonts_bold[utilprefs.get("fontsize_ui").u], @ptrCast([*c]const u8, mepo.uibuttons.items[btn_i].text), (types.Color{ .value = 0x000000 }).to_sdl()),
            sdl.TTF_RenderText_Blended(mepo.fonts_bold[p.get(p.pref.fontsize_ui).u], @ptrCast([*c]const u8, mepo.uibuttons.items[btn_i].text), (types.Color{ .value = 0x000000 }).to_sdl()),
        );
        defer sdl.SDL_FreeSurface(surf);



@@ 524,7 524,7 @@ pub fn blit(mepo: *@This()) !void {
            .w = @intCast(c_int, mepo.win_w),
            .h = @intCast(c_int, mepo.win_h),
        },
        utilprefs.get("zoom").u,
        p.get(p.pref.zoom).u,
    );
    try mepo.blit_pins();
    try mepo.blit_crosshair();


@@ 541,7 541,7 @@ pub fn blit(mepo: *@This()) !void {
    // specified config frequency
    if (sdl.SDL_GetTicks() > mepo.title_update_ms + config.TitleUpdateFrequencyMs) {
        mepo.title_update_ms = sdl.SDL_GetTicks();
        const title = try std.fmt.allocPrintZ(mepo.allocator, "mepo - {d:.5} lat, {d:.5} lon", .{ utilprefs.get("lat").f, utilprefs.get("lon").f });
        const title = try std.fmt.allocPrintZ(mepo.allocator, "mepo - {d:.5} lat, {d:.5} lon", .{ p.get(p.pref.lat).f, p.get(p.pref.lon).f });
        defer mepo.allocator.free(title);
        _ = sdl.SDL_SetWindowTitle(mepo.window, title);
    }


@@ 549,8 549,8 @@ pub fn blit(mepo: *@This()) !void {

pub fn convert_latlon_to_xy(mepo: *@This(), lat_or_lon: enum { LonToX, LatToY }, lat_lon_value: f64) i32 {
    return switch (lat_or_lon) {
        .LonToX => -1 * (mepo.get_x() - @divTrunc(@intCast(i32, mepo.win_w), 2) - utilconversion.lon_to_px_x(lat_lon_value, utilprefs.get("zoom").u)),
        .LatToY => -1 * (mepo.get_y() - @divTrunc(@intCast(i32, mepo.win_h), 2) - utilconversion.lat_to_px_y(lat_lon_value, utilprefs.get("zoom").u)),
        .LonToX => -1 * (mepo.get_x() - @divTrunc(@intCast(i32, mepo.win_w), 2) - utilconversion.lon_to_px_x(lat_lon_value, p.get(p.pref.zoom).u)),
        .LatToY => -1 * (mepo.get_y() - @divTrunc(@intCast(i32, mepo.win_h), 2) - utilconversion.lat_to_px_y(lat_lon_value, p.get(p.pref.zoom).u)),
    };
}



@@ 709,8 709,8 @@ fn event_mousemotion(mepo: *@This(), e: sdl.SDL_Event) types.Pending {
        mepo.drag.?.point.y = e.motion.y;
        mepo.drag.?.delta_x += std.math.absInt(e.motion.xrel) catch unreachable;
        mepo.drag.?.delta_y += std.math.absInt(e.motion.yrel) catch unreachable;
        mepo.set_x(mepo.get_x() - (e.motion.xrel * utilprefs.get("drag_scale").u));
        mepo.set_y(mepo.get_y() - (e.motion.yrel * utilprefs.get("drag_scale").u));
        mepo.set_x(mepo.get_x() - (e.motion.xrel * p.get(p.pref.drag_scale).u));
        mepo.set_y(mepo.get_y() - (e.motion.yrel * p.get(p.pref.drag_scale).u));
        return .Drag;
    } else {
        mepo.drag = null;


@@ 1006,12 1006,12 @@ fn blit_table(mepo: *@This(), x: i32, y: i32, padding: c_int, rows: []const [2][
    for (rows) |row| {
        const surf_lab = try utilsdl.errorcheck_ptr(
            sdl.SDL_Surface,
            sdl.TTF_RenderText_Blended(mepo.fonts_bold[utilprefs.get("fontsize_ui").u], @ptrCast([*c]const u8, row[0]), (types.Color{ .value = 0x000000 }).to_sdl()),
            sdl.TTF_RenderText_Blended(mepo.fonts_bold[p.get(p.pref.fontsize_ui).u], @ptrCast([*c]const u8, row[0]), (types.Color{ .value = 0x000000 }).to_sdl()),
        );
        defer sdl.SDL_FreeSurface(surf_lab);
        const surf_val = try utilsdl.errorcheck_ptr(
            sdl.SDL_Surface,
            sdl.TTF_RenderText_Blended(mepo.fonts_normal[utilprefs.get("fontsize_ui").u], @ptrCast([*c]const u8, row[1]), (types.Color{ .value = 0x000000 }).to_sdl()),
            sdl.TTF_RenderText_Blended(mepo.fonts_normal[p.get(p.pref.fontsize_ui).u], @ptrCast([*c]const u8, row[1]), (types.Color{ .value = 0x000000 }).to_sdl()),
        );
        defer sdl.SDL_FreeSurface(surf_val);
        width_label = std.math.max(width_label, surf_lab.w);


@@ 1045,7 1045,7 @@ fn blit_table(mepo: *@This(), x: i32, y: i32, padding: c_int, rows: []const [2][
        // Label
        const surf_lab = try utilsdl.errorcheck_ptr(
            sdl.SDL_Surface,
            sdl.TTF_RenderText_Blended(mepo.fonts_bold[utilprefs.get("fontsize_ui").u], @ptrCast([*c]const u8, row[0]), (types.Color{ .value = 0x000000 }).to_sdl()),
            sdl.TTF_RenderText_Blended(mepo.fonts_bold[p.get(p.pref.fontsize_ui).u], @ptrCast([*c]const u8, row[0]), (types.Color{ .value = 0x000000 }).to_sdl()),
        );
        const text_lab = try utilsdl.errorcheck_ptr(sdl.SDL_Texture, sdl.SDL_CreateTextureFromSurface(mepo.renderer, surf_lab));
        defer sdl.SDL_FreeSurface(surf_lab);


@@ 1060,7 1060,7 @@ fn blit_table(mepo: *@This(), x: i32, y: i32, padding: c_int, rows: []const [2][
        // Value
        const surf_value = try utilsdl.errorcheck_ptr(
            sdl.SDL_Surface,
            sdl.TTF_RenderText_Blended(mepo.fonts_normal[utilprefs.get("fontsize_ui").u], @ptrCast([*c]const u8, row[1]), (types.Color{ .value = 0x000000 }).to_sdl()),
            sdl.TTF_RenderText_Blended(mepo.fonts_normal[p.get(p.pref.fontsize_ui).u], @ptrCast([*c]const u8, row[1]), (types.Color{ .value = 0x000000 }).to_sdl()),
        );
        const text_value = try utilsdl.errorcheck_ptr(sdl.SDL_Texture, sdl.SDL_CreateTextureFromSurface(mepo.renderer, surf_value));
        defer sdl.SDL_FreeSurface(surf_value);


@@ 1101,7 1101,7 @@ pub fn blit_multiline_text(
        if (font_size_opt) |font_size| {
            if (font_size > mepo.fonts_normal.len) return error.FontTooBig else break :font_size font_size;
        } else {
            break :font_size utilprefs.get("fontsize_ui").u;
            break :font_size p.get(p.pref.fontsize_ui).u;
        }
    };



@@ 1193,27 1193,27 @@ pub fn update_debug_message(mepo: *@This(), new_msg_opt: ?[]const u8) !void {
}

pub fn get_x(_: *@This()) i32 {
    return utilconversion.lon_to_px_x(utilprefs.get("lon").f, utilprefs.get("zoom").u);
    return utilconversion.lon_to_px_x(p.get(p.pref.lon).f, p.get(p.pref.zoom).u);
}

pub fn get_y(_: *@This()) i32 {
    return utilconversion.lat_to_px_y(utilprefs.get("lat").f, utilprefs.get("zoom").u);
    return utilconversion.lat_to_px_y(p.get(p.pref.lat).f, p.get(p.pref.zoom).u);
}

pub fn set_x(_: *@This(), x: i32) void {
    utilprefs.set_n("lon", utilconversion.px_x_to_lon(x, utilprefs.get("zoom").u));
    p.set_n(p.pref.lon, utilconversion.px_x_to_lon(x, p.get(p.pref.zoom).u));
}

pub fn set_y(_: *@This(), y: i32) void {
    utilprefs.set_n("lat", utilconversion.px_y_to_lat(y, utilprefs.get("zoom").u));
    p.set_n(p.pref.lat, utilconversion.px_y_to_lat(y, p.get(p.pref.zoom).u));
}

pub fn bounding_box(mepo: *@This()) types.LatLonBox {
    return .{
        .topleft_lat = utilconversion.px_y_to_lat(mepo.get_y() - @divTrunc(@intCast(i32, mepo.win_h), @intCast(i32, 2)), utilprefs.get("zoom").u),
        .topleft_lon = utilconversion.px_x_to_lon(mepo.get_x() - @divTrunc(@intCast(i32, mepo.win_w), @intCast(i32, 2)), utilprefs.get("zoom").u),
        .bottomright_lat = utilconversion.px_y_to_lat(mepo.get_y() + @divTrunc(@intCast(i32, mepo.win_h), @intCast(i32, 2)), utilprefs.get("zoom").u),
        .bottomright_lon = utilconversion.px_x_to_lon(mepo.get_x() + @divTrunc(@intCast(i32, mepo.win_w), @intCast(i32, 2)), utilprefs.get("zoom").u),
        .topleft_lat = utilconversion.px_y_to_lat(mepo.get_y() - @divTrunc(@intCast(i32, mepo.win_h), @intCast(i32, 2)), p.get(p.pref.zoom).u),
        .topleft_lon = utilconversion.px_x_to_lon(mepo.get_x() - @divTrunc(@intCast(i32, mepo.win_w), @intCast(i32, 2)), p.get(p.pref.zoom).u),
        .bottomright_lat = utilconversion.px_y_to_lat(mepo.get_y() + @divTrunc(@intCast(i32, mepo.win_h), @intCast(i32, 2)), p.get(p.pref.zoom).u),
        .bottomright_lon = utilconversion.px_x_to_lon(mepo.get_x() + @divTrunc(@intCast(i32, mepo.win_w), @intCast(i32, 2)), p.get(p.pref.zoom).u),
    };
}


M src/TileCache.zig => src/TileCache.zig +12 -12
@@ 12,7 12,7 @@ const utilsdl = @import("./util/utilsdl.zig");
const utilconversion = @import("./util/utilconversion.zig");
const utilfile = @import("./util/utilfile.zig");
const utildbg = @import("./util/utildbg.zig");
const utilprefs = @import("./util/utilprefs.zig");
const p = @import("./util/utilprefs.zig");
const datastructure = @import("./datastructure/datastructure.zig");

pub const DownloadBBoxRequest = struct {


@@ 81,13 81,13 @@ pub fn download_loop(tile_cache: *@This(), graphical_mode: bool) !void {
        }

        // 2. Transfer from UI LIFO into transfers
        while (tile_cache.queue_lifo_ui.count() > 0 and tile_cache.transfer_map.count() < utilprefs.get("tile_cache_max_n_transfers").u) {
        while (tile_cache.queue_lifo_ui.count() > 0 and tile_cache.transfer_map.count() < p.get(p.pref.tile_cache_max_n_transfers).u) {
            var coords = tile_cache.queue_lifo_ui.pop();
            try tile_cache.curl_add_to_multi_and_register_transfer(coords.key, true);
        }

        // 3. Transfer from BG LIFO into transfers
        while (tile_cache.queue_lifo_bg.count() > 0 and tile_cache.transfer_map.count() < utilprefs.get("tile_cache_max_n_transfers").u) {
        while (tile_cache.queue_lifo_bg.count() > 0 and tile_cache.transfer_map.count() < p.get(p.pref.tile_cache_max_n_transfers).u) {
            var coords = tile_cache.queue_lifo_bg.pop();
            try tile_cache.curl_add_to_multi_and_register_transfer(coords.key, false);
        }


@@ 133,13 133,13 @@ pub fn set_cache_url(tile_cache: *@This(), url: [:0]const u8) !void {
    tile_cache.queue_lifo_ui.clearAndFree();
    tile_cache.queue_lifo_bg.clearAndFree();

    try utilprefs.set_t(tile_cache.allocator, "tile_cache_url", url);
    try p.set_t(tile_cache.allocator, p.pref.tile_cache_url, url);
}

pub fn set_cache_dir(tile_cache: *@This(), path: [:0]const u8) !void {
    try utilprefs.set_t(tile_cache.allocator, "tile_cache_dir", path);
    try p.set_t(tile_cache.allocator, p.pref.tile_cache_dir, path);

    const expanded_path = try utilfile.wordexp_filepath(tile_cache.allocator, utilprefs.get("tile_cache_dir").t.?);
    const expanded_path = try utilfile.wordexp_filepath(tile_cache.allocator, p.get(p.pref.tile_cache_dir).t.?);
    defer tile_cache.allocator.free(expanded_path);
    try std.fs.cwd().makePath(expanded_path);
    tile_cache.cache_dir = try std.fs.cwd().openDir(expanded_path, .{ .iterate = true });


@@ 254,7 254,7 @@ pub fn tile_ui_retreive_or_queue(tile_cache: *@This(), coords: types.XYZ) !TileD

        // Load tile to surface
        {
            const png = try png_path(tile_cache.allocator, utilprefs.get("tile_cache_url").t.?, coords);
            const png = try png_path(tile_cache.allocator, p.get(p.pref.tile_cache_url).t.?, coords);
            defer tile_cache.allocator.free(png);
            file_cached_png_opt = cache_dir.readFileAlloc(tile_cache.allocator, png, 500000) catch null;
            if (file_cached_png_opt) |file_cached_png| {


@@ 306,10 306,10 @@ fn curl_add_to_multi_and_register_transfer(tile_cache: *@This(), coords: types.X
    try tile_cache.transfer_map.put(coords, transfer_datum);

    var tile_url = url: {
        var url = try tile_cache.allocator.alloc(u8, utilprefs.get("tile_cache_url").t.?.len + (3 * 10));
        var url = try tile_cache.allocator.alloc(u8, p.get(p.pref.tile_cache_url).t.?.len + (3 * 10));
        if (cstdio.sprintf(
            &url[0],
            utilprefs.get("tile_cache_url").t.?,
            p.get(p.pref.tile_cache_url).t.?,
            @intCast(c_int, coords.x),
            @intCast(c_int, coords.y),
            @intCast(c_int, coords.z),


@@ 424,7 424,7 @@ fn download_loop_transfer_complete(tile_cache: *@This(), msg: *curl.CURLMsg) !vo

                if (tile_cache.cache_dir) |cache_dir| {
                    // Save to FS
                    const path = try png_path(tile_cache.allocator, utilprefs.get("tile_cache_url").t.?, coords);
                    const path = try png_path(tile_cache.allocator, p.get(p.pref.tile_cache_url).t.?, coords);
                    try cache_dir.writeFile(path, datum_array);
                }
                if (tile_cache.transfer_map.get(coords).?.load_to_texture) {


@@ 480,11 480,11 @@ fn png_path(allocator: std.mem.Allocator, source: []const u8, coords: types.XYZ)
/// to creation time & expiry seconds setting
fn tile_exists_in_fs_and_non_expired(tile_cache: *@This(), coords: types.XYZ) !bool {
    if (tile_cache.cache_dir) |cache_dir| {
        const png = try png_path(tile_cache.allocator, utilprefs.get("tile_cache_url").t.?, coords);
        const png = try png_path(tile_cache.allocator, p.get(p.pref.tile_cache_url).t.?, coords);
        defer tile_cache.allocator.free(png);
        const tile_file = cache_dir.openFile(png, .{}) catch return false;
        defer tile_file.close();
        const expiry_seconds = @floatToInt(i32, utilprefs.get("tile_cache_expiry_seconds").f);
        const expiry_seconds = @floatToInt(i32, p.get(p.pref.tile_cache_expiry_seconds).f);
        if (expiry_seconds < 0 or std.time.timestamp() < (try tile_file.stat()).ctime + expiry_seconds) {
            return true;
        }

M src/api/center_on_coords.zig => src/api/center_on_coords.zig +3 -3
@@ 1,7 1,7 @@
const Mepo = @import("../Mepo.zig");
const types = @import("../types.zig");
const std = @import("std");
const utilprefs = @import("../util/utilprefs.zig");
const p = @import("../util/utilprefs.zig");

pub const spec = .{
    .name = "center_on_coords",


@@ 16,6 16,6 @@ pub const spec = .{
fn execute(_: *Mepo, args: [types.MepoFnNargs]types.MepoArg) !void {
    const lat = args[0].Number;
    const lon = args[1].Number;
    utilprefs.set_n("lat", lat);
    utilprefs.set_n("lon", lon);
    p.set_n(p.pref.lat, lat);
    p.set_n(p.pref.lon, lon);
}

M src/api/center_on_pin.zig => src/api/center_on_pin.zig +3 -3
@@ 1,7 1,7 @@
const Mepo = @import("../Mepo.zig");
const types = @import("../types.zig");
const std = @import("std");
const utilprefs = @import("../util/utilprefs.zig");
const p = @import("../util/utilprefs.zig");

pub const spec = .{
    .name = "center_on_pin",


@@ 13,7 13,7 @@ pub const spec = .{
fn execute(mepo: *Mepo, _: [types.MepoFnNargs]types.MepoArg) !void {
    if (mepo.pin_group_active_item != null) {
        const pin = mepo.pin_groups[mepo.pin_group_active].pins.items[mepo.pin_group_active_item.?];
        utilprefs.set_n("lat", pin.lat);
        utilprefs.set_n("lon", pin.lon);
        p.set_n(p.pref.lat, pin.lat);
        p.set_n(p.pref.lon, pin.lon);
    }
}

M src/api/clipcopy.zig => src/api/clipcopy.zig +2 -2
@@ 4,7 4,7 @@ const std = @import("std");
const sdl = @import("../sdlshim.zig");
const utildbg = @import("../util/utildbg.zig");
const utilsdl = @import("../util/utilsdl.zig");
const utilprefs = @import("../util/utilprefs.zig");
const p = @import("../util/utilprefs.zig");

pub const spec = .{
    .name = "clipcopy",


@@ 17,7 17,7 @@ fn execute(mepo: *Mepo, _: [types.MepoFnNargs]types.MepoArg) !void {
    const copy_text = try std.fmt.allocPrintZ(
        mepo.allocator,
        "{d:.5}, {d:.5}",
        .{ utilprefs.get("lat").f, utilprefs.get("lon").f },
        .{ p.get(p.pref.lat).f, p.get(p.pref.lon).f },
    );
    defer mepo.allocator.free(copy_text);
    try utilsdl.errorcheck(sdl.SDL_SetClipboardText(copy_text));

M src/api/clippaste.zig => src/api/clippaste.zig +3 -3
@@ 4,7 4,7 @@ const std = @import("std");
const sdl = @import("../sdlshim.zig");
const utildbg = @import("../util/utildbg.zig");
const utilsdl = @import("../util/utilsdl.zig");
const utilprefs = @import("../util/utilprefs.zig");
const p = @import("../util/utilprefs.zig");

pub const spec = .{
    .name = "clippaste",


@@ 39,8 39,8 @@ fn execute(mepo: *Mepo, _: [types.MepoFnNargs]types.MepoArg) !void {
        }

        if (lat == null or lon == null) break :parse_lat_lon;
        utilprefs.set_n("lat", lat.?);
        utilprefs.set_n("lon", lon.?);
        p.set_n(p.pref.lat, lat.?);
        p.set_n(p.pref.lon, lon.?);
        return;
    }


M src/api/prefinc.zig => src/api/prefinc.zig +5 -3
@@ 2,7 2,7 @@ const Mepo = @import("../Mepo.zig");
const types = @import("../types.zig");
const std = @import("std");
const utildbg = @import("../util/utildbg.zig");
const utilprefs = @import("../util/utilprefs.zig");
const p = @import("../util/utilprefs.zig");

pub const spec = .{
    .name = "prefinc",


@@ 18,6 18,8 @@ fn execute(_: *Mepo, args: [types.MepoFnNargs]types.MepoArg) !void {
    const name = args[0].Text;
    const delta = args[1].Number;

    const val = utilprefs.get(name).u;
    utilprefs.set_n(name, @intToFloat(f64, val) + delta);
    if (p.lookup_pref_from_string(name)) |key| {
        const val = p.get(key).u;
        p.set_n(key, @intToFloat(f64, val) + delta);
    }
}

M src/api/prefset_n.zig => src/api/prefset_n.zig +2 -2
@@ 2,7 2,7 @@ const Mepo = @import("../Mepo.zig");
const types = @import("../types.zig");
const std = @import("std");
const utildbg = @import("../util/utildbg.zig");
const utilprefs = @import("../util/utilprefs.zig");
const p = @import("../util/utilprefs.zig");

pub const spec = .{
    .name = "prefset_n",


@@ 22,5 22,5 @@ fn execute(mepo: *Mepo, args: [types.MepoFnNargs]types.MepoArg) !void {
    if (std.mem.eql(u8, "tile_cache_network", name)) {
        mepo.tile_cache.set_network(value == 1);
    }
    utilprefs.set_n(name, value);
    if (p.lookup_pref_from_string(name)) |key| p.set_n(key, value);
}

M src/api/preftoggle.zig => src/api/preftoggle.zig +3 -3
@@ 2,7 2,7 @@ const Mepo = @import("../Mepo.zig");
const types = @import("../types.zig");
const std = @import("std");
const utildbg = @import("../util/utildbg.zig");
const utilprefs = @import("../util/utilprefs.zig");
const p = @import("../util/utilprefs.zig");

pub const spec = .{
    .name = "preftoggle",


@@ 20,8 20,8 @@ fn execute(mepo: *Mepo, args: [types.MepoFnNargs]types.MepoArg) !void {
    if (std.mem.eql(u8, "tile_cache_network", name)) {
        const network_on = !(mepo.tile_cache.thread_download != null);
        mepo.tile_cache.set_network(network_on);
        utilprefs.set_n(name, if (network_on) 1 else 0);
        if (p.lookup_pref_from_string(name)) |key| p.set_n(key, if (network_on) 1 else 0);
    } else {
        utilprefs.toggle_bool(name);
        if (p.lookup_pref_from_string(name)) |key| p.toggle_bool(key);
    }
}

M src/api/shellpipe.zig => src/api/shellpipe.zig +6 -6
@@ 5,7 5,7 @@ const utilconversion = @import("../util/utilconversion.zig");
const utilplatform = @import("../util/utilplatform.zig");
const utildbg = @import("../util/utildbg.zig");
const utilsdl = @import("../util/utilsdl.zig");
const utilprefs = @import("../util/utilprefs.zig");
const p = @import("../util/utilprefs.zig");
const sdl = @import("../sdlshim.zig");

const ShellpipeRequest = struct {


@@ 154,17 154,17 @@ fn get_env_vars(mepo: *Mepo, allocator: std.mem.Allocator) !std.BufMap {
    var cursor_x: c_int = undefined;
    var cursor_y: c_int = undefined;
    _ = sdl.SDL_GetMouseState(&cursor_x, &cursor_y);
    const cursor_lat = utilconversion.px_y_to_lat(mepo.get_y() - @divTrunc(@intCast(i32, mepo.win_h), 2) + cursor_y, utilprefs.get("zoom").u);
    const cursor_lon = utilconversion.px_x_to_lon(mepo.get_x() - @divTrunc(@intCast(i32, mepo.win_w), 2) + cursor_x, utilprefs.get("zoom").u);
    const cursor_lat = utilconversion.px_y_to_lat(mepo.get_y() - @divTrunc(@intCast(i32, mepo.win_h), 2) + cursor_y, p.get(p.pref.zoom).u);
    const cursor_lon = utilconversion.px_x_to_lon(mepo.get_x() - @divTrunc(@intCast(i32, mepo.win_w), 2) + cursor_x, p.get(p.pref.zoom).u);

    // Window and zoom info
    try v.put("MEPO_WIN_W", try std.fmt.allocPrint(allocator, "{d}", .{mepo.win_w}));
    try v.put("MEPO_WIN_H", try std.fmt.allocPrint(allocator, "{d}", .{mepo.win_h}));
    try v.put("MEPO_ZOOM", try std.fmt.allocPrint(allocator, "{d}", .{utilprefs.get("zoom").u}));
    try v.put("MEPO_ZOOM", try std.fmt.allocPrint(allocator, "{d}", .{p.get(p.pref.zoom).u}));

    // Center and bbox
    try v.put("MEPO_CENTER_LAT", try std.fmt.allocPrint(allocator, "{d}", .{utilprefs.get("lat").f}));
    try v.put("MEPO_CENTER_LON", try std.fmt.allocPrint(allocator, "{d}", .{utilprefs.get("lon").f}));
    try v.put("MEPO_CENTER_LAT", try std.fmt.allocPrint(allocator, "{d}", .{p.get(p.pref.lat).f}));
    try v.put("MEPO_CENTER_LON", try std.fmt.allocPrint(allocator, "{d}", .{p.get(p.pref.lon).f}));
    try v.put("MEPO_TL_LAT", try std.fmt.allocPrint(allocator, "{d}", .{bbox.topleft_lat}));
    try v.put("MEPO_TL_LON", try std.fmt.allocPrint(allocator, "{d}", .{bbox.topleft_lon}));
    try v.put("MEPO_BR_LAT", try std.fmt.allocPrint(allocator, "{d}", .{bbox.bottomright_lat}));

M src/api/zoom_relative.zig => src/api/zoom_relative.zig +2 -2
@@ 1,7 1,7 @@
const Mepo = @import("../Mepo.zig");
const types = @import("../types.zig");
const std = @import("std");
const utilprefs = @import("../util/utilprefs.zig");
const p = @import("../util/utilprefs.zig");

pub const spec = .{
    .name = "zoom_relative",


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

pub fn zoom_relative(_: *Mepo, relative: i32) void {
    utilprefs.set_n("zoom", @intToFloat(f64, @intCast(u8, std.math.min(19, std.math.max(0, @intCast(i32, utilprefs.get("zoom").u) + relative)))));
    p.set_n(p.pref.zoom, @intToFloat(f64, @intCast(u8, std.math.min(19, std.math.max(0, @intCast(i32, p.get(p.pref.zoom).u) + relative)))));
}

M src/util/utildbg.zig => src/util/utildbg.zig +2 -2
@@ 1,6 1,6 @@
const std = @import("std");
const utilprefs = @import("./utilprefs.zig");
const p = @import("./utilprefs.zig");

pub fn log(comptime msg: []const u8, args: anytype) void {
    if (utilprefs.get("debug_stderr").b) std.debug.print(msg, args);
    if (p.get(p.pref.debug_stderr).b) std.debug.print(msg, args);
}

M src/util/utilprefs.zig => src/util/utilprefs.zig +67 -67
@@ 2,6 2,28 @@ const std = @import("std");

const PrefValueEnum = enum { b, t, f, u };
const PrefValueUnion = union(PrefValueEnum) { b: bool, t: ?[:0]const u8, f: f64, u: u8 };

pub const pref = enum(u8) {
    lat,
    lon,
    zoom,
    debug_message_enabled,
    distance_unit_tf_km_mi,
    overlay_debugbar,
    help,
    overlay_pindetails,
    crosshair_size,
    drag_scale,
    fontsize_ui,
    debug_tiles,
    debug_stderr,
    tile_cache_max_n_transfers,
    tile_cache_expiry_seconds,
    tile_cache_network,
    tile_cache_dir,
    tile_cache_url,
};

const PrefMapping = struct {
    name: []const u8,
    value: PrefValueUnion,


@@ 11,85 33,63 @@ const PrefMapping = struct {
const n_prefs = 18;
pub var prefs_mapping: [n_prefs]PrefMapping = mapping: {
    var mapping: [n_prefs]PrefMapping = undefined;
    mapping[0] = .{ .name = "lat", .value = .{ .f = 40.78392 }, .desc = "TODO" };
    mapping[1] = .{ .name = "lon", .value = .{ .f = -73.96442 }, .desc = "TODO" };
    mapping[2] = .{ .name = "zoom", .value = .{ .u = 14 }, .desc = "TODO" };
    mapping[3] = .{ .name = "debug_message_enabled", .value = .{ .b = true }, .desc = "TODO" };
    mapping[4] = .{ .name = "distance_unit_tf_km_mi", .value = .{ .b = false }, .desc = "TODO" };
    mapping[5] = .{ .name = "overlay_debugbar", .value = .{ .b = true }, .desc = "TODO" };
    mapping[6] = .{ .name = "help", .value = .{ .b = false }, .desc = "TODO" };
    mapping[7] = .{ .name = "overlay_pindetails", .value = .{ .b = true }, .desc = "TODO" };
    mapping[8] = .{ .name = "crosshair_size", .value = .{ .u = 15 }, .desc = "TODO" };
    mapping[9] = .{ .name = "drag_scale", .value = .{ .u = 2 }, .desc = "TODO" };
    mapping[10] = .{ .name = "fontsize_ui", .value = .{ .u = 20 }, .desc = "TODO" };
    mapping[11] = .{ .name = "debug_tiles", .value = .{ .b = false }, .desc = "TODO" };
    mapping[12] = .{ .name = "debug_stderr", .value = .{ .b = false }, .desc = "TODO" };
    mapping[13] = .{ .name = "tile_cache_max_n_transfers", .value = .{ .u = 20 }, .desc = "TODO" };
    mapping[14] = .{ .name = "tile_cache_expiry_seconds", .value = .{ .f = -1 }, .desc = "TODO" };
    mapping[15] = .{ .name = "tile_cache_network", .value = .{ .b = true }, .desc = "TODO" };
    mapping[16] = .{ .name = "tile_cache_dir", .value = .{ .t = null }, .desc = "TODO" };
    mapping[17] = .{ .name = "tile_cache_url", .value = .{ .t = null }, .desc = "TODO" };
    mapping[@enumToInt(pref.lat)] = .{ .name = "lat", .value = .{ .f = 40.78392 }, .desc = "TODO" };
    mapping[@enumToInt(pref.lon)] = .{ .name = "lon", .value = .{ .f = -73.96442 }, .desc = "TODO" };
    mapping[@enumToInt(pref.zoom)] = .{ .name = "zoom", .value = .{ .u = 14 }, .desc = "TODO" };
    mapping[@enumToInt(pref.debug_message_enabled)] = .{ .name = "debug_message_enabled", .value = .{ .b = true }, .desc = "TODO" };
    mapping[@enumToInt(pref.distance_unit_tf_km_mi)] = .{ .name = "distance_unit_tf_km_mi", .value = .{ .b = false }, .desc = "TODO" };
    mapping[@enumToInt(pref.overlay_debugbar)] = .{ .name = "overlay_debugbar", .value = .{ .b = true }, .desc = "TODO" };
    mapping[@enumToInt(pref.help)] = .{ .name = "help", .value = .{ .b = false }, .desc = "TODO" };
    mapping[@enumToInt(pref.overlay_pindetails)] = .{ .name = "overlay_pindetails", .value = .{ .b = true }, .desc = "TODO" };
    mapping[@enumToInt(pref.crosshair_size)] = .{ .name = "crosshair_size", .value = .{ .u = 15 }, .desc = "TODO" };
    mapping[@enumToInt(pref.drag_scale)] = .{ .name = "drag_scale", .value = .{ .u = 2 }, .desc = "TODO" };
    mapping[@enumToInt(pref.fontsize_ui)] = .{ .name = "fontsize_ui", .value = .{ .u = 20 }, .desc = "TODO" };
    mapping[@enumToInt(pref.debug_tiles)] = .{ .name = "debug_tiles", .value = .{ .b = false }, .desc = "TODO" };
    mapping[@enumToInt(pref.debug_stderr)] = .{ .name = "debug_stderr", .value = .{ .b = false }, .desc = "TODO" };
    mapping[@enumToInt(pref.tile_cache_max_n_transfers)] = .{ .name = "tile_cache_max_n_transfers", .value = .{ .u = 20 }, .desc = "TODO" };
    mapping[@enumToInt(pref.tile_cache_expiry_seconds)] = .{ .name = "tile_cache_expiry_seconds", .value = .{ .f = -1 }, .desc = "TODO" };
    mapping[@enumToInt(pref.tile_cache_network)] = .{ .name = "tile_cache_network", .value = .{ .b = true }, .desc = "TODO" };
    mapping[@enumToInt(pref.tile_cache_dir)] = .{ .name = "tile_cache_dir", .value = .{ .t = null }, .desc = "TODO" };
    mapping[@enumToInt(pref.tile_cache_url)] = .{ .name = "tile_cache_url", .value = .{ .t = null }, .desc = "TODO" };
    break :mapping mapping;
};

pub fn get_u8(prefname: []const u8) f64 {
    for (prefs_mapping) |pref| {
        if (std.mem.eql(u8, pref.name, prefname)) return pref.value.u;
    }
    return 0;
pub fn get(prefname: pref) PrefValueUnion {
    return prefs_mapping[@enumToInt(prefname)].value;
}

pub fn get(prefname: []const u8) PrefValueUnion {
    for (prefs_mapping) |pref| {
        if (std.mem.eql(u8, pref.name, prefname)) {
            return pref.value;
        }
pub fn set_n(prefname: pref, value: f64) void {
    switch (prefs_mapping[@enumToInt(prefname)].value) {
        .b => {
            prefs_mapping[@enumToInt(prefname)].value = .{ .b = value == 1 };
        },
        .u => {
            prefs_mapping[@enumToInt(prefname)].value = .{ .u = @floatToInt(u8, value) };
        },
        .f => {
            prefs_mapping[@enumToInt(prefname)].value = .{ .f = value };
        },
        .t => {},
    }
    return .{ .b = false };
}

pub fn set_n(prefname: []const u8, value: f64) void {
    for (prefs_mapping) |*pref| {
        if (std.mem.eql(u8, pref.name, prefname)) {
            switch (pref.value) {
                .b => {
                    pref.value = .{ .b = value == 1 };
                },
                .u => {
                    pref.value = .{ .u = @floatToInt(u8, value) };
                },
                .f => {
                    pref.value = .{ .f = value };
                },
                .t => {},
            }
        }
    }
pub fn set_t(allocator: std.mem.Allocator, prefname: pref, value: []const u8) !void {
    if (prefs_mapping[@enumToInt(prefname)].value.t) |heap_allocated_text| allocator.free(heap_allocated_text);
    prefs_mapping[@enumToInt(prefname)].value.t = try allocator.dupeZ(u8, value);
}

pub fn set_t(allocator: std.mem.Allocator, prefname: []const u8, value: []const u8) !void {
    for (prefs_mapping) |*pref| {
        if (std.mem.eql(u8, pref.name, prefname)) {
            switch (pref.value) {
                .t => {
                    if (pref.value.t) |heap_allocated_text| allocator.free(heap_allocated_text);
                    pref.value.t = try allocator.dupeZ(u8, value);
                },
                else => {}
            }
        }
pub fn lookup_pref_from_string(prefname: []const u8) ?pref {
    for (prefs_mapping) |p, i| {
        if (std.mem.eql(u8, p.name, prefname)) return @intToEnum(pref, i);
    }
    return null;
}

pub fn toggle_bool(prefname: []const u8) void {
    for (prefs_mapping) |*pref| {
        if (std.mem.eql(u8, pref.name, prefname)) {
            switch (pref.value) {
                .b => {
                    pref.value = .{ .b = !pref.value.b };
                },
                else => {},
            }
        }
pub fn toggle_bool(prefname: pref) void {
    switch (prefs_mapping[@enumToInt(prefname)].value) {
        .b => {
            prefs_mapping[@enumToInt(prefname)].value = .{ .b = !prefs_mapping[@enumToInt(prefname)].value.b };
        },
        else => {},
    }
}