1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30of Be Incorporated in the United States and other countries. Other brand product
31names are registered trademarks or trademarks of their respective holders.
32All rights reserved.
33*/
34
35
36#if DEBUG
37
38#include "Tests.h"
39
40#include <Debug.h>
41#include <Locker.h>
42#include <Path.h>
43#include <String.h>
44#include <Window.h>
45
46#include <directories.h>
47
48#include "EntryIterator.h"
49#include "IconCache.h"
50#include "Model.h"
51#include "NodeWalker.h"
52#include "StopWatch.h"
53#include "Thread.h"
54
55
56const char* pathsToSearch[] = {
57//	"/boot/home/config/settings/NetPositive/Bookmarks/",
58	kSystemDirectory,
59	kAppsDirectory,
60	kUserDirectory,
61	0
62};
63
64
65namespace BTrackerPrivate {
66
67class IconSpewer : public SimpleThread {
68public:
69	IconSpewer(bool newCache = true);
70	~IconSpewer();
71	void SetTarget(BWindow* target)
72		{ this->target = target; }
73
74	void Quit();
75	void Run();
76
77protected:
78	void DrawSomeNew();
79	void DrawSomeOld();
80	const entry_ref* NextRef();
81private:
82	BLocker locker;
83	bool quitting;
84	BWindow* target;
85	TNodeWalker* walker;
86	CachedEntryIterator* cachingIterator;
87	int32 searchPathIndex;
88	bigtime_t cycleTime;
89	bigtime_t lastCycleLap;
90	int32 numDrawn;
91	BStopWatch watch;
92	bool newCache;
93	BPath currentPath;
94
95	entry_ref ref;
96};
97
98
99class IconTestWindow : public BWindow {
100public:
101	IconTestWindow();
102	bool QuitRequested();
103private:
104	IconSpewer iconSpewer;
105};
106
107}	// namespace BTrackerPrivate
108
109
110//	#pragma mark - IconSpewer
111
112
113IconSpewer::IconSpewer(bool newCache)
114	:
115	quitting(false),
116	cachingIterator(0),
117	searchPathIndex(0),
118	cycleTime(0),
119	lastCycleLap(0),
120	numDrawn(0),
121	watch("", true),
122	newCache(newCache)
123{
124	walker = new TNodeWalker(pathsToSearch[searchPathIndex++]);
125	if (newCache)
126		cachingIterator = new CachedEntryIterator(walker, 40);
127}
128
129
130IconSpewer::~IconSpewer()
131{
132	delete walker;
133	delete cachingIterator;
134}
135
136
137void
138IconSpewer::Run()
139{
140	BStopWatch watch("", true);
141	for (;;) {
142		AutoLock<BLocker> lock(locker);
143
144		if (!lock || quitting)
145			break;
146
147		lock.Unlock();
148		if (newCache)
149			DrawSomeNew();
150		else
151			DrawSomeOld();
152	}
153}
154
155
156void
157IconSpewer::Quit()
158{
159	kill_thread(fScanThread);
160	fScanThread = -1;
161}
162
163
164const icon_size kIconSize = B_LARGE_ICON;
165const int32 kRowCount = 10;
166const int32 kColumnCount = 10;
167
168
169void
170IconSpewer::DrawSomeNew()
171{
172	target->Lock();
173	BView* view = target->FindView("iconView");
174	ASSERT(view);
175
176	BRect bounds(target->Bounds());
177	view->SetHighColor(255, 255, 255);
178	view->FillRect(bounds);
179
180	view->SetHighColor(0, 0, 0);
181	char buffer[256];
182	if (cycleTime) {
183		sprintf(buffer, "last cycle time %" B_PRId64 " ms", cycleTime/1000);
184		view->DrawString(buffer, BPoint(20, bounds.bottom - 20));
185	}
186
187	if (numDrawn) {
188		sprintf(buffer, "average draw time %" B_PRId64 " us per icon",
189			watch.ElapsedTime() / numDrawn);
190		view->DrawString(buffer, BPoint(20, bounds.bottom - 30));
191	}
192
193	sprintf(buffer, "directory: %s", currentPath.Path());
194	view->DrawString(buffer, BPoint(20, bounds.bottom - 40));
195
196	target->Unlock();
197
198	for (int32 row = 0; row < kRowCount; row++) {
199		for (int32 column = 0; column < kColumnCount; column++) {
200			BEntry entry(NextRef());
201			Model model(&entry, true);
202
203			if (!target->Lock())
204				return;
205
206			if (model.IsDirectory())
207				entry.GetPath(&currentPath);
208
209			IconCache::sIconCache->Draw(&model, view,
210				BPoint(column * (kIconSize + 2), row * (kIconSize + 2)),
211				kNormalIcon, BSize(kIconSize - 1, kIconSize - 1), true);
212			target->Unlock();
213			numDrawn++;
214		}
215	}
216}
217
218
219bool oldIconCacheInited = false;
220
221
222void
223IconSpewer::DrawSomeOld()
224{
225#if 0
226	if (!oldIconCacheInited)
227		BIconCache::InitIconCaches();
228
229	target->Lock();
230	target->SetTitle("old cache");
231	BView* view = target->FindView("iconView");
232	ASSERT(view);
233
234	BRect bounds(target->Bounds());
235	view->SetHighColor(255, 255, 255);
236	view->FillRect(bounds);
237
238	view->SetHighColor(0, 0, 0);
239	char buffer[256];
240	if (cycleTime) {
241		sprintf(buffer, "last cycle time %lld ms", cycleTime/1000);
242		view->DrawString(buffer, BPoint(20, bounds.bottom - 20));
243	}
244	if (numDrawn) {
245		sprintf(buffer, "average draw time %lld us per icon",
246			watch.ElapsedTime() / numDrawn);
247		view->DrawString(buffer, BPoint(20, bounds.bottom - 30));
248	}
249	sprintf(buffer, "directory: %s", currentPath.Path());
250	view->DrawString(buffer, BPoint(20, bounds.bottom - 40));
251
252	target->Unlock();
253
254	for (int32 row = 0; row < kRowCount; row++) {
255		for (int32 column = 0; column < kColumnCount; column++) {
256			BEntry entry(NextRef());
257			BModel model(&entry, true);
258
259			if (!target->Lock())
260				return;
261
262			if (model.IsDirectory())
263				entry.GetPath(&currentPath);
264
265			BIconCache::LockIconCache();
266			BIconCache* iconCache
267				= BIconCache::GetIconCache(&model, kIconSize);
268			iconCache->Draw(view, BPoint(column * (kIconSize + 2),
269				row * (kIconSize + 2)), B_NORMAL_ICON, kIconSize, true);
270			BIconCache::UnlockIconCache();
271
272			target->Unlock();
273			numDrawn++;
274		}
275	}
276#endif
277}
278
279
280const entry_ref*
281IconSpewer::NextRef()
282{
283	status_t result;
284	if (newCache)
285		result = cachingIterator->GetNextRef(&ref);
286	else
287		result = walker->GetNextRef(&ref);
288
289	if (result == B_OK)
290		return &ref;
291
292	delete walker;
293	if (!pathsToSearch[searchPathIndex]) {
294		bigtime_t now = watch.ElapsedTime();
295		cycleTime = now - lastCycleLap;
296		lastCycleLap = now;
297		PRINT(("**************************hit end of disk, starting over\n"));
298		searchPathIndex = 0;
299	}
300
301	walker = new TNodeWalker(pathsToSearch[searchPathIndex++]);
302	if (newCache) {
303		cachingIterator->SetTo(walker);
304		result = cachingIterator->GetNextRef(&ref);
305	} else
306		result = walker->GetNextRef(&ref);
307
308	ASSERT(result == B_OK);
309		// we don't expect and cannot deal with any problems here
310	return &ref;
311}
312
313
314//	#pragma mark - IconTestWindow
315
316
317IconTestWindow::IconTestWindow()
318	:
319	BWindow(BRect(100, 100, 500, 600), "icon cache test",
320		B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 0),
321	iconSpewer(modifiers() == 0)
322{
323	iconSpewer.SetTarget(this);
324	BView* view = new BView(Bounds(), "iconView", B_FOLLOW_ALL, B_WILL_DRAW);
325	AddChild(view);
326	iconSpewer.Go();
327}
328
329
330bool
331IconTestWindow::QuitRequested()
332{
333	iconSpewer.Quit();
334	return true;
335}
336
337
338void
339RunIconCacheTests()
340{
341	(new IconTestWindow())->Show();
342}
343
344#endif	// DEBUG
345