xref: /haiku/src/kits/tracker/ViewState.cpp (revision 04b1c44b89086a9521bb478c8e99d024cef8f6a6)
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 	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 	_Init();
282 	_StorePreviousState();
283 }
284 
285 
286 BViewState::BViewState(BMallocIO* stream, bool endianSwap)
287 {
288 	_Init();
289 	stream->Read(&fViewMode, sizeof(uint32));
290 	stream->Read(&fLastIconMode, sizeof(uint32));
291 	stream->Read(&fListOrigin, sizeof(BPoint));
292 	stream->Read(&fIconOrigin, sizeof(BPoint));
293 	stream->Read(&fPrimarySortAttr, sizeof(uint32));
294 	stream->Read(&fPrimarySortType, sizeof(uint32));
295 	stream->Read(&fSecondarySortAttr, sizeof(uint32));
296 	stream->Read(&fSecondarySortType, sizeof(uint32));
297 	stream->Read(&fReverseSort, sizeof(bool));
298 	stream->Read(&fIconSize, sizeof(uint32));
299 	stream->Read(&fLastIconSize, sizeof(uint32));
300 
301 	if (endianSwap) {
302 		PRINT(("endian swapping view state\n"));
303 		fViewMode = B_SWAP_INT32(fViewMode);
304 		fLastIconMode = B_SWAP_INT32(fLastIconMode);
305 		fIconSize = B_SWAP_INT32(fIconSize);
306 		fLastIconSize = B_SWAP_INT32(fLastIconSize);
307 		swap_data(B_POINT_TYPE, &fListOrigin,
308 			sizeof(fListOrigin), B_SWAP_ALWAYS);
309 		swap_data(B_POINT_TYPE, &fIconOrigin,
310 			sizeof(fIconOrigin), B_SWAP_ALWAYS);
311 		fPrimarySortAttr = B_SWAP_INT32(fPrimarySortAttr);
312 		fSecondarySortAttr = B_SWAP_INT32(fSecondarySortAttr);
313 		fPrimarySortType = B_SWAP_INT32(fPrimarySortType);
314 		fSecondarySortType = B_SWAP_INT32(fSecondarySortType);
315 	}
316 
317 	_StorePreviousState();
318 	_Sanitize(this, true);
319 }
320 
321 
322 BViewState::BViewState(const BMessage &message)
323 {
324 	_Init();
325 	message.FindInt32(kViewStateViewModeName, (int32*)&fViewMode);
326 	message.FindInt32(kViewStateLastIconModeName, (int32*)&fLastIconMode);
327 	message.FindInt32(kViewStateLastIconSizeName,(int32*)&fLastIconSize);
328 	message.FindInt32(kViewStateIconSizeName, (int32*)&fIconSize);
329 	message.FindPoint(kViewStateListOriginName, &fListOrigin);
330 	message.FindPoint(kViewStateIconOriginName, &fIconOrigin);
331 	message.FindInt32(kViewStatePrimarySortAttrName,
332 		(int32*)&fPrimarySortAttr);
333 	message.FindInt32(kViewStatePrimarySortTypeName,
334 		(int32*)&fPrimarySortType);
335 	message.FindInt32(kViewStateSecondarySortAttrName,
336 		(int32*)&fSecondarySortAttr);
337 	message.FindInt32(kViewStateSecondarySortTypeName,
338 		(int32*)&fSecondarySortType);
339 	message.FindBool(kViewStateReverseSortName, &fReverseSort);
340 
341 	_StorePreviousState();
342 	_Sanitize(this, true);
343 }
344 
345 
346 void
347 BViewState::ArchiveToStream(BMallocIO* stream) const
348 {
349 	// write class identifier and verison info
350 	uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE);
351 	stream->Write(&key, sizeof(key));
352 	int32 version = kViewStateArchiveVersion;
353 	stream->Write(&version, sizeof(version));
354 
355 	stream->Write(&fViewMode, sizeof(uint32));
356 	stream->Write(&fLastIconMode, sizeof(uint32));
357 	stream->Write(&fListOrigin, sizeof(BPoint));
358 	stream->Write(&fIconOrigin, sizeof(BPoint));
359 	stream->Write(&fPrimarySortAttr, sizeof(uint32));
360 	stream->Write(&fPrimarySortType, sizeof(uint32));
361 	stream->Write(&fSecondarySortAttr, sizeof(uint32));
362 	stream->Write(&fSecondarySortType, sizeof(uint32));
363 	stream->Write(&fReverseSort, sizeof(bool));
364 	stream->Write(&fIconSize, sizeof(uint32));
365 	stream->Write(&fLastIconSize, sizeof(uint32));
366 }
367 
368 
369 void
370 BViewState::ArchiveToMessage(BMessage &message) const
371 {
372 	message.AddInt32(kViewStateVersionName, kViewStateArchiveVersion);
373 
374 	message.AddInt32(kViewStateViewModeName, static_cast<int32>(fViewMode));
375 	message.AddInt32(kViewStateLastIconModeName,
376 		static_cast<int32>(fLastIconMode));
377 	message.AddPoint(kViewStateListOriginName, fListOrigin);
378 	message.AddPoint(kViewStateIconOriginName, fIconOrigin);
379 	message.AddInt32(kViewStatePrimarySortAttrName,
380 		static_cast<int32>(fPrimarySortAttr));
381 	message.AddInt32(kViewStatePrimarySortTypeName,
382 		static_cast<int32>(fPrimarySortType));
383 	message.AddInt32(kViewStateSecondarySortAttrName,
384 		static_cast<int32>(fSecondarySortAttr));
385 	message.AddInt32(kViewStateSecondarySortTypeName,
386 		static_cast<int32>(fSecondarySortType));
387 	message.AddBool(kViewStateReverseSortName, fReverseSort);
388 	message.AddInt32(kViewStateIconSizeName, static_cast<int32>(fIconSize));
389 	message.AddInt32(kViewStateLastIconSizeName,
390 		static_cast<int32>(fLastIconSize));
391 }
392 
393 
394 BViewState*
395 BViewState::InstantiateFromStream(BMallocIO* stream, bool endianSwap)
396 {
397 	// compare stream header in canonical form
398 	uint32 key = AttrHashString("BViewState", B_OBJECT_TYPE);
399 	int32 version = kViewStateArchiveVersion;
400 
401 	if (endianSwap) {
402 		key = SwapUInt32(key);
403 		version = SwapInt32(version);
404 	}
405 
406 	if (!ValidateStream(stream, key, version))
407 		return NULL;
408 
409 	return _Sanitize(new (std::nothrow) BViewState(stream, endianSwap));
410 }
411 
412 
413 BViewState*
414 BViewState::InstantiateFromMessage(const BMessage &message)
415 {
416 	int32 version = kViewStateArchiveVersion;
417 
418 	int32 messageVersion;
419 	if (message.FindInt32(kViewStateVersionName, &messageVersion) != B_OK)
420 		return NULL;
421 
422 	if (version != messageVersion)
423 		return NULL;
424 
425 	return _Sanitize(new (std::nothrow) BViewState(message));
426 }
427 
428 
429 void
430 BViewState::_Init()
431 {
432 	fViewMode = kListMode;
433 	fLastIconMode = 0;
434 	fIconSize = 32;
435 	fLastIconSize = 32;
436 	fListOrigin.Set(0, 0);
437 	fIconOrigin.Set(0, 0);
438 	fPrimarySortAttr = AttrHashString(kAttrStatName, B_STRING_TYPE);
439 	fPrimarySortType = B_STRING_TYPE;
440 	fSecondarySortAttr = 0;
441 	fSecondarySortType = 0;
442 	fReverseSort = false;
443 }
444 
445 
446 void
447 BViewState::_StorePreviousState()
448 {
449 	fPreviousViewMode = fViewMode;
450 	fPreviousLastIconMode = fLastIconMode;
451 	fPreviousIconSize = fIconSize;
452 	fPreviousLastIconSize = fLastIconSize;
453 	fPreviousListOrigin = fListOrigin;
454 	fPreviousIconOrigin = fIconOrigin;
455 	fPreviousPrimarySortAttr = fPrimarySortAttr;
456 	fPreviousSecondarySortAttr = fSecondarySortAttr;
457 	fPreviousPrimarySortType = fPrimarySortType;
458 	fPreviousSecondarySortType = fSecondarySortType;
459 	fPreviousReverseSort = fReverseSort;
460 }
461 
462 
463 BViewState*
464 BViewState::_Sanitize(BViewState* state, bool fixOnly)
465 {
466 	if (state == NULL)
467 		return NULL;
468 
469 	if (state->fViewMode == kListMode) {
470 		if (state->fListOrigin.x < 0)
471 			state->fListOrigin.x = 0;
472 		if (state->fListOrigin.y < 0)
473 			state->fListOrigin.y = 0;
474 	}
475 	if (state->fIconSize < 16)
476 		state->fIconSize = 16;
477 	if (state->fIconSize > 128)
478 		state->fIconSize = 128;
479 	if (state->fLastIconSize < 16)
480 		state->fLastIconSize = 16;
481 	if (state->fLastIconSize > 128)
482 		state->fLastIconSize = 128;
483 
484 	if (fixOnly)
485 		return state;
486 
487 	// do a sanity check here
488 	if ((state->fViewMode != kListMode
489 			&& state->fViewMode != kIconMode
490 			&& state->fViewMode != kMiniIconMode
491 			&& state->fViewMode != 0)
492 		|| (state->fLastIconMode != kListMode
493 			&& state->fLastIconMode != kIconMode
494 			&& state->fLastIconMode != kMiniIconMode
495 			&& state->fLastIconMode != 0)) {
496 		PRINT(("Bad data instantiating ViewState, view mode %" B_PRIx32
497 			", lastIconMode %" B_PRIx32 "\n", state->fViewMode,
498 			state->fLastIconMode));
499 
500 		delete state;
501 		return NULL;
502 	}
503 #if DEBUG
504 // TODO: Whatever this is supposed to mean, fix it.
505 //	else if (endianSwap)
506 //		PRINT(("Instantiated foreign view state ok\n"));
507 #endif
508 
509 	return state;
510 }
511