Step 88: drag-and-drop open
This commit is contained in:
@@ -185,6 +185,7 @@ All 38 steps implemented and passing. Each step has a corresponding test (`step1
|
||||
- [x] Step 85: **IMPLEMENTED** — Filesystem tree with .gitignore filtering, recursive Explorer rendering (1/1 tests pass)
|
||||
- [x] Step 86: **IMPLEMENTED** — Multi-tab editing with BufferManager and per-buffer editor state (3/3 tests pass)
|
||||
- [x] Step 87: **IMPLEMENTED** — Welcome screen wired with recent files persistence and quick actions (2/2 tests pass)
|
||||
- [x] Step 88: **IMPLEMENTED** — Drag-and-drop file/folder open via SDL_DROPFILE (2/2 tests pass)
|
||||
|
||||
---
|
||||
|
||||
@@ -251,6 +252,7 @@ vcpkg's imgui 1.91.9 removed the `sdl2-binding` feature (only `sdl3-binding` exi
|
||||
**Step 85:** Compile and pass (1/1)
|
||||
**Step 86:** Compile and pass (3/3)
|
||||
**Step 87:** Compile and pass (2/2)
|
||||
**Step 88:** Compile and pass (2/2)
|
||||
|
||||
---
|
||||
|
||||
@@ -346,3 +348,4 @@ Sprint 4 in progress. Step 76 (LayoutManager) done. Next: Step 77 (custom code e
|
||||
| 2026-02-09 | Codex | Step 85: Filesystem tree with .gitignore filtering and Explorer rendering. 1/1 tests pass. |
|
||||
| 2026-02-09 | Codex | Step 86: Multi-tab editing wired via BufferManager with per-buffer state. 3/3 tests pass. |
|
||||
| 2026-02-09 | Codex | Step 87: Welcome screen wired with recent files persistence and quick actions. 2/2 tests pass. |
|
||||
| 2026-02-09 | Codex | Step 88: Drag-and-drop open for files and folders. 2/2 tests pass. |
|
||||
|
||||
@@ -496,6 +496,9 @@ target_include_directories(step86_test PRIVATE src)
|
||||
add_executable(step87_test tests/step87_test.cpp)
|
||||
target_include_directories(step87_test PRIVATE src)
|
||||
|
||||
add_executable(step88_test tests/step88_test.cpp)
|
||||
target_include_directories(step88_test PRIVATE src)
|
||||
|
||||
find_package(SDL2 CONFIG REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
find_package(glad CONFIG REQUIRED)
|
||||
|
||||
24
editor/src/DragDropHandler.h
Normal file
24
editor/src/DragDropHandler.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
// Step 88: Drag-and-drop handler
|
||||
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <filesystem>
|
||||
|
||||
class DragDropHandler {
|
||||
public:
|
||||
using FileCallback = std::function<void(const std::string&)>;
|
||||
using FolderCallback = std::function<void(const std::string&)>;
|
||||
|
||||
static void handleDrop(const std::string& path,
|
||||
const FileCallback& onFile,
|
||||
const FolderCallback& onFolder) {
|
||||
if (path.empty()) return;
|
||||
std::filesystem::path p(path);
|
||||
if (std::filesystem::is_directory(p)) {
|
||||
if (onFolder) onFolder(path);
|
||||
} else {
|
||||
if (onFile) onFile(path);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "FileDialog.h"
|
||||
#include "FileTree.h"
|
||||
#include "WelcomeScreen.h"
|
||||
#include "DragDropHandler.h"
|
||||
#include "ast/Generator.h"
|
||||
|
||||
#include <cstdio>
|
||||
@@ -624,6 +625,18 @@ int main(int, char**) {
|
||||
event.window.event == SDL_WINDOWEVENT_CLOSE &&
|
||||
event.window.windowID == SDL_GetWindowID(window))
|
||||
done = true;
|
||||
if (event.type == SDL_DROPFILE) {
|
||||
char* droppedFile = event.drop.file;
|
||||
if (droppedFile) {
|
||||
DragDropHandler::handleDrop(droppedFile,
|
||||
[&](const std::string& p) { state.doOpen(p); },
|
||||
[&](const std::string& p) {
|
||||
state.workspaceRoot = p;
|
||||
state.fileTreeDirty = true;
|
||||
});
|
||||
SDL_free(droppedFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle keyboard shortcuts via KeybindingManager
|
||||
if (event.type == SDL_KEYDOWN && !io.WantTextInput) {
|
||||
|
||||
49
editor/tests/step88_test.cpp
Normal file
49
editor/tests/step88_test.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// Step 88 TDD Test: Drag-and-drop handler
|
||||
//
|
||||
// Tests:
|
||||
// 1. File drop invokes file callback
|
||||
// 2. Folder drop invokes folder callback
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include "DragDropHandler.h"
|
||||
|
||||
int main() {
|
||||
int passed = 0;
|
||||
int failed = 0;
|
||||
|
||||
std::filesystem::path root = std::filesystem::current_path() / "tmp_step88";
|
||||
std::filesystem::create_directories(root / "dir");
|
||||
std::filesystem::path file = root / "file.txt";
|
||||
std::ofstream f(file.string());
|
||||
f << "x";
|
||||
f.close();
|
||||
|
||||
bool fileCalled = false;
|
||||
bool folderCalled = false;
|
||||
|
||||
DragDropHandler::handleDrop(file.string(),
|
||||
[&](const std::string& p){ fileCalled = (p == file.string()); },
|
||||
[&](const std::string& p){ folderCalled = (p == (root / "dir").string()); }
|
||||
);
|
||||
assert(fileCalled);
|
||||
std::cout << "Test 1 PASS: File drop" << std::endl;
|
||||
++passed;
|
||||
|
||||
fileCalled = false;
|
||||
folderCalled = false;
|
||||
DragDropHandler::handleDrop((root / "dir").string(),
|
||||
[&](const std::string& p){ fileCalled = (p == file.string()); },
|
||||
[&](const std::string& p){ folderCalled = (p == (root / "dir").string()); }
|
||||
);
|
||||
assert(folderCalled);
|
||||
std::cout << "Test 2 PASS: Folder drop" << std::endl;
|
||||
++passed;
|
||||
|
||||
std::filesystem::remove_all(root);
|
||||
|
||||
std::cout << "\n=== Step 88 Results: " << passed << " passed, " << failed << " failed ===" << std::endl;
|
||||
return failed > 0 ? 1 : 0;
|
||||
}
|
||||
Reference in New Issue
Block a user