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 HeaderView::~HeaderView() 120 { 121 if (fIconModel != fModel) 122 delete fIconModel; 123 } 124 125 126 void 127 HeaderView::ModelChanged(Model* model, BMessage* message) 128 { 129 // Update the icon stuff 130 if (fIconModel != fModel) { 131 delete fIconModel; 132 fIconModel = NULL; 133 } 134 135 fModel = model; 136 if (fModel->IsSymLink()) { 137 // if we are looking at a symlink, deference the model and look 138 // at the target 139 Model* resolvedModel = new Model(model->EntryRef(), true, true); 140 if (resolvedModel->InitCheck() == B_OK) { 141 if (fIconModel != fModel) 142 delete fIconModel; 143 fIconModel = resolvedModel; 144 } else { 145 fIconModel = model; 146 delete resolvedModel; 147 } 148 } 149 150 Invalidate(); 151 } 152 153 154 void 155 HeaderView::ReLinkTargetModel(Model* model) 156 { 157 fModel = model; 158 if (fModel->IsSymLink()) { 159 Model* resolvedModel = new Model(model->EntryRef(), true, true); 160 if (resolvedModel->InitCheck() == B_OK) { 161 if (fIconModel != fModel) 162 delete fIconModel; 163 fIconModel = resolvedModel; 164 } else { 165 fIconModel = fModel; 166 delete resolvedModel; 167 } 168 } 169 Invalidate(); 170 } 171 172 173 void 174 HeaderView::BeginEditingTitle() 175 { 176 if (fTitleEditView != NULL) 177 return; 178 179 BFont font(be_plain_font); 180 font.SetSize(font.Size() + 2); 181 BRect textFrame(fTitleRect); 182 textFrame.right = Bounds().Width() - 5; 183 BRect textRect(textFrame); 184 textRect.OffsetTo(0, 0); 185 textRect.InsetBy(1, 1); 186 187 // Just make it some really large size, since we don't do any line 188 // wrapping. The text filter will make sure to scroll the cursor 189 // into position 190 191 textRect.right = 2000; 192 fTitleEditView = new BTextView(textFrame, "text_editor", 193 textRect, &font, 0, B_FOLLOW_ALL, B_WILL_DRAW); 194 fTitleEditView->SetText(fModel->Name()); 195 DisallowFilenameKeys(fTitleEditView); 196 197 // Reset the width of the text rect 198 textRect = fTitleEditView->TextRect(); 199 textRect.right = fTitleEditView->LineWidth() + 20; 200 fTitleEditView->SetTextRect(textRect); 201 fTitleEditView->SetWordWrap(false); 202 // Add filter for catching B_RETURN and B_ESCAPE key's 203 fTitleEditView->AddFilter( 204 new BMessageFilter(B_KEY_DOWN, HeaderView::TextViewFilter)); 205 206 BScrollView* scrollView = new BScrollView("BorderView", fTitleEditView, 207 0, 0, false, false, B_PLAIN_BORDER); 208 AddChild(scrollView); 209 fTitleEditView->SelectAll(); 210 fTitleEditView->MakeFocus(); 211 212 Window()->UpdateIfNeeded(); 213 } 214 215 216 void 217 HeaderView::FinishEditingTitle(bool commit) 218 { 219 if (fTitleEditView == NULL) 220 return; 221 222 bool reopen = false; 223 224 const char* text = fTitleEditView->Text(); 225 uint32 length = strlen(text); 226 if (commit && strcmp(text, fModel->Name()) != 0 227 && length < B_FILE_NAME_LENGTH) { 228 BEntry entry(fModel->EntryRef()); 229 BDirectory parent; 230 if (entry.InitCheck() == B_OK 231 && entry.GetParent(&parent) == B_OK) { 232 if (parent.Contains(text)) { 233 BAlert* alert = new BAlert("", 234 B_TRANSLATE("That name is already taken. " 235 "Please type another one."), 236 B_TRANSLATE("OK"), 237 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 238 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 239 alert->Go(); 240 reopen = true; 241 } else { 242 if (fModel->IsVolume()) { 243 BVolume volume(fModel->NodeRef()->device); 244 if (volume.InitCheck() == B_OK) 245 volume.SetName(text); 246 } else 247 entry.Rename(text); 248 249 // Adjust the size of the text rect 250 BFont currentFont(be_plain_font); 251 currentFont.SetSize(currentFont.Size() + 2); 252 fTitleRect.right = min_c(fTitleRect.left 253 + currentFont.StringWidth(fTitleEditView->Text()), 254 Bounds().Width() - 5); 255 } 256 } 257 } else if (length >= B_FILE_NAME_LENGTH) { 258 BAlert* alert = new BAlert("", 259 B_TRANSLATE("That name is too long. Please type another one."), 260 B_TRANSLATE("OK"), 261 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT); 262 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); 263 alert->Go(); 264 reopen = true; 265 } 266 267 // Remove view 268 BView* scrollView = fTitleEditView->Parent(); 269 RemoveChild(scrollView); 270 delete scrollView; 271 fTitleEditView = NULL; 272 273 if (reopen) 274 BeginEditingTitle(); 275 } 276 277 278 void 279 HeaderView::Draw(BRect) 280 { 281 // Set the low color for anti-aliasing 282 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 283 284 // Clear the old contents 285 SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 286 FillRect(Bounds()); 287 288 rgb_color labelColor = ui_color(B_PANEL_TEXT_COLOR); 289 290 // Draw the icon, straddling the border 291 SetDrawingMode(B_OP_OVER); 292 IconCache::sIconCache->Draw(fIconModel, this, fIconRect.LeftTop(), 293 kNormalIcon, fIconRect.Size(), true); 294 SetDrawingMode(B_OP_COPY); 295 296 // Font information 297 font_height fontMetrics; 298 BFont currentFont; 299 float lineBase = 0; 300 301 // Draw the main title if the user is not currently editing it 302 if (fTitleEditView == NULL) { 303 SetFont(be_bold_font); 304 SetFontSize(be_bold_font->Size()); 305 GetFont(¤tFont); 306 currentFont.GetHeight(&fontMetrics); 307 lineBase = fTitleRect.bottom - fontMetrics.descent; 308 SetHighColor(labelColor); 309 MovePenTo(BPoint(fIconRect.right + 6, lineBase)); 310 311 // Recalculate the rect width 312 fTitleRect.right = min_c( 313 fTitleRect.left + currentFont.StringWidth(fModel->Name()), 314 Bounds().Width() - 5); 315 // Check for possible need of truncation 316 if (StringWidth(fModel->Name()) > fTitleRect.Width()) { 317 BString nameString(fModel->Name()); 318 TruncateString(&nameString, B_TRUNCATE_END, 319 fTitleRect.Width() - 2); 320 DrawString(nameString.String()); 321 } else 322 DrawString(fModel->Name()); 323 } 324 325 } 326 327 328 void 329 HeaderView::MakeFocus(bool focus) 330 { 331 if (!focus && fTitleEditView != NULL) 332 FinishEditingTitle(true); 333 } 334 335 336 void 337 HeaderView::WindowActivated(bool active) 338 { 339 if (active) 340 return; 341 342 if (fTitleEditView != NULL) 343 FinishEditingTitle(true); 344 } 345 346 347 void 348 HeaderView::MouseDown(BPoint where) 349 { 350 // Assume this isn't part of a double click 351 fDoubleClick = false; 352 353 BEntry entry; 354 fModel->GetEntry(&entry); 355 356 if (fTitleRect.Contains(where)) { 357 if (!fModel->HasLocalizedName() 358 && ConfirmChangeIfWellKnownDirectory(&entry, kRename, true)) { 359 BeginEditingTitle(); 360 } 361 } else if (fTitleEditView) { 362 FinishEditingTitle(true); 363 } else if (fIconRect.Contains(where)) { 364 uint32 buttons; 365 Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); 366 if (SecondaryMouseButtonDown(modifiers(), buttons)) { 367 // Show contextual menu 368 BPopUpMenu* contextMenu 369 = new BPopUpMenu("FileContext", false, false); 370 if (contextMenu) { 371 BuildContextMenu(contextMenu); 372 contextMenu->SetAsyncAutoDestruct(true); 373 contextMenu->Go(ConvertToScreen(where), true, true, 374 ConvertToScreen(fIconRect)); 375 } 376 } else { 377 // Check to see if the point is actually on part of the icon, 378 // versus just in the container rect. The icons are always 379 // the large version 380 BPoint offsetPoint; 381 offsetPoint.x = where.x - fIconRect.left; 382 offsetPoint.y = where.y - fIconRect.top; 383 if (IconCache::sIconCache->IconHitTest(offsetPoint, fIconModel, 384 kNormalIcon, fIconRect.Size())) { 385 // Can't drag the trash anywhere.. 386 fTrackingState = fModel->IsTrash() 387 ? open_only_track : icon_track; 388 389 // Check for possible double click 390 if (abs((int32)(fClickPoint.x - where.x)) < kDragSlop 391 && abs((int32)(fClickPoint.y - where.y)) < kDragSlop) { 392 int32 clickCount; 393 Window()->CurrentMessage()->FindInt32("clicks", 394 &clickCount); 395 396 // This checks the* previous* click point 397 if (clickCount == 2) { 398 offsetPoint.x = fClickPoint.x - fIconRect.left; 399 offsetPoint.y = fClickPoint.y - fIconRect.top; 400 fDoubleClick 401 = IconCache::sIconCache->IconHitTest(offsetPoint, 402 fIconModel, kNormalIcon, fIconRect.Size()); 403 } 404 } 405 } 406 } 407 } 408 409 fClickPoint = where; 410 fMouseDown = true; 411 SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); 412 } 413 414 415 void 416 HeaderView::MouseMoved(BPoint where, uint32, const BMessage* dragMessage) 417 { 418 if (dragMessage != NULL && dragMessage->ReturnAddress() != BMessenger(this) 419 && dragMessage->what == B_SIMPLE_DATA 420 && BPoseView::CanHandleDragSelection(fModel, dragMessage, 421 (modifiers() & B_CONTROL_KEY) != 0)) { 422 // highlight drag target 423 bool overTarget = fIconRect.Contains(where); 424 SetDrawingMode(B_OP_OVER); 425 if (overTarget != fIsDropTarget) { 426 IconCache::sIconCache->Draw(fIconModel, this, fIconRect.LeftTop(), 427 overTarget ? kSelectedIcon : kNormalIcon, fIconRect.Size(), true); 428 fIsDropTarget = overTarget; 429 } 430 } 431 432 switch (fTrackingState) { 433 case icon_track: 434 if (fMouseDown && !fDragging 435 && (abs((int32)(where.x - fClickPoint.x)) > kDragSlop 436 || abs((int32)(where.y - fClickPoint.y)) > kDragSlop)) { 437 // Find the required height 438 BFont font; 439 GetFont(&font); 440 441 float height = CurrentFontHeight() 442 + fIconRect.Height() + 8; 443 BRect rect(0, 0, min_c(fIconRect.Width() 444 + font.StringWidth(fModel->Name()) + 4, 445 fIconRect.Width() * 3), height); 446 BBitmap* dragBitmap = new BBitmap(rect, B_RGBA32, true); 447 dragBitmap->Lock(); 448 BView* view = new BView(dragBitmap->Bounds(), "", 449 B_FOLLOW_NONE, 0); 450 dragBitmap->AddChild(view); 451 view->SetOrigin(0, 0); 452 BRect clipRect(view->Bounds()); 453 BRegion newClip; 454 newClip.Set(clipRect); 455 view->ConstrainClippingRegion(&newClip); 456 457 // Transparent draw magic 458 view->SetHighColor(0, 0, 0, 0); 459 view->FillRect(view->Bounds()); 460 view->SetDrawingMode(B_OP_ALPHA); 461 rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR); 462 textColor.alpha = 128; 463 // set transparency by value 464 view->SetHighColor(textColor); 465 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_COMPOSITE); 466 467 // Draw the icon 468 float hIconOffset = (rect.Width() - fIconRect.Width()) / 2; 469 IconCache::sIconCache->Draw(fIconModel, view, 470 BPoint(hIconOffset, 0), kNormalIcon, fIconRect.Size(), true); 471 472 // See if we need to truncate the string 473 BString nameString(fModel->Name()); 474 if (view->StringWidth(fModel->Name()) > rect.Width()) { 475 view->TruncateString(&nameString, B_TRUNCATE_END, 476 rect.Width() - 5); 477 } 478 479 // Draw the label 480 font_height fontHeight; 481 font.GetHeight(&fontHeight); 482 float leftText = (view->StringWidth(nameString.String()) 483 - fIconRect.Width()) / 2; 484 view->MovePenTo(BPoint(hIconOffset - leftText + 2, 485 fIconRect.Height() + (fontHeight.ascent + 2))); 486 view->DrawString(nameString.String()); 487 488 view->Sync(); 489 dragBitmap->Unlock(); 490 491 BMessage dragMessage(B_REFS_RECEIVED); 492 dragMessage.AddPoint("click_pt", fClickPoint); 493 BPoint tmpLoc; 494 uint32 button; 495 GetMouse(&tmpLoc, &button); 496 if (button) 497 dragMessage.AddInt32("buttons", (int32)button); 498 499 dragMessage.AddInt32("be:actions", 500 (modifiers() & B_OPTION_KEY) != 0 501 ? B_COPY_TARGET : B_MOVE_TARGET); 502 dragMessage.AddRef("refs", fModel->EntryRef()); 503 DragMessage(&dragMessage, dragBitmap, B_OP_ALPHA, 504 BPoint((fClickPoint.x - fIconRect.left) 505 + hIconOffset, fClickPoint.y - fIconRect.top), this); 506 fDragging = true; 507 } 508 break; 509 510 case open_only_track : 511 // Special type of entry that can't be renamed or drag and dropped 512 // It can only be opened by double clicking on the icon 513 break; 514 515 case no_track: 516 // No mouse tracking, do nothing 517 break; 518 } 519 } 520 521 522 void 523 HeaderView::MouseUp(BPoint where) 524 { 525 if ((fTrackingState == icon_track 526 || fTrackingState == open_only_track) 527 && fIconRect.Contains(where)) { 528 // If it was a double click, then tell Tracker to open the item 529 // The CurrentMessage() here does* not* have a "clicks" field, 530 // which is why we are tracking the clicks with this temp var 531 if (fDoubleClick) { 532 // Double click, launch. 533 BMessage message(B_REFS_RECEIVED); 534 message.AddRef("refs", fModel->EntryRef()); 535 536 // add a messenger to the launch message that will be used to 537 // dispatch scripting calls from apps to the PoseView 538 message.AddMessenger("TrackerViewToken", BMessenger(this)); 539 be_app->PostMessage(&message); 540 fDoubleClick = false; 541 } 542 } 543 544 // End mouse tracking 545 fMouseDown = false; 546 fDragging = false; 547 fTrackingState = no_track; 548 } 549 550 551 void 552 HeaderView::MessageReceived(BMessage* message) 553 { 554 if (message->WasDropped() 555 && message->what == B_SIMPLE_DATA 556 && message->ReturnAddress() != BMessenger(this) 557 && fIconRect.Contains(ConvertFromScreen(message->DropPoint())) 558 && BPoseView::CanHandleDragSelection(fModel, message, 559 (modifiers() & B_CONTROL_KEY) != 0)) { 560 BPoseView::HandleDropCommon(message, fModel, 0, this, 561 message->DropPoint()); 562 Invalidate(fIconRect); 563 return; 564 } 565 566 BView::MessageReceived(message); 567 } 568 569 570 571 status_t 572 HeaderView::BuildContextMenu(BMenu* parent) 573 { 574 if (parent == NULL) 575 return B_BAD_VALUE; 576 577 // Add navigation menu if this is not a symlink 578 // Symlink's to directories are OK however! 579 BEntry entry(fModel->EntryRef()); 580 entry_ref ref; 581 entry.GetRef(&ref); 582 Model model(&entry); 583 bool navigate = false; 584 if (model.InitCheck() == B_OK) { 585 if (model.IsSymLink()) { 586 // Check if it's to a directory 587 if (entry.SetTo(model.EntryRef(), true) == B_OK) { 588 navigate = entry.IsDirectory(); 589 entry.GetRef(&ref); 590 } 591 } else if (model.IsDirectory() || model.IsVolume()) 592 navigate = true; 593 } 594 ModelMenuItem* navigationItem = NULL; 595 if (navigate) { 596 navigationItem = new ModelMenuItem(new Model(model), 597 new BNavMenu(model.Name(), B_REFS_RECEIVED, be_app, Window())); 598 599 // setup a navigation menu item which will dynamically load items 600 // as menu items are traversed 601 BNavMenu* navMenu = dynamic_cast<BNavMenu*>(navigationItem->Submenu()); 602 if (navMenu != NULL) 603 navMenu->SetNavDir(&ref); 604 605 navigationItem->SetLabel(model.Name()); 606 navigationItem->SetEntry(&entry); 607 608 parent->AddItem(navigationItem, 0); 609 parent->AddItem(new BSeparatorItem(), 1); 610 611 BMessage* message = new BMessage(B_REFS_RECEIVED); 612 message->AddRef("refs", &ref); 613 navigationItem->SetMessage(message); 614 navigationItem->SetTarget(be_app); 615 } 616 617 parent->AddItem(new BMenuItem(B_TRANSLATE("Open"), 618 new BMessage(kOpenSelection), 'O')); 619 620 if (!model.IsDesktop() && !model.IsRoot() && !model.IsTrash() 621 && !fModel->HasLocalizedName()) { 622 parent->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), 623 new BMessage(kEditItem), 'E')); 624 parent->AddSeparatorItem(); 625 626 if (fModel->IsVolume()) { 627 BMenuItem* item = new BMenuItem(B_TRANSLATE("Unmount"), 628 new BMessage(kUnmountVolume), 'U'); 629 parent->AddItem(item); 630 // volume model, enable/disable the Unmount item 631 BVolume boot; 632 BVolumeRoster().GetBootVolume(&boot); 633 BVolume volume; 634 volume.SetTo(fModel->NodeRef()->device); 635 if (volume == boot) 636 item->SetEnabled(false); 637 } 638 } 639 640 if (!model.IsRoot() && !model.IsVolume() && !model.IsTrash()) 641 parent->AddItem(new BMenuItem(B_TRANSLATE("Identify"), 642 new BMessage(kIdentifyEntry))); 643 644 if (model.IsTrash()) 645 parent->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"), 646 new BMessage(kEmptyTrash))); 647 648 BMenuItem* sizeItem = NULL; 649 if (model.IsDirectory() && !model.IsVolume() && !model.IsRoot()) { 650 parent->AddItem(sizeItem 651 = new BMenuItem(B_TRANSLATE("Recalculate folder size"), 652 new BMessage(kRecalculateSize))); 653 } 654 655 if (model.IsSymLink()) { 656 parent->AddItem(sizeItem 657 = new BMenuItem(B_TRANSLATE("Set new link target"), 658 new BMessage(kSetLinkTarget))); 659 } 660 661 parent->AddItem(new BSeparatorItem()); 662 parent->AddItem(new BMenuItem(B_TRANSLATE("Permissions"), 663 new BMessage(kPermissionsSelected), 'P')); 664 665 parent->SetFont(be_plain_font); 666 parent->SetTargetForItems(this); 667 668 // Reset the nav menu to be_app 669 if (navigate) 670 navigationItem->SetTarget(be_app); 671 if (sizeItem) 672 sizeItem->SetTarget(Window()); 673 674 return B_OK; 675 } 676 677 678 filter_result 679 HeaderView::TextViewFilter(BMessage* message, BHandler**, 680 BMessageFilter* filter) 681 { 682 uchar key; 683 HeaderView* attribView = static_cast<HeaderView*>( 684 static_cast<BWindow*>(filter->Looper())->FindView("header")); 685 686 // Adjust the size of the text rect 687 BRect nuRect(attribView->TextView()->TextRect()); 688 nuRect.right = attribView->TextView()->LineWidth() + 20; 689 attribView->TextView()->SetTextRect(nuRect); 690 691 // Make sure the cursor is in view 692 attribView->TextView()->ScrollToSelection(); 693 if (message->FindInt8("byte", (int8*)&key) != B_OK) 694 return B_DISPATCH_MESSAGE; 695 696 if (key == B_RETURN || key == B_ESCAPE) { 697 attribView->FinishEditingTitle(key == B_RETURN); 698 return B_SKIP_MESSAGE; 699 } 700 701 return B_DISPATCH_MESSAGE; 702 } 703 704 705 float 706 HeaderView::CurrentFontHeight() 707 { 708 BFont font; 709 GetFont(&font); 710 font_height fontHeight; 711 font.GetHeight(&fontHeight); 712 713 return fontHeight.ascent + fontHeight.descent + fontHeight.leading + 2; 714 } 715