2 * Copyright 2010-2017, Haiku, Inc. All Rights Reserved.
3 * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
4 * Copyright 2004-2008, Michael Davidson. All Rights Reserved.
5 * Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
6 * Distributed under the terms of the MIT License.
9 * Michael Davidson, slaad@bong.com.au
10 * Mikael Eiman, mikael@eiman.tv
11 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
12 * Brian Hill, supernova@tycho.email
17 #include <ControlLook.h>
18 #include <GroupLayout.h>
19 #include <GroupView.h>
21 #include "AppGroupView.h"
23 #include "NotificationWindow.h"
24 #include "NotificationView.h"
26 const float kCloseSize
= 6;
27 const float kEdgePadding
= 2;
30 AppGroupView::AppGroupView(const BMessenger
& messenger
, const char* label
)
32 BGroupView("appGroup", B_VERTICAL
, 0),
34 fMessenger(messenger
),
39 SetFlags(Flags() | B_WILL_DRAW
);
41 fHeaderSize
= be_bold_font
->Size()
42 + be_control_look
->ComposeSpacing(B_USE_ITEM_SPACING
);
43 static_cast<BGroupLayout
*>(GetLayout())->SetInsets(0, fHeaderSize
, 0, 0);
48 AppGroupView::Draw(BRect updateRect
)
50 rgb_color menuColor
= ViewColor();
51 BRect bounds
= Bounds();
52 rgb_color hilite
= tint_color(menuColor
, B_DARKEN_1_TINT
);
53 rgb_color vlight
= tint_color(menuColor
, B_LIGHTEN_2_TINT
);
54 bounds
.bottom
= bounds
.top
+ fHeaderSize
;
56 // Draw the header background
57 SetHighColor(tint_color(menuColor
, 1.22));
58 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR
));
59 StrokeLine(bounds
.LeftTop(), bounds
.LeftBottom());
60 uint32 borders
= BControlLook::B_TOP_BORDER
61 | BControlLook::B_BOTTOM_BORDER
| BControlLook::B_RIGHT_BORDER
;
62 be_control_look
->DrawButtonBackground(this, bounds
, bounds
, menuColor
,
66 fCollapseRect
.top
= (fHeaderSize
- kExpandSize
) / 2;
67 fCollapseRect
.left
= kEdgePadding
* 3;
68 fCollapseRect
.right
= fCollapseRect
.left
+ 1.5 * kExpandSize
;
69 fCollapseRect
.bottom
= fCollapseRect
.top
+ kExpandSize
;
72 fCloseRect
.top
= (fHeaderSize
- kCloseSize
) / 2;
73 // Take off the 1 to line this up with the close button on the
75 fCloseRect
.right
-= kEdgePadding
* 3 - 1;
76 fCloseRect
.left
= fCloseRect
.right
- kCloseSize
;
77 fCloseRect
.bottom
= fCloseRect
.top
+ kCloseSize
;
79 uint32 arrowDirection
= fCollapsed
80 ? BControlLook::B_DOWN_ARROW
: BControlLook::B_UP_ARROW
;
81 be_control_look
->DrawArrowShape(this, fCollapseRect
, fCollapseRect
,
82 LowColor(), arrowDirection
, 0, B_DARKEN_3_TINT
);
86 // Draw the dismiss widget
87 _DrawCloseButton(updateRect
);
90 SetHighColor(ui_color(B_PANEL_TEXT_COLOR
));
91 BString label
= fLabel
;
93 label
<< " (" << fInfo
.size() << ")";
95 SetFont(be_bold_font
);
96 font_height fontHeight
;
97 GetFontHeight(&fontHeight
);
98 float y
= (bounds
.top
+ bounds
.bottom
- ceilf(fontHeight
.ascent
)
99 - ceilf(fontHeight
.descent
)) / 2.0 + ceilf(fontHeight
.ascent
);
101 DrawString(label
.String(),
102 BPoint(fCollapseRect
.right
+ 4 * kEdgePadding
, y
));
107 AppGroupView::_DrawCloseButton(const BRect
& updateRect
)
110 BRect closeRect
= fCloseRect
;
112 rgb_color base
= ui_color(B_PANEL_BACKGROUND_COLOR
);
113 float tint
= B_DARKEN_2_TINT
;
116 BRect
buttonRect(closeRect
.InsetByCopy(-4, -4));
117 be_control_look
->DrawButtonFrame(this, buttonRect
, updateRect
,
119 BControlLook::B_ACTIVATED
| BControlLook::B_BLEND_FRAME
);
120 be_control_look
->DrawButtonBackground(this, buttonRect
, updateRect
,
121 base
, BControlLook::B_ACTIVATED
);
123 closeRect
.OffsetBy(1, 1);
126 base
= tint_color(base
, tint
);
129 StrokeLine(closeRect
.LeftTop(), closeRect
.RightBottom());
130 StrokeLine(closeRect
.LeftBottom(), closeRect
.RightTop());
136 AppGroupView::MouseDown(BPoint point
)
138 // Preview Mode ignores any mouse clicks
142 if (BRect(fCloseRect
).InsetBySelf(-5, -5).Contains(point
)) {
143 int32 children
= fInfo
.size();
144 for (int32 i
= 0; i
< children
; i
++) {
145 fInfo
[i
]->RemoveSelf();
151 // Remove ourselves from the parent view
152 BMessage
message(kRemoveGroupView
);
153 message
.AddPointer("view", this);
154 fMessenger
.SendMessage(&message
);
155 } else if (BRect(fCollapseRect
).InsetBySelf(-5, -5).Contains(point
)) {
156 fCollapsed
= !fCollapsed
;
157 int32 children
= fInfo
.size();
159 for (int32 i
= 0; i
< children
; i
++) {
160 if (!fInfo
[i
]->IsHidden())
163 GetLayout()->SetExplicitMaxSize(GetLayout()->MinSize());
165 for (int32 i
= 0; i
< children
; i
++) {
166 if (fInfo
[i
]->IsHidden())
169 GetLayout()->SetExplicitMaxSize(BSize(B_SIZE_UNSET
, B_SIZE_UNSET
));
173 Invalidate(); // Need to redraw the collapse indicator and title
179 AppGroupView::MessageReceived(BMessage
* msg
)
184 NotificationView
* view
= NULL
;
185 if (msg
->FindPointer("view", (void**)&view
) != B_OK
)
188 infoview_t::iterator vIt
= find(fInfo
.begin(), fInfo
.end(), view
);
189 if (vIt
== fInfo
.end())
196 fMessenger
.SendMessage(msg
);
198 if (!this->HasChildren()) {
200 BMessage
removeSelfMessage(kRemoveGroupView
);
201 removeSelfMessage
.AddPointer("view", this);
202 fMessenger
.SendMessage(&removeSelfMessage
);
208 BView::MessageReceived(msg
);
214 AppGroupView::AddInfo(NotificationView
* view
)
216 BString id
= view
->MessageID();
219 if (id
.Length() > 0) {
220 int32 children
= fInfo
.size();
221 for (int32 i
= 0; i
< children
; i
++) {
222 if (id
== fInfo
[i
]->MessageID()) {
223 NotificationView
* oldView
= fInfo
[i
];
224 oldView
->RemoveSelf();
233 // Invalidate all children to show or hide the close buttons in the
235 int32 children
= fInfo
.size();
236 for (int32 i
= 0; i
< children
; i
++) {
237 fInfo
[i
]->Invalidate();
241 fInfo
.push_back(view
);
243 GetLayout()->AddView(view
);
247 if (view
->IsHidden(view
) && !fCollapsed
)
253 AppGroupView::SetPreviewModeOn(bool enabled
)
255 fPreviewModeOn
= enabled
;
260 AppGroupView::Group() const
267 AppGroupView::SetGroup(const char* group
)
275 AppGroupView::HasChildren()
277 return !fInfo
.empty();
282 AppGroupView::ChildrenCount()