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