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 * Stephan Aßmus <superstippi@gmx.de> 8 * Ingo Weinhold <bonefish@cs.tu-berlin.de> 9 */ 10 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include <AbstractLayoutItem.h> 15 #include <LayoutUtils.h> 16 #include <MenuBar.h> 17 #include <MenuField.h> 18 #include <Message.h> 19 #include <BMCPrivate.h> 20 #include <Window.h> 21 22 23 class BMenuField::LabelLayoutItem : public BAbstractLayoutItem { 24 public: 25 LabelLayoutItem(BMenuField* parent); 26 27 virtual bool IsVisible(); 28 virtual void SetVisible(bool visible); 29 30 virtual BRect Frame(); 31 virtual void SetFrame(BRect frame); 32 33 virtual BView* View(); 34 35 virtual BSize BaseMinSize(); 36 virtual BSize BaseMaxSize(); 37 virtual BSize BasePreferredSize(); 38 virtual BAlignment BaseAlignment(); 39 40 private: 41 BMenuField* fParent; 42 BRect fFrame; 43 }; 44 45 46 class BMenuField::MenuBarLayoutItem : public BAbstractLayoutItem { 47 public: 48 MenuBarLayoutItem(BMenuField* parent); 49 50 virtual bool IsVisible(); 51 virtual void SetVisible(bool visible); 52 53 virtual BRect Frame(); 54 virtual void SetFrame(BRect frame); 55 56 virtual BView* View(); 57 58 virtual BSize BaseMinSize(); 59 virtual BSize BaseMaxSize(); 60 virtual BSize BasePreferredSize(); 61 virtual BAlignment BaseAlignment(); 62 63 private: 64 BMenuField* fParent; 65 BRect fFrame; 66 }; 67 68 69 // #pragma mark - 70 71 72 static float kVMargin = 2.0f; 73 74 75 BMenuField::BMenuField(BRect frame, const char *name, const char *label, 76 BMenu *menu, uint32 resize, uint32 flags) 77 : BView(frame, name, resize, flags) 78 { 79 InitObject(label); 80 81 frame.OffsetTo(B_ORIGIN); 82 _InitMenuBar(menu, frame, false); 83 84 InitObject2(); 85 } 86 87 88 BMenuField::BMenuField(BRect frame, const char *name, const char *label, 89 BMenu *menu, bool fixedSize, uint32 resize, uint32 flags) 90 : BView(frame, name, resize, flags) 91 { 92 InitObject(label); 93 94 fFixedSizeMB = fixedSize; 95 96 frame.OffsetTo(B_ORIGIN); 97 _InitMenuBar(menu, frame, fixedSize); 98 99 InitObject2(); 100 } 101 102 103 BMenuField::BMenuField(const char* name, const char* label, BMenu* menu, 104 BMessage* message, uint32 flags) 105 : BView(BRect(0, 0, -1, -1), name, B_FOLLOW_NONE, 106 flags | B_FRAME_EVENTS | B_SUPPORTS_LAYOUT) 107 { 108 InitObject(label); 109 110 _InitMenuBar(menu, BRect(0, 0, 100, 15), false); 111 112 InitObject2(); 113 } 114 115 116 BMenuField::BMenuField(const char* label, 117 BMenu* menu, BMessage* message) 118 : BView(BRect(0, 0, -1, -1), NULL, B_FOLLOW_NONE, 119 B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS | B_SUPPORTS_LAYOUT) 120 { 121 InitObject(label); 122 123 _InitMenuBar(menu, BRect(0, 0, 100, 15), false); 124 125 InitObject2(); 126 } 127 128 129 BMenuField::BMenuField(BMessage *data) 130 : BView(data) 131 { 132 const char *label = NULL; 133 data->FindString("_label", &label); 134 135 InitObject(label); 136 137 fMenuBar = (BMenuBar*)FindView("_mc_mb_"); 138 fMenu = fMenuBar->SubmenuAt(0); 139 140 InitObject2(); 141 142 bool disable; 143 if (data->FindBool("_disable", &disable) == B_OK) 144 SetEnabled(!disable); 145 146 int32 align; 147 data->FindInt32("_align", &align); 148 SetAlignment((alignment)align); 149 150 data->FindFloat("_divide", &fDivider); 151 152 bool fixed; 153 if (data->FindBool("be:fixeds", &fixed) == B_OK) 154 fFixedSizeMB = fixed; 155 156 bool dmark = false; 157 data->FindBool("be:dmark", &dmark); 158 if (_BMCMenuBar_ *menuBar = dynamic_cast<_BMCMenuBar_ *>(fMenuBar)) { 159 menuBar->TogglePopUpMarker(dmark); 160 } 161 } 162 163 164 BMenuField::~BMenuField() 165 { 166 free(fLabel); 167 168 status_t dummy; 169 if (fMenuTaskID >= 0) 170 wait_for_thread(fMenuTaskID, &dummy); 171 } 172 173 174 BArchivable * 175 BMenuField::Instantiate(BMessage *data) 176 { 177 if (validate_instantiation(data, "BMenuField")) 178 return new BMenuField(data); 179 180 return NULL; 181 } 182 183 184 status_t 185 BMenuField::Archive(BMessage *data, bool deep) const 186 { 187 status_t ret = BView::Archive(data, deep); 188 189 if (ret == B_OK && Label()) 190 ret = data->AddString("_label", Label()); 191 192 if (ret == B_OK && !IsEnabled()) 193 ret = data->AddBool("_disable", true); 194 195 if (ret == B_OK) 196 ret = data->AddInt32("_align", Alignment()); 197 if (ret == B_OK) 198 ret = data->AddFloat("_divide", Divider()); 199 200 if (ret == B_OK && fFixedSizeMB) 201 ret = data->AddBool("be:fixeds", true); 202 203 bool dmark = false; 204 if (_BMCMenuBar_ *menuBar = dynamic_cast<_BMCMenuBar_ *>(fMenuBar)) { 205 dmark = menuBar->IsPopUpMarkerShown(); 206 } 207 data->AddBool("be:dmark", dmark); 208 209 return ret; 210 } 211 212 213 void 214 BMenuField::Draw(BRect update) 215 { 216 BRect bounds(Bounds()); 217 bool active = false; 218 219 if (IsFocus()) 220 active = Window()->IsActive(); 221 222 DrawLabel(bounds, update); 223 224 BRect frame(fMenuBar->Frame()); 225 226 if (frame.InsetByCopy(-kVMargin, -kVMargin).Intersects(update)) { 227 SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_2_TINT)); 228 StrokeLine(BPoint(frame.left - 1.0f, frame.top - 1.0f), 229 BPoint(frame.left - 1.0f, frame.bottom - 1.0f)); 230 StrokeLine(BPoint(frame.left - 1.0f, frame.top - 1.0f), 231 BPoint(frame.right - 1.0f, frame.top - 1.0f)); 232 233 StrokeLine(BPoint(frame.left + 1.0f, frame.bottom + 1.0f), 234 BPoint(frame.right + 1.0f, frame.bottom + 1.0f)); 235 StrokeLine(BPoint(frame.right + 1.0f, frame.top + 1.0f)); 236 237 SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_4_TINT)); 238 StrokeLine(BPoint(frame.left - 1.0f, frame.bottom), 239 BPoint(frame.left - 1.0f, frame.bottom)); 240 StrokeLine(BPoint(frame.right, frame.top - 1.0f), 241 BPoint(frame.right, frame.top - 1.0f)); 242 } 243 244 if (active || fTransition) { 245 SetHighColor(active ? ui_color(B_KEYBOARD_NAVIGATION_COLOR) : 246 ViewColor()); 247 StrokeRect(frame.InsetByCopy(-kVMargin, -kVMargin)); 248 249 fTransition = false; 250 } 251 } 252 253 254 void 255 BMenuField::AttachedToWindow() 256 { 257 if (Parent()) { 258 SetViewColor(Parent()->ViewColor()); 259 SetLowColor(Parent()->ViewColor()); 260 } 261 262 if (fLabel) 263 fStringWidth = StringWidth(fLabel); 264 } 265 266 267 void 268 BMenuField::AllAttached() 269 { 270 ResizeTo(Bounds().Width(), 271 fMenuBar->Bounds().Height() + kVMargin + kVMargin); 272 } 273 274 275 void 276 BMenuField::MouseDown(BPoint where) 277 { 278 if (!fMenuBar->Frame().Contains(where)) 279 return; 280 281 BRect bounds = fMenuBar->ConvertFromParent(Bounds()); 282 283 fMenuBar->StartMenuBar(-1, false, true, &bounds); 284 285 fMenuTaskID = spawn_thread((thread_func)MenuTask, "_m_task_", B_NORMAL_PRIORITY, this); 286 if (fMenuTaskID) 287 resume_thread(fMenuTaskID); 288 } 289 290 291 void 292 BMenuField::KeyDown(const char *bytes, int32 numBytes) 293 { 294 switch (bytes[0]) { 295 case B_SPACE: 296 case B_RIGHT_ARROW: 297 case B_DOWN_ARROW: 298 { 299 if (!IsEnabled()) 300 break; 301 302 BRect bounds = fMenuBar->ConvertFromParent(Bounds()); 303 304 fMenuBar->StartMenuBar(0, true, true, &bounds); 305 306 fSelected = true; 307 fTransition = true; 308 309 bounds = Bounds(); 310 bounds.right = fDivider; 311 312 Invalidate(bounds); 313 } 314 315 default: 316 BView::KeyDown(bytes, numBytes); 317 } 318 } 319 320 321 void 322 BMenuField::MakeFocus(bool state) 323 { 324 if (IsFocus() == state) 325 return; 326 327 BView::MakeFocus(state); 328 329 if (Window()) 330 Invalidate(); // TODO: use fStringWidth 331 } 332 333 334 void 335 BMenuField::MessageReceived(BMessage *msg) 336 { 337 BView::MessageReceived(msg); 338 } 339 340 341 void 342 BMenuField::WindowActivated(bool state) 343 { 344 BView::WindowActivated(state); 345 346 if (IsFocus()) 347 Invalidate(); 348 } 349 350 351 void 352 BMenuField::MouseUp(BPoint point) 353 { 354 BView::MouseUp(point); 355 } 356 357 358 void 359 BMenuField::MouseMoved(BPoint point, uint32 code, const BMessage *message) 360 { 361 BView::MouseMoved(point, code, message); 362 } 363 364 365 void 366 BMenuField::DetachedFromWindow() 367 { 368 BView::DetachedFromWindow(); 369 } 370 371 372 void 373 BMenuField::AllDetached() 374 { 375 BView::AllDetached(); 376 } 377 378 379 void 380 BMenuField::FrameMoved(BPoint newPosition) 381 { 382 BView::FrameMoved(newPosition); 383 } 384 385 386 void 387 BMenuField::FrameResized(float newWidth, float newHeight) 388 { 389 BView::FrameResized(newWidth, newHeight); 390 } 391 392 393 BMenu * 394 BMenuField::Menu() const 395 { 396 return fMenu; 397 } 398 399 400 BMenuBar * 401 BMenuField::MenuBar() const 402 { 403 return fMenuBar; 404 } 405 406 407 BMenuItem * 408 BMenuField::MenuItem() const 409 { 410 return fMenuBar->ItemAt(0); 411 } 412 413 414 void 415 BMenuField::SetLabel(const char *label) 416 { 417 if (fLabel) { 418 if (label && strcmp(fLabel, label) == 0) 419 return; 420 421 free(fLabel); 422 } 423 424 fLabel = strdup(label); 425 426 if (Window()) { 427 Invalidate(); 428 if (fLabel) 429 fStringWidth = StringWidth(fLabel); 430 } 431 432 InvalidateLayout(); 433 } 434 435 436 const char * 437 BMenuField::Label() const 438 { 439 return fLabel; 440 } 441 442 443 void 444 BMenuField::SetEnabled(bool on) 445 { 446 if (fEnabled == on) 447 return; 448 449 fEnabled = on; 450 fMenuBar->SetEnabled(on); 451 452 if (Window()) { 453 fMenuBar->Invalidate(fMenuBar->Bounds()); 454 Invalidate(Bounds()); 455 } 456 } 457 458 459 bool 460 BMenuField::IsEnabled() const 461 { 462 return fEnabled; 463 } 464 465 466 void 467 BMenuField::SetAlignment(alignment label) 468 { 469 fAlign = label; 470 } 471 472 473 alignment 474 BMenuField::Alignment() const 475 { 476 return fAlign; 477 } 478 479 480 void 481 BMenuField::SetDivider(float divider) 482 { 483 divider = floorf(divider + 0.5); 484 485 float dx = fDivider - divider; 486 487 if (dx == 0.0f) 488 return; 489 490 fDivider = divider; 491 492 BRect dirty(fMenuBar->Frame()); 493 494 fMenuBar->MoveTo(fDivider + 1, kVMargin); 495 496 if (fFixedSizeMB) { 497 fMenuBar->ResizeTo(Bounds().Width() - fDivider + 1 - 2, 498 dirty.Height()); 499 } 500 501 dirty = dirty | fMenuBar->Frame(); 502 503 dirty.left -= 1; 504 dirty.top -= 1; 505 dirty.right += 2; 506 dirty.bottom += 2; 507 508 Invalidate(dirty); 509 } 510 511 512 float 513 BMenuField::Divider() const 514 { 515 return fDivider; 516 } 517 518 519 void 520 BMenuField::ShowPopUpMarker() 521 { 522 if (_BMCMenuBar_ *menuBar = dynamic_cast<_BMCMenuBar_ *>(fMenuBar)) { 523 menuBar->TogglePopUpMarker(true); 524 menuBar->Invalidate(); 525 } 526 } 527 528 529 void 530 BMenuField::HidePopUpMarker() 531 { 532 if (_BMCMenuBar_ *menuBar = dynamic_cast<_BMCMenuBar_ *>(fMenuBar)) { 533 menuBar->TogglePopUpMarker(false); 534 menuBar->Invalidate(); 535 } 536 } 537 538 539 BHandler * 540 BMenuField::ResolveSpecifier(BMessage *message, int32 index, 541 BMessage *specifier, int32 form, const char *property) 542 { 543 return BView::ResolveSpecifier(message, index, specifier, form, property); 544 } 545 546 547 status_t 548 BMenuField::GetSupportedSuites(BMessage *data) 549 { 550 return BView::GetSupportedSuites(data); 551 } 552 553 554 void 555 BMenuField::ResizeToPreferred() 556 { 557 fMenuBar->ResizeToPreferred(); 558 559 BView::ResizeToPreferred(); 560 } 561 562 563 void 564 BMenuField::GetPreferredSize(float *_width, float *_height) 565 { 566 fMenuBar->GetPreferredSize(_width, _height); 567 568 if (_width) { 569 // the width is already the menu bars preferred width 570 // add the room we need to draw the shadow and stuff 571 *_width += 2 * kVMargin; 572 573 // add the room needed for the label 574 float labelWidth = fDivider; 575 if (Label()) { 576 labelWidth = ceilf(StringWidth(Label())); 577 if (labelWidth > 0.0) { 578 // add some room between label and menu bar 579 labelWidth += 5.0; 580 } 581 582 // have divider override the calculated label width 583 labelWidth = max_c(labelWidth, fDivider); 584 } 585 586 *_width += labelWidth; 587 } 588 589 if (_height) { 590 // the height is already the menu bars preferred height 591 // add the room we need to draw the shadow and stuff 592 *_height += 2 * kVMargin; 593 594 // see if our label would fit vertically 595 font_height fh; 596 GetFontHeight(&fh); 597 *_height = max_c(*_height, ceilf(fh.ascent + fh.descent)); 598 } 599 } 600 601 602 BLayoutItem* 603 BMenuField::CreateLabelLayoutItem() 604 { 605 if (!fLabelLayoutItem) 606 fLabelLayoutItem = new LabelLayoutItem(this); 607 return fLabelLayoutItem; 608 } 609 610 611 BLayoutItem* 612 BMenuField::CreateMenuBarLayoutItem() 613 { 614 if (!fMenuBarLayoutItem) 615 fMenuBarLayoutItem = new MenuBarLayoutItem(this); 616 return fMenuBarLayoutItem; 617 } 618 619 620 status_t 621 BMenuField::Perform(perform_code d, void *arg) 622 { 623 return BView::Perform(d, arg); 624 } 625 626 627 void BMenuField::_ReservedMenuField1() {} 628 void BMenuField::_ReservedMenuField2() {} 629 void BMenuField::_ReservedMenuField3() {} 630 631 632 BMenuField & 633 BMenuField::operator=(const BMenuField &) 634 { 635 return *this; 636 } 637 638 639 void 640 BMenuField::InitObject(const char *label) 641 { 642 fLabel = NULL; 643 fMenu = NULL; 644 fMenuBar = NULL; 645 fAlign = B_ALIGN_LEFT; 646 fStringWidth = 0; 647 fEnabled = true; 648 fSelected = false; 649 fTransition = false; 650 fFixedSizeMB = false; 651 fMenuTaskID = -1; 652 fLabelLayoutItem = NULL; 653 fMenuBarLayoutItem = NULL; 654 655 SetLabel(label); 656 657 if (label) 658 fDivider = (float)floor(Frame().Width() / 2.0f); 659 else 660 fDivider = 0; 661 } 662 663 664 void 665 BMenuField::InitObject2() 666 { 667 font_height fontHeight; 668 GetFontHeight(&fontHeight); 669 670 // TODO: fix this calculation 671 float height = floorf(fontHeight.ascent + fontHeight.descent 672 + fontHeight.leading) + 7; 673 674 fMenuBar->ResizeTo(Bounds().Width() - fDivider, height); 675 fMenuBar->AddFilter(new _BMCFilter_(this, B_MOUSE_DOWN)); 676 } 677 678 679 void 680 BMenuField::DrawLabel(BRect bounds, BRect update) 681 { 682 font_height fh; 683 GetFontHeight(&fh); 684 685 if (Label()) { 686 SetLowColor(ViewColor()); 687 688 float y = (float)ceil(fh.ascent + fh.descent + fh.leading) + 2.0f; 689 float x; 690 691 switch (fAlign) { 692 case B_ALIGN_RIGHT: 693 x = fDivider - StringWidth(Label()) - 3.0f; 694 break; 695 696 case B_ALIGN_CENTER: 697 x = fDivider - StringWidth(Label()) / 2.0f; 698 break; 699 700 default: 701 x = 3.0f; 702 break; 703 } 704 705 SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 706 IsEnabled() ? B_DARKEN_MAX_TINT : B_DISABLED_LABEL_TINT)); 707 DrawString(Label(), BPoint(x, y)); 708 } 709 } 710 711 712 void 713 BMenuField::InitMenu(BMenu *menu) 714 { 715 menu->SetFont(be_plain_font); 716 717 int32 index = 0; 718 BMenu *subMenu; 719 720 while ((subMenu = menu->SubmenuAt(index++)) != NULL) 721 InitMenu(subMenu); 722 } 723 724 725 long 726 BMenuField::MenuTask(void *arg) 727 { 728 BMenuField *menuField = static_cast<BMenuField *>(arg); 729 730 if (!menuField->LockLooper()) 731 return 0; 732 733 menuField->fSelected = true; 734 menuField->fTransition = true; 735 menuField->Invalidate(); 736 menuField->UnlockLooper(); 737 738 bool tracking; 739 do { 740 snooze(20000); 741 if (!menuField->LockLooper()) 742 return 0; 743 744 tracking = menuField->fMenuBar->fTracking; 745 746 menuField->UnlockLooper(); 747 } while (tracking); 748 749 if (menuField->LockLooper()) { 750 menuField->fSelected = false; 751 menuField->fTransition = true; 752 menuField->Invalidate(); 753 menuField->UnlockLooper(); 754 } 755 756 return 0; 757 } 758 759 760 void 761 BMenuField::_UpdateFrame() 762 { 763 if (fLabelLayoutItem && fMenuBarLayoutItem) { 764 BRect labelFrame = fLabelLayoutItem->Frame(); 765 BRect menuFrame = fMenuBarLayoutItem->Frame(); 766 MoveTo(labelFrame.left, labelFrame.top); 767 ResizeTo(menuFrame.left + menuFrame.Width() - labelFrame.left, 768 menuFrame.top + menuFrame.Height() - labelFrame.top); 769 SetDivider(menuFrame.left - labelFrame.left); 770 } 771 } 772 773 774 void 775 BMenuField::_InitMenuBar(BMenu* menu, BRect frame, bool fixedSize) 776 { 777 fMenu = menu; 778 InitMenu(menu); 779 780 fMenuBar = new _BMCMenuBar_(BRect(frame.left + fDivider + 1, 781 frame.top + kVMargin, frame.right, frame.bottom - kVMargin), 782 fixedSize, this); 783 784 AddChild(fMenuBar); 785 fMenuBar->AddItem(menu); 786 787 fMenuBar->SetFont(be_plain_font); 788 } 789 790 791 // #pragma mark - 792 793 794 BMenuField::LabelLayoutItem::LabelLayoutItem(BMenuField* parent) 795 : fParent(parent), 796 fFrame() 797 { 798 } 799 800 801 bool 802 BMenuField::LabelLayoutItem::IsVisible() 803 { 804 return !fParent->IsHidden(fParent); 805 } 806 807 808 void 809 BMenuField::LabelLayoutItem::SetVisible(bool visible) 810 { 811 // not allowed 812 } 813 814 815 BRect 816 BMenuField::LabelLayoutItem::Frame() 817 { 818 return fFrame; 819 } 820 821 822 void 823 BMenuField::LabelLayoutItem::SetFrame(BRect frame) 824 { 825 fFrame = frame; 826 fParent->_UpdateFrame(); 827 } 828 829 830 BView* 831 BMenuField::LabelLayoutItem::View() 832 { 833 return fParent; 834 } 835 836 837 BSize 838 BMenuField::LabelLayoutItem::BaseMinSize() 839 { 840 // TODO: Cache the info. Might be too expensive for this call. 841 const char* label = fParent->Label(); 842 if (!label) 843 return BSize(-1, -1); 844 845 BSize size; 846 fParent->GetPreferredSize(NULL, &size.height); 847 848 size.width = fParent->StringWidth(label) + 2 * 3 - 1; 849 850 return size; 851 } 852 853 854 BSize 855 BMenuField::LabelLayoutItem::BaseMaxSize() 856 { 857 return BaseMinSize(); 858 } 859 860 861 BSize 862 BMenuField::LabelLayoutItem::BasePreferredSize() 863 { 864 return BaseMinSize(); 865 } 866 867 868 BAlignment 869 BMenuField::LabelLayoutItem::BaseAlignment() 870 { 871 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 872 } 873 874 875 // #pragma mark - 876 877 878 BMenuField::MenuBarLayoutItem::MenuBarLayoutItem(BMenuField* parent) 879 : fParent(parent), 880 fFrame() 881 { 882 } 883 884 885 bool 886 BMenuField::MenuBarLayoutItem::IsVisible() 887 { 888 return !fParent->IsHidden(fParent); 889 } 890 891 892 void 893 BMenuField::MenuBarLayoutItem::SetVisible(bool visible) 894 { 895 // not allowed 896 } 897 898 899 BRect 900 BMenuField::MenuBarLayoutItem::Frame() 901 { 902 return fFrame; 903 } 904 905 906 void 907 BMenuField::MenuBarLayoutItem::SetFrame(BRect frame) 908 { 909 fFrame = frame; 910 fParent->_UpdateFrame(); 911 } 912 913 914 BView* 915 BMenuField::MenuBarLayoutItem::View() 916 { 917 return fParent; 918 } 919 920 921 BSize 922 BMenuField::MenuBarLayoutItem::BaseMinSize() 923 { 924 // TODO: Cache the info. Might be too expensive for this call. 925 BSize size; 926 fParent->fMenuBar->GetPreferredSize(&size.width, &size.height); 927 928 // BMenuField draws additional lines around BMenuBar, 929 // one line on left and top side, two on right and bottom 930 size.width += 3; 931 size.height += 3; 932 933 return size; 934 } 935 936 937 BSize 938 BMenuField::MenuBarLayoutItem::BaseMaxSize() 939 { 940 BSize size(BaseMinSize()); 941 size.width = B_SIZE_UNLIMITED; 942 return size; 943 } 944 945 946 BSize 947 BMenuField::MenuBarLayoutItem::BasePreferredSize() 948 { 949 BSize size(BaseMinSize()); 950 // puh, no idea... 951 size.width = 100; 952 return size; 953 } 954 955 956 BAlignment 957 BMenuField::MenuBarLayoutItem::BaseAlignment() 958 { 959 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 960 } 961 962