1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: BMCPrivate.cpp 23 // Author: Marc Flerackers (mflerackers@androme.be) 24 // Description: The BMCPrivate classes are used by BMenuField. 25 //------------------------------------------------------------------------------ 26 27 #include <BMCPrivate.h> 28 #include <MenuField.h> 29 #include <MenuItem.h> 30 #include <Message.h> 31 #include <Region.h> 32 #include <Window.h> 33 34 35 _BMCItem_::_BMCItem_(BMenu *menu) 36 : BMenuItem(menu), 37 fShowPopUpMarker(true) 38 { 39 } 40 41 42 _BMCItem_::_BMCItem_(BMessage *message) 43 : BMenuItem(message), 44 fShowPopUpMarker(true) 45 { 46 } 47 48 49 _BMCItem_::~_BMCItem_() 50 { 51 } 52 53 54 BArchivable * 55 _BMCItem_::Instantiate(BMessage *data) 56 { 57 if (validate_instantiation(data, "_BMCItem_")) 58 return new _BMCItem_(data); 59 else 60 return NULL; 61 } 62 63 64 void 65 _BMCItem_::Draw() 66 { 67 BMenu *menu = Menu(); 68 69 BMenuItem::Draw(); 70 71 if (!fShowPopUpMarker) 72 return; 73 74 BRect rect(menu->Bounds()); 75 76 rect.right -= 4; 77 rect.bottom -= 5; 78 rect.left = rect.right - 4; 79 rect.top = rect.bottom - 2; 80 81 if (IsEnabled()) 82 menu->SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), 83 B_DARKEN_4_TINT)); 84 else 85 menu->SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), 86 B_DARKEN_4_TINT)); 87 88 menu->StrokeLine(BPoint(rect.left, rect.top), BPoint(rect.right, rect.top)); 89 menu->StrokeLine(BPoint(rect.left + 1.0f, rect.top + 1.0f), 90 BPoint(rect.right - 1.0f, rect.top + 1.0f)); 91 menu->StrokeLine(BPoint(rect.left + 2.0f, rect.bottom), 92 BPoint(rect.left + 2.0f, rect.bottom)); 93 } 94 95 96 void 97 _BMCItem_::GetContentSize(float *width, float *height) 98 { 99 BMenuItem::GetContentSize(width, height); 100 } 101 102 103 /* 104 _BMCFilter_::_BMCFilter_(BMenuField *menuField, uint32) 105 { 106 } 107 108 109 _BMCFilter_::~_BMCFilter_() 110 { 111 } 112 113 114 filter_result 115 _BMCFilter_::Filter(BMessage *message, BHandler **handler) 116 { 117 } 118 119 120 _BMCFilter_ & 121 _BMCFilter_::operator=(const _BMCFilter_ &) 122 { 123 return *this; 124 }*/ 125 126 127 _BMCMenuBar_::_BMCMenuBar_(BRect frame, bool fixed_size, BMenuField *menuField) 128 : BMenuBar(frame, "_mc_mb_", B_FOLLOW_LEFT | B_FOLLOW_TOP, B_ITEMS_IN_ROW, 129 !fixed_size) 130 { 131 SetFlags(Flags() | B_FRAME_EVENTS); 132 SetBorder(B_BORDER_CONTENTS); 133 134 fMenuField = menuField; 135 fFixedSize = fixed_size; 136 fRunner = NULL; 137 138 float left, top, right, bottom; 139 140 GetItemMargins(&left, &top, &right, &bottom); 141 SetItemMargins(left, top, right, bottom); // TODO: 142 143 SetMaxContentWidth(frame.Width() - (left + right)); 144 } 145 146 147 _BMCMenuBar_::_BMCMenuBar_(BMessage *data) 148 : BMenuBar(data) 149 { 150 SetFlags(Flags() | B_FRAME_EVENTS); 151 152 bool rsize_to_fit; 153 154 if (data->FindBool("_rsize_to_fit", &rsize_to_fit) == B_OK) 155 fFixedSize = !rsize_to_fit; 156 else 157 fFixedSize = true; 158 } 159 160 161 _BMCMenuBar_::~_BMCMenuBar_() 162 { 163 } 164 165 166 BArchivable * 167 _BMCMenuBar_::Instantiate(BMessage *data) 168 { 169 if (validate_instantiation(data, "_BMCMenuBar_")) 170 return new _BMCMenuBar_(data); 171 else 172 return NULL; 173 } 174 175 176 void 177 _BMCMenuBar_::AttachedToWindow() 178 { 179 fMenuField = (BMenuField*)Parent(); 180 181 BMenuBar *menuBar = Window()->KeyMenuBar(); 182 BMenuBar::AttachedToWindow(); 183 Window()->SetKeyMenuBar(menuBar); 184 } 185 186 187 void 188 _BMCMenuBar_::Draw(BRect updateRect) 189 { 190 // draw the right and bottom line here in a darker tint 191 BRect bounds(Bounds()); 192 bounds.right -= 2.0; 193 bounds.bottom -= 1.0; 194 195 // prevent the original BMenuBar's Draw from 196 // drawing in those parts 197 BRegion clipping(bounds); 198 ConstrainClippingRegion(&clipping); 199 200 BMenuBar::Draw(updateRect); 201 202 ConstrainClippingRegion(NULL); 203 204 bounds.right += 2.0; 205 bounds.bottom += 1.0; 206 207 SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_4_TINT)); 208 StrokeLine(BPoint(bounds.left, bounds.bottom), 209 BPoint(bounds.right, bounds.bottom)); 210 StrokeLine(BPoint(bounds.right, bounds.bottom - 1), 211 BPoint(bounds.right, bounds.top)); 212 SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT)); 213 StrokeLine(BPoint(bounds.right - 1, bounds.bottom - 1), 214 BPoint(bounds.right - 1, bounds.top + 1)); 215 } 216 217 218 void 219 _BMCMenuBar_::FrameResized(float width, float height) 220 { 221 // we need to take care of resizing and cleaning up 222 // the parent menu field 223 float diff = Frame().right - fMenuField->Bounds().right; 224 if (Window()) { 225 if (diff > 0) { 226 // clean up the dirty right top corner of 227 // the menu field when enlarging 228 BRect dirty(fMenuField->Bounds()); 229 dirty.left = dirty.right - 2; 230 dirty.bottom = Frame().top - 1; 231 fMenuField->Invalidate(dirty); 232 } else if (diff < 0) { 233 // clean up the dirty right line of 234 // the menu field when shrinking 235 BRect dirty(fMenuField->Bounds()); 236 dirty.left = dirty.right + diff + 1; 237 dirty.right = dirty.left + 1; 238 fMenuField->Invalidate(dirty); 239 } 240 } 241 // we have been shrinked or enlarged and need to take 242 // of the size of the parent menu field as well 243 // NOTE: no worries about follow mode, we follow left and top 244 fMenuField->ResizeBy(diff + 2, 0.0); 245 BMenuBar::FrameResized(width, height); 246 } 247 248 249 void 250 _BMCMenuBar_::MessageReceived(BMessage *msg) 251 { 252 switch (msg->what) { 253 case 'TICK': 254 { 255 BMenuItem *item = ItemAt(0); 256 257 if (item && item->Submenu() && item->Submenu()->Window()) { 258 BMessage message(B_KEY_DOWN); 259 260 message.AddInt8("byte", B_ESCAPE); 261 message.AddInt8("key", B_ESCAPE); 262 message.AddInt32("modifiers", 0); 263 message.AddInt8("raw_char", B_ESCAPE); 264 265 Window()->PostMessage(&message, this, NULL); 266 } 267 } 268 // fall through 269 default: 270 BMenuBar::MessageReceived(msg); 271 break; 272 } 273 } 274 275 276 void 277 _BMCMenuBar_::MakeFocus(bool focused) 278 { 279 if (IsFocus() == focused) 280 return; 281 282 BMenuBar::MakeFocus(focused); 283 284 if (focused) { 285 BMessage message('TICK'); 286 //fRunner = new BMessageRunner(BMessenger(this, NULL, NULL), &message, 287 // 50000, -1); 288 } else if (fRunner) { 289 //delete fRunner; 290 fRunner = NULL; 291 } 292 293 if (focused) 294 return; 295 296 fMenuField->fSelected = false; 297 fMenuField->fTransition = true; 298 299 BRect bounds(fMenuField->Bounds()); 300 301 fMenuField->Invalidate(BRect(bounds.left, bounds.top, fMenuField->fDivider, 302 bounds.bottom)); 303 } 304 305 306 void 307 _BMCMenuBar_::MouseDown(BPoint where) 308 { 309 // Don't show the associated menu if it's disabled 310 if (fMenuField->IsEnabled() && SubmenuAt(0)->IsEnabled()) 311 BMenuBar::MouseDown(where); 312 } 313 314 315 _BMCMenuBar_ 316 &_BMCMenuBar_::operator=(const _BMCMenuBar_ &) 317 { 318 return *this; 319 } 320