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