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