1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 36 #include "HeaderView.h" 37 38 #include <Alert.h> 39 #include <Application.h> 40 #include <Catalog.h> 41 #include <ControlLook.h> 42 #include <Locale.h> 43 #include <PopUpMenu.h> 44 #include <ScrollView.h> 45 #include <Volume.h> 46 #include <VolumeRoster.h> 47 #include <Window.h> 48 49 #include "Commands.h" 50 #include "FSUtils.h" 51 #include "GeneralInfoView.h" 52 #include "IconMenuItem.h" 53 #include "Model.h" 54 #include "NavMenu.h" 55 #include "PoseView.h" 56 #include "Tracker.h" 57 58 59 #undef B_TRANSLATION_CONTEXT 60 #define B_TRANSLATION_CONTEXT "InfoWindow" 61 62 63 // Amount you have to move the mouse before a drag starts 64 const float kDragSlop = 3.0f; 65 66 67 HeaderView::HeaderView(Model* model) 68 : 69 BView("header", B_WILL_DRAW), 70 fModel(model), 71 fIconModel(model), 72 fTitleEditView(NULL), 73 fTrackingState(no_track), 74 fMouseDown(false), 75 fIsDropTarget(false), 76 fDoubleClick(false), 77 fDragging(false) 78 { 79 const float labelSpacing = be_control_look->DefaultLabelSpacing(); 80 fIconRect = BRect(BPoint(labelSpacing * 3.0f, labelSpacing), 81 be_control_look->ComposeIconSize(B_LARGE_ICON)); 82 SetExplicitSize(BSize(B_SIZE_UNSET, fIconRect.Width() + 2 * fIconRect.top)); 83 84 // The title rect 85 // The magic numbers are used to properly calculate the rect so that 86 // when the editing text view is displayed, the position of the text 87 // does not change. 88 BFont currentFont; 89 font_height fontMetrics; 90 GetFont(¤tFont); 91 currentFont.GetHeight(&fontMetrics); 92 93 fTitleRect.left = fIconRect.right + labelSpacing; 94 fTitleRect.top = 0; 95 fTitleRect.bottom = fontMetrics.ascent + 1; 96 fTitleRect.right = min_c( 97 fTitleRect.left + currentFont.StringWidth(fModel->Name()), 98 Bounds().Width() - labelSpacing); 99 // Offset so that it centers with the icon 100 fTitleRect.OffsetBy(0, 101 fIconRect.top + ((fIconRect.Height() - fTitleRect.Height()) / 2)); 102 // Make some room for the border for when we are in edit mode 103 // (Negative numbers increase the size of the rect) 104 fTitleRect.InsetBy(-1, -2); 105 106 // If the model is a symlink, then we deference the model to 107 // get the targets icon 108 if (fModel->IsSymLink()) { 109 Model* resolvedModel = new Model(model->EntryRef(), true, true); 110 if (resolvedModel->InitCheck() == B_OK) 111 fIconModel = resolvedModel; 112 // broken link, just show the symlink 113 else 114 delete resolvedModel; 115 } 116 117 } 118 119 120 HeaderView::~HeaderView() 121 { 122 if (fIconModel != fModel) 123 delete fIconModel; 124 } 125 126 127 void 128 HeaderView::ModelChanged(Model* model, BMessage* message) 129 { 130 // Update the icon stuff 131 if (fIconModel != fModel) { 132 delete fIconModel; 133 fIconModel = NULL; 134 } 135 136 fModel = model; 137 if (fModel->IsSymLink()) { 138 // if we are looking at a symlink, deference the model and look 139 // at the target 140 Model* resolvedModel = new Model(model->EntryRef(), true, true); 141 if (resolvedModel->InitCheck() == B_OK) { 142 if (fIconModel != fModel) 143 delete fIconModel; 144 fIconModel = resolvedModel; 145 } else { 146 fIconModel = model; 147 delete resolvedModel; 148 } 149 } 150 151 Invalidate(); 152 } 153 154 155 void 156 HeaderView::ReLinkTargetModel(Model* model) 157 { 158 fModel = model; 159 if (fModel->IsSymLink()) { 160 Model* resolvedModel = new Model(model->EntryRef(), true, true); 161 if (resolvedModel->InitCheck() == B_OK) { 162 if (fIconModel != fModel) 163 delete fIconModel; 164 fIconModel = resolvedModel; 165 } else { 166 fIconModel = fModel; 167 delete resolvedModel; 168 } 169 } 170 Invalidate(); 171 } 172 173 174 void 175 HeaderView::BeginEditingTitle() 176 { 177 if (fTitleEditView != NULL) 178 return; 179 180 BFont font(be_plain_font); 181 font.SetSize(font.Size() + 2); 182 BRect textFrame(fTitleRect); 183 textFrame.right = Bounds().Width() - 5; 184 BRect textRect(textFrame); 185 textRect.OffsetTo(0, 0); 186 textRect.InsetBy(1, 1); 187 188 // Just make it some really large size, since we don't do any line 189 // wrapping. The text filter will make sure to scroll the cursor 190 // into position 191 192 textRect.right = 2000; 193 fTitleEditView = new BTextView(textFrame, "text_editor", 194 textRect, &font, 0, B_FOLLOW_ALL, B_WILL_DRAW); 195 fTitleEditView->SetText(fModel->Name()); 196 DisallowFilenameKeys(fTitleEditView); 197 198 // Reset the width of the text rect 199 textRect = fTitleEditView->TextRect(); 200 textRect.right = fTitleEditView->LineWidth() + 20; 201 fTitleEditView->SetTextRect(textRect); 202 fTitleEditView->SetWordWrap(false); 203 // Add filter for catching B_RETURN and B_ESCAPE key's 204 fTitleEditView->AddFilter( 205 new BMessageFilter(B_KEY_DOWN, HeaderView::TextViewFilter)); 206 207 BScrollView* scrollView = new BScrollView("BorderView", fTitleEditView, 208 0, 0, false, false, B_PLAIN_BORDER); 209 AddChild(scrollView); 210 fTitleEditView->SelectAll(); 211 fTitleEditView->MakeFocus(); 212 213 Window()->UpdateIfNeeded(); 214 } 215 216 217 void 218 HeaderView::FinishEditingTitle(bool commit) 219 { 220 if (fTitleEditView == NULL) 221 return; 222 223 bool reopen = false; 224 225 const char* text = fTitleEditView->Text(); 226 uint32 length = strlen(text); 227 if (commit && strcmp(text, fModel->Name()) != 0 228 && length < B_FILE_NAME_LENGTH) { 229 BEntry entry(fModel->EntryRef()); 230 BDirectory parent; 231 if (entry.InitCheck() == B_OK 232 && entry.GetParent(&parent) == B_OK) { 233 if (parent.Contains(text)) { 234 BAlert* alert = new BAlert("", 235 B_TRANSLATE("That name is already taken. " 236 "Please type another one."), 237 B_TRANSLATE("OK"), 238 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 239 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 240 alert->Go(); 241 reopen = true; 242 } else { 243 if (fModel->IsVolume()) { 244 BVolume volume(fModel->NodeRef()->device); 245 if (volume.InitCheck() == B_OK) 246 volume.SetName(text); 247 } else 248 entry.Rename(text); 249 250 // Adjust the size of the text rect 251 BFont currentFont(be_plain_font); 252 currentFont.SetSize(currentFont.Size() + 2); 253 fTitleRect.right = min_c(fTitleRect.left 254 + currentFont.StringWidth(fTitleEditView->Text()), 255 Bounds().Width() - 5); 256 } 257 } 258 } else if (length >= B_FILE_NAME_LENGTH) { 259 BAlert* alert = new BAlert("", 260 B_TRANSLATE("That name is too long. Please type another one."), 261 B_TRANSLATE("OK"), 262 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 263 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 264 alert->Go(); 265 reopen = true; 266 } 267 268 // Remove view 269 BView* scrollView = fTitleEditView->Parent(); 270 RemoveChild(scrollView); 271 delete scrollView; 272 fTitleEditView = NULL; 273 274 if (reopen) 275 BeginEditingTitle(); 276 } 277 278 279 void 280 HeaderView::Draw(BRect) 281 { 282 // Set the low color for anti-aliasing 283 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 284 285 // Clear the old contents 286 SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 287 FillRect(Bounds()); 288 289 rgb_color labelColor = ui_color(B_PANEL_TEXT_COLOR); 290 291 // Draw the icon, straddling the border 292 SetDrawingMode(B_OP_OVER); 293 IconCache::sIconCache->Draw(fIconModel, this, fIconRect.LeftTop(), 294 kNormalIcon, fIconRect.Size(), true); 295 SetDrawingMode(B_OP_COPY); 296 297 // Font information 298 font_height fontMetrics; 299 BFont currentFont; 300 float lineBase = 0; 301 302 // Draw the main title if the user is not currently editing it 303 if (fTitleEditView == NULL) { 304 SetFont(be_bold_font); 305 SetFontSize(be_bold_font->Size()); 306 GetFont(¤tFont); 307 currentFont.GetHeight(&fontMetrics); 308 lineBase = fTitleRect.bottom - fontMetrics.descent; 309 SetHighColor(labelColor); 310 MovePenTo(BPoint(fIconRect.right + 6, lineBase)); 311 312 // Recalculate the rect width 313 fTitleRect.right = min_c( 314 fTitleRect.left + currentFont.StringWidth(fModel->Name()), 315 Bounds().Width() - 5); 316 // Check for possible need of truncation 317 if (StringWidth(fModel->Name()) > fTitleRect.Width()) { 318 BString nameString(fModel->Name()); 319 TruncateString(&nameString, B_TRUNCATE_END, 320 fTitleRect.Width() - 2); 321 DrawString(nameString.String()); 322 } else 323 DrawString(fModel->Name()); 324 } 325 326 } 327 328 329 void 330 HeaderView::MakeFocus(bool focus) 331 { 332 if (!focus && fTitleEditView != NULL) 333 FinishEditingTitle(true); 334 } 335 336 337 void 338 HeaderView::WindowActivated(bool active) 339 { 340 if (active) 341 return; 342 343 if (fTitleEditView != NULL) 344 FinishEditingTitle(true); 345 } 346 347 348 void 349 HeaderView::MouseDown(BPoint where) 350 { 351 // Assume this isn't part of a double click 352 fDoubleClick = false; 353 354 BEntry entry; 355 fModel->GetEntry(&entry); 356 357 if (fTitleRect.Contains(where)) { 358 if (!fModel->HasLocalizedName() 359 && ConfirmChangeIfWellKnownDirectory(&entry, kRename, true)) { 360 BeginEditingTitle(); 361 } 362 } else if (fTitleEditView) { 363 FinishEditingTitle(true); 364 } else if (fIconRect.Contains(where)) { 365 uint32 buttons; 366 Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); 367 if (SecondaryMouseButtonDown(modifiers(), buttons)) { 368 // Show contextual menu 369 BPopUpMenu* contextMenu 370 = new BPopUpMenu("FileContext", false, false); 371 if (contextMenu) { 372 BuildContextMenu(contextMenu); 373 contextMenu->SetAsyncAutoDestruct(true); 374 contextMenu->Go(ConvertToScreen(where), true, true, 375 ConvertToScreen(fIconRect)); 376 } 377 } else { 378 // Check to see if the point is actually on part of the icon, 379 // versus just in the container rect. The icons are always 380 // the large version 381 BPoint offsetPoint; 382 offsetPoint.x = where.x - fIconRect.left; 383 offsetPoint.y = where.y - fIconRect.top; 384 if (IconCache::sIconCache->IconHitTest(offsetPoint, fIconModel, 385 kNormalIcon, fIconRect.Size())) { 386 // Can't drag the trash anywhere.. 387 fTrackingState = fModel->IsTrash() 388 ? open_only_track : icon_track; 389 390 // Check for possible double click 391 if (abs((int32)(fClickPoint.x - where.x)) < kDragSlop 392 && abs((int32)(fClickPoint.y - where.y)) < kDragSlop) { 393 int32 clickCount; 394 Window()->CurrentMessage()->FindInt32("clicks", 395 &clickCount); 396 397 // This checks the* previous* click point 398 if (clickCount == 2) { 399 offsetPoint.x = fClickPoint.x - fIconRect.left; 400 offsetPoint.y = fClickPoint.y - fIconRect.top; 401 fDoubleClick 402 = IconCache::sIconCache->IconHitTest(offsetPoint, 403 fIconModel, kNormalIcon, fIconRect.Size()); 404 } 405 } 406 } 407 } 408 } 409 410 fClickPoint = where; 411 fMouseDown = true; 412 SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); 413 } 414 415 416 void 417 HeaderView::MouseMoved(BPoint where, uint32, const BMessage* dragMessage) 418 { 419 if (dragMessage != NULL && dragMessage->ReturnAddress() != BMessenger(this) 420 && dragMessage->what == B_SIMPLE_DATA 421 && BPoseView::CanHandleDragSelection(fModel, dragMessage, 422 (modifiers() & B_CONTROL_KEY) != 0)) { 423 // highlight drag target 424 bool overTarget = fIconRect.Contains(where); 425 SetDrawingMode(B_OP_OVER); 426 if (overTarget != fIsDropTarget) { 427 IconCache::sIconCache->Draw(fIconModel, this, fIconRect.LeftTop(), 428 overTarget ? kSelectedIcon : kNormalIcon, fIconRect.Size(), true); 429 fIsDropTarget = overTarget; 430 } 431 } 432 433 switch (fTrackingState) { 434 case icon_track: 435 if (fMouseDown && !fDragging 436 && (abs((int32)(where.x - fClickPoint.x)) > kDragSlop 437 || abs((int32)(where.y - fClickPoint.y)) > kDragSlop)) { 438 // Find the required height 439 BFont font; 440 GetFont(&font); 441 442 float height = CurrentFontHeight() 443 + fIconRect.Height() + 8; 444 BRect rect(0, 0, min_c(fIconRect.Width() 445 + font.StringWidth(fModel->Name()) + 4, 446 fIconRect.Width() * 3), height); 447 BBitmap* dragBitmap = new BBitmap(rect, B_RGBA32, true); 448 dragBitmap->Lock(); 449 BView* view = new BView(dragBitmap->Bounds(), "", 450 B_FOLLOW_NONE, 0); 451 dragBitmap->AddChild(view); 452 view->SetOrigin(0, 0); 453 BRect clipRect(view->Bounds()); 454 BRegion newClip; 455 newClip.Set(clipRect); 456 view->ConstrainClippingRegion(&newClip); 457 458 // Transparent draw magic 459 view->SetHighColor(0, 0, 0, 0); 460 view->FillRect(view->Bounds()); 461 view->SetDrawingMode(B_OP_ALPHA); 462 rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR); 463 textColor.alpha = 128; 464 // set transparency by value 465 view->SetHighColor(textColor); 466 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); 467 468 // Draw the icon 469 float hIconOffset = (rect.Width() - fIconRect.Width()) / 2; 470 IconCache::sIconCache->Draw(fIconModel, view, 471 BPoint(hIconOffset, 0), kNormalIcon, fIconRect.Size(), true); 472 473 // See if we need to truncate the string 474 BString nameString(fModel->Name()); 475 if (view->StringWidth(fModel->Name()) > rect.Width()) { 476 view->TruncateString(&nameString, B_TRUNCATE_END, 477 rect.Width() - 5); 478 } 479 480 // Draw the label 481 font_height fontHeight; 482 font.GetHeight(&fontHeight); 483 float leftText = (view->StringWidth(nameString.String()) 484 - fIconRect.Width()) / 2; 485 view->MovePenTo(BPoint(hIconOffset - leftText + 2, 486 fIconRect.Height() + (fontHeight.ascent + 2))); 487 view->DrawString(nameString.String()); 488 489 view->Sync(); 490 dragBitmap->Unlock(); 491 492 BMessage dragMessage(B_REFS_RECEIVED); 493 dragMessage.AddPoint("click_pt", fClickPoint); 494 BPoint tmpLoc; 495 uint32 button; 496 GetMouse(&tmpLoc, &button); 497 if (button) 498 dragMessage.AddInt32("buttons", (int32)button); 499 500 dragMessage.AddInt32("be:actions", 501 (modifiers() & B_OPTION_KEY) != 0 502 ? B_COPY_TARGET : B_MOVE_TARGET); 503 dragMessage.AddRef("refs", fModel->EntryRef()); 504 DragMessage(&dragMessage, dragBitmap, B_OP_ALPHA, 505 BPoint((fClickPoint.x - fIconRect.left) 506 + hIconOffset, fClickPoint.y - fIconRect.top), this); 507 fDragging = true; 508 } 509 break; 510 511 case open_only_track : 512 // Special type of entry that can't be renamed or drag and dropped 513 // It can only be opened by double clicking on the icon 514 break; 515 516 case no_track: 517 // No mouse tracking, do nothing 518 break; 519 } 520 } 521 522 523 void 524 HeaderView::MouseUp(BPoint where) 525 { 526 if ((fTrackingState == icon_track 527 || fTrackingState == open_only_track) 528 && fIconRect.Contains(where)) { 529 // If it was a double click, then tell Tracker to open the item 530 // The CurrentMessage() here does* not* have a "clicks" field, 531 // which is why we are tracking the clicks with this temp var 532 if (fDoubleClick) { 533 // Double click, launch. 534 BMessage message(B_REFS_RECEIVED); 535 message.AddRef("refs", fModel->EntryRef()); 536 537 // add a messenger to the launch message that will be used to 538 // dispatch scripting calls from apps to the PoseView 539 message.AddMessenger("TrackerViewToken", BMessenger(this)); 540 be_app->PostMessage(&message); 541 fDoubleClick = false; 542 } 543 } 544 545 // End mouse tracking 546 fMouseDown = false; 547 fDragging = false; 548 fTrackingState = no_track; 549 } 550 551 552 void 553 HeaderView::MessageReceived(BMessage* message) 554 { 555 if (message->WasDropped() 556 && message->what == B_SIMPLE_DATA 557 && message->ReturnAddress() != BMessenger(this) 558 && fIconRect.Contains(ConvertFromScreen(message->DropPoint())) 559 && BPoseView::CanHandleDragSelection(fModel, message, 560 (modifiers() & B_CONTROL_KEY) != 0)) { 561 BPoseView::HandleDropCommon(message, fModel, 0, this, 562 message->DropPoint()); 563 Invalidate(fIconRect); 564 return; 565 } 566 567 BView::MessageReceived(message); 568 } 569 570 571 572 status_t 573 HeaderView::BuildContextMenu(BMenu* parent) 574 { 575 if (parent == NULL) 576 return B_BAD_VALUE; 577 578 // Add navigation menu if this is not a symlink 579 // Symlink's to directories are OK however! 580 BEntry entry(fModel->EntryRef()); 581 entry_ref ref; 582 entry.GetRef(&ref); 583 Model model(&entry); 584 bool navigate = false; 585 if (model.InitCheck() == B_OK) { 586 if (model.IsSymLink()) { 587 // Check if it's to a directory 588 if (entry.SetTo(model.EntryRef(), true) == B_OK) { 589 navigate = entry.IsDirectory(); 590 entry.GetRef(&ref); 591 } 592 } else if (model.IsDirectory() || model.IsVolume()) 593 navigate = true; 594 } 595 ModelMenuItem* navigationItem = NULL; 596 if (navigate) { 597 navigationItem = new ModelMenuItem(new Model(model), 598 new BNavMenu(model.Name(), B_REFS_RECEIVED, be_app, Window())); 599 600 // setup a navigation menu item which will dynamically load items 601 // as menu items are traversed 602 BNavMenu* navMenu = dynamic_cast<BNavMenu*>(navigationItem->Submenu()); 603 if (navMenu != NULL) 604 navMenu->SetNavDir(&ref); 605 606 navigationItem->SetLabel(model.Name()); 607 navigationItem->SetEntry(&entry); 608 609 parent->AddItem(navigationItem, 0); 610 parent->AddItem(new BSeparatorItem(), 1); 611 612 BMessage* message = new BMessage(B_REFS_RECEIVED); 613 message->AddRef("refs", &ref); 614 navigationItem->SetMessage(message); 615 navigationItem->SetTarget(be_app); 616 } 617 618 parent->AddItem(new BMenuItem(B_TRANSLATE("Open"), 619 new BMessage(kOpenSelection), 'O')); 620 621 if (!model.IsDesktop() && !model.IsRoot() && !model.IsTrash() 622 && !fModel->HasLocalizedName()) { 623 parent->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), 624 new BMessage(kEditItem), 'E')); 625 parent->AddSeparatorItem(); 626 627 if (fModel->IsVolume()) { 628 BMenuItem* item = new BMenuItem(B_TRANSLATE("Unmount"), 629 new BMessage(kUnmountVolume), 'U'); 630 parent->AddItem(item); 631 // volume model, enable/disable the Unmount item 632 BVolume boot; 633 BVolumeRoster().GetBootVolume(&boot); 634 BVolume volume; 635 volume.SetTo(fModel->NodeRef()->device); 636 if (volume == boot) 637 item->SetEnabled(false); 638 } 639 } 640 641 if (!model.IsRoot() && !model.IsVolume() && !model.IsTrash()) 642 parent->AddItem(new BMenuItem(B_TRANSLATE("Identify"), 643 new BMessage(kIdentifyEntry))); 644 645 if (model.IsTrash()) 646 parent->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"), 647 new BMessage(kEmptyTrash))); 648 649 BMenuItem* sizeItem = NULL; 650 if (model.IsDirectory() && !model.IsVolume() && !model.IsRoot()) { 651 parent->AddItem(sizeItem 652 = new BMenuItem(B_TRANSLATE("Recalculate folder size"), 653 new BMessage(kRecalculateSize))); 654 } 655 656 if (model.IsSymLink()) { 657 parent->AddItem(sizeItem 658 = new BMenuItem(B_TRANSLATE("Set new link target"), 659 new BMessage(kSetLinkTarget))); 660 } 661 662 parent->AddItem(new BSeparatorItem()); 663 parent->AddItem(new BMenuItem(B_TRANSLATE("Permissions"), 664 new BMessage(kPermissionsSelected), 'P')); 665 666 parent->SetFont(be_plain_font); 667 parent->SetTargetForItems(this); 668 669 // Reset the nav menu to be_app 670 if (navigate) 671 navigationItem->SetTarget(be_app); 672 if (sizeItem) 673 sizeItem->SetTarget(Window()); 674 675 return B_OK; 676 } 677 678 679 filter_result 680 HeaderView::TextViewFilter(BMessage* message, BHandler**, 681 BMessageFilter* filter) 682 { 683 uchar key; 684 HeaderView* attribView = static_cast<HeaderView*>( 685 static_cast<BWindow*>(filter->Looper())->FindView("header")); 686 687 // Adjust the size of the text rect 688 BRect nuRect(attribView->TextView()->TextRect()); 689 nuRect.right = attribView->TextView()->LineWidth() + 20; 690 attribView->TextView()->SetTextRect(nuRect); 691 692 // Make sure the cursor is in view 693 attribView->TextView()->ScrollToSelection(); 694 if (message->FindInt8("byte", (int8*)&key) != B_OK) 695 return B_DISPATCH_MESSAGE; 696 697 if (key == B_RETURN || key == B_ESCAPE) { 698 attribView->FinishEditingTitle(key == B_RETURN); 699 return B_SKIP_MESSAGE; 700 } 701 702 return B_DISPATCH_MESSAGE; 703 } 704 705 706 float 707 HeaderView::CurrentFontHeight() 708 { 709 BFont font; 710 GetFont(&font); 711 font_height fontHeight; 712 font.GetHeight(&fontHeight); 713 714 return fontHeight.ascent + fontHeight.descent + fontHeight.leading + 2; 715 } 716 717 718