2 * Copyright 2001-2015 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
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
21 #include <Application.h>
26 #include <GradientLinear.h>
27 #include <GradientRadial.h>
28 #include <GradientRadialFocus.h>
29 #include <GradientDiamond.h>
30 #include <GradientConic.h>
31 #include <InterfaceDefs.h>
33 #include <LayoutContext.h>
34 #include <LayoutUtils.h>
37 #include <MessageQueue.h>
38 #include <ObjectList.h>
42 #include <PropertyInfo.h>
44 #include <ScrollBar.h>
51 #include <AppServerLink.h>
52 #include <binary_compatibility/Interface.h>
53 #include <binary_compatibility/Support.h>
54 #include <MessagePrivate.h>
55 #include <MessageUtils.h>
57 #include <ServerProtocol.h>
58 #include <ServerProtocolStructs.h>
59 #include <ShapePrivate.h>
61 #include <ToolTipManager.h>
62 #include <TokenSpace.h>
63 #include <ViewPrivate.h>
70 # define STRACE(x) printf x
71 # define BVTRACE _PrintToStream()
78 static property_info sViewPropInfo
[] = {
79 { "Frame", { B_GET_PROPERTY
, B_SET_PROPERTY
},
80 { B_DIRECT_SPECIFIER
, 0 }, "The view's frame rectangle.", 0,
83 { "Hidden", { B_GET_PROPERTY
, B_SET_PROPERTY
},
84 { B_DIRECT_SPECIFIER
, 0 }, "Whether or not the view is hidden.",
88 { B_DIRECT_SPECIFIER
, 0 }, "Directs the scripting message to the "
91 { "View", { B_COUNT_PROPERTIES
, 0 },
92 { B_DIRECT_SPECIFIER
, 0 }, "Returns the number of child views.", 0,
96 { B_INDEX_SPECIFIER
, B_REVERSE_INDEX_SPECIFIER
, B_NAME_SPECIFIER
, 0 },
97 "Directs the scripting message to the specified view.", 0
100 { 0, { 0 }, { 0 }, 0, 0 }
108 get_uint32_color(rgb_color color
)
110 return B_BENDIAN_TO_HOST_INT32(*(uint32
*)&color
);
111 // rgb_color is always in rgba format, no matter what endian;
112 // we always return the int32 value in host endian.
116 static inline rgb_color
117 get_rgb_color(uint32 value
)
119 value
= B_HOST_TO_BENDIAN_INT32(value
);
120 return *(rgb_color
*)&value
;
129 ViewState::ViewState()
131 pen_location
.Set(0, 0);
134 // NOTE: the clipping_region is empty
135 // on construction but it is not used yet,
136 // we avoid having to keep track of it via
138 clipping_region_used
= false;
140 high_color
= (rgb_color
){ 0, 0, 0, 255 };
141 low_color
= (rgb_color
){ 255, 255, 255, 255 };
142 view_color
= low_color
;
144 pattern
= B_SOLID_HIGH
;
145 drawing_mode
= B_OP_COPY
;
149 line_join
= B_MITER_JOIN
;
150 line_cap
= B_BUTT_CAP
;
151 miter_limit
= B_DEFAULT_MITER_LIMIT
;
152 fill_rule
= B_NONZERO
;
154 alpha_source_mode
= B_PIXEL_ALPHA
;
155 alpha_function_mode
= B_ALPHA_OVERLAY
;
159 font
= *be_plain_font
;
160 font_flags
= font
.Flags();
161 font_aliasing
= false;
163 // We only keep the B_VIEW_CLIP_REGION_BIT flag invalidated,
164 // because we should get the clipping region from app_server.
165 // The other flags do not need to be included because the data they
166 // represent is already in sync with app_server - app_server uses the
167 // same init (default) values.
168 valid_flags
= ~B_VIEW_CLIP_REGION_BIT
;
170 archiving_flags
= B_VIEW_FRAME_BIT
| B_VIEW_RESIZE_BIT
;
175 ViewState::UpdateServerFontState(BPrivate::PortLink
&link
)
177 link
.StartMessage(AS_VIEW_SET_FONT_STATE
);
178 link
.Attach
<uint16
>(font_flags
);
181 if (font_flags
& B_FONT_FAMILY_AND_STYLE
)
182 link
.Attach
<uint32
>(font
.FamilyAndStyle());
184 if (font_flags
& B_FONT_SIZE
)
185 link
.Attach
<float>(font
.Size());
187 if (font_flags
& B_FONT_SHEAR
)
188 link
.Attach
<float>(font
.Shear());
190 if (font_flags
& B_FONT_ROTATION
)
191 link
.Attach
<float>(font
.Rotation());
193 if (font_flags
& B_FONT_FALSE_BOLD_WIDTH
)
194 link
.Attach
<float>(font
.FalseBoldWidth());
196 if (font_flags
& B_FONT_SPACING
)
197 link
.Attach
<uint8
>(font
.Spacing());
199 if (font_flags
& B_FONT_ENCODING
)
200 link
.Attach
<uint8
>(font
.Encoding());
202 if (font_flags
& B_FONT_FACE
)
203 link
.Attach
<uint16
>(font
.Face());
205 if (font_flags
& B_FONT_FLAGS
)
206 link
.Attach
<uint32
>(font
.Flags());
211 ViewState::UpdateServerState(BPrivate::PortLink
&link
)
213 UpdateServerFontState(link
);
215 link
.StartMessage(AS_VIEW_SET_STATE
);
217 ViewSetStateInfo info
;
218 info
.penLocation
= pen_location
;
219 info
.penSize
= pen_size
;
220 info
.highColor
= high_color
;
221 info
.lowColor
= low_color
;
222 info
.pattern
= pattern
;
223 info
.drawingMode
= drawing_mode
;
224 info
.origin
= origin
;
226 info
.transform
= transform
;
227 info
.lineJoin
= line_join
;
228 info
.lineCap
= line_cap
;
229 info
.miterLimit
= miter_limit
;
230 info
.fillRule
= fill_rule
;
231 info
.alphaSourceMode
= alpha_source_mode
;
232 info
.alphaFunctionMode
= alpha_function_mode
;
233 info
.fontAntialiasing
= font_aliasing
;
234 link
.Attach
<ViewSetStateInfo
>(info
);
236 // we send the 'local' clipping region... if we have one...
237 // TODO: Could be optimized, but is low prio, since most views won't
238 // have a custom clipping region.
239 if (clipping_region_used
) {
240 int32 count
= clipping_region
.CountRects();
241 link
.Attach
<int32
>(count
);
242 for (int32 i
= 0; i
< count
; i
++)
243 link
.Attach
<BRect
>(clipping_region
.RectAt(i
));
245 // no clipping region
246 link
.Attach
<int32
>(-1);
249 // Although we might have a 'local' clipping region, when we call
250 // BView::GetClippingRegion() we ask for the 'global' one and it
251 // is kept on server, so we must invalidate B_VIEW_CLIP_REGION_BIT flag
253 valid_flags
= ~B_VIEW_CLIP_REGION_BIT
;
258 ViewState::UpdateFrom(BPrivate::PortLink
&link
)
260 link
.StartMessage(AS_VIEW_GET_STATE
);
263 if (link
.FlushWithReply(code
) != B_OK
267 ViewGetStateInfo info
;
268 link
.Read
<ViewGetStateInfo
>(&info
);
270 // set view's font state
271 font_flags
= B_FONT_ALL
;
272 font
.SetFamilyAndStyle(info
.fontID
);
273 font
.SetSize(info
.fontSize
);
274 font
.SetShear(info
.fontShear
);
275 font
.SetRotation(info
.fontRotation
);
276 font
.SetFalseBoldWidth(info
.fontFalseBoldWidth
);
277 font
.SetSpacing(info
.fontSpacing
);
278 font
.SetEncoding(info
.fontEncoding
);
279 font
.SetFace(info
.fontFace
);
280 font
.SetFlags(info
.fontFlags
);
283 pen_location
= info
.viewStateInfo
.penLocation
;
284 pen_size
= info
.viewStateInfo
.penSize
;
285 high_color
= info
.viewStateInfo
.highColor
;
286 low_color
= info
.viewStateInfo
.lowColor
;
287 pattern
= info
.viewStateInfo
.pattern
;
288 drawing_mode
= info
.viewStateInfo
.drawingMode
;
289 origin
= info
.viewStateInfo
.origin
;
290 scale
= info
.viewStateInfo
.scale
;
291 transform
= info
.viewStateInfo
.transform
;
292 line_join
= info
.viewStateInfo
.lineJoin
;
293 line_cap
= info
.viewStateInfo
.lineCap
;
294 miter_limit
= info
.viewStateInfo
.miterLimit
;
295 fill_rule
= info
.viewStateInfo
.fillRule
;
296 alpha_source_mode
= info
.viewStateInfo
.alphaSourceMode
;
297 alpha_function_mode
= info
.viewStateInfo
.alphaFunctionMode
;
298 font_aliasing
= info
.viewStateInfo
.fontAntialiasing
;
300 // read the user clipping
301 // (that's NOT the current View visible clipping but the additional
302 // user specified clipping!)
303 int32 clippingRectCount
;
304 link
.Read
<int32
>(&clippingRectCount
);
305 if (clippingRectCount
>= 0) {
306 clipping_region
.MakeEmpty();
307 for (int32 i
= 0; i
< clippingRectCount
; i
++) {
309 link
.Read
<BRect
>(&rect
);
310 clipping_region
.Include(rect
);
313 // no user clipping used
314 clipping_region_used
= false;
317 valid_flags
= ~B_VIEW_CLIP_REGION_BIT
;
320 } // namespace BPrivate
326 // archiving constants
328 const char* const kSizesField
= "BView:sizes";
329 // kSizesField = {min, max, pref}
330 const char* const kAlignmentField
= "BView:alignment";
331 const char* const kLayoutField
= "BView:layout";
335 struct BView::LayoutData
{
342 fLayoutInvalidationDisabled(0),
344 fLayoutContext(NULL
),
345 fLayoutItems(5, false),
346 fLayoutValid(true), // TODO: Rethink these initial values!
347 fMinMaxValid(true), //
348 fLayoutInProgress(false),
354 AddDataToArchive(BMessage
* archive
)
356 status_t err
= archive
->AddSize(kSizesField
, fMinSize
);
359 err
= archive
->AddSize(kSizesField
, fMaxSize
);
362 err
= archive
->AddSize(kSizesField
, fPreferredSize
);
365 err
= archive
->AddAlignment(kAlignmentField
, fAlignment
);
371 PopulateFromArchive(BMessage
* archive
)
373 archive
->FindSize(kSizesField
, 0, &fMinSize
);
374 archive
->FindSize(kSizesField
, 1, &fMaxSize
);
375 archive
->FindSize(kSizesField
, 2, &fPreferredSize
);
376 archive
->FindAlignment(kAlignmentField
, &fAlignment
);
381 BSize fPreferredSize
;
382 BAlignment fAlignment
;
383 int fLayoutInvalidationDisabled
;
385 BLayoutContext
* fLayoutContext
;
386 BObjectList
<BLayoutItem
> fLayoutItems
;
389 bool fLayoutInProgress
;
394 BView::BView(const char* name
, uint32 flags
, BLayout
* layout
)
398 _InitData(BRect(0, 0, 0, 0), name
, B_FOLLOW_NONE
,
399 flags
| B_SUPPORTS_LAYOUT
);
404 BView::BView(BRect frame
, const char* name
, uint32 resizingMode
, uint32 flags
)
408 _InitData(frame
, name
, resizingMode
, flags
);
412 BView::BView(BMessage
* archive
)
414 BHandler(BUnarchiver::PrepareArchive(archive
))
416 BUnarchiver
unarchiver(archive
);
418 debugger("BView cannot be constructed from a NULL archive.");
421 archive
->FindRect("_frame", &frame
);
424 if (archive
->FindInt32("_resize_mode", (int32
*)&resizingMode
) != B_OK
)
428 if (archive
->FindInt32("_flags", (int32
*)&flags
) != B_OK
)
431 _InitData(frame
, Name(), resizingMode
, flags
);
435 if (archive
->FindString("_fname", 0, (const char**)&family
) == B_OK
436 && archive
->FindString("_fname", 1, (const char**)&style
) == B_OK
) {
438 font
.SetFamilyAndStyle(family
, style
);
441 if (archive
->FindFloat("_fflt", 0, &size
) == B_OK
)
445 if (archive
->FindFloat("_fflt", 1, &shear
) == B_OK
446 && shear
>= 45.0 && shear
<= 135.0)
447 font
.SetShear(shear
);
450 if (archive
->FindFloat("_fflt", 2, &rotation
) == B_OK
451 && rotation
>=0 && rotation
<= 360)
452 font
.SetRotation(rotation
);
454 SetFont(&font
, B_FONT_FAMILY_AND_STYLE
| B_FONT_SIZE
455 | B_FONT_SHEAR
| B_FONT_ROTATION
);
459 if (archive
->FindInt32("_color", 0, &color
) == B_OK
)
460 SetHighColor(get_rgb_color(color
));
461 if (archive
->FindInt32("_color", 1, &color
) == B_OK
)
462 SetLowColor(get_rgb_color(color
));
463 if (archive
->FindInt32("_color", 2, &color
) == B_OK
)
464 SetViewColor(get_rgb_color(color
));
468 if (archive
->FindInt32("_evmask", 0, (int32
*)&evMask
) == B_OK
469 && archive
->FindInt32("_evmask", 1, (int32
*)&options
) == B_OK
)
470 SetEventMask(evMask
, options
);
473 if (archive
->FindPoint("_origin", &origin
) == B_OK
)
477 if (archive
->FindFloat("_scale", &scale
) == B_OK
)
480 BAffineTransform transform
;
481 if (archive
->FindFlat("_transform", &transform
) == B_OK
)
482 SetTransform(transform
);
485 if (archive
->FindFloat("_psize", &penSize
) == B_OK
)
489 if (archive
->FindPoint("_ploc", &penLocation
) == B_OK
)
490 MovePenTo(penLocation
);
495 if (archive
->FindInt16("_lmcapjoin", 0, &lineCap
) == B_OK
496 && archive
->FindInt16("_lmcapjoin", 1, &lineJoin
) == B_OK
497 && archive
->FindFloat("_lmmiter", &lineMiter
) == B_OK
)
498 SetLineMode((cap_mode
)lineCap
, (join_mode
)lineJoin
, lineMiter
);
501 if (archive
->FindInt16("_fillrule", &fillRule
) == B_OK
)
502 SetFillRule(fillRule
);
506 if (archive
->FindInt16("_blend", 0, &alphaBlend
) == B_OK
507 && archive
->FindInt16("_blend", 1, &modeBlend
) == B_OK
)
508 SetBlendingMode( (source_alpha
)alphaBlend
, (alpha_function
)modeBlend
);
511 if (archive
->FindInt32("_dmod", (int32
*)&drawingMode
) == B_OK
)
512 SetDrawingMode((drawing_mode
)drawingMode
);
514 fLayoutData
->PopulateFromArchive(archive
);
516 if (archive
->FindInt16("_show", &fShowLevel
) != B_OK
)
519 if (BUnarchiver::IsArchiveManaged(archive
)) {
521 while (unarchiver
.EnsureUnarchived("_views", i
++) == B_OK
)
523 unarchiver
.EnsureUnarchived(kLayoutField
);
527 for (int32 i
= 0; archive
->FindMessage("_views", i
, &msg
) == B_OK
;
529 BArchivable
* object
= instantiate_object(&msg
);
530 if (BView
* child
= dynamic_cast<BView
*>(object
))
538 BView::Instantiate(BMessage
* data
)
540 if (!validate_instantiation(data
, "BView"))
543 return new(std::nothrow
) BView(data
);
548 BView::Archive(BMessage
* data
, bool deep
) const
550 BArchiver
archiver(data
);
551 status_t ret
= BHandler::Archive(data
, deep
);
556 if ((fState
->archiving_flags
& B_VIEW_FRAME_BIT
) != 0)
557 ret
= data
->AddRect("_frame", Bounds().OffsetToCopy(fParentOffset
));
560 ret
= data
->AddInt32("_resize_mode", ResizingMode());
563 ret
= data
->AddInt32("_flags", Flags());
565 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_EVENT_MASK_BIT
) != 0) {
566 ret
= data
->AddInt32("_evmask", fEventMask
);
568 ret
= data
->AddInt32("_evmask", fEventOptions
);
571 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_FONT_BIT
) != 0) {
577 font
.GetFamilyAndStyle(&family
, &style
);
578 ret
= data
->AddString("_fname", family
);
580 ret
= data
->AddString("_fname", style
);
582 ret
= data
->AddFloat("_fflt", font
.Size());
584 ret
= data
->AddFloat("_fflt", font
.Shear());
586 ret
= data
->AddFloat("_fflt", font
.Rotation());
591 ret
= data
->AddInt32("_color", get_uint32_color(HighColor()));
593 ret
= data
->AddInt32("_color", get_uint32_color(LowColor()));
595 ret
= data
->AddInt32("_color", get_uint32_color(ViewColor()));
597 // NOTE: we do not use this flag any more
599 // ret = data->AddInt32("_dbuf", 1);
602 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_ORIGIN_BIT
) != 0)
603 ret
= data
->AddPoint("_origin", Origin());
605 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_SCALE_BIT
) != 0)
606 ret
= data
->AddFloat("_scale", Scale());
608 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_TRANSFORM_BIT
) != 0) {
609 BAffineTransform transform
= Transform();
610 ret
= data
->AddFlat("_transform", &transform
);
613 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_PEN_SIZE_BIT
) != 0)
614 ret
= data
->AddFloat("_psize", PenSize());
616 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_PEN_LOCATION_BIT
) != 0)
617 ret
= data
->AddPoint("_ploc", PenLocation());
619 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_LINE_MODES_BIT
) != 0) {
620 ret
= data
->AddInt16("_lmcapjoin", (int16
)LineCapMode());
622 ret
= data
->AddInt16("_lmcapjoin", (int16
)LineJoinMode());
624 ret
= data
->AddFloat("_lmmiter", LineMiterLimit());
627 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_FILL_RULE_BIT
) != 0)
628 ret
= data
->AddInt16("_fillrule", (int16
)FillRule());
630 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_BLENDING_BIT
) != 0) {
631 source_alpha alphaSourceMode
;
632 alpha_function alphaFunctionMode
;
633 GetBlendingMode(&alphaSourceMode
, &alphaFunctionMode
);
635 ret
= data
->AddInt16("_blend", (int16
)alphaSourceMode
);
637 ret
= data
->AddInt16("_blend", (int16
)alphaFunctionMode
);
640 if (ret
== B_OK
&& (fState
->archiving_flags
& B_VIEW_DRAWING_MODE_BIT
) != 0)
641 ret
= data
->AddInt32("_dmod", DrawingMode());
644 ret
= fLayoutData
->AddDataToArchive(data
);
647 ret
= data
->AddInt16("_show", fShowLevel
);
649 if (deep
&& ret
== B_OK
) {
650 for (BView
* child
= fFirstChild
; child
!= NULL
&& ret
== B_OK
;
651 child
= child
->fNextSibling
)
652 ret
= archiver
.AddArchivable("_views", child
, deep
);
655 ret
= archiver
.AddArchivable(kLayoutField
, GetLayout(), deep
);
658 return archiver
.Finish(ret
);
663 BView::AllUnarchived(const BMessage
* from
)
665 BUnarchiver
unarchiver(from
);
669 from
->GetInfo("_views", NULL
, &count
);
671 for (int32 i
= 0; err
== B_OK
&& i
< count
; i
++) {
673 err
= unarchiver
.FindObject
<BView
>("_views", i
, child
);
675 err
= _AddChild(child
, NULL
) ? B_OK
: B_ERROR
;
679 BLayout
*& layout
= fLayoutData
->fLayout
;
680 err
= unarchiver
.FindObject(kLayoutField
, layout
);
681 if (err
== B_OK
&& layout
) {
682 fFlags
|= B_SUPPORTS_LAYOUT
;
683 fLayoutData
->fLayout
->SetOwner(this);
692 BView::AllArchived(BMessage
* into
) const
694 return BHandler::AllArchived(into
);
700 STRACE(("BView(%s)::~BView()\n", this->Name()));
702 if (fOwner
!= NULL
) {
703 debugger("Trying to delete a view that belongs to a window. "
704 "Call RemoveSelf first.");
707 // we also delete all our children
709 BView
* child
= fFirstChild
;
711 BView
* nextChild
= child
->fNextSibling
;
718 _RemoveLayoutItemsFromLayout(true);
724 if (fToolTip
!= NULL
)
725 fToolTip
->ReleaseReference();
727 if (fVerScroller
!= NULL
)
728 fVerScroller
->SetTarget((BView
*)NULL
);
729 if (fHorScroller
!= NULL
)
730 fHorScroller
->SetTarget((BView
*)NULL
);
740 BView::Bounds() const
745 return fState
->print_rect
;
752 BView::_ConvertToParent(BPoint
* point
, bool checkLock
) const
760 // - our scrolling offset
761 // + our bounds location within the parent
762 point
->x
+= -fBounds
.left
+ fParentOffset
.x
;
763 point
->y
+= -fBounds
.top
+ fParentOffset
.y
;
768 BView::ConvertToParent(BPoint
* point
) const
770 _ConvertToParent(point
, true);
775 BView::ConvertToParent(BPoint point
) const
777 ConvertToParent(&point
);
784 BView::_ConvertFromParent(BPoint
* point
, bool checkLock
) const
792 // - our bounds location within the parent
793 // + our scrolling offset
794 point
->x
+= -fParentOffset
.x
+ fBounds
.left
;
795 point
->y
+= -fParentOffset
.y
+ fBounds
.top
;
800 BView::ConvertFromParent(BPoint
* point
) const
802 _ConvertFromParent(point
, true);
807 BView::ConvertFromParent(BPoint point
) const
809 ConvertFromParent(&point
);
816 BView::ConvertToParent(BRect
* rect
) const
823 // - our scrolling offset
824 // + our bounds location within the parent
825 rect
->OffsetBy(-fBounds
.left
+ fParentOffset
.x
,
826 -fBounds
.top
+ fParentOffset
.y
);
831 BView::ConvertToParent(BRect rect
) const
833 ConvertToParent(&rect
);
840 BView::ConvertFromParent(BRect
* rect
) const
847 // - our bounds location within the parent
848 // + our scrolling offset
849 rect
->OffsetBy(-fParentOffset
.x
+ fBounds
.left
,
850 -fParentOffset
.y
+ fBounds
.top
);
855 BView::ConvertFromParent(BRect rect
) const
857 ConvertFromParent(&rect
);
864 BView::_ConvertToScreen(BPoint
* point
, bool checkLock
) const
868 fOwner
->ConvertToScreen(point
);
876 _ConvertToParent(point
, false);
877 fParent
->_ConvertToScreen(point
, false);
882 BView::ConvertToScreen(BPoint
* point
) const
884 _ConvertToScreen(point
, true);
889 BView::ConvertToScreen(BPoint point
) const
891 ConvertToScreen(&point
);
898 BView::_ConvertFromScreen(BPoint
* point
, bool checkLock
) const
902 fOwner
->ConvertFromScreen(point
);
910 _ConvertFromParent(point
, false);
911 fParent
->_ConvertFromScreen(point
, false);
916 BView::ConvertFromScreen(BPoint
* point
) const
918 _ConvertFromScreen(point
, true);
923 BView::ConvertFromScreen(BPoint point
) const
925 ConvertFromScreen(&point
);
932 BView::ConvertToScreen(BRect
* rect
) const
934 BPoint
offset(0.0, 0.0);
935 ConvertToScreen(&offset
);
936 rect
->OffsetBy(offset
);
941 BView::ConvertToScreen(BRect rect
) const
943 ConvertToScreen(&rect
);
950 BView::ConvertFromScreen(BRect
* rect
) const
952 BPoint
offset(0.0, 0.0);
953 ConvertFromScreen(&offset
);
954 rect
->OffsetBy(offset
);
959 BView::ConvertFromScreen(BRect rect
) const
961 ConvertFromScreen(&rect
);
971 return fFlags
& ~_RESIZE_MASK_
;
976 BView::SetFlags(uint32 flags
)
978 if (Flags() == flags
)
982 if (flags
& B_PULSE_NEEDED
) {
984 if (fOwner
->fPulseRunner
== NULL
)
985 fOwner
->SetPulseRate(fOwner
->PulseRate());
988 uint32 changesFlags
= flags
^ fFlags
;
989 if (changesFlags
& (B_WILL_DRAW
| B_FULL_UPDATE_ON_RESIZE
990 | B_FRAME_EVENTS
| B_SUBPIXEL_PRECISE
)) {
991 _CheckLockAndSwitchCurrent();
993 fOwner
->fLink
->StartMessage(AS_VIEW_SET_FLAGS
);
994 fOwner
->fLink
->Attach
<uint32
>(flags
);
995 fOwner
->fLink
->Flush();
1000 fFlags is a unsigned long (32 bits)
1001 * bits 1-16 are used for BView's flags
1002 * bits 17-32 are used for BView' resize mask
1003 * _RESIZE_MASK_ is used for that. Look into View.h to see how
1006 fFlags
= (flags
& ~_RESIZE_MASK_
) | (fFlags
& _RESIZE_MASK_
);
1008 fState
->archiving_flags
|= B_VIEW_FLAGS_BIT
;
1013 BView::Frame() const
1015 return Bounds().OffsetToCopy(fParentOffset
.x
, fParentOffset
.y
);
1022 if (fOwner
&& fShowLevel
== 0) {
1023 _CheckLockAndSwitchCurrent();
1024 fOwner
->fLink
->StartMessage(AS_VIEW_HIDE
);
1025 fOwner
->fLink
->Flush();
1029 if (fShowLevel
== 1)
1030 _InvalidateParentLayout();
1038 if (fOwner
&& fShowLevel
== 0) {
1039 _CheckLockAndSwitchCurrent();
1040 fOwner
->fLink
->StartMessage(AS_VIEW_SHOW
);
1041 fOwner
->fLink
->Flush();
1044 if (fShowLevel
== 0)
1045 _InvalidateParentLayout();
1050 BView::IsFocus() const
1054 return fOwner
->CurrentFocus() == this;
1061 BView::IsHidden(const BView
* lookingFrom
) const
1066 // may we be egocentric?
1067 if (lookingFrom
== this)
1070 // we have the same visibility state as our
1071 // parent, if there is one
1073 return fParent
->IsHidden(lookingFrom
);
1075 // if we're the top view, and we're interested
1076 // in the "global" view, we're inheriting the
1077 // state of the window's visibility
1078 if (fOwner
&& lookingFrom
== NULL
)
1079 return fOwner
->IsHidden();
1086 BView::IsHidden() const
1088 return IsHidden(NULL
);
1093 BView::IsPrinting() const
1100 BView::LeftTop() const
1102 return Bounds().LeftTop();
1107 BView::SetResizingMode(uint32 mode
)
1110 _CheckLockAndSwitchCurrent();
1112 fOwner
->fLink
->StartMessage(AS_VIEW_RESIZE_MODE
);
1113 fOwner
->fLink
->Attach
<uint32
>(mode
);
1116 // look at SetFlags() for more info on the below line
1117 fFlags
= (fFlags
& ~_RESIZE_MASK_
) | (mode
& _RESIZE_MASK_
);
1122 BView::ResizingMode() const
1124 return fFlags
& _RESIZE_MASK_
;
1129 BView::SetViewCursor(const BCursor
* cursor
, bool sync
)
1131 if (cursor
== NULL
|| fOwner
== NULL
)
1136 ViewSetViewCursorInfo info
;
1137 info
.cursorToken
= cursor
->fServerToken
;
1138 info
.viewToken
= _get_object_token_(this);
1141 BPrivate::AppServerLink link
;
1142 link
.StartMessage(AS_SET_VIEW_CURSOR
);
1143 link
.Attach
<ViewSetViewCursorInfo
>(info
);
1146 // Make sure the server has processed the message.
1148 link
.FlushWithReply(code
);
1154 BView::Flush() const
1171 BView::Window() const
1177 // #pragma mark - Hook Functions
1181 BView::AttachedToWindow()
1184 STRACE(("\tHOOK: BView(%s)::AttachedToWindow()\n", Name()));
1189 BView::AllAttached()
1192 STRACE(("\tHOOK: BView(%s)::AllAttached()\n", Name()));
1197 BView::DetachedFromWindow()
1200 STRACE(("\tHOOK: BView(%s)::DetachedFromWindow()\n", Name()));
1205 BView::AllDetached()
1208 STRACE(("\tHOOK: BView(%s)::AllDetached()\n", Name()));
1213 BView::Draw(BRect updateRect
)
1216 STRACE(("\tHOOK: BView(%s)::Draw()\n", Name()));
1221 BView::DrawAfterChildren(BRect updateRect
)
1224 STRACE(("\tHOOK: BView(%s)::DrawAfterChildren()\n", Name()));
1229 BView::FrameMoved(BPoint newPosition
)
1232 STRACE(("\tHOOK: BView(%s)::FrameMoved()\n", Name()));
1237 BView::FrameResized(float newWidth
, float newHeight
)
1240 STRACE(("\tHOOK: BView(%s)::FrameResized()\n", Name()));
1245 BView::GetPreferredSize(float* _width
, float* _height
)
1247 STRACE(("\tHOOK: BView(%s)::GetPreferredSize()\n", Name()));
1250 *_width
= fBounds
.Width();
1251 if (_height
!= NULL
)
1252 *_height
= fBounds
.Height();
1257 BView::ResizeToPreferred()
1259 STRACE(("\tHOOK: BView(%s)::ResizeToPreferred()\n", Name()));
1263 GetPreferredSize(&width
, &height
);
1265 ResizeTo(width
, height
);
1270 BView::KeyDown(const char* bytes
, int32 numBytes
)
1273 STRACE(("\tHOOK: BView(%s)::KeyDown()\n", Name()));
1276 Window()->_KeyboardNavigation();
1281 BView::KeyUp(const char* bytes
, int32 numBytes
)
1284 STRACE(("\tHOOK: BView(%s)::KeyUp()\n", Name()));
1289 BView::MouseDown(BPoint where
)
1292 STRACE(("\tHOOK: BView(%s)::MouseDown()\n", Name()));
1297 BView::MouseUp(BPoint where
)
1300 STRACE(("\tHOOK: BView(%s)::MouseUp()\n", Name()));
1305 BView::MouseMoved(BPoint where
, uint32 code
, const BMessage
* dragMessage
)
1308 STRACE(("\tHOOK: BView(%s)::MouseMoved()\n", Name()));
1316 STRACE(("\tHOOK: BView(%s)::Pulse()\n", Name()));
1321 BView::TargetedByScrollView(BScrollView
* scroll_view
)
1324 STRACE(("\tHOOK: BView(%s)::TargetedByScrollView()\n", Name()));
1329 BView::WindowActivated(bool active
)
1332 STRACE(("\tHOOK: BView(%s)::WindowActivated()\n", Name()));
1336 // #pragma mark - Input Functions
1340 BView::BeginRectTracking(BRect startRect
, uint32 style
)
1342 if (_CheckOwnerLockAndSwitchCurrent()) {
1343 fOwner
->fLink
->StartMessage(AS_VIEW_BEGIN_RECT_TRACK
);
1344 fOwner
->fLink
->Attach
<BRect
>(startRect
);
1345 fOwner
->fLink
->Attach
<uint32
>(style
);
1346 fOwner
->fLink
->Flush();
1352 BView::EndRectTracking()
1354 if (_CheckOwnerLockAndSwitchCurrent()) {
1355 fOwner
->fLink
->StartMessage(AS_VIEW_END_RECT_TRACK
);
1356 fOwner
->fLink
->Flush();
1362 BView::DragMessage(BMessage
* message
, BRect dragRect
, BHandler
* replyTo
)
1369 // calculate the offset
1372 BMessage
* current
= fOwner
->CurrentMessage();
1373 if (!current
|| current
->FindPoint("be:view_where", &offset
) != B_OK
)
1374 GetMouse(&offset
, &buttons
, false);
1375 offset
-= dragRect
.LeftTop();
1377 if (!dragRect
.IsValid()) {
1378 DragMessage(message
, NULL
, B_OP_BLEND
, offset
, replyTo
);
1382 // TODO: that's not really what should happen - the app_server should take
1383 // the chance *NOT* to need to drag a whole bitmap around but just a frame.
1385 // create a drag bitmap for the rect
1386 BBitmap
* bitmap
= new(std::nothrow
) BBitmap(dragRect
, B_RGBA32
);
1390 uint32
* bits
= (uint32
*)bitmap
->Bits();
1391 uint32 bytesPerRow
= bitmap
->BytesPerRow();
1392 uint32 width
= dragRect
.IntegerWidth() + 1;
1393 uint32 height
= dragRect
.IntegerHeight() + 1;
1394 uint32 lastRow
= (height
- 1) * width
;
1396 memset(bits
, 0x00, height
* bytesPerRow
);
1399 for (uint32 i
= 0; i
< width
; i
+= 2)
1400 bits
[i
] = 0xff000000;
1403 for (uint32 i
= (height
% 2 == 0 ? 1 : 0); i
< width
; i
+= 2)
1404 bits
[lastRow
+ i
] = 0xff000000;
1407 for (uint32 i
= 0; i
< lastRow
; i
+= width
* 2)
1408 bits
[i
] = 0xff000000;
1411 for (uint32 i
= (width
% 2 == 0 ? width
: 0); i
< lastRow
; i
+= width
* 2)
1412 bits
[width
- 1 + i
] = 0xff000000;
1414 DragMessage(message
, bitmap
, B_OP_BLEND
, offset
, replyTo
);
1419 BView::DragMessage(BMessage
* message
, BBitmap
* image
, BPoint offset
,
1422 DragMessage(message
, image
, B_OP_COPY
, offset
, replyTo
);
1427 BView::DragMessage(BMessage
* message
, BBitmap
* image
,
1428 drawing_mode dragMode
, BPoint offset
, BHandler
* replyTo
)
1430 if (message
== NULL
)
1433 if (image
== NULL
) {
1434 // TODO: workaround for drags without a bitmap - should not be necessary if
1435 // we move the rectangle dragging into the app_server
1436 image
= new(std::nothrow
) BBitmap(BRect(0, 0, 0, 0), B_RGBA32
);
1441 if (replyTo
== NULL
)
1444 if (replyTo
->Looper() == NULL
)
1445 debugger("DragMessage: warning - the Handler needs a looper");
1449 if (!message
->HasInt32("buttons")) {
1450 BMessage
* msg
= fOwner
->CurrentMessage();
1454 || msg
->FindInt32("buttons", (int32
*)&buttons
) != B_OK
) {
1456 GetMouse(&point
, &buttons
, false);
1459 message
->AddInt32("buttons", buttons
);
1462 BMessage::Private
privateMessage(message
);
1463 privateMessage
.SetReply(BMessenger(replyTo
, replyTo
->Looper()));
1465 int32 bufferSize
= message
->FlattenedSize();
1466 char* buffer
= new(std::nothrow
) char[bufferSize
];
1467 if (buffer
!= NULL
) {
1468 message
->Flatten(buffer
, bufferSize
);
1470 fOwner
->fLink
->StartMessage(AS_VIEW_DRAG_IMAGE
);
1471 fOwner
->fLink
->Attach
<int32
>(image
->_ServerToken());
1472 fOwner
->fLink
->Attach
<int32
>((int32
)dragMode
);
1473 fOwner
->fLink
->Attach
<BPoint
>(offset
);
1474 fOwner
->fLink
->Attach
<int32
>(bufferSize
);
1475 fOwner
->fLink
->Attach(buffer
, bufferSize
);
1477 // we need to wait for the server
1478 // to actually process this message
1479 // before we can delete the bitmap
1481 fOwner
->fLink
->FlushWithReply(code
);
1485 fprintf(stderr
, "BView::DragMessage() - no memory to flatten drag "
1494 BView::GetMouse(BPoint
* _location
, uint32
* _buttons
, bool checkMessageQueue
)
1496 if (_location
== NULL
&& _buttons
== NULL
)
1499 _CheckOwnerLockAndSwitchCurrent();
1501 uint32 eventOptions
= fEventOptions
| fMouseEventOptions
;
1502 bool noHistory
= eventOptions
& B_NO_POINTER_HISTORY
;
1503 bool fullHistory
= eventOptions
& B_FULL_POINTER_HISTORY
;
1505 if (checkMessageQueue
&& !noHistory
) {
1506 Window()->UpdateIfNeeded();
1507 BMessageQueue
* queue
= Window()->MessageQueue();
1510 // Look out for mouse update messages
1513 for (int32 i
= 0; (message
= queue
->FindMessage(i
)) != NULL
; i
++) {
1514 switch (message
->what
) {
1519 if (!Window()->_StealMouseMessage(message
, deleteMessage
))
1522 if (!fullHistory
&& message
->what
== B_MOUSE_MOVED
) {
1523 // Check if the message is too old. Some applications
1524 // check the message queue in such a way that mouse
1525 // messages *must* pile up. This check makes them work
1526 // as intended, although these applications could simply
1527 // use the version of BView::GetMouse() that does not
1528 // check the history. Also note that it isn't a problem
1529 // to delete the message in case there is not a newer
1530 // one. If we don't find a message in the queue, we will
1531 // just fall back to asking the app_sever directly. So
1532 // the imposed delay will not be a problem on slower
1533 // computers. This check also prevents another problem,
1534 // when the message that we use is *not* removed from
1535 // the queue. Subsequent calls to GetMouse() would find
1536 // this message over and over!
1537 bigtime_t eventTime
;
1538 if (message
->FindInt64("when", &eventTime
) == B_OK
1539 && system_time() - eventTime
> 10000) {
1540 // just discard the message
1546 message
->FindPoint("screen_where", _location
);
1547 message
->FindInt32("buttons", (int32
*)_buttons
);
1549 // we need to hold the queue lock until here, because
1550 // the message might still be used for something else
1552 if (_location
!= NULL
)
1553 ConvertFromScreen(_location
);
1564 // If no mouse update message has been found in the message queue,
1565 // we get the current mouse location and buttons from the app_server
1567 fOwner
->fLink
->StartMessage(AS_GET_MOUSE
);
1570 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
1574 fOwner
->fLink
->Read
<BPoint
>(&location
);
1575 fOwner
->fLink
->Read
<uint32
>(&buttons
);
1576 // TODO: ServerWindow replies with an int32 here
1578 ConvertFromScreen(&location
);
1579 // TODO: in beos R5, location is already converted to the view
1580 // local coordinate system, so if an app checks the window message
1581 // queue by itself, it might not find what it expects.
1582 // NOTE: the fact that we have mouse coords in screen space in our
1583 // queue avoids the problem that messages already in the queue will
1584 // be outdated as soon as a window or even the view moves. The
1585 // second situation being quite common actually, also with regards
1586 // to scrolling. An app reading these messages would have to know
1587 // the locations of the window and view for each message...
1588 // otherwise it is potentially broken anyways.
1589 if (_location
!= NULL
)
1590 *_location
= location
;
1591 if (_buttons
!= NULL
)
1592 *_buttons
= buttons
;
1594 if (_location
!= NULL
)
1595 _location
->Set(0, 0);
1596 if (_buttons
!= NULL
)
1603 BView::MakeFocus(bool focus
)
1608 // TODO: If this view has focus and focus == false,
1609 // will there really be no other view with focus? No
1610 // cycling to the next one?
1611 BView
* focusView
= fOwner
->CurrentFocus();
1613 // Unfocus a previous focus view
1614 if (focusView
!= NULL
&& focusView
!= this)
1615 focusView
->MakeFocus(false);
1617 // if we want to make this view the current focus view
1618 fOwner
->_SetFocus(this, true);
1620 // we want to unfocus this view, but only if it actually has focus
1621 if (focusView
== this)
1622 fOwner
->_SetFocus(NULL
, true);
1628 BView::ScrollBar(orientation direction
) const
1630 switch (direction
) {
1632 return fVerScroller
;
1635 return fHorScroller
;
1644 BView::ScrollBy(float deltaX
, float deltaY
)
1646 ScrollTo(BPoint(fBounds
.left
+ deltaX
, fBounds
.top
+ deltaY
));
1651 BView::ScrollTo(BPoint where
)
1653 // scrolling by fractional values is not supported
1654 where
.x
= roundf(where
.x
);
1655 where
.y
= roundf(where
.y
);
1657 // no reason to process this further if no scroll is intended.
1658 if (where
.x
== fBounds
.left
&& where
.y
== fBounds
.top
)
1661 // make sure scrolling is within valid bounds
1664 fHorScroller
->GetRange(&min
, &max
);
1668 else if (where
.x
> max
)
1673 fVerScroller
->GetRange(&min
, &max
);
1677 else if (where
.y
> max
)
1681 _CheckLockAndSwitchCurrent();
1683 float xDiff
= where
.x
- fBounds
.left
;
1684 float yDiff
= where
.y
- fBounds
.top
;
1686 // if we're attached to a window tell app_server about this change
1688 fOwner
->fLink
->StartMessage(AS_VIEW_SCROLL
);
1689 fOwner
->fLink
->Attach
<float>(xDiff
);
1690 fOwner
->fLink
->Attach
<float>(yDiff
);
1692 fOwner
->fLink
->Flush();
1694 // fState->valid_flags &= ~B_VIEW_FRAME_BIT;
1697 // we modify our bounds rectangle by deltaX/deltaY coord units hor/ver.
1698 fBounds
.OffsetTo(where
.x
, where
.y
);
1700 // then set the new values of the scrollbars
1701 if (fHorScroller
&& xDiff
!= 0.0)
1702 fHorScroller
->SetValue(fBounds
.left
);
1703 if (fVerScroller
&& yDiff
!= 0.0)
1704 fVerScroller
->SetValue(fBounds
.top
);
1710 BView::SetEventMask(uint32 mask
, uint32 options
)
1712 if (fEventMask
== mask
&& fEventOptions
== options
)
1715 // don't change the mask if it's zero and we've got options
1716 if (mask
!= 0 || options
== 0)
1717 fEventMask
= mask
| (fEventMask
& 0xffff0000);
1718 fEventOptions
= options
;
1720 fState
->archiving_flags
|= B_VIEW_EVENT_MASK_BIT
;
1723 _CheckLockAndSwitchCurrent();
1725 fOwner
->fLink
->StartMessage(AS_VIEW_SET_EVENT_MASK
);
1726 fOwner
->fLink
->Attach
<uint32
>(mask
);
1727 fOwner
->fLink
->Attach
<uint32
>(options
);
1728 fOwner
->fLink
->Flush();
1743 BView::SetMouseEventMask(uint32 mask
, uint32 options
)
1745 // Just don't do anything if the view is not yet attached
1746 // or we were called outside of BView::MouseDown()
1748 && fOwner
->CurrentMessage() != NULL
1749 && fOwner
->CurrentMessage()->what
== B_MOUSE_DOWN
) {
1750 _CheckLockAndSwitchCurrent();
1751 fMouseEventOptions
= options
;
1753 fOwner
->fLink
->StartMessage(AS_VIEW_SET_MOUSE_EVENT_MASK
);
1754 fOwner
->fLink
->Attach
<uint32
>(mask
);
1755 fOwner
->fLink
->Attach
<uint32
>(options
);
1756 fOwner
->fLink
->Flush();
1764 // #pragma mark - Graphic State Functions
1770 _CheckOwnerLockAndSwitchCurrent();
1772 fOwner
->fLink
->StartMessage(AS_VIEW_PUSH_STATE
);
1774 // initialize origin, scale and transform, new states start "clean".
1775 fState
->valid_flags
|= B_VIEW_SCALE_BIT
| B_VIEW_ORIGIN_BIT
1776 | B_VIEW_TRANSFORM_BIT
;
1777 fState
->scale
= 1.0f
;
1778 fState
->origin
.Set(0, 0);
1779 fState
->transform
.Reset();
1786 _CheckOwnerLockAndSwitchCurrent();
1788 fOwner
->fLink
->StartMessage(AS_VIEW_POP_STATE
);
1789 _FlushIfNotInTransaction();
1791 // invalidate all flags (except those that are not part of pop/push)
1792 fState
->valid_flags
= B_VIEW_VIEW_COLOR_BIT
;
1797 BView::SetOrigin(BPoint where
)
1799 SetOrigin(where
.x
, where
.y
);
1804 BView::SetOrigin(float x
, float y
)
1806 if (fState
->IsValid(B_VIEW_ORIGIN_BIT
)
1807 && x
== fState
->origin
.x
&& y
== fState
->origin
.y
)
1810 fState
->origin
.x
= x
;
1811 fState
->origin
.y
= y
;
1813 if (_CheckOwnerLockAndSwitchCurrent()) {
1814 fOwner
->fLink
->StartMessage(AS_VIEW_SET_ORIGIN
);
1815 fOwner
->fLink
->Attach
<float>(x
);
1816 fOwner
->fLink
->Attach
<float>(y
);
1818 fState
->valid_flags
|= B_VIEW_ORIGIN_BIT
;
1821 // our local coord system origin has changed, so when archiving we'll add
1823 fState
->archiving_flags
|= B_VIEW_ORIGIN_BIT
;
1828 BView::Origin() const
1830 if (!fState
->IsValid(B_VIEW_ORIGIN_BIT
)) {
1831 // we don't keep graphics state information, therefor
1832 // we need to ask the server for the origin after PopState()
1833 _CheckOwnerLockAndSwitchCurrent();
1835 fOwner
->fLink
->StartMessage(AS_VIEW_GET_ORIGIN
);
1838 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
&& code
== B_OK
)
1839 fOwner
->fLink
->Read
<BPoint
>(&fState
->origin
);
1841 fState
->valid_flags
|= B_VIEW_ORIGIN_BIT
;
1844 return fState
->origin
;
1849 BView::SetScale(float scale
) const
1851 if (fState
->IsValid(B_VIEW_SCALE_BIT
) && scale
== fState
->scale
)
1855 _CheckLockAndSwitchCurrent();
1857 fOwner
->fLink
->StartMessage(AS_VIEW_SET_SCALE
);
1858 fOwner
->fLink
->Attach
<float>(scale
);
1860 fState
->valid_flags
|= B_VIEW_SCALE_BIT
;
1863 fState
->scale
= scale
;
1864 fState
->archiving_flags
|= B_VIEW_SCALE_BIT
;
1869 BView::Scale() const
1871 if (!fState
->IsValid(B_VIEW_SCALE_BIT
) && fOwner
) {
1872 _CheckLockAndSwitchCurrent();
1874 fOwner
->fLink
->StartMessage(AS_VIEW_GET_SCALE
);
1877 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
&& code
== B_OK
)
1878 fOwner
->fLink
->Read
<float>(&fState
->scale
);
1880 fState
->valid_flags
|= B_VIEW_SCALE_BIT
;
1883 return fState
->scale
;
1888 BView::SetTransform(BAffineTransform transform
)
1890 if (fState
->IsValid(B_VIEW_TRANSFORM_BIT
) && transform
== fState
->transform
)
1893 if (fOwner
!= NULL
) {
1894 _CheckLockAndSwitchCurrent();
1896 fOwner
->fLink
->StartMessage(AS_VIEW_SET_TRANSFORM
);
1897 fOwner
->fLink
->Attach
<BAffineTransform
>(transform
);
1899 fState
->valid_flags
|= B_VIEW_TRANSFORM_BIT
;
1902 fState
->transform
= transform
;
1903 fState
->archiving_flags
|= B_VIEW_TRANSFORM_BIT
;
1908 BView::Transform() const
1910 if (!fState
->IsValid(B_VIEW_TRANSFORM_BIT
) && fOwner
!= NULL
) {
1911 _CheckLockAndSwitchCurrent();
1913 fOwner
->fLink
->StartMessage(AS_VIEW_GET_TRANSFORM
);
1916 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
&& code
== B_OK
)
1917 fOwner
->fLink
->Read
<BAffineTransform
>(&fState
->transform
);
1919 fState
->valid_flags
|= B_VIEW_TRANSFORM_BIT
;
1922 return fState
->transform
;
1927 BView::SetLineMode(cap_mode lineCap
, join_mode lineJoin
, float miterLimit
)
1929 if (fState
->IsValid(B_VIEW_LINE_MODES_BIT
)
1930 && lineCap
== fState
->line_cap
&& lineJoin
== fState
->line_join
1931 && miterLimit
== fState
->miter_limit
)
1935 _CheckLockAndSwitchCurrent();
1937 ViewSetLineModeInfo info
;
1938 info
.lineJoin
= lineJoin
;
1939 info
.lineCap
= lineCap
;
1940 info
.miterLimit
= miterLimit
;
1942 fOwner
->fLink
->StartMessage(AS_VIEW_SET_LINE_MODE
);
1943 fOwner
->fLink
->Attach
<ViewSetLineModeInfo
>(info
);
1945 fState
->valid_flags
|= B_VIEW_LINE_MODES_BIT
;
1948 fState
->line_cap
= lineCap
;
1949 fState
->line_join
= lineJoin
;
1950 fState
->miter_limit
= miterLimit
;
1952 fState
->archiving_flags
|= B_VIEW_LINE_MODES_BIT
;
1957 BView::LineJoinMode() const
1959 // This will update the current state, if necessary
1960 if (!fState
->IsValid(B_VIEW_LINE_MODES_BIT
))
1963 return fState
->line_join
;
1968 BView::LineCapMode() const
1970 // This will update the current state, if necessary
1971 if (!fState
->IsValid(B_VIEW_LINE_MODES_BIT
))
1974 return fState
->line_cap
;
1979 BView::LineMiterLimit() const
1981 if (!fState
->IsValid(B_VIEW_LINE_MODES_BIT
) && fOwner
) {
1982 _CheckLockAndSwitchCurrent();
1984 fOwner
->fLink
->StartMessage(AS_VIEW_GET_LINE_MODE
);
1987 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
&& code
== B_OK
) {
1989 ViewSetLineModeInfo info
;
1990 fOwner
->fLink
->Read
<ViewSetLineModeInfo
>(&info
);
1992 fState
->line_cap
= info
.lineCap
;
1993 fState
->line_join
= info
.lineJoin
;
1994 fState
->miter_limit
= info
.miterLimit
;
1997 fState
->valid_flags
|= B_VIEW_LINE_MODES_BIT
;
2000 return fState
->miter_limit
;
2005 BView::SetFillRule(int32 fillRule
)
2007 if (fState
->IsValid(B_VIEW_FILL_RULE_BIT
) && fillRule
== fState
->fill_rule
)
2011 _CheckLockAndSwitchCurrent();
2013 fOwner
->fLink
->StartMessage(AS_VIEW_SET_FILL_RULE
);
2014 fOwner
->fLink
->Attach
<int32
>(fillRule
);
2016 fState
->valid_flags
|= B_VIEW_FILL_RULE_BIT
;
2019 fState
->fill_rule
= fillRule
;
2021 fState
->archiving_flags
|= B_VIEW_FILL_RULE_BIT
;
2026 BView::FillRule() const
2028 if (!fState
->IsValid(B_VIEW_FILL_RULE_BIT
) && fOwner
) {
2029 _CheckLockAndSwitchCurrent();
2031 fOwner
->fLink
->StartMessage(AS_VIEW_GET_FILL_RULE
);
2034 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
&& code
== B_OK
) {
2037 fOwner
->fLink
->Read
<int32
>(&fillRule
);
2039 fState
->fill_rule
= fillRule
;
2042 fState
->valid_flags
|= B_VIEW_FILL_RULE_BIT
;
2045 return fState
->fill_rule
;
2050 BView::SetDrawingMode(drawing_mode mode
)
2052 if (fState
->IsValid(B_VIEW_DRAWING_MODE_BIT
)
2053 && mode
== fState
->drawing_mode
)
2057 _CheckLockAndSwitchCurrent();
2059 fOwner
->fLink
->StartMessage(AS_VIEW_SET_DRAWING_MODE
);
2060 fOwner
->fLink
->Attach
<int8
>((int8
)mode
);
2062 fState
->valid_flags
|= B_VIEW_DRAWING_MODE_BIT
;
2065 fState
->drawing_mode
= mode
;
2066 fState
->archiving_flags
|= B_VIEW_DRAWING_MODE_BIT
;
2071 BView::DrawingMode() const
2073 if (!fState
->IsValid(B_VIEW_DRAWING_MODE_BIT
) && fOwner
) {
2074 _CheckLockAndSwitchCurrent();
2076 fOwner
->fLink
->StartMessage(AS_VIEW_GET_DRAWING_MODE
);
2079 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
2082 fOwner
->fLink
->Read
<int8
>(&drawingMode
);
2084 fState
->drawing_mode
= (drawing_mode
)drawingMode
;
2085 fState
->valid_flags
|= B_VIEW_DRAWING_MODE_BIT
;
2089 return fState
->drawing_mode
;
2094 BView::SetBlendingMode(source_alpha sourceAlpha
, alpha_function alphaFunction
)
2096 if (fState
->IsValid(B_VIEW_BLENDING_BIT
)
2097 && sourceAlpha
== fState
->alpha_source_mode
2098 && alphaFunction
== fState
->alpha_function_mode
)
2102 _CheckLockAndSwitchCurrent();
2104 ViewBlendingModeInfo info
;
2105 info
.sourceAlpha
= sourceAlpha
;
2106 info
.alphaFunction
= alphaFunction
;
2108 fOwner
->fLink
->StartMessage(AS_VIEW_SET_BLENDING_MODE
);
2109 fOwner
->fLink
->Attach
<ViewBlendingModeInfo
>(info
);
2111 fState
->valid_flags
|= B_VIEW_BLENDING_BIT
;
2114 fState
->alpha_source_mode
= sourceAlpha
;
2115 fState
->alpha_function_mode
= alphaFunction
;
2117 fState
->archiving_flags
|= B_VIEW_BLENDING_BIT
;
2122 BView::GetBlendingMode(source_alpha
* _sourceAlpha
,
2123 alpha_function
* _alphaFunction
) const
2125 if (!fState
->IsValid(B_VIEW_BLENDING_BIT
) && fOwner
) {
2126 _CheckLockAndSwitchCurrent();
2128 fOwner
->fLink
->StartMessage(AS_VIEW_GET_BLENDING_MODE
);
2131 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
&& code
== B_OK
) {
2132 ViewBlendingModeInfo info
;
2133 fOwner
->fLink
->Read
<ViewBlendingModeInfo
>(&info
);
2135 fState
->alpha_source_mode
= info
.sourceAlpha
;
2136 fState
->alpha_function_mode
= info
.alphaFunction
;
2138 fState
->valid_flags
|= B_VIEW_BLENDING_BIT
;
2143 *_sourceAlpha
= fState
->alpha_source_mode
;
2146 *_alphaFunction
= fState
->alpha_function_mode
;
2151 BView::MovePenTo(BPoint point
)
2153 MovePenTo(point
.x
, point
.y
);
2158 BView::MovePenTo(float x
, float y
)
2160 if (fState
->IsValid(B_VIEW_PEN_LOCATION_BIT
)
2161 && x
== fState
->pen_location
.x
&& y
== fState
->pen_location
.y
)
2165 _CheckLockAndSwitchCurrent();
2167 fOwner
->fLink
->StartMessage(AS_VIEW_SET_PEN_LOC
);
2168 fOwner
->fLink
->Attach
<BPoint
>(BPoint(x
, y
));
2170 fState
->valid_flags
|= B_VIEW_PEN_LOCATION_BIT
;
2173 fState
->pen_location
.x
= x
;
2174 fState
->pen_location
.y
= y
;
2176 fState
->archiving_flags
|= B_VIEW_PEN_LOCATION_BIT
;
2181 BView::MovePenBy(float x
, float y
)
2183 // this will update the pen location if necessary
2184 if (!fState
->IsValid(B_VIEW_PEN_LOCATION_BIT
))
2187 MovePenTo(fState
->pen_location
.x
+ x
, fState
->pen_location
.y
+ y
);
2192 BView::PenLocation() const
2194 if (!fState
->IsValid(B_VIEW_PEN_LOCATION_BIT
) && fOwner
) {
2195 _CheckLockAndSwitchCurrent();
2197 fOwner
->fLink
->StartMessage(AS_VIEW_GET_PEN_LOC
);
2200 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
2202 fOwner
->fLink
->Read
<BPoint
>(&fState
->pen_location
);
2204 fState
->valid_flags
|= B_VIEW_PEN_LOCATION_BIT
;
2208 return fState
->pen_location
;
2213 BView::SetPenSize(float size
)
2215 if (fState
->IsValid(B_VIEW_PEN_SIZE_BIT
) && size
== fState
->pen_size
)
2219 _CheckLockAndSwitchCurrent();
2221 fOwner
->fLink
->StartMessage(AS_VIEW_SET_PEN_SIZE
);
2222 fOwner
->fLink
->Attach
<float>(size
);
2224 fState
->valid_flags
|= B_VIEW_PEN_SIZE_BIT
;
2227 fState
->pen_size
= size
;
2228 fState
->archiving_flags
|= B_VIEW_PEN_SIZE_BIT
;
2233 BView::PenSize() const
2235 if (!fState
->IsValid(B_VIEW_PEN_SIZE_BIT
) && fOwner
) {
2236 _CheckLockAndSwitchCurrent();
2238 fOwner
->fLink
->StartMessage(AS_VIEW_GET_PEN_SIZE
);
2241 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
2243 fOwner
->fLink
->Read
<float>(&fState
->pen_size
);
2245 fState
->valid_flags
|= B_VIEW_PEN_SIZE_BIT
;
2249 return fState
->pen_size
;
2254 BView::SetHighColor(rgb_color color
)
2256 // are we up-to-date already?
2257 if (fState
->IsValid(B_VIEW_HIGH_COLOR_BIT
)
2258 && fState
->high_color
== color
)
2262 _CheckLockAndSwitchCurrent();
2264 fOwner
->fLink
->StartMessage(AS_VIEW_SET_HIGH_COLOR
);
2265 fOwner
->fLink
->Attach
<rgb_color
>(color
);
2267 fState
->valid_flags
|= B_VIEW_HIGH_COLOR_BIT
;
2270 fState
->high_color
= color
;
2272 fState
->archiving_flags
|= B_VIEW_HIGH_COLOR_BIT
;
2277 BView::HighColor() const
2279 if (!fState
->IsValid(B_VIEW_HIGH_COLOR_BIT
) && fOwner
) {
2280 _CheckLockAndSwitchCurrent();
2282 fOwner
->fLink
->StartMessage(AS_VIEW_GET_HIGH_COLOR
);
2285 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
2287 fOwner
->fLink
->Read
<rgb_color
>(&fState
->high_color
);
2289 fState
->valid_flags
|= B_VIEW_HIGH_COLOR_BIT
;
2293 return fState
->high_color
;
2298 BView::SetLowColor(rgb_color color
)
2300 if (fState
->IsValid(B_VIEW_LOW_COLOR_BIT
)
2301 && fState
->low_color
== color
)
2305 _CheckLockAndSwitchCurrent();
2307 fOwner
->fLink
->StartMessage(AS_VIEW_SET_LOW_COLOR
);
2308 fOwner
->fLink
->Attach
<rgb_color
>(color
);
2310 fState
->valid_flags
|= B_VIEW_LOW_COLOR_BIT
;
2313 fState
->low_color
= color
;
2315 fState
->archiving_flags
|= B_VIEW_LOW_COLOR_BIT
;
2320 BView::LowColor() const
2322 if (!fState
->IsValid(B_VIEW_LOW_COLOR_BIT
) && fOwner
) {
2323 _CheckLockAndSwitchCurrent();
2325 fOwner
->fLink
->StartMessage(AS_VIEW_GET_LOW_COLOR
);
2328 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
2330 fOwner
->fLink
->Read
<rgb_color
>(&fState
->low_color
);
2332 fState
->valid_flags
|= B_VIEW_LOW_COLOR_BIT
;
2336 return fState
->low_color
;
2341 BView::SetViewColor(rgb_color color
)
2343 if (fState
->IsValid(B_VIEW_VIEW_COLOR_BIT
) && fState
->view_color
== color
)
2347 _CheckLockAndSwitchCurrent();
2349 fOwner
->fLink
->StartMessage(AS_VIEW_SET_VIEW_COLOR
);
2350 fOwner
->fLink
->Attach
<rgb_color
>(color
);
2351 fOwner
->fLink
->Flush();
2353 fState
->valid_flags
|= B_VIEW_VIEW_COLOR_BIT
;
2356 fState
->view_color
= color
;
2358 fState
->archiving_flags
|= B_VIEW_VIEW_COLOR_BIT
;
2363 BView::ViewColor() const
2365 if (!fState
->IsValid(B_VIEW_VIEW_COLOR_BIT
) && fOwner
) {
2366 _CheckLockAndSwitchCurrent();
2368 fOwner
->fLink
->StartMessage(AS_VIEW_GET_VIEW_COLOR
);
2371 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
2373 fOwner
->fLink
->Read
<rgb_color
>(&fState
->view_color
);
2375 fState
->valid_flags
|= B_VIEW_VIEW_COLOR_BIT
;
2379 return fState
->view_color
;
2384 BView::ForceFontAliasing(bool enable
)
2386 if (fState
->IsValid(B_VIEW_FONT_ALIASING_BIT
)
2387 && enable
== fState
->font_aliasing
)
2391 _CheckLockAndSwitchCurrent();
2393 fOwner
->fLink
->StartMessage(AS_VIEW_PRINT_ALIASING
);
2394 fOwner
->fLink
->Attach
<bool>(enable
);
2396 fState
->valid_flags
|= B_VIEW_FONT_ALIASING_BIT
;
2399 fState
->font_aliasing
= enable
;
2400 fState
->archiving_flags
|= B_VIEW_FONT_ALIASING_BIT
;
2405 BView::SetFont(const BFont
* font
, uint32 mask
)
2407 if (!font
|| mask
== 0)
2410 if (mask
== B_FONT_ALL
) {
2411 fState
->font
= *font
;
2413 // TODO: move this into a BFont method
2414 if (mask
& B_FONT_FAMILY_AND_STYLE
)
2415 fState
->font
.SetFamilyAndStyle(font
->FamilyAndStyle());
2417 if (mask
& B_FONT_SIZE
)
2418 fState
->font
.SetSize(font
->Size());
2420 if (mask
& B_FONT_SHEAR
)
2421 fState
->font
.SetShear(font
->Shear());
2423 if (mask
& B_FONT_ROTATION
)
2424 fState
->font
.SetRotation(font
->Rotation());
2426 if (mask
& B_FONT_FALSE_BOLD_WIDTH
)
2427 fState
->font
.SetFalseBoldWidth(font
->FalseBoldWidth());
2429 if (mask
& B_FONT_SPACING
)
2430 fState
->font
.SetSpacing(font
->Spacing());
2432 if (mask
& B_FONT_ENCODING
)
2433 fState
->font
.SetEncoding(font
->Encoding());
2435 if (mask
& B_FONT_FACE
)
2436 fState
->font
.SetFace(font
->Face());
2438 if (mask
& B_FONT_FLAGS
)
2439 fState
->font
.SetFlags(font
->Flags());
2442 fState
->font_flags
|= mask
;
2445 _CheckLockAndSwitchCurrent();
2447 fState
->UpdateServerFontState(*fOwner
->fLink
);
2448 fState
->valid_flags
|= B_VIEW_FONT_BIT
;
2451 fState
->archiving_flags
|= B_VIEW_FONT_BIT
;
2452 // TODO: InvalidateLayout() here for convenience?
2457 BView::GetFont(BFont
* font
) const
2459 if (!fState
->IsValid(B_VIEW_FONT_BIT
)) {
2460 // we don't keep graphics state information, therefor
2461 // we need to ask the server for the origin after PopState()
2462 _CheckOwnerLockAndSwitchCurrent();
2464 // TODO: add a font getter!
2465 fState
->UpdateFrom(*fOwner
->fLink
);
2468 *font
= fState
->font
;
2473 BView::GetFontHeight(font_height
* height
) const
2475 fState
->font
.GetHeight(height
);
2480 BView::SetFontSize(float size
)
2485 SetFont(&font
, B_FONT_SIZE
);
2490 BView::StringWidth(const char* string
) const
2492 return fState
->font
.StringWidth(string
);
2497 BView::StringWidth(const char* string
, int32 length
) const
2499 return fState
->font
.StringWidth(string
, length
);
2504 BView::GetStringWidths(char* stringArray
[], int32 lengthArray
[],
2505 int32 numStrings
, float widthArray
[]) const
2507 fState
->font
.GetStringWidths(const_cast<const char**>(stringArray
),
2508 const_cast<const int32
*>(lengthArray
), numStrings
, widthArray
);
2513 BView::TruncateString(BString
* string
, uint32 mode
, float width
) const
2515 fState
->font
.TruncateString(string
, mode
, width
);
2520 BView::ClipToPicture(BPicture
* picture
, BPoint where
, bool sync
)
2522 _ClipToPicture(picture
, where
, false, sync
);
2527 BView::ClipToInversePicture(BPicture
* picture
, BPoint where
, bool sync
)
2529 _ClipToPicture(picture
, where
, true, sync
);
2534 BView::GetClippingRegion(BRegion
* region
) const
2539 // NOTE: the client has no idea when the clipping in the server
2540 // changed, so it is always read from the server
2541 region
->MakeEmpty();
2545 if (fIsPrinting
&& _CheckOwnerLock()) {
2546 region
->Set(fState
->print_rect
);
2550 _CheckLockAndSwitchCurrent();
2551 fOwner
->fLink
->StartMessage(AS_VIEW_GET_CLIP_REGION
);
2554 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
2556 fOwner
->fLink
->ReadRegion(region
);
2557 fState
->valid_flags
|= B_VIEW_CLIP_REGION_BIT
;
2564 BView::ConstrainClippingRegion(BRegion
* region
)
2566 if (_CheckOwnerLockAndSwitchCurrent()) {
2567 fOwner
->fLink
->StartMessage(AS_VIEW_SET_CLIP_REGION
);
2570 int32 count
= region
->CountRects();
2571 fOwner
->fLink
->Attach
<int32
>(count
);
2573 fOwner
->fLink
->AttachRegion(*region
);
2575 fOwner
->fLink
->Attach
<int32
>(-1);
2576 // '-1' means that in the app_server, there won't be any 'local'
2577 // clipping region (it will be NULL)
2580 _FlushIfNotInTransaction();
2582 fState
->valid_flags
&= ~B_VIEW_CLIP_REGION_BIT
;
2583 fState
->archiving_flags
|= B_VIEW_CLIP_REGION_BIT
;
2588 // #pragma mark - Drawing Functions
2592 BView::DrawBitmapAsync(const BBitmap
* bitmap
, BRect bitmapRect
, BRect viewRect
,
2595 if (bitmap
== NULL
|| fOwner
== NULL
2596 || !bitmapRect
.IsValid() || !viewRect
.IsValid())
2599 _CheckLockAndSwitchCurrent();
2601 ViewDrawBitmapInfo info
;
2602 info
.bitmapToken
= bitmap
->_ServerToken();
2603 info
.options
= options
;
2604 info
.viewRect
= viewRect
;
2605 info
.bitmapRect
= bitmapRect
;
2607 fOwner
->fLink
->StartMessage(AS_VIEW_DRAW_BITMAP
);
2608 fOwner
->fLink
->Attach
<ViewDrawBitmapInfo
>(info
);
2610 _FlushIfNotInTransaction();
2615 BView::DrawBitmapAsync(const BBitmap
* bitmap
, BRect bitmapRect
, BRect viewRect
)
2617 DrawBitmapAsync(bitmap
, bitmapRect
, viewRect
, 0);
2622 BView::DrawBitmapAsync(const BBitmap
* bitmap
, BRect viewRect
)
2624 if (bitmap
&& fOwner
) {
2625 DrawBitmapAsync(bitmap
, bitmap
->Bounds().OffsetToCopy(B_ORIGIN
),
2632 BView::DrawBitmapAsync(const BBitmap
* bitmap
, BPoint where
)
2634 if (bitmap
== NULL
|| fOwner
== NULL
)
2637 _CheckLockAndSwitchCurrent();
2639 ViewDrawBitmapInfo info
;
2640 info
.bitmapToken
= bitmap
->_ServerToken();
2642 info
.bitmapRect
= bitmap
->Bounds().OffsetToCopy(B_ORIGIN
);
2643 info
.viewRect
= info
.bitmapRect
.OffsetToCopy(where
);
2645 fOwner
->fLink
->StartMessage(AS_VIEW_DRAW_BITMAP
);
2646 fOwner
->fLink
->Attach
<ViewDrawBitmapInfo
>(info
);
2648 _FlushIfNotInTransaction();
2653 BView::DrawBitmapAsync(const BBitmap
* bitmap
)
2655 DrawBitmapAsync(bitmap
, PenLocation());
2660 BView::DrawBitmap(const BBitmap
* bitmap
, BRect bitmapRect
, BRect viewRect
,
2664 DrawBitmapAsync(bitmap
, bitmapRect
, viewRect
, options
);
2671 BView::DrawBitmap(const BBitmap
* bitmap
, BRect bitmapRect
, BRect viewRect
)
2674 DrawBitmapAsync(bitmap
, bitmapRect
, viewRect
, 0);
2681 BView::DrawBitmap(const BBitmap
* bitmap
, BRect viewRect
)
2683 if (bitmap
&& fOwner
) {
2684 DrawBitmap(bitmap
, bitmap
->Bounds().OffsetToCopy(B_ORIGIN
), viewRect
,
2691 BView::DrawBitmap(const BBitmap
* bitmap
, BPoint where
)
2694 DrawBitmapAsync(bitmap
, where
);
2701 BView::DrawBitmap(const BBitmap
* bitmap
)
2703 DrawBitmap(bitmap
, PenLocation());
2708 BView::DrawChar(char c
)
2710 DrawString(&c
, 1, PenLocation());
2715 BView::DrawChar(char c
, BPoint location
)
2717 DrawString(&c
, 1, location
);
2722 BView::DrawString(const char* string
, escapement_delta
* delta
)
2727 DrawString(string
, strlen(string
), PenLocation(), delta
);
2732 BView::DrawString(const char* string
, BPoint location
, escapement_delta
* delta
)
2737 DrawString(string
, strlen(string
), location
, delta
);
2742 BView::DrawString(const char* string
, int32 length
, escapement_delta
* delta
)
2744 DrawString(string
, length
, PenLocation(), delta
);
2749 BView::DrawString(const char* string
, int32 length
, BPoint location
,
2750 escapement_delta
* delta
)
2752 if (fOwner
== NULL
|| string
== NULL
|| length
< 1)
2755 _CheckLockAndSwitchCurrent();
2757 ViewDrawStringInfo info
;
2758 info
.stringLength
= length
;
2759 info
.location
= location
;
2761 info
.delta
= *delta
;
2763 // quite often delta will be NULL
2765 fOwner
->fLink
->StartMessage(AS_DRAW_STRING_WITH_DELTA
);
2767 fOwner
->fLink
->StartMessage(AS_DRAW_STRING
);
2769 fOwner
->fLink
->Attach
<ViewDrawStringInfo
>(info
);
2770 fOwner
->fLink
->Attach(string
, length
);
2772 _FlushIfNotInTransaction();
2774 // this modifies our pen location, so we invalidate the flag.
2775 fState
->valid_flags
&= ~B_VIEW_PEN_LOCATION_BIT
;
2780 BView::DrawString(const char* string
, const BPoint
* locations
,
2781 int32 locationCount
)
2786 DrawString(string
, strlen(string
), locations
, locationCount
);
2791 BView::DrawString(const char* string
, int32 length
, const BPoint
* locations
,
2792 int32 locationCount
)
2794 if (fOwner
== NULL
|| string
== NULL
|| length
< 1 || locations
== NULL
)
2797 _CheckLockAndSwitchCurrent();
2799 fOwner
->fLink
->StartMessage(AS_DRAW_STRING_WITH_OFFSETS
);
2801 fOwner
->fLink
->Attach
<int32
>(length
);
2802 fOwner
->fLink
->Attach
<int32
>(locationCount
);
2803 fOwner
->fLink
->Attach(string
, length
);
2804 fOwner
->fLink
->Attach(locations
, locationCount
* sizeof(BPoint
));
2806 _FlushIfNotInTransaction();
2808 // this modifies our pen location, so we invalidate the flag.
2809 fState
->valid_flags
&= ~B_VIEW_PEN_LOCATION_BIT
;
2814 BView::StrokeEllipse(BPoint center
, float xRadius
, float yRadius
,
2817 StrokeEllipse(BRect(center
.x
- xRadius
, center
.y
- yRadius
,
2818 center
.x
+ xRadius
, center
.y
+ yRadius
), pattern
);
2823 BView::StrokeEllipse(BRect rect
, ::pattern pattern
)
2828 _CheckLockAndSwitchCurrent();
2829 _UpdatePattern(pattern
);
2831 fOwner
->fLink
->StartMessage(AS_STROKE_ELLIPSE
);
2832 fOwner
->fLink
->Attach
<BRect
>(rect
);
2834 _FlushIfNotInTransaction();
2839 BView::FillEllipse(BPoint center
, float xRadius
, float yRadius
,
2842 FillEllipse(BRect(center
.x
- xRadius
, center
.y
- yRadius
,
2843 center
.x
+ xRadius
, center
.y
+ yRadius
), pattern
);
2848 BView::FillEllipse(BPoint center
, float xRadius
, float yRadius
,
2849 const BGradient
& gradient
)
2851 FillEllipse(BRect(center
.x
- xRadius
, center
.y
- yRadius
,
2852 center
.x
+ xRadius
, center
.y
+ yRadius
), gradient
);
2857 BView::FillEllipse(BRect rect
, ::pattern pattern
)
2862 _CheckLockAndSwitchCurrent();
2863 _UpdatePattern(pattern
);
2865 fOwner
->fLink
->StartMessage(AS_FILL_ELLIPSE
);
2866 fOwner
->fLink
->Attach
<BRect
>(rect
);
2868 _FlushIfNotInTransaction();
2873 BView::FillEllipse(BRect rect
, const BGradient
& gradient
)
2878 _CheckLockAndSwitchCurrent();
2880 fOwner
->fLink
->StartMessage(AS_FILL_ELLIPSE_GRADIENT
);
2881 fOwner
->fLink
->Attach
<BRect
>(rect
);
2882 fOwner
->fLink
->AttachGradient(gradient
);
2884 _FlushIfNotInTransaction();
2889 BView::StrokeArc(BPoint center
, float xRadius
, float yRadius
, float startAngle
,
2890 float arcAngle
, ::pattern pattern
)
2892 StrokeArc(BRect(center
.x
- xRadius
, center
.y
- yRadius
, center
.x
+ xRadius
,
2893 center
.y
+ yRadius
), startAngle
, arcAngle
, pattern
);
2898 BView::StrokeArc(BRect rect
, float startAngle
, float arcAngle
,
2904 _CheckLockAndSwitchCurrent();
2905 _UpdatePattern(pattern
);
2907 fOwner
->fLink
->StartMessage(AS_STROKE_ARC
);
2908 fOwner
->fLink
->Attach
<BRect
>(rect
);
2909 fOwner
->fLink
->Attach
<float>(startAngle
);
2910 fOwner
->fLink
->Attach
<float>(arcAngle
);
2912 _FlushIfNotInTransaction();
2917 BView::FillArc(BPoint center
,float xRadius
, float yRadius
, float startAngle
,
2918 float arcAngle
, ::pattern pattern
)
2920 FillArc(BRect(center
.x
- xRadius
, center
.y
- yRadius
, center
.x
+ xRadius
,
2921 center
.y
+ yRadius
), startAngle
, arcAngle
, pattern
);
2926 BView::FillArc(BPoint center
,float xRadius
, float yRadius
, float startAngle
,
2927 float arcAngle
, const BGradient
& gradient
)
2929 FillArc(BRect(center
.x
- xRadius
, center
.y
- yRadius
, center
.x
+ xRadius
,
2930 center
.y
+ yRadius
), startAngle
, arcAngle
, gradient
);
2935 BView::FillArc(BRect rect
, float startAngle
, float arcAngle
,
2941 _CheckLockAndSwitchCurrent();
2942 _UpdatePattern(pattern
);
2944 fOwner
->fLink
->StartMessage(AS_FILL_ARC
);
2945 fOwner
->fLink
->Attach
<BRect
>(rect
);
2946 fOwner
->fLink
->Attach
<float>(startAngle
);
2947 fOwner
->fLink
->Attach
<float>(arcAngle
);
2949 _FlushIfNotInTransaction();
2954 BView::FillArc(BRect rect
, float startAngle
, float arcAngle
,
2955 const BGradient
& gradient
)
2960 _CheckLockAndSwitchCurrent();
2962 fOwner
->fLink
->StartMessage(AS_FILL_ARC_GRADIENT
);
2963 fOwner
->fLink
->Attach
<BRect
>(rect
);
2964 fOwner
->fLink
->Attach
<float>(startAngle
);
2965 fOwner
->fLink
->Attach
<float>(arcAngle
);
2966 fOwner
->fLink
->AttachGradient(gradient
);
2968 _FlushIfNotInTransaction();
2973 BView::StrokeBezier(BPoint
* controlPoints
, ::pattern pattern
)
2978 _CheckLockAndSwitchCurrent();
2979 _UpdatePattern(pattern
);
2981 fOwner
->fLink
->StartMessage(AS_STROKE_BEZIER
);
2982 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[0]);
2983 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[1]);
2984 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[2]);
2985 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[3]);
2987 _FlushIfNotInTransaction();
2992 BView::FillBezier(BPoint
* controlPoints
, ::pattern pattern
)
2997 _CheckLockAndSwitchCurrent();
2998 _UpdatePattern(pattern
);
3000 fOwner
->fLink
->StartMessage(AS_FILL_BEZIER
);
3001 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[0]);
3002 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[1]);
3003 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[2]);
3004 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[3]);
3006 _FlushIfNotInTransaction();
3011 BView::FillBezier(BPoint
* controlPoints
, const BGradient
& gradient
)
3016 _CheckLockAndSwitchCurrent();
3018 fOwner
->fLink
->StartMessage(AS_FILL_BEZIER_GRADIENT
);
3019 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[0]);
3020 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[1]);
3021 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[2]);
3022 fOwner
->fLink
->Attach
<BPoint
>(controlPoints
[3]);
3023 fOwner
->fLink
->AttachGradient(gradient
);
3025 _FlushIfNotInTransaction();
3030 BView::StrokePolygon(const BPolygon
* polygon
, bool closed
, ::pattern pattern
)
3032 if (polygon
== NULL
)
3035 StrokePolygon(polygon
->fPoints
, polygon
->fCount
, polygon
->Frame(), closed
,
3041 BView::StrokePolygon(const BPoint
* pointArray
, int32 numPoints
, bool closed
,
3044 BPolygon
polygon(pointArray
, numPoints
);
3046 StrokePolygon(polygon
.fPoints
, polygon
.fCount
, polygon
.Frame(), closed
,
3052 BView::StrokePolygon(const BPoint
* pointArray
, int32 numPoints
, BRect bounds
,
3053 bool closed
, ::pattern pattern
)
3055 if (pointArray
== NULL
3060 _CheckLockAndSwitchCurrent();
3061 _UpdatePattern(pattern
);
3063 BPolygon
polygon(pointArray
, numPoints
);
3064 polygon
.MapTo(polygon
.Frame(), bounds
);
3066 if (fOwner
->fLink
->StartMessage(AS_STROKE_POLYGON
,
3067 polygon
.fCount
* sizeof(BPoint
) + sizeof(BRect
) + sizeof(bool)
3068 + sizeof(int32
)) == B_OK
) {
3069 fOwner
->fLink
->Attach
<BRect
>(polygon
.Frame());
3070 fOwner
->fLink
->Attach
<bool>(closed
);
3071 fOwner
->fLink
->Attach
<int32
>(polygon
.fCount
);
3072 fOwner
->fLink
->Attach(polygon
.fPoints
, polygon
.fCount
* sizeof(BPoint
));
3074 _FlushIfNotInTransaction();
3076 fprintf(stderr
, "ERROR: Can't send polygon to app_server!\n");
3082 BView::FillPolygon(const BPolygon
* polygon
, ::pattern pattern
)
3085 || polygon
->fCount
<= 2
3089 _CheckLockAndSwitchCurrent();
3090 _UpdatePattern(pattern
);
3092 if (fOwner
->fLink
->StartMessage(AS_FILL_POLYGON
,
3093 polygon
->fCount
* sizeof(BPoint
) + sizeof(BRect
) + sizeof(int32
))
3095 fOwner
->fLink
->Attach
<BRect
>(polygon
->Frame());
3096 fOwner
->fLink
->Attach
<int32
>(polygon
->fCount
);
3097 fOwner
->fLink
->Attach(polygon
->fPoints
,
3098 polygon
->fCount
* sizeof(BPoint
));
3100 _FlushIfNotInTransaction();
3102 fprintf(stderr
, "ERROR: Can't send polygon to app_server!\n");
3108 BView::FillPolygon(const BPolygon
* polygon
, const BGradient
& gradient
)
3111 || polygon
->fCount
<= 2
3115 _CheckLockAndSwitchCurrent();
3117 if (fOwner
->fLink
->StartMessage(AS_FILL_POLYGON_GRADIENT
,
3118 polygon
->fCount
* sizeof(BPoint
) + sizeof(BRect
) + sizeof(int32
))
3120 fOwner
->fLink
->Attach
<BRect
>(polygon
->Frame());
3121 fOwner
->fLink
->Attach
<int32
>(polygon
->fCount
);
3122 fOwner
->fLink
->Attach(polygon
->fPoints
,
3123 polygon
->fCount
* sizeof(BPoint
));
3124 fOwner
->fLink
->AttachGradient(gradient
);
3126 _FlushIfNotInTransaction();
3128 fprintf(stderr
, "ERROR: Can't send polygon to app_server!\n");
3134 BView::FillPolygon(const BPoint
* pointArray
, int32 numPoints
, ::pattern pattern
)
3136 if (pointArray
== NULL
)
3139 BPolygon
polygon(pointArray
, numPoints
);
3140 FillPolygon(&polygon
, pattern
);
3145 BView::FillPolygon(const BPoint
* pointArray
, int32 numPoints
,
3146 const BGradient
& gradient
)
3148 if (pointArray
== NULL
)
3151 BPolygon
polygon(pointArray
, numPoints
);
3152 FillPolygon(&polygon
, gradient
);
3157 BView::FillPolygon(const BPoint
* pointArray
, int32 numPoints
, BRect bounds
,
3160 if (pointArray
== NULL
)
3163 BPolygon
polygon(pointArray
, numPoints
);
3165 polygon
.MapTo(polygon
.Frame(), bounds
);
3166 FillPolygon(&polygon
, pattern
);
3171 BView::FillPolygon(const BPoint
* pointArray
, int32 numPoints
, BRect bounds
,
3172 const BGradient
& gradient
)
3174 if (pointArray
== NULL
)
3177 BPolygon
polygon(pointArray
, numPoints
);
3179 polygon
.MapTo(polygon
.Frame(), bounds
);
3180 FillPolygon(&polygon
, gradient
);
3185 BView::StrokeRect(BRect rect
, ::pattern pattern
)
3190 _CheckLockAndSwitchCurrent();
3191 _UpdatePattern(pattern
);
3193 fOwner
->fLink
->StartMessage(AS_STROKE_RECT
);
3194 fOwner
->fLink
->Attach
<BRect
>(rect
);
3196 _FlushIfNotInTransaction();
3201 BView::FillRect(BRect rect
, ::pattern pattern
)
3206 // NOTE: ensuring compatibility with R5,
3207 // invalid rects are not filled, they are stroked though!
3208 if (!rect
.IsValid())
3211 _CheckLockAndSwitchCurrent();
3212 _UpdatePattern(pattern
);
3214 fOwner
->fLink
->StartMessage(AS_FILL_RECT
);
3215 fOwner
->fLink
->Attach
<BRect
>(rect
);
3217 _FlushIfNotInTransaction();
3222 BView::FillRect(BRect rect
, const BGradient
& gradient
)
3227 // NOTE: ensuring compatibility with R5,
3228 // invalid rects are not filled, they are stroked though!
3229 if (!rect
.IsValid())
3232 _CheckLockAndSwitchCurrent();
3234 fOwner
->fLink
->StartMessage(AS_FILL_RECT_GRADIENT
);
3235 fOwner
->fLink
->Attach
<BRect
>(rect
);
3236 fOwner
->fLink
->AttachGradient(gradient
);
3238 _FlushIfNotInTransaction();
3243 BView::StrokeRoundRect(BRect rect
, float xRadius
, float yRadius
,
3249 _CheckLockAndSwitchCurrent();
3250 _UpdatePattern(pattern
);
3252 fOwner
->fLink
->StartMessage(AS_STROKE_ROUNDRECT
);
3253 fOwner
->fLink
->Attach
<BRect
>(rect
);
3254 fOwner
->fLink
->Attach
<float>(xRadius
);
3255 fOwner
->fLink
->Attach
<float>(yRadius
);
3257 _FlushIfNotInTransaction();
3262 BView::FillRoundRect(BRect rect
, float xRadius
, float yRadius
,
3268 _CheckLockAndSwitchCurrent();
3270 _UpdatePattern(pattern
);
3272 fOwner
->fLink
->StartMessage(AS_FILL_ROUNDRECT
);
3273 fOwner
->fLink
->Attach
<BRect
>(rect
);
3274 fOwner
->fLink
->Attach
<float>(xRadius
);
3275 fOwner
->fLink
->Attach
<float>(yRadius
);
3277 _FlushIfNotInTransaction();
3282 BView::FillRoundRect(BRect rect
, float xRadius
, float yRadius
,
3283 const BGradient
& gradient
)
3288 _CheckLockAndSwitchCurrent();
3290 fOwner
->fLink
->StartMessage(AS_FILL_ROUNDRECT_GRADIENT
);
3291 fOwner
->fLink
->Attach
<BRect
>(rect
);
3292 fOwner
->fLink
->Attach
<float>(xRadius
);
3293 fOwner
->fLink
->Attach
<float>(yRadius
);
3294 fOwner
->fLink
->AttachGradient(gradient
);
3296 _FlushIfNotInTransaction();
3301 BView::FillRegion(BRegion
* region
, ::pattern pattern
)
3303 if (region
== NULL
|| fOwner
== NULL
)
3306 _CheckLockAndSwitchCurrent();
3308 _UpdatePattern(pattern
);
3310 fOwner
->fLink
->StartMessage(AS_FILL_REGION
);
3311 fOwner
->fLink
->AttachRegion(*region
);
3313 _FlushIfNotInTransaction();
3318 BView::FillRegion(BRegion
* region
, const BGradient
& gradient
)
3320 if (region
== NULL
|| fOwner
== NULL
)
3323 _CheckLockAndSwitchCurrent();
3325 fOwner
->fLink
->StartMessage(AS_FILL_REGION_GRADIENT
);
3326 fOwner
->fLink
->AttachRegion(*region
);
3327 fOwner
->fLink
->AttachGradient(gradient
);
3329 _FlushIfNotInTransaction();
3334 BView::StrokeTriangle(BPoint point1
, BPoint point2
, BPoint point3
, BRect bounds
,
3340 _CheckLockAndSwitchCurrent();
3342 _UpdatePattern(pattern
);
3344 fOwner
->fLink
->StartMessage(AS_STROKE_TRIANGLE
);
3345 fOwner
->fLink
->Attach
<BPoint
>(point1
);
3346 fOwner
->fLink
->Attach
<BPoint
>(point2
);
3347 fOwner
->fLink
->Attach
<BPoint
>(point3
);
3348 fOwner
->fLink
->Attach
<BRect
>(bounds
);
3350 _FlushIfNotInTransaction();
3355 BView::StrokeTriangle(BPoint point1
, BPoint point2
, BPoint point3
,
3359 // we construct the smallest rectangle that contains the 3 points
3360 // for the 1st point
3361 BRect
bounds(point1
, point1
);
3363 // for the 2nd point
3364 if (point2
.x
< bounds
.left
)
3365 bounds
.left
= point2
.x
;
3367 if (point2
.y
< bounds
.top
)
3368 bounds
.top
= point2
.y
;
3370 if (point2
.x
> bounds
.right
)
3371 bounds
.right
= point2
.x
;
3373 if (point2
.y
> bounds
.bottom
)
3374 bounds
.bottom
= point2
.y
;
3376 // for the 3rd point
3377 if (point3
.x
< bounds
.left
)
3378 bounds
.left
= point3
.x
;
3380 if (point3
.y
< bounds
.top
)
3381 bounds
.top
= point3
.y
;
3383 if (point3
.x
> bounds
.right
)
3384 bounds
.right
= point3
.x
;
3386 if (point3
.y
> bounds
.bottom
)
3387 bounds
.bottom
= point3
.y
;
3389 StrokeTriangle(point1
, point2
, point3
, bounds
, pattern
);
3395 BView::FillTriangle(BPoint point1
, BPoint point2
, BPoint point3
,
3399 // we construct the smallest rectangle that contains the 3 points
3400 // for the 1st point
3401 BRect
bounds(point1
, point1
);
3403 // for the 2nd point
3404 if (point2
.x
< bounds
.left
)
3405 bounds
.left
= point2
.x
;
3407 if (point2
.y
< bounds
.top
)
3408 bounds
.top
= point2
.y
;
3410 if (point2
.x
> bounds
.right
)
3411 bounds
.right
= point2
.x
;
3413 if (point2
.y
> bounds
.bottom
)
3414 bounds
.bottom
= point2
.y
;
3416 // for the 3rd point
3417 if (point3
.x
< bounds
.left
)
3418 bounds
.left
= point3
.x
;
3420 if (point3
.y
< bounds
.top
)
3421 bounds
.top
= point3
.y
;
3423 if (point3
.x
> bounds
.right
)
3424 bounds
.right
= point3
.x
;
3426 if (point3
.y
> bounds
.bottom
)
3427 bounds
.bottom
= point3
.y
;
3429 FillTriangle(point1
, point2
, point3
, bounds
, pattern
);
3435 BView::FillTriangle(BPoint point1
, BPoint point2
, BPoint point3
,
3436 const BGradient
& gradient
)
3439 // we construct the smallest rectangle that contains the 3 points
3440 // for the 1st point
3441 BRect
bounds(point1
, point1
);
3443 // for the 2nd point
3444 if (point2
.x
< bounds
.left
)
3445 bounds
.left
= point2
.x
;
3447 if (point2
.y
< bounds
.top
)
3448 bounds
.top
= point2
.y
;
3450 if (point2
.x
> bounds
.right
)
3451 bounds
.right
= point2
.x
;
3453 if (point2
.y
> bounds
.bottom
)
3454 bounds
.bottom
= point2
.y
;
3456 // for the 3rd point
3457 if (point3
.x
< bounds
.left
)
3458 bounds
.left
= point3
.x
;
3460 if (point3
.y
< bounds
.top
)
3461 bounds
.top
= point3
.y
;
3463 if (point3
.x
> bounds
.right
)
3464 bounds
.right
= point3
.x
;
3466 if (point3
.y
> bounds
.bottom
)
3467 bounds
.bottom
= point3
.y
;
3469 FillTriangle(point1
, point2
, point3
, bounds
, gradient
);
3475 BView::FillTriangle(BPoint point1
, BPoint point2
, BPoint point3
,
3476 BRect bounds
, ::pattern pattern
)
3481 _CheckLockAndSwitchCurrent();
3482 _UpdatePattern(pattern
);
3484 fOwner
->fLink
->StartMessage(AS_FILL_TRIANGLE
);
3485 fOwner
->fLink
->Attach
<BPoint
>(point1
);
3486 fOwner
->fLink
->Attach
<BPoint
>(point2
);
3487 fOwner
->fLink
->Attach
<BPoint
>(point3
);
3488 fOwner
->fLink
->Attach
<BRect
>(bounds
);
3490 _FlushIfNotInTransaction();
3495 BView::FillTriangle(BPoint point1
, BPoint point2
, BPoint point3
, BRect bounds
,
3496 const BGradient
& gradient
)
3501 _CheckLockAndSwitchCurrent();
3502 fOwner
->fLink
->StartMessage(AS_FILL_TRIANGLE_GRADIENT
);
3503 fOwner
->fLink
->Attach
<BPoint
>(point1
);
3504 fOwner
->fLink
->Attach
<BPoint
>(point2
);
3505 fOwner
->fLink
->Attach
<BPoint
>(point3
);
3506 fOwner
->fLink
->Attach
<BRect
>(bounds
);
3507 fOwner
->fLink
->AttachGradient(gradient
);
3509 _FlushIfNotInTransaction();
3514 BView::StrokeLine(BPoint toPoint
, ::pattern pattern
)
3516 StrokeLine(PenLocation(), toPoint
, pattern
);
3521 BView::StrokeLine(BPoint start
, BPoint end
, ::pattern pattern
)
3526 _CheckLockAndSwitchCurrent();
3527 _UpdatePattern(pattern
);
3529 ViewStrokeLineInfo info
;
3530 info
.startPoint
= start
;
3531 info
.endPoint
= end
;
3533 fOwner
->fLink
->StartMessage(AS_STROKE_LINE
);
3534 fOwner
->fLink
->Attach
<ViewStrokeLineInfo
>(info
);
3536 _FlushIfNotInTransaction();
3538 // this modifies our pen location, so we invalidate the flag.
3539 fState
->valid_flags
&= ~B_VIEW_PEN_LOCATION_BIT
;
3544 BView::StrokeShape(BShape
* shape
, ::pattern pattern
)
3546 if (shape
== NULL
|| fOwner
== NULL
)
3549 shape_data
* sd
= (shape_data
*)shape
->fPrivateData
;
3550 if (sd
->opCount
== 0 || sd
->ptCount
== 0)
3553 _CheckLockAndSwitchCurrent();
3554 _UpdatePattern(pattern
);
3556 fOwner
->fLink
->StartMessage(AS_STROKE_SHAPE
);
3557 fOwner
->fLink
->Attach
<BRect
>(shape
->Bounds());
3558 fOwner
->fLink
->Attach
<int32
>(sd
->opCount
);
3559 fOwner
->fLink
->Attach
<int32
>(sd
->ptCount
);
3560 fOwner
->fLink
->Attach(sd
->opList
, sd
->opCount
* sizeof(uint32
));
3561 fOwner
->fLink
->Attach(sd
->ptList
, sd
->ptCount
* sizeof(BPoint
));
3563 _FlushIfNotInTransaction();
3568 BView::FillShape(BShape
* shape
, ::pattern pattern
)
3570 if (shape
== NULL
|| fOwner
== NULL
)
3573 shape_data
* sd
= (shape_data
*)(shape
->fPrivateData
);
3574 if (sd
->opCount
== 0 || sd
->ptCount
== 0)
3577 _CheckLockAndSwitchCurrent();
3578 _UpdatePattern(pattern
);
3580 fOwner
->fLink
->StartMessage(AS_FILL_SHAPE
);
3581 fOwner
->fLink
->Attach
<BRect
>(shape
->Bounds());
3582 fOwner
->fLink
->Attach
<int32
>(sd
->opCount
);
3583 fOwner
->fLink
->Attach
<int32
>(sd
->ptCount
);
3584 fOwner
->fLink
->Attach(sd
->opList
, sd
->opCount
* sizeof(int32
));
3585 fOwner
->fLink
->Attach(sd
->ptList
, sd
->ptCount
* sizeof(BPoint
));
3587 _FlushIfNotInTransaction();
3592 BView::FillShape(BShape
* shape
, const BGradient
& gradient
)
3594 if (shape
== NULL
|| fOwner
== NULL
)
3597 shape_data
* sd
= (shape_data
*)(shape
->fPrivateData
);
3598 if (sd
->opCount
== 0 || sd
->ptCount
== 0)
3601 _CheckLockAndSwitchCurrent();
3603 fOwner
->fLink
->StartMessage(AS_FILL_SHAPE_GRADIENT
);
3604 fOwner
->fLink
->Attach
<BRect
>(shape
->Bounds());
3605 fOwner
->fLink
->Attach
<int32
>(sd
->opCount
);
3606 fOwner
->fLink
->Attach
<int32
>(sd
->ptCount
);
3607 fOwner
->fLink
->Attach(sd
->opList
, sd
->opCount
* sizeof(int32
));
3608 fOwner
->fLink
->Attach(sd
->ptList
, sd
->ptCount
* sizeof(BPoint
));
3609 fOwner
->fLink
->AttachGradient(gradient
);
3611 _FlushIfNotInTransaction();
3616 BView::BeginLineArray(int32 count
)
3622 debugger("Calling BeginLineArray with a count <= 0");
3627 debugger("Can't nest BeginLineArray calls");
3628 // not fatal, but it helps during
3629 // development of your app and is in
3631 delete[] fCommArray
->array
;
3635 // TODO: since this method cannot return failure, and further AddLine()
3636 // calls with a NULL fCommArray would drop into the debugger anyway,
3637 // we allow the possible std::bad_alloc exceptions here...
3638 fCommArray
= new _array_data_
;
3639 fCommArray
->count
= 0;
3641 // Make sure the fCommArray is initialized to reasonable values in cases of
3642 // bad_alloc. At least the exception can be caught and EndLineArray won't
3644 fCommArray
->array
= NULL
;
3645 fCommArray
->maxCount
= 0;
3647 fCommArray
->array
= new ViewLineArrayInfo
[count
];
3648 fCommArray
->maxCount
= count
;
3653 BView::AddLine(BPoint start
, BPoint end
, rgb_color color
)
3659 debugger("BeginLineArray must be called before using AddLine");
3663 const uint32
&arrayCount
= fCommArray
->count
;
3664 if (arrayCount
< fCommArray
->maxCount
) {
3665 fCommArray
->array
[arrayCount
].startPoint
= start
;
3666 fCommArray
->array
[arrayCount
].endPoint
= end
;
3667 fCommArray
->array
[arrayCount
].color
= color
;
3669 fCommArray
->count
++;
3675 BView::EndLineArray()
3680 if (fCommArray
== NULL
)
3681 debugger("Can't call EndLineArray before BeginLineArray");
3683 _CheckLockAndSwitchCurrent();
3685 fOwner
->fLink
->StartMessage(AS_STROKE_LINEARRAY
);
3686 fOwner
->fLink
->Attach
<int32
>(fCommArray
->count
);
3687 fOwner
->fLink
->Attach(fCommArray
->array
,
3688 fCommArray
->count
* sizeof(ViewLineArrayInfo
));
3690 _FlushIfNotInTransaction();
3697 BView::SetDiskMode(char* filename
, long offset
)
3700 // One BeBook version has this to say about SetDiskMode():
3702 // "Begins recording a picture to the file with the given filename
3703 // at the given offset. Subsequent drawing commands sent to the view
3704 // will be written to the file until EndPicture() is called. The
3705 // stored commands may be played from the file with DrawPicture()."
3710 BView::BeginPicture(BPicture
* picture
)
3712 if (_CheckOwnerLockAndSwitchCurrent()
3713 && picture
&& picture
->fUsurped
== NULL
) {
3714 picture
->Usurp(fCurrentPicture
);
3715 fCurrentPicture
= picture
;
3717 fOwner
->fLink
->StartMessage(AS_VIEW_BEGIN_PICTURE
);
3723 BView::AppendToPicture(BPicture
* picture
)
3725 _CheckLockAndSwitchCurrent();
3727 if (picture
&& picture
->fUsurped
== NULL
) {
3728 int32 token
= picture
->Token();
3731 BeginPicture(picture
);
3733 picture
->SetToken(-1);
3734 picture
->Usurp(fCurrentPicture
);
3735 fCurrentPicture
= picture
;
3736 fOwner
->fLink
->StartMessage(AS_VIEW_APPEND_TO_PICTURE
);
3737 fOwner
->fLink
->Attach
<int32
>(token
);
3746 if (_CheckOwnerLockAndSwitchCurrent() && fCurrentPicture
) {
3749 fOwner
->fLink
->StartMessage(AS_VIEW_END_PICTURE
);
3752 if (fOwner
->fLink
->FlushWithReply(code
) == B_OK
3754 && fOwner
->fLink
->Read
<int32
>(&token
) == B_OK
) {
3755 BPicture
* picture
= fCurrentPicture
;
3756 fCurrentPicture
= picture
->StepDown();
3757 picture
->SetToken(token
);
3759 // TODO do this more efficient e.g. use a shared area and let the
3760 // client write into it
3761 picture
->_Download();
3771 BView::SetViewBitmap(const BBitmap
* bitmap
, BRect srcRect
, BRect dstRect
,
3772 uint32 followFlags
, uint32 options
)
3774 _SetViewBitmap(bitmap
, srcRect
, dstRect
, followFlags
, options
);
3779 BView::SetViewBitmap(const BBitmap
* bitmap
, uint32 followFlags
, uint32 options
)
3783 rect
= bitmap
->Bounds();
3785 rect
.OffsetTo(B_ORIGIN
);
3787 _SetViewBitmap(bitmap
, rect
, rect
, followFlags
, options
);
3792 BView::ClearViewBitmap()
3794 _SetViewBitmap(NULL
, BRect(), BRect(), 0, 0);
3799 BView::SetViewOverlay(const BBitmap
* overlay
, BRect srcRect
, BRect dstRect
,
3800 rgb_color
* colorKey
, uint32 followFlags
, uint32 options
)
3802 if (overlay
== NULL
|| (overlay
->fFlags
& B_BITMAP_WILL_OVERLAY
) == 0)
3805 status_t status
= _SetViewBitmap(overlay
, srcRect
, dstRect
, followFlags
,
3806 options
| AS_REQUEST_COLOR_KEY
);
3807 if (status
== B_OK
) {
3808 // read the color that will be treated as transparent
3809 fOwner
->fLink
->Read
<rgb_color
>(colorKey
);
3817 BView::SetViewOverlay(const BBitmap
* overlay
, rgb_color
* colorKey
,
3818 uint32 followFlags
, uint32 options
)
3820 if (overlay
== NULL
)
3823 BRect rect
= overlay
->Bounds();
3824 rect
.OffsetTo(B_ORIGIN
);
3826 return SetViewOverlay(overlay
, rect
, rect
, colorKey
, followFlags
, options
);
3831 BView::ClearViewOverlay()
3833 _SetViewBitmap(NULL
, BRect(), BRect(), 0, 0);
3838 BView::CopyBits(BRect src
, BRect dst
)
3843 if (!src
.IsValid() || !dst
.IsValid())
3846 _CheckLockAndSwitchCurrent();
3848 fOwner
->fLink
->StartMessage(AS_VIEW_COPY_BITS
);
3849 fOwner
->fLink
->Attach
<BRect
>(src
);
3850 fOwner
->fLink
->Attach
<BRect
>(dst
);
3852 _FlushIfNotInTransaction();
3857 BView::DrawPicture(const BPicture
* picture
)
3859 if (picture
== NULL
)
3862 DrawPictureAsync(picture
, PenLocation());
3868 BView::DrawPicture(const BPicture
* picture
, BPoint where
)
3870 if (picture
== NULL
)
3873 DrawPictureAsync(picture
, where
);
3879 BView::DrawPicture(const char* filename
, long offset
, BPoint where
)
3884 DrawPictureAsync(filename
, offset
, where
);
3890 BView::DrawPictureAsync(const BPicture
* picture
)
3892 if (picture
== NULL
)
3895 DrawPictureAsync(picture
, PenLocation());
3900 BView::DrawPictureAsync(const BPicture
* picture
, BPoint where
)
3902 if (picture
== NULL
)
3905 if (_CheckOwnerLockAndSwitchCurrent() && picture
->Token() > 0) {
3906 fOwner
->fLink
->StartMessage(AS_VIEW_DRAW_PICTURE
);
3907 fOwner
->fLink
->Attach
<int32
>(picture
->Token());
3908 fOwner
->fLink
->Attach
<BPoint
>(where
);
3910 _FlushIfNotInTransaction();
3916 BView::DrawPictureAsync(const char* filename
, long offset
, BPoint where
)
3922 BFile
file(filename
, B_READ_ONLY
);
3923 if (file
.InitCheck() < B_OK
)
3926 file
.Seek(offset
, SEEK_SET
);
3929 if (picture
.Unflatten(&file
) < B_OK
)
3932 DrawPictureAsync(&picture
, where
);
3937 BView::Invalidate(BRect invalRect
)
3942 // NOTE: This rounding of the invalid rect is to stay compatible with BeOS.
3943 // On the server side, the invalid rect will be converted to a BRegion,
3944 // which rounds in a different manner, so that it really includes the
3945 // fractional coordinates of a BRect (ie ceilf(rect.right) &
3946 // ceilf(rect.bottom)), which is also what BeOS does. So we have to do the
3947 // different rounding here to stay compatible in both ways.
3948 invalRect
.left
= (int)invalRect
.left
;
3949 invalRect
.top
= (int)invalRect
.top
;
3950 invalRect
.right
= (int)invalRect
.right
;
3951 invalRect
.bottom
= (int)invalRect
.bottom
;
3952 if (!invalRect
.IsValid())
3955 _CheckLockAndSwitchCurrent();
3957 fOwner
->fLink
->StartMessage(AS_VIEW_INVALIDATE_RECT
);
3958 fOwner
->fLink
->Attach
<BRect
>(invalRect
);
3960 // TODO: determine why this check isn't working correctly.
3962 if (!fOwner
->fUpdateRequested
) {
3963 fOwner
->fLink
->Flush();
3964 fOwner
->fUpdateRequested
= true;
3967 fOwner
->fLink
->Flush();
3973 BView::Invalidate(const BRegion
* region
)
3975 if (region
== NULL
|| fOwner
== NULL
)
3978 _CheckLockAndSwitchCurrent();
3980 fOwner
->fLink
->StartMessage(AS_VIEW_INVALIDATE_REGION
);
3981 fOwner
->fLink
->AttachRegion(*region
);
3985 if (!fOwner
->fUpdateRequested
) {
3986 fOwner
->fLink
->Flush();
3987 fOwner
->fUpdateRequested
= true;
3990 fOwner
->fLink
->Flush();
3998 Invalidate(Bounds());
4003 BView::InvertRect(BRect rect
)
4006 _CheckLockAndSwitchCurrent();
4008 fOwner
->fLink
->StartMessage(AS_VIEW_INVERT_RECT
);
4009 fOwner
->fLink
->Attach
<BRect
>(rect
);
4011 _FlushIfNotInTransaction();
4016 // #pragma mark - View Hierarchy Functions
4020 BView::AddChild(BView
* child
, BView
* before
)
4022 STRACE(("BView(%s)::AddChild(child '%s', before '%s')\n",
4024 child
!= NULL
&& child
->Name() ? child
->Name() : "NULL",
4025 before
!= NULL
&& before
->Name() ? before
->Name() : "NULL"));
4027 if (!_AddChild(child
, before
))
4030 if (fLayoutData
->fLayout
)
4031 fLayoutData
->fLayout
->AddView(child
);
4036 BView::AddChild(BLayoutItem
* child
)
4038 if (!fLayoutData
->fLayout
)
4040 return fLayoutData
->fLayout
->AddItem(child
);
4045 BView::_AddChild(BView
* child
, BView
* before
)
4050 if (child
->fParent
!= NULL
) {
4051 debugger("AddChild failed - the view already has a parent.");
4055 if (child
== this) {
4056 debugger("AddChild failed - cannot add a view to itself.");
4060 bool lockedOwner
= false;
4061 if (fOwner
&& !fOwner
->IsLocked()) {
4066 if (!_AddChildToList(child
, before
)) {
4067 debugger("AddChild failed!");
4074 _CheckLockAndSwitchCurrent();
4076 child
->_SetOwner(fOwner
);
4077 child
->_CreateSelf();
4091 BView::RemoveChild(BView
* child
)
4093 STRACE(("BView(%s)::RemoveChild(%s)\n", Name(), child
->Name()));
4098 if (child
->fParent
!= this)
4101 return child
->RemoveSelf();
4106 BView::CountChildren() const
4111 BView
* child
= fFirstChild
;
4113 while (child
!= NULL
) {
4115 child
= child
->fNextSibling
;
4123 BView::ChildAt(int32 index
) const
4127 BView
* child
= fFirstChild
;
4128 while (child
!= NULL
&& index
-- > 0) {
4129 child
= child
->fNextSibling
;
4137 BView::NextSibling() const
4139 return fNextSibling
;
4144 BView::PreviousSibling() const
4146 return fPreviousSibling
;
4153 _RemoveLayoutItemsFromLayout(false);
4155 return _RemoveSelf();
4160 BView::_RemoveSelf()
4162 STRACE(("BView(%s)::_RemoveSelf()\n", Name()));
4164 // Remove this child from its parent
4166 BWindow
* owner
= fOwner
;
4169 if (owner
!= NULL
) {
4170 _UpdateStateForRemove();
4174 BView
* parent
= fParent
;
4175 if (!parent
|| !parent
->_RemoveChildFromList(this))
4178 if (owner
!= NULL
&& !fTopLevelView
) {
4179 // the top level view is deleted by the app_server automatically
4180 owner
->fLink
->StartMessage(AS_VIEW_DELETE
);
4181 owner
->fLink
->Attach
<int32
>(_get_object_token_(this));
4184 parent
->InvalidateLayout();
4186 STRACE(("DONE: BView(%s)::_RemoveSelf()\n", Name()));
4193 BView::_RemoveLayoutItemsFromLayout(bool deleteItems
)
4195 if (fParent
== NULL
|| fParent
->fLayoutData
->fLayout
== NULL
)
4198 int32 index
= fLayoutData
->fLayoutItems
.CountItems();
4199 while (index
-- > 0) {
4200 BLayoutItem
* item
= fLayoutData
->fLayoutItems
.ItemAt(index
);
4202 // Removes item from fLayoutItems list
4210 BView::Parent() const
4212 if (fParent
&& fParent
->fTopLevelView
)
4220 BView::FindView(const char* name
) const
4225 if (Name() != NULL
&& !strcmp(Name(), name
))
4226 return const_cast<BView
*>(this);
4228 BView
* child
= fFirstChild
;
4229 while (child
!= NULL
) {
4230 BView
* view
= child
->FindView(name
);
4234 child
= child
->fNextSibling
;
4242 BView::MoveBy(float deltaX
, float deltaY
)
4244 MoveTo(fParentOffset
.x
+ roundf(deltaX
), fParentOffset
.y
+ roundf(deltaY
));
4249 BView::MoveTo(BPoint where
)
4251 MoveTo(where
.x
, where
.y
);
4256 BView::MoveTo(float x
, float y
)
4258 if (x
== fParentOffset
.x
&& y
== fParentOffset
.y
)
4261 // BeBook says we should do this. And it makes sense.
4266 _CheckLockAndSwitchCurrent();
4267 fOwner
->fLink
->StartMessage(AS_VIEW_MOVE_TO
);
4268 fOwner
->fLink
->Attach
<float>(x
);
4269 fOwner
->fLink
->Attach
<float>(y
);
4271 // fState->valid_flags |= B_VIEW_FRAME_BIT;
4273 _FlushIfNotInTransaction();
4276 _MoveTo((int32
)x
, (int32
)y
);
4281 BView::ResizeBy(float deltaWidth
, float deltaHeight
)
4283 // BeBook says we should do this. And it makes sense.
4284 deltaWidth
= roundf(deltaWidth
);
4285 deltaHeight
= roundf(deltaHeight
);
4287 if (deltaWidth
== 0 && deltaHeight
== 0)
4291 _CheckLockAndSwitchCurrent();
4292 fOwner
->fLink
->StartMessage(AS_VIEW_RESIZE_TO
);
4294 fOwner
->fLink
->Attach
<float>(fBounds
.Width() + deltaWidth
);
4295 fOwner
->fLink
->Attach
<float>(fBounds
.Height() + deltaHeight
);
4297 // fState->valid_flags |= B_VIEW_FRAME_BIT;
4299 _FlushIfNotInTransaction();
4302 _ResizeBy((int32
)deltaWidth
, (int32
)deltaHeight
);
4307 BView::ResizeTo(float width
, float height
)
4309 ResizeBy(width
- fBounds
.Width(), height
- fBounds
.Height());
4314 BView::ResizeTo(BSize size
)
4316 ResizeBy(size
.width
- fBounds
.Width(), size
.height
- fBounds
.Height());
4320 // #pragma mark - Inherited Methods (from BHandler)
4324 BView::GetSupportedSuites(BMessage
* data
)
4329 status_t status
= data
->AddString("suites", "suite/vnd.Be-view");
4330 BPropertyInfo
propertyInfo(sViewPropInfo
);
4332 status
= data
->AddFlat("messages", &propertyInfo
);
4334 return BHandler::GetSupportedSuites(data
);
4340 BView::ResolveSpecifier(BMessage
* message
, int32 index
, BMessage
* specifier
,
4341 int32 what
, const char* property
)
4343 if (message
->what
== B_WINDOW_MOVE_BY
4344 || message
->what
== B_WINDOW_MOVE_TO
) {
4348 BPropertyInfo
propertyInfo(sViewPropInfo
);
4349 status_t err
= B_BAD_SCRIPT_SYNTAX
;
4350 BMessage
replyMsg(B_REPLY
);
4352 switch (propertyInfo
.FindMatch(message
, index
, specifier
, what
, property
)) {
4360 message
->PopSpecifier();
4364 err
= B_NAME_NOT_FOUND
;
4365 replyMsg
.AddString("message", "This window doesn't have a shelf");
4371 err
= B_NAME_NOT_FOUND
;
4372 replyMsg
.AddString("message", "This window doesn't have "
4376 BView
* child
= NULL
;
4378 case B_INDEX_SPECIFIER
:
4381 err
= specifier
->FindInt32("index", &index
);
4383 child
= ChildAt(index
);
4386 case B_REVERSE_INDEX_SPECIFIER
:
4389 err
= specifier
->FindInt32("index", &rindex
);
4391 child
= ChildAt(CountChildren() - rindex
);
4394 case B_NAME_SPECIFIER
:
4397 err
= specifier
->FindString("name", &name
);
4399 child
= FindView(name
);
4404 if (child
!= NULL
) {
4405 message
->PopSpecifier();
4412 replyMsg
.AddString("message",
4413 "Cannot find view at/with specified index/name.");
4418 return BHandler::ResolveSpecifier(message
, index
, specifier
, what
,
4423 replyMsg
.what
= B_MESSAGE_NOT_UNDERSTOOD
;
4425 if (err
== B_BAD_SCRIPT_SYNTAX
)
4426 replyMsg
.AddString("message", "Didn't understand the specifier(s)");
4428 replyMsg
.AddString("message", strerror(err
));
4431 replyMsg
.AddInt32("error", err
);
4432 message
->SendReply(&replyMsg
);
4438 BView::MessageReceived(BMessage
* message
)
4440 if (!message
->HasSpecifiers()) {
4441 switch (message
->what
) {
4442 case B_VIEW_RESIZED
:
4443 // By the time the message arrives, the bounds may have
4444 // changed already, that's why we don't use the values
4445 // in the message itself.
4446 FrameResized(fBounds
.Width(), fBounds
.Height());
4450 FrameMoved(fParentOffset
);
4456 if (message
->FindPoint("be:view_where", &where
) != B_OK
)
4460 if (GetToolTipAt(where
, &tip
))
4463 BHandler::MessageReceived(message
);
4467 case B_MOUSE_WHEEL_CHANGED
:
4469 BScrollBar
* horizontal
= ScrollBar(B_HORIZONTAL
);
4470 BScrollBar
* vertical
= ScrollBar(B_VERTICAL
);
4471 if (horizontal
== NULL
&& vertical
== NULL
) {
4472 // Pass the message to the next handler
4473 BHandler::MessageReceived(message
);
4477 float deltaX
= 0.0f
;
4478 float deltaY
= 0.0f
;
4480 if (horizontal
!= NULL
)
4481 message
->FindFloat("be:wheel_delta_x", &deltaX
);
4483 if (vertical
!= NULL
)
4484 message
->FindFloat("be:wheel_delta_y", &deltaY
);
4486 if (deltaX
== 0.0f
&& deltaY
== 0.0f
)
4489 if ((modifiers() & B_CONTROL_KEY
) != 0)
4490 std::swap(horizontal
, vertical
);
4492 if (horizontal
!= NULL
&& deltaX
!= 0.0f
)
4493 ScrollWithMouseWheelDelta(horizontal
, deltaX
);
4495 if (vertical
!= NULL
&& deltaY
!= 0.0f
)
4496 ScrollWithMouseWheelDelta(vertical
, deltaY
);
4502 BHandler::MessageReceived(message
);
4509 // Scripting message
4511 BMessage
replyMsg(B_REPLY
);
4512 status_t err
= B_BAD_SCRIPT_SYNTAX
;
4516 const char* property
;
4518 if (message
->GetCurrentSpecifier(&index
, &specifier
, &what
, &property
)
4520 return BHandler::MessageReceived(message
);
4523 BPropertyInfo
propertyInfo(sViewPropInfo
);
4524 switch (propertyInfo
.FindMatch(message
, index
, &specifier
, what
,
4527 if (message
->what
== B_GET_PROPERTY
) {
4528 err
= replyMsg
.AddRect("result", Frame());
4529 } else if (message
->what
== B_SET_PROPERTY
) {
4531 err
= message
->FindRect("data", &newFrame
);
4533 MoveTo(newFrame
.LeftTop());
4534 ResizeTo(newFrame
.Width(), newFrame
.Height());
4539 if (message
->what
== B_GET_PROPERTY
) {
4540 err
= replyMsg
.AddBool("result", IsHidden());
4541 } else if (message
->what
== B_SET_PROPERTY
) {
4542 bool newHiddenState
;
4543 err
= message
->FindBool("data", &newHiddenState
);
4545 if (newHiddenState
== true)
4553 err
= replyMsg
.AddInt32("result", CountChildren());
4556 return BHandler::MessageReceived(message
);
4560 replyMsg
.what
= B_MESSAGE_NOT_UNDERSTOOD
;
4562 if (err
== B_BAD_SCRIPT_SYNTAX
)
4563 replyMsg
.AddString("message", "Didn't understand the specifier(s)");
4565 replyMsg
.AddString("message", strerror(err
));
4567 replyMsg
.AddInt32("error", err
);
4570 message
->SendReply(&replyMsg
);
4575 BView::Perform(perform_code code
, void* _data
)
4578 case PERFORM_CODE_MIN_SIZE
:
4579 ((perform_data_min_size
*)_data
)->return_value
4582 case PERFORM_CODE_MAX_SIZE
:
4583 ((perform_data_max_size
*)_data
)->return_value
4586 case PERFORM_CODE_PREFERRED_SIZE
:
4587 ((perform_data_preferred_size
*)_data
)->return_value
4588 = BView::PreferredSize();
4590 case PERFORM_CODE_LAYOUT_ALIGNMENT
:
4591 ((perform_data_layout_alignment
*)_data
)->return_value
4592 = BView::LayoutAlignment();
4594 case PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH
:
4595 ((perform_data_has_height_for_width
*)_data
)->return_value
4596 = BView::HasHeightForWidth();
4598 case PERFORM_CODE_GET_HEIGHT_FOR_WIDTH
:
4600 perform_data_get_height_for_width
* data
4601 = (perform_data_get_height_for_width
*)_data
;
4602 BView::GetHeightForWidth(data
->width
, &data
->min
, &data
->max
,
4606 case PERFORM_CODE_SET_LAYOUT
:
4608 perform_data_set_layout
* data
= (perform_data_set_layout
*)_data
;
4609 BView::SetLayout(data
->layout
);
4612 case PERFORM_CODE_LAYOUT_INVALIDATED
:
4614 perform_data_layout_invalidated
* data
4615 = (perform_data_layout_invalidated
*)_data
;
4616 BView::LayoutInvalidated(data
->descendants
);
4619 case PERFORM_CODE_DO_LAYOUT
:
4624 case PERFORM_CODE_LAYOUT_CHANGED
:
4626 BView::LayoutChanged();
4629 case PERFORM_CODE_GET_TOOL_TIP_AT
:
4631 perform_data_get_tool_tip_at
* data
4632 = (perform_data_get_tool_tip_at
*)_data
;
4634 = BView::GetToolTipAt(data
->point
, data
->tool_tip
);
4637 case PERFORM_CODE_ALL_UNARCHIVED
:
4639 perform_data_all_unarchived
* data
=
4640 (perform_data_all_unarchived
*)_data
;
4642 data
->return_value
= BView::AllUnarchived(data
->archive
);
4645 case PERFORM_CODE_ALL_ARCHIVED
:
4647 perform_data_all_archived
* data
=
4648 (perform_data_all_archived
*)_data
;
4650 data
->return_value
= BView::AllArchived(data
->archive
);
4655 return BHandler::Perform(code
, _data
);
4659 // #pragma mark - Layout Functions
4665 // TODO: make sure this works correctly when some methods are overridden
4666 float width
, height
;
4667 GetPreferredSize(&width
, &height
);
4669 return BLayoutUtils::ComposeSize(fLayoutData
->fMinSize
,
4670 (fLayoutData
->fLayout
? fLayoutData
->fLayout
->MinSize()
4671 : BSize(width
, height
)));
4678 return BLayoutUtils::ComposeSize(fLayoutData
->fMaxSize
,
4679 (fLayoutData
->fLayout
? fLayoutData
->fLayout
->MaxSize()
4680 : BSize(B_SIZE_UNLIMITED
, B_SIZE_UNLIMITED
)));
4685 BView::PreferredSize()
4687 // TODO: make sure this works correctly when some methods are overridden
4688 float width
, height
;
4689 GetPreferredSize(&width
, &height
);
4691 return BLayoutUtils::ComposeSize(fLayoutData
->fPreferredSize
,
4692 (fLayoutData
->fLayout
? fLayoutData
->fLayout
->PreferredSize()
4693 : BSize(width
, height
)));
4698 BView::LayoutAlignment()
4700 return BLayoutUtils::ComposeAlignment(fLayoutData
->fAlignment
,
4701 (fLayoutData
->fLayout
? fLayoutData
->fLayout
->Alignment()
4702 : BAlignment(B_ALIGN_HORIZONTAL_CENTER
, B_ALIGN_VERTICAL_CENTER
)));
4707 BView::SetExplicitMinSize(BSize size
)
4709 fLayoutData
->fMinSize
= size
;
4715 BView::SetExplicitMaxSize(BSize size
)
4717 fLayoutData
->fMaxSize
= size
;
4723 BView::SetExplicitPreferredSize(BSize size
)
4725 fLayoutData
->fPreferredSize
= size
;
4731 BView::SetExplicitSize(BSize size
)
4733 fLayoutData
->fMinSize
= size
;
4734 fLayoutData
->fMaxSize
= size
;
4735 fLayoutData
->fPreferredSize
= size
;
4741 BView::SetExplicitAlignment(BAlignment alignment
)
4743 fLayoutData
->fAlignment
= alignment
;
4749 BView::ExplicitMinSize() const
4751 return fLayoutData
->fMinSize
;
4756 BView::ExplicitMaxSize() const
4758 return fLayoutData
->fMaxSize
;
4763 BView::ExplicitPreferredSize() const
4765 return fLayoutData
->fPreferredSize
;
4770 BView::ExplicitAlignment() const
4772 return fLayoutData
->fAlignment
;
4777 BView::HasHeightForWidth()
4779 return (fLayoutData
->fLayout
4780 ? fLayoutData
->fLayout
->HasHeightForWidth() : false);
4785 BView::GetHeightForWidth(float width
, float* min
, float* max
, float* preferred
)
4787 if (fLayoutData
->fLayout
)
4788 fLayoutData
->fLayout
->GetHeightForWidth(width
, min
, max
, preferred
);
4793 BView::SetLayout(BLayout
* layout
)
4795 if (layout
== fLayoutData
->fLayout
)
4798 if (layout
&& layout
->Layout())
4799 debugger("BView::SetLayout() failed, layout is already in use.");
4801 fFlags
|= B_SUPPORTS_LAYOUT
;
4803 // unset and delete the old layout
4804 if (fLayoutData
->fLayout
) {
4805 fLayoutData
->fLayout
->RemoveSelf();
4806 fLayoutData
->fLayout
->SetOwner(NULL
);
4807 delete fLayoutData
->fLayout
;
4810 fLayoutData
->fLayout
= layout
;
4812 if (fLayoutData
->fLayout
) {
4813 fLayoutData
->fLayout
->SetOwner(this);
4816 int count
= CountChildren();
4817 for (int i
= 0; i
< count
; i
++)
4818 fLayoutData
->fLayout
->AddView(ChildAt(i
));
4826 BView::GetLayout() const
4828 return fLayoutData
->fLayout
;
4833 BView::InvalidateLayout(bool descendants
)
4835 // printf("BView(%p)::InvalidateLayout(%i), valid: %i, inProgress: %i\n",
4836 // this, descendants, fLayoutData->fLayoutValid,
4837 // fLayoutData->fLayoutInProgress);
4839 if (!fLayoutData
->fMinMaxValid
|| fLayoutData
->fLayoutInProgress
4840 || fLayoutData
->fLayoutInvalidationDisabled
> 0) {
4844 fLayoutData
->fLayoutValid
= false;
4845 fLayoutData
->fMinMaxValid
= false;
4846 LayoutInvalidated(descendants
);
4849 for (BView
* child
= fFirstChild
;
4850 child
; child
= child
->fNextSibling
) {
4851 child
->InvalidateLayout(descendants
);
4855 if (fLayoutData
->fLayout
)
4856 fLayoutData
->fLayout
->InvalidateLayout(descendants
);
4858 _InvalidateParentLayout();
4860 if (fTopLevelView
&& fOwner
)
4861 fOwner
->PostMessage(B_LAYOUT_WINDOW
);
4866 BView::EnableLayoutInvalidation()
4868 if (fLayoutData
->fLayoutInvalidationDisabled
> 0)
4869 fLayoutData
->fLayoutInvalidationDisabled
--;
4874 BView::DisableLayoutInvalidation()
4876 fLayoutData
->fLayoutInvalidationDisabled
++;
4881 BView::IsLayoutInvalidationDisabled()
4883 if (fLayoutData
->fLayoutInvalidationDisabled
> 0)
4890 BView::IsLayoutValid() const
4892 return fLayoutData
->fLayoutValid
;
4897 BView::ResetLayoutInvalidation()
4899 fLayoutData
->fMinMaxValid
= true;
4904 BView::LayoutContext() const
4906 return fLayoutData
->fLayoutContext
;
4911 BView::Layout(bool force
)
4913 BLayoutContext context
;
4914 _Layout(force
, &context
);
4921 if (fLayoutData
->fLayoutValid
&& !fLayoutData
->fLayoutInProgress
) {
4922 fLayoutData
->fNeedsRelayout
= true;
4923 if (fLayoutData
->fLayout
)
4924 fLayoutData
->fLayout
->RequireLayout();
4926 // Layout() is recursive, that is if the parent view is currently laid
4927 // out, we don't call layout() on this view, but wait for the parent's
4928 // Layout() to do that for us.
4929 if (!fParent
|| !fParent
->fLayoutData
->fLayoutInProgress
)
4936 BView::LayoutInvalidated(bool descendants
)
4945 if (fLayoutData
->fLayout
)
4946 fLayoutData
->fLayout
->_LayoutWithinContext(false, LayoutContext());
4951 BView::SetToolTip(const char* text
)
4953 if (text
== NULL
|| text
[0] == '\0') {
4954 SetToolTip((BToolTip
*)NULL
);
4958 if (BTextToolTip
* tip
= dynamic_cast<BTextToolTip
*>(fToolTip
))
4961 SetToolTip(new BTextToolTip(text
));
4966 BView::SetToolTip(BToolTip
* tip
)
4968 if (fToolTip
== tip
)
4970 else if (tip
== NULL
)
4973 if (fToolTip
!= NULL
)
4974 fToolTip
->ReleaseReference();
4978 if (fToolTip
!= NULL
)
4979 fToolTip
->AcquireReference();
4984 BView::ToolTip() const
4991 BView::ShowToolTip(BToolTip
* tip
)
4997 GetMouse(&where
, NULL
, false);
4999 BToolTipManager::Manager()->ShowTip(tip
, ConvertToScreen(where
), this);
5004 BView::HideToolTip()
5006 BToolTipManager::Manager()->HideTip();
5011 BView::GetToolTipAt(BPoint point
, BToolTip
** _tip
)
5013 if (fToolTip
!= NULL
) {
5024 BView::LayoutChanged()
5031 BView::_Layout(bool force
, BLayoutContext
* context
)
5033 //printf("%p->BView::_Layout(%d, %p)\n", this, force, context);
5034 //printf(" fNeedsRelayout: %d, fLayoutValid: %d, fLayoutInProgress: %d\n",
5035 //fLayoutData->fNeedsRelayout, fLayoutData->fLayoutValid,
5036 //fLayoutData->fLayoutInProgress);
5037 if (fLayoutData
->fNeedsRelayout
|| !fLayoutData
->fLayoutValid
|| force
) {
5038 fLayoutData
->fLayoutValid
= false;
5040 if (fLayoutData
->fLayoutInProgress
)
5043 BLayoutContext
* oldContext
= fLayoutData
->fLayoutContext
;
5044 fLayoutData
->fLayoutContext
= context
;
5046 fLayoutData
->fLayoutInProgress
= true;
5048 fLayoutData
->fLayoutInProgress
= false;
5050 fLayoutData
->fLayoutValid
= true;
5051 fLayoutData
->fMinMaxValid
= true;
5052 fLayoutData
->fNeedsRelayout
= false;
5055 for(BView
* child
= fFirstChild
; child
; child
= child
->fNextSibling
) {
5056 if (!child
->IsHidden(child
))
5057 child
->_Layout(force
, context
);
5062 fLayoutData
->fLayoutContext
= oldContext
;
5064 // invalidate the drawn content, if requested
5065 if (fFlags
& B_INVALIDATE_AFTER_LAYOUT
)
5072 BView::_LayoutLeft(BLayout
* deleted
)
5074 // If our layout is added to another layout (via BLayout::AddItem())
5075 // then we share ownership of our layout. In the event that our layout gets
5076 // deleted by the layout it has been added to, this method is called so
5077 // that we don't double-delete our layout.
5078 if (fLayoutData
->fLayout
== deleted
)
5079 fLayoutData
->fLayout
= NULL
;
5085 BView::_InvalidateParentLayout()
5090 BLayout
* layout
= fLayoutData
->fLayout
;
5091 BLayout
* layoutParent
= layout
? layout
->Layout() : NULL
;
5093 layoutParent
->InvalidateLayout();
5094 } else if (fLayoutData
->fLayoutItems
.CountItems() > 0) {
5095 int32 count
= fLayoutData
->fLayoutItems
.CountItems();
5096 for (int32 i
= 0; i
< count
; i
++) {
5097 fLayoutData
->fLayoutItems
.ItemAt(i
)->Layout()->InvalidateLayout();
5100 fParent
->InvalidateLayout();
5105 // #pragma mark - Private Functions
5109 BView::_InitData(BRect frame
, const char* name
, uint32 resizingMode
,
5112 // Info: The name of the view is set by BHandler constructor
5114 STRACE(("BView::_InitData: enter\n"));
5116 // initialize members
5117 if ((resizingMode
& ~_RESIZE_MASK_
) || (flags
& _RESIZE_MASK_
))
5118 printf("%s BView::_InitData(): resizing mode or flags swapped\n", name
);
5120 // There are applications that swap the resize mask and the flags in the
5121 // BView constructor. This does not cause problems under BeOS as it just
5122 // ors the two fields to one 32bit flag.
5123 // For now we do the same but print the above warning message.
5124 // TODO: this should be removed at some point and the original
5125 // version restored:
5126 // fFlags = (resizingMode & _RESIZE_MASK_) | (flags & ~_RESIZE_MASK_);
5127 fFlags
= resizingMode
| flags
;
5130 frame
.left
= roundf(frame
.left
);
5131 frame
.top
= roundf(frame
.top
);
5132 frame
.right
= roundf(frame
.right
);
5133 frame
.bottom
= roundf(frame
.bottom
);
5135 fParentOffset
.Set(frame
.left
, frame
.top
);
5139 fNextSibling
= NULL
;
5140 fPreviousSibling
= NULL
;
5144 fTopLevelView
= false;
5146 fCurrentPicture
= NULL
;
5149 fVerScroller
= NULL
;
5150 fHorScroller
= NULL
;
5152 fIsPrinting
= false;
5155 // TODO: Since we cannot communicate failure, we don't use std::nothrow here
5156 // TODO: Maybe we could auto-delete those views on AddChild() instead?
5157 fState
= new BPrivate::ViewState
;
5159 fBounds
= frame
.OffsetToCopy(B_ORIGIN
);
5164 fMouseEventOptions
= 0;
5166 fLayoutData
= new LayoutData
;
5173 BView::_RemoveCommArray()
5176 delete [] fCommArray
->array
;
5184 BView::_SetOwner(BWindow
* newOwner
)
5189 if (fOwner
!= newOwner
&& fOwner
) {
5190 if (fOwner
->fFocus
== this)
5193 if (fOwner
->fLastMouseMovedView
== this)
5194 fOwner
->fLastMouseMovedView
= NULL
;
5196 fOwner
->RemoveHandler(this);
5198 fOwner
->RemoveHandler(fShelf
);
5201 if (newOwner
&& newOwner
!= fOwner
) {
5202 newOwner
->AddHandler(this);
5204 newOwner
->AddHandler(fShelf
);
5207 SetNextHandler(newOwner
);
5209 SetNextHandler(fParent
);
5214 for (BView
* child
= fFirstChild
; child
!= NULL
; child
= child
->fNextSibling
)
5215 child
->_SetOwner(newOwner
);
5220 BView::_ClipToPicture(BPicture
* picture
, BPoint where
, bool invert
, bool sync
)
5222 if (!_CheckOwnerLockAndSwitchCurrent())
5225 if (picture
== NULL
) {
5226 fOwner
->fLink
->StartMessage(AS_VIEW_CLIP_TO_PICTURE
);
5227 fOwner
->fLink
->Attach
<int32
>(-1);
5229 // NOTE: No need to sync here, since the -1 token cannot
5230 // become invalid on the server.
5232 fOwner
->fLink
->StartMessage(AS_VIEW_CLIP_TO_PICTURE
);
5233 fOwner
->fLink
->Attach
<int32
>(picture
->Token());
5234 fOwner
->fLink
->Attach
<BPoint
>(where
);
5235 fOwner
->fLink
->Attach
<bool>(invert
);
5237 // NOTE: "sync" defaults to true in public methods. If you know what
5238 // you are doing, i.e. if you know your BPicture stays valid, you
5239 // can avoid the performance impact of syncing. In a use-case where
5240 // the client creates BPictures on the stack, these BPictures may
5241 // have issued a AS_DELETE_PICTURE command to the ServerApp when Draw()
5242 // goes out of scope, and the command is processed earlier in the
5243 // ServerApp thread than the AS_VIEW_CLIP_TO_PICTURE command in the
5244 // ServerWindow thread, which will then have the result that no
5245 // ServerPicture is found of the token.
5253 BView::_RemoveChildFromList(BView
* child
)
5255 if (child
->fParent
!= this)
5258 if (fFirstChild
== child
) {
5259 // it's the first view in the list
5260 fFirstChild
= child
->fNextSibling
;
5262 // there must be a previous sibling
5263 child
->fPreviousSibling
->fNextSibling
= child
->fNextSibling
;
5266 if (child
->fNextSibling
)
5267 child
->fNextSibling
->fPreviousSibling
= child
->fPreviousSibling
;
5269 child
->fParent
= NULL
;
5270 child
->fNextSibling
= NULL
;
5271 child
->fPreviousSibling
= NULL
;
5278 BView::_AddChildToList(BView
* child
, BView
* before
)
5282 if (child
->fParent
!= NULL
) {
5283 debugger("View already belongs to someone else");
5286 if (before
!= NULL
&& before
->fParent
!= this) {
5287 debugger("Invalid before view");
5291 if (before
!= NULL
) {
5292 // add view before this one
5293 child
->fNextSibling
= before
;
5294 child
->fPreviousSibling
= before
->fPreviousSibling
;
5295 if (child
->fPreviousSibling
!= NULL
)
5296 child
->fPreviousSibling
->fNextSibling
= child
;
5298 before
->fPreviousSibling
= child
;
5299 if (fFirstChild
== before
)
5300 fFirstChild
= child
;
5302 // add view to the end of the list
5303 BView
* last
= fFirstChild
;
5304 while (last
!= NULL
&& last
->fNextSibling
!= NULL
) {
5305 last
= last
->fNextSibling
;
5309 last
->fNextSibling
= child
;
5310 child
->fPreviousSibling
= last
;
5312 fFirstChild
= child
;
5313 child
->fPreviousSibling
= NULL
;
5316 child
->fNextSibling
= NULL
;
5319 child
->fParent
= this;
5324 /*! \brief Creates the server counterpart of this view.
5325 This is only done for views that are part of the view hierarchy, ie. when
5326 they are attached to a window.
5327 RemoveSelf() deletes the server object again.
5330 BView::_CreateSelf()
5332 // AS_VIEW_CREATE & AS_VIEW_CREATE_ROOT do not use the
5333 // current view mechanism via _CheckLockAndSwitchCurrent() - the token
5334 // of the view and its parent are both send to the server.
5337 fOwner
->fLink
->StartMessage(AS_VIEW_CREATE_ROOT
);
5339 fOwner
->fLink
->StartMessage(AS_VIEW_CREATE
);
5341 fOwner
->fLink
->Attach
<int32
>(_get_object_token_(this));
5342 fOwner
->fLink
->AttachString(Name());
5343 fOwner
->fLink
->Attach
<BRect
>(Frame());
5344 fOwner
->fLink
->Attach
<BPoint
>(LeftTop());
5345 fOwner
->fLink
->Attach
<uint32
>(ResizingMode());
5346 fOwner
->fLink
->Attach
<uint32
>(fEventMask
);
5347 fOwner
->fLink
->Attach
<uint32
>(fEventOptions
);
5348 fOwner
->fLink
->Attach
<uint32
>(Flags());
5349 fOwner
->fLink
->Attach
<bool>(IsHidden(this));
5350 fOwner
->fLink
->Attach
<rgb_color
>(fState
->view_color
);
5352 fOwner
->fLink
->Attach
<int32
>(B_NULL_TOKEN
);
5354 fOwner
->fLink
->Attach
<int32
>(_get_object_token_(fParent
));
5355 fOwner
->fLink
->Flush();
5357 _CheckOwnerLockAndSwitchCurrent();
5358 fState
->UpdateServerState(*fOwner
->fLink
);
5360 // we create all its children, too
5362 for (BView
* child
= fFirstChild
; child
!= NULL
;
5363 child
= child
->fNextSibling
) {
5364 child
->_CreateSelf();
5367 fOwner
->fLink
->Flush();
5372 /*! Sets the new view position.
5373 It doesn't contact the server, though - the only case where this
5374 is called outside of MoveTo() is as reaction of moving a view
5375 in the server (a.k.a. B_WINDOW_RESIZED).
5376 It also calls the BView's FrameMoved() hook.
5379 BView::_MoveTo(int32 x
, int32 y
)
5381 fParentOffset
.Set(x
, y
);
5383 if (Window() != NULL
&& fFlags
& B_FRAME_EVENTS
) {
5384 BMessage
moved(B_VIEW_MOVED
);
5385 moved
.AddInt64("when", system_time());
5386 moved
.AddPoint("where", BPoint(x
, y
));
5388 BMessenger
target(this);
5389 target
.SendMessage(&moved
);
5394 /*! Computes the actual new frame size and recalculates the size of
5395 the children as well.
5396 It doesn't contact the server, though - the only case where this
5397 is called outside of ResizeBy() is as reaction of resizing a view
5398 in the server (a.k.a. B_WINDOW_RESIZED).
5399 It also calls the BView's FrameResized() hook.
5402 BView::_ResizeBy(int32 deltaWidth
, int32 deltaHeight
)
5404 fBounds
.right
+= deltaWidth
;
5405 fBounds
.bottom
+= deltaHeight
;
5407 if (Window() == NULL
) {
5408 // we're not supposed to exercise the resizing code in case
5409 // we haven't been attached to a window yet
5413 // layout the children
5414 if (fFlags
& B_SUPPORTS_LAYOUT
) {
5417 for (BView
* child
= fFirstChild
; child
; child
= child
->fNextSibling
)
5418 child
->_ParentResizedBy(deltaWidth
, deltaHeight
);
5421 if (fFlags
& B_FRAME_EVENTS
) {
5422 BMessage
resized(B_VIEW_RESIZED
);
5423 resized
.AddInt64("when", system_time());
5424 resized
.AddInt32("width", fBounds
.IntegerWidth());
5425 resized
.AddInt32("height", fBounds
.IntegerHeight());
5427 BMessenger
target(this);
5428 target
.SendMessage(&resized
);
5433 /*! Relayouts the view according to its resizing mode. */
5435 BView::_ParentResizedBy(int32 x
, int32 y
)
5437 uint32 resizingMode
= fFlags
& _RESIZE_MASK_
;
5438 BRect newFrame
= Frame();
5440 // follow with left side
5441 if ((resizingMode
& 0x0F00U
) == _VIEW_RIGHT_
<< 8)
5443 else if ((resizingMode
& 0x0F00U
) == _VIEW_CENTER_
<< 8)
5444 newFrame
.left
+= x
/ 2;
5446 // follow with right side
5447 if ((resizingMode
& 0x000FU
) == _VIEW_RIGHT_
)
5448 newFrame
.right
+= x
;
5449 else if ((resizingMode
& 0x000FU
) == _VIEW_CENTER_
)
5450 newFrame
.right
+= x
/ 2;
5452 // follow with top side
5453 if ((resizingMode
& 0xF000U
) == _VIEW_BOTTOM_
<< 12)
5455 else if ((resizingMode
& 0xF000U
) == _VIEW_CENTER_
<< 12)
5456 newFrame
.top
+= y
/ 2;
5458 // follow with bottom side
5459 if ((resizingMode
& 0x00F0U
) == _VIEW_BOTTOM_
<< 4)
5460 newFrame
.bottom
+= y
;
5461 else if ((resizingMode
& 0x00F0U
) == _VIEW_CENTER_
<< 4)
5462 newFrame
.bottom
+= y
/ 2;
5464 if (newFrame
.LeftTop() != fParentOffset
) {
5466 _MoveTo((int32
)roundf(newFrame
.left
), (int32
)roundf(newFrame
.top
));
5469 if (newFrame
!= Frame()) {
5471 int32 widthDiff
= (int32
)(newFrame
.Width() - fBounds
.Width());
5472 int32 heightDiff
= (int32
)(newFrame
.Height() - fBounds
.Height());
5473 _ResizeBy(widthDiff
, heightDiff
);
5479 BView::_Activate(bool active
)
5481 WindowActivated(active
);
5483 for (BView
* child
= fFirstChild
; child
!= NULL
;
5484 child
= child
->fNextSibling
) {
5485 child
->_Activate(active
);
5496 // after giving the view a chance to do this itself,
5497 // check for the B_PULSE_NEEDED flag and make sure the
5498 // window set's up the pulse messaging
5500 if (fFlags
& B_PULSE_NEEDED
) {
5502 if (fOwner
->fPulseRunner
== NULL
)
5503 fOwner
->SetPulseRate(fOwner
->PulseRate());
5506 if (!fOwner
->IsHidden())
5510 for (BView
* child
= fFirstChild
; child
!= NULL
;
5511 child
= child
->fNextSibling
) {
5512 // we need to check for fAttached as new views could have been
5513 // added in AttachedToWindow() - and those are already attached
5514 if (!child
->fAttached
)
5525 DetachedFromWindow();
5528 for (BView
* child
= fFirstChild
; child
!= NULL
;
5529 child
= child
->fNextSibling
) {
5538 if (!fOwner
->IsHidden())
5541 // make sure our owner doesn't need us anymore
5543 if (fOwner
->CurrentFocus() == this) {
5545 // MakeFocus() is virtual and might not be
5546 // passing through to the BView version,
5547 // but we need to make sure at this point
5548 // that we are not the focus view anymore.
5549 if (fOwner
->CurrentFocus() == this)
5550 fOwner
->_SetFocus(NULL
, true);
5553 if (fOwner
->fDefaultButton
== this)
5554 fOwner
->SetDefaultButton(NULL
);
5556 if (fOwner
->fKeyMenuBar
== this)
5557 fOwner
->fKeyMenuBar
= NULL
;
5559 if (fOwner
->fLastMouseMovedView
== this)
5560 fOwner
->fLastMouseMovedView
= NULL
;
5562 if (fOwner
->fLastViewToken
== _get_object_token_(this))
5563 fOwner
->fLastViewToken
= B_NULL_TOKEN
;
5571 BView::_Draw(BRect updateRect
)
5573 if (IsHidden(this) || !(Flags() & B_WILL_DRAW
))
5576 // NOTE: if ViewColor() == B_TRANSPARENT_COLOR and no B_WILL_DRAW
5577 // -> View is simply not drawn at all
5579 _SwitchServerCurrentView();
5581 ConvertFromScreen(&updateRect
);
5583 // TODO: make states robust (the hook implementation could
5584 // mess things up if it uses non-matching Push- and PopState(),
5585 // we would not be guaranteed to still have the same state on
5586 // the stack after having called Draw())
5595 BView::_DrawAfterChildren(BRect updateRect
)
5597 if (IsHidden(this) || !(Flags() & B_WILL_DRAW
)
5598 || !(Flags() & B_DRAW_ON_CHILDREN
))
5601 _SwitchServerCurrentView();
5603 ConvertFromScreen(&updateRect
);
5605 // TODO: make states robust (see above)
5607 DrawAfterChildren(updateRect
);
5616 if ((Flags() & B_PULSE_NEEDED
) != 0)
5619 for (BView
* child
= fFirstChild
; child
!= NULL
;
5620 child
= child
->fNextSibling
) {
5627 BView::_UpdateStateForRemove()
5629 // TODO: _CheckLockAndSwitchCurrent() would be good enough, no?
5630 if (!_CheckOwnerLockAndSwitchCurrent())
5633 fState
->UpdateFrom(*fOwner
->fLink
);
5634 // if (!fState->IsValid(B_VIEW_FRAME_BIT)) {
5635 // fOwner->fLink->StartMessage(AS_VIEW_GET_COORD);
5638 // if (fOwner->fLink->FlushWithReply(code) == B_OK
5639 // && code == B_OK) {
5640 // fOwner->fLink->Read<BPoint>(&fParentOffset);
5641 // fOwner->fLink->Read<BRect>(&fBounds);
5642 // fState->valid_flags |= B_VIEW_FRAME_BIT;
5646 // update children as well
5648 for (BView
* child
= fFirstChild
; child
!= NULL
;
5649 child
= child
->fNextSibling
) {
5651 child
->_UpdateStateForRemove();
5657 BView::_UpdatePattern(::pattern pattern
)
5659 if (fState
->IsValid(B_VIEW_PATTERN_BIT
) && pattern
== fState
->pattern
)
5663 _CheckLockAndSwitchCurrent();
5665 fOwner
->fLink
->StartMessage(AS_VIEW_SET_PATTERN
);
5666 fOwner
->fLink
->Attach
< ::pattern
>(pattern
);
5668 fState
->valid_flags
|= B_VIEW_PATTERN_BIT
;
5671 fState
->pattern
= pattern
;
5676 BView::_FlushIfNotInTransaction()
5678 if (!fOwner
->fInTransaction
) {
5685 BView::_Shelf() const
5692 BView::_SetShelf(BShelf
* shelf
)
5694 if (fShelf
!= NULL
&& fOwner
!= NULL
)
5695 fOwner
->RemoveHandler(fShelf
);
5699 if (fShelf
!= NULL
&& fOwner
!= NULL
)
5700 fOwner
->AddHandler(fShelf
);
5705 BView::_SetViewBitmap(const BBitmap
* bitmap
, BRect srcRect
, BRect dstRect
,
5706 uint32 followFlags
, uint32 options
)
5708 if (!_CheckOwnerLockAndSwitchCurrent())
5711 int32 serverToken
= bitmap
? bitmap
->_ServerToken() : -1;
5713 fOwner
->fLink
->StartMessage(AS_VIEW_SET_VIEW_BITMAP
);
5714 fOwner
->fLink
->Attach
<int32
>(serverToken
);
5715 fOwner
->fLink
->Attach
<BRect
>(srcRect
);
5716 fOwner
->fLink
->Attach
<BRect
>(dstRect
);
5717 fOwner
->fLink
->Attach
<int32
>(followFlags
);
5718 fOwner
->fLink
->Attach
<int32
>(options
);
5720 status_t status
= B_ERROR
;
5721 fOwner
->fLink
->FlushWithReply(status
);
5728 BView::_CheckOwnerLockAndSwitchCurrent() const
5730 STRACE(("BView(%s)::_CheckOwnerLockAndSwitchCurrent()\n", Name()));
5732 if (fOwner
== NULL
) {
5733 debugger("View method requires owner and doesn't have one.");
5737 _CheckLockAndSwitchCurrent();
5744 BView::_CheckOwnerLock() const
5747 fOwner
->check_lock();
5750 debugger("View method requires owner and doesn't have one.");
5757 BView::_CheckLockAndSwitchCurrent() const
5759 STRACE(("BView(%s)::_CheckLockAndSwitchCurrent()\n", Name()));
5764 fOwner
->check_lock();
5766 _SwitchServerCurrentView();
5771 BView::_CheckLock() const
5774 fOwner
->check_lock();
5779 BView::_SwitchServerCurrentView() const
5781 int32 serverToken
= _get_object_token_(this);
5783 if (fOwner
->fLastViewToken
!= serverToken
) {
5784 STRACE(("contacting app_server... sending token: %" B_PRId32
"\n",
5786 fOwner
->fLink
->StartMessage(AS_SET_CURRENT_VIEW
);
5787 fOwner
->fLink
->Attach
<int32
>(serverToken
);
5789 fOwner
->fLastViewToken
= serverToken
;
5795 BView::ScrollWithMouseWheelDelta(BScrollBar
* scrollBar
, float delta
)
5797 if (scrollBar
== NULL
|| delta
== 0.0f
)
5802 scrollBar
->GetSteps(&smallStep
, &largeStep
);
5804 // pressing the shift key scrolls faster (following the pseudo-standard set
5805 // by other desktop environments).
5806 if ((modifiers() & B_SHIFT_KEY
) != 0)
5809 delta
*= smallStep
* 3;
5811 scrollBar
->SetValue(scrollBar
->Value() + delta
);
5821 _ReservedView1__5BView(BView
* view
, BRect rect
)
5823 view
->BView::DrawAfterChildren(rect
);
5828 _ReservedView2__5BView(BView
* view
)
5831 perform_data_min_size data
;
5832 view
->Perform(PERFORM_CODE_MIN_SIZE
, &data
);
5837 _ReservedView3__5BView(BView
* view
)
5840 perform_data_max_size data
;
5841 view
->Perform(PERFORM_CODE_MAX_SIZE
, &data
);
5846 _ReservedView4__5BView(BView
* view
)
5849 perform_data_preferred_size data
;
5850 view
->Perform(PERFORM_CODE_PREFERRED_SIZE
, &data
);
5851 return data
.return_value
;
5855 extern "C" BAlignment
5856 _ReservedView5__5BView(BView
* view
)
5858 // LayoutAlignment()
5859 perform_data_layout_alignment data
;
5860 view
->Perform(PERFORM_CODE_LAYOUT_ALIGNMENT
, &data
);
5861 return data
.return_value
;
5866 _ReservedView6__5BView(BView
* view
)
5868 // HasHeightForWidth()
5869 perform_data_has_height_for_width data
;
5870 view
->Perform(PERFORM_CODE_HAS_HEIGHT_FOR_WIDTH
, &data
);
5871 return data
.return_value
;
5876 _ReservedView7__5BView(BView
* view
, float width
, float* min
, float* max
,
5879 // GetHeightForWidth()
5880 perform_data_get_height_for_width data
;
5882 view
->Perform(PERFORM_CODE_GET_HEIGHT_FOR_WIDTH
, &data
);
5887 if (preferred
!= NULL
)
5888 *preferred
= data
.preferred
;
5893 _ReservedView8__5BView(BView
* view
, BLayout
* layout
)
5896 perform_data_set_layout data
;
5897 data
.layout
= layout
;
5898 view
->Perform(PERFORM_CODE_SET_LAYOUT
, &data
);
5903 _ReservedView9__5BView(BView
* view
, bool descendants
)
5905 // LayoutInvalidated()
5906 perform_data_layout_invalidated data
;
5907 data
.descendants
= descendants
;
5908 view
->Perform(PERFORM_CODE_LAYOUT_INVALIDATED
, &data
);
5913 _ReservedView10__5BView(BView
* view
)
5916 view
->Perform(PERFORM_CODE_DO_LAYOUT
, NULL
);
5920 #endif // __GNUC__ == 2
5924 B_IF_GCC_2(_ReservedView11__5BView
, _ZN5BView15_ReservedView11Ev
)(
5925 BView
* view
, BPoint point
, BToolTip
** _toolTip
)
5928 perform_data_get_tool_tip_at data
;
5930 data
.tool_tip
= _toolTip
;
5931 view
->Perform(PERFORM_CODE_GET_TOOL_TIP_AT
, &data
);
5932 return data
.return_value
;
5937 B_IF_GCC_2(_ReservedView12__5BView
, _ZN5BView15_ReservedView12Ev
)(
5941 view
->Perform(PERFORM_CODE_LAYOUT_CHANGED
, NULL
);
5945 void BView::_ReservedView13() {}
5946 void BView::_ReservedView14() {}
5947 void BView::_ReservedView15() {}
5948 void BView::_ReservedView16() {}
5951 BView::BView(const BView
& other
)
5955 // this is private and not functional, but exported
5960 BView::operator=(const BView
& other
)
5962 // this is private and not functional, but exported
5968 BView::_PrintToStream()
5970 printf("BView::_PrintToStream()\n");
5971 printf("\tName: %s\n"
5973 "\tFirstChild: %s\n"
5974 "\tNextSibling: %s\n"
5975 "\tPrevSibling: %s\n"
5976 "\tOwner(Window): %s\n"
5977 "\tToken: %" B_PRId32
"\n"
5978 "\tFlags: %" B_PRId32
"\n"
5979 "\tView origin: (%f,%f)\n"
5980 "\tView Bounds rectangle: (%f,%f,%f,%f)\n"
5981 "\tShow level: %d\n"
5984 "\tVertical Scrollbar %s\n"
5985 "\tHorizontal Scrollbar %s\n"
5986 "\tIs Printing?: %s\n"
5988 "\tEventMask: %" B_PRId32
"\n"
5989 "\tEventOptions: %" B_PRId32
"\n",
5991 fParent
? fParent
->Name() : "NULL",
5992 fFirstChild
? fFirstChild
->Name() : "NULL",
5993 fNextSibling
? fNextSibling
->Name() : "NULL",
5994 fPreviousSibling
? fPreviousSibling
->Name() : "NULL",
5995 fOwner
? fOwner
->Name() : "NULL",
5996 _get_object_token_(this),
5998 fParentOffset
.x
, fParentOffset
.y
,
5999 fBounds
.left
, fBounds
.top
, fBounds
.right
, fBounds
.bottom
,
6001 fTopLevelView
? "YES" : "NO",
6002 fCurrentPicture
? "YES" : "NULL",
6003 fVerScroller
? "YES" : "NULL",
6004 fHorScroller
? "YES" : "NULL",
6005 fIsPrinting
? "YES" : "NO",
6006 fShelf
? "YES" : "NO",
6010 printf("\tState status:\n"
6011 "\t\tLocalCoordianteSystem: (%f,%f)\n"
6012 "\t\tPenLocation: (%f,%f)\n"
6014 "\t\tHighColor: [%d,%d,%d,%d]\n"
6015 "\t\tLowColor: [%d,%d,%d,%d]\n"
6016 "\t\tViewColor: [%d,%d,%d,%d]\n"
6017 "\t\tPattern: %" B_PRIx64
"\n"
6018 "\t\tDrawingMode: %d\n"
6019 "\t\tLineJoinMode: %d\n"
6020 "\t\tLineCapMode: %d\n"
6021 "\t\tMiterLimit: %f\n"
6022 "\t\tAlphaSource: %d\n"
6023 "\t\tAlphaFuntion: %d\n"
6025 "\t\t(Print)FontAliasing: %s\n"
6027 fState
->origin
.x
, fState
->origin
.y
,
6028 fState
->pen_location
.x
, fState
->pen_location
.y
,
6030 fState
->high_color
.red
, fState
->high_color
.blue
, fState
->high_color
.green
, fState
->high_color
.alpha
,
6031 fState
->low_color
.red
, fState
->low_color
.blue
, fState
->low_color
.green
, fState
->low_color
.alpha
,
6032 fState
->view_color
.red
, fState
->view_color
.blue
, fState
->view_color
.green
, fState
->view_color
.alpha
,
6033 *((uint64
*)&(fState
->pattern
)),
6034 fState
->drawing_mode
,
6037 fState
->miter_limit
,
6038 fState
->alpha_source_mode
,
6039 fState
->alpha_function_mode
,
6041 fState
->font_aliasing
? "YES" : "NO");
6043 fState
->font
.PrintToStream();
6045 // TODO: also print the line array.
6053 BView
* c
= fFirstChild
; //c = short for: current
6054 printf( "'%s'\n", Name() );
6059 for (int i
= 0; i
< spaces
; i
++)
6062 printf( "'%s'\n", c
->Name() );
6066 if (c
->fFirstChild
) {
6071 if (c
->fNextSibling
) {
6072 c
= c
->fNextSibling
;
6075 while (!c
->fParent
->fNextSibling
&& c
->fParent
!= this) {
6080 // that enough! We've reached this view.
6081 if (c
->fParent
== this)
6084 c
= c
->fParent
->fNextSibling
;
6097 BView::Private::LayoutItemAt(int32 index
)
6099 return fView
->fLayoutData
->fLayoutItems
.ItemAt(index
);
6104 BView::Private::CountLayoutItems()
6106 return fView
->fLayoutData
->fLayoutItems
.CountItems();
6111 BView::Private::RegisterLayoutItem(BLayoutItem
* item
)
6113 fView
->fLayoutData
->fLayoutItems
.AddItem(item
);
6118 BView::Private::DeregisterLayoutItem(BLayoutItem
* item
)
6120 fView
->fLayoutData
->fLayoutItems
.RemoveItem(item
);
6125 BView::Private::MinMaxValid()
6127 return fView
->fLayoutData
->fMinMaxValid
;
6132 BView::Private::WillLayout()
6134 BView::LayoutData
* data
= fView
->fLayoutData
;
6135 if (data
->fLayoutInProgress
)
6137 if (data
->fNeedsRelayout
|| !data
->fLayoutValid
|| !data
->fMinMaxValid
)