xref: /haiku/src/kits/tracker/ViewState.cpp (revision 0754c319592cd8a523959d85fb06ab23c64a98a6)
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 //	#pragma mark - BColumn
82 
83 
84 BColumn::BColumn(const char* title, float offset, float width,
85 	alignment align, const char* attributeName, uint32 attrType,
86 	const char* displayAs, bool statField, bool editable)
87 {
88 	_Init(title, offset, width, align, attributeName, attrType, displayAs,
89 		statField, editable);
90 }
91 
92 
93 BColumn::BColumn(const char* title, float offset, float width,
94 	alignment align, const char* attributeName, uint32 attrType,
95 	bool statField, bool editable)
96 {
97 	_Init(title, offset, width, align, attributeName, attrType, NULL,
98 		statField, editable);
99 }
100 
101 
102 BColumn::~BColumn()
103 {
104 }
105 
106 
107 BColumn::BColumn(BMallocIO* stream, int32 version, bool endianSwap)
108 {
109 	StringFromStream(&fTitle, stream, endianSwap);
110 	stream->Read(&fOffset, sizeof(float));
111 	stream->Read(&fWidth, sizeof(float));
112 	stream->Read(&fAlignment, sizeof(alignment));
113 	StringFromStream(&fAttrName, stream, endianSwap);
114 	stream->Read(&fAttrHash, sizeof(uint32));
115 	stream->Read(&fAttrType, sizeof(uint32));
116 	stream->Read(&fStatField, sizeof(bool));
117 	stream->Read(&fEditable, sizeof(bool));
118 	if (version == kColumnStateArchiveVersion)
119 		StringFromStream(&fDisplayAs, stream, endianSwap);
120 
121 	if (endianSwap) {
122 		PRINT(("endian swapping column\n"));
123 		fOffset = B_SWAP_FLOAT(fOffset);
124 		fWidth = B_SWAP_FLOAT(fWidth);
125 		STATIC_ASSERT(sizeof(alignment) == sizeof(int32));
126 		fAlignment = (alignment)B_SWAP_INT32(fAlignment);
127 		fAttrHash = B_SWAP_INT32(fAttrHash);
128 		fAttrType = B_SWAP_INT32(fAttrType);
129 	}
130 }
131 
132 
133 BColumn::BColumn(const BMessage &message, int32 index)
134 {
135 	message.FindString(kColumnTitleName, index, &fTitle);
136 	message.FindFloat(kColumnOffsetName, index, &fOffset);
137 	message.FindFloat(kColumnWidthName, index, &fWidth);
138 	message.FindInt32(kColumnAlignmentName, index, (int32*)&fAlignment);
139 	message.FindString(kColumnAttrName, index, &fAttrName);
140 	message.FindInt32(kColumnAttrHashName, index, (int32*)&fAttrHash);
141 	message.FindInt32(kColumnAttrTypeName, index, (int32*)&fAttrType);
142 	message.FindString(kColumnDisplayAsName, index, &fDisplayAs);
143 	message.FindBool(kColumnStatFieldName, index, &fStatField);
144 	message.FindBool(kColumnEditableName, index, &fEditable);
145 }
146 
147 
148 void
149 BColumn::_Init(const char* title, float offset, float width,
150 	alignment align, const char* attributeName, uint32 attrType,
151 	const char* displayAs, bool statField, bool editable)
152 {
153 	fTitle = title;
154 	fAttrName = attributeName;
155 	fDisplayAs = displayAs;
156 	fOffset = offset;
157 	fWidth = width;
158 	fAlignment = align;
159 	fAttrHash = AttrHashString(attributeName, attrType);
160 	fAttrType = attrType;
161 	fStatField = statField;
162 	fEditable = editable;
163 }
164 
165 
166 BColumn*
167 BColumn::InstantiateFromStream(BMallocIO* stream, bool endianSwap)
168 {
169 	// compare stream header in canonical form
170 
171 	// we can't use ValidateStream(), as we preserve backwards compatibility
172 	int32 version;
173 	uint32 key;
174 	if (stream->Read(&key, sizeof(uint32)) <= 0
175 		|| stream->Read(&version, sizeof(int32)) <=0)
176 		return 0;
177 
178 	if (endianSwap) {
179 		key = SwapUInt32(key);
180 		version = SwapInt32(version);
181 	}
182 
183 	if (key != AttrHashString("BColumn", B_OBJECT_TYPE)
184 		|| version < kColumnStateMinArchiveVersion)
185 		return 0;
186 
187 //	PRINT(("instantiating column, %s\n", endianSwap ? "endian swapping," : ""));
188 	return _Sanitize(new (std::nothrow) BColumn(stream, version, endianSwap));
189 }
190 
191 
192 BColumn*
193 BColumn::InstantiateFromMessage(const BMessage &message, int32 index)
194 {
195 	int32 version = kColumnStateArchiveVersion;
196 	int32 messageVersion;
197 
198 	if (message.FindInt32(kColumnVersionName, index, &messageVersion) != B_OK)
199 		return NULL;
200 
201 	if (version != messageVersion)
202 		return NULL;
203 
204 	return _Sanitize(new (std::nothrow) BColumn(message, index));
205 }
206 
207 
208 void
209 BColumn::ArchiveToStream(BMallocIO* stream) const
210 {
211 	// write class identifier and version info
212 	uint32 key = AttrHashString("BColumn", B_OBJECT_TYPE);
213 	stream->Write(&key, sizeof(uint32));
214 	int32 version = kColumnStateArchiveVersion;
215 	stream->Write(&version, sizeof(int32));
216 
217 //	PRINT(("ArchiveToStream column, key %x, version %d\n", key, version));
218 
219 	StringToStream(&fTitle, stream);
220 	stream->Write(&fOffset, sizeof(float));
221 	stream->Write(&fWidth, sizeof(float));
222 	stream->Write(&fAlignment, sizeof(alignment));
223 	StringToStream(&fAttrName, stream);
224 	stream->Write(&fAttrHash, sizeof(uint32));
225 	stream->Write(&fAttrType, sizeof(uint32));
226 	stream->Write(&fStatField, sizeof(bool));
227 	stream->Write(&fEditable, sizeof(bool));
228 	StringToStream(&fDisplayAs, stream);
229 }
230 
231 
232 void
233 BColumn::ArchiveToMessage(BMessage &message) const
234 {
235 	message.AddInt32(kColumnVersionName, kColumnStateArchiveVersion);
236 
237 	message.AddString(kColumnTitleName, fTitle);
238 	message.AddFloat(kColumnOffsetName, fOffset);
239 	message.AddFloat(kColumnWidthName, fWidth);
240 	message.AddInt32(kColumnAlignmentName, fAlignment);
241 	message.AddString(kColumnAttrName, fAttrName);
242 	message.AddInt32(kColumnAttrHashName, static_cast<int32>(fAttrHash));
243 	message.AddInt32(kColumnAttrTypeName, static_cast<int32>(fAttrType));
244 	message.AddString(kColumnDisplayAsName, fDisplayAs.String());
245 	message.AddBool(kColumnStatFieldName, fStatField);
246 	message.AddBool(kColumnEditableName, fEditable);
247 }
248 
249 
250 BColumn*
251 BColumn::_Sanitize(BColumn* column)
252 {
253 	if (column == NULL)
254 		return NULL;
255 
256 	// sanity-check the resulting column
257 	if (column->fTitle.Length() > 500
258 		|| column->fOffset < 0
259 		|| column->fOffset > 10000
260 		|| column->fWidth < 0
261 		|| column->fWidth > 10000
262 		|| (int32)column->fAlignment < B_ALIGN_LEFT
263 		|| (int32)column->fAlignment > B_ALIGN_CENTER
264 		|| column->fAttrName.Length() > 500) {
265 		PRINT(("column data not valid\n"));
266 		delete column;
267 		return NULL;
268 	}
269 #if DEBUG
270 // TODO: Whatever this is supposed to mean, fix it.
271 //	else if (endianSwap)
272 //		PRINT(("Instantiated foreign column ok\n"));
273 #endif
274 
275 	return column;
276 }
277 
278 
279 //	#pragma mark - BViewState
280 
281 
282 BViewState::BViewState()
283 {
284 	_Init();
285 	_StorePreviousState();
286 }
287 
288 
289 BViewState::BViewState(BMallocIO* stream, bool endianSwap)
290 {
291 	_Init();
292 	stream->Read(&fViewMode, sizeof(uint32));
293 	stream->Read(&fLastIconMode, sizeof(uint32));
294 	stream->Read(&fListOrigin, sizeof(BPoint));
295 	stream->Read(&fIconOrigin, sizeof(BPoint));
296 	stream->Read(&fPrimarySortAttr, sizeof(uint32));
297 	stream->Read(&fPrimarySortType, sizeof(uint32));
298 	stream->Read(&fSecondarySortAttr, sizeof(uint32));
299 	stream->Read(&fSecondarySortType, sizeof(uint32));
300 	stream->Read(&fReverseSort, sizeof(bool));
301 	stream->Read(&fIconSize, sizeof(uint32));
302 	stream->Read(&fLastIconSize, sizeof(uint32));
303 
304 	if (endianSwap) {
305 		PRINT(("endian swapping view state\n"));
306 		fViewMode = B_SWAP_INT32(fViewMode);
307 		fLastIconMode = B_SWAP_INT32(fLastIconMode);
308 		fIconSize = B_SWAP_INT32(fIconSize);
309 		fLastIconSize = B_SWAP_INT32(fLastIconSize);
310 		swap_data(B_POINT_TYPE, &fListOrigin,
311 			sizeof(fListOrigin), B_SWAP_ALWAYS);
312 		swap_data(B_POINT_TYPE, &fIconOrigin,
313 			sizeof(fIconOrigin), B_SWAP_ALWAYS);
314 		fPrimarySortAttr = B_SWAP_INT32(fPrimarySortAttr);
315 		fSecondarySortAttr = B_SWAP_INT32(fSecondarySortAttr);
316 		fPrimarySortType = B_SWAP_INT32(fPrimarySortType);
317 		fSecondarySortType = B_SWAP_INT32(fSecondarySortType);
318 	}
319 
320 	_StorePreviousState();
321 	_Sanitize(this, true);
322 }
323 
324 
325 BViewState::BViewState(const BMessage &message)
326 {
327 	_Init();
328 	message.FindInt32(kViewStateViewModeName, (int32*)&fViewMode);
329 	message.FindInt32(kViewStateLastIconModeName, (int32*)&fLastIconMode);
330 	message.FindInt32(kViewStateLastIconSizeName,(int32*)&fLastIconSize);
331 	message.FindInt32(kViewStateIconSizeName, (int32*)&fIconSize);
332 	message.FindPoint(kViewStateListOriginName, &fListOrigin);
333 	message.FindPoint(kViewStateIconOriginName, &fIconOrigin);
334 	message.FindInt32(kViewStatePrimarySortAttrName,
335 		(int32*)&fPrimarySortAttr);
336 	message.FindInt32(kViewStatePrimarySortTypeName,
337 		(int32*)&fPrimarySortType);
338 	message.FindInt32(kViewStateSecondarySortAttrName,
339 		(int32*)&fSecondarySortAttr);
340 	message.FindInt32(kViewStateSecondarySortTypeName,
341 		(int32*)&fSecondarySortType);
342 	message.FindBool(kViewStateReverseSortName, &fReverseSort);
343 
344 	_StorePreviousState();
345 	_Sanitize(this, true);
346 }
347 
348 
349 void
350 BViewState::ArchiveToStream(BMallocIO* stream) const
351 {
352 	// write class identifier and verison info
353 	uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE);
354 	stream->Write(&key, sizeof(key));
355 	int32 version = kViewStateArchiveVersion;
356 	stream->Write(&version, sizeof(version));
357 
358 	stream->Write(&fViewMode, sizeof(uint32));
359 	stream->Write(&fLastIconMode, sizeof(uint32));
360 	stream->Write(&fListOrigin, sizeof(BPoint));
361 	stream->Write(&fIconOrigin, sizeof(BPoint));
362 	stream->Write(&fPrimarySortAttr, sizeof(uint32));
363 	stream->Write(&fPrimarySortType, sizeof(uint32));
364 	stream->Write(&fSecondarySortAttr, sizeof(uint32));
365 	stream->Write(&fSecondarySortType, sizeof(uint32));
366 	stream->Write(&fReverseSort, sizeof(bool));
367 	stream->Write(&fIconSize, sizeof(uint32));
368 	stream->Write(&fLastIconSize, sizeof(uint32));
369 }
370 
371 
372 void
373 BViewState::ArchiveToMessage(BMessage &message) const
374 {
375 	message.AddInt32(kViewStateVersionName, kViewStateArchiveVersion);
376 
377 	message.AddInt32(kViewStateViewModeName, static_cast<int32>(fViewMode));
378 	message.AddInt32(kViewStateLastIconModeName,
379 		static_cast<int32>(fLastIconMode));
380 	message.AddPoint(kViewStateListOriginName, fListOrigin);
381 	message.AddPoint(kViewStateIconOriginName, fIconOrigin);
382 	message.AddInt32(kViewStatePrimarySortAttrName,
383 		static_cast<int32>(fPrimarySortAttr));
384 	message.AddInt32(kViewStatePrimarySortTypeName,
385 		static_cast<int32>(fPrimarySortType));
386 	message.AddInt32(kViewStateSecondarySortAttrName,
387 		static_cast<int32>(fSecondarySortAttr));
388 	message.AddInt32(kViewStateSecondarySortTypeName,
389 		static_cast<int32>(fSecondarySortType));
390 	message.AddBool(kViewStateReverseSortName, fReverseSort);
391 	message.AddInt32(kViewStateIconSizeName, static_cast<int32>(fIconSize));
392 	message.AddInt32(kViewStateLastIconSizeName,
393 		static_cast<int32>(fLastIconSize));
394 }
395 
396 
397 BViewState*
398 BViewState::InstantiateFromStream(BMallocIO* stream, bool endianSwap)
399 {
400 	// compare stream header in canonical form
401 	uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE);
402 	int32 version = kViewStateArchiveVersion;
403 
404 	if (endianSwap) {
405 		key = SwapUInt32(key);
406 		version = SwapInt32(version);
407 	}
408 
409 	if (!ValidateStream(stream, key, version))
410 		return NULL;
411 
412 	return _Sanitize(new (std::nothrow) BViewState(stream, endianSwap));
413 }
414 
415 
416 BViewState*
417 BViewState::InstantiateFromMessage(const BMessage &message)
418 {
419 	int32 version = kViewStateArchiveVersion;
420 
421 	int32 messageVersion;
422 	if (message.FindInt32(kViewStateVersionName, &messageVersion) != B_OK)
423 		return NULL;
424 
425 	if (version != messageVersion)
426 		return NULL;
427 
428 	return _Sanitize(new (std::nothrow) BViewState(message));
429 }
430 
431 
432 void
433 BViewState::_Init()
434 {
435 	fViewMode = kListMode;
436 	fLastIconMode = 0;
437 	fIconSize = 32;
438 	fLastIconSize = 32;
439 	fListOrigin.Set(0, 0);
440 	fIconOrigin.Set(0, 0);
441 	fPrimarySortAttr = AttrHashString(kAttrStatName, B_STRING_TYPE);
442 	fPrimarySortType = B_STRING_TYPE;
443 	fSecondarySortAttr = 0;
444 	fSecondarySortType = 0;
445 	fReverseSort = false;
446 }
447 
448 
449 void
450 BViewState::_StorePreviousState()
451 {
452 	fPreviousViewMode = fViewMode;
453 	fPreviousLastIconMode = fLastIconMode;
454 	fPreviousIconSize = fIconSize;
455 	fPreviousLastIconSize = fLastIconSize;
456 	fPreviousListOrigin = fListOrigin;
457 	fPreviousIconOrigin = fIconOrigin;
458 	fPreviousPrimarySortAttr = fPrimarySortAttr;
459 	fPreviousSecondarySortAttr = fSecondarySortAttr;
460 	fPreviousPrimarySortType = fPrimarySortType;
461 	fPreviousSecondarySortType = fSecondarySortType;
462 	fPreviousReverseSort = fReverseSort;
463 }
464 
465 
466 BViewState*
467 BViewState::_Sanitize(BViewState* state, bool fixOnly)
468 {
469 	if (state == NULL)
470 		return NULL;
471 
472 	if (state->fViewMode == kListMode) {
473 		if (state->fListOrigin.x < 0)
474 			state->fListOrigin.x = 0;
475 
476 		if (state->fListOrigin.y < 0)
477 			state->fListOrigin.y = 0;
478 	}
479 	if (state->fIconSize < 16)
480 		state->fIconSize = 16;
481 
482 	if (state->fIconSize > 128)
483 		state->fIconSize = 128;
484 
485 	if (state->fLastIconSize < 16)
486 		state->fLastIconSize = 16;
487 
488 	if (state->fLastIconSize > 128)
489 		state->fLastIconSize = 128;
490 
491 	if (fixOnly)
492 		return state;
493 
494 	// do a sanity check here
495 	if ((state->fViewMode != kListMode
496 			&& state->fViewMode != kIconMode
497 			&& state->fViewMode != kMiniIconMode
498 			&& state->fViewMode != 0)
499 		|| (state->fLastIconMode != kListMode
500 			&& state->fLastIconMode != kIconMode
501 			&& state->fLastIconMode != kMiniIconMode
502 			&& state->fLastIconMode != 0)) {
503 		PRINT(("Bad data instantiating ViewState, view mode %" B_PRIx32
504 			", lastIconMode %" B_PRIx32 "\n", state->fViewMode,
505 			state->fLastIconMode));
506 
507 		delete state;
508 		return NULL;
509 	}
510 #if DEBUG
511 // TODO: Whatever this is supposed to mean, fix it.
512 //	else if (endianSwap)
513 //		PRINT(("Instantiated foreign view state ok\n"));
514 #endif
515 
516 	return state;
517 }
518