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.
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
)
30 bool CTreeDropTarget::OnDrop(FORMATETC
* pFmtEtc
, STGMEDIUM
& medium
, DWORD
*pdwEffect
, POINTL pt
)
34 HTREEITEM hDropTarget
= m_pRepoBrowser
->m_RepoTree
.GetNextItem(TVI_ROOT
, TVGN_DROPHILITE
);
37 CTreeItem
* pItem
= (CTreeItem
*)m_pRepoBrowser
->m_RepoTree
.GetItemData(hDropTarget
);
40 targetUrl
= pItem
->url
;
42 if (pFmtEtc
->cfFormat
== CF_UNICODETEXT
&& medium
.tymed
== TYMED_HGLOBAL
)
44 TCHAR
* pStr
= (TCHAR
*)GlobalLock(medium
.hGlobal
);
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
);
66 GlobalUnlock(medium
.hGlobal
);
67 urls
.Replace(_T("\r\n"), _T("*"));
68 CTSVNPathList urlListRevs
;
69 urlListRevs
.LoadFromAsteriskSeparatedString(urls
);
70 CTSVNPathList urlList
;
72 for (int i
=0; i
<urlListRevs
.GetCount(); ++i
)
74 int pos
= urlListRevs
[i
].GetSVNPathString().Find('?');
77 if (!srcRev
.IsValid())
78 srcRev
= SVNRev(urlListRevs
[i
].GetSVNPathString().Mid(pos
+1));
79 urlList
.AddPath(CTSVNPath(urlListRevs
[i
].GetSVNPathString().Left(pos
)));
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
);
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
);
110 HRESULT
CTreeDropTarget::DragEnter(IDataObject __RPC_FAR
*pDataObj
, DWORD grfKeyState
, POINTL pt
, DWORD __RPC_FAR
*pdwEffect
)
113 ftetc
.dwAspect
= DVASPECT_CONTENT
;
115 ftetc
.tymed
= TYMED_HGLOBAL
;
116 ftetc
.cfFormat
=CF_HDROP
;
117 if (pDataObj
->QueryGetData(&ftetc
) == S_OK
)
121 m_dwHoverStartTicks
= 0;
123 return CIDropTarget::DragEnter(pDataObj
, grfKeyState
, pt
, pdwEffect
);
126 HRESULT
CTreeDropTarget::DragOver(DWORD grfKeyState
, POINTL pt
, DWORD __RPC_FAR
*pdwEffect
)
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;
137 *pdwEffect
= DROPEFFECT_MOVE
;
138 if (grfKeyState
& MK_CONTROL
)
139 *pdwEffect
= DROPEFFECT_COPY
;
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();
151 //SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &timeout, 0);
153 if ((GetTickCount() - m_dwHoverStartTicks
) > timeout
)
156 m_pRepoBrowser
->m_RepoTree
.Expand(hItem
, TVE_EXPAND
);
157 m_dwHoverStartTicks
= 0;
161 m_dwHoverStartTicks
= 0;
165 TreeView_SelectDropTarget(m_hTargetWnd
, NULL
);
166 *pdwEffect
= DROPEFFECT_NONE
;
167 m_dwHoverStartTicks
= 0;
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
)
201 bool CListDropTarget::OnDrop(FORMATETC
* pFmtEtc
, STGMEDIUM
& medium
, DWORD
*pdwEffect
, POINTL pt
)
203 // find the target url
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
;
212 HTREEITEM hDropTarget
= m_pRepoBrowser
->m_RepoTree
.GetSelectedItem();
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
);
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
);
240 GlobalUnlock(medium
.hGlobal
);
241 urls
.Replace(_T("\r\n"), _T("*"));
242 CTSVNPathList urlListRevs
;
243 urlListRevs
.LoadFromAsteriskSeparatedString(urls
);
244 CTSVNPathList urlList
;
246 for (int i
=0; i
<urlListRevs
.GetCount(); ++i
)
248 int pos
= urlListRevs
[i
].GetSVNPathString().Find('?');
251 if (!srcRev
.IsValid())
252 srcRev
= SVNRev(urlListRevs
[i
].GetSVNPathString().Mid(pos
+1));
253 urlList
.AddPath(CTSVNPath(urlListRevs
[i
].GetSVNPathString().Left(pos
)));
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
);
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
)
287 ftetc
.dwAspect
= DVASPECT_CONTENT
;
289 ftetc
.tymed
= TYMED_HGLOBAL
;
290 ftetc
.cfFormat
=CF_HDROP
;
291 if (pDataObj
->QueryGetData(&ftetc
) == S_OK
)
299 return CIDropTarget::DragEnter(pDataObj
, grfKeyState
, pt
, pdwEffect
);
303 HRESULT
CListDropTarget::DragOver(DWORD grfKeyState
, POINTL pt
, DWORD __RPC_FAR
*pdwEffect
)
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
;
317 CItem
* pItem
= (CItem
*)m_pRepoBrowser
->m_RepoList
.GetItemData(iItem
);
320 if (pItem
->kind
!= svn_node_dir
)
322 *pdwEffect
= DROPEFFECT_NONE
;
323 ListView_SetItemState(m_hTargetWnd
, -1, 0, LVIS_DROPHILITED
);
328 *pdwEffect
= DROPEFFECT_COPY
;
329 ListView_SetItemState(m_hTargetWnd
, -1, 0, LVIS_DROPHILITED
);
330 ListView_SetItemState(m_hTargetWnd
, iItem
, LVIS_DROPHILITED
, LVIS_DROPHILITED
);
336 ListView_SetItemState(m_hTargetWnd
, -1, 0, LVIS_DROPHILITED
);
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();