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