tcp: Fix 64 bit build with debugging features enabled.
[haiku.git] / src / kits / interface / BMCPrivate.cpp
blob581c7552714036ba13e70d52ec33951ceb512551
1 /*
2 * Copyright 2001-2013 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Stephan Aßmus, superstippi@gmx.de
7 * Marc Flerackers, mflerackers@androme.be
8 * John Scipione, jcipione@gmail.com
9 */
12 #include <BMCPrivate.h>
14 #include <algorithm>
16 #include <ControlLook.h>
17 #include <LayoutUtils.h>
18 #include <MenuField.h>
19 #include <MenuItem.h>
20 #include <Message.h>
21 #include <MessageRunner.h>
22 #include <Window.h>
25 static const float kPopUpIndicatorWidth = 13.0f;
28 #if __GNUC__ == 2
31 // This is kept only for binary compatibility with BeOS R5. This class was
32 // used in their BMenuField implementation and we may come across some archived
33 // BMenuField that needs it.
34 class _BMCItem_: public BMenuItem {
35 public:
36 _BMCItem_(BMessage* data);
37 static BArchivable* Instantiate(BMessage *data);
41 _BMCItem_::_BMCItem_(BMessage* data)
42 : BMenuItem(data)
48 /*static*/ BArchivable*
49 _BMCItem_::Instantiate(BMessage *data) {
50 if (validate_instantiation(data, "_BMCItem_"))
51 return new _BMCItem_(data);
53 return NULL;
57 #endif
60 // #pragma mark - _BMCFilter_
63 _BMCFilter_::_BMCFilter_(BMenuField* menuField, uint32 what)
65 BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, what),
66 fMenuField(menuField)
71 _BMCFilter_::~_BMCFilter_()
76 filter_result
77 _BMCFilter_::Filter(BMessage* message, BHandler** handler)
79 if (message->what == B_MOUSE_DOWN) {
80 if (BView* view = dynamic_cast<BView*>(*handler)) {
81 BPoint point;
82 message->FindPoint("be:view_where", &point);
83 view->ConvertToParent(&point);
84 message->ReplacePoint("be:view_where", point);
85 *handler = fMenuField;
89 return B_DISPATCH_MESSAGE;
93 // #pragma mark - _BMCMenuBar_
96 _BMCMenuBar_::_BMCMenuBar_(BRect frame, bool fixedSize, BMenuField* menuField)
98 BMenuBar(frame, "_mc_mb_", B_FOLLOW_LEFT | B_FOLLOW_TOP, B_ITEMS_IN_ROW,
99 !fixedSize),
100 fMenuField(menuField),
101 fFixedSize(fixedSize),
102 fShowPopUpMarker(true)
104 _Init();
108 _BMCMenuBar_::_BMCMenuBar_(BMenuField* menuField)
110 BMenuBar("_mc_mb_", B_ITEMS_IN_ROW),
111 fMenuField(menuField),
112 fFixedSize(true),
113 fShowPopUpMarker(true)
115 _Init();
119 _BMCMenuBar_::_BMCMenuBar_(BMessage* data)
121 BMenuBar(data),
122 fMenuField(NULL),
123 fFixedSize(true),
124 fShowPopUpMarker(true)
126 SetFlags(Flags() | B_FRAME_EVENTS);
128 bool resizeToFit;
129 if (data->FindBool("_rsize_to_fit", &resizeToFit) == B_OK)
130 fFixedSize = !resizeToFit;
134 _BMCMenuBar_::~_BMCMenuBar_()
139 // #pragma mark - _BMCMenuBar_ public methods
142 BArchivable*
143 _BMCMenuBar_::Instantiate(BMessage* data)
145 if (validate_instantiation(data, "_BMCMenuBar_"))
146 return new _BMCMenuBar_(data);
148 return NULL;
152 void
153 _BMCMenuBar_::AttachedToWindow()
155 fMenuField = static_cast<BMenuField*>(Parent());
157 // Don't cause the KeyMenuBar to change by being attached
158 BMenuBar* menuBar = Window()->KeyMenuBar();
159 BMenuBar::AttachedToWindow();
160 Window()->SetKeyMenuBar(menuBar);
162 if (fFixedSize && (Flags() & B_SUPPORTS_LAYOUT) == 0)
163 SetResizingMode(B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
165 if (Parent() != NULL)
166 SetLowColor(Parent()->LowColor());
167 else
168 SetLowColor(ui_color(B_MENU_BACKGROUND_COLOR));
170 fPreviousWidth = Bounds().Width();
174 void
175 _BMCMenuBar_::Draw(BRect updateRect)
177 if (fFixedSize) {
178 // Set the width of the menu bar because the menu bar bounds may have
179 // been expanded by the selected menu item.
180 ResizeTo(fMenuField->_MenuBarWidth(), Bounds().Height());
181 } else {
182 // For compatability with BeOS R5:
183 // - Set to the minimum of the menu bar width set by the menu frame
184 // and the selected menu item width.
185 // - Set the height to the preferred height ignoring the height of the
186 // menu field.
187 float height;
188 BMenuBar::GetPreferredSize(NULL, &height);
189 ResizeTo(std::min(Bounds().Width(), fMenuField->_MenuBarWidth()),
190 height);
193 BRect rect(Bounds());
194 rgb_color base = ui_color(B_MENU_BACKGROUND_COLOR);
195 uint32 flags = 0;
196 if (!IsEnabled())
197 flags |= BControlLook::B_DISABLED;
198 if (IsFocus())
199 flags |= BControlLook::B_FOCUSED;
201 be_control_look->DrawMenuFieldBackground(this, rect,
202 updateRect, base, fShowPopUpMarker, flags);
204 _DrawItems(updateRect);
208 void
209 _BMCMenuBar_::FrameResized(float width, float height)
211 // we need to take care of cleaning up the parent menu field
212 float diff = width - fPreviousWidth;
213 fPreviousWidth = width;
215 if (Window() != NULL && diff != 0) {
216 BRect dirty(fMenuField->Bounds());
217 if (diff > 0) {
218 // clean up the dirty right border of
219 // the menu field when enlarging
220 dirty.right = Frame().right + kVMargin;
221 dirty.left = dirty.right - diff - kVMargin * 2;
222 fMenuField->Invalidate(dirty);
223 } else if (diff < 0) {
224 // clean up the dirty right line of
225 // the menu field when shrinking
226 dirty.left = Frame().right - kVMargin;
227 fMenuField->Invalidate(dirty);
231 BMenuBar::FrameResized(width, height);
235 void
236 _BMCMenuBar_::MakeFocus(bool focused)
238 if (IsFocus() == focused)
239 return;
241 BMenuBar::MakeFocus(focused);
245 void
246 _BMCMenuBar_::MessageReceived(BMessage* message)
248 switch (message->what) {
249 case 'TICK':
251 BMenuItem* item = ItemAt(0);
253 if (item && item->Submenu() && item->Submenu()->Window()) {
254 BMessage message(B_KEY_DOWN);
256 message.AddInt8("byte", B_ESCAPE);
257 message.AddInt8("key", B_ESCAPE);
258 message.AddInt32("modifiers", 0);
259 message.AddInt8("raw_char", B_ESCAPE);
261 Window()->PostMessage(&message, this, NULL);
264 // fall through
265 default:
266 BMenuBar::MessageReceived(message);
267 break;
272 void
273 _BMCMenuBar_::SetMaxContentWidth(float width)
275 float left;
276 float right;
277 GetItemMargins(&left, NULL, &right, NULL);
279 BMenuBar::SetMaxContentWidth(width - (left + right));
283 void
284 _BMCMenuBar_::SetEnabled(bool enabled)
286 fMenuField->SetEnabled(enabled);
288 BMenuBar::SetEnabled(enabled);
292 BSize
293 _BMCMenuBar_::MinSize()
295 BSize size;
296 BMenuBar::GetPreferredSize(&size.width, &size.height);
297 if (fShowPopUpMarker) {
298 // account for popup indicator + a few pixels margin
299 size.width += kPopUpIndicatorWidth;
302 return BLayoutUtils::ComposeSize(ExplicitMinSize(), size);
306 BSize
307 _BMCMenuBar_::MaxSize()
309 // The maximum width of a normal BMenuBar is unlimited, but we want it
310 // limited.
311 BSize size;
312 BMenuBar::GetPreferredSize(&size.width, &size.height);
314 return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size);
318 // #pragma mark - _BMCMenuBar_ private methods
321 void
322 _BMCMenuBar_::_Init()
324 SetFlags(Flags() | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE);
325 SetBorder(B_BORDER_CONTENTS);
327 float left, top, right, bottom;
328 GetItemMargins(&left, &top, &right, &bottom);
330 #if 0
331 // TODO: Better fix would be to make BMenuItem draw text properly
332 // centered
333 font_height fontHeight;
334 GetFontHeight(&fontHeight);
335 top = ceilf((Bounds().Height() - ceilf(fontHeight.ascent)
336 - ceilf(fontHeight.descent)) / 2) + 1;
337 bottom = top - 1;
338 #else
339 // TODO: Fix content location properly. This is just a quick fix to
340 // make the BMenuField label and the super-item of the BMenuBar
341 // align vertically.
342 top++;
343 bottom--;
344 #endif
346 if (be_control_look != NULL)
347 left = right = be_control_look->DefaultLabelSpacing();
349 SetItemMargins(left, top,
350 right + fShowPopUpMarker ? kPopUpIndicatorWidth : 0, bottom);