← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 3161: Drag & drop text into text input fields

 

------------------------------------------------------------
revno: 3161
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Fri 2012-12-21 23:50:48 +0100
message:
  Drag & drop text into text input fields
modified:
  changelog.txt
  dwt/include/dwt/widgets/TextBox.h
  dwt/src/Application.cpp
  dwt/src/widgets/TextBox.cpp
  win32/main.cpp


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'changelog.txt'
--- changelog.txt	2012-12-20 19:38:26 +0000
+++ changelog.txt	2012-12-21 22:50:48 +0000
@@ -12,6 +12,7 @@
 * [L#311818] Share file name duplicates due to directory merges (poy)
 * [L#311818] Share file name duplicates due to case differences (poy)
 * [L#311818] Reject file lists that contain duplicate items (poy)
+* Drag & drop text into text input fields (poy)
 
 Note: The hash registry will be upgraded when running this version for the
 first time. Make sure all your drives are connected to avoid re-hashing.

=== modified file 'dwt/include/dwt/widgets/TextBox.h'
--- dwt/include/dwt/widgets/TextBox.h	2012-02-09 19:45:38 +0000
+++ dwt/include/dwt/widgets/TextBox.h	2012-12-21 22:50:48 +0000
@@ -153,6 +153,9 @@
 
 	unsigned getLineCount() const;
 
+	virtual int charFromPos(const ScreenCoordinate& pt) = 0;
+	virtual int lineFromPos(const ScreenCoordinate& pt) = 0;
+
 	virtual tstring textUnderCursor(const ScreenCoordinate& p, bool includeSpaces = false) = 0;
 	virtual tstring getSelection() const = 0;
 

=== modified file 'dwt/src/Application.cpp'
--- dwt/src/Application.cpp	2012-11-05 20:39:11 +0000
+++ dwt/src/Application.cpp	2012-12-21 22:50:48 +0000
@@ -250,8 +250,14 @@
 int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
 	dwt::Application::init(nCmdShow);
 
+	auto hr = ::OleInitialize(nullptr);
+	if(FAILED(hr))
+		return hr;
+
 	int ret = dwtMain(dwt::Application::instance()); // Call library user's startup function.
 
+	::OleUninitialize();
+
 	dwt::Application::uninit();
 
 	return ret;

=== modified file 'dwt/src/widgets/TextBox.cpp'
--- dwt/src/widgets/TextBox.cpp	2012-03-05 20:48:24 +0000
+++ dwt/src/widgets/TextBox.cpp	2012-12-21 22:50:48 +0000
@@ -59,10 +59,121 @@
 {
 }
 
+class Dropper : public IDropTarget {
+public:
+	Dropper(TextBoxBase* const w) : IDropTarget(), w(w), ref(0), dragging(false) { }
+
+	virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+		/* [in] */ REFIID riid,
+		/* [iid_is][out]  _COM_Outptr_*/ void __RPC_FAR *__RPC_FAR *ppvObject)
+	{
+		if(!ppvObject) { return E_POINTER; }
+		if(IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IDropTarget)) {
+			*ppvObject = this;
+			AddRef();
+			return S_OK;
+		}
+		return E_NOINTERFACE;
+	}
+
+	virtual ULONG STDMETHODCALLTYPE AddRef( void)
+	{
+		return ++ref;
+	}
+
+	virtual ULONG STDMETHODCALLTYPE Release( void)
+	{
+		if(--ref == 0) { delete this; }
+		return ref;
+	}
+
+	virtual HRESULT STDMETHODCALLTYPE DragEnter(
+		/* [unique][in]  __RPC__in_opt*/ IDataObject *pDataObj,
+		/* [in] */ DWORD /*grfKeyState*/,
+		/* [in] */ POINTL /*pt*/,
+		/* [out][in]  __RPC__inout*/ DWORD *pdwEffect)
+	{
+		if(w->hasStyle(ES_READONLY)) { return S_OK; }
+		FORMATETC formatetc { CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+		dragging = pDataObj->QueryGetData(&formatetc) == S_OK;
+		if(dragging) {
+			w->setFocus(); // focus to display the caret
+			*pdwEffect = DROPEFFECT_COPY;
+		} else {
+			*pdwEffect = DROPEFFECT_NONE;
+		}
+		return S_OK;
+	}
+
+	virtual HRESULT STDMETHODCALLTYPE DragOver(
+		/* [in] */ DWORD /*grfKeyState*/,
+		/* [in] */ POINTL pt,
+		/* [out][in]  __RPC__inout*/ DWORD *pdwEffect)
+	{
+		if(dragging) {
+			moveCaret(pt);
+			*pdwEffect = DROPEFFECT_COPY;
+		} else {
+			*pdwEffect = DROPEFFECT_NONE;
+		}
+		return S_OK;
+	}
+
+	virtual HRESULT STDMETHODCALLTYPE DragLeave( void)
+	{
+		dragging = false;
+		return S_OK;
+	}
+
+	virtual HRESULT STDMETHODCALLTYPE Drop(
+		/* [unique][in]  __RPC__in_opt*/ IDataObject *pDataObj,
+		/* [in] */ DWORD /*grfKeyState*/,
+		/* [in] */ POINTL pt,
+		/* [out][in]  __RPC__inout*/ DWORD *pdwEffect)
+	{
+		if(dragging) {
+			FORMATETC formatetc { CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+			STGMEDIUM stgmedium;
+			if(pDataObj->GetData(&formatetc, &stgmedium) == S_OK) {
+				if(stgmedium.tymed == TYMED_HGLOBAL && stgmedium.hGlobal) {
+					auto text = reinterpret_cast<LPCTSTR>(::GlobalLock(stgmedium.hGlobal));
+					if(text) {
+						moveCaret(pt);
+						w->replaceSelection(text);
+						::GlobalUnlock(stgmedium.hGlobal);
+					}
+				}
+				::ReleaseStgMedium(&stgmedium);
+			}
+			*pdwEffect = DROPEFFECT_COPY;
+		} else {
+			*pdwEffect = DROPEFFECT_NONE;
+		}
+		return S_OK;
+	}
+
+private:
+	inline void moveCaret(const POINTL& pt) {
+		auto pos = w->charFromPos(ScreenCoordinate(Point(pt.x, pt.y)));
+		w->setSelection(pos, pos);
+	}
+
+	TextBoxBase* const w;
+	ULONG ref;
+	bool dragging;
+};
+
 void TextBoxBase::create(const Seed& cs) {
 	lines = cs.lines;
 	menuSeed = cs.menuSeed;
 	BaseType::create(cs);
+
+	auto dropper = new Dropper(this);
+	if(::RegisterDragDrop(handle(), dropper) == S_OK) {
+		onDestroy([this] { ::RevokeDragDrop(handle()); });
+	} else {
+		delete dropper;
+	}
 }
 
 TextBox::Seed::Seed(const tstring& caption) :

=== modified file 'win32/main.cpp'
--- win32/main.cpp	2012-12-08 17:44:30 +0000
+++ win32/main.cpp	2012-12-21 22:50:48 +0000
@@ -122,10 +122,6 @@
 		return 1;
 	}
 
-	HRESULT hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
-	if(FAILED(hr))
-		return hr;
-
 	try {
 		std::string module = File(Text::fromT(app.getModuleFileName()), File::READ, File::OPEN).read();
 		TigerTree tth(TigerTree::calcBlockSize(module.size(), 1));
@@ -172,8 +168,6 @@
 
 	shutdown();
 
-	::CoUninitialize();
-
 	return 0;
 }