1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2008-2011, 2013-2014, 2016 - TortoiseGit
4 // Copyright (C) 2003-2008, 2014 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "TortoiseProc.h"
22 #include "DirFileEnum.h"
23 #include "SetOverlayIcons.h"
24 #include "StringUtils.h"
25 #include "PathUtils.h"
26 #include "LoadIconEx.h"
28 IMPLEMENT_DYNAMIC(CSetOverlayIcons
, ISettingsPropPage
)
29 CSetOverlayIcons::CSetOverlayIcons()
30 : ISettingsPropPage(CSetOverlayIcons::IDD
)
32 m_regNormal
= CRegString(L
"Software\\TortoiseOverlays\\NormalIcon");
33 m_regModified
= CRegString(L
"Software\\TortoiseOverlays\\ModifiedIcon");
34 m_regConflicted
= CRegString(L
"Software\\TortoiseOverlays\\ConflictIcon");
35 m_regReadOnly
= CRegString(L
"Software\\TortoiseOverlays\\ReadOnlyIcon");
36 m_regDeleted
= CRegString(L
"Software\\TortoiseOverlays\\DeletedIcon");
37 m_regLocked
= CRegString(L
"Software\\TortoiseOverlays\\LockedIcon");
38 m_regAdded
= CRegString(L
"Software\\TortoiseOverlays\\AddedIcon");
39 m_regIgnored
= CRegString(L
"Software\\TortoiseOverlays\\IgnoredIcon");
40 m_regUnversioned
= CRegString(L
"Software\\TortoiseOverlays\\UnversionedIcon");
44 CSetOverlayIcons::~CSetOverlayIcons()
48 void CSetOverlayIcons::DoDataExchange(CDataExchange
* pDX
)
50 ISettingsPropPage::DoDataExchange(pDX
);
51 DDX_Control(pDX
, IDC_ICONSETCOMBO
, m_cIconSet
);
52 DDX_Control(pDX
, IDC_ICONLIST
, m_cIconList
);
56 BEGIN_MESSAGE_MAP(CSetOverlayIcons
, ISettingsPropPage
)
57 ON_BN_CLICKED(IDC_LISTRADIO
, OnBnClickedListradio
)
58 ON_BN_CLICKED(IDC_SYMBOLRADIO
, OnBnClickedSymbolradio
)
59 ON_CBN_SELCHANGE(IDC_ICONSETCOMBO
, OnCbnSelchangeIconsetcombo
)
62 BOOL
CSetOverlayIcons::OnInitDialog()
64 ISettingsPropPage::OnInitDialog();
66 AdjustControlSize(IDC_LISTRADIO
);
67 AdjustControlSize(IDC_SYMBOLRADIO
);
69 m_cIconList
.SetExtendedStyle(LVS_EX_DOUBLEBUFFER
| LVS_EX_INFOTIP
| LVS_EX_SUBITEMIMAGES
);
70 // get the path to our icon sets
71 TCHAR buf
[MAX_PATH
] = {0};
72 SHGetSpecialFolderPath(m_hWnd
, buf
, CSIDL_PROGRAM_FILES_COMMON
, true);
74 m_sIconPath
+= L
"\\TortoiseOverlays\\Icons";
75 // list all the icon sets
76 CDirFileEnum
filefinder(m_sIconPath
);
79 while (filefinder
.NextFile(item
, &isDir
))
83 m_cIconSet
.AddString(CPathUtils::GetFileNameFromPath(item
));
85 CheckRadioButton(IDC_LISTRADIO
, IDC_SYMBOLRADIO
, IDC_LISTRADIO
);
86 CString sModifiedIcon
= m_regModified
;
87 if (sModifiedIcon
.IsEmpty())
89 // no custom icon set, use the default
90 sModifiedIcon
= m_sIconPath
+ L
"\\XPStyle\\ModifiedIcon.ico";
92 if (!CStringUtils::StartsWithI(sModifiedIcon
, m_sIconPath
))
94 // an icon set outside our own installation? We don't support that,
95 // so fall back to the default!
96 sModifiedIcon
= m_sIconPath
+ L
"\\XPStyle\\ModifiedIcon.ico";
98 // the name of the icon set is the folder of the icon location
99 m_sOriginalIconSet
= sModifiedIcon
.Mid(m_sIconPath
.GetLength()+1);
100 m_sOriginalIconSet
= m_sOriginalIconSet
.Left(m_sOriginalIconSet
.ReverseFind('\\'));
101 // now we have the name of the icon set. Set the combobox to show
104 for (int i
=0; i
<m_cIconSet
.GetCount(); ++i
)
106 m_cIconSet
.GetLBText(i
, ComboItem
);
107 if (ComboItem
.CompareNoCase(m_sOriginalIconSet
)==0)
108 m_cIconSet
.SetCurSel(i
);
111 m_sNormal
.LoadString(IDS_STATUSNORMAL
);
112 m_sModified
.LoadString(IDS_STATUSMODIFIED
);
113 m_sConflicted
.LoadString(IDS_STATUSCONFLICTED
);
114 m_sDeleted
.LoadString(IDS_STATUSDELETED
);
115 m_sAdded
.LoadString(IDS_STATUSADDED
);
116 m_sIgnored
.LoadString(IDS_STATUSIGNORED
);
117 m_sUnversioned
.LoadString(IDS_STATUSUNVERSIONED
);
119 m_sReadOnly
.LoadString(IDS_SETTINGS_READONLYNAME
);
120 m_sLocked
.LoadString(IDS_SETTINGS_LOCKEDNAME
);
122 SetWindowTheme(m_hWnd
, L
"Explorer", nullptr);
129 void CSetOverlayIcons::ShowIconSet(bool bSmallIcons
)
131 m_cIconList
.SetRedraw(FALSE
);
132 m_cIconList
.DeleteAllItems();
133 m_ImageList
.DeleteImageList();
134 m_ImageListBig
.DeleteImageList();
135 int smallIconWidth
= GetSystemMetrics(SM_CXSMICON
);
136 int smallIconHeight
= GetSystemMetrics(SM_CYSMICON
);
137 int normalIconWidth
= GetSystemMetrics(SM_CXICON
);
138 int normalIconHeight
= GetSystemMetrics(SM_CYICON
);
139 m_ImageList
.Create(smallIconWidth
, smallIconHeight
, ILC_COLOR32
| ILC_MASK
, 20, 10);
140 m_ImageListBig
.Create(normalIconWidth
, normalIconHeight
, ILC_COLOR32
| ILC_MASK
, 20, 10);
141 m_cIconList
.SetImageList(&m_ImageList
, LVSIL_SMALL
);
142 m_cIconList
.SetImageList(&m_ImageListBig
, LVSIL_NORMAL
);
144 // find all the icons of the selected icon set
146 int index
= m_cIconSet
.GetCurSel();
149 // nothing selected. Shouldn't happen!
152 m_cIconSet
.GetLBText(index
, sIconSet
);
153 CString sIconSetPath
= m_sIconPath
+ L
'\\' + sIconSet
;
155 CImageList
* pImageList
= bSmallIcons
? &m_ImageList
: &m_ImageListBig
;
156 int iconWidth
= (bSmallIcons
? smallIconWidth
: normalIconWidth
);
157 int iconHeight
= (bSmallIcons
? smallIconHeight
: normalIconHeight
);
158 auto hNormalOverlay
= LoadIconEx(nullptr, sIconSetPath
+ L
"\\NormalIcon.ico", iconWidth
, iconHeight
);
159 index
= pImageList
->Add(hNormalOverlay
);
160 VERIFY(pImageList
->SetOverlayImage(index
, 1));
161 auto hModifiedOverlay
= LoadIconEx(nullptr, sIconSetPath
+ L
"\\ModifiedIcon.ico", iconWidth
, iconHeight
);
162 index
= pImageList
->Add(hModifiedOverlay
);
163 VERIFY(pImageList
->SetOverlayImage(index
, 2));
164 auto hConflictedOverlay
= LoadIconEx(nullptr, sIconSetPath
+ L
"\\ConflictIcon.ico", iconWidth
, iconHeight
);
165 index
= pImageList
->Add(hConflictedOverlay
);
166 VERIFY(pImageList
->SetOverlayImage(index
, 3));
167 auto hReadOnlyOverlay
= LoadIconEx(nullptr, sIconSetPath
+ L
"\\ReadOnlyIcon.ico", iconWidth
, iconHeight
);
168 index
= pImageList
->Add(hReadOnlyOverlay
);
169 VERIFY(pImageList
->SetOverlayImage(index
, 4));
170 auto hDeletedOverlay
= LoadIconEx(nullptr, sIconSetPath
+ L
"\\DeletedIcon.ico", iconWidth
, iconHeight
);
171 index
= pImageList
->Add(hDeletedOverlay
);
172 VERIFY(pImageList
->SetOverlayImage(index
, 5));
173 auto hLockedOverlay
= LoadIconEx(nullptr, sIconSetPath
+ L
"\\LockedIcon.ico", iconWidth
, iconHeight
);
174 index
= pImageList
->Add(hLockedOverlay
);
175 VERIFY(pImageList
->SetOverlayImage(index
, 6));
176 auto hAddedOverlay
= LoadIconEx(nullptr, sIconSetPath
+ L
"\\AddedIcon.ico", iconWidth
, iconHeight
);
177 index
= pImageList
->Add(hAddedOverlay
);
178 VERIFY(pImageList
->SetOverlayImage(index
, 7));
179 auto hIgnoredOverlay
= LoadIconEx(nullptr, sIconSetPath
+ L
"\\IgnoredIcon.ico", iconWidth
, iconHeight
);
180 index
= pImageList
->Add(hIgnoredOverlay
);
181 VERIFY(pImageList
->SetOverlayImage(index
, 8));
182 auto hUnversionedOverlay
= LoadIconEx(nullptr, sIconSetPath
+ L
"\\UnversionedIcon.ico", iconWidth
, iconHeight
);
183 index
= pImageList
->Add(hUnversionedOverlay
);
184 VERIFY(pImageList
->SetOverlayImage(index
, 9));
186 DestroyIcon(hNormalOverlay
);
187 DestroyIcon(hModifiedOverlay
);
188 DestroyIcon(hConflictedOverlay
);
189 DestroyIcon(hReadOnlyOverlay
);
190 DestroyIcon(hDeletedOverlay
);
191 DestroyIcon(hLockedOverlay
);
192 DestroyIcon(hAddedOverlay
);
193 DestroyIcon(hIgnoredOverlay
);
194 DestroyIcon(hUnversionedOverlay
);
196 // create an image list with different file icons
197 SHFILEINFO sfi
= { 0 };
199 UINT flags
= SHGFI_ICON
| SHGFI_USEFILEATTRIBUTES
;
201 flags
|= SHGFI_SMALLICON
;
203 flags
|= SHGFI_LARGEICON
;
206 FILE_ATTRIBUTE_DIRECTORY
,
210 int folderindex
= pImageList
->Add(sfi
.hIcon
); //folder
211 DestroyIcon(sfi
.hIcon
);
213 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sNormal
, folderindex
);
214 VERIFY(m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(1), TVIS_OVERLAYMASK
));
215 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sModified
, folderindex
);
216 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(2), TVIS_OVERLAYMASK
);
217 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sConflicted
, folderindex
);
218 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(3), TVIS_OVERLAYMASK
);
219 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sReadOnly
, folderindex
);
220 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(4), TVIS_OVERLAYMASK
);
221 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sDeleted
, folderindex
);
222 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(5), TVIS_OVERLAYMASK
);
223 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sLocked
, folderindex
);
224 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(6), TVIS_OVERLAYMASK
);
225 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sAdded
, folderindex
);
226 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(7), TVIS_OVERLAYMASK
);
227 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sIgnored
, folderindex
);
228 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(8), TVIS_OVERLAYMASK
);
229 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sUnversioned
, folderindex
);
230 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(9), TVIS_OVERLAYMASK
);
232 AddFileTypeGroup(L
".cpp", bSmallIcons
);
233 AddFileTypeGroup(L
".h", bSmallIcons
);
234 AddFileTypeGroup(L
".txt", bSmallIcons
);
235 AddFileTypeGroup(L
".java", bSmallIcons
);
236 AddFileTypeGroup(L
".doc", bSmallIcons
);
237 AddFileTypeGroup(L
".pl", bSmallIcons
);
238 AddFileTypeGroup(L
".php", bSmallIcons
);
239 AddFileTypeGroup(L
".asp", bSmallIcons
);
240 AddFileTypeGroup(L
".cs", bSmallIcons
);
241 AddFileTypeGroup(L
".vb", bSmallIcons
);
242 AddFileTypeGroup(L
".xml", bSmallIcons
);
243 AddFileTypeGroup(L
".pas", bSmallIcons
);
244 AddFileTypeGroup(L
".dpr", bSmallIcons
);
245 AddFileTypeGroup(L
".dfm", bSmallIcons
);
246 AddFileTypeGroup(L
".res", bSmallIcons
);
247 AddFileTypeGroup(L
".asmx", bSmallIcons
);
248 AddFileTypeGroup(L
".aspx", bSmallIcons
);
249 AddFileTypeGroup(L
".resx", bSmallIcons
);
250 AddFileTypeGroup(L
".vbp", bSmallIcons
);
251 AddFileTypeGroup(L
".frm", bSmallIcons
);
252 AddFileTypeGroup(L
".frx", bSmallIcons
);
253 AddFileTypeGroup(L
".bas", bSmallIcons
);
254 AddFileTypeGroup(L
".config", bSmallIcons
);
255 AddFileTypeGroup(L
".css", bSmallIcons
);
256 AddFileTypeGroup(L
".acsx", bSmallIcons
);
257 AddFileTypeGroup(L
".jpg", bSmallIcons
);
258 AddFileTypeGroup(L
".png", bSmallIcons
);
259 m_cIconList
.SetRedraw(TRUE
);
261 void CSetOverlayIcons::AddFileTypeGroup(CString sFileType
, bool bSmallIcons
)
263 UINT flags
= SHGFI_ICON
| SHGFI_USEFILEATTRIBUTES
;
265 flags
|= SHGFI_SMALLICON
;
267 flags
|= SHGFI_LARGEICON
;
268 SHFILEINFO sfi
= { 0 };
272 FILE_ATTRIBUTE_NORMAL
,
278 imageindex
= m_ImageList
.Add(sfi
.hIcon
);
280 imageindex
= m_ImageListBig
.Add(sfi
.hIcon
);
282 DestroyIcon(sfi
.hIcon
);
284 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sNormal
+sFileType
, imageindex
);
285 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(1), TVIS_OVERLAYMASK
);
286 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sModified
+sFileType
, imageindex
);
287 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(2), TVIS_OVERLAYMASK
);
288 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sConflicted
+sFileType
, imageindex
);
289 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(3), TVIS_OVERLAYMASK
);
290 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sReadOnly
+sFileType
, imageindex
);
291 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(4), TVIS_OVERLAYMASK
);
292 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sDeleted
+sFileType
, imageindex
);
293 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(5), TVIS_OVERLAYMASK
);
294 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sLocked
+sFileType
, imageindex
);
295 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(6), TVIS_OVERLAYMASK
);
296 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sAdded
+sFileType
, imageindex
);
297 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(7), TVIS_OVERLAYMASK
);
298 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sIgnored
+sFileType
, imageindex
);
299 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(8), TVIS_OVERLAYMASK
);
300 index
= m_cIconList
.InsertItem(m_cIconList
.GetItemCount(), m_sUnversioned
+sFileType
, imageindex
);
301 m_cIconList
.SetItemState(index
, INDEXTOOVERLAYMASK(9), TVIS_OVERLAYMASK
);
304 void CSetOverlayIcons::OnBnClickedListradio()
306 m_cIconList
.ModifyStyle(LVS_TYPEMASK
, LVS_LIST
);
310 void CSetOverlayIcons::OnBnClickedSymbolradio()
312 m_cIconList
.ModifyStyle(LVS_TYPEMASK
, LVS_ICON
);
316 void CSetOverlayIcons::OnCbnSelchangeIconsetcombo()
318 bool bSmallIcons
= (GetCheckedRadioButton(IDC_LISTRADIO
, IDC_SYMBOLRADIO
) == IDC_LISTRADIO
);
319 ShowIconSet(bSmallIcons
);
320 m_selIndex
= m_cIconSet
.GetCurSel();
321 if (m_selIndex
!= CB_ERR
)
322 m_cIconSet
.GetLBText(m_selIndex
, m_sIconSet
);
323 if (m_sIconSet
.CompareNoCase(m_sOriginalIconSet
)!=0)
327 BOOL
CSetOverlayIcons::OnApply()
331 if ((!m_sIconSet
.IsEmpty())&&(m_sIconSet
.CompareNoCase(m_sOriginalIconSet
)!=0))
333 // the selected icon set has changed.
334 Store(m_sIconPath
+ L
'\\' + m_sIconSet
+ L
"\\NormalIcon.ico", m_regNormal
);
335 Store(m_sIconPath
+ L
'\\' + m_sIconSet
+ L
"\\ModifiedIcon.ico", m_regModified
);
336 Store(m_sIconPath
+ L
'\\' + m_sIconSet
+ L
"\\ConflictIcon.ico", m_regConflicted
);
337 Store(m_sIconPath
+ L
'\\' + m_sIconSet
+ L
"\\ReadOnlyIcon.ico", m_regReadOnly
);
338 Store(m_sIconPath
+ L
'\\' + m_sIconSet
+ L
"\\DeletedIcon.ico", m_regDeleted
);
339 Store(m_sIconPath
+ L
'\\' + m_sIconSet
+ L
"\\LockedIcon.ico", m_regLocked
);
340 Store(m_sIconPath
+ L
'\\' + m_sIconSet
+ L
"\\AddedIcon.ico", m_regAdded
);
341 Store(m_sIconPath
+ L
'\\' + m_sIconSet
+ L
"\\IgnoredIcon.ico", m_regIgnored
);
342 Store(m_sIconPath
+ L
'\\' + m_sIconSet
+ L
"\\UnversionedIcon.ico", m_regUnversioned
);
344 m_restart
= Restart_System
;
345 m_sOriginalIconSet
= m_sIconSet
;
348 return ISettingsPropPage::OnApply();