|
| 1 | +#include <cstdio> |
| 2 | +#include <filesystem> |
| 3 | +#include <fstream> |
| 4 | +#include <iostream> |
| 5 | +#include "nativeapi.h" |
| 6 | + |
| 7 | +using nativeapi::DragOperation; |
| 8 | +using nativeapi::DragSource; |
| 9 | +using nativeapi::DragSourceEndedEvent; |
| 10 | +using nativeapi::DropTarget; |
| 11 | +using nativeapi::DropTargetDroppedEvent; |
| 12 | +using nativeapi::DropTargetEnteredEvent; |
| 13 | +using nativeapi::DropTargetExitedEvent; |
| 14 | +using nativeapi::DropTargetMovedEvent; |
| 15 | +using nativeapi::RunApp; |
| 16 | +using nativeapi::Window; |
| 17 | +using nativeapi::WindowFocusedEvent; |
| 18 | +using nativeapi::WindowManager; |
| 19 | + |
| 20 | +namespace { |
| 21 | + |
| 22 | +const char* OperationName(DragOperation operation) { |
| 23 | + switch (operation) { |
| 24 | + case DragOperation::Copy: |
| 25 | + return "copy"; |
| 26 | + case DragOperation::Move: |
| 27 | + return "move"; |
| 28 | + case DragOperation::Link: |
| 29 | + return "link"; |
| 30 | + case DragOperation::None: |
| 31 | + break; |
| 32 | + } |
| 33 | + return "none"; |
| 34 | +} |
| 35 | + |
| 36 | +} // namespace |
| 37 | + |
| 38 | +// Drag and drop without any UI toolkit. |
| 39 | +// |
| 40 | +// - Drop files or text from a file manager or editor onto the "Drop here" |
| 41 | +// window; every event is printed. |
| 42 | +// - Press inside the "Drag me" window (not on its title bar) and keep dragging |
| 43 | +// to drag a text file out of it, into a file manager or the "Drop here" |
| 44 | +// window. There is no widget to press on, so the window becoming focused |
| 45 | +// stands in for the mouse-down. |
| 46 | +int main() { |
| 47 | + WindowManager& window_manager = WindowManager::GetInstance(); |
| 48 | + |
| 49 | + auto drop_window = std::make_shared<Window>(); |
| 50 | + drop_window->SetTitle("Drop here"); |
| 51 | + drop_window->SetSize({480, 320}, false); |
| 52 | + drop_window->Center(); |
| 53 | + |
| 54 | + auto source_window = std::make_shared<Window>(); |
| 55 | + source_window->SetTitle("Drag me"); |
| 56 | + source_window->SetSize({240, 160}, false); |
| 57 | + auto position = drop_window->GetPosition(); |
| 58 | + source_window->SetPosition({position.x + 520, position.y}); |
| 59 | + source_window->Show(); |
| 60 | + |
| 61 | + std::cout << "Drop target supported: " << DropTarget::IsSupported() |
| 62 | + << ", drag source supported: " << DragSource::IsSupported() << std::endl; |
| 63 | + |
| 64 | + auto target = std::make_shared<DropTarget>(drop_window); |
| 65 | + target->AddListener<DropTargetEnteredEvent>([](const DropTargetEnteredEvent& event) { |
| 66 | + auto p = event.GetPosition(); |
| 67 | + std::cout << "Entered at (" << p.x << ", " << p.y << ")" << std::endl; |
| 68 | + }); |
| 69 | + target->AddListener<DropTargetMovedEvent>([](const DropTargetMovedEvent& event) { |
| 70 | + auto p = event.GetPosition(); |
| 71 | + std::cout << "Moved to (" << p.x << ", " << p.y << ")" << std::endl; |
| 72 | + }); |
| 73 | + target->AddListener<DropTargetExitedEvent>([](const DropTargetExitedEvent&) { |
| 74 | + std::cout << "Exited" << std::endl; |
| 75 | + }); |
| 76 | + target->AddListener<DropTargetDroppedEvent>([](const DropTargetDroppedEvent& event) { |
| 77 | + auto p = event.GetPosition(); |
| 78 | + std::cout << "Dropped at (" << p.x << ", " << p.y << ")" << std::endl; |
| 79 | + for (const auto& path : event.GetFilePaths()) { |
| 80 | + std::cout << " file: " << path << std::endl; |
| 81 | + } |
| 82 | + if (!event.GetText().empty()) { |
| 83 | + std::cout << " text: " << event.GetText() << std::endl; |
| 84 | + } |
| 85 | + }); |
| 86 | + std::cout << "Drop target active: " << target->IsActive() << std::endl; |
| 87 | + auto content = drop_window->GetContentBounds(); |
| 88 | + std::cout << "Drop content at (" << content.x << ", " << content.y << ")" << std::endl; |
| 89 | + |
| 90 | + // A file to drag out. |
| 91 | + auto file = std::filesystem::temp_directory_path() / "nativeapi-drag-drop-example.txt"; |
| 92 | + std::ofstream(file) << "Dragged out of drag_drop_example.\n"; |
| 93 | + |
| 94 | + auto source = std::make_shared<DragSource>(); |
| 95 | + source->SetFilePaths({file.string()}); |
| 96 | + source->SetText("Hello from drag_drop_example"); |
| 97 | + source->AddListener<DragSourceEndedEvent>([](const DragSourceEndedEvent& event) { |
| 98 | + std::cout << "Drag ended: " << OperationName(event.GetOperation()) << std::endl; |
| 99 | + }); |
| 100 | + |
| 101 | + window_manager.AddListener<WindowFocusedEvent>([&](const WindowFocusedEvent& event) { |
| 102 | + if (event.GetWindowId() != source_window->GetId() || source->IsDragging()) { |
| 103 | + return; |
| 104 | + } |
| 105 | + if (source->StartDragging(source_window)) { |
| 106 | + std::cout << "Dragging " << file.string() << std::endl; |
| 107 | + } |
| 108 | + }); |
| 109 | + |
| 110 | + std::cout << "Drop something on \"Drop here\", or press inside \"Drag me\" and drag." |
| 111 | + << std::endl; |
| 112 | + return RunApp(drop_window); |
| 113 | +} |
0 commit comments