Merge branch 'restructure-tree'
[TortoiseGit.git] / src / TortoiseProc / RepoDrags.cpp
blob37acf61b88ecd8291239d06d97ed5d60f967e453
1 // TortoiseSVN - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2008 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include "StdAfx.h"
20 #include "RepoDrags.h"
21 #include "RepositoryBrowser.h"
22 #include "SVNDataObject.h"
24 CTreeDropTarget::CTreeDropTarget(CRepositoryBrowser * pRepoBrowser) : CIDropTarget(pRepoBrowser->m_RepoTree.GetSafeHwnd())
25 , m_pRepoBrowser(pRepoBrowser)
26 , m_bFiles(false)
30 bool CTreeDropTarget::OnDrop(FORMATETC* pFmtEtc, STGMEDIUM& medium, DWORD *pdwEffect, POINTL pt)
32 // find the target
33 CString targetUrl;
34 HTREEITEM hDropTarget = m_pRepoBrowser->m_RepoTree.GetNextItem(TVI_ROOT, TVGN_DROPHILITE);
35 if (hDropTarget)
37 CTreeItem * pItem = (CTreeItem*)m_pRepoBrowser->m_RepoTree.GetItemData(hDropTarget);
38 if (pItem == NULL)
39 return false;
40 targetUrl = pItem->url;
42 if (pFmtEtc->cfFormat == CF_UNICODETEXT && medium.tymed == TYMED_HGLOBAL)
44 TCHAR* pStr = (TCHAR*)GlobalLock(medium.hGlobal);
45 CString urls;
46 if(pStr != NULL)
48 urls = pStr;
50 GlobalUnlock(medium.hGlobal);
51 urls.Replace(_T("\r\n"), _T("*"));
52 CTSVNPathList urlList;
53 urlList.LoadFromAsteriskSeparatedString(urls);
55 m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, m_pRepoBrowser->GetRevision(), *pdwEffect, pt);
58 if (pFmtEtc->cfFormat == CF_SVNURL && medium.tymed == TYMED_HGLOBAL)
60 TCHAR* pStr = (TCHAR*)GlobalLock(medium.hGlobal);
61 CString urls;
62 if(pStr != NULL)
64 urls = pStr;
66 GlobalUnlock(medium.hGlobal);
67 urls.Replace(_T("\r\n"), _T("*"));
68 CTSVNPathList urlListRevs;
69 urlListRevs.LoadFromAsteriskSeparatedString(urls);
70 CTSVNPathList urlList;
71 SVNRev srcRev;
72 for (int i=0; i<urlListRevs.GetCount(); ++i)
74 int pos = urlListRevs[i].GetSVNPathString().Find('?');
75 if (pos > 0)
77 if (!srcRev.IsValid())
78 srcRev = SVNRev(urlListRevs[i].GetSVNPathString().Mid(pos+1));
79 urlList.AddPath(CTSVNPath(urlListRevs[i].GetSVNPathString().Left(pos)));
81 else
82 urlList.AddPath(urlListRevs[i]);
85 m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, srcRev, *pdwEffect, pt);
88 if(pFmtEtc->cfFormat == CF_HDROP && medium.tymed == TYMED_HGLOBAL)
90 HDROP hDrop = (HDROP)GlobalLock(medium.hGlobal);
91 if(hDrop != NULL)
93 CTSVNPathList urlList;
94 TCHAR szFileName[MAX_PATH];
96 UINT cFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
97 for(UINT i = 0; i < cFiles; ++i)
99 DragQueryFile(hDrop, i, szFileName, sizeof(szFileName));
100 urlList.AddPath(CTSVNPath(szFileName));
102 m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, m_pRepoBrowser->GetRevision(), *pdwEffect, pt);
104 GlobalUnlock(medium.hGlobal);
106 TreeView_SelectDropTarget(m_hTargetWnd, NULL);
107 return true;
110 HRESULT CTreeDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)
112 FORMATETC ftetc={0};
113 ftetc.dwAspect = DVASPECT_CONTENT;
114 ftetc.lindex = -1;
115 ftetc.tymed = TYMED_HGLOBAL;
116 ftetc.cfFormat=CF_HDROP;
117 if (pDataObj->QueryGetData(&ftetc) == S_OK)
118 m_bFiles = true;
119 else
120 m_bFiles = false;
121 m_dwHoverStartTicks = 0;
122 hLastItem = NULL;
123 return CIDropTarget::DragEnter(pDataObj, grfKeyState, pt, pdwEffect);
126 HRESULT CTreeDropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)
128 TVHITTESTINFO hit;
129 hit.pt = (POINT&)pt;
130 ScreenToClient(m_hTargetWnd,&hit.pt);
131 hit.flags = TVHT_ONITEM;
132 HTREEITEM hItem = TreeView_HitTest(m_hTargetWnd,&hit);
133 if (hItem != hLastItem)
134 m_dwHoverStartTicks = 0;
135 hLastItem = hItem;
137 *pdwEffect = DROPEFFECT_MOVE;
138 if (grfKeyState & MK_CONTROL)
139 *pdwEffect = DROPEFFECT_COPY;
141 if (hItem != NULL)
143 if (m_bFiles)
144 *pdwEffect = DROPEFFECT_COPY;
145 TreeView_SelectDropTarget(m_hTargetWnd, hItem);
146 if ((m_pRepoBrowser->m_RepoTree.GetItemState(hItem, TVIS_EXPANDED)&TVIS_EXPANDED) != TVIS_EXPANDED)
148 if (m_dwHoverStartTicks == 0)
149 m_dwHoverStartTicks = GetTickCount();
150 UINT timeout = 0;
151 //SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &timeout, 0);
152 timeout = 2000;
153 if ((GetTickCount() - m_dwHoverStartTicks) > timeout)
155 // expand the item
156 m_pRepoBrowser->m_RepoTree.Expand(hItem, TVE_EXPAND);
157 m_dwHoverStartTicks = 0;
160 else
161 m_dwHoverStartTicks = 0;
163 else
165 TreeView_SelectDropTarget(m_hTargetWnd, NULL);
166 *pdwEffect = DROPEFFECT_NONE;
167 m_dwHoverStartTicks = 0;
169 CRect rect;
170 m_pRepoBrowser->m_RepoTree.GetWindowRect(&rect);
171 if (rect.PtInRect((POINT&)pt))
173 if (pt.y > (rect.bottom-20))
175 m_pRepoBrowser->m_RepoTree.SendMessage(WM_VSCROLL, MAKEWPARAM (SB_LINEDOWN, 0), NULL);
176 m_dwHoverStartTicks = 0;
178 if (pt.y < (rect.top+20))
180 m_pRepoBrowser->m_RepoTree.SendMessage(WM_VSCROLL, MAKEWPARAM (SB_LINEUP, 0), NULL);
181 m_dwHoverStartTicks = 0;
185 return CIDropTarget::DragOver(grfKeyState, pt, pdwEffect);
188 HRESULT CTreeDropTarget::DragLeave(void)
190 TreeView_SelectDropTarget(m_hTargetWnd, NULL);
191 m_dwHoverStartTicks = 0;
192 return CIDropTarget::DragLeave();
195 CListDropTarget::CListDropTarget(CRepositoryBrowser * pRepoBrowser):CIDropTarget(pRepoBrowser->m_RepoList.GetSafeHwnd())
196 , m_pRepoBrowser(pRepoBrowser)
197 , m_bFiles(false)
201 bool CListDropTarget::OnDrop(FORMATETC* pFmtEtc, STGMEDIUM& medium, DWORD *pdwEffect, POINTL pt)
203 // find the target url
204 CString targetUrl;
205 int targetIndex = m_pRepoBrowser->m_RepoList.GetNextItem(-1, LVNI_DROPHILITED);
206 if (targetIndex >= 0)
208 targetUrl = ((CItem*)m_pRepoBrowser->m_RepoList.GetItemData(targetIndex))->absolutepath;
210 else
212 HTREEITEM hDropTarget = m_pRepoBrowser->m_RepoTree.GetSelectedItem();
213 if (hDropTarget)
215 targetUrl = ((CTreeItem*)m_pRepoBrowser->m_RepoTree.GetItemData(hDropTarget))->url;
218 if(pFmtEtc->cfFormat == CF_UNICODETEXT && medium.tymed == TYMED_HGLOBAL)
220 TCHAR* pStr = (TCHAR*)GlobalLock(medium.hGlobal);
221 CString urls;
222 if(pStr != NULL)
224 urls = pStr;
226 GlobalUnlock(medium.hGlobal);
227 urls.Replace(_T("\r\n"), _T("*"));
228 CTSVNPathList urlList;
229 urlList.LoadFromAsteriskSeparatedString(urls);
230 m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, m_pRepoBrowser->GetRevision(), *pdwEffect, pt);
232 if(pFmtEtc->cfFormat == CF_SVNURL && medium.tymed == TYMED_HGLOBAL)
234 TCHAR* pStr = (TCHAR*)GlobalLock(medium.hGlobal);
235 CString urls;
236 if(pStr != NULL)
238 urls = pStr;
240 GlobalUnlock(medium.hGlobal);
241 urls.Replace(_T("\r\n"), _T("*"));
242 CTSVNPathList urlListRevs;
243 urlListRevs.LoadFromAsteriskSeparatedString(urls);
244 CTSVNPathList urlList;
245 SVNRev srcRev;
246 for (int i=0; i<urlListRevs.GetCount(); ++i)
248 int pos = urlListRevs[i].GetSVNPathString().Find('?');
249 if (pos > 0)
251 if (!srcRev.IsValid())
252 srcRev = SVNRev(urlListRevs[i].GetSVNPathString().Mid(pos+1));
253 urlList.AddPath(CTSVNPath(urlListRevs[i].GetSVNPathString().Left(pos)));
255 else
256 urlList.AddPath(urlListRevs[i]);
259 m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, srcRev, *pdwEffect, pt);
262 if(pFmtEtc->cfFormat == CF_HDROP && medium.tymed == TYMED_HGLOBAL)
264 HDROP hDrop = (HDROP)GlobalLock(medium.hGlobal);
265 if(hDrop != NULL)
267 CTSVNPathList urlList;
268 TCHAR szFileName[MAX_PATH];
270 UINT cFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
271 for(UINT i = 0; i < cFiles; ++i)
273 DragQueryFile(hDrop, i, szFileName, sizeof(szFileName));
274 urlList.AddPath(CTSVNPath(szFileName));
276 m_pRepoBrowser->OnDrop(CTSVNPath(targetUrl), urlList, m_pRepoBrowser->GetRevision(), *pdwEffect, pt);
278 GlobalUnlock(medium.hGlobal);
280 ListView_SetItemState(m_hTargetWnd, -1, 0, LVIS_DROPHILITED);
281 return true; //let base free the medium
284 HRESULT CListDropTarget::DragEnter(IDataObject __RPC_FAR *pDataObj, DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)
286 FORMATETC ftetc={0};
287 ftetc.dwAspect = DVASPECT_CONTENT;
288 ftetc.lindex = -1;
289 ftetc.tymed = TYMED_HGLOBAL;
290 ftetc.cfFormat=CF_HDROP;
291 if (pDataObj->QueryGetData(&ftetc) == S_OK)
293 m_bFiles = true;
295 else
297 m_bFiles = false;
299 return CIDropTarget::DragEnter(pDataObj, grfKeyState, pt, pdwEffect);
303 HRESULT CListDropTarget::DragOver(DWORD grfKeyState, POINTL pt, DWORD __RPC_FAR *pdwEffect)
305 LVHITTESTINFO hit;
306 hit.pt = (POINT&)pt;
307 ScreenToClient(m_hTargetWnd,&hit.pt);
308 hit.flags = LVHT_ONITEM;
309 int iItem = ListView_HitTest(m_hTargetWnd,&hit);
311 *pdwEffect = DROPEFFECT_MOVE;
312 if (grfKeyState & MK_CONTROL)
313 *pdwEffect = DROPEFFECT_COPY;
315 if (iItem >= 0)
317 CItem * pItem = (CItem*)m_pRepoBrowser->m_RepoList.GetItemData(iItem);
318 if (pItem)
320 if (pItem->kind != svn_node_dir)
322 *pdwEffect = DROPEFFECT_NONE;
323 ListView_SetItemState(m_hTargetWnd, -1, 0, LVIS_DROPHILITED);
325 else
327 if (m_bFiles)
328 *pdwEffect = DROPEFFECT_COPY;
329 ListView_SetItemState(m_hTargetWnd, -1, 0, LVIS_DROPHILITED);
330 ListView_SetItemState(m_hTargetWnd, iItem, LVIS_DROPHILITED, LVIS_DROPHILITED);
334 else
336 ListView_SetItemState(m_hTargetWnd, -1, 0, LVIS_DROPHILITED);
339 CRect rect;
340 m_pRepoBrowser->m_RepoList.GetWindowRect(&rect);
341 if (rect.PtInRect((POINT&)pt))
343 if (pt.y > (rect.bottom-20))
345 m_pRepoBrowser->m_RepoList.SendMessage(WM_VSCROLL, MAKEWPARAM (SB_LINEDOWN, 0), NULL);
347 if (pt.y < (rect.top+20))
349 m_pRepoBrowser->m_RepoList.SendMessage(WM_VSCROLL, MAKEWPARAM (SB_LINEUP, 0), NULL);
353 return CIDropTarget::DragOver(grfKeyState, pt, pdwEffect);
356 HRESULT CListDropTarget::DragLeave(void)
358 ListView_SetItemState(m_hTargetWnd, -1, 0, LVIS_DROPHILITED);
359 return CIDropTarget::DragLeave();