xref: /haiku/src/kits/interface/View.cpp (revision 2b0aa4245bc5e6b0a38dbb0fb31ccb56794d13ff)
1 /*
2  * Copyright 2001-2019 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus, superstippi@gmx.de
7  *		Axel Dörfler, axeld@pinc-software.de
8  *		Adrian Oanca, adioanca@cotty.iren.ro
9  *		Ingo Weinhold. ingo_weinhold@gmx.de
10  *		Julian Harnath, julian.harnath@rwth-aachen.de
11  *		Joseph Groover, looncraz@looncraz.net
12  */
13 
14 
15 #include <View.h>
16 
17 #include <algorithm>
18 #include <new>
19 
20 #include <math.h>
21 #include <stdio.h>
22 
23 #include <Application.h>
24 #include <Bitmap.h>
25 #include <Button.h>
26 #include <Cursor.h>
27 #include <File.h>
28 #include <GradientLinear.h>
29 #include <GradientRadial.h>
30 #include <GradientRadialFocus.h>
31 #include <GradientDiamond.h>
32 #include <GradientConic.h>
33 #include <InterfaceDefs.h>
34 #include <Layout.h>
35 #include <LayoutContext.h>
36 #include <LayoutUtils.h>
37 #include <MenuBar.h>
38 #include <Message.h>
39 #include <MessageQueue.h>
40 #include <ObjectList.h>
41 #include <Picture.h>
42 #include <Point.h>
43 #include <Polygon.h>
44 #include <PropertyInfo.h>
45 #include <Region.h>
46 #include <ScrollBar.h>
47 #include <Shape.h>
48 #include <Shelf.h>
49 #include <String.h>
50 #include <Window.h>
51 
52 #include <AppMisc.h>
53 #include <AppServerLink.h>
54 #include <binary_compatibility/Interface.h>
55 #include <binary_compatibility/Support.h>
56 #include <MessagePrivate.h>
57 #include <MessageUtils.h>
58 #include <PortLink.h>
59 #include <ServerProtocol.h>
60 #include <ServerProtocolStructs.h>
61 #include <ShapePrivate.h>
62 #include <ToolTip.h>
63 #include <ToolTipManager.h>
64 #include <TokenSpace.h>
65 #include <ViewPrivate.h>
66 
67 using std::nothrow;
68 
69 //#define DEBUG_BVIEW
70 #ifdef DEBUG_BVIEW
71 #	include <stdio.h>
72 #	define STRACE(x) printf x
73 #	define BVTRACE _PrintToStream()
74 #else
75 #	define STRACE(x) ;
76 #	define BVTRACE ;
77 #endif
78 
79 
80 static property_info sViewPropInfo[] = {
81 	{ "Frame", { B_GET_PROPERTY, B_SET_PROPERTY },
82 		{ B_DIRECT_SPECIFIER, 0 }, "The view's frame rectangle.", 0,
83 		{ B_RECT_TYPE }
84 	},
85 	{ "Hidden", { B_GET_PROPERTY, B_SET_PROPERTY },
86 		{ B_DIRECT_SPECIFIER, 0 }, "Whether or not the view is hidden.",
87 		0, { B_BOOL_TYPE }
88 	},
89 	{ "Shelf", { 0 },
90 		{ B_DIRECT_SPECIFIER, 0 }, "Directs the scripting message to the "
91 			"shelf.", 0
92 	},
93 	{ "View", { B_COUNT_PROPERTIES, 0 },
94 		{ B_DIRECT_SPECIFIER, 0 }, "Returns the number of child views.", 0,
95 		{ B_INT32_TYPE }
96 	},
97 	{ "View", { 0 },
98 		{ B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, B_NAME_SPECIFIER, 0 },
99 		"Directs the scripting message to the specified view.", 0
100 	},
101 
102 	{ 0 }
103 };
104 
105 
106 //	#pragma mark -
107 
108 
109 static inline uint32
get_uint32_color(rgb_color color)110 get_uint32_color(rgb_color color)
111 {
112 	return B_BENDIAN_TO_HOST_INT32(*(uint32*)&color);
113 		// rgb_color is always in rgba format, no matter what endian;
114 		// we always return the int32 value in host endian.
115 }
116 
117 
118 static inline rgb_color
get_rgb_color(uint32 value)119 get_rgb_color(uint32 value)
120 {
121 	value = B_HOST_TO_BENDIAN_INT32(value);
122 	return *(rgb_color*)&value;
123 }
124 
125 
126 //	#pragma mark -
127 
128 
129 namespace BPrivate {
130 
ViewState()131 ViewState::ViewState()
132 {
133 	pen_location.Set(0, 0);
134 	pen_size = 1.0;
135 
136 	// NOTE: the clipping_region is empty
137 	// on construction but it is not used yet,
138 	// we avoid having to keep track of it via
139 	// this flag
140 	clipping_region_used = false;
141 
142 	high_color = (rgb_color){ 0, 0, 0, 255 };
143 	low_color = (rgb_color){ 255, 255, 255, 255 };
144 	view_color = low_color;
145 	which_view_color = B_NO_COLOR;
146 	which_view_color_tint = B_NO_TINT;
147 
148 	which_high_color = B_NO_COLOR;
149 	which_high_color_tint = B_NO_TINT;
150 
151 	which_low_color = B_NO_COLOR;
152 	which_low_color_tint = B_NO_TINT;
153 
154 	pattern = B_SOLID_HIGH;
155 	drawing_mode = B_OP_COPY;
156 
157 	origin.Set(0, 0);
158 
159 	line_join = B_MITER_JOIN;
160 	line_cap = B_BUTT_CAP;
161 	miter_limit = B_DEFAULT_MITER_LIMIT;
162 	fill_rule = B_NONZERO;
163 
164 	alpha_source_mode = B_PIXEL_ALPHA;
165 	alpha_function_mode = B_ALPHA_OVERLAY;
166 
167 	scale = 1.0;
168 
169 	font = *be_plain_font;
170 	font_flags = font.Flags();
171 	font_aliasing = false;
172 
173 	parent_composite_transform.Reset();
174 	parent_composite_scale = 1.0f;
175 	parent_composite_origin.Set(0, 0);
176 
177 	// We only keep the B_VIEW_CLIP_REGION_BIT flag invalidated,
178 	// because we should get the clipping region from app_server.
179 	// The other flags do not need to be included because the data they
180 	// represent is already in sync with app_server - app_server uses the
181 	// same init (default) values.
182 	valid_flags = ~B_VIEW_CLIP_REGION_BIT;
183 
184 	archiving_flags = B_VIEW_FRAME_BIT | B_VIEW_RESIZE_BIT;
185 }
186 
187 
188 void
UpdateServerFontState(BPrivate::PortLink & link)189 ViewState::UpdateServerFontState(BPrivate::PortLink &link)
190 {
191 	link.StartMessage(AS_VIEW_SET_FONT_STATE);
192 	link.Attach<uint16>(font_flags);
193 		// always present
194 
195 	if (font_flags & B_FONT_FAMILY_AND_STYLE)
196 		link.Attach<uint32>(font.FamilyAndStyle());
197 
198 	if (font_flags & B_FONT_SIZE)
199 		link.Attach<float>(font.Size());
200 
201 	if (font_flags & B_FONT_SHEAR)
202 		link.Attach<float>(font.Shear());
203 
204 	if (font_flags & B_FONT_ROTATION)
205 		link.Attach<float>(font.Rotation());
206 
207 	if (font_flags & B_FONT_FALSE_BOLD_WIDTH)
208 		link.Attach<float>(font.FalseBoldWidth());
209 
210 	if (font_flags & B_FONT_SPACING)
211 		link.Attach<uint8>(font.Spacing());
212 
213 	if (font_flags & B_FONT_ENCODING)
214 		link.Attach<uint8>(font.Encoding());
215 
216 	if (font_flags & B_FONT_FACE)
217 		link.Attach<uint16>(font.Face());
218 
219 	if (font_flags & B_FONT_FLAGS)
220 		link.Attach<uint32>(font.Flags());
221 }
222 
223 
224 void
UpdateServerState(BPrivate::PortLink & link)225 ViewState::UpdateServerState(BPrivate::PortLink &link)
226 {
227 	UpdateServerFontState(link);
228 
229 	link.StartMessage(AS_VIEW_SET_STATE);
230 
231 	ViewSetStateInfo info;
232 	info.penLocation = pen_location;
233 	info.penSize = pen_size;
234 	info.highColor = high_color;
235 	info.lowColor = low_color;
236 	info.whichHighColor = which_high_color;
237 	info.whichLowColor = which_low_color;
238 	info.whichHighColorTint = which_high_color_tint;
239 	info.whichLowColorTint = which_low_color_tint;
240 	info.pattern = pattern;
241 	info.drawingMode = drawing_mode;
242 	info.origin = origin;
243 	info.scale = scale;
244 	info.lineJoin = line_join;
245 	info.lineCap = line_cap;
246 	info.miterLimit = miter_limit;
247 	info.fillRule = fill_rule;
248 	info.alphaSourceMode = alpha_source_mode;
249 	info.alphaFunctionMode = alpha_function_mode;
250 	info.fontAntialiasing = font_aliasing;
251 	link.Attach<ViewSetStateInfo>(info);
252 
253 	// BAffineTransform is transmitted as a double array
254 	double _transform[6];
255 	if (transform.Flatten(_transform, sizeof(_transform)) != B_OK)
256 		return;
257 	link.Attach<double[6]>(_transform);
258 
259 	// we send the 'local' clipping region... if we have one...
260 	// TODO: Could be optimized, but is low prio, since most views won't
261 	// have a custom clipping region.
262 	if (clipping_region_used) {
263 		int32 count = clipping_region.CountRects();
264 		link.Attach<int32>(count);
265 		for (int32 i = 0; i < count; i++)
266 			link.Attach<BRect>(clipping_region.RectAt(i));
267 	} else {
268 		// no clipping region
269 		link.Attach<int32>(-1);
270 	}
271 
272 	// Although we might have a 'local' clipping region, when we call
273 	// BView::GetClippingRegion() we ask for the 'global' one and it
274 	// is kept on server, so we must invalidate B_VIEW_CLIP_REGION_BIT flag
275 
276 	valid_flags = ~B_VIEW_CLIP_REGION_BIT;
277 }
278 
279 
280 void
UpdateFrom(BPrivate::PortLink & link)281 ViewState::UpdateFrom(BPrivate::PortLink &link)
282 {
283 	link.StartMessage(AS_VIEW_GET_STATE);
284 
285 	int32 code;
286 	if (link.FlushWithReply(code) != B_OK
287 		|| code != B_OK)
288 		return;
289 
290 	ViewGetStateInfo info;
291 	link.Read<ViewGetStateInfo>(&info);
292 
293 	// set view's font state
294 	font_flags = B_FONT_ALL;
295 	font.SetFamilyAndStyle(info.fontID);
296 	font.SetSize(info.fontSize);
297 	font.SetShear(info.fontShear);
298 	font.SetRotation(info.fontRotation);
299 	font.SetFalseBoldWidth(info.fontFalseBoldWidth);
300 	font.SetSpacing(info.fontSpacing);
301 	font.SetEncoding(info.fontEncoding);
302 	font.SetFace(info.fontFace);
303 	font.SetFlags(info.fontFlags);
304 
305 	// set view's state
306 	pen_location = info.viewStateInfo.penLocation;
307 	pen_size = info.viewStateInfo.penSize;
308 	high_color = info.viewStateInfo.highColor;
309 	low_color = info.viewStateInfo.lowColor;
310 	pattern = info.viewStateInfo.pattern;
311 	drawing_mode = info.viewStateInfo.drawingMode;
312 	origin = info.viewStateInfo.origin;
313 	scale = info.viewStateInfo.scale;
314 	line_join = info.viewStateInfo.lineJoin;
315 	line_cap = info.viewStateInfo.lineCap;
316 	miter_limit = info.viewStateInfo.miterLimit;
317 	fill_rule = info.viewStateInfo.fillRule;
318 	alpha_source_mode = info.viewStateInfo.alphaSourceMode;
319 	alpha_function_mode = info.viewStateInfo.alphaFunctionMode;
320 	font_aliasing = info.viewStateInfo.fontAntialiasing;
321 
322 	// BAffineTransform is transmitted as a double array
323 	double _transform[6];
324 	link.Read<double[6]>(&_transform);
325 	if (transform.Unflatten(B_AFFINE_TRANSFORM_TYPE, _transform,
326 		sizeof(_transform)) != B_OK) {
327 		return;
328 	}
329 
330 	// read the user clipping
331 	// (that's NOT the current View visible clipping but the additional
332 	// user specified clipping!)
333 	int32 clippingRectCount;
334 	link.Read<int32>(&clippingRectCount);
335 	if (clippingRectCount >= 0) {
336 		clipping_region.MakeEmpty();
337 		for (int32 i = 0; i < clippingRectCount; i++) {
338 			BRect rect;
339 			link.Read<BRect>(&rect);
340 			clipping_region.Include(rect);
341 		}
342 	} else {
343 		// no user clipping used
344 		clipping_region_used = false;
345 	}
346 
347 	valid_flags = ~(B_VIEW_CLIP_REGION_BIT | B_VIEW_PARENT_COMPOSITE_BIT)
348 		| (valid_flags & B_VIEW_PARENT_COMPOSITE_BIT);
349 }
350 
351 }	// namespace BPrivate
352 
353 
354 //	#pragma mark -
355 
356 
357 // archiving constants
358 namespace {
359 	const char* const kSizesField = "BView:sizes";
360 		// kSizesField = {min, max, pref}
361 	const char* const kAlignmentField = "BView:alignment";
362 	const char* const kLayoutField = "BView:layout";
363 }
364 
365 
366 struct BView::LayoutData {
LayoutDataBView::LayoutData367 	LayoutData()
368 		:
369 		fMinSize(),
370 		fMaxSize(),
371 		fPreferredSize(),
372 		fAlignment(),
373 		fLayoutInvalidationDisabled(0),
374 		fLayout(NULL),
375 		fLayoutContext(NULL),
376 		fLayoutItems(5, false),
377 		fLayoutValid(true),		// TODO: Rethink these initial values!
378 		fMinMaxValid(true),		//
379 		fLayoutInProgress(false),
380 		fNeedsRelayout(true)
381 	{
382 	}
383 
384 	status_t
AddDataToArchiveBView::LayoutData385 	AddDataToArchive(BMessage* archive)
386 	{
387 		status_t err = archive->AddSize(kSizesField, fMinSize);
388 
389 		if (err == B_OK)
390 			err = archive->AddSize(kSizesField, fMaxSize);
391 
392 		if (err == B_OK)
393 			err = archive->AddSize(kSizesField, fPreferredSize);
394 
395 		if (err == B_OK)
396 			err = archive->AddAlignment(kAlignmentField, fAlignment);
397 
398 		return err;
399 	}
400 
401 	void
PopulateFromArchiveBView::LayoutData402 	PopulateFromArchive(BMessage* archive)
403 	{
404 		archive->FindSize(kSizesField, 0, &fMinSize);
405 		archive->FindSize(kSizesField, 1, &fMaxSize);
406 		archive->FindSize(kSizesField, 2, &fPreferredSize);
407 		archive->FindAlignment(kAlignmentField, &fAlignment);
408 	}
409 
410 	BSize			fMinSize;
411 	BSize			fMaxSize;
412 	BSize			fPreferredSize;
413 	BAlignment		fAlignment;
414 	int				fLayoutInvalidationDisabled;
415 	BLayout*		fLayout;
416 	BLayoutContext*	fLayoutContext;
417 	BObjectList<BLayoutItem> fLayoutItems;
418 	bool			fLayoutValid;
419 	bool			fMinMaxValid;
420 	bool			fLayoutInProgress;
421 	bool			fNeedsRelayout;
422 };
423 
424 
BView(const char * name,uint32 flags,BLayout * layout)425 BView::BView(const char* name, uint32 flags, BLayout* layout)
426 	:
427 	BHandler(name)
428 {
429 	_InitData(BRect(0, 0, -1, -1), name, B_FOLLOW_NONE,
430 		flags | B_SUPPORTS_LAYOUT);
431 	SetLayout(layout);
432 }
433 
434 
BView(BRect frame,const char * name,uint32 resizingMode,uint32 flags)435 BView::BView(BRect frame, const char* name, uint32 resizingMode, uint32 flags)
436 	:
437 	BHandler(name)
438 {
439 	_InitData(frame, name, resizingMode, flags);
440 }
441 
442 
BView(BMessage * archive)443 BView::BView(BMessage* archive)
444 	:
445 	BHandler(BUnarchiver::PrepareArchive(archive))
446 {
447 	BUnarchiver unarchiver(archive);
448 	if (!archive)
449 		debugger("BView cannot be constructed from a NULL archive.");
450 
451 	BRect frame;
452 	archive->FindRect("_frame", &frame);
453 
454 	uint32 resizingMode;
455 	if (archive->FindInt32("_resize_mode", (int32*)&resizingMode) != B_OK)
456 		resizingMode = 0;
457 
458 	uint32 flags;
459 	if (archive->FindInt32("_flags", (int32*)&flags) != B_OK)
460 		flags = 0;
461 
462 	_InitData(frame, Name(), resizingMode, flags);
463 
464 	font_family family;
465 	font_style style;
466 	if (archive->FindString("_fname", 0, (const char**)&family) == B_OK
467 		&& archive->FindString("_fname", 1, (const char**)&style) == B_OK) {
468 		BFont font;
469 		font.SetFamilyAndStyle(family, style);
470 
471 		float size;
472 		if (archive->FindFloat("_fflt", 0, &size) == B_OK)
473 			font.SetSize(size);
474 
475 		float shear;
476 		if (archive->FindFloat("_fflt", 1, &shear) == B_OK
477 			&& shear >= 45.0 && shear <= 135.0)
478 			font.SetShear(shear);
479 
480 		float rotation;
481 		if (archive->FindFloat("_fflt", 2, &rotation) == B_OK
482 			&& rotation >=0 && rotation <= 360)
483 			font.SetRotation(rotation);
484 
485 		SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE
486 			| B_FONT_SHEAR | B_FONT_ROTATION);
487 	}
488 
489 	int32 color = 0;
490 	if (archive->FindInt32("_color", 0, &color) == B_OK)
491 		SetHighColor(get_rgb_color(color));
492 	if (archive->FindInt32("_color", 1, &color) == B_OK)
493 		SetLowColor(get_rgb_color(color));
494 	if (archive->FindInt32("_color", 2, &color) == B_OK)
495 		SetViewColor(get_rgb_color(color));
496 
497 	float tint = B_NO_TINT;
498 	if (archive->FindInt32("_uicolor", 0, &color) == B_OK
499 		&& color != B_NO_COLOR) {
500 		if (archive->FindFloat("_uitint", 0, &tint) != B_OK)
501 			tint = B_NO_TINT;
502 
503 		SetHighUIColor((color_which)color, tint);
504 	}
505 	if (archive->FindInt32("_uicolor", 1, &color) == B_OK
506 		&& color != B_NO_COLOR) {
507 		if (archive->FindFloat("_uitint", 1, &tint) != B_OK)
508 			tint = B_NO_TINT;
509 
510 		SetLowUIColor((color_which)color, tint);
511 	}
512 	if (archive->FindInt32("_uicolor", 2, &color) == B_OK
513 		&& color != B_NO_COLOR) {
514 		if (archive->FindFloat("_uitint", 2, &tint) != B_OK)
515 			tint = B_NO_TINT;
516 
517 		SetViewUIColor((color_which)color, tint);
518 	}
519 
520 	uint32 evMask;
521 	uint32 options;
522 	if (archive->FindInt32("_evmask", 0, (int32*)&evMask) == B_OK
523 		&& archive->FindInt32("_evmask", 1, (int32*)&options) == B_OK)
524 		SetEventMask(evMask, options);
525 
526 	BPoint origin;
527 	if (archive->FindPoint("_origin", &origin) == B_OK)
528 		SetOrigin(origin);
529 
530 	float scale;
531 	if (archive->FindFloat("_scale", &scale) == B_OK)
532 		SetScale(scale);
533 
534 	BAffineTransform transform;
535 	if (archive->FindFlat("_transform", &transform) == B_OK)
536 		SetTransform(transform);
537 
538 	float penSize;
539 	if (archive->FindFloat("_psize", &penSize) == B_OK)
540 		SetPenSize(penSize);
541 
542 	BPoint penLocation;
543 	if (archive->FindPoint("_ploc", &penLocation) == B_OK)
544 		MovePenTo(penLocation);
545 
546 	int16 lineCap;
547 	int16 lineJoin;
548 	float lineMiter;
549 	if (archive->FindInt16("_lmcapjoin", 0, &lineCap) == B_OK
550 		&& archive->FindInt16("_lmcapjoin", 1, &lineJoin) == B_OK
551 		&& archive->FindFloat("_lmmiter", &lineMiter) == B_OK)
552 		SetLineMode((cap_mode)lineCap, (join_mode)lineJoin, lineMiter);
553 
554 	int16 fillRule;
555 	if (archive->FindInt16("_fillrule", &fillRule) == B_OK)
556 		SetFillRule(fillRule);
557 
558 	int16 alphaBlend;
559 	int16 modeBlend;
560 	if (archive->FindInt16("_blend", 0, &alphaBlend) == B_OK
561 		&& archive->FindInt16("_blend", 1, &modeBlend) == B_OK)
562 		SetBlendingMode( (source_alpha)alphaBlend, (alpha_function)modeBlend);
563 
564 	uint32 drawingMode;
565 	if (archive->FindInt32("_dmod", (int32*)&drawingMode) == B_OK)
566 		SetDrawingMode((drawing_mode)drawingMode);
567 
568 	fLayoutData->PopulateFromArchive(archive);
569 
570 	if (archive->FindInt16("_show", &fShowLevel) != B_OK)
571 		fShowLevel = 0;
572 
573 	if (BUnarchiver::IsArchiveManaged(archive)) {
574 		int32 i = 0;
575 		while (unarchiver.EnsureUnarchived("_views", i++) == B_OK)
576 				;
577 		unarchiver.EnsureUnarchived(kLayoutField);
578 
579 	} else {
580 		BMessage msg;
581 		for (int32 i = 0; archive->FindMessage("_views", i, &msg) == B_OK;
582 			i++) {
583 			BArchivable* object = instantiate_object(&msg);
584 			if (BView* child = dynamic_cast<BView*>(object))
585 				AddChild(child);
586 		}
587 	}
588 }
589 
590 
591 BArchivable*
Instantiate(BMessage * data)592 BView::Instantiate(BMessage* data)
593 {
594 	if (!validate_instantiation(data , "BView"))
595 		return NULL;
596 
597 	return new(std::nothrow) BView(data);
598 }
599 
600 
601 status_t
Archive(BMessage * data,bool deep) const602 BView::Archive(BMessage* data, bool deep) const
603 {
604 	BArchiver archiver(data);
605 	status_t ret = BHandler::Archive(data, deep);
606 
607 	if (ret != B_OK)
608 		return ret;
609 
610 	if ((fState->archiving_flags & B_VIEW_FRAME_BIT) != 0)
611 		ret = data->AddRect("_frame", Bounds().OffsetToCopy(fParentOffset));
612 
613 	if (ret == B_OK)
614 		ret = data->AddInt32("_resize_mode", ResizingMode());
615 
616 	if (ret == B_OK)
617 		ret = data->AddInt32("_flags", Flags());
618 
619 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_EVENT_MASK_BIT) != 0) {
620 		ret = data->AddInt32("_evmask", fEventMask);
621 		if (ret == B_OK)
622 			ret = data->AddInt32("_evmask", fEventOptions);
623 	}
624 
625 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_FONT_BIT) != 0) {
626 		BFont font;
627 		GetFont(&font);
628 
629 		font_family family;
630 		font_style style;
631 		font.GetFamilyAndStyle(&family, &style);
632 		ret = data->AddString("_fname", family);
633 		if (ret == B_OK)
634 			ret = data->AddString("_fname", style);
635 		if (ret == B_OK)
636 			ret = data->AddFloat("_fflt", font.Size());
637 		if (ret == B_OK)
638 			ret = data->AddFloat("_fflt", font.Shear());
639 		if (ret == B_OK)
640 			ret = data->AddFloat("_fflt", font.Rotation());
641 	}
642 
643 	// colors
644 	if (ret == B_OK)
645 		ret = data->AddInt32("_color", get_uint32_color(HighColor()));
646 	if (ret == B_OK)
647 		ret = data->AddInt32("_color", get_uint32_color(LowColor()));
648 	if (ret == B_OK)
649 		ret = data->AddInt32("_color", get_uint32_color(ViewColor()));
650 
651 	if (ret == B_OK)
652 		ret = data->AddInt32("_uicolor", (int32)HighUIColor());
653 	if (ret == B_OK)
654 		ret = data->AddInt32("_uicolor", (int32)LowUIColor());
655 	if (ret == B_OK)
656 		ret = data->AddInt32("_uicolor", (int32)ViewUIColor());
657 
658 	if (ret == B_OK)
659 		ret = data->AddFloat("_uitint", fState->which_high_color_tint);
660 	if (ret == B_OK)
661 		ret = data->AddFloat("_uitint", fState->which_low_color_tint);
662 	if (ret == B_OK)
663 		ret = data->AddFloat("_uitint", fState->which_view_color_tint);
664 
665 //	NOTE: we do not use this flag any more
666 //	if ( 1 ){
667 //		ret = data->AddInt32("_dbuf", 1);
668 //	}
669 
670 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_ORIGIN_BIT) != 0)
671 		ret = data->AddPoint("_origin", Origin());
672 
673 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_SCALE_BIT) != 0)
674 		ret = data->AddFloat("_scale", Scale());
675 
676 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_TRANSFORM_BIT) != 0) {
677 		BAffineTransform transform = Transform();
678 		ret = data->AddFlat("_transform", &transform);
679 	}
680 
681 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_PEN_SIZE_BIT) != 0)
682 		ret = data->AddFloat("_psize", PenSize());
683 
684 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_PEN_LOCATION_BIT) != 0)
685 		ret = data->AddPoint("_ploc", PenLocation());
686 
687 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_LINE_MODES_BIT) != 0) {
688 		ret = data->AddInt16("_lmcapjoin", (int16)LineCapMode());
689 		if (ret == B_OK)
690 			ret = data->AddInt16("_lmcapjoin", (int16)LineJoinMode());
691 		if (ret == B_OK)
692 			ret = data->AddFloat("_lmmiter", LineMiterLimit());
693 	}
694 
695 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_FILL_RULE_BIT) != 0)
696 		ret = data->AddInt16("_fillrule", (int16)FillRule());
697 
698 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_BLENDING_BIT) != 0) {
699 		source_alpha alphaSourceMode;
700 		alpha_function alphaFunctionMode;
701 		GetBlendingMode(&alphaSourceMode, &alphaFunctionMode);
702 
703 		ret = data->AddInt16("_blend", (int16)alphaSourceMode);
704 		if (ret == B_OK)
705 			ret = data->AddInt16("_blend", (int16)alphaFunctionMode);
706 	}
707 
708 	if (ret == B_OK && (fState->archiving_flags & B_VIEW_DRAWING_MODE_BIT) != 0)
709 		ret = data->AddInt32("_dmod", DrawingMode());
710 
711 	if (ret == B_OK)
712 		ret = fLayoutData->AddDataToArchive(data);
713 
714 	if (ret == B_OK)
715 		ret = data->AddInt16("_show", fShowLevel);
716 
717 	if (deep && ret == B_OK) {
718 		for (BView* child = fFirstChild; child != NULL && ret == B_OK;
719 			child = child->fNextSibling)
720 			ret = archiver.AddArchivable("_views", child, deep);
721 
722 		if (ret == B_OK)
723 			ret = archiver.AddArchivable(kLayoutField, GetLayout(), deep);
724 	}
725 
726 	return archiver.Finish(ret);
727 }
728 
729 
730 status_t
AllUnarchived(const BMessage * from)731 BView::AllUnarchived(const BMessage* from)
732 {
733 	BUnarchiver unarchiver(from);
734 	status_t err = B_OK;
735 
736 	int32 count;
737 	from->GetInfo("_views", NULL, &count);
738 
739 	for (int32 i = 0; err == B_OK && i < count; i++) {
740 		BView* child;
741 		err = unarchiver.FindObject<BView>("_views", i, child);
742 		if (err == B_OK)
743 			err = _AddChild(child, NULL) ? B_OK : B_ERROR;
744 	}
745 
746 	if (err == B_OK) {
747 		BLayout*& layout = fLayoutData->fLayout;
748 		err = unarchiver.FindObject(kLayoutField, layout);
749 		if (err == B_OK && layout) {
750 			fFlags |= B_SUPPORTS_LAYOUT;
751 			fLayoutData->fLayout->SetOwner(this);
752 		}
753 	}
754 
755 	return err;
756 }
757 
758 
759 status_t
AllArchived(BMessage * into) const760 BView::AllArchived(BMessage* into) const
761 {
762 	return BHandler::AllArchived(into);
763 }
764 
765 
~BView()766 BView::~BView()
767 {
768 	STRACE(("BView(%s)::~BView()\n", this->Name()));
769 
770 	if (fOwner != NULL) {
771 		debugger("Trying to delete a view that belongs to a window. "
772 			"Call RemoveSelf first.");
773 	}
774 
775 	// we also delete all our children
776 
777 	BView* child = fFirstChild;
778 	while (child) {
779 		BView* nextChild = child->fNextSibling;
780 
781 		delete child;
782 		child = nextChild;
783 	}
784 
785 	SetLayout(NULL);
786 	_RemoveLayoutItemsFromLayout(true);
787 
788 	delete fLayoutData;
789 
790 	_RemoveSelf();
791 
792 	if (fToolTip != NULL)
793 		fToolTip->ReleaseReference();
794 
795 	if (fVerScroller != NULL)
796 		fVerScroller->SetTarget((BView*)NULL);
797 	if (fHorScroller != NULL)
798 		fHorScroller->SetTarget((BView*)NULL);
799 
800 	SetName(NULL);
801 
802 	_RemoveCommArray();
803 	delete fState;
804 }
805 
806 
807 BRect
Bounds() const808 BView::Bounds() const
809 {
810 	_CheckLock();
811 
812 	if (fIsPrinting)
813 		return fState->print_rect;
814 
815 	return fBounds;
816 }
817 
818 
819 void
_ConvertToParent(BPoint * point,bool checkLock) const820 BView::_ConvertToParent(BPoint* point, bool checkLock) const
821 {
822 	if (!fParent)
823 		return;
824 
825 	if (checkLock)
826 		_CheckLock();
827 
828 	// - our scrolling offset
829 	// + our bounds location within the parent
830 	point->x += -fBounds.left + fParentOffset.x;
831 	point->y += -fBounds.top + fParentOffset.y;
832 }
833 
834 
835 void
ConvertToParent(BPoint * point) const836 BView::ConvertToParent(BPoint* point) const
837 {
838 	_ConvertToParent(point, true);
839 }
840 
841 
842 BPoint
ConvertToParent(BPoint point) const843 BView::ConvertToParent(BPoint point) const
844 {
845 	ConvertToParent(&point);
846 
847 	return point;
848 }
849 
850 
851 void
_ConvertFromParent(BPoint * point,bool checkLock) const852 BView::_ConvertFromParent(BPoint* point, bool checkLock) const
853 {
854 	if (!fParent)
855 		return;
856 
857 	if (checkLock)
858 		_CheckLock();
859 
860 	// - our bounds location within the parent
861 	// + our scrolling offset
862 	point->x += -fParentOffset.x + fBounds.left;
863 	point->y += -fParentOffset.y + fBounds.top;
864 }
865 
866 
867 void
ConvertFromParent(BPoint * point) const868 BView::ConvertFromParent(BPoint* point) const
869 {
870 	_ConvertFromParent(point, true);
871 }
872 
873 
874 BPoint
ConvertFromParent(BPoint point) const875 BView::ConvertFromParent(BPoint point) const
876 {
877 	ConvertFromParent(&point);
878 
879 	return point;
880 }
881 
882 
883 void
ConvertToParent(BRect * rect) const884 BView::ConvertToParent(BRect* rect) const
885 {
886 	if (!fParent)
887 		return;
888 
889 	_CheckLock();
890 
891 	// - our scrolling offset
892 	// + our bounds location within the parent
893 	rect->OffsetBy(-fBounds.left + fParentOffset.x,
894 		-fBounds.top + fParentOffset.y);
895 }
896 
897 
898 BRect
ConvertToParent(BRect rect) const899 BView::ConvertToParent(BRect rect) const
900 {
901 	ConvertToParent(&rect);
902 
903 	return rect;
904 }
905 
906 
907 void
ConvertFromParent(BRect * rect) const908 BView::ConvertFromParent(BRect* rect) const
909 {
910 	if (!fParent)
911 		return;
912 
913 	_CheckLock();
914 
915 	// - our bounds location within the parent
916 	// + our scrolling offset
917 	rect->OffsetBy(-fParentOffset.x + fBounds.left,
918 		-fParentOffset.y + fBounds.top);
919 }
920 
921 
922 BRect
ConvertFromParent(BRect rect) const923 BView::ConvertFromParent(BRect rect) const
924 {
925 	ConvertFromParent(&rect);
926 
927 	return rect;
928 }
929 
930 
931 void
_ConvertToScreen(BPoint * point,bool checkLock) const932 BView::_ConvertToScreen(BPoint* point, bool checkLock) const
933 {
934 	if (!fParent) {
935 		if (fOwner)
936 			fOwner->ConvertToScreen(point);
937 
938 		return;
939 	}
940 
941 	if (checkLock)
942 		_CheckOwnerLock();
943 
944 	_ConvertToParent(point, false);
945 	fParent->_ConvertToScreen(point, false);
946 }
947 
948 
949 void
ConvertToScreen(BPoint * point) const950 BView::ConvertToScreen(BPoint* point) const
951 {
952 	_ConvertToScreen(point, true);
953 }
954 
955 
956 BPoint
ConvertToScreen(BPoint point) const957 BView::ConvertToScreen(BPoint point) const
958 {
959 	ConvertToScreen(&point);
960 
961 	return point;
962 }
963 
964 
965 void
_ConvertFromScreen(BPoint * point,bool checkLock) const966 BView::_ConvertFromScreen(BPoint* point, bool checkLock) const
967 {
968 	if (!fParent) {
969 		if (fOwner)
970 			fOwner->ConvertFromScreen(point);
971 
972 		return;
973 	}
974 
975 	if (checkLock)
976 		_CheckOwnerLock();
977 
978 	_ConvertFromParent(point, false);
979 	fParent->_ConvertFromScreen(point, false);
980 }
981 
982 
983 void
ConvertFromScreen(BPoint * point) const984 BView::ConvertFromScreen(BPoint* point) const
985 {
986 	_ConvertFromScreen(point, true);
987 }
988 
989 
990 BPoint
ConvertFromScreen(BPoint point) const991 BView::ConvertFromScreen(BPoint point) const
992 {
993 	ConvertFromScreen(&point);
994 
995 	return point;
996 }
997 
998 
999 void
ConvertToScreen(BRect * rect) const1000 BView::ConvertToScreen(BRect* rect) const
1001 {
1002 	BPoint offset(0.0, 0.0);
1003 	ConvertToScreen(&offset);
1004 	rect->OffsetBy(offset);
1005 }
1006 
1007 
1008 BRect
ConvertToScreen(BRect rect) const1009 BView::ConvertToScreen(BRect rect) const
1010 {
1011 	ConvertToScreen(&rect);
1012 
1013 	return rect;
1014 }
1015 
1016 
1017 void
ConvertFromScreen(BRect * rect) const1018 BView::ConvertFromScreen(BRect* rect) const
1019 {
1020 	BPoint offset(0.0, 0.0);
1021 	ConvertFromScreen(&offset);
1022 	rect->OffsetBy(offset);
1023 }
1024 
1025 
1026 BRect
ConvertFromScreen(BRect rect) const1027 BView::ConvertFromScreen(BRect rect) const
1028 {
1029 	ConvertFromScreen(&rect);
1030 
1031 	return rect;
1032 }
1033 
1034 
1035 uint32
Flags() const1036 BView::Flags() const
1037 {
1038 	_CheckLock();
1039 	return fFlags & ~_RESIZE_MASK_;
1040 }
1041 
1042 
1043 void
SetFlags(uint32 flags)1044 BView::SetFlags(uint32 flags)
1045 {
1046 	if (Flags() == flags)
1047 		return;
1048 
1049 	if (fOwner) {
1050 		if (flags & B_PULSE_NEEDED) {
1051 			_CheckLock();
1052 			if (fOwner->fPulseRunner == NULL)
1053 				fOwner->SetPulseRate(fOwner->PulseRate());
1054 		}
1055 
1056 		uint32 changesFlags = flags ^ fFlags;
1057 		if (changesFlags & (B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE
1058 				| B_FRAME_EVENTS | B_SUBPIXEL_PRECISE
1059 				| B_TRANSPARENT_BACKGROUND)) {
1060 			_CheckLockAndSwitchCurrent();
1061 
1062 			fOwner->fLink->StartMessage(AS_VIEW_SET_FLAGS);
1063 			fOwner->fLink->Attach<uint32>(flags);
1064 			fOwner->fLink->Flush();
1065 		}
1066 	}
1067 
1068 	/* Some useful info:
1069 		fFlags is a unsigned long (32 bits)
1070 		* bits 1-16 are used for BView's flags
1071 		* bits 17-32 are used for BView' resize mask
1072 		* _RESIZE_MASK_ is used for that. Look into View.h to see how
1073 			it's defined
1074 	*/
1075 	fFlags = (flags & ~_RESIZE_MASK_) | (fFlags & _RESIZE_MASK_);
1076 
1077 	fState->archiving_flags |= B_VIEW_FLAGS_BIT;
1078 }
1079 
1080 
1081 BRect
Frame() const1082 BView::Frame() const
1083 {
1084 	return Bounds().OffsetToCopy(fParentOffset.x, fParentOffset.y);
1085 }
1086 
1087 
1088 void
Hide()1089 BView::Hide()
1090 {
1091 	if (fOwner && fShowLevel == 0) {
1092 		_CheckLockAndSwitchCurrent();
1093 		fOwner->fLink->StartMessage(AS_VIEW_HIDE);
1094 		fOwner->fLink->Flush();
1095 	}
1096 	fShowLevel++;
1097 
1098 	if (fShowLevel == 1)
1099 		_InvalidateParentLayout();
1100 }
1101 
1102 
1103 void
Show()1104 BView::Show()
1105 {
1106 	fShowLevel--;
1107 	if (fOwner && fShowLevel == 0) {
1108 		_CheckLockAndSwitchCurrent();
1109 		fOwner->fLink->StartMessage(AS_VIEW_SHOW);
1110 		fOwner->fLink->Flush();
1111 	}
1112 
1113 	if (fShowLevel == 0)
1114 		_InvalidateParentLayout();
1115 }
1116 
1117 
1118 bool
IsFocus() const1119 BView::IsFocus() const
1120 {
1121 	if (fOwner) {
1122 		_CheckLock();
1123 		return fOwner->CurrentFocus() == this;
1124 	} else
1125 		return false;
1126 }
1127 
1128 
1129 bool
IsHidden(const BView * lookingFrom) const1130 BView::IsHidden(const BView* lookingFrom) const
1131 {
1132 	if (fShowLevel > 0)
1133 		return true;
1134 
1135 	// may we be egocentric?
1136 	if (lookingFrom == this)
1137 		return false;
1138 
1139 	// we have the same visibility state as our
1140 	// parent, if there is one
1141 	if (fParent)
1142 		return fParent->IsHidden(lookingFrom);
1143 
1144 	// if we're the top view, and we're interested
1145 	// in the "global" view, we're inheriting the
1146 	// state of the window's visibility
1147 	if (fOwner && lookingFrom == NULL)
1148 		return fOwner->IsHidden();
1149 
1150 	return false;
1151 }
1152 
1153 
1154 bool
IsHidden() const1155 BView::IsHidden() const
1156 {
1157 	return IsHidden(NULL);
1158 }
1159 
1160 
1161 bool
IsPrinting() const1162 BView::IsPrinting() const
1163 {
1164 	return fIsPrinting;
1165 }
1166 
1167 
1168 BPoint
LeftTop() const1169 BView::LeftTop() const
1170 {
1171 	return Bounds().LeftTop();
1172 }
1173 
1174 
1175 void
SetResizingMode(uint32 mode)1176 BView::SetResizingMode(uint32 mode)
1177 {
1178 	if (fOwner) {
1179 		_CheckLockAndSwitchCurrent();
1180 
1181 		fOwner->fLink->StartMessage(AS_VIEW_RESIZE_MODE);
1182 		fOwner->fLink->Attach<uint32>(mode);
1183 	}
1184 
1185 	// look at SetFlags() for more info on the below line
1186 	fFlags = (fFlags & ~_RESIZE_MASK_) | (mode & _RESIZE_MASK_);
1187 }
1188 
1189 
1190 uint32
ResizingMode() const1191 BView::ResizingMode() const
1192 {
1193 	return fFlags & _RESIZE_MASK_;
1194 }
1195 
1196 
1197 void
SetViewCursor(const BCursor * cursor,bool sync)1198 BView::SetViewCursor(const BCursor* cursor, bool sync)
1199 {
1200 	if (cursor == NULL || fOwner == NULL)
1201 		return;
1202 
1203 	_CheckLock();
1204 
1205 	ViewSetViewCursorInfo info;
1206 	info.cursorToken = cursor->fServerToken;
1207 	info.viewToken = _get_object_token_(this);
1208 	info.sync = sync;
1209 
1210 	BPrivate::AppServerLink link;
1211 	link.StartMessage(AS_SET_VIEW_CURSOR);
1212 	link.Attach<ViewSetViewCursorInfo>(info);
1213 
1214 	if (sync) {
1215 		// Make sure the server has processed the message.
1216 		int32 code;
1217 		link.FlushWithReply(code);
1218 	}
1219 }
1220 
1221 
1222 void
Flush() const1223 BView::Flush() const
1224 {
1225 	if (fOwner)
1226 		fOwner->Flush();
1227 }
1228 
1229 
1230 void
Sync() const1231 BView::Sync() const
1232 {
1233 	_CheckOwnerLock();
1234 	if (fOwner)
1235 		fOwner->Sync();
1236 }
1237 
1238 
1239 BWindow*
Window() const1240 BView::Window() const
1241 {
1242 	return fOwner;
1243 }
1244 
1245 
1246 //	#pragma mark - Hook Functions
1247 
1248 
1249 void
AttachedToWindow()1250 BView::AttachedToWindow()
1251 {
1252 	// Hook function
1253 	STRACE(("\tHOOK: BView(%s)::AttachedToWindow()\n", Name()));
1254 }
1255 
1256 
1257 void
AllAttached()1258 BView::AllAttached()
1259 {
1260 	// Hook function
1261 	STRACE(("\tHOOK: BView(%s)::AllAttached()\n", Name()));
1262 }
1263 
1264 
1265 void
DetachedFromWindow()1266 BView::DetachedFromWindow()
1267 {
1268 	// Hook function
1269 	STRACE(("\tHOOK: BView(%s)::DetachedFromWindow()\n", Name()));
1270 }
1271 
1272 
1273 void
AllDetached()1274 BView::AllDetached()
1275 {
1276 	// Hook function
1277 	STRACE(("\tHOOK: BView(%s)::AllDetached()\n", Name()));
1278 }
1279 
1280 
1281 void
Draw(BRect updateRect)1282 BView::Draw(BRect updateRect)
1283 {
1284 	// Hook function
1285 	STRACE(("\tHOOK: BView(%s)::Draw()\n", Name()));
1286 }
1287 
1288 
1289 void
DrawAfterChildren(BRect updateRect)1290 BView::DrawAfterChildren(BRect updateRect)
1291 {
1292 	// Hook function
1293 	STRACE(("\tHOOK: BView(%s)::DrawAfterChildren()\n", Name()));
1294 }
1295 
1296 
1297 void
FrameMoved(BPoint newPosition)1298 BView::FrameMoved(BPoint newPosition)
1299 {
1300 	// Hook function
1301 	STRACE(("\tHOOK: BView(%s)::FrameMoved()\n", Name()));
1302 }
1303 
1304 
1305 void
FrameResized(float newWidth,float newHeight)1306 BView::FrameResized(float newWidth, float newHeight)
1307 {
1308 	// Hook function
1309 	STRACE(("\tHOOK: BView(%s)::FrameResized()\n", Name()));
1310 }
1311 
1312 
1313 void
GetPreferredSize(float * _width,float * _height)1314 BView::GetPreferredSize(float* _width, float* _height)
1315 {
1316 	STRACE(("\tHOOK: BView(%s)::GetPreferredSize()\n", Name()));
1317 
1318 	if (_width != NULL)
1319 		*_width = fBounds.Width();
1320 	if (_height != NULL)
1321 		*_height = fBounds.Height();
1322 }
1323 
1324 
1325 void
ResizeToPreferred()1326 BView::ResizeToPreferred()
1327 {
1328 	STRACE(("\tHOOK: BView(%s)::ResizeToPreferred()\n", Name()));
1329 
1330 	float width;
1331 	float height;
1332 	GetPreferredSize(&width, &height);
1333 
1334 	ResizeTo(width, height);
1335 }
1336 
1337 
1338 void
KeyDown(const char * bytes,int32 numBytes)1339 BView::KeyDown(const char* bytes, int32 numBytes)
1340 {
1341 	// Hook function
1342 	STRACE(("\tHOOK: BView(%s)::KeyDown()\n", Name()));
1343 
1344 	if (Window())
1345 		Window()->_KeyboardNavigation();
1346 }
1347 
1348 
1349 void
KeyUp(const char * bytes,int32 numBytes)1350 BView::KeyUp(const char* bytes, int32 numBytes)
1351 {
1352 	// Hook function
1353 	STRACE(("\tHOOK: BView(%s)::KeyUp()\n", Name()));
1354 }
1355 
1356 
1357 void
MouseDown(BPoint where)1358 BView::MouseDown(BPoint where)
1359 {
1360 	// Hook function
1361 	STRACE(("\tHOOK: BView(%s)::MouseDown()\n", Name()));
1362 }
1363 
1364 
1365 void
MouseUp(BPoint where)1366 BView::MouseUp(BPoint where)
1367 {
1368 	// Hook function
1369 	STRACE(("\tHOOK: BView(%s)::MouseUp()\n", Name()));
1370 }
1371 
1372 
1373 void
MouseMoved(BPoint where,uint32 code,const BMessage * dragMessage)1374 BView::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
1375 {
1376 	// Hook function
1377 	STRACE(("\tHOOK: BView(%s)::MouseMoved()\n", Name()));
1378 }
1379 
1380 
1381 void
Pulse()1382 BView::Pulse()
1383 {
1384 	// Hook function
1385 	STRACE(("\tHOOK: BView(%s)::Pulse()\n", Name()));
1386 }
1387 
1388 
1389 void
TargetedByScrollView(BScrollView * scroll_view)1390 BView::TargetedByScrollView(BScrollView* scroll_view)
1391 {
1392 	// Hook function
1393 	STRACE(("\tHOOK: BView(%s)::TargetedByScrollView()\n", Name()));
1394 }
1395 
1396 
1397 void
WindowActivated(bool active)1398 BView::WindowActivated(bool active)
1399 {
1400 	// Hook function
1401 	STRACE(("\tHOOK: BView(%s)::WindowActivated()\n", Name()));
1402 }
1403 
1404 
1405 //	#pragma mark - Input Functions
1406 
1407 
1408 void
BeginRectTracking(BRect startRect,uint32 style)1409 BView::BeginRectTracking(BRect startRect, uint32 style)
1410 {
1411 	if (_CheckOwnerLockAndSwitchCurrent()) {
1412 		fOwner->fLink->StartMessage(AS_VIEW_BEGIN_RECT_TRACK);
1413 		fOwner->fLink->Attach<BRect>(startRect);
1414 		fOwner->fLink->Attach<uint32>(style);
1415 		fOwner->fLink->Flush();
1416 	}
1417 }
1418 
1419 
1420 void
EndRectTracking()1421 BView::EndRectTracking()
1422 {
1423 	if (_CheckOwnerLockAndSwitchCurrent()) {
1424 		fOwner->fLink->StartMessage(AS_VIEW_END_RECT_TRACK);
1425 		fOwner->fLink->Flush();
1426 	}
1427 }
1428 
1429 
1430 void
DragMessage(BMessage * message,BRect dragRect,BHandler * replyTo)1431 BView::DragMessage(BMessage* message, BRect dragRect, BHandler* replyTo)
1432 {
1433 	if (!message)
1434 		return;
1435 
1436 	_CheckOwnerLock();
1437 
1438 	// calculate the offset
1439 	BPoint offset;
1440 	uint32 buttons;
1441 	BMessage* current = fOwner->CurrentMessage();
1442 	if (!current || current->FindPoint("be:view_where", &offset) != B_OK)
1443 		GetMouse(&offset, &buttons, false);
1444 	offset -= dragRect.LeftTop();
1445 
1446 	if (!dragRect.IsValid()) {
1447 		DragMessage(message, NULL, B_OP_BLEND, offset, replyTo);
1448 		return;
1449 	}
1450 
1451 	// TODO: that's not really what should happen - the app_server should take
1452 	// the chance *NOT* to need to drag a whole bitmap around but just a frame.
1453 
1454 	// create a drag bitmap for the rect
1455 	BBitmap* bitmap = new(std::nothrow) BBitmap(dragRect, B_RGBA32);
1456 	if (bitmap == NULL)
1457 		return;
1458 
1459 	uint32* bits = (uint32*)bitmap->Bits();
1460 	uint32 bytesPerRow = bitmap->BytesPerRow();
1461 	uint32 width = dragRect.IntegerWidth() + 1;
1462 	uint32 height = dragRect.IntegerHeight() + 1;
1463 	uint32 lastRow = (height - 1) * width;
1464 
1465 	memset(bits, 0x00, height * bytesPerRow);
1466 
1467 	// top
1468 	for (uint32 i = 0; i < width; i += 2)
1469 		bits[i] = 0xff000000;
1470 
1471 	// bottom
1472 	for (uint32 i = (height % 2 == 0 ? 1 : 0); i < width; i += 2)
1473 		bits[lastRow + i] = 0xff000000;
1474 
1475 	// left
1476 	for (uint32 i = 0; i < lastRow; i += width * 2)
1477 		bits[i] = 0xff000000;
1478 
1479 	// right
1480 	for (uint32 i = (width % 2 == 0 ? width : 0); i < lastRow; i += width * 2)
1481 		bits[width - 1 + i] = 0xff000000;
1482 
1483 	DragMessage(message, bitmap, B_OP_BLEND, offset, replyTo);
1484 }
1485 
1486 
1487 void
DragMessage(BMessage * message,BBitmap * image,BPoint offset,BHandler * replyTo)1488 BView::DragMessage(BMessage* message, BBitmap* image, BPoint offset,
1489 	BHandler* replyTo)
1490 {
1491 	DragMessage(message, image, B_OP_COPY, offset, replyTo);
1492 }
1493 
1494 
1495 void
DragMessage(BMessage * message,BBitmap * image,drawing_mode dragMode,BPoint offset,BHandler * replyTo)1496 BView::DragMessage(BMessage* message, BBitmap* image,
1497 	drawing_mode dragMode, BPoint offset, BHandler* replyTo)
1498 {
1499 	if (message == NULL)
1500 		return;
1501 
1502 	if (image == NULL) {
1503 		// TODO: workaround for drags without a bitmap - should not be necessary if
1504 		//	we move the rectangle dragging into the app_server
1505 		image = new(std::nothrow) BBitmap(BRect(0, 0, 0, 0), B_RGBA32);
1506 		if (image == NULL)
1507 			return;
1508 	}
1509 
1510 	if (replyTo == NULL)
1511 		replyTo = this;
1512 
1513 	if (replyTo->Looper() == NULL)
1514 		debugger("DragMessage: warning - the Handler needs a looper");
1515 
1516 	_CheckOwnerLock();
1517 
1518 	if (!message->HasInt32("buttons")) {
1519 		BMessage* msg = fOwner->CurrentMessage();
1520 		uint32 buttons;
1521 
1522 		if (msg == NULL
1523 			|| msg->FindInt32("buttons", (int32*)&buttons) != B_OK) {
1524 			BPoint point;
1525 			GetMouse(&point, &buttons, false);
1526 		}
1527 
1528 		message->AddInt32("buttons", buttons);
1529 	}
1530 
1531 	BMessage::Private privateMessage(message);
1532 	privateMessage.SetReply(BMessenger(replyTo, replyTo->Looper()));
1533 
1534 	int32 bufferSize = message->FlattenedSize();
1535 	char* buffer = new(std::nothrow) char[bufferSize];
1536 	if (buffer != NULL) {
1537 		message->Flatten(buffer, bufferSize);
1538 
1539 		fOwner->fLink->StartMessage(AS_VIEW_DRAG_IMAGE);
1540 		fOwner->fLink->Attach<int32>(image->_ServerToken());
1541 		fOwner->fLink->Attach<int32>((int32)dragMode);
1542 		fOwner->fLink->Attach<BPoint>(offset);
1543 		fOwner->fLink->Attach<int32>(bufferSize);
1544 		fOwner->fLink->Attach(buffer, bufferSize);
1545 
1546 		// we need to wait for the server
1547 		// to actually process this message
1548 		// before we can delete the bitmap
1549 		int32 code;
1550 		fOwner->fLink->FlushWithReply(code);
1551 
1552 		delete [] buffer;
1553 	} else {
1554 		fprintf(stderr, "BView::DragMessage() - no memory to flatten drag "
1555 			"message\n");
1556 	}
1557 
1558 	delete image;
1559 }
1560 
1561 
1562 void
GetMouse(BPoint * _location,uint32 * _buttons,bool checkMessageQueue)1563 BView::GetMouse(BPoint* _location, uint32* _buttons, bool checkMessageQueue)
1564 {
1565 	if (_location == NULL && _buttons == NULL)
1566 		return;
1567 
1568 	_CheckOwnerLockAndSwitchCurrent();
1569 
1570 	uint32 eventOptions = fEventOptions | fMouseEventOptions;
1571 	bool noHistory = eventOptions & B_NO_POINTER_HISTORY;
1572 	bool fullHistory = eventOptions & B_FULL_POINTER_HISTORY;
1573 
1574 	if (checkMessageQueue && !noHistory) {
1575 		Window()->UpdateIfNeeded();
1576 		BMessageQueue* queue = Window()->MessageQueue();
1577 		queue->Lock();
1578 
1579 		// Look out for mouse update messages
1580 
1581 		BMessage* message;
1582 		for (int32 i = 0; (message = queue->FindMessage(i)) != NULL; i++) {
1583 			switch (message->what) {
1584 				case B_MOUSE_MOVED:
1585 				case B_MOUSE_UP:
1586 				case B_MOUSE_DOWN:
1587 					bool deleteMessage;
1588 					if (!Window()->_StealMouseMessage(message, deleteMessage))
1589 						continue;
1590 
1591 					if (!fullHistory && message->what == B_MOUSE_MOVED) {
1592 						// Check if the message is too old. Some applications
1593 						// check the message queue in such a way that mouse
1594 						// messages *must* pile up. This check makes them work
1595 						// as intended, although these applications could simply
1596 						// use the version of BView::GetMouse() that does not
1597 						// check the history. Also note that it isn't a problem
1598 						// to delete the message in case there is not a newer
1599 						// one. If we don't find a message in the queue, we will
1600 						// just fall back to asking the app_sever directly. So
1601 						// the imposed delay will not be a problem on slower
1602 						// computers. This check also prevents another problem,
1603 						// when the message that we use is *not* removed from
1604 						// the queue. Subsequent calls to GetMouse() would find
1605 						// this message over and over!
1606 						bigtime_t eventTime;
1607 						if (message->FindInt64("when", &eventTime) == B_OK
1608 							&& system_time() - eventTime > 10000) {
1609 							// just discard the message
1610 							if (deleteMessage)
1611 								delete message;
1612 							continue;
1613 						}
1614 					}
1615 					if (_location != NULL)
1616 						message->FindPoint("screen_where", _location);
1617 					if (_buttons != NULL)
1618 						message->FindInt32("buttons", (int32*)_buttons);
1619 					queue->Unlock();
1620 						// we need to hold the queue lock until here, because
1621 						// the message might still be used for something else
1622 
1623 					if (_location != NULL)
1624 						ConvertFromScreen(_location);
1625 
1626 					if (deleteMessage)
1627 						delete message;
1628 
1629 					return;
1630 			}
1631 		}
1632 		queue->Unlock();
1633 	}
1634 
1635 	// If no mouse update message has been found in the message queue,
1636 	// we get the current mouse location and buttons from the app_server
1637 
1638 	fOwner->fLink->StartMessage(AS_GET_MOUSE);
1639 
1640 	int32 code;
1641 	if (fOwner->fLink->FlushWithReply(code) == B_OK
1642 		&& code == B_OK) {
1643 		BPoint location;
1644 		uint32 buttons;
1645 		fOwner->fLink->Read<BPoint>(&location);
1646 		fOwner->fLink->Read<uint32>(&buttons);
1647 			// TODO: ServerWindow replies with an int32 here
1648 
1649 		ConvertFromScreen(&location);
1650 			// TODO: in beos R5, location is already converted to the view
1651 			// local coordinate system, so if an app checks the window message
1652 			// queue by itself, it might not find what it expects.
1653 			// NOTE: the fact that we have mouse coords in screen space in our
1654 			// queue avoids the problem that messages already in the queue will
1655 			// be outdated as soon as a window or even the view moves. The
1656 			// second situation being quite common actually, also with regards
1657 			// to scrolling. An app reading these messages would have to know
1658 			// the locations of the window and view for each message...
1659 			// otherwise it is potentially broken anyways.
1660 		if (_location != NULL)
1661 			*_location = location;
1662 		if (_buttons != NULL)
1663 			*_buttons = buttons;
1664 	} else {
1665 		if (_location != NULL)
1666 			_location->Set(0, 0);
1667 		if (_buttons != NULL)
1668 			*_buttons = 0;
1669 	}
1670 }
1671 
1672 
1673 void
MakeFocus(bool focus)1674 BView::MakeFocus(bool focus)
1675 {
1676 	if (fOwner == NULL)
1677 		return;
1678 
1679 	// TODO: If this view has focus and focus == false,
1680 	// will there really be no other view with focus? No
1681 	// cycling to the next one?
1682 	BView* focusView = fOwner->CurrentFocus();
1683 	if (focus) {
1684 		// Unfocus a previous focus view
1685 		if (focusView != NULL && focusView != this)
1686 			focusView->MakeFocus(false);
1687 
1688 		// if we want to make this view the current focus view
1689 		fOwner->_SetFocus(this, true);
1690 	} else {
1691 		// we want to unfocus this view, but only if it actually has focus
1692 		if (focusView == this)
1693 			fOwner->_SetFocus(NULL, true);
1694 	}
1695 }
1696 
1697 
1698 BScrollBar*
ScrollBar(orientation direction) const1699 BView::ScrollBar(orientation direction) const
1700 {
1701 	switch (direction) {
1702 		case B_VERTICAL:
1703 			return fVerScroller;
1704 
1705 		case B_HORIZONTAL:
1706 			return fHorScroller;
1707 
1708 		default:
1709 			return NULL;
1710 	}
1711 }
1712 
1713 
1714 void
ScrollBy(float deltaX,float deltaY)1715 BView::ScrollBy(float deltaX, float deltaY)
1716 {
1717 	ScrollTo(BPoint(fBounds.left + deltaX, fBounds.top + deltaY));
1718 }
1719 
1720 
1721 void
ScrollTo(BPoint where)1722 BView::ScrollTo(BPoint where)
1723 {
1724 	// scrolling by fractional values is not supported
1725 	where.x = roundf(where.x);
1726 	where.y = roundf(where.y);
1727 
1728 	// no reason to process this further if no scroll is intended.
1729 	if (where.x == fBounds.left && where.y == fBounds.top)
1730 		return;
1731 
1732 	// make sure scrolling is within valid bounds
1733 	if (fHorScroller) {
1734 		float min, max;
1735 		fHorScroller->GetRange(&min, &max);
1736 
1737 		if (where.x < min)
1738 			where.x = min;
1739 		else if (where.x > max)
1740 			where.x = max;
1741 	}
1742 	if (fVerScroller) {
1743 		float min, max;
1744 		fVerScroller->GetRange(&min, &max);
1745 
1746 		if (where.y < min)
1747 			where.y = min;
1748 		else if (where.y > max)
1749 			where.y = max;
1750 	}
1751 
1752 	_CheckLockAndSwitchCurrent();
1753 
1754 	float xDiff = where.x - fBounds.left;
1755 	float yDiff = where.y - fBounds.top;
1756 
1757 	// if we're attached to a window tell app_server about this change
1758 	if (fOwner) {
1759 		fOwner->fLink->StartMessage(AS_VIEW_SCROLL);
1760 		fOwner->fLink->Attach<float>(xDiff);
1761 		fOwner->fLink->Attach<float>(yDiff);
1762 
1763 		fOwner->fLink->Flush();
1764 
1765 //		fState->valid_flags &= ~B_VIEW_FRAME_BIT;
1766 	}
1767 
1768 	// we modify our bounds rectangle by deltaX/deltaY coord units hor/ver.
1769 	fBounds.OffsetTo(where.x, where.y);
1770 
1771 	// then set the new values of the scrollbars
1772 	if (fHorScroller && xDiff != 0.0)
1773 		fHorScroller->SetValue(fBounds.left);
1774 	if (fVerScroller && yDiff != 0.0)
1775 		fVerScroller->SetValue(fBounds.top);
1776 
1777 }
1778 
1779 
1780 status_t
SetEventMask(uint32 mask,uint32 options)1781 BView::SetEventMask(uint32 mask, uint32 options)
1782 {
1783 	if (fEventMask == mask && fEventOptions == options)
1784 		return B_OK;
1785 
1786 	// don't change the mask if it's zero and we've got options
1787 	if (mask != 0 || options == 0)
1788 		fEventMask = mask | (fEventMask & 0xffff0000);
1789 	fEventOptions = options;
1790 
1791 	fState->archiving_flags |= B_VIEW_EVENT_MASK_BIT;
1792 
1793 	if (fOwner) {
1794 		_CheckLockAndSwitchCurrent();
1795 
1796 		fOwner->fLink->StartMessage(AS_VIEW_SET_EVENT_MASK);
1797 		fOwner->fLink->Attach<uint32>(mask);
1798 		fOwner->fLink->Attach<uint32>(options);
1799 		fOwner->fLink->Flush();
1800 	}
1801 
1802 	return B_OK;
1803 }
1804 
1805 
1806 uint32
EventMask()1807 BView::EventMask()
1808 {
1809 	return fEventMask;
1810 }
1811 
1812 
1813 status_t
SetMouseEventMask(uint32 mask,uint32 options)1814 BView::SetMouseEventMask(uint32 mask, uint32 options)
1815 {
1816 	// Just don't do anything if the view is not yet attached
1817 	// or we were called outside of BView::MouseDown()
1818 	if (fOwner != NULL
1819 		&& fOwner->CurrentMessage() != NULL
1820 		&& fOwner->CurrentMessage()->what == B_MOUSE_DOWN) {
1821 		_CheckLockAndSwitchCurrent();
1822 		fMouseEventOptions = options;
1823 
1824 		fOwner->fLink->StartMessage(AS_VIEW_SET_MOUSE_EVENT_MASK);
1825 		fOwner->fLink->Attach<uint32>(mask);
1826 		fOwner->fLink->Attach<uint32>(options);
1827 		fOwner->fLink->Flush();
1828 		return B_OK;
1829 	}
1830 
1831 	return B_ERROR;
1832 }
1833 
1834 
1835 //	#pragma mark - Graphic State Functions
1836 
1837 
1838 void
PushState()1839 BView::PushState()
1840 {
1841 	_CheckOwnerLockAndSwitchCurrent();
1842 
1843 	fOwner->fLink->StartMessage(AS_VIEW_PUSH_STATE);
1844 
1845 	fState->valid_flags &= ~B_VIEW_PARENT_COMPOSITE_BIT;
1846 
1847 	// initialize origin, scale and transform, new states start "clean".
1848 	fState->valid_flags |= B_VIEW_SCALE_BIT | B_VIEW_ORIGIN_BIT
1849 		| B_VIEW_TRANSFORM_BIT;
1850 	fState->scale = 1.0f;
1851 	fState->origin.Set(0, 0);
1852 	fState->transform.Reset();
1853 }
1854 
1855 
1856 void
PopState()1857 BView::PopState()
1858 {
1859 	_CheckOwnerLockAndSwitchCurrent();
1860 
1861 	fOwner->fLink->StartMessage(AS_VIEW_POP_STATE);
1862 	_FlushIfNotInTransaction();
1863 
1864 	// invalidate all flags (except those that are not part of pop/push)
1865 	fState->valid_flags = B_VIEW_VIEW_COLOR_BIT;
1866 }
1867 
1868 
1869 void
SetOrigin(BPoint where)1870 BView::SetOrigin(BPoint where)
1871 {
1872 	SetOrigin(where.x, where.y);
1873 }
1874 
1875 
1876 void
SetOrigin(float x,float y)1877 BView::SetOrigin(float x, float y)
1878 {
1879 	if (fState->IsValid(B_VIEW_ORIGIN_BIT)
1880 		&& x == fState->origin.x && y == fState->origin.y)
1881 		return;
1882 
1883 	fState->origin.x = x;
1884 	fState->origin.y = y;
1885 
1886 	if (_CheckOwnerLockAndSwitchCurrent()) {
1887 		fOwner->fLink->StartMessage(AS_VIEW_SET_ORIGIN);
1888 		fOwner->fLink->Attach<float>(x);
1889 		fOwner->fLink->Attach<float>(y);
1890 
1891 		fState->valid_flags |= B_VIEW_ORIGIN_BIT;
1892 	}
1893 
1894 	// our local coord system origin has changed, so when archiving we'll add
1895 	// this too
1896 	fState->archiving_flags |= B_VIEW_ORIGIN_BIT;
1897 }
1898 
1899 
1900 BPoint
Origin() const1901 BView::Origin() const
1902 {
1903 	if (!fState->IsValid(B_VIEW_ORIGIN_BIT)) {
1904 		// we don't keep graphics state information, therefor
1905 		// we need to ask the server for the origin after PopState()
1906 		_CheckOwnerLockAndSwitchCurrent();
1907 
1908 		fOwner->fLink->StartMessage(AS_VIEW_GET_ORIGIN);
1909 
1910 		int32 code;
1911 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK)
1912 			fOwner->fLink->Read<BPoint>(&fState->origin);
1913 
1914 		fState->valid_flags |= B_VIEW_ORIGIN_BIT;
1915 	}
1916 
1917 	return fState->origin;
1918 }
1919 
1920 
1921 void
SetScale(float scale) const1922 BView::SetScale(float scale) const
1923 {
1924 	if (fState->IsValid(B_VIEW_SCALE_BIT) && scale == fState->scale)
1925 		return;
1926 
1927 	if (fOwner) {
1928 		_CheckLockAndSwitchCurrent();
1929 
1930 		fOwner->fLink->StartMessage(AS_VIEW_SET_SCALE);
1931 		fOwner->fLink->Attach<float>(scale);
1932 
1933 		fState->valid_flags |= B_VIEW_SCALE_BIT;
1934 	}
1935 
1936 	fState->scale = scale;
1937 	fState->archiving_flags |= B_VIEW_SCALE_BIT;
1938 }
1939 
1940 
1941 float
Scale() const1942 BView::Scale() const
1943 {
1944 	if (!fState->IsValid(B_VIEW_SCALE_BIT) && fOwner) {
1945 		_CheckLockAndSwitchCurrent();
1946 
1947 		fOwner->fLink->StartMessage(AS_VIEW_GET_SCALE);
1948 
1949  		int32 code;
1950 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK)
1951 			fOwner->fLink->Read<float>(&fState->scale);
1952 
1953 		fState->valid_flags |= B_VIEW_SCALE_BIT;
1954 	}
1955 
1956 	return fState->scale;
1957 }
1958 
1959 
1960 void
SetTransform(BAffineTransform transform)1961 BView::SetTransform(BAffineTransform transform)
1962 {
1963 	if (fState->IsValid(B_VIEW_TRANSFORM_BIT) && transform == fState->transform)
1964 		return;
1965 
1966 	if (fOwner != NULL) {
1967 		_CheckLockAndSwitchCurrent();
1968 
1969 		fOwner->fLink->StartMessage(AS_VIEW_SET_TRANSFORM);
1970 		fOwner->fLink->Attach<BAffineTransform>(transform);
1971 
1972 		fState->valid_flags |= B_VIEW_TRANSFORM_BIT;
1973 	}
1974 
1975 	fState->transform = transform;
1976 	fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
1977 }
1978 
1979 
1980 BAffineTransform
Transform() const1981 BView::Transform() const
1982 {
1983 	if (!fState->IsValid(B_VIEW_TRANSFORM_BIT) && fOwner != NULL) {
1984 		_CheckLockAndSwitchCurrent();
1985 
1986 		fOwner->fLink->StartMessage(AS_VIEW_GET_TRANSFORM);
1987 
1988  		int32 code;
1989 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK)
1990 			fOwner->fLink->Read<BAffineTransform>(&fState->transform);
1991 
1992 		fState->valid_flags |= B_VIEW_TRANSFORM_BIT;
1993 	}
1994 
1995 	return fState->transform;
1996 }
1997 
1998 
1999 BAffineTransform
TransformTo(coordinate_space basis) const2000 BView::TransformTo(coordinate_space basis) const
2001 {
2002 	if (basis == B_CURRENT_STATE_COORDINATES)
2003 		return B_AFFINE_IDENTITY_TRANSFORM;
2004 
2005 	if (!fState->IsValid(B_VIEW_PARENT_COMPOSITE_BIT) && fOwner != NULL) {
2006 		_CheckLockAndSwitchCurrent();
2007 
2008 		fOwner->fLink->StartMessage(AS_VIEW_GET_PARENT_COMPOSITE);
2009 
2010 		int32 code;
2011 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) {
2012 			fOwner->fLink->Read<BAffineTransform>(&fState->parent_composite_transform);
2013 			fOwner->fLink->Read<float>(&fState->parent_composite_scale);
2014 			fOwner->fLink->Read<BPoint>(&fState->parent_composite_origin);
2015 		}
2016 
2017 		fState->valid_flags |= B_VIEW_PARENT_COMPOSITE_BIT;
2018 	}
2019 
2020 	BAffineTransform transform = fState->parent_composite_transform * Transform();
2021 	float scale = fState->parent_composite_scale * Scale();
2022 	transform.PreScaleBy(scale, scale);
2023 	BPoint origin = Origin();
2024 	origin.x *= fState->parent_composite_scale;
2025 	origin.y *= fState->parent_composite_scale;
2026 	origin += fState->parent_composite_origin;
2027 	transform.TranslateBy(origin);
2028 
2029 	if (basis == B_PREVIOUS_STATE_COORDINATES) {
2030 		transform.TranslateBy(-fState->parent_composite_origin);
2031 		transform.PreMultiplyInverse(fState->parent_composite_transform);
2032 		transform.ScaleBy(1.0f / fState->parent_composite_scale);
2033 		return transform;
2034 	}
2035 
2036 	if (basis == B_VIEW_COORDINATES)
2037 		return transform;
2038 
2039 	origin = B_ORIGIN;
2040 
2041 	if (basis == B_PARENT_VIEW_COORDINATES || basis == B_PARENT_VIEW_DRAW_COORDINATES) {
2042 		BView* parent = Parent();
2043 		if (parent != NULL) {
2044 			ConvertToParent(&origin);
2045 			transform.TranslateBy(origin);
2046 			if (basis == B_PARENT_VIEW_DRAW_COORDINATES)
2047 				transform = transform.PreMultiplyInverse(parent->TransformTo(B_VIEW_COORDINATES));
2048 			return transform;
2049 		}
2050 		basis = B_WINDOW_COORDINATES;
2051 	}
2052 
2053 	ConvertToScreen(&origin);
2054 	if (basis == B_WINDOW_COORDINATES) {
2055 		BWindow* window = Window();
2056 		if (window != NULL)
2057 			origin -= window->Frame().LeftTop();
2058 	}
2059 	transform.TranslateBy(origin);
2060 	return transform;
2061 }
2062 
2063 
2064 void
TranslateBy(double x,double y)2065 BView::TranslateBy(double x, double y)
2066 {
2067 	if (fOwner != NULL) {
2068 		_CheckLockAndSwitchCurrent();
2069 
2070 		fOwner->fLink->StartMessage(AS_VIEW_AFFINE_TRANSLATE);
2071 		fOwner->fLink->Attach<double>(x);
2072 		fOwner->fLink->Attach<double>(y);
2073 
2074 		fState->valid_flags &= ~B_VIEW_TRANSFORM_BIT;
2075 	}
2076 
2077 	fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
2078 }
2079 
2080 
2081 void
ScaleBy(double x,double y)2082 BView::ScaleBy(double x, double y)
2083 {
2084 	if (fOwner != NULL) {
2085 		_CheckLockAndSwitchCurrent();
2086 
2087 		fOwner->fLink->StartMessage(AS_VIEW_AFFINE_SCALE);
2088 		fOwner->fLink->Attach<double>(x);
2089 		fOwner->fLink->Attach<double>(y);
2090 
2091 		fState->valid_flags &= ~B_VIEW_TRANSFORM_BIT;
2092 	}
2093 
2094 	fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
2095 }
2096 
2097 
2098 void
RotateBy(double angleRadians)2099 BView::RotateBy(double angleRadians)
2100 {
2101 	if (fOwner != NULL) {
2102 		_CheckLockAndSwitchCurrent();
2103 
2104 		fOwner->fLink->StartMessage(AS_VIEW_AFFINE_ROTATE);
2105 		fOwner->fLink->Attach<double>(angleRadians);
2106 
2107 		fState->valid_flags &= ~B_VIEW_TRANSFORM_BIT;
2108 	}
2109 
2110 	fState->archiving_flags |= B_VIEW_TRANSFORM_BIT;
2111 }
2112 
2113 
2114 void
SetLineMode(cap_mode lineCap,join_mode lineJoin,float miterLimit)2115 BView::SetLineMode(cap_mode lineCap, join_mode lineJoin, float miterLimit)
2116 {
2117 	if (fState->IsValid(B_VIEW_LINE_MODES_BIT)
2118 		&& lineCap == fState->line_cap && lineJoin == fState->line_join
2119 		&& miterLimit == fState->miter_limit)
2120 		return;
2121 
2122 	if (fOwner) {
2123 		_CheckLockAndSwitchCurrent();
2124 
2125 		ViewSetLineModeInfo info;
2126 		info.lineJoin = lineJoin;
2127 		info.lineCap = lineCap;
2128 		info.miterLimit = miterLimit;
2129 
2130 		fOwner->fLink->StartMessage(AS_VIEW_SET_LINE_MODE);
2131 		fOwner->fLink->Attach<ViewSetLineModeInfo>(info);
2132 
2133 		fState->valid_flags |= B_VIEW_LINE_MODES_BIT;
2134 	}
2135 
2136 	fState->line_cap = lineCap;
2137 	fState->line_join = lineJoin;
2138 	fState->miter_limit = miterLimit;
2139 
2140 	fState->archiving_flags |= B_VIEW_LINE_MODES_BIT;
2141 }
2142 
2143 
2144 join_mode
LineJoinMode() const2145 BView::LineJoinMode() const
2146 {
2147 	// This will update the current state, if necessary
2148 	if (!fState->IsValid(B_VIEW_LINE_MODES_BIT))
2149 		LineMiterLimit();
2150 
2151 	return fState->line_join;
2152 }
2153 
2154 
2155 cap_mode
LineCapMode() const2156 BView::LineCapMode() const
2157 {
2158 	// This will update the current state, if necessary
2159 	if (!fState->IsValid(B_VIEW_LINE_MODES_BIT))
2160 		LineMiterLimit();
2161 
2162 	return fState->line_cap;
2163 }
2164 
2165 
2166 float
LineMiterLimit() const2167 BView::LineMiterLimit() const
2168 {
2169 	if (!fState->IsValid(B_VIEW_LINE_MODES_BIT) && fOwner) {
2170 		_CheckLockAndSwitchCurrent();
2171 
2172 		fOwner->fLink->StartMessage(AS_VIEW_GET_LINE_MODE);
2173 
2174 		int32 code;
2175 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) {
2176 
2177 			ViewSetLineModeInfo info;
2178 			fOwner->fLink->Read<ViewSetLineModeInfo>(&info);
2179 
2180 			fState->line_cap = info.lineCap;
2181 			fState->line_join = info.lineJoin;
2182 			fState->miter_limit = info.miterLimit;
2183 		}
2184 
2185 		fState->valid_flags |= B_VIEW_LINE_MODES_BIT;
2186 	}
2187 
2188 	return fState->miter_limit;
2189 }
2190 
2191 
2192 void
SetFillRule(int32 fillRule)2193 BView::SetFillRule(int32 fillRule)
2194 {
2195 	if (fState->IsValid(B_VIEW_FILL_RULE_BIT) && fillRule == fState->fill_rule)
2196 		return;
2197 
2198 	if (fOwner) {
2199 		_CheckLockAndSwitchCurrent();
2200 
2201 		fOwner->fLink->StartMessage(AS_VIEW_SET_FILL_RULE);
2202 		fOwner->fLink->Attach<int32>(fillRule);
2203 
2204 		fState->valid_flags |= B_VIEW_FILL_RULE_BIT;
2205 	}
2206 
2207 	fState->fill_rule = fillRule;
2208 
2209 	fState->archiving_flags |= B_VIEW_FILL_RULE_BIT;
2210 }
2211 
2212 
2213 int32
FillRule() const2214 BView::FillRule() const
2215 {
2216 	if (!fState->IsValid(B_VIEW_FILL_RULE_BIT) && fOwner) {
2217 		_CheckLockAndSwitchCurrent();
2218 
2219 		fOwner->fLink->StartMessage(AS_VIEW_GET_FILL_RULE);
2220 
2221 		int32 code;
2222 		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) {
2223 
2224 			int32 fillRule;
2225 			fOwner->fLink->Read<int32>(&fillRule);
2226 
2227 			fState->fill_rule = fillRule;
2228 		}
2229 
2230 		fState->valid_flags |= B_VIEW_FILL_RULE_BIT;
2231 	}
2232 
2233 	return fState->fill_rule;
2234 }
2235 
2236 
2237 void
SetDrawingMode(drawing_mode mode)2238 BView::SetDrawingMode(drawing_mode mode)
2239 {
2240 	if (fState->IsValid(B_VIEW_DRAWING_MODE_BIT)
2241 		&& mode == fState->drawing_mode)
2242 		return;
2243 
2244 	if (fOwner) {
2245 		_CheckLockAndSwitchCurrent();
2246 
2247 		fOwner->fLink->StartMessage(AS_VIEW_SET_DRAWING_MODE);
2248 		fOwner->fLink->Attach<int8>((int8)mode);
2249 
2250 		fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT;
2251 	}
2252 
2253 	fState->drawing_mode = mode;
2254 	fState->archiving_flags |= B_VIEW_DRAWING_MODE_BIT;
2255 }
2256 
2257 
2258 drawing_mode
DrawingMode() const2259 BView::DrawingMode() const
2260 {
2261 	if (!fState->IsValid(B_VIEW_DRAWING_MODE_BIT) && fOwner) {
2262 		_CheckLockAndSwitchCurrent();
2263 
2264 		fOwner->fLink->StartMessage(AS_VIEW_GET_DRAWING_MODE);
2265 
2266 		int32 code;
2267 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2268 			&& code == B_OK) {
2269 			int8 drawingMode;
2270 			fOwner->fLink->Read<int8>(&drawingMode);
2271 
2272 			fState->drawing_mode = (drawing_mode)drawingMode;
2273 			fState->valid_flags |= B_VIEW_DRAWING_MODE_BIT;
2274 		}
2275 	}
2276 
2277 	return fState->drawing_mode;
2278 }
2279 
2280 
2281 void
SetBlendingMode(source_alpha sourceAlpha,alpha_function alphaFunction)2282 BView::SetBlendingMode(source_alpha sourceAlpha, alpha_function alphaFunction)
2283 {
2284 	if (fState->IsValid(B_VIEW_BLENDING_BIT)
2285 		&& sourceAlpha == fState->alpha_source_mode
2286 		&& alphaFunction == fState->alpha_function_mode)
2287 		return;
2288 
2289 	if (fOwner) {
2290 		_CheckLockAndSwitchCurrent();
2291 
2292 		ViewBlendingModeInfo info;
2293 		info.sourceAlpha = sourceAlpha;
2294 		info.alphaFunction = alphaFunction;
2295 
2296 		fOwner->fLink->StartMessage(AS_VIEW_SET_BLENDING_MODE);
2297 		fOwner->fLink->Attach<ViewBlendingModeInfo>(info);
2298 
2299 		fState->valid_flags |= B_VIEW_BLENDING_BIT;
2300 	}
2301 
2302 	fState->alpha_source_mode = sourceAlpha;
2303 	fState->alpha_function_mode = alphaFunction;
2304 
2305 	fState->archiving_flags |= B_VIEW_BLENDING_BIT;
2306 }
2307 
2308 
2309 void
GetBlendingMode(source_alpha * _sourceAlpha,alpha_function * _alphaFunction) const2310 BView::GetBlendingMode(source_alpha* _sourceAlpha,
2311 	alpha_function* _alphaFunction) const
2312 {
2313 	if (!fState->IsValid(B_VIEW_BLENDING_BIT) && fOwner) {
2314 		_CheckLockAndSwitchCurrent();
2315 
2316 		fOwner->fLink->StartMessage(AS_VIEW_GET_BLENDING_MODE);
2317 
2318 		int32 code;
2319  		if (fOwner->fLink->FlushWithReply(code) == B_OK && code == B_OK) {
2320  			ViewBlendingModeInfo info;
2321 			fOwner->fLink->Read<ViewBlendingModeInfo>(&info);
2322 
2323 			fState->alpha_source_mode = info.sourceAlpha;
2324 			fState->alpha_function_mode = info.alphaFunction;
2325 
2326 			fState->valid_flags |= B_VIEW_BLENDING_BIT;
2327 		}
2328 	}
2329 
2330 	if (_sourceAlpha)
2331 		*_sourceAlpha = fState->alpha_source_mode;
2332 
2333 	if (_alphaFunction)
2334 		*_alphaFunction = fState->alpha_function_mode;
2335 }
2336 
2337 
2338 void
MovePenTo(BPoint point)2339 BView::MovePenTo(BPoint point)
2340 {
2341 	MovePenTo(point.x, point.y);
2342 }
2343 
2344 
2345 void
MovePenTo(float x,float y)2346 BView::MovePenTo(float x, float y)
2347 {
2348 	if (fState->IsValid(B_VIEW_PEN_LOCATION_BIT)
2349 		&& x == fState->pen_location.x && y == fState->pen_location.y)
2350 		return;
2351 
2352 	if (fOwner) {
2353 		_CheckLockAndSwitchCurrent();
2354 
2355 		fOwner->fLink->StartMessage(AS_VIEW_SET_PEN_LOC);
2356 		fOwner->fLink->Attach<BPoint>(BPoint(x, y));
2357 
2358 		fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT;
2359 	}
2360 
2361 	fState->pen_location.x = x;
2362 	fState->pen_location.y = y;
2363 
2364 	fState->archiving_flags |= B_VIEW_PEN_LOCATION_BIT;
2365 }
2366 
2367 
2368 void
MovePenBy(float x,float y)2369 BView::MovePenBy(float x, float y)
2370 {
2371 	// this will update the pen location if necessary
2372 	if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT))
2373 		PenLocation();
2374 
2375 	MovePenTo(fState->pen_location.x + x, fState->pen_location.y + y);
2376 }
2377 
2378 
2379 BPoint
PenLocation() const2380 BView::PenLocation() const
2381 {
2382 	if (!fState->IsValid(B_VIEW_PEN_LOCATION_BIT) && fOwner) {
2383 		_CheckLockAndSwitchCurrent();
2384 
2385 		fOwner->fLink->StartMessage(AS_VIEW_GET_PEN_LOC);
2386 
2387 		int32 code;
2388 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2389 			&& code == B_OK) {
2390 			fOwner->fLink->Read<BPoint>(&fState->pen_location);
2391 
2392 			fState->valid_flags |= B_VIEW_PEN_LOCATION_BIT;
2393 		}
2394 	}
2395 
2396 	return fState->pen_location;
2397 }
2398 
2399 
2400 void
SetPenSize(float size)2401 BView::SetPenSize(float size)
2402 {
2403 	if (fState->IsValid(B_VIEW_PEN_SIZE_BIT) && size == fState->pen_size)
2404 		return;
2405 
2406 	if (fOwner) {
2407 		_CheckLockAndSwitchCurrent();
2408 
2409 		fOwner->fLink->StartMessage(AS_VIEW_SET_PEN_SIZE);
2410 		fOwner->fLink->Attach<float>(size);
2411 
2412 		fState->valid_flags |= B_VIEW_PEN_SIZE_BIT;
2413 	}
2414 
2415 	fState->pen_size = size;
2416 	fState->archiving_flags	|= B_VIEW_PEN_SIZE_BIT;
2417 }
2418 
2419 
2420 float
PenSize() const2421 BView::PenSize() const
2422 {
2423 	if (!fState->IsValid(B_VIEW_PEN_SIZE_BIT) && fOwner) {
2424 		_CheckLockAndSwitchCurrent();
2425 
2426 		fOwner->fLink->StartMessage(AS_VIEW_GET_PEN_SIZE);
2427 
2428 		int32 code;
2429 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2430 			&& code == B_OK) {
2431 			fOwner->fLink->Read<float>(&fState->pen_size);
2432 
2433 			fState->valid_flags |= B_VIEW_PEN_SIZE_BIT;
2434 		}
2435 	}
2436 
2437 	return fState->pen_size;
2438 }
2439 
2440 
2441 void
SetHighColor(rgb_color color)2442 BView::SetHighColor(rgb_color color)
2443 {
2444 	SetHighUIColor(B_NO_COLOR);
2445 
2446 	// are we up-to-date already?
2447 	if (fState->IsValid(B_VIEW_HIGH_COLOR_BIT)
2448 		&& fState->high_color == color)
2449 		return;
2450 
2451 	if (fOwner) {
2452 		_CheckLockAndSwitchCurrent();
2453 
2454 		fOwner->fLink->StartMessage(AS_VIEW_SET_HIGH_COLOR);
2455 		fOwner->fLink->Attach<rgb_color>(color);
2456 
2457 		fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
2458 	}
2459 
2460 	fState->high_color = color;
2461 
2462 	fState->archiving_flags |= B_VIEW_HIGH_COLOR_BIT;
2463 }
2464 
2465 
2466 rgb_color
HighColor() const2467 BView::HighColor() const
2468 {
2469 	if (!fState->IsValid(B_VIEW_HIGH_COLOR_BIT) && fOwner) {
2470 		_CheckLockAndSwitchCurrent();
2471 
2472 		fOwner->fLink->StartMessage(AS_VIEW_GET_HIGH_COLOR);
2473 
2474 		int32 code;
2475 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2476 			&& code == B_OK) {
2477 			fOwner->fLink->Read<rgb_color>(&fState->high_color);
2478 
2479 			fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
2480 		}
2481 	}
2482 
2483 	return fState->high_color;
2484 }
2485 
2486 
2487 void
SetHighUIColor(color_which which,float tint)2488 BView::SetHighUIColor(color_which which, float tint)
2489 {
2490 	if (fState->IsValid(B_VIEW_WHICH_HIGH_COLOR_BIT)
2491 		&& fState->which_high_color == which
2492 		&& fState->which_high_color_tint == tint)
2493 		return;
2494 
2495 	if (fOwner != NULL) {
2496 		_CheckLockAndSwitchCurrent();
2497 
2498 		fOwner->fLink->StartMessage(AS_VIEW_SET_HIGH_UI_COLOR);
2499 		fOwner->fLink->Attach<color_which>(which);
2500 		fOwner->fLink->Attach<float>(tint);
2501 
2502 		fState->valid_flags |= B_VIEW_WHICH_HIGH_COLOR_BIT;
2503 	}
2504 
2505 	fState->which_high_color = which;
2506 	fState->which_high_color_tint = tint;
2507 
2508 	if (which != B_NO_COLOR) {
2509 		fState->archiving_flags |= B_VIEW_WHICH_HIGH_COLOR_BIT;
2510 		fState->archiving_flags &= ~B_VIEW_HIGH_COLOR_BIT;
2511 		fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
2512 
2513 		fState->high_color = tint_color(ui_color(which), tint);
2514 	} else {
2515 		fState->valid_flags &= ~B_VIEW_HIGH_COLOR_BIT;
2516 		fState->archiving_flags &= ~B_VIEW_WHICH_HIGH_COLOR_BIT;
2517 	}
2518 }
2519 
2520 
2521 color_which
HighUIColor(float * tint) const2522 BView::HighUIColor(float* tint) const
2523 {
2524 	if (!fState->IsValid(B_VIEW_WHICH_HIGH_COLOR_BIT)
2525 		&& fOwner != NULL) {
2526 		_CheckLockAndSwitchCurrent();
2527 
2528 		fOwner->fLink->StartMessage(AS_VIEW_GET_HIGH_UI_COLOR);
2529 
2530 		int32 code;
2531 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2532 			&& code == B_OK) {
2533 			fOwner->fLink->Read<color_which>(&fState->which_high_color);
2534 			fOwner->fLink->Read<float>(&fState->which_high_color_tint);
2535 			fOwner->fLink->Read<rgb_color>(&fState->high_color);
2536 
2537 			fState->valid_flags |= B_VIEW_WHICH_HIGH_COLOR_BIT;
2538 			fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
2539 		}
2540 	}
2541 
2542 	if (tint != NULL)
2543 		*tint = fState->which_high_color_tint;
2544 
2545 	return fState->which_high_color;
2546 }
2547 
2548 
2549 void
SetLowColor(rgb_color color)2550 BView::SetLowColor(rgb_color color)
2551 {
2552 	SetLowUIColor(B_NO_COLOR);
2553 
2554 	if (fState->IsValid(B_VIEW_LOW_COLOR_BIT)
2555 		&& fState->low_color == color)
2556 		return;
2557 
2558 	if (fOwner) {
2559 		_CheckLockAndSwitchCurrent();
2560 
2561 		fOwner->fLink->StartMessage(AS_VIEW_SET_LOW_COLOR);
2562 		fOwner->fLink->Attach<rgb_color>(color);
2563 
2564 		fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
2565 	}
2566 
2567 	fState->low_color = color;
2568 
2569 	fState->archiving_flags |= B_VIEW_LOW_COLOR_BIT;
2570 }
2571 
2572 
2573 rgb_color
LowColor() const2574 BView::LowColor() const
2575 {
2576 	if (!fState->IsValid(B_VIEW_LOW_COLOR_BIT) && fOwner) {
2577 		_CheckLockAndSwitchCurrent();
2578 
2579 		fOwner->fLink->StartMessage(AS_VIEW_GET_LOW_COLOR);
2580 
2581 		int32 code;
2582 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2583 			&& code == B_OK) {
2584 			fOwner->fLink->Read<rgb_color>(&fState->low_color);
2585 
2586 			fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
2587 		}
2588 	}
2589 
2590 	return fState->low_color;
2591 }
2592 
2593 
2594 void
SetLowUIColor(color_which which,float tint)2595 BView::SetLowUIColor(color_which which, float tint)
2596 {
2597 	if (fState->IsValid(B_VIEW_WHICH_LOW_COLOR_BIT)
2598 		&& fState->which_low_color == which
2599 		&& fState->which_low_color_tint == tint)
2600 		return;
2601 
2602 	if (fOwner != NULL) {
2603 		_CheckLockAndSwitchCurrent();
2604 
2605 		fOwner->fLink->StartMessage(AS_VIEW_SET_LOW_UI_COLOR);
2606 		fOwner->fLink->Attach<color_which>(which);
2607 		fOwner->fLink->Attach<float>(tint);
2608 
2609 		fState->valid_flags |= B_VIEW_WHICH_LOW_COLOR_BIT;
2610 	}
2611 
2612 	fState->which_low_color = which;
2613 	fState->which_low_color_tint = tint;
2614 
2615 	if (which != B_NO_COLOR) {
2616 		fState->archiving_flags |= B_VIEW_WHICH_LOW_COLOR_BIT;
2617 		fState->archiving_flags &= ~B_VIEW_LOW_COLOR_BIT;
2618 		fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
2619 
2620 		fState->low_color = tint_color(ui_color(which), tint);
2621 	} else {
2622 		fState->valid_flags &= ~B_VIEW_LOW_COLOR_BIT;
2623 		fState->archiving_flags &= ~B_VIEW_WHICH_LOW_COLOR_BIT;
2624 	}
2625 }
2626 
2627 
2628 color_which
LowUIColor(float * tint) const2629 BView::LowUIColor(float* tint) const
2630 {
2631 	if (!fState->IsValid(B_VIEW_WHICH_LOW_COLOR_BIT)
2632 		&& fOwner != NULL) {
2633 		_CheckLockAndSwitchCurrent();
2634 
2635 		fOwner->fLink->StartMessage(AS_VIEW_GET_LOW_UI_COLOR);
2636 
2637 		int32 code;
2638 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2639 			&& code == B_OK) {
2640 			fOwner->fLink->Read<color_which>(&fState->which_low_color);
2641 			fOwner->fLink->Read<float>(&fState->which_low_color_tint);
2642 			fOwner->fLink->Read<rgb_color>(&fState->low_color);
2643 
2644 			fState->valid_flags |= B_VIEW_WHICH_LOW_COLOR_BIT;
2645 			fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
2646 		}
2647 	}
2648 
2649 	if (tint != NULL)
2650 		*tint = fState->which_low_color_tint;
2651 
2652 	return fState->which_low_color;
2653 }
2654 
2655 
2656 bool
HasDefaultColors() const2657 BView::HasDefaultColors() const
2658 {
2659 	// If we don't have any of these flags, then we have default colors
2660 	uint32 testMask = B_VIEW_VIEW_COLOR_BIT | B_VIEW_HIGH_COLOR_BIT
2661 		| B_VIEW_LOW_COLOR_BIT | B_VIEW_WHICH_VIEW_COLOR_BIT
2662 		| B_VIEW_WHICH_HIGH_COLOR_BIT | B_VIEW_WHICH_LOW_COLOR_BIT;
2663 
2664 	return (fState->archiving_flags & testMask) == 0;
2665 }
2666 
2667 
2668 bool
HasSystemColors() const2669 BView::HasSystemColors() const
2670 {
2671 	return fState->which_view_color == B_PANEL_BACKGROUND_COLOR
2672 		&& fState->which_high_color == B_PANEL_TEXT_COLOR
2673 		&& fState->which_low_color == B_PANEL_BACKGROUND_COLOR
2674 		&& fState->which_view_color_tint == B_NO_TINT
2675 		&& fState->which_high_color_tint == B_NO_TINT
2676 		&& fState->which_low_color_tint == B_NO_TINT;
2677 }
2678 
2679 
2680 void
AdoptParentColors()2681 BView::AdoptParentColors()
2682 {
2683 	AdoptViewColors(Parent());
2684 }
2685 
2686 
2687 void
AdoptSystemColors()2688 BView::AdoptSystemColors()
2689 {
2690 	SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
2691 	SetLowUIColor(B_PANEL_BACKGROUND_COLOR);
2692 	SetHighUIColor(B_PANEL_TEXT_COLOR);
2693 }
2694 
2695 
2696 void
AdoptViewColors(BView * view)2697 BView::AdoptViewColors(BView* view)
2698 {
2699 	if (view == NULL || (view->Window() != NULL && !view->LockLooper()))
2700 		return;
2701 
2702 	float tint = B_NO_TINT;
2703 	float viewTint = tint;
2704 	color_which viewWhich = view->ViewUIColor(&viewTint);
2705 
2706 	// View color
2707 	if (viewWhich != B_NO_COLOR)
2708 		SetViewUIColor(viewWhich, viewTint);
2709 	else
2710 		SetViewColor(view->ViewColor());
2711 
2712 	// Low color
2713 	color_which which = view->LowUIColor(&tint);
2714 	if (which != B_NO_COLOR)
2715 		SetLowUIColor(which, tint);
2716 	else if (viewWhich != B_NO_COLOR)
2717 		SetLowUIColor(viewWhich, viewTint);
2718 	else
2719 		SetLowColor(view->LowColor());
2720 
2721 	// High color
2722 	which = view->HighUIColor(&tint);
2723 	if (which != B_NO_COLOR)
2724 		SetHighUIColor(which, tint);
2725 	else
2726 		SetHighColor(view->HighColor());
2727 
2728 	if (view->Window() != NULL)
2729 		view->UnlockLooper();
2730 }
2731 
2732 
2733 void
SetViewColor(rgb_color color)2734 BView::SetViewColor(rgb_color color)
2735 {
2736 	SetViewUIColor(B_NO_COLOR);
2737 
2738 	if (fState->IsValid(B_VIEW_VIEW_COLOR_BIT)
2739 		&& fState->view_color == color)
2740 		return;
2741 
2742 	if (fOwner) {
2743 		_CheckLockAndSwitchCurrent();
2744 
2745 		fOwner->fLink->StartMessage(AS_VIEW_SET_VIEW_COLOR);
2746 		fOwner->fLink->Attach<rgb_color>(color);
2747 		fOwner->fLink->Flush();
2748 
2749 		fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
2750 	}
2751 
2752 	fState->view_color = color;
2753 
2754 	fState->archiving_flags |= B_VIEW_VIEW_COLOR_BIT;
2755 }
2756 
2757 
2758 rgb_color
ViewColor() const2759 BView::ViewColor() const
2760 {
2761 	if (!fState->IsValid(B_VIEW_VIEW_COLOR_BIT) && fOwner) {
2762 		_CheckLockAndSwitchCurrent();
2763 
2764 		fOwner->fLink->StartMessage(AS_VIEW_GET_VIEW_COLOR);
2765 
2766 		int32 code;
2767 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2768 			&& code == B_OK) {
2769 			fOwner->fLink->Read<rgb_color>(&fState->view_color);
2770 
2771 			fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
2772 		}
2773 	}
2774 
2775 	return fState->view_color;
2776 }
2777 
2778 
2779 void
SetViewUIColor(color_which which,float tint)2780 BView::SetViewUIColor(color_which which, float tint)
2781 {
2782 	if (fState->IsValid(B_VIEW_WHICH_VIEW_COLOR_BIT)
2783 		&& fState->which_view_color == which
2784 		&& fState->which_view_color_tint == tint)
2785 		return;
2786 
2787 	if (fOwner != NULL) {
2788 		_CheckLockAndSwitchCurrent();
2789 
2790 		fOwner->fLink->StartMessage(AS_VIEW_SET_VIEW_UI_COLOR);
2791 		fOwner->fLink->Attach<color_which>(which);
2792 		fOwner->fLink->Attach<float>(tint);
2793 
2794 		fState->valid_flags |= B_VIEW_WHICH_VIEW_COLOR_BIT;
2795 	}
2796 
2797 	fState->which_view_color = which;
2798 	fState->which_view_color_tint = tint;
2799 
2800 	if (which != B_NO_COLOR) {
2801 		fState->archiving_flags |= B_VIEW_WHICH_VIEW_COLOR_BIT;
2802 		fState->archiving_flags &= ~B_VIEW_VIEW_COLOR_BIT;
2803 		fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
2804 
2805 		fState->view_color = tint_color(ui_color(which), tint);
2806 	} else {
2807 		fState->valid_flags &= ~B_VIEW_VIEW_COLOR_BIT;
2808 		fState->archiving_flags &= ~B_VIEW_WHICH_VIEW_COLOR_BIT;
2809 	}
2810 
2811 	if (!fState->IsValid(B_VIEW_WHICH_LOW_COLOR_BIT))
2812 		SetLowUIColor(which, tint);
2813 }
2814 
2815 
2816 color_which
ViewUIColor(float * tint) const2817 BView::ViewUIColor(float* tint) const
2818 {
2819 	if (!fState->IsValid(B_VIEW_WHICH_VIEW_COLOR_BIT)
2820 		&& fOwner != NULL) {
2821 		_CheckLockAndSwitchCurrent();
2822 
2823 		fOwner->fLink->StartMessage(AS_VIEW_GET_VIEW_UI_COLOR);
2824 
2825 		int32 code;
2826 		if (fOwner->fLink->FlushWithReply(code) == B_OK
2827 			&& code == B_OK) {
2828 			fOwner->fLink->Read<color_which>(&fState->which_view_color);
2829 			fOwner->fLink->Read<float>(&fState->which_view_color_tint);
2830 			fOwner->fLink->Read<rgb_color>(&fState->view_color);
2831 
2832 			fState->valid_flags |= B_VIEW_WHICH_VIEW_COLOR_BIT;
2833 			fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
2834 		}
2835 	}
2836 
2837 	if (tint != NULL)
2838 		*tint = fState->which_view_color_tint;
2839 
2840 	return fState->which_view_color;
2841 }
2842 
2843 
2844 void
ForceFontAliasing(bool enable)2845 BView::ForceFontAliasing(bool enable)
2846 {
2847 	if (fState->IsValid(B_VIEW_FONT_ALIASING_BIT)
2848 		&& enable == fState->font_aliasing)
2849 		return;
2850 
2851 	if (fOwner) {
2852 		_CheckLockAndSwitchCurrent();
2853 
2854 		fOwner->fLink->StartMessage(AS_VIEW_PRINT_ALIASING);
2855 		fOwner->fLink->Attach<bool>(enable);
2856 
2857 		fState->valid_flags |= B_VIEW_FONT_ALIASING_BIT;
2858 	}
2859 
2860 	fState->font_aliasing = enable;
2861 	fState->archiving_flags |= B_VIEW_FONT_ALIASING_BIT;
2862 }
2863 
2864 
2865 void
SetFont(const BFont * font,uint32 mask)2866 BView::SetFont(const BFont* font, uint32 mask)
2867 {
2868 	if (!font || mask == 0)
2869 		return;
2870 
2871 	if (mask == B_FONT_ALL) {
2872 		fState->font = *font;
2873 	} else {
2874 		// TODO: move this into a BFont method
2875 		if (mask & B_FONT_FAMILY_AND_STYLE)
2876 			fState->font.SetFamilyAndStyle(font->FamilyAndStyle());
2877 
2878 		if (mask & B_FONT_SIZE)
2879 			fState->font.SetSize(font->Size());
2880 
2881 		if (mask & B_FONT_SHEAR)
2882 			fState->font.SetShear(font->Shear());
2883 
2884 		if (mask & B_FONT_ROTATION)
2885 			fState->font.SetRotation(font->Rotation());
2886 
2887 		if (mask & B_FONT_FALSE_BOLD_WIDTH)
2888 			fState->font.SetFalseBoldWidth(font->FalseBoldWidth());
2889 
2890 		if (mask & B_FONT_SPACING)
2891 			fState->font.SetSpacing(font->Spacing());
2892 
2893 		if (mask & B_FONT_ENCODING)
2894 			fState->font.SetEncoding(font->Encoding());
2895 
2896 		if (mask & B_FONT_FACE)
2897 			fState->font.SetFace(font->Face());
2898 
2899 		if (mask & B_FONT_FLAGS)
2900 			fState->font.SetFlags(font->Flags());
2901 	}
2902 
2903 	fState->font_flags |= mask;
2904 
2905 	if (fOwner) {
2906 		_CheckLockAndSwitchCurrent();
2907 
2908 		fState->UpdateServerFontState(*fOwner->fLink);
2909 		fState->valid_flags |= B_VIEW_FONT_BIT;
2910 	}
2911 
2912 	fState->archiving_flags |= B_VIEW_FONT_BIT;
2913 	// TODO: InvalidateLayout() here for convenience?
2914 }
2915 
2916 
2917 void
GetFont(BFont * font) const2918 BView::GetFont(BFont* font) const
2919 {
2920 	if (!fState->IsValid(B_VIEW_FONT_BIT)) {
2921 		// we don't keep graphics state information, therefor
2922 		// we need to ask the server for the origin after PopState()
2923 		_CheckOwnerLockAndSwitchCurrent();
2924 
2925 		// TODO: add a font getter!
2926 		fState->UpdateFrom(*fOwner->fLink);
2927 	}
2928 
2929 	*font = fState->font;
2930 }
2931 
2932 
2933 void
GetFontHeight(font_height * height) const2934 BView::GetFontHeight(font_height* height) const
2935 {
2936 	fState->font.GetHeight(height);
2937 }
2938 
2939 
2940 void
SetFontSize(float size)2941 BView::SetFontSize(float size)
2942 {
2943 	BFont font;
2944 	font.SetSize(size);
2945 
2946 	SetFont(&font, B_FONT_SIZE);
2947 }
2948 
2949 
2950 float
StringWidth(const char * string) const2951 BView::StringWidth(const char* string) const
2952 {
2953 	return fState->font.StringWidth(string);
2954 }
2955 
2956 
2957 float
StringWidth(const char * string,int32 length) const2958 BView::StringWidth(const char* string, int32 length) const
2959 {
2960 	return fState->font.StringWidth(string, length);
2961 }
2962 
2963 
2964 void
GetStringWidths(char * stringArray[],int32 lengthArray[],int32 numStrings,float widthArray[]) const2965 BView::GetStringWidths(char* stringArray[], int32 lengthArray[],
2966 	int32 numStrings, float widthArray[]) const
2967 {
2968 	fState->font.GetStringWidths(const_cast<const char**>(stringArray),
2969 		const_cast<const int32*>(lengthArray), numStrings, widthArray);
2970 }
2971 
2972 
2973 void
TruncateString(BString * string,uint32 mode,float width) const2974 BView::TruncateString(BString* string, uint32 mode, float width) const
2975 {
2976 	fState->font.TruncateString(string, mode, width);
2977 }
2978 
2979 
2980 void
ClipToPicture(BPicture * picture,BPoint where,bool sync)2981 BView::ClipToPicture(BPicture* picture, BPoint where, bool sync)
2982 {
2983 	_ClipToPicture(picture, where, false, sync);
2984 }
2985 
2986 
2987 void
ClipToInversePicture(BPicture * picture,BPoint where,bool sync)2988 BView::ClipToInversePicture(BPicture* picture, BPoint where, bool sync)
2989 {
2990 	_ClipToPicture(picture, where, true, sync);
2991 }
2992 
2993 
2994 void
GetClippingRegion(BRegion * region) const2995 BView::GetClippingRegion(BRegion* region) const
2996 {
2997 	if (!region)
2998 		return;
2999 
3000 	// NOTE: the client has no idea when the clipping in the server
3001 	// changed, so it is always read from the server
3002 	region->MakeEmpty();
3003 
3004 
3005 	if (fOwner) {
3006 		if (fIsPrinting && _CheckOwnerLock()) {
3007 			region->Set(fState->print_rect);
3008 			return;
3009 		}
3010 
3011 		_CheckLockAndSwitchCurrent();
3012 		fOwner->fLink->StartMessage(AS_VIEW_GET_CLIP_REGION);
3013 
3014  		int32 code;
3015  		if (fOwner->fLink->FlushWithReply(code) == B_OK
3016  			&& code == B_OK) {
3017 			fOwner->fLink->ReadRegion(region);
3018 			fState->valid_flags |= B_VIEW_CLIP_REGION_BIT;
3019 		}
3020 	}
3021 }
3022 
3023 
3024 void
ConstrainClippingRegion(BRegion * region)3025 BView::ConstrainClippingRegion(BRegion* region)
3026 {
3027 	if (_CheckOwnerLockAndSwitchCurrent()) {
3028 		fOwner->fLink->StartMessage(AS_VIEW_SET_CLIP_REGION);
3029 
3030 		if (region) {
3031 			int32 count = region->CountRects();
3032 			fOwner->fLink->Attach<int32>(count);
3033 			if (count > 0)
3034 				fOwner->fLink->AttachRegion(*region);
3035 		} else {
3036 			fOwner->fLink->Attach<int32>(-1);
3037 			// '-1' means that in the app_server, there won't be any 'local'
3038 			// clipping region (it will be NULL)
3039 		}
3040 
3041 		_FlushIfNotInTransaction();
3042 
3043 		fState->valid_flags &= ~B_VIEW_CLIP_REGION_BIT;
3044 		fState->archiving_flags |= B_VIEW_CLIP_REGION_BIT;
3045 	}
3046 }
3047 
3048 
3049 void
ClipToRect(BRect rect)3050 BView::ClipToRect(BRect rect)
3051 {
3052 	_ClipToRect(rect, false);
3053 }
3054 
3055 
3056 void
ClipToInverseRect(BRect rect)3057 BView::ClipToInverseRect(BRect rect)
3058 {
3059 	_ClipToRect(rect, true);
3060 }
3061 
3062 
3063 void
ClipToShape(BShape * shape)3064 BView::ClipToShape(BShape* shape)
3065 {
3066 	_ClipToShape(shape, false);
3067 }
3068 
3069 
3070 void
ClipToInverseShape(BShape * shape)3071 BView::ClipToInverseShape(BShape* shape)
3072 {
3073 	_ClipToShape(shape, true);
3074 }
3075 
3076 
3077 //	#pragma mark - Drawing Functions
3078 
3079 
3080 void
DrawBitmapAsync(const BBitmap * bitmap,BRect bitmapRect,BRect viewRect,uint32 options)3081 BView::DrawBitmapAsync(const BBitmap* bitmap, BRect bitmapRect, BRect viewRect,
3082 	uint32 options)
3083 {
3084 	if (bitmap == NULL || fOwner == NULL
3085 		|| !bitmapRect.IsValid() || !viewRect.IsValid())
3086 		return;
3087 
3088 	_CheckLockAndSwitchCurrent();
3089 
3090 	ViewDrawBitmapInfo info;
3091 	info.bitmapToken = bitmap->_ServerToken();
3092 	info.options = options;
3093 	info.viewRect = viewRect;
3094 	info.bitmapRect = bitmapRect;
3095 
3096 	fOwner->fLink->StartMessage(AS_VIEW_DRAW_BITMAP);
3097 	fOwner->fLink->Attach<ViewDrawBitmapInfo>(info);
3098 
3099 	_FlushIfNotInTransaction();
3100 }
3101 
3102 
3103 void
DrawBitmapAsync(const BBitmap * bitmap,BRect bitmapRect,BRect viewRect)3104 BView::DrawBitmapAsync(const BBitmap* bitmap, BRect bitmapRect, BRect viewRect)
3105 {
3106 	DrawBitmapAsync(bitmap, bitmapRect, viewRect, 0);
3107 }
3108 
3109 
3110 void
DrawBitmapAsync(const BBitmap * bitmap,BRect viewRect)3111 BView::DrawBitmapAsync(const BBitmap* bitmap, BRect viewRect)
3112 {
3113 	if (bitmap && fOwner) {
3114 		DrawBitmapAsync(bitmap, bitmap->Bounds().OffsetToCopy(B_ORIGIN),
3115 			viewRect, 0);
3116 	}
3117 }
3118 
3119 
3120 void
DrawBitmapAsync(const BBitmap * bitmap,BPoint where)3121 BView::DrawBitmapAsync(const BBitmap* bitmap, BPoint where)
3122 {
3123 	if (bitmap == NULL || fOwner == NULL)
3124 		return;
3125 
3126 	_CheckLockAndSwitchCurrent();
3127 
3128 	ViewDrawBitmapInfo info;
3129 	info.bitmapToken = bitmap->_ServerToken();
3130 	info.options = 0;
3131 	info.bitmapRect = bitmap->Bounds().OffsetToCopy(B_ORIGIN);
3132 	info.viewRect = info.bitmapRect.OffsetToCopy(where);
3133 
3134 	fOwner->fLink->StartMessage(AS_VIEW_DRAW_BITMAP);
3135 	fOwner->fLink->Attach<ViewDrawBitmapInfo>(info);
3136 
3137 	_FlushIfNotInTransaction();
3138 }
3139 
3140 
3141 void
DrawBitmapAsync(const BBitmap * bitmap)3142 BView::DrawBitmapAsync(const BBitmap* bitmap)
3143 {
3144 	DrawBitmapAsync(bitmap, PenLocation());
3145 }
3146 
3147 
3148 void
DrawBitmap(const BBitmap * bitmap,BRect bitmapRect,BRect viewRect,uint32 options)3149 BView::DrawBitmap(const BBitmap* bitmap, BRect bitmapRect, BRect viewRect,
3150 	uint32 options)
3151 {
3152 	if (fOwner) {
3153 		DrawBitmapAsync(bitmap, bitmapRect, viewRect, options);
3154 		Sync();
3155 	}
3156 }
3157 
3158 
3159 void
DrawBitmap(const BBitmap * bitmap,BRect bitmapRect,BRect viewRect)3160 BView::DrawBitmap(const BBitmap* bitmap, BRect bitmapRect, BRect viewRect)
3161 {
3162 	if (fOwner) {
3163 		DrawBitmapAsync(bitmap, bitmapRect, viewRect, 0);
3164 		Sync();
3165 	}
3166 }
3167 
3168 
3169 void
DrawBitmap(const BBitmap * bitmap,BRect viewRect)3170 BView::DrawBitmap(const BBitmap* bitmap, BRect viewRect)
3171 {
3172 	if (bitmap && fOwner) {
3173 		DrawBitmap(bitmap, bitmap->Bounds().OffsetToCopy(B_ORIGIN), viewRect,
3174 			0);
3175 	}
3176 }
3177 
3178 
3179 void
DrawBitmap(const BBitmap * bitmap,BPoint where)3180 BView::DrawBitmap(const BBitmap* bitmap, BPoint where)
3181 {
3182 	if (fOwner) {
3183 		DrawBitmapAsync(bitmap, where);
3184 		Sync();
3185 	}
3186 }
3187 
3188 
3189 void
DrawBitmap(const BBitmap * bitmap)3190 BView::DrawBitmap(const BBitmap* bitmap)
3191 {
3192 	DrawBitmap(bitmap, PenLocation());
3193 }
3194 
3195 
3196 void
DrawTiledBitmapAsync(const BBitmap * bitmap,BRect viewRect,BPoint phase)3197 BView::DrawTiledBitmapAsync(const BBitmap* bitmap, BRect viewRect,
3198 	BPoint phase)
3199 {
3200 	if (bitmap == NULL || fOwner == NULL || !viewRect.IsValid())
3201 		return;
3202 
3203 	_CheckLockAndSwitchCurrent();
3204 
3205 	ViewDrawBitmapInfo info;
3206 	info.bitmapToken = bitmap->_ServerToken();
3207 	info.options = B_TILE_BITMAP;
3208 	info.viewRect = viewRect;
3209 	info.bitmapRect = bitmap->Bounds().OffsetToCopy(phase);
3210 
3211 	fOwner->fLink->StartMessage(AS_VIEW_DRAW_BITMAP);
3212 	fOwner->fLink->Attach<ViewDrawBitmapInfo>(info);
3213 
3214 	_FlushIfNotInTransaction();
3215 }
3216 
3217 
3218 void
DrawTiledBitmap(const BBitmap * bitmap,BRect viewRect,BPoint phase)3219 BView::DrawTiledBitmap(const BBitmap* bitmap, BRect viewRect, BPoint phase)
3220 {
3221 	if (fOwner) {
3222 		DrawTiledBitmapAsync(bitmap, viewRect, phase);
3223 		Sync();
3224 	}
3225 }
3226 
3227 
3228 void
DrawChar(char c)3229 BView::DrawChar(char c)
3230 {
3231 	DrawString(&c, 1, PenLocation());
3232 }
3233 
3234 
3235 void
DrawChar(char c,BPoint location)3236 BView::DrawChar(char c, BPoint location)
3237 {
3238 	DrawString(&c, 1, location);
3239 }
3240 
3241 
3242 void
DrawString(const char * string,escapement_delta * delta)3243 BView::DrawString(const char* string, escapement_delta* delta)
3244 {
3245 	if (string == NULL)
3246 		return;
3247 
3248 	DrawString(string, strlen(string), PenLocation(), delta);
3249 }
3250 
3251 
3252 void
DrawString(const char * string,BPoint location,escapement_delta * delta)3253 BView::DrawString(const char* string, BPoint location, escapement_delta* delta)
3254 {
3255 	if (string == NULL)
3256 		return;
3257 
3258 	DrawString(string, strlen(string), location, delta);
3259 }
3260 
3261 
3262 void
DrawString(const char * string,int32 length,escapement_delta * delta)3263 BView::DrawString(const char* string, int32 length, escapement_delta* delta)
3264 {
3265 	DrawString(string, length, PenLocation(), delta);
3266 }
3267 
3268 
3269 void
DrawString(const char * string,int32 length,BPoint location,escapement_delta * delta)3270 BView::DrawString(const char* string, int32 length, BPoint location,
3271 	escapement_delta* delta)
3272 {
3273 	if (fOwner == NULL || string == NULL || length < 1)
3274 		return;
3275 
3276 	_CheckLockAndSwitchCurrent();
3277 
3278 	ViewDrawStringInfo info;
3279 	info.stringLength = length;
3280 	info.location = location;
3281 	if (delta != NULL)
3282 		info.delta = *delta;
3283 
3284 	// quite often delta will be NULL
3285 	if (delta)
3286 		fOwner->fLink->StartMessage(AS_DRAW_STRING_WITH_DELTA);
3287 	else
3288 		fOwner->fLink->StartMessage(AS_DRAW_STRING);
3289 
3290 	fOwner->fLink->Attach<ViewDrawStringInfo>(info);
3291 	fOwner->fLink->Attach(string, length);
3292 
3293 	_FlushIfNotInTransaction();
3294 
3295 	// this modifies our pen location, so we invalidate the flag.
3296 	fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
3297 }
3298 
3299 
3300 void
DrawString(const char * string,const BPoint * locations,int32 locationCount)3301 BView::DrawString(const char* string, const BPoint* locations,
3302 	int32 locationCount)
3303 {
3304 	if (string == NULL)
3305 		return;
3306 
3307 	DrawString(string, strlen(string), locations, locationCount);
3308 }
3309 
3310 
3311 void
DrawString(const char * string,int32 length,const BPoint * locations,int32 locationCount)3312 BView::DrawString(const char* string, int32 length, const BPoint* locations,
3313 	int32 locationCount)
3314 {
3315 	if (fOwner == NULL || string == NULL || length < 1 || locations == NULL)
3316 		return;
3317 
3318 	_CheckLockAndSwitchCurrent();
3319 
3320 	fOwner->fLink->StartMessage(AS_DRAW_STRING_WITH_OFFSETS);
3321 
3322 	fOwner->fLink->Attach<int32>(length);
3323 	fOwner->fLink->Attach<int32>(locationCount);
3324 	fOwner->fLink->Attach(string, length);
3325 	fOwner->fLink->Attach(locations, locationCount * sizeof(BPoint));
3326 
3327 	_FlushIfNotInTransaction();
3328 
3329 	// this modifies our pen location, so we invalidate the flag.
3330 	fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
3331 }
3332 
3333 
3334 void
StrokeEllipse(BPoint center,float xRadius,float yRadius,::pattern pattern)3335 BView::StrokeEllipse(BPoint center, float xRadius, float yRadius,
3336 	::pattern pattern)
3337 {
3338 	StrokeEllipse(BRect(center.x - xRadius, center.y - yRadius,
3339 		center.x + xRadius, center.y + yRadius), pattern);
3340 }
3341 
3342 
3343 void
StrokeEllipse(BRect rect,::pattern pattern)3344 BView::StrokeEllipse(BRect rect, ::pattern pattern)
3345 {
3346 	if (fOwner == NULL)
3347 		return;
3348 
3349 	_CheckLockAndSwitchCurrent();
3350 	_UpdatePattern(pattern);
3351 
3352 	fOwner->fLink->StartMessage(AS_STROKE_ELLIPSE);
3353 	fOwner->fLink->Attach<BRect>(rect);
3354 
3355 	_FlushIfNotInTransaction();
3356 }
3357 
3358 
3359 void
FillEllipse(BPoint center,float xRadius,float yRadius,::pattern pattern)3360 BView::FillEllipse(BPoint center, float xRadius, float yRadius,
3361 	::pattern pattern)
3362 {
3363 	FillEllipse(BRect(center.x - xRadius, center.y - yRadius,
3364 		center.x + xRadius, center.y + yRadius), pattern);
3365 }
3366 
3367 
3368 void
FillEllipse(BPoint center,float xRadius,float yRadius,const BGradient & gradient)3369 BView::FillEllipse(BPoint center, float xRadius, float yRadius,
3370 	const BGradient& gradient)
3371 {
3372 	FillEllipse(BRect(center.x - xRadius, center.y - yRadius,
3373 		center.x + xRadius, center.y + yRadius), gradient);
3374 }
3375 
3376 
3377 void
FillEllipse(BRect rect,::pattern pattern)3378 BView::FillEllipse(BRect rect, ::pattern pattern)
3379 {
3380 	if (fOwner == NULL)
3381 		return;
3382 
3383 	_CheckLockAndSwitchCurrent();
3384 	_UpdatePattern(pattern);
3385 
3386 	fOwner->fLink->StartMessage(AS_FILL_ELLIPSE);
3387 	fOwner->fLink->Attach<BRect>(rect);
3388 
3389 	_FlushIfNotInTransaction();
3390 }
3391 
3392 
3393 void
FillEllipse(BRect rect,const BGradient & gradient)3394 BView::FillEllipse(BRect rect, const BGradient& gradient)
3395 {
3396 	if (fOwner == NULL)
3397 		return;
3398 
3399 	_CheckLockAndSwitchCurrent();
3400 
3401 	fOwner->fLink->StartMessage(AS_FILL_ELLIPSE_GRADIENT);
3402 	fOwner->fLink->Attach<BRect>(rect);
3403 	fOwner->fLink->AttachGradient(gradient);
3404 
3405 	_FlushIfNotInTransaction();
3406 }
3407 
3408 
3409 void
StrokeArc(BPoint center,float xRadius,float yRadius,float startAngle,float arcAngle,::pattern pattern)3410 BView::StrokeArc(BPoint center, float xRadius, float yRadius, float startAngle,
3411 	float arcAngle, ::pattern pattern)
3412 {
3413 	StrokeArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
3414 		center.y + yRadius), startAngle, arcAngle, pattern);
3415 }
3416 
3417 
3418 void
StrokeArc(BRect rect,float startAngle,float arcAngle,::pattern pattern)3419 BView::StrokeArc(BRect rect, float startAngle, float arcAngle,
3420 	::pattern pattern)
3421 {
3422 	if (fOwner == NULL)
3423 		return;
3424 
3425 	_CheckLockAndSwitchCurrent();
3426 	_UpdatePattern(pattern);
3427 
3428 	fOwner->fLink->StartMessage(AS_STROKE_ARC);
3429 	fOwner->fLink->Attach<BRect>(rect);
3430 	fOwner->fLink->Attach<float>(startAngle);
3431 	fOwner->fLink->Attach<float>(arcAngle);
3432 
3433 	_FlushIfNotInTransaction();
3434 }
3435 
3436 
3437 void
FillArc(BPoint center,float xRadius,float yRadius,float startAngle,float arcAngle,::pattern pattern)3438 BView::FillArc(BPoint center,float xRadius, float yRadius, float startAngle,
3439 	float arcAngle, ::pattern pattern)
3440 {
3441 	FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
3442 		center.y + yRadius), startAngle, arcAngle, pattern);
3443 }
3444 
3445 
3446 void
FillArc(BPoint center,float xRadius,float yRadius,float startAngle,float arcAngle,const BGradient & gradient)3447 BView::FillArc(BPoint center,float xRadius, float yRadius, float startAngle,
3448 	float arcAngle, const BGradient& gradient)
3449 {
3450 	FillArc(BRect(center.x - xRadius, center.y - yRadius, center.x + xRadius,
3451 		center.y + yRadius), startAngle, arcAngle, gradient);
3452 }
3453 
3454 
3455 void
FillArc(BRect rect,float startAngle,float arcAngle,::pattern pattern)3456 BView::FillArc(BRect rect, float startAngle, float arcAngle,
3457 	::pattern pattern)
3458 {
3459 	if (fOwner == NULL)
3460 		return;
3461 
3462 	_CheckLockAndSwitchCurrent();
3463 	_UpdatePattern(pattern);
3464 
3465 	fOwner->fLink->StartMessage(AS_FILL_ARC);
3466 	fOwner->fLink->Attach<BRect>(rect);
3467 	fOwner->fLink->Attach<float>(startAngle);
3468 	fOwner->fLink->Attach<float>(arcAngle);
3469 
3470 	_FlushIfNotInTransaction();
3471 }
3472 
3473 
3474 void
FillArc(BRect rect,float startAngle,float arcAngle,const BGradient & gradient)3475 BView::FillArc(BRect rect, float startAngle, float arcAngle,
3476 	const BGradient& gradient)
3477 {
3478 	if (fOwner == NULL)
3479 		return;
3480 
3481 	_CheckLockAndSwitchCurrent();
3482 
3483 	fOwner->fLink->StartMessage(AS_FILL_ARC_GRADIENT);
3484 	fOwner->fLink->Attach<BRect>(rect);
3485 	fOwner->fLink->Attach<float>(startAngle);
3486 	fOwner->fLink->Attach<float>(arcAngle);
3487 	fOwner->fLink->AttachGradient(gradient);
3488 
3489 	_FlushIfNotInTransaction();
3490 }
3491 
3492 
3493 void
StrokeBezier(BPoint * controlPoints,::pattern pattern)3494 BView::StrokeBezier(BPoint* controlPoints, ::pattern pattern)
3495 {
3496 	if (fOwner == NULL)
3497 		return;
3498 
3499 	_CheckLockAndSwitchCurrent();
3500 	_UpdatePattern(pattern);
3501 
3502 	fOwner->fLink->StartMessage(AS_STROKE_BEZIER);
3503 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
3504 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
3505 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
3506 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
3507 
3508 	_FlushIfNotInTransaction();
3509 }
3510 
3511 
3512 void
FillBezier(BPoint * controlPoints,::pattern pattern)3513 BView::FillBezier(BPoint* controlPoints, ::pattern pattern)
3514 {
3515 	if (fOwner == NULL)
3516 		return;
3517 
3518 	_CheckLockAndSwitchCurrent();
3519 	_UpdatePattern(pattern);
3520 
3521 	fOwner->fLink->StartMessage(AS_FILL_BEZIER);
3522 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
3523 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
3524 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
3525 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
3526 
3527 	_FlushIfNotInTransaction();
3528 }
3529 
3530 
3531 void
FillBezier(BPoint * controlPoints,const BGradient & gradient)3532 BView::FillBezier(BPoint* controlPoints, const BGradient& gradient)
3533 {
3534 	if (fOwner == NULL)
3535 		return;
3536 
3537 	_CheckLockAndSwitchCurrent();
3538 
3539 	fOwner->fLink->StartMessage(AS_FILL_BEZIER_GRADIENT);
3540 	fOwner->fLink->Attach<BPoint>(controlPoints[0]);
3541 	fOwner->fLink->Attach<BPoint>(controlPoints[1]);
3542 	fOwner->fLink->Attach<BPoint>(controlPoints[2]);
3543 	fOwner->fLink->Attach<BPoint>(controlPoints[3]);
3544 	fOwner->fLink->AttachGradient(gradient);
3545 
3546 	_FlushIfNotInTransaction();
3547 }
3548 
3549 
3550 void
StrokePolygon(const BPolygon * polygon,bool closed,::pattern pattern)3551 BView::StrokePolygon(const BPolygon* polygon, bool closed, ::pattern pattern)
3552 {
3553 	if (polygon == NULL)
3554 		return;
3555 
3556 	StrokePolygon(polygon->fPoints, polygon->fCount, polygon->Frame(), closed,
3557 		pattern);
3558 }
3559 
3560 
3561 void
StrokePolygon(const BPoint * pointArray,int32 numPoints,bool closed,::pattern pattern)3562 BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, bool closed,
3563 	::pattern pattern)
3564 {
3565 	BPolygon polygon(pointArray, numPoints);
3566 
3567 	StrokePolygon(polygon.fPoints, polygon.fCount, polygon.Frame(), closed,
3568 		pattern);
3569 }
3570 
3571 
3572 void
StrokePolygon(const BPoint * pointArray,int32 numPoints,BRect bounds,bool closed,::pattern pattern)3573 BView::StrokePolygon(const BPoint* pointArray, int32 numPoints, BRect bounds,
3574 	bool closed, ::pattern pattern)
3575 {
3576 	if (pointArray == NULL
3577 		|| numPoints <= 1
3578 		|| fOwner == NULL)
3579 		return;
3580 
3581 	_CheckLockAndSwitchCurrent();
3582 	_UpdatePattern(pattern);
3583 
3584 	BPolygon polygon(pointArray, numPoints);
3585 	polygon.MapTo(polygon.Frame(), bounds);
3586 
3587 	if (fOwner->fLink->StartMessage(AS_STROKE_POLYGON,
3588 			polygon.fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(bool)
3589 				+ sizeof(int32)) == B_OK) {
3590 		fOwner->fLink->Attach<BRect>(polygon.Frame());
3591 		fOwner->fLink->Attach<bool>(closed);
3592 		fOwner->fLink->Attach<int32>(polygon.fCount);
3593 		fOwner->fLink->Attach(polygon.fPoints, polygon.fCount * sizeof(BPoint));
3594 
3595 		_FlushIfNotInTransaction();
3596 	} else {
3597 		fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
3598 	}
3599 }
3600 
3601 
3602 void
FillPolygon(const BPolygon * polygon,::pattern pattern)3603 BView::FillPolygon(const BPolygon* polygon, ::pattern pattern)
3604 {
3605 	if (polygon == NULL
3606 		|| polygon->fCount <= 2
3607 		|| fOwner == NULL)
3608 		return;
3609 
3610 	_CheckLockAndSwitchCurrent();
3611 	_UpdatePattern(pattern);
3612 
3613 	if (fOwner->fLink->StartMessage(AS_FILL_POLYGON,
3614 			polygon->fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(int32))
3615 				== B_OK) {
3616 		fOwner->fLink->Attach<BRect>(polygon->Frame());
3617 		fOwner->fLink->Attach<int32>(polygon->fCount);
3618 		fOwner->fLink->Attach(polygon->fPoints,
3619 			polygon->fCount * sizeof(BPoint));
3620 
3621 		_FlushIfNotInTransaction();
3622 	} else {
3623 		fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
3624 	}
3625 }
3626 
3627 
3628 void
FillPolygon(const BPolygon * polygon,const BGradient & gradient)3629 BView::FillPolygon(const BPolygon* polygon, const BGradient& gradient)
3630 {
3631 	if (polygon == NULL
3632 		|| polygon->fCount <= 2
3633 		|| fOwner == NULL)
3634 		return;
3635 
3636 	_CheckLockAndSwitchCurrent();
3637 
3638 	if (fOwner->fLink->StartMessage(AS_FILL_POLYGON_GRADIENT,
3639 			polygon->fCount * sizeof(BPoint) + sizeof(BRect) + sizeof(int32))
3640 				== B_OK) {
3641 		fOwner->fLink->Attach<BRect>(polygon->Frame());
3642 		fOwner->fLink->Attach<int32>(polygon->fCount);
3643 		fOwner->fLink->Attach(polygon->fPoints,
3644 			polygon->fCount * sizeof(BPoint));
3645 		fOwner->fLink->AttachGradient(gradient);
3646 
3647 		_FlushIfNotInTransaction();
3648 	} else {
3649 		fprintf(stderr, "ERROR: Can't send polygon to app_server!\n");
3650 	}
3651 }
3652 
3653 
3654 void
FillPolygon(const BPoint * pointArray,int32 numPoints,::pattern pattern)3655 BView::FillPolygon(const BPoint* pointArray, int32 numPoints, ::pattern pattern)
3656 {
3657 	if (pointArray == NULL)
3658 		return;
3659 
3660 	BPolygon polygon(pointArray, numPoints);
3661 	FillPolygon(&polygon, pattern);
3662 }
3663 
3664 
3665 void
FillPolygon(const BPoint * pointArray,int32 numPoints,const BGradient & gradient)3666 BView::FillPolygon(const BPoint* pointArray, int32 numPoints,
3667 	const BGradient& gradient)
3668 {
3669 	if (pointArray == NULL)
3670 		return;
3671 
3672 	BPolygon polygon(pointArray, numPoints);
3673 	FillPolygon(&polygon, gradient);
3674 }
3675 
3676 
3677 void
FillPolygon(const BPoint * pointArray,int32 numPoints,BRect bounds,::pattern pattern)3678 BView::FillPolygon(const BPoint* pointArray, int32 numPoints, BRect bounds,
3679 	::pattern pattern)
3680 {
3681 	if (pointArray == NULL)
3682 		return;
3683 
3684 	BPolygon polygon(pointArray, numPoints);
3685 
3686 	polygon.MapTo(polygon.Frame(), bounds);
3687 	FillPolygon(&polygon, pattern);
3688 }
3689 
3690 
3691 void
FillPolygon(const BPoint * pointArray,int32 numPoints,BRect bounds,const BGradient & gradient)3692 BView::FillPolygon(const BPoint* pointArray, int32 numPoints, BRect bounds,
3693 	const BGradient& gradient)
3694 {
3695 	if (pointArray == NULL)
3696 		return;
3697 
3698 	BPolygon polygon(pointArray, numPoints);
3699 
3700 	polygon.MapTo(polygon.Frame(), bounds);
3701 	FillPolygon(&polygon, gradient);
3702 }
3703 
3704 
3705 void
StrokeRect(BRect rect,::pattern pattern)3706 BView::StrokeRect(BRect rect, ::pattern pattern)
3707 {
3708 	if (fOwner == NULL)
3709 		return;
3710 
3711 	_CheckLockAndSwitchCurrent();
3712 	_UpdatePattern(pattern);
3713 
3714 	fOwner->fLink->StartMessage(AS_STROKE_RECT);
3715 	fOwner->fLink->Attach<BRect>(rect);
3716 
3717 	_FlushIfNotInTransaction();
3718 }
3719 
3720 
3721 void
FillRect(BRect rect,::pattern pattern)3722 BView::FillRect(BRect rect, ::pattern pattern)
3723 {
3724 	if (fOwner == NULL)
3725 		return;
3726 
3727 	// NOTE: ensuring compatibility with R5,
3728 	// invalid rects are not filled, they are stroked though!
3729 	if (!rect.IsValid())
3730 		return;
3731 
3732 	_CheckLockAndSwitchCurrent();
3733 	_UpdatePattern(pattern);
3734 
3735 	fOwner->fLink->StartMessage(AS_FILL_RECT);
3736 	fOwner->fLink->Attach<BRect>(rect);
3737 
3738 	_FlushIfNotInTransaction();
3739 }
3740 
3741 
3742 void
FillRect(BRect rect,const BGradient & gradient)3743 BView::FillRect(BRect rect, const BGradient& gradient)
3744 {
3745 	if (fOwner == NULL)
3746 		return;
3747 
3748 	// NOTE: ensuring compatibility with R5,
3749 	// invalid rects are not filled, they are stroked though!
3750 	if (!rect.IsValid())
3751 		return;
3752 
3753 	_CheckLockAndSwitchCurrent();
3754 
3755 	fOwner->fLink->StartMessage(AS_FILL_RECT_GRADIENT);
3756 	fOwner->fLink->Attach<BRect>(rect);
3757 	fOwner->fLink->AttachGradient(gradient);
3758 
3759 	_FlushIfNotInTransaction();
3760 }
3761 
3762 
3763 void
StrokeRoundRect(BRect rect,float xRadius,float yRadius,::pattern pattern)3764 BView::StrokeRoundRect(BRect rect, float xRadius, float yRadius,
3765 	::pattern pattern)
3766 {
3767 	if (fOwner == NULL)
3768 		return;
3769 
3770 	_CheckLockAndSwitchCurrent();
3771 	_UpdatePattern(pattern);
3772 
3773 	fOwner->fLink->StartMessage(AS_STROKE_ROUNDRECT);
3774 	fOwner->fLink->Attach<BRect>(rect);
3775 	fOwner->fLink->Attach<float>(xRadius);
3776 	fOwner->fLink->Attach<float>(yRadius);
3777 
3778 	_FlushIfNotInTransaction();
3779 }
3780 
3781 
3782 void
FillRoundRect(BRect rect,float xRadius,float yRadius,::pattern pattern)3783 BView::FillRoundRect(BRect rect, float xRadius, float yRadius,
3784 	::pattern pattern)
3785 {
3786 	if (fOwner == NULL)
3787 		return;
3788 
3789 	_CheckLockAndSwitchCurrent();
3790 
3791 	_UpdatePattern(pattern);
3792 
3793 	fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT);
3794 	fOwner->fLink->Attach<BRect>(rect);
3795 	fOwner->fLink->Attach<float>(xRadius);
3796 	fOwner->fLink->Attach<float>(yRadius);
3797 
3798 	_FlushIfNotInTransaction();
3799 }
3800 
3801 
3802 void
FillRoundRect(BRect rect,float xRadius,float yRadius,const BGradient & gradient)3803 BView::FillRoundRect(BRect rect, float xRadius, float yRadius,
3804 	const BGradient& gradient)
3805 {
3806 	if (fOwner == NULL)
3807 		return;
3808 
3809 	_CheckLockAndSwitchCurrent();
3810 
3811 	fOwner->fLink->StartMessage(AS_FILL_ROUNDRECT_GRADIENT);
3812 	fOwner->fLink->Attach<BRect>(rect);
3813 	fOwner->fLink->Attach<float>(xRadius);
3814 	fOwner->fLink->Attach<float>(yRadius);
3815 	fOwner->fLink->AttachGradient(gradient);
3816 
3817 	_FlushIfNotInTransaction();
3818 }
3819 
3820 
3821 void
FillRegion(BRegion * region,::pattern pattern)3822 BView::FillRegion(BRegion* region, ::pattern pattern)
3823 {
3824 	if (region == NULL || fOwner == NULL)
3825 		return;
3826 
3827 	_CheckLockAndSwitchCurrent();
3828 
3829 	_UpdatePattern(pattern);
3830 
3831 	fOwner->fLink->StartMessage(AS_FILL_REGION);
3832 	fOwner->fLink->AttachRegion(*region);
3833 
3834 	_FlushIfNotInTransaction();
3835 }
3836 
3837 
3838 void
FillRegion(BRegion * region,const BGradient & gradient)3839 BView::FillRegion(BRegion* region, const BGradient& gradient)
3840 {
3841 	if (region == NULL || fOwner == NULL)
3842 		return;
3843 
3844 	_CheckLockAndSwitchCurrent();
3845 
3846 	fOwner->fLink->StartMessage(AS_FILL_REGION_GRADIENT);
3847 	fOwner->fLink->AttachRegion(*region);
3848 	fOwner->fLink->AttachGradient(gradient);
3849 
3850 	_FlushIfNotInTransaction();
3851 }
3852 
3853 
3854 void
StrokeTriangle(BPoint point1,BPoint point2,BPoint point3,BRect bounds,::pattern pattern)3855 BView::StrokeTriangle(BPoint point1, BPoint point2, BPoint point3, BRect bounds,
3856 	::pattern pattern)
3857 {
3858 	if (fOwner == NULL)
3859 		return;
3860 
3861 	_CheckLockAndSwitchCurrent();
3862 
3863 	_UpdatePattern(pattern);
3864 
3865 	fOwner->fLink->StartMessage(AS_STROKE_TRIANGLE);
3866 	fOwner->fLink->Attach<BPoint>(point1);
3867 	fOwner->fLink->Attach<BPoint>(point2);
3868 	fOwner->fLink->Attach<BPoint>(point3);
3869 	fOwner->fLink->Attach<BRect>(bounds);
3870 
3871 	_FlushIfNotInTransaction();
3872 }
3873 
3874 
3875 void
StrokeTriangle(BPoint point1,BPoint point2,BPoint point3,::pattern pattern)3876 BView::StrokeTriangle(BPoint point1, BPoint point2, BPoint point3,
3877 	::pattern pattern)
3878 {
3879 	if (fOwner) {
3880 		// we construct the smallest rectangle that contains the 3 points
3881 		// for the 1st point
3882 		BRect bounds(point1, point1);
3883 
3884 		// for the 2nd point
3885 		if (point2.x < bounds.left)
3886 			bounds.left = point2.x;
3887 
3888 		if (point2.y < bounds.top)
3889 			bounds.top = point2.y;
3890 
3891 		if (point2.x > bounds.right)
3892 			bounds.right = point2.x;
3893 
3894 		if (point2.y > bounds.bottom)
3895 			bounds.bottom = point2.y;
3896 
3897 		// for the 3rd point
3898 		if (point3.x < bounds.left)
3899 			bounds.left = point3.x;
3900 
3901 		if (point3.y < bounds.top)
3902 			bounds.top = point3.y;
3903 
3904 		if (point3.x > bounds.right)
3905 			bounds.right = point3.x;
3906 
3907 		if (point3.y > bounds.bottom)
3908 			bounds.bottom = point3.y;
3909 
3910 		StrokeTriangle(point1, point2, point3, bounds, pattern);
3911 	}
3912 }
3913 
3914 
3915 void
FillTriangle(BPoint point1,BPoint point2,BPoint point3,::pattern pattern)3916 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3,
3917 	::pattern pattern)
3918 {
3919 	if (fOwner) {
3920 		// we construct the smallest rectangle that contains the 3 points
3921 		// for the 1st point
3922 		BRect bounds(point1, point1);
3923 
3924 		// for the 2nd point
3925 		if (point2.x < bounds.left)
3926 			bounds.left = point2.x;
3927 
3928 		if (point2.y < bounds.top)
3929 			bounds.top = point2.y;
3930 
3931 		if (point2.x > bounds.right)
3932 			bounds.right = point2.x;
3933 
3934 		if (point2.y > bounds.bottom)
3935 			bounds.bottom = point2.y;
3936 
3937 		// for the 3rd point
3938 		if (point3.x < bounds.left)
3939 			bounds.left = point3.x;
3940 
3941 		if (point3.y < bounds.top)
3942 			bounds.top = point3.y;
3943 
3944 		if (point3.x > bounds.right)
3945 			bounds.right = point3.x;
3946 
3947 		if (point3.y > bounds.bottom)
3948 			bounds.bottom = point3.y;
3949 
3950 		FillTriangle(point1, point2, point3, bounds, pattern);
3951 	}
3952 }
3953 
3954 
3955 void
FillTriangle(BPoint point1,BPoint point2,BPoint point3,const BGradient & gradient)3956 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3,
3957 	const BGradient& gradient)
3958 {
3959 	if (fOwner) {
3960 		// we construct the smallest rectangle that contains the 3 points
3961 		// for the 1st point
3962 		BRect bounds(point1, point1);
3963 
3964 		// for the 2nd point
3965 		if (point2.x < bounds.left)
3966 			bounds.left = point2.x;
3967 
3968 		if (point2.y < bounds.top)
3969 			bounds.top = point2.y;
3970 
3971 		if (point2.x > bounds.right)
3972 			bounds.right = point2.x;
3973 
3974 		if (point2.y > bounds.bottom)
3975 			bounds.bottom = point2.y;
3976 
3977 		// for the 3rd point
3978 		if (point3.x < bounds.left)
3979 			bounds.left = point3.x;
3980 
3981 		if (point3.y < bounds.top)
3982 			bounds.top = point3.y;
3983 
3984 		if (point3.x > bounds.right)
3985 			bounds.right = point3.x;
3986 
3987 		if (point3.y > bounds.bottom)
3988 			bounds.bottom = point3.y;
3989 
3990 		FillTriangle(point1, point2, point3, bounds, gradient);
3991 	}
3992 }
3993 
3994 
3995 void
FillTriangle(BPoint point1,BPoint point2,BPoint point3,BRect bounds,::pattern pattern)3996 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3,
3997 	BRect bounds, ::pattern pattern)
3998 {
3999 	if (fOwner == NULL)
4000 		return;
4001 
4002 	_CheckLockAndSwitchCurrent();
4003 	_UpdatePattern(pattern);
4004 
4005 	fOwner->fLink->StartMessage(AS_FILL_TRIANGLE);
4006 	fOwner->fLink->Attach<BPoint>(point1);
4007 	fOwner->fLink->Attach<BPoint>(point2);
4008 	fOwner->fLink->Attach<BPoint>(point3);
4009 	fOwner->fLink->Attach<BRect>(bounds);
4010 
4011 	_FlushIfNotInTransaction();
4012 }
4013 
4014 
4015 void
FillTriangle(BPoint point1,BPoint point2,BPoint point3,BRect bounds,const BGradient & gradient)4016 BView::FillTriangle(BPoint point1, BPoint point2, BPoint point3, BRect bounds,
4017 	const BGradient& gradient)
4018 {
4019 	if (fOwner == NULL)
4020 		return;
4021 
4022 	_CheckLockAndSwitchCurrent();
4023 	fOwner->fLink->StartMessage(AS_FILL_TRIANGLE_GRADIENT);
4024 	fOwner->fLink->Attach<BPoint>(point1);
4025 	fOwner->fLink->Attach<BPoint>(point2);
4026 	fOwner->fLink->Attach<BPoint>(point3);
4027 	fOwner->fLink->Attach<BRect>(bounds);
4028 	fOwner->fLink->AttachGradient(gradient);
4029 
4030 	_FlushIfNotInTransaction();
4031 }
4032 
4033 
4034 void
StrokeLine(BPoint toPoint,::pattern pattern)4035 BView::StrokeLine(BPoint toPoint, ::pattern pattern)
4036 {
4037 	StrokeLine(PenLocation(), toPoint, pattern);
4038 }
4039 
4040 
4041 void
StrokeLine(BPoint start,BPoint end,::pattern pattern)4042 BView::StrokeLine(BPoint start, BPoint end, ::pattern pattern)
4043 {
4044 	if (fOwner == NULL)
4045 		return;
4046 
4047 	_CheckLockAndSwitchCurrent();
4048 	_UpdatePattern(pattern);
4049 
4050 	ViewStrokeLineInfo info;
4051 	info.startPoint = start;
4052 	info.endPoint = end;
4053 
4054 	fOwner->fLink->StartMessage(AS_STROKE_LINE);
4055 	fOwner->fLink->Attach<ViewStrokeLineInfo>(info);
4056 
4057 	_FlushIfNotInTransaction();
4058 
4059 	// this modifies our pen location, so we invalidate the flag.
4060 	fState->valid_flags &= ~B_VIEW_PEN_LOCATION_BIT;
4061 }
4062 
4063 
4064 void
StrokeShape(BShape * shape,::pattern pattern)4065 BView::StrokeShape(BShape* shape, ::pattern pattern)
4066 {
4067 	if (shape == NULL || fOwner == NULL)
4068 		return;
4069 
4070 	shape_data* sd = BShape::Private(*shape).PrivateData();
4071 	if (sd->opCount == 0 || sd->ptCount == 0)
4072 		return;
4073 
4074 	_CheckLockAndSwitchCurrent();
4075 	_UpdatePattern(pattern);
4076 
4077 	fOwner->fLink->StartMessage(AS_STROKE_SHAPE);
4078 	fOwner->fLink->Attach<BRect>(shape->Bounds());
4079 	fOwner->fLink->AttachShape(*shape);
4080 
4081 	_FlushIfNotInTransaction();
4082 }
4083 
4084 
4085 void
FillShape(BShape * shape,::pattern pattern)4086 BView::FillShape(BShape* shape, ::pattern pattern)
4087 {
4088 	if (shape == NULL || fOwner == NULL)
4089 		return;
4090 
4091 	shape_data* sd = BShape::Private(*shape).PrivateData();
4092 	if (sd->opCount == 0 || sd->ptCount == 0)
4093 		return;
4094 
4095 	_CheckLockAndSwitchCurrent();
4096 	_UpdatePattern(pattern);
4097 
4098 	fOwner->fLink->StartMessage(AS_FILL_SHAPE);
4099 	fOwner->fLink->Attach<BRect>(shape->Bounds());
4100 	fOwner->fLink->AttachShape(*shape);
4101 
4102 	_FlushIfNotInTransaction();
4103 }
4104 
4105 
4106 void
FillShape(BShape * shape,const BGradient & gradient)4107 BView::FillShape(BShape* shape, const BGradient& gradient)
4108 {
4109 	if (shape == NULL || fOwner == NULL)
4110 		return;
4111 
4112 	shape_data* sd = BShape::Private(*shape).PrivateData();
4113 	if (sd->opCount == 0 || sd->ptCount == 0)
4114 		return;
4115 
4116 	_CheckLockAndSwitchCurrent();
4117 
4118 	fOwner->fLink->StartMessage(AS_FILL_SHAPE_GRADIENT);
4119 	fOwner->fLink->Attach<BRect>(shape->Bounds());
4120 	fOwner->fLink->AttachShape(*shape);
4121 	fOwner->fLink->AttachGradient(gradient);
4122 
4123 	_FlushIfNotInTransaction();
4124 }
4125 
4126 
4127 void
BeginLineArray(int32 count)4128 BView::BeginLineArray(int32 count)
4129 {
4130 	if (fOwner == NULL)
4131 		return;
4132 
4133 	if (count <= 0)
4134 		debugger("Calling BeginLineArray with a count <= 0");
4135 
4136 	_CheckLock();
4137 
4138 	if (fCommArray) {
4139 		debugger("Can't nest BeginLineArray calls");
4140 			// not fatal, but it helps during
4141 			// development of your app and is in
4142 			// line with R5...
4143 		delete[] fCommArray->array;
4144 		delete fCommArray;
4145 	}
4146 
4147 	// TODO: since this method cannot return failure, and further AddLine()
4148 	//	calls with a NULL fCommArray would drop into the debugger anyway,
4149 	//	we allow the possible std::bad_alloc exceptions here...
4150 	fCommArray = new _array_data_;
4151 	fCommArray->count = 0;
4152 
4153 	// Make sure the fCommArray is initialized to reasonable values in cases of
4154 	// bad_alloc. At least the exception can be caught and EndLineArray won't
4155 	// crash.
4156 	fCommArray->array = NULL;
4157 	fCommArray->maxCount = 0;
4158 
4159 	fCommArray->array = new ViewLineArrayInfo[count];
4160 	fCommArray->maxCount = count;
4161 }
4162 
4163 
4164 void
AddLine(BPoint start,BPoint end,rgb_color color)4165 BView::AddLine(BPoint start, BPoint end, rgb_color color)
4166 {
4167 	if (fOwner == NULL)
4168 		return;
4169 
4170 	if (!fCommArray)
4171 		debugger("BeginLineArray must be called before using AddLine");
4172 
4173 	_CheckLock();
4174 
4175 	const uint32 &arrayCount = fCommArray->count;
4176 	if (arrayCount < fCommArray->maxCount) {
4177 		fCommArray->array[arrayCount].startPoint = start;
4178 		fCommArray->array[arrayCount].endPoint = end;
4179 		fCommArray->array[arrayCount].color = color;
4180 
4181 		fCommArray->count++;
4182 	}
4183 }
4184 
4185 
4186 void
EndLineArray()4187 BView::EndLineArray()
4188 {
4189 	if (fOwner == NULL)
4190 		return;
4191 
4192 	if (fCommArray == NULL)
4193 		debugger("Can't call EndLineArray before BeginLineArray");
4194 
4195 	_CheckLockAndSwitchCurrent();
4196 
4197 	fOwner->fLink->StartMessage(AS_STROKE_LINEARRAY);
4198 	fOwner->fLink->Attach<int32>(fCommArray->count);
4199 	fOwner->fLink->Attach(fCommArray->array,
4200 		fCommArray->count * sizeof(ViewLineArrayInfo));
4201 
4202 	_FlushIfNotInTransaction();
4203 
4204 	_RemoveCommArray();
4205 }
4206 
4207 
4208 void
SetDiskMode(char * filename,long offset)4209 BView::SetDiskMode(char* filename, long offset)
4210 {
4211 	// TODO: implement
4212 	// One BeBook version has this to say about SetDiskMode():
4213 	//
4214 	// "Begins recording a picture to the file with the given filename
4215 	// at the given offset. Subsequent drawing commands sent to the view
4216 	// will be written to the file until EndPicture() is called. The
4217 	// stored commands may be played from the file with DrawPicture()."
4218 }
4219 
4220 
4221 void
BeginPicture(BPicture * picture)4222 BView::BeginPicture(BPicture* picture)
4223 {
4224 	if (_CheckOwnerLockAndSwitchCurrent()
4225 		&& picture && picture->fUsurped == NULL) {
4226 		picture->Usurp(fCurrentPicture);
4227 		fCurrentPicture = picture;
4228 
4229 		fOwner->fLink->StartMessage(AS_VIEW_BEGIN_PICTURE);
4230 	}
4231 }
4232 
4233 
4234 void
AppendToPicture(BPicture * picture)4235 BView::AppendToPicture(BPicture* picture)
4236 {
4237 	_CheckLockAndSwitchCurrent();
4238 
4239 	if (picture && picture->fUsurped == NULL) {
4240 		int32 token = picture->Token();
4241 
4242 		if (token == -1) {
4243 			BeginPicture(picture);
4244 		} else {
4245 			picture->SetToken(-1);
4246 			picture->Usurp(fCurrentPicture);
4247 			fCurrentPicture = picture;
4248 			fOwner->fLink->StartMessage(AS_VIEW_APPEND_TO_PICTURE);
4249 			fOwner->fLink->Attach<int32>(token);
4250 		}
4251 	}
4252 }
4253 
4254 
4255 BPicture*
EndPicture()4256 BView::EndPicture()
4257 {
4258 	if (_CheckOwnerLockAndSwitchCurrent() && fCurrentPicture) {
4259 		int32 token;
4260 
4261 		fOwner->fLink->StartMessage(AS_VIEW_END_PICTURE);
4262 
4263 		int32 code;
4264 		if (fOwner->fLink->FlushWithReply(code) == B_OK
4265 			&& code == B_OK
4266 			&& fOwner->fLink->Read<int32>(&token) == B_OK) {
4267 			BPicture* picture = fCurrentPicture;
4268 			fCurrentPicture = picture->StepDown();
4269 			picture->SetToken(token);
4270 
4271 			// TODO do this more efficient e.g. use a shared area and let the
4272 			// client write into it
4273 			picture->_Download();
4274 			return picture;
4275 		}
4276 	}
4277 
4278 	return NULL;
4279 }
4280 
4281 
4282 void
SetViewBitmap(const BBitmap * bitmap,BRect srcRect,BRect dstRect,uint32 followFlags,uint32 options)4283 BView::SetViewBitmap(const BBitmap* bitmap, BRect srcRect, BRect dstRect,
4284 	uint32 followFlags, uint32 options)
4285 {
4286 	_SetViewBitmap(bitmap, srcRect, dstRect, followFlags, options);
4287 }
4288 
4289 
4290 void
SetViewBitmap(const BBitmap * bitmap,uint32 followFlags,uint32 options)4291 BView::SetViewBitmap(const BBitmap* bitmap, uint32 followFlags, uint32 options)
4292 {
4293 	BRect rect;
4294  	if (bitmap)
4295 		rect = bitmap->Bounds();
4296 
4297  	rect.OffsetTo(B_ORIGIN);
4298 
4299 	_SetViewBitmap(bitmap, rect, rect, followFlags, options);
4300 }
4301 
4302 
4303 void
ClearViewBitmap()4304 BView::ClearViewBitmap()
4305 {
4306 	_SetViewBitmap(NULL, BRect(), BRect(), 0, 0);
4307 }
4308 
4309 
4310 status_t
SetViewOverlay(const BBitmap * overlay,BRect srcRect,BRect dstRect,rgb_color * colorKey,uint32 followFlags,uint32 options)4311 BView::SetViewOverlay(const BBitmap* overlay, BRect srcRect, BRect dstRect,
4312 	rgb_color* colorKey, uint32 followFlags, uint32 options)
4313 {
4314 	if (overlay == NULL || (overlay->fFlags & B_BITMAP_WILL_OVERLAY) == 0)
4315 		return B_BAD_VALUE;
4316 
4317 	status_t status = _SetViewBitmap(overlay, srcRect, dstRect, followFlags,
4318 		options | AS_REQUEST_COLOR_KEY);
4319 	if (status == B_OK) {
4320 		// read the color that will be treated as transparent
4321 		fOwner->fLink->Read<rgb_color>(colorKey);
4322 	}
4323 
4324 	return status;
4325 }
4326 
4327 
4328 status_t
SetViewOverlay(const BBitmap * overlay,rgb_color * colorKey,uint32 followFlags,uint32 options)4329 BView::SetViewOverlay(const BBitmap* overlay, rgb_color* colorKey,
4330 	uint32 followFlags, uint32 options)
4331 {
4332 	if (overlay == NULL)
4333 		return B_BAD_VALUE;
4334 
4335 	BRect rect = overlay->Bounds();
4336  	rect.OffsetTo(B_ORIGIN);
4337 
4338 	return SetViewOverlay(overlay, rect, rect, colorKey, followFlags, options);
4339 }
4340 
4341 
4342 void
ClearViewOverlay()4343 BView::ClearViewOverlay()
4344 {
4345 	_SetViewBitmap(NULL, BRect(), BRect(), 0, 0);
4346 }
4347 
4348 
4349 void
CopyBits(BRect src,BRect dst)4350 BView::CopyBits(BRect src, BRect dst)
4351 {
4352 	if (fOwner == NULL)
4353 		return;
4354 
4355 	if (!src.IsValid() || !dst.IsValid())
4356 		return;
4357 
4358 	_CheckLockAndSwitchCurrent();
4359 
4360 	fOwner->fLink->StartMessage(AS_VIEW_COPY_BITS);
4361 	fOwner->fLink->Attach<BRect>(src);
4362 	fOwner->fLink->Attach<BRect>(dst);
4363 
4364 	_FlushIfNotInTransaction();
4365 }
4366 
4367 
4368 void
DrawPicture(const BPicture * picture)4369 BView::DrawPicture(const BPicture* picture)
4370 {
4371 	if (picture == NULL)
4372 		return;
4373 
4374 	DrawPictureAsync(picture, PenLocation());
4375 	Sync();
4376 }
4377 
4378 
4379 void
DrawPicture(const BPicture * picture,BPoint where)4380 BView::DrawPicture(const BPicture* picture, BPoint where)
4381 {
4382 	if (picture == NULL)
4383 		return;
4384 
4385 	DrawPictureAsync(picture, where);
4386 	Sync();
4387 }
4388 
4389 
4390 void
DrawPicture(const char * filename,long offset,BPoint where)4391 BView::DrawPicture(const char* filename, long offset, BPoint where)
4392 {
4393 	if (!filename)
4394 		return;
4395 
4396 	DrawPictureAsync(filename, offset, where);
4397 	Sync();
4398 }
4399 
4400 
4401 void
DrawPictureAsync(const BPicture * picture)4402 BView::DrawPictureAsync(const BPicture* picture)
4403 {
4404 	if (picture == NULL)
4405 		return;
4406 
4407 	DrawPictureAsync(picture, PenLocation());
4408 }
4409 
4410 
4411 void
DrawPictureAsync(const BPicture * picture,BPoint where)4412 BView::DrawPictureAsync(const BPicture* picture, BPoint where)
4413 {
4414 	if (picture == NULL)
4415 		return;
4416 
4417 	if (_CheckOwnerLockAndSwitchCurrent() && picture->Token() > 0) {
4418 		fOwner->fLink->StartMessage(AS_VIEW_DRAW_PICTURE);
4419 		fOwner->fLink->Attach<int32>(picture->Token());
4420 		fOwner->fLink->Attach<BPoint>(where);
4421 
4422 		_FlushIfNotInTransaction();
4423 	}
4424 }
4425 
4426 
4427 void
DrawPictureAsync(const char * filename,long offset,BPoint where)4428 BView::DrawPictureAsync(const char* filename, long offset, BPoint where)
4429 {
4430 	if (!filename)
4431 		return;
4432 
4433 	// TODO: Test
4434 	BFile file(filename, B_READ_ONLY);
4435 	if (file.InitCheck() < B_OK)
4436 		return;
4437 
4438 	file.Seek(offset, SEEK_SET);
4439 
4440 	BPicture picture;
4441 	if (picture.Unflatten(&file) < B_OK)
4442 		return;
4443 
4444 	DrawPictureAsync(&picture, where);
4445 }
4446 
4447 
4448 void
BeginLayer(uint8 opacity)4449 BView::BeginLayer(uint8 opacity)
4450 {
4451 	if (_CheckOwnerLockAndSwitchCurrent()) {
4452 		fOwner->fLink->StartMessage(AS_VIEW_BEGIN_LAYER);
4453 		fOwner->fLink->Attach<uint8>(opacity);
4454 		_FlushIfNotInTransaction();
4455 	}
4456 }
4457 
4458 
4459 void
EndLayer()4460 BView::EndLayer()
4461 {
4462 	if (_CheckOwnerLockAndSwitchCurrent()) {
4463 		fOwner->fLink->StartMessage(AS_VIEW_END_LAYER);
4464 		_FlushIfNotInTransaction();
4465 	}
4466 }
4467 
4468 
4469 void
Invalidate(BRect invalRect)4470 BView::Invalidate(BRect invalRect)
4471 {
4472 	if (fOwner == NULL)
4473 		return;
4474 
4475 	// NOTE: This rounding of the invalid rect is to stay compatible with BeOS.
4476 	// On the server side, the invalid rect will be converted to a BRegion,
4477 	// which rounds in a different manner, so that it really includes the
4478 	// fractional coordinates of a BRect (ie ceilf(rect.right) &
4479 	// ceilf(rect.bottom)), which is also what BeOS does. So we have to do the
4480 	// different rounding here to stay compatible in both ways.
4481 	invalRect.left = (int)invalRect.left;
4482 	invalRect.top = (int)invalRect.top;
4483 	invalRect.right = (int)invalRect.right;
4484 	invalRect.bottom = (int)invalRect.bottom;
4485 	if (!invalRect.IsValid())
4486 		return;
4487 
4488 	_CheckLockAndSwitchCurrent();
4489 
4490 	fOwner->fLink->StartMessage(AS_VIEW_INVALIDATE_RECT);
4491 	fOwner->fLink->Attach<BRect>(invalRect);
4492 
4493 // TODO: determine why this check isn't working correctly.
4494 #if 0
4495 	if (!fOwner->fUpdateRequested) {
4496 		fOwner->fLink->Flush();
4497 		fOwner->fUpdateRequested = true;
4498 	}
4499 #else
4500 	fOwner->fLink->Flush();
4501 #endif
4502 }
4503 
4504 
4505 void
Invalidate(const BRegion * region)4506 BView::Invalidate(const BRegion* region)
4507 {
4508 	if (region == NULL || fOwner == NULL)
4509 		return;
4510 
4511 	_CheckLockAndSwitchCurrent();
4512 
4513 	fOwner->fLink->StartMessage(AS_VIEW_INVALIDATE_REGION);
4514 	fOwner->fLink->AttachRegion(*region);
4515 
4516 // TODO: See above.
4517 #if 0
4518 	if (!fOwner->fUpdateRequested) {
4519 		fOwner->fLink->Flush();
4520 		fOwner->fUpdateRequested = true;
4521 	}
4522 #else
4523 	fOwner->fLink->Flush();
4524 #endif
4525 }
4526 
4527 
4528 void
Invalidate()4529 BView::Invalidate()
4530 {
4531 	Invalidate(Bounds());
4532 }
4533 
4534 
4535 void
DelayedInvalidate(bigtime_t delay)4536 BView::DelayedInvalidate(bigtime_t delay)
4537 {
4538 	DelayedInvalidate(delay, Bounds());
4539 }
4540 
4541 
4542 void
DelayedInvalidate(bigtime_t delay,BRect invalRect)4543 BView::DelayedInvalidate(bigtime_t delay, BRect invalRect)
4544 {
4545 	if (fOwner == NULL)
4546 		return;
4547 
4548 	invalRect.left = (int)invalRect.left;
4549 	invalRect.top = (int)invalRect.top;
4550 	invalRect.right = (int)invalRect.right;
4551 	invalRect.bottom = (int)invalRect.bottom;
4552 	if (!invalRect.IsValid())
4553 		return;
4554 
4555 	_CheckLockAndSwitchCurrent();
4556 
4557 	fOwner->fLink->StartMessage(AS_VIEW_DELAYED_INVALIDATE_RECT);
4558 	fOwner->fLink->Attach<bigtime_t>(system_time() + delay);
4559 	fOwner->fLink->Attach<BRect>(invalRect);
4560 	fOwner->fLink->Flush();
4561 }
4562 
4563 
4564 void
InvertRect(BRect rect)4565 BView::InvertRect(BRect rect)
4566 {
4567 	if (fOwner) {
4568 		_CheckLockAndSwitchCurrent();
4569 
4570 		fOwner->fLink->StartMessage(AS_VIEW_INVERT_RECT);
4571 		fOwner->fLink->Attach<BRect>(rect);
4572 
4573 		_FlushIfNotInTransaction();
4574 	}
4575 }
4576 
4577 
4578 //	#pragma mark - View Hierarchy Functions
4579 
4580 
4581 void
AddChild(BView * child,BView * before)4582 BView::AddChild(BView* child, BView* before)
4583 {
4584 	STRACE(("BView(%s)::AddChild(child '%s', before '%s')\n",
4585 		this->Name(),
4586 		child != NULL && child->Name() ? child->Name() : "NULL",
4587 		before != NULL && before->Name() ? before->Name() : "NULL"));
4588 
4589 	if (!_AddChild(child, before))
4590 		return;
4591 
4592 	if (fLayoutData->fLayout)
4593 		fLayoutData->fLayout->AddView(child);
4594 }
4595 
4596 
4597 bool
AddChild(BLayoutItem * child)4598 BView::AddChild(BLayoutItem* child)
4599 {
4600 	if (!fLayoutData->fLayout)
4601 		return false;
4602 	return fLayoutData->fLayout->AddItem(child);
4603 }
4604 
4605 
4606 bool
_AddChild(BView * child,BView * before)4607 BView::_AddChild(BView* child, BView* before)
4608 {
4609 	if (!child)
4610 		return false;
4611 
4612 	if (child->fParent != NULL) {
4613 		debugger("AddChild failed - the view already has a parent.");
4614 		return false;
4615 	}
4616 
4617 	if (child == this) {
4618 		debugger("AddChild failed - cannot add a view to itself.");
4619 		return false;
4620 	}
4621 
4622 	bool lockedOwner = false;
4623 	if (fOwner && !fOwner->IsLocked()) {
4624 		fOwner->Lock();
4625 		lockedOwner = true;
4626 	}
4627 
4628 	if (!_AddChildToList(child, before)) {
4629 		debugger("AddChild failed!");
4630 		if (lockedOwner)
4631 			fOwner->Unlock();
4632 		return false;
4633 	}
4634 
4635 	if (fOwner) {
4636 		_CheckLockAndSwitchCurrent();
4637 
4638 		child->_SetOwner(fOwner);
4639 		child->_CreateSelf();
4640 		child->_Attach();
4641 
4642 		if (lockedOwner)
4643 			fOwner->Unlock();
4644 	}
4645 
4646 	InvalidateLayout();
4647 
4648 	return true;
4649 }
4650 
4651 
4652 bool
RemoveChild(BView * child)4653 BView::RemoveChild(BView* child)
4654 {
4655 	STRACE(("BView(%s)::RemoveChild(%s)\n", Name(), child->Name()));
4656 
4657 	if (!child)
4658 		return false;
4659 
4660 	if (child->fParent != this)
4661 		return false;
4662 
4663 	return child->RemoveSelf();
4664 }
4665 
4666 
4667 int32
CountChildren() const4668 BView::CountChildren() const
4669 {
4670 	_CheckLock();
4671 
4672 	uint32 count = 0;
4673 	BView* child = fFirstChild;
4674 
4675 	while (child != NULL) {
4676 		count++;
4677 		child = child->fNextSibling;
4678 	}
4679 
4680 	return count;
4681 }
4682 
4683 
4684 BView*
ChildAt(int32 index) const4685 BView::ChildAt(int32 index) const
4686 {
4687 	_CheckLock();
4688 
4689 	BView* child = fFirstChild;
4690 	while (child != NULL && index-- > 0) {
4691 		child = child->fNextSibling;
4692 	}
4693 
4694 	return child;
4695 }
4696 
4697 
4698 BView*
NextSibling() const4699 BView::NextSibling() const
4700 {
4701 	return fNextSibling;
4702 }
4703 
4704 
4705 BView*
PreviousSibling() const4706 BView::PreviousSibling() const
4707 {
4708 	return fPreviousSibling;
4709 }
4710 
4711 
4712 bool
RemoveSelf()4713 BView::RemoveSelf()
4714 {
4715 	_RemoveLayoutItemsFromLayout(false);
4716 
4717 	return _RemoveSelf();
4718 }
4719 
4720 
4721 bool
_RemoveSelf()4722 BView::_RemoveSelf()
4723 {
4724 	STRACE(("BView(%s)::_RemoveSelf()\n", Name()));
4725 
4726 	// Remove this child from its parent
4727 
4728 	BWindow* owner = fOwner;
4729 	_CheckLock();
4730 
4731 	if (owner != NULL) {
4732 		_UpdateStateForRemove();
4733 		_Detach();
4734 	}
4735 
4736 	BView* parent = fParent;
4737 	if (!parent || !parent->_RemoveChildFromList(this))
4738 		return false;
4739 
4740 	if (owner != NULL && !fTopLevelView) {
4741 		// the top level view is deleted by the app_server automatically
4742 		owner->fLink->StartMessage(AS_VIEW_DELETE);
4743 		owner->fLink->Attach<int32>(_get_object_token_(this));
4744 	}
4745 
4746 	parent->InvalidateLayout();
4747 
4748 	STRACE(("DONE: BView(%s)::_RemoveSelf()\n", Name()));
4749 
4750 	return true;
4751 }
4752 
4753 
4754 void
_RemoveLayoutItemsFromLayout(bool deleteItems)4755 BView::_RemoveLayoutItemsFromLayout(bool deleteItems)
4756 {
4757 	if (fParent == NULL || fParent->fLayoutData->fLayout == NULL)
4758 		return;
4759 
4760 	int32 index = fLayoutData->fLayoutItems.CountItems();
4761 	while (index-- > 0) {
4762 		BLayoutItem* item = fLayoutData->fLayoutItems.ItemAt(index);
4763 		item->RemoveSelf();
4764 			// Removes item from fLayoutItems list
4765 		if (deleteItems)
4766 			delete item;
4767 	}
4768 }
4769 
4770 
4771 BView*
Parent() const4772 BView::Parent() const
4773 {
4774 	if (fParent && fParent->fTopLevelView)
4775 		return NULL;
4776 
4777 	return fParent;
4778 }
4779 
4780 
4781 BView*
FindView(const char * name) const4782 BView::FindView(const char* name) const
4783 {
4784 	if (name == NULL)
4785 		return NULL;
4786 
4787 	if (Name() != NULL && !strcmp(Name(), name))
4788 		return const_cast<BView*>(this);
4789 
4790 	BView* child = fFirstChild;
4791 	while (child != NULL) {
4792 		BView* view = child->FindView(name);
4793 		if (view != NULL)
4794 			return view;
4795 
4796 		child = child->fNextSibling;
4797 	}
4798 
4799 	return NULL;
4800 }
4801 
4802 
4803 void
MoveBy(float deltaX,float deltaY)4804 BView::MoveBy(float deltaX, float deltaY)
4805 {
4806 	MoveTo(fParentOffset.x + roundf(deltaX), fParentOffset.y + roundf(deltaY));
4807 }
4808 
4809 
4810 void
MoveTo(BPoint where)4811 BView::MoveTo(BPoint where)
4812 {
4813 	MoveTo(where.x, where.y);
4814 }
4815 
4816 
4817 void
MoveTo(float x,float y)4818 BView::MoveTo(float x, float y)
4819 {
4820 	if (x == fParentOffset.x && y == fParentOffset.y)
4821 		return;
4822 
4823 	// BeBook says we should do this. And it makes sense.
4824 	x = roundf(x);
4825 	y = roundf(y);
4826 
4827 	if (fOwner) {
4828 		_CheckLockAndSwitchCurrent();
4829 		fOwner->fLink->StartMessage(AS_VIEW_MOVE_TO);
4830 		fOwner->fLink->Attach<float>(x);
4831 		fOwner->fLink->Attach<float>(y);
4832 
4833 //		fState->valid_flags |= B_VIEW_FRAME_BIT;
4834 
4835 		_FlushIfNotInTransaction();
4836 	}
4837 
4838 	_MoveTo((int32)x, (int32)y);
4839 }
4840 
4841 
4842 void
ResizeBy(float deltaWidth,float deltaHeight)4843 BView::ResizeBy(float deltaWidth, float deltaHeight)
4844 {
4845 	// BeBook says we should do this. And it makes sense.
4846 	deltaWidth = roundf(deltaWidth);
4847 	deltaHeight = roundf(deltaHeight);
4848 
4849 	if (deltaWidth == 0 && deltaHeight == 0)
4850 		return;
4851 
4852 	if (fOwner) {
4853 		_CheckLockAndSwitchCurrent();
4854 		fOwner->fLink->StartMessage(AS_VIEW_RESIZE_TO);
4855 
4856 		fOwner->fLink->Attach<float>(fBounds.Width() + deltaWidth);
4857 		fOwner->fLink->Attach<float>(fBounds.Height() + deltaHeight);
4858 
4859 //		fState->valid_flags |= B_VIEW_FRAME_BIT;
4860 
4861 		_FlushIfNotInTransaction();
4862 	}
4863 
4864 	_ResizeBy((int32)deltaWidth, (int32)deltaHeight);
4865 }
4866 
4867 
4868 void
ResizeTo(float width,float height)4869 BView::ResizeTo(float width, float height)
4870 {
4871 	ResizeBy(width - fBounds.Width(), height - fBounds.Height());
4872 }
4873 
4874 
4875 void
ResizeTo(BSize size)4876 BView::ResizeTo(BSize size)
4877 {
4878 	ResizeBy(size.width - fBounds.Width(), size.height - fBounds.Height());
4879 }
4880 
4881 
4882 //	#pragma mark - Inherited Methods (from BHandler)
4883 
4884 
4885 status_t
GetSupportedSuites(BMessage * data)4886 BView::GetSupportedSuites(BMessage* data)
4887 {
4888 	if (data == NULL)
4889 		return B_BAD_VALUE;
4890 
4891 	status_t status = data->AddString("suites", "suite/vnd.Be-view");
4892 	BPropertyInfo propertyInfo(sViewPropInfo);
4893 	if (status == B_OK)
4894 		status = data->AddFlat("messages", &propertyInfo);
4895 	if (status == B_OK)
4896 		return BHandler::GetSupportedSuites(data);
4897 	return status;
4898 }
4899 
4900 
4901 BHandler*
ResolveSpecifier(BMessage * message,int32 index,BMessage * specifier,int32 what,const char * property)4902 BView::ResolveSpecifier(BMessage* message, int32 index, BMessage* specifier,
4903 	int32 what, const char* property)
4904 {
4905 	if (message->what == B_WINDOW_MOVE_BY
4906 		|| message->what == B_WINDOW_MOVE_TO) {
4907 		return this;
4908 	}
4909 
4910 	BPropertyInfo propertyInfo(sViewPropInfo);
4911 	status_t err = B_BAD_SCRIPT_SYNTAX;
4912 	BMessage replyMsg(B_REPLY);
4913 
4914 	switch (propertyInfo.FindMatch(message, index, specifier, what, property)) {
4915 		case 0:
4916 		case 1:
4917 		case 3:
4918 			return this;
4919 
4920 		case 2:
4921 			if (fShelf) {
4922 				message->PopSpecifier();
4923 				return fShelf;
4924 			}
4925 
4926 			err = B_NAME_NOT_FOUND;
4927 			replyMsg.AddString("message", "This window doesn't have a shelf");
4928 			break;
4929 
4930 		case 4:
4931 		{
4932 			if (!fFirstChild) {
4933 				err = B_NAME_NOT_FOUND;
4934 				replyMsg.AddString("message", "This window doesn't have "
4935 					"children.");
4936 				break;
4937 			}
4938 			BView* child = NULL;
4939 			switch (what) {
4940 				case B_INDEX_SPECIFIER:
4941 				{
4942 					int32 index;
4943 					err = specifier->FindInt32("index", &index);
4944 					if (err == B_OK)
4945 						child = ChildAt(index);
4946 					break;
4947 				}
4948 				case B_REVERSE_INDEX_SPECIFIER:
4949 				{
4950 					int32 rindex;
4951 					err = specifier->FindInt32("index", &rindex);
4952 					if (err == B_OK)
4953 						child = ChildAt(CountChildren() - rindex);
4954 					break;
4955 				}
4956 				case B_NAME_SPECIFIER:
4957 				{
4958 					const char* name;
4959 					err = specifier->FindString("name", &name);
4960 					if (err == B_OK)
4961 						child = FindView(name);
4962 					break;
4963 				}
4964 			}
4965 
4966 			if (child != NULL) {
4967 				message->PopSpecifier();
4968 				return child;
4969 			}
4970 
4971 			if (err == B_OK)
4972 				err = B_BAD_INDEX;
4973 
4974 			replyMsg.AddString("message",
4975 				"Cannot find view at/with specified index/name.");
4976 			break;
4977 		}
4978 
4979 		default:
4980 			return BHandler::ResolveSpecifier(message, index, specifier, what,
4981 				property);
4982 	}
4983 
4984 	if (err < B_OK) {
4985 		replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
4986 
4987 		if (err == B_BAD_SCRIPT_SYNTAX)
4988 			replyMsg.AddString("message", "Didn't understand the specifier(s)");
4989 		else
4990 			replyMsg.AddString("message", strerror(err));
4991 	}
4992 
4993 	replyMsg.AddInt32("error", err);
4994 	message->SendReply(&replyMsg);
4995 	return NULL;
4996 }
4997 
4998 
4999 void
MessageReceived(BMessage * message)5000 BView::MessageReceived(BMessage* message)
5001 {
5002 	if (!message->HasSpecifiers()) {
5003 		switch (message->what) {
5004 			case B_INVALIDATE:
5005 			{
5006 				BRect rect;
5007 				if (message->FindRect("be:area", &rect) == B_OK)
5008 					Invalidate(rect);
5009 				else
5010 					Invalidate();
5011 				break;
5012 			}
5013 
5014 			case B_KEY_DOWN:
5015 			{
5016 				// TODO: cannot use "string" here if we support having different
5017 				// font encoding per view (it's supposed to be converted by
5018 				// BWindow::_HandleKeyDown() one day)
5019 				const char* string;
5020 				ssize_t bytes;
5021 				if (message->FindData("bytes", B_STRING_TYPE,
5022 						(const void**)&string, &bytes) == B_OK)
5023 					KeyDown(string, bytes - 1);
5024 				break;
5025 			}
5026 
5027 			case B_KEY_UP:
5028 			{
5029 				// TODO: same as above
5030 				const char* string;
5031 				ssize_t bytes;
5032 				if (message->FindData("bytes", B_STRING_TYPE,
5033 						(const void**)&string, &bytes) == B_OK)
5034 					KeyUp(string, bytes - 1);
5035 				break;
5036 			}
5037 
5038 			case B_VIEW_RESIZED:
5039 				FrameResized(message->GetInt32("width", 0),
5040 					message->GetInt32("height", 0));
5041 				break;
5042 
5043 			case B_VIEW_MOVED:
5044 				FrameMoved(fParentOffset);
5045 				break;
5046 
5047 			case B_MOUSE_DOWN:
5048 			{
5049 				BPoint where;
5050 				message->FindPoint("be:view_where", &where);
5051 				MouseDown(where);
5052 				break;
5053 			}
5054 
5055 			case B_MOUSE_IDLE:
5056 			{
5057 				BPoint where;
5058 				if (message->FindPoint("be:view_where", &where) != B_OK)
5059 					break;
5060 
5061 				BToolTip* tip;
5062 				if (GetToolTipAt(where, &tip))
5063 					ShowToolTip(tip);
5064 				else
5065 					BHandler::MessageReceived(message);
5066 				break;
5067 			}
5068 
5069 			case B_MOUSE_MOVED:
5070 			{
5071 				uint32 eventOptions = fEventOptions | fMouseEventOptions;
5072 				bool noHistory = eventOptions & B_NO_POINTER_HISTORY;
5073 				bool dropIfLate = !(eventOptions & B_FULL_POINTER_HISTORY);
5074 
5075 				bigtime_t eventTime;
5076 				if (message->FindInt64("when", (int64*)&eventTime) < B_OK)
5077 					eventTime = system_time();
5078 
5079 				uint32 transit;
5080 				message->FindInt32("be:transit", (int32*)&transit);
5081 				// don't drop late messages with these important transit values
5082 				if (transit == B_ENTERED_VIEW || transit == B_EXITED_VIEW)
5083 					dropIfLate = false;
5084 
5085 				// TODO: The dropping code may have the following problem: On
5086 				// slower computers, 20ms may just be to abitious a delay.
5087 				// There, we might constantly check the message queue for a
5088 				// newer message, not find any, and still use the only but later
5089 				// than 20ms message, which of course makes the whole thing
5090 				// later than need be. An adaptive delay would be kind of neat,
5091 				// but would probably use additional BWindow members to count
5092 				// the successful versus fruitless queue searches and the delay
5093 				// value itself or something similar.
5094 				if (noHistory
5095 					|| (dropIfLate && (system_time() - eventTime > 20000))) {
5096 					// filter out older mouse moved messages in the queue
5097 					BWindow* window = Window();
5098 					window->_DequeueAll();
5099 					BMessageQueue* queue = window->MessageQueue();
5100 					queue->Lock();
5101 
5102 					BMessage* moved;
5103 					for (int32 i = 0; (moved = queue->FindMessage(i)) != NULL;
5104 						 i++) {
5105 						if (moved != message && moved->what == B_MOUSE_MOVED) {
5106 							// there is a newer mouse moved message in the
5107 							// queue, just ignore the current one, the newer one
5108 							// will be handled here eventually
5109 							queue->Unlock();
5110 							return;
5111 						}
5112 					}
5113 					queue->Unlock();
5114 				}
5115 
5116 				BPoint where;
5117 				uint32 buttons;
5118 				message->FindPoint("be:view_where", &where);
5119 				message->FindInt32("buttons", (int32*)&buttons);
5120 
5121 				if (transit == B_EXITED_VIEW || transit == B_OUTSIDE_VIEW)
5122 					HideToolTip();
5123 
5124 				BMessage* dragMessage = NULL;
5125 				if (message->HasMessage("be:drag_message")) {
5126 					dragMessage = new BMessage();
5127 					if (message->FindMessage("be:drag_message", dragMessage)
5128 						!= B_OK) {
5129 						delete dragMessage;
5130 						dragMessage = NULL;
5131 					}
5132 				}
5133 
5134 				MouseMoved(where, transit, dragMessage);
5135 				delete dragMessage;
5136 				break;
5137 			}
5138 
5139 			case B_MOUSE_UP:
5140 			{
5141 				BPoint where;
5142 				message->FindPoint("be:view_where", &where);
5143 				fMouseEventOptions = 0;
5144 				MouseUp(where);
5145 				break;
5146 			}
5147 
5148 			case B_MOUSE_WHEEL_CHANGED:
5149 			{
5150 				BScrollBar* horizontal = ScrollBar(B_HORIZONTAL);
5151 				BScrollBar* vertical = ScrollBar(B_VERTICAL);
5152 				if (horizontal == NULL && vertical == NULL) {
5153 					// Pass the message to the next handler
5154 					BHandler::MessageReceived(message);
5155 					break;
5156 				}
5157 
5158 				float deltaX = 0.0f;
5159 				float deltaY = 0.0f;
5160 
5161 				if (horizontal != NULL)
5162 					message->FindFloat("be:wheel_delta_x", &deltaX);
5163 
5164 				if (vertical != NULL)
5165 					message->FindFloat("be:wheel_delta_y", &deltaY);
5166 
5167 				if (deltaX == 0.0f && deltaY == 0.0f)
5168 					break;
5169 
5170 				if ((modifiers() & B_CONTROL_KEY) != 0)
5171 					std::swap(horizontal, vertical);
5172 
5173 				if (horizontal != NULL && deltaX != 0.0f)
5174 					ScrollWithMouseWheelDelta(horizontal, deltaX);
5175 
5176 				if (vertical != NULL && deltaY != 0.0f)
5177 					ScrollWithMouseWheelDelta(vertical, deltaY);
5178 
5179 				break;
5180 			}
5181 
5182 			// prevent message repeats
5183 			case B_COLORS_UPDATED:
5184 			case B_FONTS_UPDATED:
5185 				break;
5186 
5187 			case B_SCREEN_CHANGED:
5188 			case B_WORKSPACE_ACTIVATED:
5189 			case B_WORKSPACES_CHANGED:
5190 			{
5191 				BWindow* window = Window();
5192 				if (window == NULL)
5193 					break;
5194 
5195 				// propagate message to child views
5196 				int32 childCount = CountChildren();
5197 				for (int32 i = 0; i < childCount; i++) {
5198 					BView* view = ChildAt(i);
5199 					if (view != NULL)
5200 						window->PostMessage(message, view);
5201 				}
5202 				break;
5203 			}
5204 
5205 			default:
5206 				BHandler::MessageReceived(message);
5207 				break;
5208 		}
5209 
5210 		return;
5211 	}
5212 
5213 	// Scripting message
5214 
5215 	BMessage replyMsg(B_REPLY);
5216 	status_t err = B_BAD_SCRIPT_SYNTAX;
5217 	int32 index;
5218 	BMessage specifier;
5219 	int32 what;
5220 	const char* property;
5221 
5222 	if (message->GetCurrentSpecifier(&index, &specifier, &what, &property)
5223 			!= B_OK) {
5224 		return BHandler::MessageReceived(message);
5225 	}
5226 
5227 	BPropertyInfo propertyInfo(sViewPropInfo);
5228 	switch (propertyInfo.FindMatch(message, index, &specifier, what,
5229 			property)) {
5230 		case 0:
5231 			if (message->what == B_GET_PROPERTY) {
5232 				err = replyMsg.AddRect("result", Frame());
5233 			} else if (message->what == B_SET_PROPERTY) {
5234 				BRect newFrame;
5235 				err = message->FindRect("data", &newFrame);
5236 				if (err == B_OK) {
5237 					MoveTo(newFrame.LeftTop());
5238 					ResizeTo(newFrame.Width(), newFrame.Height());
5239 				}
5240 			}
5241 			break;
5242 		case 1:
5243 			if (message->what == B_GET_PROPERTY) {
5244 				err = replyMsg.AddBool("result", IsHidden());
5245 			} else if (message->what == B_SET_PROPERTY) {
5246 				bool newHiddenState;
5247 				err = message->FindBool("data", &newHiddenState);
5248 				if (err == B_OK) {
5249 					if (newHiddenState == true)
5250 						Hide();
5251 					else
5252 						Show();
5253 				}
5254 			}
5255 			break;
5256 		case 3:
5257 			err = replyMsg.AddInt32("result", CountChildren());
5258 			break;
5259 		default:
5260 			return BHandler::MessageReceived(message);
5261 	}
5262 
5263 	if (err != B_OK) {
5264 		replyMsg.what = B_MESSAGE_NOT_UNDERSTOOD;
5265 
5266 		if (err == B_BAD_SCRIPT_SYNTAX)
5267 			replyMsg.AddString("message", "Didn't understand the specifier(s)");
5268 		else
5269 			replyMsg.AddString("message", strerror(err));
5270 
5271 		replyMsg.AddInt32("error", err);
5272 	}
5273 
5274 	message->SendReply(&replyMsg);
5275 }
5276 
5277 
5278 status_t
Perform(perform_code code,void * _data)5279 BView::Perform(perform_code code, void* _data)
5280 {
5281 	switch (code) {
5282 		case PERFORM_CODE_MIN_SIZE:
5283 			((perform_data_min_size*)_data)->return_value
5284 				= BView::MinSize();
5285 			return B_OK;
5286 		case PERFORM_CODE_MAX_SIZE:
5287 			((perform_data_max_size*)_data)->return_value
5288 				= BView::MaxSize();
5289 			return B_OK;
5290 		case PERFORM_CODE_PREFERRED_SIZE:
5291 			((perform_data_preferred_size*)_data)->return_value
5292 				= BView::PreferredSize();
5293 			return B_OK;
5294 		case PERFORM_CODE_LAYOUT_ALIGNMENT:
5295 			((perform_data_layout_alignment*)_data)->return_value
5296 				= BView::LayoutAlignment();
5297 			return B_OK;
5298 		case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH:
5299 			((perform_data_has_height_for_width*)_data)->return_value
5300 				= BView::HasHeightForWidth();
5301 			return B_OK;
5302 		case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH:
5303 		{
5304 			perform_data_get_height_for_width* data
5305 				= (perform_data_get_height_for_width*)_data;
5306 			BView::GetHeightForWidth(data->width, &data->min, &data->max,
5307 				&data->preferred);
5308 			return B_OK;
5309 		}
5310 		case PERFORM_CODE_SET_LAYOUT:
5311 		{
5312 			perform_data_set_layout* data = (perform_data_set_layout*)_data;
5313 			BView::SetLayout(data->layout);
5314 			return B_OK;
5315 		}
5316 		case PERFORM_CODE_LAYOUT_INVALIDATED:
5317 		{
5318 			perform_data_layout_invalidated* data
5319 				= (perform_data_layout_invalidated*)_data;
5320 			BView::LayoutInvalidated(data->descendants);
5321 			return B_OK;
5322 		}
5323 		case PERFORM_CODE_DO_LAYOUT:
5324 		{
5325 			BView::DoLayout();
5326 			return B_OK;
5327 		}
5328 		case PERFORM_CODE_LAYOUT_CHANGED:
5329 		{
5330 			BView::LayoutChanged();
5331 			return B_OK;
5332 		}
5333 		case PERFORM_CODE_GET_TOOL_TIP_AT:
5334 		{
5335 			perform_data_get_tool_tip_at* data
5336 				= (perform_data_get_tool_tip_at*)_data;
5337 			data->return_value
5338 				= BView::GetToolTipAt(data->point, data->tool_tip);
5339 			return B_OK;
5340 		}
5341 		case PERFORM_CODE_ALL_UNARCHIVED:
5342 		{
5343 			perform_data_all_unarchived* data =
5344 				(perform_data_all_unarchived*)_data;
5345 
5346 			data->return_value = BView::AllUnarchived(data->archive);
5347 			return B_OK;
5348 		}
5349 		case PERFORM_CODE_ALL_ARCHIVED:
5350 		{
5351 			perform_data_all_archived* data =
5352 				(perform_data_all_archived*)_data;
5353 
5354 			data->return_value = BView::AllArchived(data->archive);
5355 			return B_OK;
5356 		}
5357 	}
5358 
5359 	return BHandler::Perform(code, _data);
5360 }
5361 
5362 
5363 // #pragma mark - Layout Functions
5364 
5365 
5366 BSize
MinSize()5367 BView::MinSize()
5368 {
5369 	// TODO: make sure this works correctly when some methods are overridden
5370 	float width, height;
5371 	GetPreferredSize(&width, &height);
5372 
5373 	return BLayoutUtils::ComposeSize(fLayoutData->fMinSize,
5374 		(fLayoutData->fLayout ? fLayoutData->fLayout->MinSize()
5375 			: BSize(width, height)));
5376 }
5377 
5378 
5379 BSize
MaxSize()5380 BView::MaxSize()
5381 {
5382 	return BLayoutUtils::ComposeSize(fLayoutData->fMaxSize,
5383 		(fLayoutData->fLayout ? fLayoutData->fLayout->MaxSize()
5384 			: BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED)));
5385 }
5386 
5387 
5388 BSize
PreferredSize()5389 BView::PreferredSize()
5390 {
5391 	// TODO: make sure this works correctly when some methods are overridden
5392 	float width, height;
5393 	GetPreferredSize(&width, &height);
5394 
5395 	return BLayoutUtils::ComposeSize(fLayoutData->fPreferredSize,
5396 		(fLayoutData->fLayout ? fLayoutData->fLayout->PreferredSize()
5397 			: BSize(width, height)));
5398 }
5399 
5400 
5401 BAlignment
LayoutAlignment()5402 BView::LayoutAlignment()
5403 {
5404 	return BLayoutUtils::ComposeAlignment(fLayoutData->fAlignment,
5405 		(fLayoutData->fLayout ? fLayoutData->fLayout->Alignment()
5406 			: BAlignment(B_ALIGN_HORIZONTAL_CENTER, B_ALIGN_VERTICAL_CENTER)));
5407 }
5408 
5409 
5410 void
SetExplicitMinSize(BSize size)5411 BView::SetExplicitMinSize(BSize size)
5412 {
5413 	fLayoutData->fMinSize = size;
5414 	InvalidateLayout();
5415 }
5416 
5417 
5418 void
SetExplicitMaxSize(BSize size)5419 BView::SetExplicitMaxSize(BSize size)
5420 {
5421 	fLayoutData->fMaxSize = size;
5422 	InvalidateLayout();
5423 }
5424 
5425 
5426 void
SetExplicitPreferredSize(BSize size)5427 BView::SetExplicitPreferredSize(BSize size)
5428 {
5429 	fLayoutData->fPreferredSize = size;
5430 	InvalidateLayout();
5431 }
5432 
5433 
5434 void
SetExplicitSize(BSize size)5435 BView::SetExplicitSize(BSize size)
5436 {
5437 	fLayoutData->fMinSize = size;
5438 	fLayoutData->fMaxSize = size;
5439 	fLayoutData->fPreferredSize = size;
5440 	InvalidateLayout();
5441 }
5442 
5443 
5444 void
SetExplicitAlignment(BAlignment alignment)5445 BView::SetExplicitAlignment(BAlignment alignment)
5446 {
5447 	fLayoutData->fAlignment = alignment;
5448 	InvalidateLayout();
5449 }
5450 
5451 
5452 BSize
ExplicitMinSize() const5453 BView::ExplicitMinSize() const
5454 {
5455 	return fLayoutData->fMinSize;
5456 }
5457 
5458 
5459 BSize
ExplicitMaxSize() const5460 BView::ExplicitMaxSize() const
5461 {
5462 	return fLayoutData->fMaxSize;
5463 }
5464 
5465 
5466 BSize
ExplicitPreferredSize() const5467 BView::ExplicitPreferredSize() const
5468 {
5469 	return fLayoutData->fPreferredSize;
5470 }
5471 
5472 
5473 BAlignment
ExplicitAlignment() const5474 BView::ExplicitAlignment() const
5475 {
5476 	return fLayoutData->fAlignment;
5477 }
5478 
5479 
5480 bool
HasHeightForWidth()5481 BView::HasHeightForWidth()
5482 {
5483 	return (fLayoutData->fLayout
5484 		? fLayoutData->fLayout->HasHeightForWidth() : false);
5485 }
5486 
5487 
5488 void
GetHeightForWidth(float width,float * min,float * max,float * preferred)5489 BView::GetHeightForWidth(float width, float* min, float* max, float* preferred)
5490 {
5491 	if (fLayoutData->fLayout)
5492 		fLayoutData->fLayout->GetHeightForWidth(width, min, max, preferred);
5493 }
5494 
5495 
5496 void
SetLayout(BLayout * layout)5497 BView::SetLayout(BLayout* layout)
5498 {
5499 	if (layout == fLayoutData->fLayout)
5500 		return;
5501 
5502 	if (layout && layout->Layout())
5503 		debugger("BView::SetLayout() failed, layout is already in use.");
5504 
5505 	fFlags |= B_SUPPORTS_LAYOUT;
5506 
5507 	// unset and delete the old layout
5508 	if (fLayoutData->fLayout) {
5509 		fLayoutData->fLayout->RemoveSelf();
5510 		fLayoutData->fLayout->SetOwner(NULL);
5511 		delete fLayoutData->fLayout;
5512 	}
5513 
5514 	fLayoutData->fLayout = layout;
5515 
5516 	if (fLayoutData->fLayout) {
5517 		fLayoutData->fLayout->SetOwner(this);
5518 
5519 		// add all children
5520 		int count = CountChildren();
5521 		for (int i = 0; i < count; i++)
5522 			fLayoutData->fLayout->AddView(ChildAt(i));
5523 	}
5524 
5525 	InvalidateLayout();
5526 }
5527 
5528 
5529 BLayout*
GetLayout() const5530 BView::GetLayout() const
5531 {
5532 	return fLayoutData->fLayout;
5533 }
5534 
5535 
5536 void
InvalidateLayout(bool descendants)5537 BView::InvalidateLayout(bool descendants)
5538 {
5539 	// printf("BView(%p)::InvalidateLayout(%i), valid: %i, inProgress: %i\n",
5540 	//	this, descendants, fLayoutData->fLayoutValid,
5541 	//	fLayoutData->fLayoutInProgress);
5542 
5543 	if (!fLayoutData->fMinMaxValid || fLayoutData->fLayoutInProgress
5544  			|| fLayoutData->fLayoutInvalidationDisabled > 0) {
5545 		return;
5546 	}
5547 	fLayoutData->fLayoutValid = false;
5548 	fLayoutData->fMinMaxValid = false;
5549 	LayoutInvalidated(descendants);
5550 
5551 	if (descendants) {
5552 		for (BView* child = fFirstChild;
5553 			child; child = child->fNextSibling) {
5554 			child->InvalidateLayout(descendants);
5555 		}
5556 	}
5557 
5558 	if (fLayoutData->fLayout)
5559 		fLayoutData->fLayout->InvalidateLayout(descendants);
5560 	else
5561 		_InvalidateParentLayout();
5562 
5563 	if (fTopLevelView
5564 		&& fOwner != NULL)
5565 		fOwner->PostMessage(B_LAYOUT_WINDOW);
5566 }
5567 
5568 
5569 void
EnableLayoutInvalidation()5570 BView::EnableLayoutInvalidation()
5571 {
5572 	if (fLayoutData->fLayoutInvalidationDisabled > 0)
5573 		fLayoutData->fLayoutInvalidationDisabled--;
5574 }
5575 
5576 
5577 void
DisableLayoutInvalidation()5578 BView::DisableLayoutInvalidation()
5579 {
5580 	fLayoutData->fLayoutInvalidationDisabled++;
5581 }
5582 
5583 
5584 bool
IsLayoutInvalidationDisabled()5585 BView::IsLayoutInvalidationDisabled()
5586 {
5587 	if (fLayoutData->fLayoutInvalidationDisabled > 0)
5588 		return true;
5589 	return false;
5590 }
5591 
5592 
5593 bool
IsLayoutValid() const5594 BView::IsLayoutValid() const
5595 {
5596 	return fLayoutData->fLayoutValid;
5597 }
5598 
5599 
5600 void
ResetLayoutInvalidation()5601 BView::ResetLayoutInvalidation()
5602 {
5603 	fLayoutData->fMinMaxValid = true;
5604 }
5605 
5606 
5607 BLayoutContext*
LayoutContext() const5608 BView::LayoutContext() const
5609 {
5610 	return fLayoutData->fLayoutContext;
5611 }
5612 
5613 
5614 void
Layout(bool force)5615 BView::Layout(bool force)
5616 {
5617 	BLayoutContext context;
5618 	_Layout(force, &context);
5619 }
5620 
5621 
5622 void
Relayout()5623 BView::Relayout()
5624 {
5625 	if (fLayoutData->fLayoutValid && !fLayoutData->fLayoutInProgress) {
5626 		fLayoutData->fNeedsRelayout = true;
5627 		if (fLayoutData->fLayout)
5628 			fLayoutData->fLayout->RequireLayout();
5629 
5630 		// Layout() is recursive, that is if the parent view is currently laid
5631 		// out, we don't call layout() on this view, but wait for the parent's
5632 		// Layout() to do that for us.
5633 		if (!fParent || !fParent->fLayoutData->fLayoutInProgress)
5634 			Layout(false);
5635 	}
5636 }
5637 
5638 
5639 void
LayoutInvalidated(bool descendants)5640 BView::LayoutInvalidated(bool descendants)
5641 {
5642 	// hook method
5643 }
5644 
5645 
5646 void
DoLayout()5647 BView::DoLayout()
5648 {
5649 	if (fLayoutData->fLayout)
5650 		fLayoutData->fLayout->_LayoutWithinContext(false, LayoutContext());
5651 }
5652 
5653 
5654 void
SetToolTip(const char * text)5655 BView::SetToolTip(const char* text)
5656 {
5657 	if (text == NULL || text[0] == '\0') {
5658 		SetToolTip((BToolTip*)NULL);
5659 		return;
5660 	}
5661 
5662 	if (BTextToolTip* tip = dynamic_cast<BTextToolTip*>(fToolTip))
5663 		tip->SetText(text);
5664 	else
5665 		SetToolTip(new BTextToolTip(text));
5666 }
5667 
5668 
5669 void
SetToolTip(BToolTip * tip)5670 BView::SetToolTip(BToolTip* tip)
5671 {
5672 	if (fToolTip == tip)
5673 		return;
5674 	else if (tip == NULL)
5675 		HideToolTip();
5676 
5677 	if (fToolTip != NULL)
5678 		fToolTip->ReleaseReference();
5679 
5680 	fToolTip = tip;
5681 
5682 	if (fToolTip != NULL)
5683 		fToolTip->AcquireReference();
5684 }
5685 
5686 
5687 BToolTip*
ToolTip() const5688 BView::ToolTip() const
5689 {
5690 	return fToolTip;
5691 }
5692 
5693 
5694 void
ShowToolTip(BToolTip * tip)5695 BView::ShowToolTip(BToolTip* tip)
5696 {
5697 	if (tip == NULL)
5698 		return;
5699 
5700 	BPoint where;
5701 	GetMouse(&where, NULL, false);
5702 
5703 	BToolTipManager::Manager()->ShowTip(tip, ConvertToScreen(where), this);
5704 }
5705 
5706 
5707 void
HideToolTip()5708 BView::HideToolTip()
5709 {
5710 	BToolTipManager::Manager()->HideTip();
5711 }
5712 
5713 
5714 bool
GetToolTipAt(BPoint point,BToolTip ** _tip)5715 BView::GetToolTipAt(BPoint point, BToolTip** _tip)
5716 {
5717 	if (fToolTip != NULL) {
5718 		*_tip = fToolTip;
5719 		return true;
5720 	}
5721 
5722 	*_tip = NULL;
5723 	return false;
5724 }
5725 
5726 
5727 void
LayoutChanged()5728 BView::LayoutChanged()
5729 {
5730 	// hook method
5731 }
5732 
5733 
5734 void
_Layout(bool force,BLayoutContext * context)5735 BView::_Layout(bool force, BLayoutContext* context)
5736 {
5737 //printf("%p->BView::_Layout(%d, %p)\n", this, force, context);
5738 //printf("  fNeedsRelayout: %d, fLayoutValid: %d, fLayoutInProgress: %d\n",
5739 //fLayoutData->fNeedsRelayout, fLayoutData->fLayoutValid,
5740 //fLayoutData->fLayoutInProgress);
5741 	if (fLayoutData->fNeedsRelayout || !fLayoutData->fLayoutValid || force) {
5742 		fLayoutData->fLayoutValid = false;
5743 
5744 		if (fLayoutData->fLayoutInProgress)
5745 			return;
5746 
5747 		BLayoutContext* oldContext = fLayoutData->fLayoutContext;
5748 		fLayoutData->fLayoutContext = context;
5749 
5750 		fLayoutData->fLayoutInProgress = true;
5751 		DoLayout();
5752 		fLayoutData->fLayoutInProgress = false;
5753 
5754 		fLayoutData->fLayoutValid = true;
5755 		fLayoutData->fMinMaxValid = true;
5756 		fLayoutData->fNeedsRelayout = false;
5757 
5758 		// layout children
5759 		for(BView* child = fFirstChild; child; child = child->fNextSibling) {
5760 			if (!child->IsHidden(child))
5761 				child->_Layout(force, context);
5762 		}
5763 
5764 		LayoutChanged();
5765 
5766 		fLayoutData->fLayoutContext = oldContext;
5767 
5768 		// invalidate the drawn content, if requested
5769 		if (fFlags & B_INVALIDATE_AFTER_LAYOUT)
5770 			Invalidate();
5771 	}
5772 }
5773 
5774 
5775 void
_LayoutLeft(BLayout * deleted)5776 BView::_LayoutLeft(BLayout* deleted)
5777 {
5778 	// If our layout is added to another layout (via BLayout::AddItem())
5779 	// then we share ownership of our layout. In the event that our layout gets
5780 	// deleted by the layout it has been added to, this method is called so
5781 	// that we don't double-delete our layout.
5782 	if (fLayoutData->fLayout == deleted)
5783 		fLayoutData->fLayout = NULL;
5784 	InvalidateLayout();
5785 }
5786 
5787 
5788 void
_InvalidateParentLayout()5789 BView::_InvalidateParentLayout()
5790 {
5791 	if (!fParent)
5792 		return;
5793 
5794 	BLayout* layout = fLayoutData->fLayout;
5795 	BLayout* layoutParent = layout ? layout->Layout() : NULL;
5796 	if (layoutParent) {
5797 		layoutParent->InvalidateLayout();
5798 	} else if (fLayoutData->fLayoutItems.CountItems() > 0) {
5799 		int32 count = fLayoutData->fLayoutItems.CountItems();
5800 		for (int32 i = 0; i < count; i++) {
5801 			fLayoutData->fLayoutItems.ItemAt(i)->Layout()->InvalidateLayout();
5802 		}
5803 	} else {
5804 		fParent->InvalidateLayout();
5805 	}
5806 }
5807 
5808 
5809 //	#pragma mark - Private Functions
5810 
5811 
5812 void
_InitData(BRect frame,const char * name,uint32 resizingMode,uint32 flags)5813 BView::_InitData(BRect frame, const char* name, uint32 resizingMode,
5814 	uint32 flags)
5815 {
5816 	// Info: The name of the view is set by BHandler constructor
5817 
5818 	STRACE(("BView::_InitData: enter\n"));
5819 
5820 	// initialize members
5821 	if ((resizingMode & ~_RESIZE_MASK_) || (flags & _RESIZE_MASK_))
5822 		printf("%s BView::_InitData(): resizing mode or flags swapped\n", name);
5823 
5824 	// There are applications that swap the resize mask and the flags in the
5825 	// BView constructor. This does not cause problems under BeOS as it just
5826 	// ors the two fields to one 32bit flag.
5827 	// For now we do the same but print the above warning message.
5828 	// TODO: this should be removed at some point and the original
5829 	// version restored:
5830 	// fFlags = (resizingMode & _RESIZE_MASK_) | (flags & ~_RESIZE_MASK_);
5831 	fFlags = resizingMode | flags;
5832 
5833 	// handle rounding
5834 	frame.left = roundf(frame.left);
5835 	frame.top = roundf(frame.top);
5836 	frame.right = roundf(frame.right);
5837 	frame.bottom = roundf(frame.bottom);
5838 
5839 	fParentOffset.Set(frame.left, frame.top);
5840 
5841 	fOwner = NULL;
5842 	fParent = NULL;
5843 	fNextSibling = NULL;
5844 	fPreviousSibling = NULL;
5845 	fFirstChild = NULL;
5846 
5847 	fShowLevel = 0;
5848 	fTopLevelView = false;
5849 
5850 	fCurrentPicture = NULL;
5851 	fCommArray = NULL;
5852 
5853 	fVerScroller = NULL;
5854 	fHorScroller = NULL;
5855 
5856 	fIsPrinting = false;
5857 	fAttached = false;
5858 
5859 	// TODO: Since we cannot communicate failure, we don't use std::nothrow here
5860 	// TODO: Maybe we could auto-delete those views on AddChild() instead?
5861 	fState = new BPrivate::ViewState;
5862 
5863 	fBounds = frame.OffsetToCopy(B_ORIGIN);
5864 	fShelf = NULL;
5865 
5866 	fEventMask = 0;
5867 	fEventOptions = 0;
5868 	fMouseEventOptions = 0;
5869 
5870 	fLayoutData = new LayoutData;
5871 
5872 	fToolTip = NULL;
5873 
5874 	if ((flags & B_SUPPORTS_LAYOUT) != 0) {
5875 		SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
5876 		SetLowUIColor(ViewUIColor());
5877 		SetHighUIColor(B_PANEL_TEXT_COLOR);
5878 	}
5879 }
5880 
5881 
5882 void
_RemoveCommArray()5883 BView::_RemoveCommArray()
5884 {
5885 	if (fCommArray) {
5886 		delete [] fCommArray->array;
5887 		delete fCommArray;
5888 		fCommArray = NULL;
5889 	}
5890 }
5891 
5892 
5893 void
_SetOwner(BWindow * newOwner)5894 BView::_SetOwner(BWindow* newOwner)
5895 {
5896 	if (!newOwner)
5897 		_RemoveCommArray();
5898 
5899 	if (fOwner != newOwner && fOwner) {
5900 		if (fOwner->fFocus == this)
5901 			MakeFocus(false);
5902 
5903 		if (fOwner->fLastMouseMovedView == this)
5904 			fOwner->fLastMouseMovedView = NULL;
5905 
5906 		fOwner->RemoveHandler(this);
5907 		if (fShelf)
5908 			fOwner->RemoveHandler(fShelf);
5909 	}
5910 
5911 	if (newOwner && newOwner != fOwner) {
5912 		newOwner->AddHandler(this);
5913 		if (fShelf)
5914 			newOwner->AddHandler(fShelf);
5915 
5916 		if (fTopLevelView)
5917 			SetNextHandler(newOwner);
5918 		else
5919 			SetNextHandler(fParent);
5920 	}
5921 
5922 	fOwner = newOwner;
5923 
5924 	for (BView* child = fFirstChild; child != NULL; child = child->fNextSibling)
5925 		child->_SetOwner(newOwner);
5926 }
5927 
5928 
5929 void
_ClipToPicture(BPicture * picture,BPoint where,bool invert,bool sync)5930 BView::_ClipToPicture(BPicture* picture, BPoint where, bool invert, bool sync)
5931 {
5932 	if (!_CheckOwnerLockAndSwitchCurrent())
5933 		return;
5934 
5935 	if (picture == NULL) {
5936 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
5937 		fOwner->fLink->Attach<int32>(-1);
5938 
5939 		// NOTE: No need to sync here, since the -1 token cannot
5940 		// become invalid on the server.
5941 	} else {
5942 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_PICTURE);
5943 		fOwner->fLink->Attach<int32>(picture->Token());
5944 		fOwner->fLink->Attach<BPoint>(where);
5945 		fOwner->fLink->Attach<bool>(invert);
5946 
5947 		// NOTE: "sync" defaults to true in public methods. If you know what
5948 		// you are doing, i.e. if you know your BPicture stays valid, you
5949 		// can avoid the performance impact of syncing. In a use-case where
5950 		// the client creates BPictures on the stack, these BPictures may
5951 		// have issued a AS_DELETE_PICTURE command to the ServerApp when Draw()
5952 		// goes out of scope, and the command is processed earlier in the
5953 		// ServerApp thread than the AS_VIEW_CLIP_TO_PICTURE command in the
5954 		// ServerWindow thread, which will then have the result that no
5955 		// ServerPicture is found of the token.
5956 		if (sync)
5957 			Sync();
5958 	}
5959 }
5960 
5961 
5962 void
_ClipToRect(BRect rect,bool inverse)5963 BView::_ClipToRect(BRect rect, bool inverse)
5964 {
5965 	if (_CheckOwnerLockAndSwitchCurrent()) {
5966 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_RECT);
5967 		fOwner->fLink->Attach<bool>(inverse);
5968 		fOwner->fLink->Attach<BRect>(rect);
5969 		_FlushIfNotInTransaction();
5970 	}
5971 }
5972 
5973 
5974 void
_ClipToShape(BShape * shape,bool inverse)5975 BView::_ClipToShape(BShape* shape, bool inverse)
5976 {
5977 	if (shape == NULL)
5978 		return;
5979 
5980 	shape_data* sd = BShape::Private(*shape).PrivateData();
5981 	if (sd->opCount == 0 || sd->ptCount == 0)
5982 		return;
5983 
5984 	if (_CheckOwnerLockAndSwitchCurrent()) {
5985 		fOwner->fLink->StartMessage(AS_VIEW_CLIP_TO_SHAPE);
5986 		fOwner->fLink->Attach<bool>(inverse);
5987 		fOwner->fLink->AttachShape(*shape);
5988 		_FlushIfNotInTransaction();
5989 	}
5990 }
5991 
5992 
5993 bool
_RemoveChildFromList(BView * child)5994 BView::_RemoveChildFromList(BView* child)
5995 {
5996 	if (child->fParent != this)
5997 		return false;
5998 
5999 	if (fFirstChild == child) {
6000 		// it's the first view in the list
6001 		fFirstChild = child->fNextSibling;
6002 	} else {
6003 		// there must be a previous sibling
6004 		child->fPreviousSibling->fNextSibling = child->fNextSibling;
6005 	}
6006 
6007 	if (child->fNextSibling)
6008 		child->fNextSibling->fPreviousSibling = child->fPreviousSibling;
6009 
6010 	child->fParent = NULL;
6011 	child->fNextSibling = NULL;
6012 	child->fPreviousSibling = NULL;
6013 
6014 	return true;
6015 }
6016 
6017 
6018 bool
_AddChildToList(BView * child,BView * before)6019 BView::_AddChildToList(BView* child, BView* before)
6020 {
6021 	if (!child)
6022 		return false;
6023 	if (child->fParent != NULL) {
6024 		debugger("View already belongs to someone else");
6025 		return false;
6026 	}
6027 	if (before != NULL && before->fParent != this) {
6028 		debugger("Invalid before view");
6029 		return false;
6030 	}
6031 
6032 	if (before != NULL) {
6033 		// add view before this one
6034 		child->fNextSibling = before;
6035 		child->fPreviousSibling = before->fPreviousSibling;
6036 		if (child->fPreviousSibling != NULL)
6037 			child->fPreviousSibling->fNextSibling = child;
6038 
6039 		before->fPreviousSibling = child;
6040 		if (fFirstChild == before)
6041 			fFirstChild = child;
6042 	} else {
6043 		// add view to the end of the list
6044 		BView* last = fFirstChild;
6045 		while (last != NULL && last->fNextSibling != NULL) {
6046 			last = last->fNextSibling;
6047 		}
6048 
6049 		if (last != NULL) {
6050 			last->fNextSibling = child;
6051 			child->fPreviousSibling = last;
6052 		} else {
6053 			fFirstChild = child;
6054 			child->fPreviousSibling = NULL;
6055 		}
6056 
6057 		child->fNextSibling = NULL;
6058 	}
6059 
6060 	child->fParent = this;
6061 	return true;
6062 }
6063 
6064 
6065 /*!	\brief Creates the server counterpart of this view.
6066 	This is only done for views that are part of the view hierarchy, ie. when
6067 	they are attached to a window.
6068 	RemoveSelf() deletes the server object again.
6069 */
6070 bool
_CreateSelf()6071 BView::_CreateSelf()
6072 {
6073 	// AS_VIEW_CREATE & AS_VIEW_CREATE_ROOT do not use the
6074 	// current view mechanism via _CheckLockAndSwitchCurrent() - the token
6075 	// of the view and its parent are both send to the server.
6076 
6077 	if (fTopLevelView)
6078 		fOwner->fLink->StartMessage(AS_VIEW_CREATE_ROOT);
6079 	else
6080  		fOwner->fLink->StartMessage(AS_VIEW_CREATE);
6081 
6082 	fOwner->fLink->Attach<int32>(_get_object_token_(this));
6083 	fOwner->fLink->AttachString(Name());
6084 	fOwner->fLink->Attach<BRect>(Frame());
6085 	fOwner->fLink->Attach<BPoint>(LeftTop());
6086 	fOwner->fLink->Attach<uint32>(ResizingMode());
6087 	fOwner->fLink->Attach<uint32>(fEventMask);
6088 	fOwner->fLink->Attach<uint32>(fEventOptions);
6089 	fOwner->fLink->Attach<uint32>(Flags());
6090 	fOwner->fLink->Attach<bool>(IsHidden(this));
6091 	fOwner->fLink->Attach<rgb_color>(fState->view_color);
6092 	if (fTopLevelView)
6093 		fOwner->fLink->Attach<int32>(B_NULL_TOKEN);
6094 	else
6095 		fOwner->fLink->Attach<int32>(_get_object_token_(fParent));
6096 	fOwner->fLink->Flush();
6097 
6098 	_CheckOwnerLockAndSwitchCurrent();
6099 	fState->UpdateServerState(*fOwner->fLink);
6100 
6101 	// we create all its children, too
6102 
6103 	for (BView* child = fFirstChild; child != NULL;
6104 			child = child->fNextSibling) {
6105 		child->_CreateSelf();
6106 	}
6107 
6108 	fOwner->fLink->Flush();
6109 	return true;
6110 }
6111 
6112 
6113 /*!	Sets the new view position.
6114 	It doesn't contact the server, though - the only case where this
6115 	is called outside of MoveTo() is as reaction of moving a view
6116 	in the server (a.k.a. B_WINDOW_RESIZED).
6117 	It also calls the BView's FrameMoved() hook.
6118 */
6119 void
_MoveTo(int32 x,int32 y)6120 BView::_MoveTo(int32 x, int32 y)
6121 {
6122 	fParentOffset.Set(x, y);
6123 
6124 	if (Window() != NULL && fFlags & B_FRAME_EVENTS) {
6125 		BMessage moved(B_VIEW_MOVED);
6126 		moved.AddInt64("when", system_time());
6127 		moved.AddPoint("where", BPoint(x, y));
6128 
6129 		BMessenger target(this);
6130 		target.SendMessage(&moved);
6131 	}
6132 }
6133 
6134 
6135 /*!	Computes the actual new frame size and recalculates the size of
6136 	the children as well.
6137 	It doesn't contact the server, though - the only case where this
6138 	is called outside of ResizeBy() is as reaction of resizing a view
6139 	in the server (a.k.a. B_WINDOW_RESIZED).
6140 	It also calls the BView's FrameResized() hook.
6141 */
6142 void
_ResizeBy(int32 deltaWidth,int32 deltaHeight)6143 BView::_ResizeBy(int32 deltaWidth, int32 deltaHeight)
6144 {
6145 	fBounds.right += deltaWidth;
6146 	fBounds.bottom += deltaHeight;
6147 
6148 	if (Window() == NULL) {
6149 		// we're not supposed to exercise the resizing code in case
6150 		// we haven't been attached to a window yet
6151 		return;
6152 	}
6153 
6154 	// layout the children
6155 	if ((fFlags & B_SUPPORTS_LAYOUT) != 0) {
6156 		Relayout();
6157 	} else {
6158 		for (BView* child = fFirstChild; child; child = child->fNextSibling)
6159 			child->_ParentResizedBy(deltaWidth, deltaHeight);
6160 	}
6161 
6162 	if (fFlags & B_FRAME_EVENTS) {
6163 		BMessage resized(B_VIEW_RESIZED);
6164 		resized.AddInt64("when", system_time());
6165 		resized.AddInt32("width", fBounds.IntegerWidth());
6166 		resized.AddInt32("height", fBounds.IntegerHeight());
6167 
6168 		BMessenger target(this);
6169 		target.SendMessage(&resized);
6170 	}
6171 }
6172 
6173 
6174 /*!	Relayouts the view according to its resizing mode. */
6175 void
_ParentResizedBy(int32 x,int32 y)6176 BView::_ParentResizedBy(int32 x, int32 y)
6177 {
6178 	uint32 resizingMode = fFlags & _RESIZE_MASK_;
6179 	BRect newFrame = Frame();
6180 
6181 	// follow with left side
6182 	if ((resizingMode & 0x0F00U) == _VIEW_RIGHT_ << 8)
6183 		newFrame.left += x;
6184 	else if ((resizingMode & 0x0F00U) == _VIEW_CENTER_ << 8)
6185 		newFrame.left += x / 2;
6186 
6187 	// follow with right side
6188 	if ((resizingMode & 0x000FU) == _VIEW_RIGHT_)
6189 		newFrame.right += x;
6190 	else if ((resizingMode & 0x000FU) == _VIEW_CENTER_)
6191 		newFrame.right += x / 2;
6192 
6193 	// follow with top side
6194 	if ((resizingMode & 0xF000U) == _VIEW_BOTTOM_ << 12)
6195 		newFrame.top += y;
6196 	else if ((resizingMode & 0xF000U) == _VIEW_CENTER_ << 12)
6197 		newFrame.top += y / 2;
6198 
6199 	// follow with bottom side
6200 	if ((resizingMode & 0x00F0U) == _VIEW_BOTTOM_ << 4)
6201 		newFrame.bottom += y;
6202 	else if ((resizingMode & 0x00F0U) == _VIEW_CENTER_ << 4)
6203 		newFrame.bottom += y / 2;
6204 
6205 	if (newFrame.LeftTop() != fParentOffset) {
6206 		// move view
6207 		_MoveTo((int32)roundf(newFrame.left), (int32)roundf(newFrame.top));
6208 	}
6209 
6210 	if (newFrame != Frame()) {
6211 		// resize view
6212 		int32 widthDiff = (int32)(newFrame.Width() - fBounds.Width());
6213 		int32 heightDiff = (int32)(newFrame.Height() - fBounds.Height());
6214 		_ResizeBy(widthDiff, heightDiff);
6215 	}
6216 }
6217 
6218 
6219 void
_Activate(bool active)6220 BView::_Activate(bool active)
6221 {
6222 	WindowActivated(active);
6223 
6224 	for (BView* child = fFirstChild; child != NULL;
6225 			child = child->fNextSibling) {
6226 		child->_Activate(active);
6227 	}
6228 }
6229 
6230 
6231 void
_Attach()6232 BView::_Attach()
6233 {
6234 	if (fOwner != NULL) {
6235 		// unmask state flags to force [re]syncing with the app_server
6236 		fState->valid_flags &= ~(B_VIEW_WHICH_VIEW_COLOR_BIT
6237 			| B_VIEW_WHICH_LOW_COLOR_BIT | B_VIEW_WHICH_HIGH_COLOR_BIT);
6238 
6239 		if (fState->which_view_color != B_NO_COLOR)
6240 			SetViewUIColor(fState->which_view_color,
6241 				fState->which_view_color_tint);
6242 
6243 		if (fState->which_high_color != B_NO_COLOR)
6244 			SetHighUIColor(fState->which_high_color,
6245 				fState->which_high_color_tint);
6246 
6247 		if (fState->which_low_color != B_NO_COLOR)
6248 			SetLowUIColor(fState->which_low_color,
6249 				fState->which_low_color_tint);
6250 	}
6251 
6252 	AttachedToWindow();
6253 
6254 	fAttached = true;
6255 
6256 	// after giving the view a chance to do this itself,
6257 	// check for the B_PULSE_NEEDED flag and make sure the
6258 	// window set's up the pulse messaging
6259 	if (fOwner) {
6260 		if (fFlags & B_PULSE_NEEDED) {
6261 			_CheckLock();
6262 			if (fOwner->fPulseRunner == NULL)
6263 				fOwner->SetPulseRate(fOwner->PulseRate());
6264 		}
6265 
6266 		if (!fOwner->IsHidden())
6267 			Invalidate();
6268 	}
6269 
6270 	for (BView* child = fFirstChild; child != NULL;
6271 			child = child->fNextSibling) {
6272 		// we need to check for fAttached as new views could have been
6273 		// added in AttachedToWindow() - and those are already attached
6274 		if (!child->fAttached)
6275 			child->_Attach();
6276 	}
6277 
6278 	AllAttached();
6279 }
6280 
6281 
6282 void
_ColorsUpdated(BMessage * message)6283 BView::_ColorsUpdated(BMessage* message)
6284 {
6285 	if (fTopLevelView
6286 		&& fLayoutData->fLayout != NULL
6287 		&& !fState->IsValid(B_VIEW_WHICH_VIEW_COLOR_BIT)) {
6288 		SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
6289 		SetHighUIColor(B_PANEL_TEXT_COLOR);
6290 	}
6291 
6292 	rgb_color color;
6293 
6294 	const char* colorName = ui_color_name(fState->which_view_color);
6295 	if (colorName != NULL && message->FindColor(colorName, &color) == B_OK) {
6296 		fState->view_color = tint_color(color, fState->which_view_color_tint);
6297 		fState->valid_flags |= B_VIEW_VIEW_COLOR_BIT;
6298 	}
6299 
6300 	colorName = ui_color_name(fState->which_low_color);
6301 	if (colorName != NULL && message->FindColor(colorName, &color) == B_OK) {
6302 		fState->low_color = tint_color(color, fState->which_low_color_tint);
6303 		fState->valid_flags |= B_VIEW_LOW_COLOR_BIT;
6304 	}
6305 
6306 	colorName = ui_color_name(fState->which_high_color);
6307 	if (colorName != NULL && message->FindColor(colorName, &color) == B_OK) {
6308 		fState->high_color = tint_color(color, fState->which_high_color_tint);
6309 		fState->valid_flags |= B_VIEW_HIGH_COLOR_BIT;
6310 	}
6311 
6312 	MessageReceived(message);
6313 
6314 	for (BView* child = fFirstChild; child != NULL;
6315 			child = child->fNextSibling)
6316 		child->_ColorsUpdated(message);
6317 
6318 	Invalidate();
6319 }
6320 
6321 
6322 void
_Detach()6323 BView::_Detach()
6324 {
6325 	DetachedFromWindow();
6326 	fAttached = false;
6327 
6328 	for (BView* child = fFirstChild; child != NULL;
6329 			child = child->fNextSibling) {
6330 		child->_Detach();
6331 	}
6332 
6333 	AllDetached();
6334 
6335 	if (fOwner) {
6336 		_CheckLock();
6337 
6338 		if (!fOwner->IsHidden())
6339 			Invalidate();
6340 
6341 		// make sure our owner doesn't need us anymore
6342 
6343 		if (fOwner->CurrentFocus() == this) {
6344 			MakeFocus(false);
6345 			// MakeFocus() is virtual and might not be
6346 			// passing through to the BView version,
6347 			// but we need to make sure at this point
6348 			// that we are not the focus view anymore.
6349 			if (fOwner->CurrentFocus() == this)
6350 				fOwner->_SetFocus(NULL, true);
6351 		}
6352 
6353 		if (fOwner->fDefaultButton == this)
6354 			fOwner->SetDefaultButton(NULL);
6355 
6356 		if (fOwner->fKeyMenuBar == this)
6357 			fOwner->fKeyMenuBar = NULL;
6358 
6359 		if (fOwner->fLastMouseMovedView == this)
6360 			fOwner->fLastMouseMovedView = NULL;
6361 
6362 		if (fOwner->fLastViewToken == _get_object_token_(this))
6363 			fOwner->fLastViewToken = B_NULL_TOKEN;
6364 
6365 		_SetOwner(NULL);
6366 	}
6367 }
6368 
6369 
6370 void
_Draw(BRect updateRect)6371 BView::_Draw(BRect updateRect)
6372 {
6373 	if (IsHidden(this) || !(Flags() & B_WILL_DRAW))
6374 		return;
6375 
6376 	// NOTE: if ViewColor() == B_TRANSPARENT_COLOR and no B_WILL_DRAW
6377 	// -> View is simply not drawn at all
6378 
6379 	_SwitchServerCurrentView();
6380 
6381 	ConvertFromScreen(&updateRect);
6382 
6383 	// TODO: make states robust (the hook implementation could
6384 	// mess things up if it uses non-matching Push- and PopState(),
6385 	// we would not be guaranteed to still have the same state on
6386 	// the stack after having called Draw())
6387 	PushState();
6388 	Draw(updateRect);
6389 	PopState();
6390 	Flush();
6391 }
6392 
6393 
6394 void
_DrawAfterChildren(BRect updateRect)6395 BView::_DrawAfterChildren(BRect updateRect)
6396 {
6397 	if (IsHidden(this) || !(Flags() & B_WILL_DRAW)
6398 		|| !(Flags() & B_DRAW_ON_CHILDREN))
6399 		return;
6400 
6401 	_SwitchServerCurrentView();
6402 
6403 	ConvertFromScreen(&updateRect);
6404 
6405 	// TODO: make states robust (see above)
6406 	PushState();
6407 	DrawAfterChildren(updateRect);
6408 	PopState();
6409 	Flush();
6410 }
6411 
6412 
6413 void
_FontsUpdated(BMessage * message)6414 BView::_FontsUpdated(BMessage* message)
6415 {
6416 	MessageReceived(message);
6417 
6418 	for (BView* child = fFirstChild; child != NULL;
6419 			child = child->fNextSibling) {
6420 		child->_FontsUpdated(message);
6421 	}
6422 }
6423 
6424 
6425 void
_Pulse()6426 BView::_Pulse()
6427 {
6428 	if ((Flags() & B_PULSE_NEEDED) != 0)
6429 		Pulse();
6430 
6431 	for (BView* child = fFirstChild; child != NULL;
6432 			child = child->fNextSibling) {
6433 		child->_Pulse();
6434 	}
6435 }
6436 
6437 
6438 void
_UpdateStateForRemove()6439 BView::_UpdateStateForRemove()
6440 {
6441 	// TODO: _CheckLockAndSwitchCurrent() would be good enough, no?
6442 	if (!_CheckOwnerLockAndSwitchCurrent())
6443 		return;
6444 
6445 	fState->UpdateFrom(*fOwner->fLink);
6446 //	if (!fState->IsValid(B_VIEW_FRAME_BIT)) {
6447 //		fOwner->fLink->StartMessage(AS_VIEW_GET_COORD);
6448 //
6449 //		status_t code;
6450 //		if (fOwner->fLink->FlushWithReply(code) == B_OK
6451 //			&& code == B_OK) {
6452 //			fOwner->fLink->Read<BPoint>(&fParentOffset);
6453 //			fOwner->fLink->Read<BRect>(&fBounds);
6454 //			fState->valid_flags |= B_VIEW_FRAME_BIT;
6455 //		}
6456 //	}
6457 
6458 	// update children as well
6459 
6460 	for (BView* child = fFirstChild; child != NULL;
6461 			child = child->fNextSibling) {
6462 		if (child->fOwner)
6463 			child->_UpdateStateForRemove();
6464 	}
6465 }
6466 
6467 
6468 inline void
_UpdatePattern(::pattern pattern)6469 BView::_UpdatePattern(::pattern pattern)
6470 {
6471 	if (fState->IsValid(B_VIEW_PATTERN_BIT) && pattern == fState->pattern)
6472 		return;
6473 
6474 	if (fOwner) {
6475 		_CheckLockAndSwitchCurrent();
6476 
6477 		fOwner->fLink->StartMessage(AS_VIEW_SET_PATTERN);
6478 		fOwner->fLink->Attach< ::pattern>(pattern);
6479 
6480 		fState->valid_flags |= B_VIEW_PATTERN_BIT;
6481 	}
6482 
6483 	fState->pattern = pattern;
6484 }
6485 
6486 
6487 void
_FlushIfNotInTransaction()6488 BView::_FlushIfNotInTransaction()
6489 {
6490 	if (!fOwner->fInTransaction) {
6491 		fOwner->Flush();
6492 	}
6493 }
6494 
6495 
6496 BShelf*
_Shelf() const6497 BView::_Shelf() const
6498 {
6499 	return fShelf;
6500 }
6501 
6502 
6503 void
_SetShelf(BShelf * shelf)6504 BView::_SetShelf(BShelf* shelf)
6505 {
6506 	if (fShelf != NULL && fOwner != NULL)
6507 		fOwner->RemoveHandler(fShelf);
6508 
6509 	fShelf = shelf;
6510 
6511 	if (fShelf != NULL && fOwner != NULL)
6512 		fOwner->AddHandler(fShelf);
6513 }
6514 
6515 
6516 status_t
_SetViewBitmap(const BBitmap * bitmap,BRect srcRect,BRect dstRect,uint32 followFlags,uint32 options)6517 BView::_SetViewBitmap(const BBitmap* bitmap, BRect srcRect, BRect dstRect,
6518 	uint32 followFlags, uint32 options)
6519 {
6520 	if (!_CheckOwnerLockAndSwitchCurrent())
6521 		return B_ERROR;
6522 
6523 	int32 serverToken = bitmap ? bitmap->_ServerToken() : -1;
6524 
6525 	fOwner->fLink->StartMessage(AS_VIEW_SET_VIEW_BITMAP);
6526 	fOwner->fLink->Attach<int32>(serverToken);
6527 	fOwner->fLink->Attach<BRect>(srcRect);
6528 	fOwner->fLink->Attach<BRect>(dstRect);
6529 	fOwner->fLink->Attach<int32>(followFlags);
6530 	fOwner->fLink->Attach<int32>(options);
6531 
6532 	status_t status = B_ERROR;
6533 	fOwner->fLink->FlushWithReply(status);
6534 
6535 	return status;
6536 }
6537 
6538 
6539 bool
_CheckOwnerLockAndSwitchCurrent() const6540 BView::_CheckOwnerLockAndSwitchCurrent() const
6541 {
6542 	STRACE(("BView(%s)::_CheckOwnerLockAndSwitchCurrent()\n", Name()));
6543 
6544 	if (fOwner == NULL) {
6545 		debugger("View method requires owner and doesn't have one.");
6546 		return false;
6547 	}
6548 
6549 	_CheckLockAndSwitchCurrent();
6550 
6551 	return true;
6552 }
6553 
6554 
6555 bool
_CheckOwnerLock() const6556 BView::_CheckOwnerLock() const
6557 {
6558 	if (fOwner) {
6559 		fOwner->check_lock();
6560 		return true;
6561 	} else {
6562 		debugger("View method requires owner and doesn't have one.");
6563 		return false;
6564 	}
6565 }
6566 
6567 
6568 void
_CheckLockAndSwitchCurrent() const6569 BView::_CheckLockAndSwitchCurrent() const
6570 {
6571 	STRACE(("BView(%s)::_CheckLockAndSwitchCurrent()\n", Name()));
6572 
6573 	if (!fOwner)
6574 		return;
6575 
6576 	fOwner->check_lock();
6577 
6578 	_SwitchServerCurrentView();
6579 }
6580 
6581 
6582 void
_CheckLock() const6583 BView::_CheckLock() const
6584 {
6585 	if (fOwner)
6586 		fOwner->check_lock();
6587 }
6588 
6589 
6590 void
_SwitchServerCurrentView() const6591 BView::_SwitchServerCurrentView() const
6592 {
6593 	int32 serverToken = _get_object_token_(this);
6594 
6595 	if (fOwner->fLastViewToken != serverToken) {
6596 		STRACE(("contacting app_server... sending token: %" B_PRId32 "\n",
6597 			serverToken));
6598 		fOwner->fLink->StartMessage(AS_SET_CURRENT_VIEW);
6599 		fOwner->fLink->Attach<int32>(serverToken);
6600 
6601 		fOwner->fLastViewToken = serverToken;
6602 	}
6603 }
6604 
6605 
6606 status_t
ScrollWithMouseWheelDelta(BScrollBar * scrollBar,float delta)6607 BView::ScrollWithMouseWheelDelta(BScrollBar* scrollBar, float delta)
6608 {
6609 	if (scrollBar == NULL || delta == 0.0f)
6610 		return B_BAD_VALUE;
6611 
6612 	float smallStep;
6613 	float largeStep;
6614 	scrollBar->GetSteps(&smallStep, &largeStep);
6615 
6616 	// pressing the shift key scrolls faster (following the pseudo-standard set
6617 	// by other desktop environments).
6618 	if ((modifiers() & B_SHIFT_KEY) != 0)
6619 		delta *= largeStep;
6620 	else
6621 		delta *= smallStep * 3;
6622 
6623 	scrollBar->SetValue(scrollBar->Value() + delta);
6624 
6625 	return B_OK;
6626 }
6627 
6628 
6629 #if __GNUC__ == 2
6630 
6631 
6632 extern "C" void
_ReservedView1__5BView(BView * view,BRect rect)6633 _ReservedView1__5BView(BView* view, BRect rect)
6634 {
6635 	view->BView::DrawAfterChildren(rect);
6636 }
6637 
6638 
6639 extern "C" void
_ReservedView2__5BView(BView * view)6640 _ReservedView2__5BView(BView* view)
6641 {
6642 	// MinSize()
6643 	perform_data_min_size data;
6644 	view->Perform(PERFORM_CODE_MIN_SIZE, &data);
6645 }
6646 
6647 
6648 extern "C" void
_ReservedView3__5BView(BView * view)6649 _ReservedView3__5BView(BView* view)
6650 {
6651 	// MaxSize()
6652 	perform_data_max_size data;
6653 	view->Perform(PERFORM_CODE_MAX_SIZE, &data);
6654 }
6655 
6656 
6657 extern "C" BSize
_ReservedView4__5BView(BView * view)6658 _ReservedView4__5BView(BView* view)
6659 {
6660 	// PreferredSize()
6661 	perform_data_preferred_size data;
6662 	view->Perform(PERFORM_CODE_PREFERRED_SIZE, &data);
6663 	return data.return_value;
6664 }
6665 
6666 
6667 extern "C" BAlignment
_ReservedView5__5BView(BView * view)6668 _ReservedView5__5BView(BView* view)
6669 {
6670 	// LayoutAlignment()
6671 	perform_data_layout_alignment data;
6672 	view->Perform(PERFORM_CODE_LAYOUT_ALIGNMENT, &data);
6673 	return data.return_value;
6674 }
6675 
6676 
6677 extern "C" bool
_ReservedView6__5BView(BView * view)6678 _ReservedView6__5BView(BView* view)
6679 {
6680 	// HasHeightForWidth()
6681 	perform_data_has_height_for_width data;
6682 	view->Perform(PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH, &data);
6683 	return data.return_value;
6684 }
6685 
6686 
6687 extern "C" void
_ReservedView7__5BView(BView * view,float width,float * min,float * max,float * preferred)6688 _ReservedView7__5BView(BView* view, float width, float* min, float* max,
6689 	float* preferred)
6690 {
6691 	// GetHeightForWidth()
6692 	perform_data_get_height_for_width data;
6693 	data.width = width;
6694 	view->Perform(PERFORM_CODE_GET_HEIGHT_FOR_WIDTH, &data);
6695 	if (min != NULL)
6696 		*min = data.min;
6697 	if (max != NULL)
6698 		*max = data.max;
6699 	if (preferred != NULL)
6700 		*preferred = data.preferred;
6701 }
6702 
6703 
6704 extern "C" void
_ReservedView8__5BView(BView * view,BLayout * layout)6705 _ReservedView8__5BView(BView* view, BLayout* layout)
6706 {
6707 	// SetLayout()
6708 	perform_data_set_layout data;
6709 	data.layout = layout;
6710 	view->Perform(PERFORM_CODE_SET_LAYOUT, &data);
6711 }
6712 
6713 
6714 extern "C" void
_ReservedView9__5BView(BView * view,bool descendants)6715 _ReservedView9__5BView(BView* view, bool descendants)
6716 {
6717 	// LayoutInvalidated()
6718 	perform_data_layout_invalidated data;
6719 	data.descendants = descendants;
6720 	view->Perform(PERFORM_CODE_LAYOUT_INVALIDATED, &data);
6721 }
6722 
6723 
6724 extern "C" void
_ReservedView10__5BView(BView * view)6725 _ReservedView10__5BView(BView* view)
6726 {
6727 	// DoLayout()
6728 	view->Perform(PERFORM_CODE_DO_LAYOUT, NULL);
6729 }
6730 
6731 
6732 #endif	// __GNUC__ == 2
6733 
6734 
6735 extern "C" bool
B_IF_GCC_2(_ReservedView11__5BView,_ZN5BView15_ReservedView11Ev)6736 B_IF_GCC_2(_ReservedView11__5BView, _ZN5BView15_ReservedView11Ev)(
6737 	BView* view, BPoint point, BToolTip** _toolTip)
6738 {
6739 	// GetToolTipAt()
6740 	perform_data_get_tool_tip_at data;
6741 	data.point = point;
6742 	data.tool_tip = _toolTip;
6743 	view->Perform(PERFORM_CODE_GET_TOOL_TIP_AT, &data);
6744 	return data.return_value;
6745 }
6746 
6747 
6748 extern "C" void
B_IF_GCC_2(_ReservedView12__5BView,_ZN5BView15_ReservedView12Ev)6749 B_IF_GCC_2(_ReservedView12__5BView, _ZN5BView15_ReservedView12Ev)(
6750 	BView* view)
6751 {
6752 	// LayoutChanged();
6753 	view->Perform(PERFORM_CODE_LAYOUT_CHANGED, NULL);
6754 }
6755 
6756 
_ReservedView13()6757 void BView::_ReservedView13() {}
_ReservedView14()6758 void BView::_ReservedView14() {}
_ReservedView15()6759 void BView::_ReservedView15() {}
_ReservedView16()6760 void BView::_ReservedView16() {}
6761 
6762 
BView(const BView & other)6763 BView::BView(const BView& other)
6764 	:
6765 	BHandler()
6766 {
6767 	// this is private and not functional, but exported
6768 }
6769 
6770 
6771 BView&
operator =(const BView & other)6772 BView::operator=(const BView& other)
6773 {
6774 	// this is private and not functional, but exported
6775 	return *this;
6776 }
6777 
6778 
6779 void
_PrintToStream()6780 BView::_PrintToStream()
6781 {
6782 	printf("BView::_PrintToStream()\n");
6783 	printf("\tName: %s\n"
6784 		"\tParent: %s\n"
6785 		"\tFirstChild: %s\n"
6786 		"\tNextSibling: %s\n"
6787 		"\tPrevSibling: %s\n"
6788 		"\tOwner(Window): %s\n"
6789 		"\tToken: %" B_PRId32 "\n"
6790 		"\tFlags: %" B_PRId32 "\n"
6791 		"\tView origin: (%f,%f)\n"
6792 		"\tView Bounds rectangle: (%f,%f,%f,%f)\n"
6793 		"\tShow level: %d\n"
6794 		"\tTopView?: %s\n"
6795 		"\tBPicture: %s\n"
6796 		"\tVertical Scrollbar %s\n"
6797 		"\tHorizontal Scrollbar %s\n"
6798 		"\tIs Printing?: %s\n"
6799 		"\tShelf?: %s\n"
6800 		"\tEventMask: %" B_PRId32 "\n"
6801 		"\tEventOptions: %" B_PRId32 "\n",
6802 	Name(),
6803 	fParent ? fParent->Name() : "NULL",
6804 	fFirstChild ? fFirstChild->Name() : "NULL",
6805 	fNextSibling ? fNextSibling->Name() : "NULL",
6806 	fPreviousSibling ? fPreviousSibling->Name() : "NULL",
6807 	fOwner ? fOwner->Name() : "NULL",
6808 	_get_object_token_(this),
6809 	fFlags,
6810 	fParentOffset.x, fParentOffset.y,
6811 	fBounds.left, fBounds.top, fBounds.right, fBounds.bottom,
6812 	fShowLevel,
6813 	fTopLevelView ? "YES" : "NO",
6814 	fCurrentPicture? "YES" : "NULL",
6815 	fVerScroller? "YES" : "NULL",
6816 	fHorScroller? "YES" : "NULL",
6817 	fIsPrinting? "YES" : "NO",
6818 	fShelf? "YES" : "NO",
6819 	fEventMask,
6820 	fEventOptions);
6821 
6822 	printf("\tState status:\n"
6823 		"\t\tLocalCoordianteSystem: (%f,%f)\n"
6824 		"\t\tPenLocation: (%f,%f)\n"
6825 		"\t\tPenSize: %f\n"
6826 		"\t\tHighColor: [%d,%d,%d,%d]\n"
6827 		"\t\tLowColor: [%d,%d,%d,%d]\n"
6828 		"\t\tViewColor: [%d,%d,%d,%d]\n"
6829 		"\t\tPattern: %" B_PRIx64 "\n"
6830 		"\t\tDrawingMode: %d\n"
6831 		"\t\tLineJoinMode: %d\n"
6832 		"\t\tLineCapMode: %d\n"
6833 		"\t\tMiterLimit: %f\n"
6834 		"\t\tAlphaSource: %d\n"
6835 		"\t\tAlphaFuntion: %d\n"
6836 		"\t\tScale: %f\n"
6837 		"\t\t(Print)FontAliasing: %s\n"
6838 		"\t\tFont Info:\n",
6839 	fState->origin.x, fState->origin.y,
6840 	fState->pen_location.x, fState->pen_location.y,
6841 	fState->pen_size,
6842 	fState->high_color.red, fState->high_color.blue, fState->high_color.green, fState->high_color.alpha,
6843 	fState->low_color.red, fState->low_color.blue, fState->low_color.green, fState->low_color.alpha,
6844 	fState->view_color.red, fState->view_color.blue, fState->view_color.green, fState->view_color.alpha,
6845 	*((uint64*)&(fState->pattern)),
6846 	fState->drawing_mode,
6847 	fState->line_join,
6848 	fState->line_cap,
6849 	fState->miter_limit,
6850 	fState->alpha_source_mode,
6851 	fState->alpha_function_mode,
6852 	fState->scale,
6853 	fState->font_aliasing? "YES" : "NO");
6854 
6855 	fState->font.PrintToStream();
6856 
6857 	// TODO: also print the line array.
6858 }
6859 
6860 
6861 void
_PrintTree()6862 BView::_PrintTree()
6863 {
6864 	int32 spaces = 2;
6865 	BView* c = fFirstChild; //c = short for: current
6866 	printf( "'%s'\n", Name() );
6867 	if (c != NULL) {
6868 		while(true) {
6869 			// action block
6870 			{
6871 				for (int i = 0; i < spaces; i++)
6872 					printf(" ");
6873 
6874 				printf( "'%s'\n", c->Name() );
6875 			}
6876 
6877 			// go deep
6878 			if (c->fFirstChild) {
6879 				c = c->fFirstChild;
6880 				spaces += 2;
6881 			} else {
6882 				// go right
6883 				if (c->fNextSibling) {
6884 					c = c->fNextSibling;
6885 				} else {
6886 					// go up
6887 					while (!c->fParent->fNextSibling && c->fParent != this) {
6888 						c = c->fParent;
6889 						spaces -= 2;
6890 					}
6891 
6892 					// that enough! We've reached this view.
6893 					if (c->fParent == this)
6894 						break;
6895 
6896 					c = c->fParent->fNextSibling;
6897 					spaces -= 2;
6898 				}
6899 			}
6900 		}
6901 	}
6902 }
6903 
6904 
6905 // #pragma mark -
6906 
6907 
6908 BLayoutItem*
LayoutItemAt(int32 index)6909 BView::Private::LayoutItemAt(int32 index)
6910 {
6911 	return fView->fLayoutData->fLayoutItems.ItemAt(index);
6912 }
6913 
6914 
6915 int32
CountLayoutItems()6916 BView::Private::CountLayoutItems()
6917 {
6918 	return fView->fLayoutData->fLayoutItems.CountItems();
6919 }
6920 
6921 
6922 void
RegisterLayoutItem(BLayoutItem * item)6923 BView::Private::RegisterLayoutItem(BLayoutItem* item)
6924 {
6925 	fView->fLayoutData->fLayoutItems.AddItem(item);
6926 }
6927 
6928 
6929 void
DeregisterLayoutItem(BLayoutItem * item)6930 BView::Private::DeregisterLayoutItem(BLayoutItem* item)
6931 {
6932 	fView->fLayoutData->fLayoutItems.RemoveItem(item);
6933 }
6934 
6935 
6936 bool
MinMaxValid()6937 BView::Private::MinMaxValid()
6938 {
6939 	return fView->fLayoutData->fMinMaxValid;
6940 }
6941 
6942 
6943 bool
WillLayout()6944 BView::Private::WillLayout()
6945 {
6946 	BView::LayoutData* data = fView->fLayoutData;
6947 	if (data->fLayoutInProgress)
6948 		return false;
6949 	if (data->fNeedsRelayout || !data->fLayoutValid || !data->fMinMaxValid)
6950 		return true;
6951 	return false;
6952 }
6953