Skip to content

Develop core GUI applications (terminal, editor, file manager) #410

Description

@pbalduino

Summary

Develop core GUI applications to demonstrate and validate the GUI stack, including a terminal emulator, text editor, file manager, and calculator.

Goals

Create essential GUI applications:

  1. Terminal Emulator - Run shell commands
  2. Text Editor - Edit text files
  3. File Manager - Browse filesystem
  4. Calculator - Basic calculator
  5. Image Viewer - Display PNG/JPEG images (optional)

Implementation

1. Terminal Emulator

```c
// GUI terminal that runs /bin/mosh
struct terminal {
struct window *window;
char grid[80][25]; // Character grid
int cursor_x, cursor_y;
int pty_fd; // Pseudo-terminal
};

void terminal_init(struct terminal *term) {
term->window = compositor_create_window(640, 400, "Terminal");
term->pty_fd = pty_open(); // Fork mosh

// Main loop
while (1) {
    // Read from PTY
    char buf[256];
    ssize_t n = read(term->pty_fd, buf, sizeof(buf));
    for (int i = 0; i < n; i++) {
        terminal_putchar(term, buf[i]);
    }

    // Render
    terminal_render(term);

    // Handle keyboard
    struct input_event evt;
    if (get_key_event(&evt)) {
        char ch = keycode_to_char(evt.key.keycode);
        write(term->pty_fd, &ch, 1);
    }
}

}

void terminal_render(struct terminal *term) {
cairo_t *cr = cairo_create(term->window->surface);

// Black background
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_paint(cr);

// Render text grid
cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);
cairo_select_font_face(cr, "Monospace", ...);
cairo_set_font_size(cr, 14);

for (int y = 0; y < 25; y++) {
    for (int x = 0; x < 80; x++) {
        if (term->grid[x][y]) {
            cairo_move_to(cr, x * 8, y * 16);
            char str[2] = { term->grid[x][y], 0 };
            cairo_show_text(cr, str);
        }
    }
}

// Draw cursor
cairo_rectangle(cr, term->cursor_x * 8, term->cursor_y * 16, 8, 16);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_stroke(cr);

cairo_destroy(cr);
window_commit(term->window);

}
```

2. Text Editor

```c
struct editor {
struct window *window;
char **lines; // Text buffer
int num_lines;
int cursor_line, cursor_col;
int scroll_offset;
char *filename;
int modified;
};

void editor_render(struct editor *ed) {
cairo_t *cr = cairo_create(ed->window->surface);

cairo_set_source_rgb(cr, 1, 1, 1);
cairo_paint(cr);

cairo_set_source_rgb(cr, 0, 0, 0);
cairo_select_font_face(cr, "Monospace", ...);

int y = 20;
for (int i = ed->scroll_offset;
     i < ed->num_lines && y < ed->window->height;
     i++, y += 16) {
    cairo_move_to(cr, 10, y);
    cairo_show_text(cr, ed->lines[i]);
}

// Draw cursor
int cursor_y = (ed->cursor_line - ed->scroll_offset) * 16 + 20;
int cursor_x = ed->cursor_col * 8 + 10;
cairo_move_to(cr, cursor_x, cursor_y);
cairo_line_to(cr, cursor_x, cursor_y - 16);
cairo_stroke(cr);

cairo_destroy(cr);
window_commit(ed->window);

}

// Handle Ctrl+S to save
void editor_save(struct editor *ed) {
FILE *f = fopen(ed->filename, "w");
for (int i = 0; i < ed->num_lines; i++) {
fprintf(f, "%s\n", ed->lines[i]);
}
fclose(f);
ed->modified = 0;
}
```

3. File Manager

```c
struct file_manager {
struct window *window;
char current_path[256];
struct dirent *entries;
int num_entries;
int selected;
};

void filemgr_render(struct filemgr *fm) {
cairo_t *cr = cairo_create(fm->window->surface);

cairo_set_source_rgb(cr, 1, 1, 1);
cairo_paint(cr);

// Draw path
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_move_to(cr, 10, 20);
cairo_show_text(cr, fm->current_path);

// Draw files
int y = 50;
for (int i = 0; i < fm->num_entries; i++) {
    if (i == fm->selected) {
        cairo_rectangle(cr, 5, y - 15, fm->window->width - 10, 20);
        cairo_set_source_rgb(cr, 0.7, 0.7, 1.0);
        cairo_fill(cr);
        cairo_set_source_rgb(cr, 0, 0, 0);
    }

    // Draw icon based on type
    if (fm->entries[i].d_type == DT_DIR) {
        draw_icon(cr, 10, y - 12, "folder.png");
    } else {
        draw_icon(cr, 10, y - 12, "file.png");
    }

    cairo_move_to(cr, 35, y);
    cairo_show_text(cr, fm->entries[i].d_name);

    y += 25;
}

cairo_destroy(cr);
window_commit(fm->window);

}

// Double-click to open
void filemgr_open(struct filemgr *fm, int index) {
if (fm->entries[index].d_type == DT_DIR) {
// Navigate to directory
chdir(fm->entries[index].d_name);
getcwd(fm->current_path, sizeof(fm->current_path));
filemgr_refresh(fm);
} else {
// Open file with default application
char cmd[512];
snprintf(cmd, sizeof(cmd), "/bin/editor %s/%s",
fm->current_path, fm->entries[index].d_name);
system(cmd);
}
}
```

4. Calculator

```c
struct calculator {
struct window *window;
char display[32];
double accumulator;
char operation;
};

void calc_render(struct calc *c) {
cairo_t *cr = cairo_create(c->window->surface);

// Background
cairo_set_source_rgb(cr, 0.9, 0.9, 0.9);
cairo_paint(cr);

// Display
cairo_rectangle(cr, 10, 10, 260, 40);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_fill(cr);

cairo_set_source_rgb(cr, 0, 0, 0);
cairo_select_font_face(cr, "Sans", ...);
cairo_set_font_size(cr, 24);
cairo_move_to(cr, 20, 40);
cairo_show_text(cr, c->display);

// Number buttons
const char *labels[] = {
    "7", "8", "9", "/",
    "4", "5", "6", "*",
    "1", "2", "3", "-",
    "0", ".", "=", "+"
};

for (int i = 0; i < 16; i++) {
    int x = (i % 4) * 65 + 10;
    int y = (i / 4) * 50 + 60;
    draw_button(cr, x, y, 60, 45, labels[i]);
}

cairo_destroy(cr);
window_commit(c->window);

}
```

Timeline

  • Terminal Emulator: 2 weeks
  • Text Editor: 2 weeks
  • File Manager: 2 weeks
  • Calculator: 1 week

Total: 6-8 weeks (can be done in parallel)

Definition of Done

  • Terminal emulator runs and is usable
  • Text editor can open, edit, and save files
  • File manager can browse directories
  • Calculator performs basic math
  • All apps have professional UI
  • Apps demonstrate GUI capabilities

Dependencies

See docs/road/road_to_gui.md for complete roadmap.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

GUIGraphical user interface componentsenhancementNew feature or request

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions