#include "CtrlCore.h" NAMESPACE_UPP ClipData::ClipData(const Value& data, String (*render)(const Value& data)) : data(data), render(render) {} String sRawClipData(const Value& data) { return data; } ClipData::ClipData(const String& data) : data(data), render(sRawClipData) {} ClipData::ClipData() : render(sRawClipData) {} void Ctrl::DragAndDrop(Point p, PasteClip& d) {} void Ctrl::FrameDragAndDrop(Point p, PasteClip& d) {} void Ctrl::DragEnter() {} void Ctrl::DragRepeat(Point p) {} void Ctrl::DragLeave() {} PasteClip& Ctrl::Clipboard() { static PasteClip d; d.fmt.Clear(); return d; } PasteClip& Ctrl::Selection() { static PasteClip d; #ifdef PLATFORM_X11 d.fmt.Clear(); d.type = 2; #endif return d; } String Ctrl::GetDropData(const String& fmt) const { return GetSelectionData(fmt); } String Ctrl::GetSelectionData(const String& fmt) const { return Null; } #ifdef PLATFORM_WIN32 bool Has(UDropTarget *dt, const char *fmt); String Get(UDropTarget *dt, const char *fmt); bool PasteClip::IsAvailable(const char *fmt) const { if(this == &Ctrl::Selection()) return false; return dt ? UPP::Has(dt, fmt) : IsClipboardAvailable(fmt); } String PasteClip::Get(const char *fmt) const { if(this == &Ctrl::Selection()) return Null; return dt ? UPP::Get(dt, fmt) : ReadClipboard(fmt); } #endif #ifdef PLATFORM_X11 bool PasteClip::IsAvailable(const char *fmt) const { return Ctrl::ClipHas(type, fmt); } String PasteClip::Get(const char *fmt) const { return Ctrl::ClipGet(type, fmt); } #endif bool PasteClip::Accept() { accepted = true; return paste; } bool PasteClip::Accept(const char *_fmt) { Vector f = Split(_fmt, ';'); for(int i = 0; i < f.GetCount(); i++) { if(IsAccepted() && fmt == _fmt) return paste; if(IsAvailable(f[i])) { accepted = true; if(paste) { fmt = f[i]; data = Get(f[i]); return true; } break; } } return false; } PasteClip::PasteClip() { paste = true; accepted = false; #ifdef PLATFORM_WIN32 dt = NULL; #else type = 0; #endif } int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions) { VectorMap dummy; return DoDragAndDrop(fmts, sample, actions, dummy); } int Ctrl::DoDragAndDrop(const VectorMap& data, const Image& sample, dword actions) { return DoDragAndDrop("", sample, actions, data); } Uuid sDndUuid; const void *sInternalPtr; String GetInternalDropId__(const char *type, const char *id) { return "U++ Internal clip:" + AsString(sDndUuid) + '-' + type + '-' + id; } void NewInternalDrop__(const void *ptr) { sDndUuid = Uuid::Create(); sInternalPtr = ptr; } const void *GetInternalDropPtr__() { return sInternalPtr; } String Unicode__(const WString& w) { return String((const char *)~w, 2 * w.GetLength()); } WString Unicode__(const String& s) { return WString((const wchar *)~s, s.GetLength() / 2); } Image MakeDragImage(const Image& arrow, Image sample) { ImageBuffer b; if(IsNull(sample)) { sample = CtrlCoreImg::DndData(); b = sample; Over(b, Point(0, 0), arrow, arrow.GetSize()); } else { b.Create(128, 128); memset(~b, 0, sizeof(RGBA) * b.GetLength()); Size ssz = sample.GetSize(); Over(b, Point(2, 22), sample, sample.GetSize()); for(int y = 20; y < 96; y++) { RGBA *s = b[y]; RGBA *e = s + 96; while(s < e) (s++)->a >>= 1; e += 32; int q = 128; while(s < e) { s->a = (s->a * q) >> 8; q -= 4; s++; } } int qq = 128; for(int y = 96; y < 128; y++) { RGBA *s = b[y]; RGBA *e = s + 96; while(s < e) { s->a = (s->a * qq) >> 8; s++; } e += 32; int q = 255; while(s < e) { s->a = (s->a * q * qq) >> 16; q -= 8; s++; } qq -= 4; } RGBA *s = b[21] + 1; RGBA c1 = Blue(); RGBA c2 = White(); for(int a = 255; a > 0; a -= 3) { c1.a = c2.a = a; *s++ = c1; Swap(c1, c2); } s = b[21] + 1; c1 = Black(); c2 = White(); for(int a = 255; a > 0; a -= 8) { c1.a = c2.a = a; *s = c1; s += b.GetWidth(); Swap(c1, c2); } } Over(b, Point(0, 0), arrow, arrow.GetSize()); return b; } Ptr Ctrl::dndctrl; Point Ctrl::dndpos; bool Ctrl::dndframe; PasteClip Ctrl::dndclip; void Ctrl::DnDRepeat() { if(dndctrl) { dndctrl->DragRepeat(dndpos); if(dndctrl) { PasteClip d = dndclip; if(dndframe) dndctrl->FrameDragAndDrop(dndpos, d); else dndctrl->DragAndDrop(dndpos, d); } } else UPP::KillTimeCallback(&dndpos); } void Ctrl::DnD(Point p, PasteClip& clip) { UPP::KillTimeCallback(&dndpos); dndclip = clip; Point hp = p - GetScreenRect().TopLeft(); Ptr ctrl = this; while(ctrl && ctrl->IsEnabled()) { Rect view = ctrl->GetScreenView(); if(ctrl->IsMouseActive()) if(view.Contains(p)) { dndpos = p - view.TopLeft(); dndframe = false; ctrl->DragAndDrop(dndpos, clip); if(clip.IsAccepted()) break; } else { dndpos = p - ctrl->GetScreenRect().TopLeft(); dndframe = true; ctrl->FrameDragAndDrop(dndpos, clip); if(clip.IsAccepted()) break; } ctrl = ctrl->ChildFromPoint(hp); } if(ctrl != dndctrl) { if(dndctrl) dndctrl->DragLeave(); dndctrl = ctrl; if(dndctrl) dndctrl->DragEnter(); } if(dndctrl) UPP::SetTimeCallback(-40, callback(DnDRepeat), &dndpos); } void Ctrl::DnDLeave() { if(dndctrl) { dndctrl->DragLeave(); UPP::KillTimeCallback(&dndpos); dndctrl = NULL; } } Ctrl *Ctrl::GetDragAndDropTarget() { return dndctrl; } END_UPP_NAMESPACE