feat: add Files app selection marquee, Properties dialog for multiple files
This commit is contained in:
@@ -50,7 +50,16 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) {
|
||||
case CTX_RENAME: filemanager_start_rename(fm); break;
|
||||
case CTX_DELETE: filemanager_delete_selected(fm); break;
|
||||
case CTX_NEW_FOLDER: filemanager_new_folder(fm); break;
|
||||
case CTX_PROPERTIES: filemanager_show_properties(fm, target); break;
|
||||
case CTX_PROPERTIES: {
|
||||
if (fm->multi_count > 1) {
|
||||
int sel[64];
|
||||
int n = filemanager_collect_selection(fm, sel, 64);
|
||||
if (n > 0) filemanager_show_multi_properties(fm, sel, n);
|
||||
} else {
|
||||
filemanager_show_properties(fm, target);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CTX_REFRESH: filemanager_refresh(fm); break;
|
||||
}
|
||||
return;
|
||||
@@ -88,6 +97,8 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) {
|
||||
else if (local_x >= 148 && local_x < 172) {
|
||||
fm->grid_view = !fm->grid_view;
|
||||
fm->scrollbar.scroll_offset = 0;
|
||||
fm->marquee_active = false;
|
||||
filemanager_clear_multi_selection(fm);
|
||||
}
|
||||
// Action buttons
|
||||
else if (local_x >= 188 && local_x < 212) filemanager_do_copy(fm);
|
||||
@@ -110,6 +121,7 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) {
|
||||
|
||||
if (clicked_idx >= 0 && clicked_idx < fm->entry_count) {
|
||||
uint64_t now = montauk::get_milliseconds();
|
||||
filemanager_clear_multi_selection(fm);
|
||||
|
||||
if (fm->last_click_item == clicked_idx &&
|
||||
(now - fm->last_click_time) < 400) {
|
||||
@@ -122,7 +134,14 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) {
|
||||
fm->last_click_time = now;
|
||||
}
|
||||
} else {
|
||||
// Background click in grid area: start marquee drag
|
||||
fm->selected = -1;
|
||||
filemanager_clear_multi_selection(fm);
|
||||
fm->marquee_active = true;
|
||||
fm->marquee_start_x = local_x;
|
||||
fm->marquee_start_y = rel_y;
|
||||
fm->marquee_cur_x = local_x;
|
||||
fm->marquee_cur_y = rel_y;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -153,6 +172,61 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) {
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Marquee drag in grid view ----
|
||||
if (fm->marquee_active) {
|
||||
int list_y = FM_TOOLBAR_H + FM_PATHBAR_H;
|
||||
int rel_y = local_y - list_y + fm->scrollbar.scroll_offset;
|
||||
int clamp_x = local_x;
|
||||
if (clamp_x < 0) clamp_x = 0;
|
||||
int max_x = cw - FM_SCROLLBAR_W - 1;
|
||||
if (clamp_x > max_x) clamp_x = max_x;
|
||||
if (rel_y < 0) rel_y = 0;
|
||||
|
||||
if (ev.left_held()) {
|
||||
fm->marquee_cur_x = clamp_x;
|
||||
fm->marquee_cur_y = rel_y;
|
||||
}
|
||||
|
||||
// Recompute hit-set every frame so icons highlight live during the drag.
|
||||
int cols = (cw - FM_SCROLLBAR_W) / FM_GRID_CELL_W;
|
||||
if (cols < 1) cols = 1;
|
||||
|
||||
int rx0 = fm->marquee_start_x < fm->marquee_cur_x ? fm->marquee_start_x : fm->marquee_cur_x;
|
||||
int ry0 = fm->marquee_start_y < fm->marquee_cur_y ? fm->marquee_start_y : fm->marquee_cur_y;
|
||||
int rx1 = fm->marquee_start_x > fm->marquee_cur_x ? fm->marquee_start_x : fm->marquee_cur_x;
|
||||
int ry1 = fm->marquee_start_y > fm->marquee_cur_y ? fm->marquee_start_y : fm->marquee_cur_y;
|
||||
|
||||
filemanager_clear_multi_selection(fm);
|
||||
int limit = fm->entry_count < 64 ? fm->entry_count : 64;
|
||||
for (int i = 0; i < limit; i++) {
|
||||
int col = i % cols;
|
||||
int row = i / cols;
|
||||
int cell_x = col * FM_GRID_CELL_W;
|
||||
int cell_y = filemanager_grid_row_y(fm, row, cols);
|
||||
int cell_h = filemanager_grid_row_height(fm, row, cols);
|
||||
int cx1 = cell_x + FM_GRID_CELL_W;
|
||||
int cy1 = cell_y + cell_h;
|
||||
|
||||
if (rx1 < cell_x || rx0 >= cx1) continue;
|
||||
if (ry1 < cell_y || ry0 >= cy1) continue;
|
||||
|
||||
fm->multi_selected[i] = true;
|
||||
fm->multi_count++;
|
||||
}
|
||||
fm->selected = -1;
|
||||
|
||||
if (!ev.left_held()) {
|
||||
// Release: collapse a single-item marquee to a normal selection.
|
||||
if (fm->multi_count == 1) {
|
||||
for (int i = 0; i < limit; i++) {
|
||||
if (fm->multi_selected[i]) { fm->selected = i; break; }
|
||||
}
|
||||
filemanager_clear_multi_selection(fm);
|
||||
}
|
||||
fm->marquee_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Right-click: open context menu ----
|
||||
if (ev.right_pressed()) {
|
||||
filemanager_cancel_rename(fm);
|
||||
@@ -170,7 +244,15 @@ void filemanager_on_mouse(Window* win, MouseEvent& ev) {
|
||||
int idx = filemanager_grid_index_at(fm, cols, local_x, rel_y);
|
||||
if (idx >= 0 && idx < fm->entry_count) {
|
||||
target_idx = idx;
|
||||
fm->selected = idx;
|
||||
// Preserve multi-selection if right-clicking inside it,
|
||||
// otherwise replace it with a single selection.
|
||||
if (!(fm->multi_count > 0 && fm->multi_selected[idx])) {
|
||||
filemanager_clear_multi_selection(fm);
|
||||
fm->selected = idx;
|
||||
}
|
||||
} else {
|
||||
filemanager_clear_multi_selection(fm);
|
||||
fm->selected = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user