Skip to content

Commit

Permalink
Merge branch 'main' into beta
Browse files Browse the repository at this point in the history
  • Loading branch information
dacap committed May 30, 2024
2 parents 9a98a5d + 4a2e2bb commit c90b81a
Show file tree
Hide file tree
Showing 28 changed files with 1,567 additions and 65 deletions.
22 changes: 17 additions & 5 deletions base/win/comptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ namespace base {
std::swap(m_ptr, tmp.m_ptr);
}

explicit ComPtr(T* p) : m_ptr(p) {
if (m_ptr)
m_ptr->AddRef();
}

~ComPtr() {
reset();
}
Expand All @@ -41,11 +46,18 @@ namespace base {

// Add new reference using operator=()
ComPtr<T>& operator=(const ComPtr<T>& p) {
if (m_ptr)
m_ptr->Release();
m_ptr = p.m_ptr;
if (m_ptr)
m_ptr->AddRef();
if (this != &p) {
if (m_ptr)
m_ptr->Release();
m_ptr = p.m_ptr;
if (m_ptr)
m_ptr->AddRef();
}
return *this;
}

ComPtr<T>& operator=(ComPtr<T>&& p) noexcept {
std::swap(m_ptr, p.m_ptr);
return *this;
}

Expand Down
2 changes: 1 addition & 1 deletion clip
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ if(LAF_BACKEND STREQUAL "skia")
laf_add_example(allevents GUI)
laf_add_example(complextextlayout GUI)
laf_add_example(custom_window GUI)
laf_add_example(drag_and_drop GUI)
laf_add_example(floating_window GUI)
laf_add_example(hello_laf GUI)
laf_add_example(multiple_windows GUI)
Expand Down
238 changes: 238 additions & 0 deletions examples/drag_and_drop.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
// LAF Library
// Copyright (c) 2024 Igara Studio S.A.
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.

#include "base/paths.h"
#include "os/os.h"
#include "text/text.h"

#include <cstdio>
#include <string>

struct WindowData {
bool dragEnter;
bool dragLeave;
int drag;
base::paths paths;
os::SurfaceRef image;
std::string url;
gfx::Point dragPosition;
gfx::Rect dropZone;
};

static text::FontRef font;
static WindowData windowData;

static void redraw_window(os::Window* window);

class DragTarget : public os::DragTarget {
public:
void dragEnter(os::DragEvent& ev) override {
if (!windowData.dropZone.contains(ev.position()) ||
!ev.sourceSupports(os::DropOperation::Copy)) {
ev.dropResult(os::DropOperation::None);
}
else if (ev.sourceSupports(os::DropOperation::Copy)) {
ev.dropResult(os::DropOperation::Copy);
}

windowData.dragEnter = true;
windowData.dragLeave = false;
windowData.drag = 0;
windowData.dragPosition = ev.position();
redraw_window(ev.target());
}

void dragLeave(os::DragEvent& ev) override {
windowData.dragEnter = false;
windowData.dragLeave = true;
windowData.dragPosition = ev.position();
redraw_window(ev.target());
}

void drag(os::DragEvent& ev) override {
++windowData.drag;
windowData.dragPosition = ev.position();
redraw_window(ev.target());
}

void drop(os::DragEvent& ev) override {
windowData.dragEnter = false;
windowData.dragLeave = false;
windowData.dragPosition = { 0, 0 };
ev.acceptDrop(windowData.dropZone.contains(ev.position()));

if (ev.acceptDrop()) {
if (ev.dataProvider()->contains(os::DragDataItemType::Paths))
windowData.paths = ev.dataProvider()->getPaths();
else
windowData.paths.clear();

#if CLIP_ENABLE_IMAGE
if (ev.dataProvider()->contains(os::DragDataItemType::Image))
windowData.image = ev.dataProvider()->getImage();
else
windowData.image.reset();
#endif

if (ev.dataProvider()->contains(os::DragDataItemType::Url))
windowData.url = ev.dataProvider()->getUrl();
else
windowData.url.clear();
}

redraw_window(ev.target());
}
};

static void redraw_window(os::Window* window)
{
os::Surface* s = window->surface();
const gfx::Rect rc = s->bounds();

os::Paint paint;
paint.color(gfx::rgba(32, 32, 32, 255));
s->drawRect(rc, paint);

paint.color(gfx::rgba(255, 255, 200, 255));

char buf[2049];
int y = 12;
std::snprintf(buf, sizeof(buf), "Drag Position = [%d, %d]", windowData.dragPosition.x, windowData.dragPosition.y);
text::draw_text(s, font, buf, gfx::Point(0, y), &paint);
y += 12;
std::snprintf(buf, sizeof(buf), "Drag Enter = %s", windowData.dragEnter ? "true" : "false");
text::draw_text(s, font, buf, gfx::Point(0, y), &paint);
y += 12;
std::snprintf(buf, sizeof(buf), "Drag = %d", windowData.drag);
text::draw_text(s, font, buf, gfx::Point(0, y), &paint);
y += 12;
std::snprintf(buf, sizeof(buf), "Drag Leave = %s", windowData.dragLeave ? "true" : "false");
text::draw_text(s, font, buf, gfx::Point(0, y), &paint);

if (!windowData.paths.empty()) {
y += 12;
std::snprintf(buf, sizeof(buf), "Paths = %lu", windowData.paths.size());
text::draw_text(s, font, buf, gfx::Point(0, y), &paint);
for (const auto& path : windowData.paths) {
y += 12;
std::snprintf(buf, sizeof(buf), "%s", path.c_str());
text::draw_text(s, font, buf, gfx::Point(12, y), &paint);
}
}

if (!windowData.url.empty()) {
y += 12;
std::snprintf(buf, sizeof(buf), "URL:");
text::draw_text(s, font, buf, gfx::Point(0, y), &paint);
y += 12;
std::snprintf(buf, sizeof(buf), "%s", windowData.url.c_str());
text::draw_text(s, font, buf, gfx::Point(12, y), &paint);
}

if (windowData.image) {
y += 12;
s->drawRgbaSurface(windowData.image.get(), 0, y);
}

paint.style(os::Paint::Style::Stroke);
s->drawRect(rc, paint);

auto zoneColor = paint.color();
auto textColor = zoneColor;

windowData.dropZone.x = rc.w - windowData.dropZone.w - 12;
if (windowData.dropZone.contains(windowData.dragPosition)) {
paint.style(os::Paint::Style::Fill);
paint.color(zoneColor);
s->drawRect(windowData.dropZone, paint);
textColor = gfx::rgba(0, 0, 0);
}

paint.color(zoneColor);
paint.style(os::Paint::Style::Stroke);
s->drawRect(windowData.dropZone, paint);

paint.color(textColor);
paint.style(os::Paint::Style::Fill);
text::draw_text(s, font, "Drop here!", windowData.dropZone.center(),
&paint, text::TextAlign::Center);

if (window->isVisible())
window->invalidateRegion(gfx::Region(rc));
else
window->setVisible(true);
}

static os::WindowRef create_window(os::DragTarget& dragTarget)
{
auto system = os::System::instance();
auto screen = system->mainScreen();
os::WindowSpec spec;
spec.titled(true);
spec.position(os::WindowSpec::Position::Frame);
spec.frame(screen->workarea()/2);
spec.screen(screen);
spec.scale(2);

os::WindowRef newWindow = system->makeWindow(spec);
newWindow->setCursor(os::NativeCursor::Arrow);
newWindow->setTitle("Drag & Drop");
newWindow->setDragTarget(&dragTarget);

windowData.dropZone = gfx::Rect(spec.frame().w-64-12, 12, 64, 64);
redraw_window(newWindow.get());
return newWindow;
}

int app_main(int argc, char* argv[])
{
auto system = os::System::make();

system->setAppMode(os::AppMode::GUI);
system->handleWindowResize = redraw_window;

font = text::FontMgr::Make()->defaultFont();

DragTarget dragTarget;
os::WindowRef window = create_window(dragTarget);

bool running = true;

system->finishLaunching();
system->activateApp();

os::EventQueue* queue = system->eventQueue();
os::Event ev;
while (running) {
queue->getEvent(ev);

switch (ev.type()) {

case os::Event::KeyDown:
switch (ev.scancode()) {
case os::kKeyEsc:
running = false;
break;
}
break;

case os::Event::CloseApp:
case os::Event::CloseWindow:
running = false;
break;

case os::Event::ResizeWindow:
redraw_window(ev.window().get());
break;

default:
// Do nothing
break;
}
}

return 0;
}
3 changes: 3 additions & 0 deletions os/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ set(LAF_OS_SOURCES
common/event_queue.cpp
common/main.cpp
common/system.cpp
dnd.cpp
error.cpp
event.cpp
none/system.cpp
window.cpp)
if(WIN32)
list(APPEND LAF_OS_SOURCES
win/color_space.cpp
win/dnd.cpp
win/event_queue.cpp
win/keys.cpp
win/native_dialogs.cpp
Expand All @@ -31,6 +33,7 @@ elseif(APPLE)
list(APPEND LAF_OS_SOURCES
osx/app.mm
osx/app_delegate.mm
osx/dnd.mm
osx/color_space.mm
osx/event_queue.mm
osx/keys.mm
Expand Down
Loading

0 comments on commit c90b81a

Please sign in to comment.