[FEATURE UPDATE]
Colored folders are now added allowing users to right click a folder and then set it's color. This data is saved in the colored folder as: >colored folder</.color with the .color folder holding the data for the folder icon color!
This commit is contained in:
Chris 2026-02-05 23:16:46 +01:00
parent a90f41d8a3
commit 2fd6f6f64f
10 changed files with 182 additions and 77 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -35,7 +35,7 @@ static void about_paint(Window *win) {
// Version info // Version info
draw_string(offset_x, offset_y + 105, "BrewOS", COLOR_BLACK); draw_string(offset_x, offset_y + 105, "BrewOS", COLOR_BLACK);
draw_string(offset_x, offset_y + 120, "BrewOS Version 1.10", COLOR_BLACK); draw_string(offset_x, offset_y + 120, "BrewOS Version 1.12", COLOR_BLACK);
draw_string(offset_x, offset_y + 135, "Kernel Version 2.1.0", COLOR_BLACK); draw_string(offset_x, offset_y + 135, "Kernel Version 2.1.0", COLOR_BLACK);
// Copyright // Copyright

View file

@ -2,6 +2,6 @@
void cli_cmd_brewver(char *args) { void cli_cmd_brewver(char *args) {
(void)args; (void)args;
cli_write("BrewOS v1.10 Alpha\n"); cli_write("BrewOS v1.12 Alpha\n");
cli_write("BrewOS Kernel V2.1.0 Pre-Alpha\n"); cli_write("BrewOS Kernel V2.1.0 Pre-Alpha\n");
} }

View file

@ -44,17 +44,18 @@ static uint32_t pattern_lumberjack[PATTERN_SIZE * PATTERN_SIZE];
static uint32_t pattern_blue_diamond[PATTERN_SIZE * PATTERN_SIZE]; static uint32_t pattern_blue_diamond[PATTERN_SIZE * PATTERN_SIZE];
static void generate_lumberjack_pattern(void) { static void generate_lumberjack_pattern(void) {
// Lumberjack pattern: 3x3 repeating cell // Lumberjack pattern: 3x3 repeating cell, scaled 5x
// Red corners, dark grey cross (top/left/right/bottom), black center // Red corners, dark grey cross (top/left/right/bottom), black center
uint32_t red = 0xFFDC143C; uint32_t red = 0xFFDC143C;
uint32_t dark_grey = 0xFF404040; uint32_t dark_grey = 0xFF404040;
uint32_t black = 0xFF000000; uint32_t black = 0xFF000000;
int scale = 5;
// Fill entire pattern with the 3x3 repeating cell // Fill entire pattern with the 3x3 repeating cell
for (int y = 0; y < PATTERN_SIZE; y++) { for (int y = 0; y < PATTERN_SIZE; y++) {
for (int x = 0; x < PATTERN_SIZE; x++) { for (int x = 0; x < PATTERN_SIZE; x++) {
int cell_x = x % 3; int cell_x = (x / scale) % 3;
int cell_y = y % 3; int cell_y = (y / scale) % 3;
uint32_t color; uint32_t color;

View file

@ -28,6 +28,7 @@ typedef struct {
char name[256]; char name[256];
bool is_directory; bool is_directory;
uint32_t size; uint32_t size;
uint32_t color;
} ExplorerItem; } ExplorerItem;
typedef enum { typedef enum {
@ -239,6 +240,41 @@ static void dropdown_menu_toggle(void) {
// === Explorer Logic === // === Explorer Logic ===
static uint32_t explorer_get_folder_color(const char *folder_path) {
char color_file_path[256];
explorer_strcpy(color_file_path, folder_path);
if (color_file_path[explorer_strlen(color_file_path) - 1] != '/') {
explorer_strcat(color_file_path, "/");
}
explorer_strcat(color_file_path, ".color");
FAT32_FileHandle *file = fat32_open(color_file_path, "r");
if (file) {
uint32_t color = 0;
int bytes_read = fat32_read(file, &color, sizeof(uint32_t));
fat32_close(file);
if (bytes_read == sizeof(uint32_t)) {
return color;
}
}
return COLOR_APPLE_YELLOW;
}
static void explorer_set_folder_color(const char *folder_path, uint32_t color) {
char color_file_path[256];
explorer_strcpy(color_file_path, folder_path);
if (color_file_path[explorer_strlen(color_file_path) - 1] != '/') {
explorer_strcat(color_file_path, "/");
}
explorer_strcat(color_file_path, ".color");
FAT32_FileHandle *file = fat32_open(color_file_path, "w");
if (file) {
fat32_write(file, &color, sizeof(uint32_t));
fat32_close(file);
}
}
static void explorer_load_directory(const char *path) { static void explorer_load_directory(const char *path) {
explorer_strcpy(current_path, path); explorer_strcpy(current_path, path);
@ -247,9 +283,26 @@ static void explorer_load_directory(const char *path) {
item_count = 0; item_count = 0;
for (int i = 0; i < count && i < EXPLORER_MAX_FILES; i++) { for (int i = 0; i < count && i < EXPLORER_MAX_FILES; i++) {
explorer_strcpy(items[i].name, entries[i].name); // Skip .color files
items[i].is_directory = entries[i].is_directory; if (explorer_strcmp(entries[i].name, ".color") == 0) {
items[i].size = entries[i].size; continue;
}
explorer_strcpy(items[item_count].name, entries[i].name);
items[item_count].is_directory = entries[i].is_directory;
items[item_count].size = entries[i].size;
if (items[item_count].is_directory) {
char subfolder_path[256];
explorer_strcpy(subfolder_path, current_path);
if (subfolder_path[explorer_strlen(subfolder_path) - 1] != '/') {
explorer_strcat(subfolder_path, "/");
}
explorer_strcat(subfolder_path, items[item_count].name);
items[item_count].color = explorer_get_folder_color(subfolder_path);
} else {
items[item_count].color = COLOR_APPLE_YELLOW;
}
item_count++; item_count++;
} }
@ -291,15 +344,21 @@ static void explorer_navigate_to(const char *dirname) {
} }
// Draw a simple file icon // Draw a simple file icon
static void explorer_draw_file_icon(int x, int y, bool is_dir) { static void explorer_draw_file_icon(int x, int y, bool is_dir, uint32_t color) {
if (is_dir) { if (is_dir) {
// Folder icon - larger // Folder icon (colored folder) - Desktop style
draw_rect(x + 10, y + 10, 30, 5, COLOR_BLUE); // Tab // Folder tab
draw_rect(x + 10, y + 15, 30, 25, COLOR_WHITE); // Main folder draw_rect(x + 10, y + 10, 15, 6, COLOR_LTGRAY);
draw_rect(x + 10, y + 15, 2, 25, COLOR_BLACK); draw_rect(x + 10, y + 10, 15, 1, COLOR_BLACK);
draw_rect(x + 10, y + 15, 30, 2, COLOR_BLACK); draw_rect(x + 10, y + 10, 1, 6, COLOR_BLACK);
draw_rect(x + 38, y + 15, 2, 25, COLOR_BLACK); draw_rect(x + 24, y + 10, 1, 6, COLOR_BLACK);
draw_rect(x + 10, y + 38, 30, 2, COLOR_BLACK);
// Folder body
draw_rect(x + 10, y + 16, 25, 15, color);
draw_rect(x + 10, y + 16, 25, 1, COLOR_BLACK);
draw_rect(x + 10, y + 16, 1, 15, COLOR_BLACK);
draw_rect(x + 34, y + 16, 1, 15, COLOR_BLACK);
draw_rect(x + 10, y + 30, 25, 1, COLOR_BLACK);
} else { } else {
// Document icon - larger // Document icon - larger
draw_rect(x + 12, y + 10, 20, 25, COLOR_WHITE); draw_rect(x + 12, y + 10, 20, 25, COLOR_WHITE);
@ -367,7 +426,7 @@ static void explorer_paint(Window *win) {
draw_rect(item_x + 2, item_y + 2, EXPLORER_ITEM_WIDTH - 4, EXPLORER_ITEM_HEIGHT - 4, bg_color); draw_rect(item_x + 2, item_y + 2, EXPLORER_ITEM_WIDTH - 4, EXPLORER_ITEM_HEIGHT - 4, bg_color);
// Draw icon (larger area) // Draw icon (larger area)
explorer_draw_file_icon(item_x + 5, item_y + 5, items[i].is_directory); explorer_draw_file_icon(item_x + 5, item_y + 5, items[i].is_directory, items[i].color);
// Draw name below icon with text wrapping // Draw name below icon with text wrapping
uint32_t text_color = (i == selected_item) ? COLOR_WHITE : COLOR_BLACK; uint32_t text_color = (i == selected_item) ? COLOR_WHITE : COLOR_BLACK;
@ -458,19 +517,37 @@ static void explorer_paint(Window *win) {
int menu_screen_x = win->x + file_context_menu_x; int menu_screen_x = win->x + file_context_menu_x;
int menu_screen_y = win->y + file_context_menu_y; int menu_screen_y = win->y + file_context_menu_y;
// Draw menu background if (items[file_context_menu_item].is_directory) {
draw_rect(menu_screen_x, menu_screen_y, FILE_CONTEXT_MENU_WIDTH, FILE_CONTEXT_MENU_HEIGHT, COLOR_LTGRAY); // Folder context menu (Color selection)
draw_bevel_rect(menu_screen_x, menu_screen_y, FILE_CONTEXT_MENU_WIDTH, FILE_CONTEXT_MENU_HEIGHT, true); int menu_height = 25 * 5; // 5 items, 25px each
// Draw menu items // Draw menu background
int item_height = FILE_CONTEXT_MENU_HEIGHT / FILE_CONTEXT_ITEMS; draw_rect(menu_screen_x, menu_screen_y, FILE_CONTEXT_MENU_WIDTH, menu_height, COLOR_LTGRAY);
draw_bevel_rect(menu_screen_x, menu_screen_y, FILE_CONTEXT_MENU_WIDTH, menu_height, true);
// Item 1: "Open with Text Editor"
draw_string(menu_screen_x + 5, menu_screen_y + 5, "Open w/ Editor", COLOR_BLACK); // Draw menu items
int item_h = 25;
// Item 2: "Open with Markdown Viewer" (only show if file is .md) draw_string(menu_screen_x + 5, menu_screen_y + 5, "Blue", COLOR_APPLE_BLUE);
if (explorer_is_markdown_file(items[file_context_menu_item].name)) { draw_string(menu_screen_x + 5, menu_screen_y + item_h + 5, "Red", COLOR_RED);
draw_string(menu_screen_x + 5, menu_screen_y + item_height + 5, "Open w/ Markdown", COLOR_BLACK); draw_string(menu_screen_x + 5, menu_screen_y + item_h * 2 + 5, "Yellow", COLOR_APPLE_YELLOW); // Text might be hard to read, but requested
draw_string(menu_screen_x + 5, menu_screen_y + item_h * 3 + 5, "Green", COLOR_APPLE_GREEN);
draw_string(menu_screen_x + 5, menu_screen_y + item_h * 4 + 5, "Black", COLOR_BLACK);
} else {
// File context menu
// Draw menu background
draw_rect(menu_screen_x, menu_screen_y, FILE_CONTEXT_MENU_WIDTH, FILE_CONTEXT_MENU_HEIGHT, COLOR_LTGRAY);
draw_bevel_rect(menu_screen_x, menu_screen_y, FILE_CONTEXT_MENU_WIDTH, FILE_CONTEXT_MENU_HEIGHT, true);
// Draw menu items
int item_height = FILE_CONTEXT_MENU_HEIGHT / FILE_CONTEXT_ITEMS;
// Item 1: "Open with Text Editor"
draw_string(menu_screen_x + 5, menu_screen_y + 5, "Open w/ Editor", COLOR_BLACK);
// Item 2: "Open with Markdown Viewer" (only show if file is .md)
if (explorer_is_markdown_file(items[file_context_menu_item].name)) {
draw_string(menu_screen_x + 5, menu_screen_y + item_height + 5, "Open w/ Markdown", COLOR_BLACK);
}
} }
} }
} }
@ -770,15 +847,13 @@ static void explorer_handle_right_click(Window *win, int x, int y) {
if (x >= item_x && x < item_x + EXPLORER_ITEM_WIDTH && if (x >= item_x && x < item_x + EXPLORER_ITEM_WIDTH &&
y >= item_y && y < item_y + EXPLORER_ITEM_HEIGHT) { y >= item_y && y < item_y + EXPLORER_ITEM_HEIGHT) {
// Right-click on a file item // Right-click on a file or folder item
if (!items[i].is_directory) { // Show context menu
// Show context menu file_context_menu_visible = true;
file_context_menu_visible = true; file_context_menu_item = i;
file_context_menu_item = i; file_context_menu_x = x;
file_context_menu_x = x; file_context_menu_y = y;
file_context_menu_y = y; return;
return;
}
} }
} }
@ -798,49 +873,78 @@ static void explorer_handle_file_context_menu_click(Window *win, int x, int y) {
int relative_x = x - file_context_menu_x; int relative_x = x - file_context_menu_x;
int relative_y = y - file_context_menu_y; int relative_y = y - file_context_menu_y;
int menu_height;
if (items[file_context_menu_item].is_directory) {
menu_height = 25 * 5;
} else {
menu_height = FILE_CONTEXT_MENU_HEIGHT;
}
if (relative_x < 0 || relative_x > FILE_CONTEXT_MENU_WIDTH || if (relative_x < 0 || relative_x > FILE_CONTEXT_MENU_WIDTH ||
relative_y < 0 || relative_y > FILE_CONTEXT_MENU_HEIGHT) { relative_y < 0 || relative_y > menu_height) {
// Clicked outside menu - close it // Clicked outside menu - close it
file_context_menu_visible = false; file_context_menu_visible = false;
file_context_menu_item = -1; file_context_menu_item = -1;
return; return;
} }
int item_height = FILE_CONTEXT_MENU_HEIGHT / FILE_CONTEXT_ITEMS; if (items[file_context_menu_item].is_directory) {
int clicked_item = relative_y / item_height; int clicked_item = relative_y / 25;
uint32_t new_color = items[file_context_menu_item].color;
// Build full path
char full_path[256]; if (clicked_item == 0) new_color = COLOR_APPLE_BLUE;
explorer_strcpy(full_path, current_path); else if (clicked_item == 1) new_color = COLOR_RED;
if (full_path[explorer_strlen(full_path) - 1] != '/') { else if (clicked_item == 2) new_color = COLOR_APPLE_YELLOW;
explorer_strcat(full_path, "/"); else if (clicked_item == 3) new_color = COLOR_APPLE_GREEN;
} else if (clicked_item == 4) new_color = COLOR_BLACK;
explorer_strcat(full_path, items[file_context_menu_item].name);
items[file_context_menu_item].color = new_color;
if (clicked_item == 0) {
// "Open with Text Editor" // Save to file
win_editor.visible = true; char full_path[256];
win_editor.focused = true; explorer_strcpy(full_path, current_path);
int max_z = 0; if (full_path[explorer_strlen(full_path) - 1] != '/') {
if (win_explorer.z_index > max_z) max_z = win_explorer.z_index; explorer_strcat(full_path, "/");
if (win_cmd.z_index > max_z) max_z = win_cmd.z_index; }
if (win_notepad.z_index > max_z) max_z = win_notepad.z_index; explorer_strcat(full_path, items[file_context_menu_item].name);
if (win_calculator.z_index > max_z) max_z = win_calculator.z_index; explorer_set_folder_color(full_path, new_color);
if (win_markdown.z_index > max_z) max_z = win_markdown.z_index; } else {
win_editor.z_index = max_z + 1; int item_height = FILE_CONTEXT_MENU_HEIGHT / FILE_CONTEXT_ITEMS;
editor_open_file(full_path); int clicked_item = relative_y / item_height;
} else if (clicked_item == 1 && explorer_is_markdown_file(items[file_context_menu_item].name)) {
// "Open with Markdown Viewer" // Build full path
win_markdown.visible = true; char full_path[256];
win_markdown.focused = true; explorer_strcpy(full_path, current_path);
int max_z = 0; if (full_path[explorer_strlen(full_path) - 1] != '/') {
if (win_explorer.z_index > max_z) max_z = win_explorer.z_index; explorer_strcat(full_path, "/");
if (win_cmd.z_index > max_z) max_z = win_cmd.z_index; }
if (win_notepad.z_index > max_z) max_z = win_notepad.z_index; explorer_strcat(full_path, items[file_context_menu_item].name);
if (win_calculator.z_index > max_z) max_z = win_calculator.z_index;
if (win_editor.z_index > max_z) max_z = win_editor.z_index; if (clicked_item == 0) {
win_markdown.z_index = max_z + 1; // "Open with Text Editor"
markdown_open_file(full_path); win_editor.visible = true;
win_editor.focused = true;
int max_z = 0;
if (win_explorer.z_index > max_z) max_z = win_explorer.z_index;
if (win_cmd.z_index > max_z) max_z = win_cmd.z_index;
if (win_notepad.z_index > max_z) max_z = win_notepad.z_index;
if (win_calculator.z_index > max_z) max_z = win_calculator.z_index;
if (win_markdown.z_index > max_z) max_z = win_markdown.z_index;
win_editor.z_index = max_z + 1;
editor_open_file(full_path);
} else if (clicked_item == 1 && explorer_is_markdown_file(items[file_context_menu_item].name)) {
// "Open with Markdown Viewer"
win_markdown.visible = true;
win_markdown.focused = true;
int max_z = 0;
if (win_explorer.z_index > max_z) max_z = win_explorer.z_index;
if (win_cmd.z_index > max_z) max_z = win_cmd.z_index;
if (win_notepad.z_index > max_z) max_z = win_notepad.z_index;
if (win_calculator.z_index > max_z) max_z = win_calculator.z_index;
if (win_editor.z_index > max_z) max_z = win_editor.z_index;
win_markdown.z_index = max_z + 1;
markdown_open_file(full_path);
}
} }
file_context_menu_visible = false; file_context_menu_visible = false;

View file

@ -11,8 +11,8 @@ static const uint8_t font8x8_basic[128][8] = {
{0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0},
// 32 Space // 32 Space
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
// 33 ! // 33 !
{0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00}, {0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00},
// 34 " // 34 "
{0x66, 0x66, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x66, 0x66, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00},
// 35 # // 35 #