Capy — Framework GUI Nativo Multiplataforma em Zig

Capy — Framework GUI Nativo Multiplataforma em Zig

O Capy é o framework de interface gráfica de usuário (GUI) mais promissor do ecossistema Zig. Projetado para criar aplicações desktop nativas multiplataforma, o Capy utiliza os widgets nativos de cada sistema operacional — GTK no Linux, Win32 no Windows e Cocoa no macOS — proporcionando aplicações que se integram naturalmente ao ambiente do usuário.

O Que É o Capy

O Capy é um framework GUI declarativo escrito em Zig que abstrai as diferenças entre toolkits nativos. Em vez de renderizar sua própria interface (como o Flutter ou o Electron), o Capy usa os controles nativos do sistema operacional, resultando em aplicações que:

  • Parecem naturais em cada plataforma
  • Consomem menos memória que soluções baseadas em browser
  • Iniciam instantaneamente sem overhead de runtime
  • Respeitam temas e configurações de acessibilidade do sistema

Arquitetura

O Capy utiliza uma arquitetura em camadas:

  1. API Declarativa: Interface de alto nível em Zig para definir layouts e widgets
  2. Backend Abstrato: Camada de abstração sobre toolkits nativos
  3. Backends Nativos: Implementações específicas para cada plataforma

Backends Suportados

  • Linux: GTK3/GTK4 via bindings C
  • Windows: Win32 API nativa
  • macOS: Cocoa via Objective-C runtime
  • WebAssembly: Canvas HTML5 para aplicações web
  • Framebuffer: Renderização direta para sistemas embarcados

Começando com o Capy

Instalação

Adicione o Capy como dependência no seu build.zig.zon:

.{
    .name = "minha-app-gui",
    .version = "0.1.0",
    .dependencies = .{
        .capy = .{
            .url = "https://github.com/capy-ui/capy/archive/refs/tags/v0.5.0.tar.gz",
            .hash = "1220...",
        },
    },
}

Configure o build.zig:

const std = @import("std");
const capy = @import("capy");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "minha-app",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    const capy_dep = b.dependency("capy", .{
        .target = target,
        .optimize = optimize,
    });
    exe.root_module.addImport("capy", capy_dep.module("capy"));

    b.installArtifact(exe);
}

Hello World

const capy = @import("capy");

pub fn main() !void {
    var app = try capy.App.init();
    defer app.deinit();

    var window = try capy.Window.init(.{
        .title = "Olá, Capy!",
        .width = 400,
        .height = 300,
    });

    try window.setContent(
        capy.Column(.{}, .{
            capy.Label(.{ .text = "Bem-vindo ao Capy!" }),
            capy.Button(.{
                .label = "Clique aqui",
                .on_click = struct {
                    fn callback() void {
                        std.debug.print("Botão clicado!\n", .{});
                    }
                }.callback,
            }),
        }),
    );

    try window.show();
    try app.run();
}

Widgets Disponíveis

Widgets Básicos

O Capy oferece um conjunto abrangente de widgets nativos:

// Label - texto estático
capy.Label(.{ .text = "Texto informativo" })

// Button - botão clicável
capy.Button(.{ .label = "Confirmar", .on_click = meu_callback })

// TextInput - campo de entrada de texto
capy.TextInput(.{
    .placeholder = "Digite seu nome...",
    .on_change = on_text_change,
})

// Checkbox
capy.Checkbox(.{ .label = "Aceitar termos", .checked = false })

// Slider
capy.Slider(.{ .min = 0, .max = 100, .value = 50 })

// Image
capy.Image(.{ .source = "assets/logo.png" })

// Canvas para desenho livre
capy.Canvas(.{
    .on_draw = minha_funcao_desenho,
    .width = 800,
    .height = 600,
})

Containers e Layouts

// Coluna vertical
capy.Column(.{ .spacing = 10 }, .{
    capy.Label(.{ .text = "Item 1" }),
    capy.Label(.{ .text = "Item 2" }),
    capy.Label(.{ .text = "Item 3" }),
})

// Linha horizontal
capy.Row(.{ .spacing = 10 }, .{
    capy.Button(.{ .label = "Esquerda" }),
    capy.Button(.{ .label = "Direita" }),
})

// Stack para sobreposição
capy.Stack(.{}, .{
    capy.Image(.{ .source = "fundo.png" }),
    capy.Label(.{ .text = "Texto sobre imagem" }),
})

// ScrollView para conteúdo rolável
capy.ScrollView(.{
    .direction = .vertical,
}, capy.Column(.{}, items))

Sistema de Eventos

O Capy usa callbacks para tratar eventos, aproveitando as capacidades de closures do Zig:

const State = struct {
    contador: i32 = 0,
    label: *capy.Label = undefined,
};

var state = State{};

// Botão com closure que captura estado
capy.Button(.{
    .label = "Incrementar",
    .on_click = struct {
        fn callback() void {
            state.contador += 1;
            state.label.setText(
                std.fmt.bufPrint(&buf, "Contagem: {}", .{state.contador}) catch "Erro",
            );
        }
    }.callback,
})

Eventos Comuns

  • on_click: Clique do mouse
  • on_change: Alteração de valor (inputs, sliders)
  • on_key_press: Tecla pressionada
  • on_mouse_move: Movimento do mouse
  • on_focus / on_blur: Ganhar/perder foco
  • on_resize: Redimensionamento de janela
  • on_draw: Renderização customizada (Canvas)

Canvas para Desenho Customizado

Quando os widgets padrão não são suficientes, use o Canvas para desenho livre:

capy.Canvas(.{
    .on_draw = struct {
        fn draw(ctx: *capy.DrawContext) void {
            // Retângulo
            ctx.setColor(.{ .r = 255, .g = 0, .b = 0, .a = 255 });
            ctx.fillRect(10, 10, 100, 50);

            // Círculo
            ctx.setColor(.{ .r = 0, .g = 0, .b = 255, .a = 255 });
            ctx.fillCircle(200, 100, 40);

            // Texto
            ctx.setColor(.{ .r = 0, .g = 0, .b = 0, .a = 255 });
            ctx.drawText(10, 80, "Texto desenhado no canvas");

            // Linha
            ctx.setColor(.{ .r = 0, .g = 128, .b = 0, .a = 255 });
            ctx.drawLine(0, 0, 300, 200);
        }
    }.draw,
})

Aplicação Completa: Calculadora

Um exemplo mais completo demonstrando o uso de múltiplos widgets e estado:

const capy = @import("capy");
const std = @import("std");

const Calculadora = struct {
    display: []const u8 = "0",
    acumulador: f64 = 0,
    operacao: ?u8 = null,

    fn pressionarDigito(self: *Calculadora, digito: u8) void {
        // Lógica da calculadora
        _ = self;
        _ = digito;
    }

    fn calcular(self: *Calculadora) f64 {
        // Executar operação
        _ = self;
        return 0;
    }
};

pub fn main() !void {
    var app = try capy.App.init();
    defer app.deinit();

    var window = try capy.Window.init(.{
        .title = "Calculadora Zig",
        .width = 300,
        .height = 400,
    });

    try window.setContent(
        capy.Column(.{ .spacing = 5 }, .{
            // Display
            capy.Label(.{
                .text = "0",
                .alignment = .right,
            }),
            // Linhas de botões
            criarLinhaBotoes("7", "8", "9", "/"),
            criarLinhaBotoes("4", "5", "6", "*"),
            criarLinhaBotoes("1", "2", "3", "-"),
            criarLinhaBotoes("0", ".", "=", "+"),
        }),
    );

    try window.show();
    try app.run();
}

Estilização

O Capy permite customização visual mantendo a aparência nativa:

capy.Label(.{
    .text = "Texto estilizado",
    .font_size = 24,
    .font_weight = .bold,
    .color = .{ .r = 51, .g = 51, .b = 51, .a = 255 },
    .background = .{ .r = 240, .g = 240, .b = 240, .a = 255 },
    .padding = .{ .top = 10, .right = 20, .bottom = 10, .left = 20 },
})

Comparação com Alternativas

CaracterísticaCapyGTK (C)Qt (C++)Electron
LinguagemZigCC++JS/HTML
Widgets nativosSimParcialPrópriosNão
Tamanho binário~5 MB~20 MB~50 MB~150 MB
Uso de memóriaBaixoMédioMédioAlto
Compilação cruzadaNativaComplexaComplexaN/A
Curva aprendizadoMédiaAltaAltaBaixa

Casos de Uso Ideais

O Capy é especialmente adequado para:

  • Ferramentas de desenvolvimento e utilitários desktop
  • Aplicações de linha de negócio que precisam parecer nativas
  • Dashboards e painéis de monitoramento
  • Editores de configuração e ferramentas administrativas
  • Aplicações embarcadas com interface gráfica (via framebuffer)

Próximos Passos

Explore outras bibliotecas visuais do ecossistema como o Mach Engine para jogos e as bibliotecas gráficas para renderização avançada. Para aprender mais sobre Zig, confira nossos tutoriais e receitas práticas.

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.