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_", 286 B_NORMAL_PRIORITY, this); 287 if (fMenuTaskID) 288 resume_thread(fMenuTaskID); 289 } 290 291 292 void 293 BMenuField::KeyDown(const char *bytes, int32 numBytes) 294 { 295 switch (bytes[0]) { 296 case B_SPACE: 297 case B_RIGHT_ARROW: 298 case B_DOWN_ARROW: 299 { 300 if (!IsEnabled()) 301 break; 302 303 BRect bounds = fMenuBar->ConvertFromParent(Bounds()); 304 305 fMenuBar->StartMenuBar(0, true, true, &bounds); 306 307 fSelected = true; 308 fTransition = true; 309 310 bounds = Bounds(); 311 bounds.right = fDivider; 312 313 Invalidate(bounds); 314 } 315 316 default: 317 BView::KeyDown(bytes, numBytes); 318 } 319 } 320 321 322 void 323 BMenuField::MakeFocus(bool state) 324 { 325 if (IsFocus() == state) 326 return; 327 328 BView::MakeFocus(state); 329 330 if (Window()) 331 Invalidate(); // TODO: use fStringWidth 332 } 333 334 335 void 336 BMenuField::MessageReceived(BMessage *msg) 337 { 338 BView::MessageReceived(msg); 339 } 340 341 342 void 343 BMenuField::WindowActivated(bool state) 344 { 345 BView::WindowActivated(state); 346 347 if (IsFocus()) 348 Invalidate(); 349 } 350 351 352 void 353 BMenuField::MouseUp(BPoint point) 354 { 355 BView::MouseUp(point); 356 } 357 358 359 void 360 BMenuField::MouseMoved(BPoint point, uint32 code, const BMessage *message) 361 { 362 BView::MouseMoved(point, code, message); 363 } 364 365 366 void 367 BMenuField::DetachedFromWindow() 368 { 369 BView::DetachedFromWindow(); 370 } 371 372 373 void 374 BMenuField::AllDetached() 375 { 376 BView::AllDetached(); 377 } 378 379 380 void 381 BMenuField::FrameMoved(BPoint newPosition) 382 { 383 BView::FrameMoved(newPosition); 384 } 385 386 387 void 388 BMenuField::FrameResized(float newWidth, float newHeight) 389 { 390 BView::FrameResized(newWidth, newHeight); 391 } 392 393 394 BMenu * 395 BMenuField::Menu() const 396 { 397 return fMenu; 398 } 399 400 401 BMenuBar * 402 BMenuField::MenuBar() const 403 { 404 return fMenuBar; 405 } 406 407 408 BMenuItem * 409 BMenuField::MenuItem() const 410 { 411 return fMenuBar->ItemAt(0); 412 } 413 414 415 void 416 BMenuField::SetLabel(const char *label) 417 { 418 if (fLabel) { 419 if (label && strcmp(fLabel, label) == 0) 420 return; 421 422 free(fLabel); 423 } 424 425 fLabel = strdup(label); 426 427 if (Window()) { 428 Invalidate(); 429 if (fLabel) 430 fStringWidth = StringWidth(fLabel); 431 } 432 433 InvalidateLayout(); 434 } 435 436 437 const char * 438 BMenuField::Label() const 439 { 440 return fLabel; 441 } 442 443 444 void 445 BMenuField::SetEnabled(bool on) 446 { 447 if (fEnabled == on) 448 return; 449 450 fEnabled = on; 451 fMenuBar->SetEnabled(on); 452 453 if (Window()) { 454 fMenuBar->Invalidate(fMenuBar->Bounds()); 455 Invalidate(Bounds()); 456 } 457 } 458 459 460 bool 461 BMenuField::IsEnabled() const 462 { 463 return fEnabled; 464 } 465 466 467 void 468 BMenuField::SetAlignment(alignment label) 469 { 470 fAlign = label; 471 } 472 473 474 alignment 475 BMenuField::Alignment() const 476 { 477 return fAlign; 478 } 479 480 481 void 482 BMenuField::SetDivider(float divider) 483 { 484 divider = floorf(divider + 0.5); 485 486 float dx = fDivider - divider; 487 488 if (dx == 0.0f) 489 return; 490 491 fDivider = divider; 492 493 BRect dirty(fMenuBar->Frame()); 494 495 fMenuBar->MoveTo(fDivider + 1, kVMargin); 496 497 if (fFixedSizeMB) { 498 fMenuBar->ResizeTo(Bounds().Width() - fDivider + 1 - 2, 499 dirty.Height()); 500 } 501 502 dirty = dirty | fMenuBar->Frame(); 503 504 dirty.left -= 1; 505 dirty.top -= 1; 506 dirty.right += 2; 507 dirty.bottom += 2; 508 509 Invalidate(dirty); 510 } 511 512 513 float 514 BMenuField::Divider() const 515 { 516 return fDivider; 517 } 518 519 520 void 521 BMenuField::ShowPopUpMarker() 522 { 523 if (_BMCMenuBar_ *menuBar = dynamic_cast<_BMCMenuBar_ *>(fMenuBar)) { 524 menuBar->TogglePopUpMarker(true); 525 menuBar->Invalidate(); 526 } 527 } 528 529 530 void 531 BMenuField::HidePopUpMarker() 532 { 533 if (_BMCMenuBar_ *menuBar = dynamic_cast<_BMCMenuBar_ *>(fMenuBar)) { 534 menuBar->TogglePopUpMarker(false); 535 menuBar->Invalidate(); 536 } 537 } 538 539 540 BHandler * 541 BMenuField::ResolveSpecifier(BMessage *message, int32 index, 542 BMessage *specifier, int32 form, const char *property) 543 { 544 return BView::ResolveSpecifier(message, index, specifier, form, property); 545 } 546 547 548 status_t 549 BMenuField::GetSupportedSuites(BMessage *data) 550 { 551 return BView::GetSupportedSuites(data); 552 } 553 554 555 void 556 BMenuField::ResizeToPreferred() 557 { 558 fMenuBar->ResizeToPreferred(); 559 560 BView::ResizeToPreferred(); 561 } 562 563 564 void 565 BMenuField::GetPreferredSize(float *_width, float *_height) 566 { 567 fMenuBar->GetPreferredSize(_width, _height); 568 569 if (_width) { 570 // the width is already the menu bars preferred width 571 // add the room we need to draw the shadow and stuff 572 *_width += 2 * kVMargin; 573 574 // add the room needed for the label 575 float labelWidth = fDivider; 576 if (Label()) { 577 labelWidth = ceilf(StringWidth(Label())); 578 if (labelWidth > 0.0) { 579 // add some room between label and menu bar 580 labelWidth += 5.0; 581 } 582 583 // have divider override the calculated label width 584 labelWidth = max_c(labelWidth, fDivider); 585 } 586 587 *_width += labelWidth; 588 } 589 590 if (_height) { 591 // the height is already the menu bars preferred height 592 // add the room we need to draw the shadow and stuff 593 *_height += 2 * kVMargin; 594 595 // see if our label would fit vertically 596 font_height fh; 597 GetFontHeight(&fh); 598 *_height = max_c(*_height, ceilf(fh.ascent + fh.descent)); 599 } 600 } 601 602 603 BLayoutItem* 604 BMenuField::CreateLabelLayoutItem() 605 { 606 if (!fLabelLayoutItem) 607 fLabelLayoutItem = new LabelLayoutItem(this); 608 return fLabelLayoutItem; 609 } 610 611 612 BLayoutItem* 613 BMenuField::CreateMenuBarLayoutItem() 614 { 615 if (!fMenuBarLayoutItem) 616 fMenuBarLayoutItem = new MenuBarLayoutItem(this); 617 return fMenuBarLayoutItem; 618 } 619 620 621 status_t 622 BMenuField::Perform(perform_code d, void *arg) 623 { 624 return BView::Perform(d, arg); 625 } 626 627 628 void BMenuField::_ReservedMenuField1() {} 629 void BMenuField::_ReservedMenuField2() {} 630 void BMenuField::_ReservedMenuField3() {} 631 632 633 BMenuField & 634 BMenuField::operator=(const BMenuField &) 635 { 636 return *this; 637 } 638 639 640 void 641 BMenuField::InitObject(const char *label) 642 { 643 fLabel = NULL; 644 fMenu = NULL; 645 fMenuBar = NULL; 646 fAlign = B_ALIGN_LEFT; 647 fStringWidth = 0; 648 fEnabled = true; 649 fSelected = false; 650 fTransition = false; 651 fFixedSizeMB = false; 652 fMenuTaskID = -1; 653 fLabelLayoutItem = NULL; 654 fMenuBarLayoutItem = NULL; 655 656 SetLabel(label); 657 658 if (label) 659 fDivider = (float)floor(Frame().Width() / 2.0f); 660 else 661 fDivider = 0; 662 } 663 664 665 void 666 BMenuField::InitObject2() 667 { 668 font_height fontHeight; 669 GetFontHeight(&fontHeight); 670 671 // TODO: fix this calculation 672 float height = floorf(fontHeight.ascent + fontHeight.descent 673 + fontHeight.leading) + 7; 674 675 fMenuBar->ResizeTo(Bounds().Width() - fDivider, height); 676 fMenuBar->AddFilter(new _BMCFilter_(this, B_MOUSE_DOWN)); 677 } 678 679 680 void 681 BMenuField::DrawLabel(BRect bounds, BRect update) 682 { 683 font_height fh; 684 GetFontHeight(&fh); 685 686 if (Label()) { 687 SetLowColor(ViewColor()); 688 689 float y = (float)ceil(fh.ascent + fh.descent + fh.leading) + 2.0f; 690 float x; 691 692 switch (fAlign) { 693 case B_ALIGN_RIGHT: 694 x = fDivider - StringWidth(Label()) - 3.0f; 695 break; 696 697 case B_ALIGN_CENTER: 698 x = fDivider - StringWidth(Label()) / 2.0f; 699 break; 700 701 default: 702 x = 3.0f; 703 break; 704 } 705 706 SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 707 IsEnabled() ? B_DARKEN_MAX_TINT : B_DISABLED_LABEL_TINT)); 708 DrawString(Label(), BPoint(x, y)); 709 } 710 } 711 712 713 void 714 BMenuField::InitMenu(BMenu *menu) 715 { 716 menu->SetFont(be_plain_font); 717 718 int32 index = 0; 719 BMenu *subMenu; 720 721 while ((subMenu = menu->SubmenuAt(index++)) != NULL) 722 InitMenu(subMenu); 723 } 724 725 726 long 727 BMenuField::MenuTask(void *arg) 728 { 729 BMenuField *menuField = static_cast<BMenuField *>(arg); 730 731 if (!menuField->LockLooper()) 732 return 0; 733 734 menuField->fSelected = true; 735 menuField->fTransition = true; 736 menuField->Invalidate(); 737 menuField->UnlockLooper(); 738 739 bool tracking; 740 do { 741 snooze(20000); 742 if (!menuField->LockLooper()) 743 return 0; 744 745 tracking = menuField->fMenuBar->fTracking; 746 747 menuField->UnlockLooper(); 748 } while (tracking); 749 750 if (menuField->LockLooper()) { 751 menuField->fSelected = false; 752 menuField->fTransition = true; 753 menuField->Invalidate(); 754 menuField->UnlockLooper(); 755 } 756 757 return 0; 758 } 759 760 761 void 762 BMenuField::_UpdateFrame() 763 { 764 if (fLabelLayoutItem && fMenuBarLayoutItem) { 765 BRect labelFrame = fLabelLayoutItem->Frame(); 766 BRect menuFrame = fMenuBarLayoutItem->Frame(); 767 MoveTo(labelFrame.left, labelFrame.top); 768 ResizeTo(menuFrame.left + menuFrame.Width() - labelFrame.left, 769 menuFrame.top + menuFrame.Height() - labelFrame.top); 770 SetDivider(menuFrame.left - labelFrame.left); 771 } 772 } 773 774 775 void 776 BMenuField::_InitMenuBar(BMenu* menu, BRect frame, bool fixedSize) 777 { 778 fMenu = menu; 779 InitMenu(menu); 780 781 fMenuBar = new _BMCMenuBar_(BRect(frame.left + fDivider + 1, 782 frame.top + kVMargin, frame.right, frame.bottom - kVMargin), 783 fixedSize, this); 784 785 AddChild(fMenuBar); 786 fMenuBar->AddItem(menu); 787 788 fMenuBar->SetFont(be_plain_font); 789 } 790 791 792 // #pragma mark - 793 794 795 BMenuField::LabelLayoutItem::LabelLayoutItem(BMenuField* parent) 796 : fParent(parent), 797 fFrame() 798 { 799 } 800 801 802 bool 803 BMenuField::LabelLayoutItem::IsVisible() 804 { 805 return !fParent->IsHidden(fParent); 806 } 807 808 809 void 810 BMenuField::LabelLayoutItem::SetVisible(bool visible) 811 { 812 // not allowed 813 } 814 815 816 BRect 817 BMenuField::LabelLayoutItem::Frame() 818 { 819 return fFrame; 820 } 821 822 823 void 824 BMenuField::LabelLayoutItem::SetFrame(BRect frame) 825 { 826 fFrame = frame; 827 fParent->_UpdateFrame(); 828 } 829 830 831 BView* 832 BMenuField::LabelLayoutItem::View() 833 { 834 return fParent; 835 } 836 837 838 BSize 839 BMenuField::LabelLayoutItem::BaseMinSize() 840 { 841 // TODO: Cache the info. Might be too expensive for this call. 842 const char* label = fParent->Label(); 843 if (!label) 844 return BSize(-1, -1); 845 846 BSize size; 847 fParent->GetPreferredSize(NULL, &size.height); 848 849 size.width = fParent->StringWidth(label) + 2 * 3 - 1; 850 851 return size; 852 } 853 854 855 BSize 856 BMenuField::LabelLayoutItem::BaseMaxSize() 857 { 858 return BaseMinSize(); 859 } 860 861 862 BSize 863 BMenuField::LabelLayoutItem::BasePreferredSize() 864 { 865 return BaseMinSize(); 866 } 867 868 869 BAlignment 870 BMenuField::LabelLayoutItem::BaseAlignment() 871 { 872 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 873 } 874 875 876 // #pragma mark - 877 878 879 BMenuField::MenuBarLayoutItem::MenuBarLayoutItem(BMenuField* parent) 880 : fParent(parent), 881 fFrame() 882 { 883 } 884 885 886 bool 887 BMenuField::MenuBarLayoutItem::IsVisible() 888 { 889 return !fParent->IsHidden(fParent); 890 } 891 892 893 void 894 BMenuField::MenuBarLayoutItem::SetVisible(bool visible) 895 { 896 // not allowed 897 } 898 899 900 BRect 901 BMenuField::MenuBarLayoutItem::Frame() 902 { 903 return fFrame; 904 } 905 906 907 void 908 BMenuField::MenuBarLayoutItem::SetFrame(BRect frame) 909 { 910 fFrame = frame; 911 fParent->_UpdateFrame(); 912 } 913 914 915 BView* 916 BMenuField::MenuBarLayoutItem::View() 917 { 918 return fParent; 919 } 920 921 922 BSize 923 BMenuField::MenuBarLayoutItem::BaseMinSize() 924 { 925 // TODO: Cache the info. Might be too expensive for this call. 926 BSize size; 927 fParent->fMenuBar->GetPreferredSize(&size.width, &size.height); 928 929 // BMenuField draws additional lines around BMenuBar, 930 // one line on left and top side, two on right and bottom 931 size.width += 3; 932 size.height += 3; 933 934 return size; 935 } 936 937 938 BSize 939 BMenuField::MenuBarLayoutItem::BaseMaxSize() 940 { 941 BSize size(BaseMinSize()); 942 size.width = B_SIZE_UNLIMITED; 943 return size; 944 } 945 946 947 BSize 948 BMenuField::MenuBarLayoutItem::BasePreferredSize() 949 { 950 BSize size(BaseMinSize()); 951 // puh, no idea... 952 size.width = 100; 953 return size; 954 } 955 956 957 BAlignment 958 BMenuField::MenuBarLayoutItem::BaseAlignment() 959 { 960 return BAlignment(B_ALIGN_USE_FULL_WIDTH, B_ALIGN_USE_FULL_HEIGHT); 961 } 962 963