1 /* 2 * Copyright 2001-2006, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Marc Flerackers (mflerackers@androme.be) 7 * Stefano Ceccherini (burton666@libero.it) 8 */ 9 10 //! BMenuWindow is a custom BWindow for BMenus. 11 12 // TODO: Add scrollers 13 14 #include <Menu.h> 15 16 #include <MenuPrivate.h> 17 #include <MenuWindow.h> 18 #include <WindowPrivate.h> 19 20 21 // This draws the frame around the BMenu 22 class BMenuFrame : public BView { 23 public: 24 BMenuFrame(BMenu *menu); 25 26 virtual void AttachedToWindow(); 27 virtual void DetachedFromWindow(); 28 virtual void Draw(BRect updateRect); 29 30 private: 31 BMenu *fMenu; 32 }; 33 34 35 BMenuWindow::BMenuWindow(const char *name) 36 // The window will be resized by BMenu, so just pass a dummy rect 37 : BWindow(BRect(0, 0, 0, 0), name, B_BORDERED_WINDOW_LOOK, kMenuWindowFeel, 38 B_NOT_ZOOMABLE | B_AVOID_FOCUS), 39 fUpperScroller(NULL), 40 fLowerScroller(NULL) 41 { 42 } 43 44 45 BMenuWindow::~BMenuWindow() 46 { 47 } 48 49 50 void 51 BMenuWindow::AttachMenu(BMenu *menu) 52 { 53 if (CountChildren() > 0) 54 debugger("BMenuWindow (%s): a menu is already attached!"); 55 if (menu != NULL) { 56 BMenuFrame *menuFrame = new BMenuFrame(menu); 57 AddChild(menuFrame); 58 menu->MakeFocus(true); 59 } 60 } 61 62 63 void 64 BMenuWindow::DetachMenu() 65 { 66 if (CountChildren() > 0) 67 RemoveChild(ChildAt(0)); 68 } 69 70 71 // #pragma mark - 72 73 74 BMenuFrame::BMenuFrame(BMenu *menu) 75 : BView(BRect(0, 0, 1, 1), "menu frame", B_FOLLOW_ALL_SIDES, B_WILL_DRAW), 76 fMenu(menu) 77 { 78 } 79 80 81 void 82 BMenuFrame::AttachedToWindow() 83 { 84 BView::AttachedToWindow(); 85 86 if (fMenu != NULL) 87 AddChild(fMenu); 88 89 ResizeTo(Window()->Bounds().Width(), Window()->Bounds().Height()); 90 if (fMenu != NULL) { 91 BFont font; 92 fMenu->GetFont(&font); 93 SetFont(&font); 94 } 95 } 96 97 98 void 99 BMenuFrame::DetachedFromWindow() 100 { 101 if (fMenu != NULL) 102 RemoveChild(fMenu); 103 } 104 105 106 void 107 BMenuFrame::Draw(BRect updateRect) 108 { 109 if (fMenu != NULL && fMenu->CountItems() == 0) { 110 // TODO: Review this as it's a bit hacky. 111 // Menu has a size of 0, 0, since there are no items in it. 112 // So the BMenuFrame class has to fake it and draw an empty item. 113 // Note that we can't add a real "empty" item because then we couldn't 114 // tell if the item was added by us or not. 115 // See also BMenu::UpdateWindowViewSize() 116 SetHighColor(ui_color(B_MENU_BACKGROUND_COLOR)); 117 SetLowColor(HighColor()); 118 FillRect(updateRect); 119 120 font_height height; 121 GetFontHeight(&height); 122 SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DISABLED_LABEL_TINT)); 123 BPoint where((Bounds().Width() - fMenu->StringWidth(kEmptyMenuLabel)) / 2, ceilf(height.ascent + 1)); 124 DrawString(kEmptyMenuLabel, where); 125 } 126 127 SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_2_TINT)); 128 BRect bounds(Bounds()); 129 130 StrokeLine(BPoint(bounds.right, bounds.top), 131 BPoint(bounds.right, bounds.bottom - 1)); 132 StrokeLine(BPoint(bounds.left + 1, bounds.bottom), 133 BPoint(bounds.right, bounds.bottom)); 134 } 135