xref: /haiku/src/kits/tracker/ViewState.cpp (revision 7a74a5df454197933bc6e80a542102362ee98703)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 
36 #include <Debug.h>
37 #include <AppDefs.h>
38 #include <InterfaceDefs.h>
39 
40 #include "Attributes.h"
41 #include "Commands.h"
42 #include "PoseView.h"
43 #include "Utilities.h"
44 #include "ViewState.h"
45 
46 #include <new>
47 #include <string.h>
48 #include <stdlib.h>
49 
50 
51 const char* kColumnVersionName = "BColumn:version";
52 const char* kColumnTitleName = "BColumn:fTitle";
53 const char* kColumnOffsetName = "BColumn:fOffset";
54 const char* kColumnWidthName = "BColumn:fWidth";
55 const char* kColumnAlignmentName = "BColumn:fAlignment";
56 const char* kColumnAttrName = "BColumn:fAttrName";
57 const char* kColumnAttrHashName = "BColumn:fAttrHash";
58 const char* kColumnAttrTypeName = "BColumn:fAttrType";
59 const char* kColumnDisplayAsName = "BColumn:fDisplayAs";
60 const char* kColumnStatFieldName = "BColumn:fStatField";
61 const char* kColumnEditableName = "BColumn:fEditable";
62 
63 const char* kViewStateVersionName = "ViewState:version";
64 const char* kViewStateViewModeName = "ViewState:fViewMode";
65 const char* kViewStateLastIconModeName = "ViewState:fLastIconMode";
66 const char* kViewStateListOriginName = "ViewState:fListOrigin";
67 const char* kViewStateIconOriginName = "ViewState:fIconOrigin";
68 const char* kViewStatePrimarySortAttrName = "ViewState:fPrimarySortAttr";
69 const char* kViewStatePrimarySortTypeName = "ViewState:fPrimarySortType";
70 const char* kViewStateSecondarySortAttrName = "ViewState:fSecondarySortAttr";
71 const char* kViewStateSecondarySortTypeName = "ViewState:fSecondarySortType";
72 const char* kViewStateReverseSortName = "ViewState:fReverseSort";
73 const char* kViewStateIconSizeName = "ViewState:fIconSize";
74 const char* kViewStateLastIconSizeName = "ViewState:fLastIconSize";
75 
76 
77 static const int32 kColumnStateMinArchiveVersion = 21;
78 	// bump version when layout changes
79 
80 
81 BColumn::BColumn(const char* title, float offset, float width,
82 	alignment align, const char* attributeName, uint32 attrType,
83 	const char* displayAs, bool statField, bool editable)
84 {
85 	_Init(title, offset, width, align, attributeName, attrType, displayAs,
86 		statField, editable);
87 }
88 
89 
90 BColumn::BColumn(const char* title, float offset, float width,
91 	alignment align, const char* attributeName, uint32 attrType,
92 	bool statField, bool editable)
93 {
94 	_Init(title, offset, width, align, attributeName, attrType, NULL,
95 		statField, editable);
96 }
97 
98 
99 BColumn::~BColumn()
100 {
101 }
102 
103 
104 BColumn::BColumn(BMallocIO* stream, int32 version, bool endianSwap)
105 {
106 	StringFromStream(&fTitle, stream, endianSwap);
107 	stream->Read(&fOffset, sizeof(float));
108 	stream->Read(&fWidth, sizeof(float));
109 	stream->Read(&fAlignment, sizeof(alignment));
110 	StringFromStream(&fAttrName, stream, endianSwap);
111 	stream->Read(&fAttrHash, sizeof(uint32));
112 	stream->Read(&fAttrType, sizeof(uint32));
113 	stream->Read(&fStatField, sizeof(bool));
114 	stream->Read(&fEditable, sizeof(bool));
115 	if (version == kColumnStateArchiveVersion)
116 		StringFromStream(&fDisplayAs, stream, endianSwap);
117 
118 	if (endianSwap) {
119 		PRINT(("endian swapping column\n"));
120 		fOffset = B_SWAP_FLOAT(fOffset);
121 		fWidth = B_SWAP_FLOAT(fWidth);
122 		STATIC_ASSERT(sizeof(BColumn::fAlignment) == sizeof(int32));
123 		fAlignment = (alignment)B_SWAP_INT32(fAlignment);
124 		fAttrHash = B_SWAP_INT32(fAttrHash);
125 		fAttrType = B_SWAP_INT32(fAttrType);
126 	}
127 }
128 
129 
130 BColumn::BColumn(const BMessage &message, int32 index)
131 {
132 	message.FindString(kColumnTitleName, index, &fTitle);
133 	message.FindFloat(kColumnOffsetName, index, &fOffset);
134 	message.FindFloat(kColumnWidthName, index, &fWidth);
135 	message.FindInt32(kColumnAlignmentName, index, (int32*)&fAlignment);
136 	message.FindString(kColumnAttrName, index, &fAttrName);
137 	message.FindInt32(kColumnAttrHashName, index, (int32*)&fAttrHash);
138 	message.FindInt32(kColumnAttrTypeName, index, (int32*)&fAttrType);
139 	message.FindString(kColumnDisplayAsName, index, &fDisplayAs);
140 	message.FindBool(kColumnStatFieldName, index, &fStatField);
141 	message.FindBool(kColumnEditableName, index, &fEditable);
142 }
143 
144 
145 void
146 BColumn::_Init(const char* title, float offset, float width,
147 	alignment align, const char* attributeName, uint32 attrType,
148 	const char* displayAs, bool statField, bool editable)
149 {
150 	fTitle = title;
151 	fAttrName = attributeName;
152 	fDisplayAs = displayAs;
153 	fOffset = offset;
154 	fWidth = width;
155 	fAlignment = align;
156 	fAttrHash = AttrHashString(attributeName, attrType);
157 	fAttrType = attrType;
158 	fStatField = statField;
159 	fEditable = editable;
160 }
161 
162 
163 BColumn*
164 BColumn::InstantiateFromStream(BMallocIO* stream, bool endianSwap)
165 {
166 	// compare stream header in canonical form
167 
168 	// we can't use ValidateStream(), as we preserve backwards compatibility
169 	int32 version;
170 	uint32 key;
171 	if (stream->Read(&key, sizeof(uint32)) <= 0
172 		|| stream->Read(&version, sizeof(int32)) <=0)
173 		return 0;
174 
175 	if (endianSwap) {
176 		key = SwapUInt32(key);
177 		version = SwapInt32(version);
178 	}
179 
180 	if (key != AttrHashString("BColumn", B_OBJECT_TYPE)
181 		|| version < kColumnStateMinArchiveVersion)
182 		return 0;
183 
184 //	PRINT(("instantiating column, %s\n", endianSwap ? "endian swapping," : ""));
185 	return _Sanitize(new (std::nothrow) BColumn(stream, version, endianSwap));
186 }
187 
188 
189 BColumn*
190 BColumn::InstantiateFromMessage(const BMessage &message, int32 index)
191 {
192 	int32 version = kColumnStateArchiveVersion;
193 	int32 messageVersion;
194 
195 	if (message.FindInt32(kColumnVersionName, index, &messageVersion) != B_OK)
196 		return NULL;
197 
198 	if (version != messageVersion)
199 		return NULL;
200 
201 	return _Sanitize(new (std::nothrow) BColumn(message, index));
202 }
203 
204 
205 void
206 BColumn::ArchiveToStream(BMallocIO* stream) const
207 {
208 	// write class identifier and version info
209 	uint32 key = AttrHashString("BColumn", B_OBJECT_TYPE);
210 	stream->Write(&key, sizeof(uint32));
211 	int32 version = kColumnStateArchiveVersion;
212 	stream->Write(&version, sizeof(int32));
213 
214 //	PRINT(("ArchiveToStream column, key %x, version %d\n", key, version));
215 
216 	StringToStream(&fTitle, stream);
217 	stream->Write(&fOffset, sizeof(float));
218 	stream->Write(&fWidth, sizeof(float));
219 	stream->Write(&fAlignment, sizeof(alignment));
220 	StringToStream(&fAttrName, stream);
221 	stream->Write(&fAttrHash, sizeof(uint32));
222 	stream->Write(&fAttrType, sizeof(uint32));
223 	stream->Write(&fStatField, sizeof(bool));
224 	stream->Write(&fEditable, sizeof(bool));
225 	StringToStream(&fDisplayAs, stream);
226 }
227 
228 
229 void
230 BColumn::ArchiveToMessage(BMessage &message) const
231 {
232 	message.AddInt32(kColumnVersionName, kColumnStateArchiveVersion);
233 
234 	message.AddString(kColumnTitleName, fTitle);
235 	message.AddFloat(kColumnOffsetName, fOffset);
236 	message.AddFloat(kColumnWidthName, fWidth);
237 	message.AddInt32(kColumnAlignmentName, fAlignment);
238 	message.AddString(kColumnAttrName, fAttrName);
239 	message.AddInt32(kColumnAttrHashName, static_cast<int32>(fAttrHash));
240 	message.AddInt32(kColumnAttrTypeName, static_cast<int32>(fAttrType));
241 	if (fDisplayAs.Length() > 0)
242 		message.AddString(kColumnDisplayAsName, fDisplayAs.String());
243 	message.AddBool(kColumnStatFieldName, fStatField);
244 	message.AddBool(kColumnEditableName, fEditable);
245 }
246 
247 
248 BColumn *
249 BColumn::_Sanitize(BColumn* column)
250 {
251 	if (column == NULL)
252 		return NULL;
253 
254 	// sanity-check the resulting column
255 	if (column->fTitle.Length() > 500
256 		|| column->fOffset < 0
257 		|| column->fOffset > 10000
258 		|| column->fWidth < 0
259 		|| column->fWidth > 10000
260 		|| (int32)column->fAlignment < B_ALIGN_LEFT
261 		|| (int32)column->fAlignment > B_ALIGN_CENTER
262 		|| column->fAttrName.Length() > 500) {
263 		PRINT(("column data not valid\n"));
264 		delete column;
265 		return NULL;
266 	}
267 #if DEBUG
268 // TODO: Whatever this is supposed to mean, fix it.
269 //	else if (endianSwap)
270 //		PRINT(("Instantiated foreign column ok\n"));
271 #endif
272 
273 	return column;
274 }
275 
276 
277 //	#pragma mark -
278 
279 
280 BViewState::BViewState()
281 {
282 	_Init();
283 	_StorePreviousState();
284 }
285 
286 
287 BViewState::BViewState(BMallocIO* stream, bool endianSwap)
288 {
289 	_Init();
290 	stream->Read(&fViewMode, sizeof(uint32));
291 	stream->Read(&fLastIconMode, sizeof(uint32));
292 	stream->Read(&fListOrigin, sizeof(BPoint));
293 	stream->Read(&fIconOrigin, sizeof(BPoint));
294 	stream->Read(&fPrimarySortAttr, sizeof(uint32));
295 	stream->Read(&fPrimarySortType, sizeof(uint32));
296 	stream->Read(&fSecondarySortAttr, sizeof(uint32));
297 	stream->Read(&fSecondarySortType, sizeof(uint32));
298 	stream->Read(&fReverseSort, sizeof(bool));
299 	stream->Read(&fIconSize, sizeof(uint32));
300 	stream->Read(&fLastIconSize, sizeof(uint32));
301 
302 	if (endianSwap) {
303 		PRINT(("endian swapping view state\n"));
304 		fViewMode = B_SWAP_INT32(fViewMode);
305 		fLastIconMode = B_SWAP_INT32(fLastIconMode);
306 		fIconSize = B_SWAP_INT32(fIconSize);
307 		fLastIconSize = B_SWAP_INT32(fLastIconSize);
308 		swap_data(B_POINT_TYPE, &fListOrigin,
309 			sizeof(fListOrigin), B_SWAP_ALWAYS);
310 		swap_data(B_POINT_TYPE, &fIconOrigin,
311 			sizeof(fIconOrigin), B_SWAP_ALWAYS);
312 		fPrimarySortAttr = B_SWAP_INT32(fPrimarySortAttr);
313 		fSecondarySortAttr = B_SWAP_INT32(fSecondarySortAttr);
314 		fPrimarySortType = B_SWAP_INT32(fPrimarySortType);
315 		fSecondarySortType = B_SWAP_INT32(fSecondarySortType);
316 	}
317 
318 	_StorePreviousState();
319 	_Sanitize(this, true);
320 }
321 
322 
323 BViewState::BViewState(const BMessage &message)
324 {
325 	_Init();
326 	message.FindInt32(kViewStateViewModeName, (int32*)&fViewMode);
327 	message.FindInt32(kViewStateLastIconModeName, (int32*)&fLastIconMode);
328 	message.FindInt32(kViewStateLastIconSizeName,(int32*)&fLastIconSize);
329 	message.FindInt32(kViewStateIconSizeName, (int32*)&fIconSize);
330 	message.FindPoint(kViewStateListOriginName, &fListOrigin);
331 	message.FindPoint(kViewStateIconOriginName, &fIconOrigin);
332 	message.FindInt32(kViewStatePrimarySortAttrName,
333 		(int32*)&fPrimarySortAttr);
334 	message.FindInt32(kViewStatePrimarySortTypeName,
335 		(int32*)&fPrimarySortType);
336 	message.FindInt32(kViewStateSecondarySortAttrName,
337 		(int32*)&fSecondarySortAttr);
338 	message.FindInt32(kViewStateSecondarySortTypeName,
339 		(int32*)&fSecondarySortType);
340 	message.FindBool(kViewStateReverseSortName, &fReverseSort);
341 
342 	_StorePreviousState();
343 	_Sanitize(this, true);
344 }
345 
346 
347 void
348 BViewState::ArchiveToStream(BMallocIO* stream) const
349 {
350 	// write class identifier and verison info
351 	uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE);
352 	stream->Write(&key, sizeof(key));
353 	int32 version = kViewStateArchiveVersion;
354 	stream->Write(&version, sizeof(version));
355 
356 	stream->Write(&fViewMode, sizeof(uint32));
357 	stream->Write(&fLastIconMode, sizeof(uint32));
358 	stream->Write(&fListOrigin, sizeof(BPoint));
359 	stream->Write(&fIconOrigin, sizeof(BPoint));
360 	stream->Write(&fPrimarySortAttr, sizeof(uint32));
361 	stream->Write(&fPrimarySortType, sizeof(uint32));
362 	stream->Write(&fSecondarySortAttr, sizeof(uint32));
363 	stream->Write(&fSecondarySortType, sizeof(uint32));
364 	stream->Write(&fReverseSort, sizeof(bool));
365 	stream->Write(&fIconSize, sizeof(uint32));
366 	stream->Write(&fLastIconSize, sizeof(uint32));
367 }
368 
369 
370 void
371 BViewState::ArchiveToMessage(BMessage &message) const
372 {
373 	message.AddInt32(kViewStateVersionName, kViewStateArchiveVersion);
374 
375 	message.AddInt32(kViewStateViewModeName, static_cast<int32>(fViewMode));
376 	message.AddInt32(kViewStateLastIconModeName,
377 		static_cast<int32>(fLastIconMode));
378 	message.AddPoint(kViewStateListOriginName, fListOrigin);
379 	message.AddPoint(kViewStateIconOriginName, fIconOrigin);
380 	message.AddInt32(kViewStatePrimarySortAttrName,
381 		static_cast<int32>(fPrimarySortAttr));
382 	message.AddInt32(kViewStatePrimarySortTypeName,
383 		static_cast<int32>(fPrimarySortType));
384 	message.AddInt32(kViewStateSecondarySortAttrName,
385 		static_cast<int32>(fSecondarySortAttr));
386 	message.AddInt32(kViewStateSecondarySortTypeName,
387 		static_cast<int32>(fSecondarySortType));
388 	message.AddBool(kViewStateReverseSortName, fReverseSort);
389 	message.AddInt32(kViewStateIconSizeName, static_cast<int32>(fIconSize));
390 	message.AddInt32(kViewStateLastIconSizeName,
391 		static_cast<int32>(fLastIconSize));
392 }
393 
394 
395 BViewState*
396 BViewState::InstantiateFromStream(BMallocIO* stream, bool endianSwap)
397 {
398 	// compare stream header in canonical form
399 	uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE);
400 	int32 version = kViewStateArchiveVersion;
401 
402 	if (endianSwap) {
403 		key = SwapUInt32(key);
404 		version = SwapInt32(version);
405 	}
406 
407 	if (!ValidateStream(stream, key, version))
408 		return NULL;
409 
410 	return _Sanitize(new (std::nothrow) BViewState(stream, endianSwap));
411 }
412 
413 
414 BViewState*
415 BViewState::InstantiateFromMessage(const BMessage &message)
416 {
417 	int32 version = kViewStateArchiveVersion;
418 
419 	int32 messageVersion;
420 	if (message.FindInt32(kViewStateVersionName, &messageVersion) != B_OK)
421 		return NULL;
422 
423 	if (version != messageVersion)
424 		return NULL;
425 
426 	return _Sanitize(new (std::nothrow) BViewState(message));
427 }
428 
429 
430 void
431 BViewState::_Init()
432 {
433 	fViewMode = kListMode;
434 	fLastIconMode = 0;
435 	fIconSize = 32;
436 	fLastIconSize = 32;
437 	fListOrigin.Set(0, 0);
438 	fIconOrigin.Set(0, 0);
439 	fPrimarySortAttr = AttrHashString(kAttrStatName, B_STRING_TYPE);
440 	fPrimarySortType = B_STRING_TYPE;
441 	fSecondarySortAttr = 0;
442 	fSecondarySortType = 0;
443 	fReverseSort = false;
444 }
445 
446 
447 void
448 BViewState::_StorePreviousState()
449 {
450 	fPreviousViewMode = fViewMode;
451 	fPreviousLastIconMode = fLastIconMode;
452 	fPreviousIconSize = fIconSize;
453 	fPreviousLastIconSize = fLastIconSize;
454 	fPreviousListOrigin = fListOrigin;
455 	fPreviousIconOrigin = fIconOrigin;
456 	fPreviousPrimarySortAttr = fPrimarySortAttr;
457 	fPreviousSecondarySortAttr = fSecondarySortAttr;
458 	fPreviousPrimarySortType = fPrimarySortType;
459 	fPreviousSecondarySortType = fSecondarySortType;
460 	fPreviousReverseSort = fReverseSort;
461 }
462 
463 
464 BViewState*
465 BViewState::_Sanitize(BViewState* state, bool fixOnly)
466 {
467 	if (state == NULL)
468 		return NULL;
469 
470 	if (state->fViewMode == kListMode) {
471 		if (state->fListOrigin.x < 0)
472 			state->fListOrigin.x = 0;
473 		if (state->fListOrigin.y < 0)
474 			state->fListOrigin.y = 0;
475 	}
476 	if (state->fIconSize < 16)
477 		state->fIconSize = 16;
478 	if (state->fIconSize > 128)
479 		state->fIconSize = 128;
480 	if (state->fLastIconSize < 16)
481 		state->fLastIconSize = 16;
482 	if (state->fLastIconSize > 128)
483 		state->fLastIconSize = 128;
484 
485 	if (fixOnly)
486 		return state;
487 
488 	// do a sanity check here
489 	if ((state->fViewMode != kListMode
490 			&& state->fViewMode != kIconMode
491 			&& state->fViewMode != kMiniIconMode
492 			&& state->fViewMode != 0)
493 		|| (state->fLastIconMode != kListMode
494 			&& state->fLastIconMode != kIconMode
495 			&& state->fLastIconMode != kMiniIconMode
496 			&& state->fLastIconMode != 0)) {
497 		PRINT(("Bad data instantiating ViewState, view mode %" B_PRIx32
498 			", lastIconMode %" B_PRIx32 "\n", state->fViewMode,
499 			state->fLastIconMode));
500 
501 		delete state;
502 		return NULL;
503 	}
504 #if DEBUG
505 // TODO: Whatever this is supposed to mean, fix it.
506 //	else if (endianSwap)
507 //		PRINT(("Instantiated foreign view state ok\n"));
508 #endif
509 
510 	return state;
511 }
512