add simple_dragdrop feature
This commit is contained in:
parent
ff9b90a766
commit
711dff56de
@ -1111,7 +1111,7 @@ namespace detail
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool platform_spec::register_dragdrop(native_window_type wd, dragdrop_interface* ddrop)
|
bool platform_spec::register_dragdrop(native_window_type wd, x11_dragdrop_interface* ddrop)
|
||||||
{
|
{
|
||||||
platform_scope_guard lock;
|
platform_scope_guard lock;
|
||||||
if(0 != xdnd_.dragdrop.count(wd))
|
if(0 != xdnd_.dragdrop.count(wd))
|
||||||
@ -1121,13 +1121,11 @@ namespace detail
|
|||||||
::XChangeProperty(display_, reinterpret_cast<Window>(wd), atombase_.xdnd_aware, XA_ATOM, sizeof(int) * 8,
|
::XChangeProperty(display_, reinterpret_cast<Window>(wd), atombase_.xdnd_aware, XA_ATOM, sizeof(int) * 8,
|
||||||
PropModeReplace, reinterpret_cast<unsigned char*>(&dndver), 1);
|
PropModeReplace, reinterpret_cast<unsigned char*>(&dndver), 1);
|
||||||
|
|
||||||
auto & ref_drop = xdnd_.dragdrop[wd];
|
xdnd_.dragdrop[wd] = ddrop;
|
||||||
ref_drop.dragdrop = ddrop;
|
|
||||||
ref_drop.ref_count = 1;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
dragdrop_interface* platform_spec::remove_dragdrop(native_window_type wd)
|
x11_dragdrop_interface* platform_spec::remove_dragdrop(native_window_type wd)
|
||||||
{
|
{
|
||||||
platform_scope_guard lock;
|
platform_scope_guard lock;
|
||||||
auto i = xdnd_.dragdrop.find(wd);
|
auto i = xdnd_.dragdrop.find(wd);
|
||||||
@ -1135,13 +1133,9 @@ namespace detail
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto ddrop = i->second;
|
auto ddrop = i->second;
|
||||||
if(ddrop.ref_count <= 1)
|
|
||||||
{
|
|
||||||
xdnd_.dragdrop.erase(i);
|
xdnd_.dragdrop.erase(i);
|
||||||
return ddrop.dragdrop;
|
|
||||||
}
|
return ddrop;
|
||||||
--ddrop.ref_count;
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//_m_msg_filter
|
//_m_msg_filter
|
||||||
|
|||||||
@ -177,10 +177,13 @@ namespace detail
|
|||||||
~platform_scope_guard();
|
~platform_scope_guard();
|
||||||
};
|
};
|
||||||
|
|
||||||
class dragdrop_interface
|
class x11_dragdrop_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~dragdrop_interface() = default;
|
virtual ~x11_dragdrop_interface() = default;
|
||||||
|
|
||||||
|
virtual void add_ref() = 0;
|
||||||
|
virtual std::size_t release() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class platform_spec
|
class platform_spec
|
||||||
@ -264,8 +267,8 @@ namespace detail
|
|||||||
// the image object is release in remove() method.
|
// the image object is release in remove() method.
|
||||||
const nana::paint::graphics& keep_window_icon(native_window_type, const nana::paint::image&);
|
const nana::paint::graphics& keep_window_icon(native_window_type, const nana::paint::image&);
|
||||||
|
|
||||||
bool register_dragdrop(native_window_type, dragdrop_interface*);
|
bool register_dragdrop(native_window_type, x11_dragdrop_interface*);
|
||||||
dragdrop_interface* remove_dragdrop(native_window_type);
|
x11_dragdrop_interface* remove_dragdrop(native_window_type);
|
||||||
private:
|
private:
|
||||||
static int _m_msg_filter(XEvent&, msg_packet_tag&);
|
static int _m_msg_filter(XEvent&, msg_packet_tag&);
|
||||||
void _m_caret_routine();
|
void _m_caret_routine();
|
||||||
@ -323,13 +326,7 @@ namespace detail
|
|||||||
Window wd_src;
|
Window wd_src;
|
||||||
nana::point pos;
|
nana::point pos;
|
||||||
|
|
||||||
struct refcount_dragdrop
|
std::map<native_window_type, x11_dragdrop_interface*> dragdrop;
|
||||||
{
|
|
||||||
dragdrop_interface* dragdrop{nullptr};
|
|
||||||
std::size_t ref_count{0};
|
|
||||||
};
|
|
||||||
|
|
||||||
std::map<native_window_type, refcount_dragdrop> dragdrop;
|
|
||||||
}xdnd_;
|
}xdnd_;
|
||||||
|
|
||||||
msg_dispatcher * msg_dispatcher_;
|
msg_dispatcher * msg_dispatcher_;
|
||||||
|
|||||||
@ -32,38 +32,65 @@
|
|||||||
# include <fstream>
|
# include <fstream>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace nana
|
namespace nana
|
||||||
{
|
{
|
||||||
/// drop_association
|
class dragdrop_session
|
||||||
/**
|
|
||||||
* This class is used for querying whether tow windows have a connection of drag and drop
|
|
||||||
*/
|
|
||||||
class drop_association
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void add(window source, window target)
|
virtual ~dragdrop_session() = default;
|
||||||
|
|
||||||
|
void insert(window source, window target)
|
||||||
{
|
{
|
||||||
assoc_[source].insert(target);
|
table_[source].insert(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase(window wd)
|
void erase(window source, window target)
|
||||||
{
|
{
|
||||||
assoc_.erase(wd);
|
auto i = table_.find(source);
|
||||||
|
if (table_.end() == i)
|
||||||
|
return;
|
||||||
|
|
||||||
for (auto & assoc : assoc_)
|
i->second.erase(target);
|
||||||
assoc.second.erase(wd);
|
|
||||||
|
if ((nullptr == target) || i->second.empty())
|
||||||
|
table_.erase(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has(window source, window target) const
|
bool has(window source, window target) const
|
||||||
{
|
{
|
||||||
auto i = assoc_.find(source);
|
auto i = table_.find(source);
|
||||||
if (i != assoc_.end())
|
if (i != table_.end())
|
||||||
return (0 != i->second.count(target));
|
return (0 != i->second.count(target));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool has_source(window source) const
|
||||||
|
{
|
||||||
|
return (table_.count(source) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
return table_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_current_source(window source)
|
||||||
|
{
|
||||||
|
if (table_.count(source))
|
||||||
|
current_source_ = source;
|
||||||
|
else
|
||||||
|
current_source_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
window current_source() const
|
||||||
|
{
|
||||||
|
return current_source_;
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
std::map<window, std::set<window>> assoc_;
|
std::map<window, std::set<window>> table_;
|
||||||
|
window current_source_{ nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef NANA_WINDOWS
|
#ifdef NANA_WINDOWS
|
||||||
@ -98,18 +125,8 @@ namespace nana
|
|||||||
LONG ref_count_{ 1 };
|
LONG ref_count_{ 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class win32com_drop_target : public IDropTarget, public dragdrop_session
|
||||||
class win32com_drop_target : public IDropTarget
|
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
win32com_drop_target(const drop_association& drop_assoc) :
|
|
||||||
drop_assoc_(drop_assoc)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void set_source(window wd)
|
|
||||||
{
|
|
||||||
source_window_ = wd;
|
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
//Implements IUnknown
|
//Implements IUnknown
|
||||||
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
|
STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
|
||||||
@ -146,11 +163,11 @@ namespace nana
|
|||||||
STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
|
STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
|
||||||
{
|
{
|
||||||
auto hovered_wd = API::find_window(point(pt.x, pt.y));
|
auto hovered_wd = API::find_window(point(pt.x, pt.y));
|
||||||
if ((hovered_wd && (hovered_wd == source_window_)) || drop_assoc_.has(source_window_, hovered_wd))
|
|
||||||
|
if ((hovered_wd && (hovered_wd == this->current_source())) || this->has(this->current_source(), hovered_wd))
|
||||||
*pdwEffect &= DROPEFFECT_COPY;
|
*pdwEffect &= DROPEFFECT_COPY;
|
||||||
else
|
else
|
||||||
*pdwEffect = DROPEFFECT_NONE;
|
*pdwEffect = DROPEFFECT_NONE;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,9 +182,6 @@ namespace nana
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
LONG ref_count_{ 1 };
|
LONG ref_count_{ 1 };
|
||||||
|
|
||||||
window source_window_{ nullptr };
|
|
||||||
const drop_association& drop_assoc_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class drop_source : public win32com_iunknown<IDropSource, IID_IDropSource>
|
class drop_source : public win32com_iunknown<IDropSource, IID_IDropSource>
|
||||||
@ -374,9 +388,25 @@ namespace nana
|
|||||||
std::vector<medium> mediums_;
|
std::vector<medium> mediums_;
|
||||||
};
|
};
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
class x11_dragdrop: public detail::dragdrop_interface
|
class x11_dragdrop: public detail::x11_dragdrop_interface, public dragdrop_session
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
//Implement x11_dragdrop_interface
|
||||||
|
void add_ref() override
|
||||||
|
{
|
||||||
|
++ref_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t release() override
|
||||||
|
{
|
||||||
|
std::size_t val = --ref_count_;
|
||||||
|
if(0 == val)
|
||||||
|
delete this;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::atomic<std::size_t> ref_count_{ 1 };
|
||||||
};
|
};
|
||||||
|
|
||||||
class shared_icons
|
class shared_icons
|
||||||
@ -433,68 +463,89 @@ namespace nana
|
|||||||
{
|
{
|
||||||
dragdrop_service() = default;
|
dragdrop_service() = default;
|
||||||
public:
|
public:
|
||||||
|
#ifdef NANA_WINDOWS
|
||||||
|
using dragdrop_target = win32com_drop_target;
|
||||||
|
#else
|
||||||
|
using dragdrop_target = x11_dragdrop;
|
||||||
|
#endif
|
||||||
|
|
||||||
static dragdrop_service& instance()
|
static dragdrop_service& instance()
|
||||||
{
|
{
|
||||||
static dragdrop_service serv;
|
static dragdrop_service serv;
|
||||||
return serv;
|
return serv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_dragdrop(window wd)
|
dragdrop_session* create_dragdrop(window wd)
|
||||||
{
|
{
|
||||||
auto native_wd = API::root(wd);
|
auto native_wd = API::root(wd);
|
||||||
if (nullptr == native_wd)
|
if (nullptr == native_wd)
|
||||||
return;
|
return nullptr;
|
||||||
|
|
||||||
|
dragdrop_target * ddrop = nullptr;
|
||||||
|
|
||||||
|
auto i = table_.find(native_wd);
|
||||||
|
if(table_.end() == i)
|
||||||
|
{
|
||||||
|
ddrop = new dragdrop_target;
|
||||||
#ifdef NANA_WINDOWS
|
#ifdef NANA_WINDOWS
|
||||||
if (table_.empty())
|
if (table_.empty())
|
||||||
::OleInitialize(nullptr);
|
::OleInitialize(nullptr);
|
||||||
|
|
||||||
win32com_drop_target* drop_target = nullptr;
|
::RegisterDragDrop(reinterpret_cast<HWND>(native_wd), ddrop);
|
||||||
|
#else
|
||||||
auto i = table_.find(native_wd);
|
if(!_m_spec().register_dragdrop(native_wd, ddrop))
|
||||||
if (i == table_.end())
|
|
||||||
{
|
{
|
||||||
drop_target = new win32com_drop_target{drop_assoc_};
|
delete ddrop;
|
||||||
::RegisterDragDrop(reinterpret_cast<HWND>(native_wd), drop_target);
|
return nullptr;
|
||||||
|
}
|
||||||
table_[native_wd] = drop_target;
|
#endif
|
||||||
|
table_[native_wd] = ddrop;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
drop_target = i->second;
|
ddrop = dynamic_cast<dragdrop_target*>(i->second);
|
||||||
drop_target->AddRef();
|
|
||||||
}
|
|
||||||
#elif defined(NANA_X11)
|
|
||||||
auto ddrop = new x11_dragdrop;
|
|
||||||
if(!_m_spec().register_dragdrop(native_wd, ddrop))
|
|
||||||
delete ddrop;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove(window wd)
|
|
||||||
{
|
|
||||||
#ifdef NANA_WINDOWS
|
#ifdef NANA_WINDOWS
|
||||||
auto i = table_.find(API::root(wd));
|
ddrop->AddRef();
|
||||||
if (i != table_.end())
|
#else
|
||||||
{
|
ddrop->add_ref();
|
||||||
if (0 == i->second->Release())
|
|
||||||
table_.erase(i);
|
|
||||||
}
|
|
||||||
#elif defined(NANA_X11)
|
|
||||||
auto ddrop = _m_spec().remove_dragdrop(API::root(wd));
|
|
||||||
delete ddrop;
|
|
||||||
#endif
|
#endif
|
||||||
drop_assoc_.erase(wd);
|
}
|
||||||
|
|
||||||
|
return ddrop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(window source)
|
||||||
|
{
|
||||||
|
auto native_src = API::root(source);
|
||||||
|
|
||||||
|
auto i = table_.find(API::root(source));
|
||||||
|
if (i == table_.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
i->second->erase(source, nullptr);
|
||||||
|
|
||||||
|
if (i->second->empty())
|
||||||
|
{
|
||||||
|
auto ddrop = dynamic_cast<dragdrop_target*>(i->second);
|
||||||
|
table_.erase(i);
|
||||||
|
#ifdef NANA_WINDOWS
|
||||||
|
::RevokeDragDrop(reinterpret_cast<HWND>(native_src));
|
||||||
|
ddrop->Release();
|
||||||
|
#elif defined(NANA_X11)
|
||||||
|
_m_spec().remove_dragdrop(native_src);
|
||||||
|
ddrop->release();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dragdrop(window drag_wd)
|
bool dragdrop(window drag_wd)
|
||||||
{
|
{
|
||||||
#ifdef NANA_WINDOWS
|
|
||||||
auto i = table_.find(API::root(drag_wd));
|
auto i = table_.find(API::root(drag_wd));
|
||||||
if (table_.end() == i)
|
if (table_.end() == i)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
#ifdef NANA_WINDOWS
|
||||||
auto drop_src = new drop_source{ drag_wd };
|
auto drop_src = new drop_source{ drag_wd };
|
||||||
auto drop_dat = new (std::nothrow) drop_data;
|
auto drop_dat = new (std::nothrow) drop_data;
|
||||||
if (!drop_dat)
|
if (!drop_dat)
|
||||||
@ -503,21 +554,25 @@ namespace nana
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
i->second->set_source(drag_wd);
|
i->second->set_current_source(drag_wd);
|
||||||
|
|
||||||
|
|
||||||
DWORD eff;
|
DWORD eff;
|
||||||
auto status = ::DoDragDrop(drop_dat, drop_src, DROPEFFECT_COPY, &eff);
|
auto status = ::DoDragDrop(drop_dat, drop_src, DROPEFFECT_COPY, &eff);
|
||||||
|
|
||||||
i->second->set_source(nullptr);
|
i->second->set_current_source(nullptr);
|
||||||
|
|
||||||
|
delete drop_src;
|
||||||
|
delete drop_dat;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
auto const native_wd = reinterpret_cast<Window>(API::root(drag_wd));
|
auto ddrop = dynamic_cast<x11_dragdrop*>(i->second);
|
||||||
|
|
||||||
|
auto const native_source = reinterpret_cast<Window>(API::root(drag_wd));
|
||||||
|
|
||||||
{
|
{
|
||||||
detail::platform_scope_guard lock;
|
detail::platform_scope_guard lock;
|
||||||
::XSetSelectionOwner(_m_spec().open_display(), _m_spec().atombase().xdnd_selection, native_wd, CurrentTime);
|
::XSetSelectionOwner(_m_spec().open_display(), _m_spec().atombase().xdnd_selection, native_source, CurrentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -528,7 +583,7 @@ namespace nana
|
|||||||
//while(true)
|
//while(true)
|
||||||
{
|
{
|
||||||
|
|
||||||
_m_spec().msg_dispatch([this, drag_wd, native_wd, &target_wd, &atombase](const detail::msg_packet_tag& msg_pkt) mutable{
|
_m_spec().msg_dispatch([this, ddrop, drag_wd, native_source, &target_wd, &atombase](const detail::msg_packet_tag& msg_pkt) mutable{
|
||||||
if(detail::msg_packet_tag::pkt_family::xevent == msg_pkt.kind)
|
if(detail::msg_packet_tag::pkt_family::xevent == msg_pkt.kind)
|
||||||
{
|
{
|
||||||
auto const disp = _m_spec().open_display();
|
auto const disp = _m_spec().open_display();
|
||||||
@ -545,22 +600,21 @@ namespace nana
|
|||||||
::XUndefineCursor(disp, hovered_.native_wd);
|
::XUndefineCursor(disp, hovered_.native_wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
_m_client_msg(native_cur_wd, native_wd, atombase.xdnd_enter, atombase.text_uri_list, XA_STRING);
|
_m_client_msg(native_cur_wd, native_source, atombase.xdnd_enter, atombase.text_uri_list, XA_STRING);
|
||||||
hovered_.native_wd = native_cur_wd;
|
hovered_.native_wd = native_cur_wd;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto cur_wd = API::find_window(API::cursor_position());
|
|
||||||
|
|
||||||
|
|
||||||
|
auto cur_wd = API::find_window(API::cursor_position());
|
||||||
if(hovered_.window_handle != cur_wd)
|
if(hovered_.window_handle != cur_wd)
|
||||||
{
|
{
|
||||||
_m_free_cursor();
|
_m_free_cursor();
|
||||||
|
|
||||||
hovered_.window_handle = cur_wd;
|
hovered_.window_handle = cur_wd;
|
||||||
|
|
||||||
if((drag_wd == cur_wd) || drop_assoc_.has(drag_wd, cur_wd))
|
const char* icon = (((drag_wd == cur_wd) || ddrop->has(drag_wd, cur_wd)) ? "dnd-move" : "dnd-none");
|
||||||
hovered_.cursor = ::XcursorFilenameLoadCursor(disp, icons_.cursor("dnd-move").c_str());
|
hovered_.cursor = ::XcursorFilenameLoadCursor(disp, icons_.cursor(icon).c_str());
|
||||||
else
|
|
||||||
hovered_.cursor = ::XcursorFilenameLoadCursor(disp, icons_.cursor("dnd-none").c_str());
|
|
||||||
::XDefineCursor(disp, native_cur_wd, hovered_.cursor);
|
::XDefineCursor(disp, native_cur_wd, hovered_.cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -582,10 +636,6 @@ namespace nana
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_association& drop_assoc()
|
|
||||||
{
|
|
||||||
return drop_assoc_;
|
|
||||||
}
|
|
||||||
#ifdef NANA_X11
|
#ifdef NANA_X11
|
||||||
private:
|
private:
|
||||||
static nana::detail::platform_spec & _m_spec()
|
static nana::detail::platform_spec & _m_spec()
|
||||||
@ -640,13 +690,12 @@ namespace nana
|
|||||||
::XFreeCursor(_m_spec().open_display(), hovered_.cursor);
|
::XFreeCursor(_m_spec().open_display(), hovered_.cursor);
|
||||||
hovered_.cursor = 0;
|
hovered_.cursor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
private:
|
private:
|
||||||
drop_association drop_assoc_;
|
std::map<native_window_type, dragdrop_session*> table_;
|
||||||
|
|
||||||
#ifdef NANA_WINDOWS
|
#ifdef NANA_WINDOWS
|
||||||
std::map<native_window_type, win32com_drop_target*> table_;
|
|
||||||
#elif defined (NANA_X11)
|
#elif defined (NANA_X11)
|
||||||
shared_icons icons_;
|
shared_icons icons_;
|
||||||
struct hovered_status
|
struct hovered_status
|
||||||
@ -664,12 +713,20 @@ namespace nana
|
|||||||
|
|
||||||
struct simple_dragdrop::implementation
|
struct simple_dragdrop::implementation
|
||||||
{
|
{
|
||||||
window window_handle;
|
window window_handle{ nullptr };
|
||||||
|
dragdrop_session * ddrop{ nullptr };
|
||||||
std::function<bool()> predicate;
|
std::function<bool()> predicate;
|
||||||
std::map<window, std::function<void()>> targets;
|
std::map<window, std::function<void()>> targets;
|
||||||
|
|
||||||
bool dragging{ false };
|
bool dragging{ false };
|
||||||
|
|
||||||
|
struct event_handlers
|
||||||
|
{
|
||||||
|
nana::event_handle destroy;
|
||||||
|
nana::event_handle mouse_move;
|
||||||
|
nana::event_handle mouse_down;
|
||||||
|
}events;
|
||||||
|
|
||||||
#ifdef NANA_X11
|
#ifdef NANA_X11
|
||||||
bool cancel()
|
bool cancel()
|
||||||
{
|
{
|
||||||
@ -697,21 +754,26 @@ namespace nana
|
|||||||
simple_dragdrop::simple_dragdrop(window drag_wd) :
|
simple_dragdrop::simple_dragdrop(window drag_wd) :
|
||||||
impl_(new implementation)
|
impl_(new implementation)
|
||||||
{
|
{
|
||||||
dragdrop_service::instance().create_dragdrop(drag_wd);
|
|
||||||
|
|
||||||
if (!API::is_window(drag_wd))
|
if (!API::is_window(drag_wd))
|
||||||
{
|
{
|
||||||
delete impl_;
|
delete impl_;
|
||||||
throw std::invalid_argument("simple_dragdrop: invalid window handle");
|
throw std::invalid_argument("simple_dragdrop: invalid window handle");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_->ddrop = dragdrop_service::instance().create_dragdrop(drag_wd);
|
||||||
|
|
||||||
impl_->window_handle = drag_wd;
|
impl_->window_handle = drag_wd;
|
||||||
API::dev::window_draggable(drag_wd, true);
|
API::dev::window_draggable(drag_wd, true);
|
||||||
|
|
||||||
auto & events = API::events<>(drag_wd);
|
auto & events = API::events<>(drag_wd);
|
||||||
|
|
||||||
#if 1 //#ifdef NANA_WINDOWS
|
#if 1 //#ifdef NANA_WINDOWS
|
||||||
events.mouse_down.connect_unignorable([this](const arg_mouse& arg){
|
impl_->events.destroy = events.destroy.connect_unignorable([this](const arg_destroy&) {
|
||||||
|
dragdrop_service::instance().remove(impl_->window_handle);
|
||||||
|
API::dev::window_draggable(impl_->window_handle, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_->events.mouse_down = events.mouse_down.connect_unignorable([this](const arg_mouse& arg){
|
||||||
if (arg.is_left_button() && API::is_window(impl_->window_handle))
|
if (arg.is_left_button() && API::is_window(impl_->window_handle))
|
||||||
{
|
{
|
||||||
impl_->dragging = ((!impl_->predicate) || impl_->predicate());
|
impl_->dragging = ((!impl_->predicate) || impl_->predicate());
|
||||||
@ -722,7 +784,7 @@ namespace nana
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
events.mouse_move.connect_unignorable([this](const arg_mouse& arg) {
|
impl_->events.mouse_move = events.mouse_move.connect_unignorable([this](const arg_mouse& arg) {
|
||||||
if (!(arg.is_left_button() && impl_->dragging && API::is_window(arg.window_handle)))
|
if (!(arg.is_left_button() && impl_->dragging && API::is_window(arg.window_handle)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -805,20 +867,34 @@ namespace nana
|
|||||||
}
|
}
|
||||||
|
|
||||||
simple_dragdrop::~simple_dragdrop()
|
simple_dragdrop::~simple_dragdrop()
|
||||||
|
{
|
||||||
|
if (impl_->window_handle)
|
||||||
{
|
{
|
||||||
dragdrop_service::instance().remove(impl_->window_handle);
|
dragdrop_service::instance().remove(impl_->window_handle);
|
||||||
API::dev::window_draggable(impl_->window_handle, false);
|
API::dev::window_draggable(impl_->window_handle, false);
|
||||||
|
|
||||||
|
API::umake_event(impl_->events.destroy);
|
||||||
|
API::umake_event(impl_->events.mouse_down);
|
||||||
|
API::umake_event(impl_->events.mouse_move);
|
||||||
|
}
|
||||||
|
|
||||||
delete impl_;
|
delete impl_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void simple_dragdrop::condition(std::function<bool()> predicate_fn)
|
void simple_dragdrop::condition(std::function<bool()> predicate_fn)
|
||||||
{
|
{
|
||||||
|
if (nullptr == impl_)
|
||||||
|
throw std::logic_error("simple_dragdrop is empty");
|
||||||
|
|
||||||
impl_->predicate.swap(predicate_fn);
|
impl_->predicate.swap(predicate_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void simple_dragdrop::make_drop(window target, std::function<void()> drop_fn)
|
void simple_dragdrop::make_drop(window target, std::function<void()> drop_fn)
|
||||||
{
|
{
|
||||||
dragdrop_service::instance().drop_assoc().add(impl_->window_handle, target);
|
if (nullptr == impl_)
|
||||||
|
throw std::logic_error("simple_dragdrop is empty");
|
||||||
|
|
||||||
|
impl_->ddrop->insert(impl_->window_handle, target);
|
||||||
impl_->targets[target].swap(drop_fn);
|
impl_->targets[target].swap(drop_fn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user