1 //------------------------------------------------------------------------------
2 // emFileManTheme.cpp
3 //
4 // Copyright (C) 2010-2011,2014-2016,2019 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20 
21 #include <emCore/emInstallInfo.h>
22 #include <emCore/emRes.h>
23 #include <emFileMan/emFileManTheme.h>
24 
25 
26 //==============================================================================
27 //=============================== emFileManTheme ===============================
28 //==============================================================================
29 
GetThemesDirPath()30 emString emFileManTheme::GetThemesDirPath()
31 {
32 	return emGetInstallPath(EM_IDT_RES,"emFileMan","themes");
33 }
34 
35 
36 const char * emFileManTheme::ThemeFileEnding = ".emFileManTheme";
37 
38 
Acquire(emRootContext & rootContext,const emString & name)39 emRef<emFileManTheme> emFileManTheme::Acquire(
40 	emRootContext & rootContext, const emString & name
41 )
42 {
43 	EM_IMPL_ACQUIRE_COMMON(emFileManTheme,rootContext,name)
44 }
45 
46 
ImageFileRec(emFileManTheme * parent,const char * varIdentifier,emRootContext & rootContext)47 emFileManTheme::ImageFileRec::ImageFileRec(
48 	emFileManTheme * parent, const char * varIdentifier, emRootContext & rootContext
49 )
50 	: emStringRec(parent,varIdentifier),
51 	emRecListener(this),
52 	RootContext(rootContext)
53 {
54 }
55 
56 
GetImage() const57 const emImage & emFileManTheme::ImageFileRec::GetImage() const
58 {
59 	if (Image.IsEmpty() && !Get().IsEmpty()) {
60 		((emFileManTheme::ImageFileRec*)this)->Image=emGetResImage(
61 			RootContext,
62 			emGetChildPath(
63 				emGetParentPath(
64 					((const emFileManTheme*)GetParent())->GetInstallPath()
65 				),
66 				Get()
67 			)
68 		);
69 	}
70 	return Image;
71 }
72 
73 
OnRecChanged()74 void emFileManTheme::ImageFileRec::OnRecChanged()
75 {
76 	Image.Clear();
77 }
78 
79 
GetFormatName() const80 const char * emFileManTheme::GetFormatName() const
81 {
82 	return "emFileManTheme";
83 }
84 
85 
emFileManTheme(emContext & context,const emString & name)86 emFileManTheme::emFileManTheme(emContext & context, const emString & name)
87 	: emConfigModel(context,name),
88 	emStructRec(),
89 	DisplayName(this,"DisplayName"),
90 	DisplayIcon(this,"DisplayIcon"),
91 	BackgroundColor(this,"BackgroundColor"),
92 	SourceSelectionColor(this,"SourceSelectionColor"),
93 	TargetSelectionColor(this,"TargetSelectionColor"),
94 	NormalNameColor(this,"NormalNameColor",emColor(0,0,0,255),true),
95 	ExeNameColor(this,"ExeNameColor",emColor(0,0,0,255),true),
96 	DirNameColor(this,"DirNameColor",emColor(0,0,0,255),true),
97 	FifoNameColor(this,"FifoNameColor",emColor(0,0,0,255),true),
98 	BlkNameColor(this,"BlkNameColor",emColor(0,0,0,255),true),
99 	ChrNameColor(this,"ChrNameColor",emColor(0,0,0,255),true),
100 	SockNameColor(this,"SockNameColor",emColor(0,0,0,255),true),
101 	OtherNameColor(this,"OtherNameColor",emColor(0,0,0,255),true),
102 	PathColor(this,"PathColor",emColor(0,0,0,255),true),
103 	SymLinkColor(this,"SymLinkColor",emColor(0,0,0,255),true),
104 	LabelColor(this,"LabelColor",emColor(0,0,0,255),true),
105 	InfoColor(this,"InfoColor",emColor(0,0,0,255),true),
106 	FileContentColor(this,"FileContentColor"),
107 	DirContentColor(this,"DirContentColor"),
108 	Height(this,"Height"),
109 	BackgroundX(this,"BackgroundX"),
110 	BackgroundY(this,"BackgroundY"),
111 	BackgroundW(this,"BackgroundW"),
112 	BackgroundH(this,"BackgroundH"),
113 	BackgroundRX(this,"BackgroundRX"),
114 	BackgroundRY(this,"BackgroundRY"),
115 	OuterBorderX(this,"OuterBorderX"),
116 	OuterBorderY(this,"OuterBorderY"),
117 	OuterBorderW(this,"OuterBorderW"),
118 	OuterBorderH(this,"OuterBorderH"),
119 	OuterBorderL(this,"OuterBorderL"),
120 	OuterBorderT(this,"OuterBorderT"),
121 	OuterBorderR(this,"OuterBorderR"),
122 	OuterBorderB(this,"OuterBorderB"),
123 	OuterBorderImg(this,"OuterBorderImg",GetRootContext()),
124 	OuterBorderImgL(this,"OuterBorderImgL"),
125 	OuterBorderImgT(this,"OuterBorderImgT"),
126 	OuterBorderImgR(this,"OuterBorderImgR"),
127 	OuterBorderImgB(this,"OuterBorderImgB"),
128 	NameX(this,"NameX"),
129 	NameY(this,"NameY"),
130 	NameW(this,"NameW"),
131 	NameH(this,"NameH"),
132 	NameAlignment(this,"NameAlignment"),
133 	PathX(this,"PathX"),
134 	PathY(this,"PathY"),
135 	PathW(this,"PathW"),
136 	PathH(this,"PathH"),
137 	PathAlignment(this,"PathAlignment"),
138 	InfoX(this,"InfoX"),
139 	InfoY(this,"InfoY"),
140 	InfoW(this,"InfoW"),
141 	InfoH(this,"InfoH"),
142 	InfoAlignment(this,"InfoAlignment"),
143 	FileInnerBorderX(this,"FileInnerBorderX"),
144 	FileInnerBorderY(this,"FileInnerBorderY"),
145 	FileInnerBorderW(this,"FileInnerBorderW"),
146 	FileInnerBorderH(this,"FileInnerBorderH"),
147 	FileInnerBorderL(this,"FileInnerBorderL"),
148 	FileInnerBorderT(this,"FileInnerBorderT"),
149 	FileInnerBorderR(this,"FileInnerBorderR"),
150 	FileInnerBorderB(this,"FileInnerBorderB"),
151 	FileInnerBorderImg(this,"FileInnerBorderImg",GetRootContext()),
152 	FileInnerBorderImgL(this,"FileInnerBorderImgL"),
153 	FileInnerBorderImgT(this,"FileInnerBorderImgT"),
154 	FileInnerBorderImgR(this,"FileInnerBorderImgR"),
155 	FileInnerBorderImgB(this,"FileInnerBorderImgB"),
156 	FileContentX(this,"FileContentX"),
157 	FileContentY(this,"FileContentY"),
158 	FileContentW(this,"FileContentW"),
159 	FileContentH(this,"FileContentH"),
160 	DirInnerBorderX(this,"DirInnerBorderX"),
161 	DirInnerBorderY(this,"DirInnerBorderY"),
162 	DirInnerBorderW(this,"DirInnerBorderW"),
163 	DirInnerBorderH(this,"DirInnerBorderH"),
164 	DirInnerBorderL(this,"DirInnerBorderL"),
165 	DirInnerBorderT(this,"DirInnerBorderT"),
166 	DirInnerBorderR(this,"DirInnerBorderR"),
167 	DirInnerBorderB(this,"DirInnerBorderB"),
168 	DirInnerBorderImg(this,"DirInnerBorderImg",GetRootContext()),
169 	DirInnerBorderImgL(this,"DirInnerBorderImgL"),
170 	DirInnerBorderImgT(this,"DirInnerBorderImgT"),
171 	DirInnerBorderImgR(this,"DirInnerBorderImgR"),
172 	DirInnerBorderImgB(this,"DirInnerBorderImgB"),
173 	DirContentX(this,"DirContentX"),
174 	DirContentY(this,"DirContentY"),
175 	DirContentW(this,"DirContentW"),
176 	DirContentH(this,"DirContentH"),
177 	AltX(this,"AltX"),
178 	AltY(this,"AltY"),
179 	AltW(this,"AltW"),
180 	AltH(this,"AltH"),
181 	AltLabelX(this,"AltLabelX"),
182 	AltLabelY(this,"AltLabelY"),
183 	AltLabelW(this,"AltLabelW"),
184 	AltLabelH(this,"AltLabelH"),
185 	AltLabelAlignment(this,"AltLabelAlignment"),
186 	AltPathX(this,"AltPathX"),
187 	AltPathY(this,"AltPathY"),
188 	AltPathW(this,"AltPathW"),
189 	AltPathH(this,"AltPathH"),
190 	AltPathAlignment(this,"AltPathAlignment"),
191 	AltAltX(this,"AltAltX"),
192 	AltAltY(this,"AltAltY"),
193 	AltAltW(this,"AltAltW"),
194 	AltAltH(this,"AltAltH"),
195 	AltInnerBorderX(this,"AltInnerBorderX"),
196 	AltInnerBorderY(this,"AltInnerBorderY"),
197 	AltInnerBorderW(this,"AltInnerBorderW"),
198 	AltInnerBorderH(this,"AltInnerBorderH"),
199 	AltInnerBorderL(this,"AltInnerBorderL"),
200 	AltInnerBorderT(this,"AltInnerBorderT"),
201 	AltInnerBorderR(this,"AltInnerBorderR"),
202 	AltInnerBorderB(this,"AltInnerBorderB"),
203 	AltInnerBorderImg(this,"AltInnerBorderImg",GetRootContext()),
204 	AltInnerBorderImgL(this,"AltInnerBorderImgL"),
205 	AltInnerBorderImgT(this,"AltInnerBorderImgT"),
206 	AltInnerBorderImgR(this,"AltInnerBorderImgR"),
207 	AltInnerBorderImgB(this,"AltInnerBorderImgB"),
208 	AltContentX(this,"AltContentX"),
209 	AltContentY(this,"AltContentY"),
210 	AltContentW(this,"AltContentW"),
211 	AltContentH(this,"AltContentH"),
212 	MinContentVW(this,"MinContentVW"),
213 	MinAltVW(this,"MinAltVW"),
214 	DirPaddingL(this,"DirPaddingL"),
215 	DirPaddingT(this,"DirPaddingT"),
216 	DirPaddingR(this,"DirPaddingR"),
217 	DirPaddingB(this,"DirPaddingB"),
218 	LnkPaddingL(this,"LnkPaddingL"),
219 	LnkPaddingT(this,"LnkPaddingT"),
220 	LnkPaddingR(this,"LnkPaddingR"),
221 	LnkPaddingB(this,"LnkPaddingB")
222 {
223 	PostConstruct(
224 		*this,
225 		emGetChildPath(GetThemesDirPath(), name + ThemeFileEnding)
226 	);
227 	Load();
228 }
229 
230 
~emFileManTheme()231 emFileManTheme::~emFileManTheme()
232 {
233 }
234 
235 
236 //==============================================================================
237 //============================ emFileManThemeNames =============================
238 //==============================================================================
239 
Acquire(emRootContext & rootContext)240 emRef<emFileManThemeNames> emFileManThemeNames::Acquire(
241 	emRootContext & rootContext
242 )
243 {
244 	EM_IMPL_ACQUIRE_COMMON(emFileManThemeNames,rootContext,"")
245 }
246 
247 
emFileManThemeNames(emContext & context,const emString & name)248 emFileManThemeNames::emFileManThemeNames(emContext & context, const emString & name)
249 	: emModel(context,name)
250 {
251 	emArray<emString> names;
252 	int i, j, eLen, nLen;
253 	emRef<emFileManTheme> t;
254 	ThemeStyle * s;
255 	ThemeAR * a;
256 
257 	try {
258 		names=emTryLoadDir(emFileManTheme::GetThemesDirPath());
259 	}
260 	catch (const emException &) {
261 		names.Clear();
262 	}
263 	eLen=strlen(emFileManTheme::ThemeFileEnding);
264 	for (i=0; i<names.GetCount(); ) {
265 		nLen=strlen(names[i])-eLen;
266 		if (nLen>0 && strcmp(names[i].Get()+nLen,emFileManTheme::ThemeFileEnding)==0) {
267 			names.GetWritable(i).Remove(nLen,eLen);
268 			i++;
269 		}
270 		else {
271 			names.Remove(i);
272 		}
273 	}
274 	names.Sort(emStdComparer<emString>::Compare);
275 
276 	for (i=0; i<names.GetCount(); i++) {
277 		t=emFileManTheme::Acquire(GetRootContext(),names[i]);
278 		for (j=ThemeStyles.GetCount()-1; j>=0; j--) {
279 			if (ThemeStyles[j].DisplayName==t->DisplayName.Get()) break;
280 		}
281 		if (j<0) {
282 			j=ThemeStyles.GetCount();
283 			ThemeStyles.AddNew();
284 		}
285 		s=&ThemeStyles.GetWritable(j);
286 		s->DisplayName=t->DisplayName.Get();
287 		s->DisplayIcon=t->DisplayIcon.Get();
288 		for (j=0; j<s->ThemeARs.GetCount(); j++) {
289 			if (s->ThemeARs[j].Height>t->Height.Get()) break;
290 		}
291 		s->ThemeARs.InsertNew(j);
292 		a=&s->ThemeARs.GetWritable(j);
293 		a->Name=names[i];
294 		a->Height=t->Height.Get();
295 		a->AspectRatio=HeightToAspectRatioString(a->Height);
296 		t=NULL;
297 	}
298 
299 	for (i=0; i<ThemeStyles.GetCount(); i++) {
300 		for (j=0; j<ThemeStyles[i].ThemeARs.GetCount(); j++) {
301 			NameToPackedIndex.Insert(
302 				ThemeStyles[i].ThemeARs[j].Name,
303 				(i<<16)|j
304 			);
305 		}
306 	}
307 
308 	SetMinCommonLifetime(INT_MAX);
309 }
310 
311 
~emFileManThemeNames()312 emFileManThemeNames::~emFileManThemeNames()
313 {
314 }
315 
316 
GetThemeAspectRatioCount(int styleIndex) const317 int emFileManThemeNames::GetThemeAspectRatioCount(int styleIndex) const
318 {
319 	if (styleIndex<0 || styleIndex>=ThemeStyles.GetCount()) {
320 		return 0;
321 	}
322 	return ThemeStyles[styleIndex].ThemeARs.GetCount();
323 }
324 
325 
GetThemeName(int styleIndex,int aspectRatioIndex) const326 emString emFileManThemeNames::GetThemeName(
327 	int styleIndex, int aspectRatioIndex
328 ) const
329 {
330 	if (styleIndex<0 || styleIndex>=ThemeStyles.GetCount()) {
331 		return emString();
332 	}
333 	const ThemeStyle & style=ThemeStyles[styleIndex];
334 	if (aspectRatioIndex<0 || aspectRatioIndex>=style.ThemeARs.GetCount()) {
335 		return emString();
336 	}
337 	return style.ThemeARs[aspectRatioIndex].Name;
338 }
339 
340 
GetDefaultThemeName() const341 emString emFileManThemeNames::GetDefaultThemeName() const
342 {
343 	emString name;
344 
345 	name="Glass1";
346 	if (!NameToPackedIndex.Contains(name)) {
347 		name=GetThemeName(0,0);
348 	}
349 	return name;
350 }
351 
352 
GetThemeStyleDisplayName(int styleIndex) const353 emString emFileManThemeNames::GetThemeStyleDisplayName(
354 	int styleIndex
355 ) const
356 {
357 	if (styleIndex<0 || styleIndex>=ThemeStyles.GetCount()) {
358 		return emString();
359 	}
360 	return ThemeStyles[styleIndex].DisplayName;
361 }
362 
363 
GetThemeStyleDisplayIcon(int styleIndex) const364 emString emFileManThemeNames::GetThemeStyleDisplayIcon(
365 	int styleIndex
366 ) const
367 {
368 	if (styleIndex<0 || styleIndex>=ThemeStyles.GetCount()) {
369 		return emString();
370 	}
371 	return ThemeStyles[styleIndex].DisplayIcon;
372 }
373 
374 
GetThemeAspectRatio(int styleIndex,int aspectRatioIndex) const375 emString emFileManThemeNames::GetThemeAspectRatio(
376 	int styleIndex, int aspectRatioIndex
377 ) const
378 {
379 	if (styleIndex<0 || styleIndex>=ThemeStyles.GetCount()) {
380 		return emString();
381 	}
382 	const ThemeStyle & style=ThemeStyles[styleIndex];
383 	if (aspectRatioIndex<0 || aspectRatioIndex>=style.ThemeARs.GetCount()) {
384 		return emString();
385 	}
386 	return style.ThemeARs[aspectRatioIndex].AspectRatio;
387 }
388 
389 
IsExistingThemeName(const emString & themeName) const390 bool emFileManThemeNames::IsExistingThemeName(const emString & themeName) const
391 {
392 	return NameToPackedIndex.Contains(themeName);
393 }
394 
395 
GetThemeStyleIndex(const emString & themeName) const396 int emFileManThemeNames::GetThemeStyleIndex(
397 	const emString & themeName
398 ) const
399 {
400 	const emAvlTreeMap<emString,int>::Element * e;
401 
402 	e=NameToPackedIndex.Get(themeName);
403 	if (!e) return -1;
404 	return e->Value>>16;
405 }
406 
407 
GetThemeAspectRatioIndex(const emString & themeName) const408 int emFileManThemeNames::GetThemeAspectRatioIndex(
409 	const emString & themeName
410 ) const
411 {
412 	const emAvlTreeMap<emString,int>::Element * e;
413 
414 	e=NameToPackedIndex.Get(themeName);
415 	if (!e) return -1;
416 	return e->Value&0xFFFF;
417 }
418 
419 
HeightToAspectRatioString(double height)420 emString emFileManThemeNames::HeightToAspectRatioString(double height)
421 {
422 	int n,d,bestN,bestD;
423 
424 	bestN=bestD=1;
425 	for (d=1; d<=10; d++) {
426 		n=(int)(d/height+0.5);
427 		if (n<1) n=1;
428 		if (fabs(height*n/d-1.0)<fabs(height*bestN/bestD-1.0)-0.001) {
429 			bestN=n;
430 			bestD=d;
431 		}
432 	}
433 	return emString::Format("%d:%d",bestN,bestD);
434 }
435