--- /dev/null
+// TortoiseSVN - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseSVN\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+#include "StdAfx.h"\r
+#include "RepoDrags.h"\r
+#include "RepositoryBrowser.h"\r
+#include "SVNDataObject.h"\r
+\r
+CTreeDropTarget::CTreeDropTarget(CRepositoryBrowser * pRepoBrowser) : CIDropTarget(pRepoBrowser->m_RepoTree.GetSafeHwnd())\r
+ , m_pRepoBrowser(pRepoBrowser)\r
+ , m_bFiles(false)\r
+{\r
+}\r
+\r
+bool CTreeDropTarget::OnDrop(FORMATETC* pFmtEtc, STGMEDIUM& medium, DWORD *pdwEffect, POINTL pt)\r
+{\r
+ // find the target\r
+ CString targetUrl;\r
+ HTREEITEM hDropTarget = m_pRepoBrowser->m_RepoTree.GetNextItem(TVI_ROOT, TVGN_DROPHILITE);\r
+ if (hDropTarget)\r
+ {\r
+ CTreeItem * pItem = (CTreeItem*)m_pRepoBrowser->m_RepoTree.GetItemData(hDropTarget);\r
+ if (pItem == NULL)\r
+ return false;\r
+ targetUrl = pItem->url;\r
+ }\r
+ if (pFmtEtc->cfFormat == CF_UNICODETEXT && medium.tymed == TYMED_HGLOBAL)\r
+ {\r
+ TCHAR* pStr = (TCHAR*)GlobalLock(medium.hGlobal);\r
+ CString urls;\r
+ if(pStr != NULL)\r
+ {\r
+ urls = pStr;\r
+ }\r
+ GlobalUnlock(medium.hGlobal);\r
+ urls.Replace(_T("\r\n"), _T("*"));\r
+ CTSVNPathList urlList;\r
+ urlList.LoadFromAsteriskSeparatedString(urls);\r
+\r
+ m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, m_pRepoBrowser->GetRevision(), *pdwEffect, pt);\r
+ }\r
+\r
+ if (pFmtEtc->cfFormat == CF_SVNURL && medium.tymed == TYMED_HGLOBAL)\r
+ {\r
+ TCHAR* pStr = (TCHAR*)GlobalLock(medium.hGlobal);\r
+ CString urls;\r
+ if(pStr != NULL)\r
+ {\r
+ urls = pStr;\r
+ }\r
+ GlobalUnlock(medium.hGlobal);\r
+ urls.Replace(_T("\r\n"), _T("*"));\r
+ CTSVNPathList urlListRevs;\r
+ urlListRevs.LoadFromAsteriskSeparatedString(urls);\r
+ CTSVNPathList urlList;\r
+ SVNRev srcRev;\r
+ for (int i=0; i<urlListRevs.GetCount(); ++i)\r
+ {\r
+ int pos = urlListRevs[i].GetSVNPathString().Find('?');\r
+ if (pos > 0)\r
+ {\r
+ if (!srcRev.IsValid())\r
+ srcRev = SVNRev(urlListRevs[i].GetSVNPathString().Mid(pos+1));\r
+ urlList.AddPath(CTSVNPath(urlListRevs[i].GetSVNPathString().Left(pos)));\r
+ }\r
+ else\r
+ urlList.AddPath(urlListRevs[i]);\r
+ }\r
+\r
+ m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, srcRev, *pdwEffect, pt);\r
+ }\r
+\r
+ if(pFmtEtc->cfFormat == CF_HDROP && medium.tymed == TYMED_HGLOBAL)\r
+ {\r
+ HDROP hDrop = (HDROP)GlobalLock(medium.hGlobal);\r
+ if(hDrop != NULL)\r
+ {\r
+ CTSVNPathList urlList;\r
+ TCHAR szFileName[MAX_PATH];\r
+\r
+ UINT cFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); \r
+ for(UINT i = 0; i < cFiles; ++i)\r
+ {\r
+ DragQueryFile(hDrop, i, szFileName, sizeof(szFileName));\r
+ urlList.AddPath(CTSVNPath(szFileName));\r
+ }\r
+ m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, m_pRepoBrowser->GetRevision(), *pdwEffect, pt);\r
+ }\r
+ GlobalUnlock(medium.hGlobal);\r
+ }\r
+ TreeView_SelectDropTarget(m_hTargetWnd, NULL);\r
+ return true;\r
+}\r
+\r
+HRESULT CTreeDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)\r
+{\r
+ FORMATETC ftetc={0}; \r
+ ftetc.dwAspect = DVASPECT_CONTENT; \r
+ ftetc.lindex = -1; \r
+ ftetc.tymed = TYMED_HGLOBAL; \r
+ ftetc.cfFormat=CF_HDROP; \r
+ if (pDataObj->QueryGetData(&ftetc) == S_OK)\r
+ m_bFiles = true;\r
+ else\r
+ m_bFiles = false;\r
+ m_dwHoverStartTicks = 0;\r
+ hLastItem = NULL;\r
+ return CIDropTarget::DragEnter(pDataObj, grfKeyState, pt, pdwEffect);\r
+}\r
+\r
+HRESULT CTreeDropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)\r
+{\r
+ TVHITTESTINFO hit;\r
+ hit.pt = (POINT&)pt;\r
+ ScreenToClient(m_hTargetWnd,&hit.pt);\r
+ hit.flags = TVHT_ONITEM;\r
+ HTREEITEM hItem = TreeView_HitTest(m_hTargetWnd,&hit);\r
+ if (hItem != hLastItem)\r
+ m_dwHoverStartTicks = 0;\r
+ hLastItem = hItem;\r
+\r
+ *pdwEffect = DROPEFFECT_MOVE;\r
+ if (grfKeyState & MK_CONTROL)\r
+ *pdwEffect = DROPEFFECT_COPY;\r
+\r
+ if (hItem != NULL)\r
+ {\r
+ if (m_bFiles)\r
+ *pdwEffect = DROPEFFECT_COPY;\r
+ TreeView_SelectDropTarget(m_hTargetWnd, hItem);\r
+ if ((m_pRepoBrowser->m_RepoTree.GetItemState(hItem, TVIS_EXPANDED)&TVIS_EXPANDED) != TVIS_EXPANDED)\r
+ {\r
+ if (m_dwHoverStartTicks == 0)\r
+ m_dwHoverStartTicks = GetTickCount();\r
+ UINT timeout = 0;\r
+ //SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &timeout, 0);\r
+ timeout = 2000;\r
+ if ((GetTickCount() - m_dwHoverStartTicks) > timeout)\r
+ {\r
+ // expand the item\r
+ m_pRepoBrowser->m_RepoTree.Expand(hItem, TVE_EXPAND);\r
+ m_dwHoverStartTicks = 0;\r
+ }\r
+ }\r
+ else\r
+ m_dwHoverStartTicks = 0;\r
+ }\r
+ else\r
+ {\r
+ TreeView_SelectDropTarget(m_hTargetWnd, NULL);\r
+ *pdwEffect = DROPEFFECT_NONE;\r
+ m_dwHoverStartTicks = 0;\r
+ }\r
+ CRect rect;\r
+ m_pRepoBrowser->m_RepoTree.GetWindowRect(&rect);\r
+ if (rect.PtInRect((POINT&)pt))\r
+ {\r
+ if (pt.y > (rect.bottom-20))\r
+ {\r
+ m_pRepoBrowser->m_RepoTree.SendMessage(WM_VSCROLL, MAKEWPARAM (SB_LINEDOWN, 0), NULL);\r
+ m_dwHoverStartTicks = 0;\r
+ }\r
+ if (pt.y < (rect.top+20))\r
+ {\r
+ m_pRepoBrowser->m_RepoTree.SendMessage(WM_VSCROLL, MAKEWPARAM (SB_LINEUP, 0), NULL);\r
+ m_dwHoverStartTicks = 0;\r
+ }\r
+ }\r
+\r
+ return CIDropTarget::DragOver(grfKeyState, pt, pdwEffect);\r
+}\r
+\r
+HRESULT CTreeDropTarget::DragLeave(void)\r
+{\r
+ TreeView_SelectDropTarget(m_hTargetWnd, NULL);\r
+ m_dwHoverStartTicks = 0;\r
+ return CIDropTarget::DragLeave();\r
+}\r
+\r
+CListDropTarget::CListDropTarget(CRepositoryBrowser * pRepoBrowser):CIDropTarget(pRepoBrowser->m_RepoList.GetSafeHwnd())\r
+ , m_pRepoBrowser(pRepoBrowser)\r
+ , m_bFiles(false)\r
+{\r
+} \r
+\r
+bool CListDropTarget::OnDrop(FORMATETC* pFmtEtc, STGMEDIUM& medium, DWORD *pdwEffect, POINTL pt)\r
+{\r
+ // find the target url\r
+ CString targetUrl;\r
+ int targetIndex = m_pRepoBrowser->m_RepoList.GetNextItem(-1, LVNI_DROPHILITED);\r
+ if (targetIndex >= 0)\r
+ {\r
+ targetUrl = ((CItem*)m_pRepoBrowser->m_RepoList.GetItemData(targetIndex))->absolutepath;\r
+ }\r
+ else\r
+ {\r
+ HTREEITEM hDropTarget = m_pRepoBrowser->m_RepoTree.GetSelectedItem();\r
+ if (hDropTarget)\r
+ {\r
+ targetUrl = ((CTreeItem*)m_pRepoBrowser->m_RepoTree.GetItemData(hDropTarget))->url;\r
+ }\r
+ }\r
+ if(pFmtEtc->cfFormat == CF_UNICODETEXT && medium.tymed == TYMED_HGLOBAL)\r
+ {\r
+ TCHAR* pStr = (TCHAR*)GlobalLock(medium.hGlobal);\r
+ CString urls;\r
+ if(pStr != NULL)\r
+ {\r
+ urls = pStr;\r
+ }\r
+ GlobalUnlock(medium.hGlobal);\r
+ urls.Replace(_T("\r\n"), _T("*"));\r
+ CTSVNPathList urlList;\r
+ urlList.LoadFromAsteriskSeparatedString(urls);\r
+ m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, m_pRepoBrowser->GetRevision(), *pdwEffect, pt);\r
+ }\r
+ if(pFmtEtc->cfFormat == CF_SVNURL && medium.tymed == TYMED_HGLOBAL)\r
+ {\r
+ TCHAR* pStr = (TCHAR*)GlobalLock(medium.hGlobal);\r
+ CString urls;\r
+ if(pStr != NULL)\r
+ {\r
+ urls = pStr;\r
+ }\r
+ GlobalUnlock(medium.hGlobal);\r
+ urls.Replace(_T("\r\n"), _T("*"));\r
+ CTSVNPathList urlListRevs;\r
+ urlListRevs.LoadFromAsteriskSeparatedString(urls);\r
+ CTSVNPathList urlList;\r
+ SVNRev srcRev;\r
+ for (int i=0; i<urlListRevs.GetCount(); ++i)\r
+ {\r
+ int pos = urlListRevs[i].GetSVNPathString().Find('?');\r
+ if (pos > 0)\r
+ {\r
+ if (!srcRev.IsValid())\r
+ srcRev = SVNRev(urlListRevs[i].GetSVNPathString().Mid(pos+1));\r
+ urlList.AddPath(CTSVNPath(urlListRevs[i].GetSVNPathString().Left(pos)));\r
+ }\r
+ else\r
+ urlList.AddPath(urlListRevs[i]);\r
+ }\r
+\r
+ m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, srcRev, *pdwEffect, pt);\r
+ }\r
+\r
+ if(pFmtEtc->cfFormat == CF_HDROP && medium.tymed == TYMED_HGLOBAL)\r
+ {\r
+ HDROP hDrop = (HDROP)GlobalLock(medium.hGlobal);\r
+ if(hDrop != NULL)\r
+ {\r
+ CTSVNPathList urlList;\r
+ TCHAR szFileName[MAX_PATH];\r
+\r
+ UINT cFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); \r
+ for(UINT i = 0; i < cFiles; ++i)\r
+ {\r
+ DragQueryFile(hDrop, i, szFileName, sizeof(szFileName));\r
+ urlList.AddPath(CTSVNPath(szFileName));\r
+ }\r
+ m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, m_pRepoBrowser->GetRevision(), *pdwEffect, pt);\r
+ }\r
+ GlobalUnlock(medium.hGlobal);\r
+ }\r
+ ListView_SetItemState(m_hTargetWnd, -1, 0, LVIS_DROPHILITED);\r
+ return true; //let base free the medium\r
+}\r
+\r
+HRESULT CListDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)\r
+{\r
+ FORMATETC ftetc={0}; \r
+ ftetc.dwAspect = DVASPECT_CONTENT; \r
+ ftetc.lindex = -1; \r
+ ftetc.tymed = TYMED_HGLOBAL; \r
+ ftetc.cfFormat=CF_HDROP; \r
+ if (pDataObj->QueryGetData(&ftetc) == S_OK)\r
+ {\r
+ m_bFiles = true;\r
+ }\r
+ else\r
+ {\r
+ m_bFiles = false;\r
+ }\r
+ return CIDropTarget::DragEnter(pDataObj, grfKeyState, pt, pdwEffect);\r
+}\r
+\r
+\r
+HRESULT CListDropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)\r
+{\r
+ LVHITTESTINFO hit;\r
+ hit.pt = (POINT&)pt;\r
+ ScreenToClient(m_hTargetWnd,&hit.pt);\r
+ hit.flags = LVHT_ONITEM;\r
+ int iItem = ListView_HitTest(m_hTargetWnd,&hit);\r
+\r
+ *pdwEffect = DROPEFFECT_MOVE;\r
+ if (grfKeyState & MK_CONTROL)\r
+ *pdwEffect = DROPEFFECT_COPY;\r
+\r
+ if (iItem >= 0)\r
+ {\r
+ CItem * pItem = (CItem*)m_pRepoBrowser->m_RepoList.GetItemData(iItem);\r
+ if (pItem)\r
+ {\r
+ if (pItem->kind != svn_node_dir)\r
+ {\r
+ *pdwEffect = DROPEFFECT_NONE;\r
+ ListView_SetItemState(m_hTargetWnd, -1, 0, LVIS_DROPHILITED);\r
+ }\r
+ else\r
+ {\r
+ if (m_bFiles)\r
+ *pdwEffect = DROPEFFECT_COPY;\r
+ ListView_SetItemState(m_hTargetWnd, -1, 0, LVIS_DROPHILITED);\r
+ ListView_SetItemState(m_hTargetWnd, iItem, LVIS_DROPHILITED, LVIS_DROPHILITED);\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ ListView_SetItemState(m_hTargetWnd, -1, 0, LVIS_DROPHILITED);\r
+ }\r
+\r
+ CRect rect;\r
+ m_pRepoBrowser->m_RepoList.GetWindowRect(&rect);\r
+ if (rect.PtInRect((POINT&)pt))\r
+ {\r
+ if (pt.y > (rect.bottom-20))\r
+ {\r
+ m_pRepoBrowser->m_RepoList.SendMessage(WM_VSCROLL, MAKEWPARAM (SB_LINEDOWN, 0), NULL);\r
+ }\r
+ if (pt.y < (rect.top+20))\r
+ {\r
+ m_pRepoBrowser->m_RepoList.SendMessage(WM_VSCROLL, MAKEWPARAM (SB_LINEUP, 0), NULL);\r
+ }\r
+ }\r
+\r
+ return CIDropTarget::DragOver(grfKeyState, pt, pdwEffect);\r
+}\r
+\r
+HRESULT CListDropTarget::DragLeave(void)\r
+{\r
+ ListView_SetItemState(m_hTargetWnd, -1, 0, LVIS_DROPHILITED);\r
+ return CIDropTarget::DragLeave();\r
+}\r