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 #ifndef _POSE_VIEW_H 35 #define _POSE_VIEW_H 36 37 38 // BPoseView is a container for poses, handling all of the interaction, drawing, 39 // etc. The three different view modes are handled here. 40 // 41 // this is by far the fattest Tracker class and over time will undergo a lot of 42 // trimming 43 44 45 #include "AttributeStream.h" 46 #include "ContainerWindow.h" 47 #include "Model.h" 48 #include "PendingNodeMonitorCache.h" 49 #include "PoseList.h" 50 #include "TitleView.h" 51 #include "Utilities.h" 52 #include "ViewState.h" 53 54 #include <ColorConversion.h> 55 #include <Directory.h> 56 #include <FilePanel.h> 57 #include <HashSet.h> 58 #include <MessageRunner.h> 59 #include <String.h> 60 #include <ScrollBar.h> 61 #include <View.h> 62 #include <set> 63 64 65 class BRefFilter; 66 class BList; 67 68 namespace BPrivate { 69 70 class BCountView; 71 class BContainerWindow; 72 class EntryListBase; 73 class TScrollBar; 74 75 76 const uint32 kMiniIconMode = 'Tmic'; 77 const uint32 kIconMode = 'Ticn'; 78 const uint32 kListMode = 'Tlst'; 79 80 const uint32 kCheckTypeahead = 'Tcty'; 81 82 class BPoseView : public BView { 83 public: 84 BPoseView(Model*, uint32 viewMode); 85 virtual ~BPoseView(); 86 87 // setup, teardown 88 virtual void Init(AttributeStreamNode*); 89 virtual void Init(const BMessage&); 90 void InitCommon(); 91 virtual void DetachedFromWindow(); 92 93 // Returns true if for instance, node ref is a remote desktop 94 // directory and this is a desktop pose view. 95 virtual bool Represents(const node_ref*) const; 96 virtual bool Represents(const entry_ref*) const; 97 98 BContainerWindow* ContainerWindow() const; 99 const char* ViewStateAttributeName() const; 100 const char* ForeignViewStateAttributeName() const; 101 Model* TargetModel() const; 102 103 virtual bool IsFilePanel() const; 104 bool IsDesktopWindow() const; 105 virtual bool IsDesktopView() const; 106 107 // state saving/restoring 108 virtual void SaveState(AttributeStreamNode* node); 109 virtual void RestoreState(AttributeStreamNode*); 110 virtual void RestoreColumnState(AttributeStreamNode*); 111 void AddColumnList(BObjectList<BColumn>*list); 112 virtual void SaveColumnState(AttributeStreamNode*); 113 virtual void SavePoseLocations(BRect* frameIfDesktop = NULL); 114 void DisableSaveLocation(); 115 116 virtual void SaveState(BMessage&) const; 117 virtual void RestoreState(const BMessage&); 118 virtual void RestoreColumnState(const BMessage&); 119 virtual void SaveColumnState(BMessage&) const; 120 121 bool StateNeedsSaving(); 122 123 // switch between mini icon mode, icon mode and list mode 124 virtual void SetViewMode(uint32 mode); 125 uint32 ViewMode() const; 126 127 // re-use the pose view for a new directory 128 virtual void SwitchDir(const entry_ref*, 129 AttributeStreamNode* node = NULL); 130 131 // in the rare cases where a pose view needs to be explicitly 132 // refreshed (for instance in a query window with a dynamic 133 // date query), this is used 134 virtual void Refresh(); 135 136 // callbacks 137 virtual void MessageReceived(BMessage* message); 138 virtual void AttachedToWindow(); 139 virtual void WindowActivated(bool active); 140 virtual void MakeFocus(bool = true); 141 virtual BSize MinSize(); 142 virtual void Draw(BRect update_rect); 143 virtual void DrawAfterChildren(BRect update_rect); 144 virtual void MouseMoved(BPoint, uint32, const BMessage*); 145 virtual void MouseDown(BPoint where); 146 virtual void MouseUp(BPoint where); 147 virtual void MouseDragged(const BMessage*); 148 virtual void MouseLongDown(const BMessage*); 149 virtual void MouseIdle(const BMessage*); 150 virtual void KeyDown(const char*, int32); 151 virtual void Pulse(); 152 virtual void ScrollTo(BPoint); 153 154 // misc. mode setters 155 void SetMultipleSelection(bool); 156 void SetDragEnabled(bool); 157 void SetDropEnabled(bool); 158 void SetSelectionRectEnabled(bool); 159 void SetAlwaysAutoPlace(bool); 160 void SetSelectionChangedHook(bool); 161 void SetEnsurePosesVisible(bool); 162 void SetIconMapping(bool); 163 void SetAutoScroll(bool); 164 void SetPoseEditing(bool); 165 166 void UpdateIcon(BPose* pose); 167 168 // file change notification handler 169 virtual bool FSNotification(const BMessage*); 170 171 // scrollbars 172 virtual void UpdateScrollRange(); 173 virtual void SetScrollBarsTo(BPoint); 174 virtual void AddScrollBars(); 175 BScrollBar* HScrollBar() const; 176 BScrollBar* VScrollBar() const ; 177 BCountView* CountView() const; 178 BTitleView* TitleView() const; 179 void DisableScrollBars(); 180 void EnableScrollBars(); 181 182 // sorting 183 virtual void SortPoses(); 184 void SetPrimarySort(uint32 attrHash); 185 void SetSecondarySort(uint32 attrHash); 186 void SetReverseSort(bool reverse); 187 uint32 PrimarySort() const; 188 uint32 PrimarySortType() const; 189 uint32 SecondarySort() const; 190 uint32 SecondarySortType() const; 191 bool ReverseSort() const; 192 void CheckPoseSortOrder(BPose*, int32 index); 193 void CheckPoseVisibility(BRect* = NULL); 194 // make sure pose fits the screen and/or window bounds if needed 195 196 // view metrics 197 font_height FontInfo() const; 198 // returns height, descent, etc. 199 float FontHeight() const; 200 float ListElemHeight() const; 201 float ListOffset() const; 202 203 void SetIconPoseHeight(); 204 float IconPoseHeight() const; 205 uint32 UnscaledIconSizeInt() const; 206 uint32 IconSizeInt() const; 207 BSize IconSize() const; 208 209 BRect Extent() const; 210 void GetLayoutInfo(uint32 viewMode, BPoint* grid, 211 BPoint* offset) const; 212 213 int32 CountItems() const; 214 void UpdateCount(); 215 216 rgb_color DeskTextColor() const; 217 rgb_color DeskTextBackColor() const; 218 219 rgb_color TextColor(bool selected = false) const; 220 rgb_color BackColor(bool selected = false) const; 221 222 bool WidgetTextOutline() const; 223 void SetWidgetTextOutline(bool); 224 // used to not erase when we have a background image and 225 // invalidate instead 226 227 void ScrollView(int32 type); 228 229 // column handling 230 void ColumnRedraw(BRect updateRect); 231 bool AddColumn(BColumn*, const BColumn* after = NULL); 232 bool RemoveColumn(BColumn* column, bool runAlert); 233 void MoveColumnTo(BColumn* src, BColumn* dest); 234 bool ResizeColumnToWidest(BColumn* column); 235 BPoint ResizeColumn(BColumn*, float, float* lastLineDrawPos = NULL, 236 void (*drawLineFunc)(BPoseView*, BPoint, BPoint) = 0, 237 void (*undrawLineFunc)(BPoseView*, BPoint, BPoint) = 0); 238 // returns the bottom right of the last pose drawn or 239 // the bottom right of bounds 240 241 BColumn* ColumnAt(int32 index) const; 242 BColumn* ColumnFor(uint32 attribute_hash) const; 243 BColumn* FirstColumn() const; 244 BColumn* LastColumn() const; 245 int32 IndexOfColumn(const BColumn*) const; 246 int32 CountColumns() const; 247 248 // Where to start the first column 249 float StartOffset() const; 250 251 // pose access 252 int32 IndexOfPose(const BPose*) const; 253 BPose* PoseAtIndex(int32 index) const; 254 255 BPose* FindPose(BPoint where, int32* index = NULL) const; 256 // return pose at location h, v (search list starting from 257 // bottom so drawing and hit detection reflect the same pose 258 // ordering) 259 BPose* FindPose(const Model*, int32* index = NULL) const; 260 BPose* FindPose(const node_ref*, int32* index = NULL) const; 261 BPose* FindPose(const entry_ref*, int32* index = NULL) const; 262 BPose* FindPose(const entry_ref*, int32 specifierForm, 263 int32* index) const; 264 // special form of FindPose used for scripting, 265 // <specifierForm> may ask for previous or next pose 266 BPose* DeepFindPose(const node_ref* node, int32* index = NULL) const; 267 // same as FindPose, node can be a target of the actual 268 // pose if the pose is a symlink 269 BPose* FirstVisiblePose(int32* _index = NULL) const; 270 BPose* LastVisiblePose(int32* _index = NULL) const; 271 272 void OpenInfoWindows(); 273 void SetDefaultPrinter(); 274 275 void IdentifySelection(bool force = false); 276 void UnmountSelectedVolumes(); 277 virtual void OpenParent(); 278 279 virtual void OpenSelection(BPose* clicked_pose = NULL, 280 int32* index = NULL); 281 void OpenSelectionUsing(BPose* clicked_pose = NULL, 282 int32* index = NULL); 283 // launches the open with window 284 virtual void MoveSelectionTo(BPoint, BPoint, BContainerWindow*); 285 void DuplicateSelection(BPoint* dropStart = NULL, 286 BPoint* dropEnd = NULL); 287 288 // Move to trash calls try to select the next pose in the view 289 // when they are dones 290 virtual void MoveSelectionToTrash(bool selectNext = true); 291 virtual void DeleteSelection(bool selectNext = true, 292 bool askUser = true); 293 virtual void MoveEntryToTrash(const entry_ref*, 294 bool selectNext = true); 295 296 void RestoreSelectionFromTrash(bool selectNext = true); 297 298 // selection 299 PoseList* SelectionList() const; 300 void SelectAll(); 301 void InvertSelection(); 302 int32 SelectMatchingEntries(const BMessage*); 303 void ShowSelectionWindow(); 304 void ClearSelection(); 305 void ShowSelection(bool); 306 void AddRemovePoseFromSelection(BPose* pose, int32 index, 307 bool select); 308 int32 CountSelected() const; 309 bool SelectedVolumeIsReadOnly() const; 310 bool TargetVolumeIsReadOnly() const; 311 bool CanEditName() const; 312 bool CanMoveToTrashOrDuplicate() const; 313 314 void SetSelectionHandler(BLooper* looper); 315 316 BObjectList<BString>*MimeTypesInSelection(); 317 318 // pose selection 319 void SelectPose(BPose*, int32 index, bool scrollIntoView = true); 320 void AddPoseToSelection(BPose*, int32 index, 321 bool scrollIntoView = true); 322 void RemovePoseFromSelection(BPose*); 323 void SelectPoseAtLocation(BPoint); 324 void SelectPoses(int32 start, int32 end); 325 void MoveOrChangePoseSelection(int32 to); 326 327 // pose handling 328 void ScrollIntoView(BPose* pose, int32 index); 329 void ScrollIntoView(BRect poseRect); 330 void SetActivePose(BPose*); 331 BPose* ActivePose() const; 332 void CommitActivePose(bool saveChanges = true); 333 static bool PoseVisible(const Model*, const PoseInfo*); 334 bool FrameForPose(BPose* targetPose, bool convert, BRect* poseRect); 335 bool CreateSymlinkPoseTarget(Model* symlink); 336 // used to complete a symlink pose; returns true if 337 // target symlink should not be shown 338 void ResetPosePlacementHint(); 339 void PlaceFolder(const entry_ref*, const BMessage*); 340 341 // clipboard handling for poses 342 inline bool HasPosesInClipboard(); 343 inline void SetHasPosesInClipboard(bool hasPoses); 344 void SetPosesClipboardMode(uint32 clipboardMode); 345 void UpdatePosesClipboardModeFromClipboard( 346 BMessage* clipboardReport = NULL); 347 348 // filtering 349 void SetRefFilter(BRefFilter*); 350 BRefFilter* RefFilter() const; 351 352 // access for mime types represented in the pose view 353 void AddMimeType(const char* mimeType); 354 const char* MimeTypeAt(int32 index); 355 int32 CountMimeTypes(); 356 void RefreshMimeTypeList(); 357 358 // drag&drop handling 359 virtual bool HandleMessageDropped(BMessage*); 360 static bool HandleDropCommon(BMessage* dragMessage, Model* target, 361 BPose*, BView* view, BPoint dropPoint); 362 // used by pose views and info windows 363 static bool CanHandleDragSelection(const Model* target, 364 const BMessage* dragMessage, bool ignoreTypes); 365 virtual void DragSelectedPoses(const BPose* clickedPose, BPoint); 366 367 void MoveSelectionInto(Model* destFolder, BContainerWindow* srcWindow, 368 bool forceCopy, bool forceMove = false, bool createLink = false, 369 bool relativeLink = false); 370 static void MoveSelectionInto(Model* destFolder, 371 BContainerWindow* srcWindow, BContainerWindow* destWindow, 372 uint32 buttons, BPoint loc, bool forceCopy, 373 bool forceMove = false, bool createLink = false, 374 bool relativeLink = false, BPoint clickPoint = BPoint(0, 0), 375 bool pinToGrid = false); 376 377 bool UpdateDropTarget(BPoint, const BMessage*, 378 bool trackingContextMenu); 379 // return true if drop target changed 380 void HiliteDropTarget(bool hiliteState); 381 382 void DragStop(); 383 // throw away cached up structures 384 385 static bool MenuTrackingHook(BMenu* menu, void* castToThis); 386 // hook for spring loaded nav-menus 387 388 // scripting 389 virtual BHandler* ResolveSpecifier(BMessage* message, int32 index, 390 BMessage* specifier, int32 form, const char* property); 391 virtual status_t GetSupportedSuites(BMessage*); 392 393 // string width calls that use local width caches, faster than using 394 // the general purpose BView::StringWidth 395 float StringWidth(const char*) const; 396 float StringWidth(const char*, int32) const; 397 // deliberately hide the BView StringWidth here - this makes it 398 // easy to have the right StringWidth picked up by 399 // template instantiation, as used by WidgetAttributeText 400 401 // show/hide barberpole while a background task is filling 402 // up the view, etc. 403 void ShowBarberPole(); 404 void HideBarberPole(); 405 406 bool fShowSelectionWhenInactive; 407 bool fIsDrawingSelectionRect; 408 409 bool IsWatchingDateFormatChange(); 410 void StartWatchDateFormatChange(); 411 void StopWatchDateFormatChange(); 412 413 // type ahead filtering 414 bool IsFiltering() const; 415 416 void UpdateDateColumns(BMessage*); 417 virtual void AdaptToVolumeChange(BMessage*); 418 virtual void AdaptToDesktopIntegrationChange(BMessage*); 419 420 void SetTextWidgetToCheck(BTextWidget*, BTextWidget* = NULL); 421 422 BTextWidget* ActiveTextWidget() { return fActiveTextWidget; }; 423 void SetActiveTextWidget(BTextWidget* w) { fActiveTextWidget = w; }; 424 425 protected: 426 // view setup 427 virtual void SetUpDefaultColumnsIfNeeded(); 428 429 virtual EntryListBase* InitDirentIterator(const entry_ref*); 430 // sets up an entry iterator for _add_poses_ 431 // overriden by QueryPoseView, etc. to provide different iteration 432 virtual void ReturnDirentIterator(EntryListBase* iterator); 433 // returns the entry iterator after _add_poses_ is done 434 435 void Cleanup(bool doAll = false); 436 // clean up poses 437 void NewFolder(const BMessage*); 438 // create a new folder, optionally specify a location 439 440 void NewFileFromTemplate(const BMessage*); 441 // create a new file based on a template, optionally specify 442 // a location 443 444 void ShowContextMenu(BPoint); 445 446 // scripting handlers 447 virtual bool HandleScriptingMessage(BMessage* message); 448 bool SetProperty(BMessage* message, BMessage* specifier, int32 form, 449 const char* property, BMessage* reply); 450 bool GetProperty(BMessage*, int32, const char*, BMessage*); 451 bool CreateProperty(BMessage* message, BMessage* specifier, int32, 452 const char*, BMessage* reply); 453 bool ExecuteProperty(BMessage* specifier, int32, const char*, 454 BMessage* reply); 455 bool CountProperty(BMessage*, int32, const char*, BMessage*); 456 bool DeleteProperty(BMessage*, int32, const char*, BMessage*); 457 458 void ClearPoses(); 459 // remove all the current poses from the view 460 461 // pose info read/write calls 462 void ReadPoseInfo(Model*, PoseInfo*); 463 ExtendedPoseInfo* ReadExtendedPoseInfo(Model*); 464 465 void _CheckPoseSortOrder(PoseList* list, BPose*, int32 index); 466 467 // pose creation 468 BPose* EntryCreated(const node_ref*, const node_ref*, const char*, 469 int32* index = 0); 470 471 void AddPoseToList(PoseList* list, bool visibleList, 472 bool insertionSort, BPose* pose, BRect&viewBounds, 473 float& listViewScrollBy, bool forceDraw, int32* indexPtr = NULL); 474 BPose* CreatePose(Model*, PoseInfo*, bool insertionSort = true, 475 int32* index = 0, BRect* boundsPointer = 0, bool forceDraw = true); 476 virtual void CreatePoses(Model**models, PoseInfo* poseInfoArray, 477 int32 count, BPose** resultingPoses, bool insertionSort = true, 478 int32* lastPoseIndexPointer = 0, BRect* boundsPointer = 0, 479 bool forceDraw = false); 480 virtual bool ShouldShowPose(const Model*, const PoseInfo*); 481 // filter, subclasses override to control which poses show up 482 // subclasses should always call inherited 483 void CreateVolumePose(BVolume*, bool watchIndividually); 484 485 void CreateTrashPose(); 486 487 virtual bool AddPosesThreadValid(const entry_ref*) const; 488 // verifies whether or not the current set of AddPoses threads 489 // are valid and allowed to be adding poses -- returns false 490 // in the case where the directory has been switched while 491 // populating the view 492 493 virtual void AddPoses(Model* model = NULL); 494 // if <model> is zero, PoseView has other means of iterating 495 // through all the entries thaat it adds 496 497 virtual void AddRootPoses(bool watchIndividually, bool mountShared); 498 // watchIndividually is used when placing a volume pose onto 499 // the Desktop where unlike in the Root window it will not be 500 // watched by the folder representing root. If set, each volume 501 // will therefore be watched individually 502 virtual void RemoveRootPoses(); 503 virtual void AddTrashPoses(); 504 505 virtual bool DeletePose(const node_ref*, BPose* pose = NULL, 506 int32 index = 0); 507 virtual void DeleteSymLinkPoseTarget(const node_ref* itemNode, 508 BPose* pose, int32 index); 509 // the pose itself wasn't deleted but it's target node was - the 510 // pose must be a symlink 511 static void PoseHandleDeviceUnmounted(BPose* pose, Model* model, 512 int32 index, BPoseView* poseView, dev_t device); 513 static void RemoveNonBootDesktopModels(BPose*, Model* model, int32, 514 BPoseView* poseView, dev_t); 515 516 // pose placement 517 void CheckAutoPlacedPoses(); 518 // find poses that need placing and place them in a new spot 519 void PlacePose(BPose*, BRect&); 520 // find a new place for a pose, starting at fHintLocation 521 // and place it 522 bool IsValidLocation(const BPose* pose); 523 bool IsValidLocation(const BRect& rect); 524 status_t GetDeskbarFrame(BRect* frame); 525 bool SlotOccupied(BRect poseRect, BRect viewBounds) const; 526 void NextSlot(BPose*, BRect&poseRect, BRect viewBounds); 527 void TrySettingPoseLocation(BNode* node, BPoint point); 528 BPoint PinToGrid(BPoint, BPoint grid, BPoint offset) const; 529 530 // zombie pose handling 531 Model* FindZombie(const node_ref*, int32* index = 0); 532 BPose* ConvertZombieToPose(Model* zombie, int32 index); 533 534 // pose handling 535 BRect CalcPoseRect(const BPose*, int32 index, 536 bool firstColumnOnly = false) const; 537 BRect CalcPoseRectIcon(const BPose*) const; 538 BRect CalcPoseRectList(const BPose*, int32 index, 539 bool firstColumnOnly = false) const; 540 void DrawPose(BPose*, int32 index, bool fullDraw = true); 541 void DrawViewCommon(const BRect&updateRect); 542 543 // pose list handling 544 int32 BSearchList(PoseList* poseList, const BPose*, int32* index, 545 int32 oldIndex); 546 void InsertPoseAfter(BPose* pose, int32* index, int32 orientation, 547 BRect* invalidRect); 548 // does a CopyBits to scroll poses making room for a new pose, 549 // returns rectangle that needs invalidating 550 void CloseGapInList(BRect* invalidRect); 551 int32 FirstIndexAtOrBelow(int32 y, bool constrainIndex = true) const; 552 void AddToVSList(BPose*); 553 int32 RemoveFromVSList(const BPose*); 554 BPose* FindNearbyPose(char arrow, int32* index); 555 BPose* FindBestMatch(int32* index); 556 BPose* FindNextMatch(int32* index, bool reverse = false); 557 558 // node monitoring calls 559 virtual void StartWatching(); 560 virtual void StopWatching(); 561 562 status_t WatchNewNode(const node_ref* item); 563 // the above would ideally be the only call of these three and 564 // it would be a virtual, overriding the specific watch mask in 565 // query pose view, etc. however we need to call WatchNewNode 566 // from inside AddPosesTask while the window is unlocked - we 567 // have to use the static and a cached messenger and masks. 568 static status_t WatchNewNode(const node_ref*, uint32, BMessenger); 569 virtual uint32 WatchNewNodeMask(); 570 // override to change different watch modes for query pose 571 // view, etc. 572 573 // drag&drop handling 574 static bool EachItemInDraggedSelection(const BMessage* message, 575 bool (*)(BPose*, BPoseView*, void*), BPoseView* poseView, 576 void* = NULL); 577 // iterates through each pose in current selectiond in the source 578 // window of the current drag message; locks the window 579 // add const version 580 BRect GetDragRect(int32 clickedPoseIndex); 581 BBitmap* MakeDragBitmap(BRect dragRect, BPoint clickedPoint, 582 int32 clickedPoseIndex, BPoint&offset); 583 static bool FindDragNDropAction(const BMessage* dragMessage, 584 bool&canCopy, bool&canMove, bool&canLink, bool&canErase); 585 586 static bool CanTrashForeignDrag(const Model*); 587 static bool CanCopyOrMoveForeignDrag(const Model*, const BMessage*); 588 static bool DragSelectionContains(const BPose* target, 589 const BMessage* dragMessage); 590 static status_t CreateClippingFile(BPoseView* poseView, BFile&result, 591 char* resultingName, BDirectory* directory, BMessage* message, 592 const char* fallbackName, bool setLocation = false, 593 BPoint dropPoint = BPoint(0, 0)); 594 595 // opening files, lanunching 596 void OpenSelectionCommon(BPose*, int32*, bool); 597 // used by OpenSelection and OpenSelectionUsing 598 static void LaunchAppWithSelection(Model*, const BMessage*, 599 bool checkTypes = true); 600 601 // node monitoring calls 602 virtual bool EntryMoved(const BMessage*); 603 virtual bool AttributeChanged(const BMessage*); 604 virtual bool NoticeMetaMimeChanged(const BMessage*); 605 virtual void MetaMimeChanged(const char*, const char*); 606 607 // click handling 608 bool WasDoubleClick(const BPose*, BPoint point, int32 buttons); 609 bool WasClickInPath(const BPose*, int32 index, 610 BPoint mouseLocation) const; 611 612 // selection 613 void SelectPoses(BRect, BList**); 614 void AddRemoveSelectionRange(BPoint where, bool extendSelection, 615 BPose* pose); 616 617 void _BeginSelectionRect(const BPoint& point, bool extendSelection); 618 void _UpdateSelectionRect(const BPoint& point); 619 void _EndSelectionRect(); 620 621 // view drawing 622 void SynchronousUpdate(BRect, bool clip = false); 623 624 // scrolling 625 void HandleAutoScroll(); 626 bool CheckAutoScroll(BPoint mouseLoc, bool shouldScroll); 627 628 // view extent handling 629 void RecalcExtent(); 630 void AddToExtent(const BRect&); 631 void ClearExtent(); 632 void RemoveFromExtent(const BRect&); 633 634 virtual void EditQueries(); 635 636 void HandleAttrMenuItemSelected(BMessage*); 637 void TryUpdatingBrokenLinks(); 638 // ran a little after a volume gets mounted 639 640 void MapToNewIconMode(BPose*, BPoint oldGrid, BPoint oldOffset); 641 void ResetOrigin(); 642 void PinPointToValidRange(BPoint&); 643 // used to ensure pose locations make sense after getting them 644 // in pose info from attributes, etc. 645 646 void FinishPendingScroll(float&listViewScrollBy, BRect bounds); 647 // utility call for CreatePoses 648 649 // background AddPoses task calls 650 static status_t AddPosesTask(void*); 651 virtual void AddPosesCompleted(); 652 bool IsValidAddPosesThread(thread_id) const; 653 654 // typeahead filtering 655 void EnsurePoseUnselected(BPose* pose); 656 void RemoveFilteredPose(BPose* pose, int32 index); 657 void FilterChanged(); 658 void UpdateAfterFilterChange(); 659 bool FilterPose(BPose* pose); 660 void StartFiltering(); 661 void StopFiltering(); 662 void ClearFilter(); 663 PoseList* CurrentPoseList() const; 664 665 // misc 666 BList* GetDropPointList(BPoint dropPoint, BPoint startPoint, 667 const PoseList*, bool sourceInListMode, bool dropOnGrid) const; 668 void SendSelectionAsRefs(uint32 what, bool onlyQueries = false); 669 void MoveListToTrash(BObjectList<entry_ref>*, bool selectNext, 670 bool deleteDirectly); 671 void Delete(BObjectList<entry_ref>*, bool selectNext, bool askUser); 672 void Delete(const entry_ref&ref, bool selectNext, bool askUser); 673 void RestoreItemsFromTrash(BObjectList<entry_ref>*, bool selectNext); 674 675 void WatchParentOf(const entry_ref*); 676 void StopWatchingParentsOf(const entry_ref*); 677 678 void ExcludeTrashFromSelection(); 679 680 private: 681 void DrawOpenAnimation(BRect); 682 void ApplyBackgroundColor(); 683 rgb_color InvertedBackColor() const; 684 685 void MoveSelectionOrEntryToTrash(const entry_ref* ref, bool selectNext); 686 687 protected: 688 struct node_ref_key { 689 node_ref_key() {} 690 node_ref_key(const node_ref& value) : value(value) {} 691 692 uint32 GetHashCode() const 693 { 694 return (uint32)value.device ^ (uint32)value.node; 695 } 696 697 node_ref_key operator=(const node_ref_key& other) 698 { 699 value = other.value; 700 return *this; 701 } 702 703 bool operator==(const node_ref_key& other) const 704 { 705 return (value == other.value); 706 } 707 708 bool operator!=(const node_ref_key& other) const 709 { 710 return (value != other.value); 711 } 712 713 node_ref value; 714 }; 715 716 protected: 717 BViewState* fViewState; 718 bool fStateNeedsSaving; 719 720 bool fSavePoseLocations : 1; 721 bool fMultipleSelection : 1; 722 bool fDragEnabled : 1; 723 bool fDropEnabled : 1; 724 725 BLooper* fSelectionHandler; 726 727 std::set<thread_id> fAddPosesThreads; 728 PoseList* fPoseList; 729 730 PendingNodeMonitorCache pendingNodeMonitorCache; 731 732 private: 733 TScrollBar* fHScrollBar; 734 BScrollBar* fVScrollBar; 735 Model* fModel; 736 BPose* fActivePose; 737 BRect fExtent; 738 // the following should probably be just member lists, not pointers 739 PoseList* fFilteredPoseList; 740 PoseList* fVSPoseList; 741 PoseList* fSelectionList; 742 HashSet<node_ref_key> fInsertedNodes; 743 BObjectList<BString> fMimeTypesInSelectionCache; 744 // used for mime string based icon highliting during a drag 745 BObjectList<Model>* fZombieList; 746 BObjectList<BColumn>* fColumnList; 747 BObjectList<BString>* fMimeTypeList; 748 BObjectList<Model>* fBrokenLinks; 749 bool fMimeTypeListIsDirty; 750 BCountView* fCountView; 751 float fListElemHeight; 752 float fListOffset; 753 float fIconPoseHeight; 754 BPose* fDropTarget; 755 BPose* fAlreadySelectedDropTarget; 756 BPoint fLastClickPoint; 757 int32 fLastClickButtons; 758 const BPose* fLastClickedPose; 759 BPoint fLastLeftTop; 760 BRect fLastExtent; 761 BTitleView* fTitleView; 762 BRefFilter* fRefFilter; 763 BPoint fGrid; 764 BPoint fOffset; 765 BPoint fHintLocation; 766 float fAutoScrollInc; 767 int32 fAutoScrollState; 768 bool fWidgetTextOutline; 769 const BPose* fSelectionPivotPose; 770 const BPose* fRealPivotPose; 771 BMessageRunner* fKeyRunner; 772 bool fTrackRightMouseUp; 773 bool fTrackMouseUp; 774 775 struct SelectionRectInfo { 776 SelectionRectInfo() 777 : 778 isDragging(false), 779 selection(NULL) 780 { 781 } 782 783 bool isDragging; 784 BRect rect; 785 BRect lastRect; 786 BPoint startPoint; 787 BPoint lastPoint; 788 BList* selection; 789 }; 790 SelectionRectInfo fSelectionRectInfo; 791 792 bool fSelectionVisible : 1; 793 bool fSelectionRectEnabled : 1; 794 bool fTransparentSelection : 1; 795 bool fAlwaysAutoPlace : 1; 796 bool fAllowPoseEditing : 1; 797 bool fSelectionChangedHook : 1; 798 // get rid of this 799 bool fOkToMapIcons : 1; 800 bool fEnsurePosesVisible : 1; 801 bool fShouldAutoScroll : 1; 802 bool fIsDesktopWindow : 1; 803 bool fIsWatchingDateFormatChange : 1; 804 bool fHasPosesInClipboard : 1; 805 bool fCursorCheck : 1; 806 bool fFiltering : 1; 807 808 BObjectList<BString> fFilterStrings; 809 int32 fLastFilterStringCount; 810 int32 fLastFilterStringLength; 811 812 BRect fStartFrame; 813 814 static float sFontHeight; 815 static font_height sFontInfo; 816 static BString sMatchString; 817 // used for typeahead - should be replaced by a typeahead state 818 819 bigtime_t fLastKeyTime; 820 bigtime_t fLastDeskbarFrameCheckTime; 821 BRect fDeskbarFrame; 822 823 static OffscreenBitmap* sOffscreen; 824 825 BTextWidget* fTextWidgetToCheck; 826 BTextWidget* fActiveTextWidget; 827 828 private: 829 mutable uint32 fCachedIconSizeFrom; 830 mutable BSize fCachedIconSize; 831 832 typedef BView _inherited; 833 }; 834 835 836 class TScrollBar : public BScrollBar { 837 public: 838 TScrollBar(const char*, BView*, float, float); 839 void SetTitleView(BView*); 840 841 // BScrollBar overrides 842 virtual void ValueChanged(float); 843 844 private: 845 BView* fTitleView; 846 847 typedef BScrollBar _inherited; 848 }; 849 850 851 class TPoseViewFilter : public BMessageFilter { 852 public: 853 TPoseViewFilter(BPoseView* pose); 854 ~TPoseViewFilter(); 855 856 filter_result Filter(BMessage*, BHandler**); 857 858 private: 859 filter_result ObjectDropFilter(BMessage*, BHandler**); 860 861 BPoseView* fPoseView; 862 }; 863 864 865 extern bool 866 ClearViewOriginOne(const char* name, uint32 type, off_t size, void* data, 867 void* params); 868 869 870 // inlines follow 871 872 873 inline BContainerWindow* 874 BPoseView::ContainerWindow() const 875 { 876 return dynamic_cast<BContainerWindow*>(Window()); 877 } 878 879 880 inline Model* 881 BPoseView::TargetModel() const 882 { 883 return fModel; 884 } 885 886 887 inline float 888 BPoseView::ListElemHeight() const 889 { 890 return fListElemHeight; 891 } 892 893 894 inline float 895 BPoseView::ListOffset() const 896 { 897 return fListOffset; 898 } 899 900 901 inline float 902 BPoseView::IconPoseHeight() const 903 { 904 return fIconPoseHeight; 905 } 906 907 908 inline uint32 909 BPoseView::UnscaledIconSizeInt() const 910 { 911 return fViewState->IconSize(); 912 } 913 914 915 inline uint32 916 BPoseView::IconSizeInt() const 917 { 918 return IconSize().IntegerWidth() + 1; 919 } 920 921 922 inline PoseList* 923 BPoseView::SelectionList() const 924 { 925 return fSelectionList; 926 } 927 928 inline int32 929 BPoseView::CountSelected() const 930 { 931 return fSelectionList->CountItems(); 932 } 933 934 inline BObjectList<BString>* 935 BPoseView::MimeTypesInSelection() 936 { 937 return &fMimeTypesInSelectionCache; 938 } 939 940 941 inline BScrollBar* 942 BPoseView::HScrollBar() const 943 { 944 return fHScrollBar; 945 } 946 947 948 inline BScrollBar* 949 BPoseView::VScrollBar() const 950 { 951 return fVScrollBar; 952 } 953 954 955 inline BCountView* 956 BPoseView::CountView() const 957 { 958 return fCountView; 959 } 960 961 962 inline BTitleView* 963 BPoseView::TitleView() const 964 { 965 return fTitleView; 966 } 967 968 969 inline bool 970 BPoseView::StateNeedsSaving() 971 { 972 return fStateNeedsSaving || fViewState->StateNeedsSaving(); 973 } 974 975 976 inline uint32 977 BPoseView::ViewMode() const 978 { 979 return fViewState->ViewMode(); 980 } 981 982 983 inline font_height 984 BPoseView::FontInfo() const 985 { 986 return sFontInfo; 987 } 988 989 990 inline float 991 BPoseView::FontHeight() const 992 { 993 return sFontHeight; 994 } 995 996 997 inline BPose* 998 BPoseView::ActivePose() const 999 { 1000 return fActivePose; 1001 } 1002 1003 1004 inline void 1005 BPoseView::DisableSaveLocation() 1006 { 1007 fSavePoseLocations = false; 1008 } 1009 1010 1011 inline bool 1012 BPoseView::IsFilePanel() const 1013 { 1014 return false; 1015 } 1016 1017 1018 inline bool 1019 BPoseView::IsDesktopWindow() const 1020 { 1021 return fIsDesktopWindow; 1022 } 1023 1024 1025 inline bool 1026 BPoseView::IsDesktopView() const 1027 { 1028 return false; 1029 } 1030 1031 1032 inline rgb_color 1033 BPoseView::DeskTextColor() const 1034 { 1035 // The desktop color is chosen independently for the desktop. 1036 // The text color is chosen globally for all directories. 1037 // It's fairly easy to get something unreadable (even with the default 1038 // settings, it's expected that text will be black on white in Tracker 1039 // folders, but white on blue on the desktop). 1040 // So here we check if the colors are different enough, and otherwise, 1041 // force the text to be either white or black. 1042 rgb_color textColor = HighColor(); 1043 rgb_color viewColor = ViewColor(); 1044 1045 int textBrightness = BPrivate::perceptual_brightness(textColor); 1046 int viewBrightness = BPrivate::perceptual_brightness(viewColor); 1047 if (abs(viewBrightness - textBrightness) > 127) { 1048 // The colors are different enough, we can use them as is 1049 return textColor; 1050 } else { 1051 if (viewBrightness > 127) { 1052 textColor.red = 0; 1053 textColor.green = 0; 1054 textColor.blue = 0; 1055 } else { 1056 textColor.red = 255; 1057 textColor.green = 255; 1058 textColor.blue = 255; 1059 } 1060 1061 return textColor; 1062 } 1063 } 1064 1065 1066 inline rgb_color 1067 BPoseView::DeskTextBackColor() const 1068 { 1069 // returns black or white color depending on the desktop background 1070 int32 thresh = 0; 1071 rgb_color color = LowColor(); 1072 1073 if (color.red > 150) 1074 thresh++; 1075 1076 if (color.green > 150) 1077 thresh++; 1078 1079 if (color.blue > 150) 1080 thresh++; 1081 1082 if (thresh > 1) { 1083 color.red = 255; 1084 color.green = 255; 1085 color.blue = 255; 1086 } else { 1087 color.red = 0; 1088 color.green = 0; 1089 color.blue = 0; 1090 } 1091 1092 return color; 1093 } 1094 1095 1096 inline uint32 1097 BPoseView::PrimarySort() const 1098 { 1099 return fViewState->PrimarySort(); 1100 } 1101 1102 1103 inline uint32 1104 BPoseView::PrimarySortType() const 1105 { 1106 return fViewState->PrimarySortType(); 1107 } 1108 1109 1110 inline uint32 1111 BPoseView::SecondarySort() const 1112 { 1113 return fViewState->SecondarySort(); 1114 } 1115 1116 1117 inline uint32 1118 BPoseView::SecondarySortType() const 1119 { 1120 return fViewState->SecondarySortType(); 1121 } 1122 1123 1124 inline bool 1125 BPoseView::ReverseSort() const 1126 { 1127 return fViewState->ReverseSort(); 1128 } 1129 1130 1131 inline void 1132 BPoseView::SetIconMapping(bool on) 1133 { 1134 fOkToMapIcons = on; 1135 } 1136 1137 1138 inline void 1139 BPoseView::AddToExtent(const BRect&rect) 1140 { 1141 fExtent = fExtent | rect; 1142 } 1143 1144 1145 inline void 1146 BPoseView::ClearExtent() 1147 { 1148 fExtent.Set(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN); 1149 } 1150 1151 1152 inline int32 1153 BPoseView::CountColumns() const 1154 { 1155 return fColumnList->CountItems(); 1156 } 1157 1158 1159 inline float 1160 BPoseView::StartOffset() const 1161 { 1162 return fListOffset + ListIconSize() + kMiniIconSeparator + 1; 1163 } 1164 1165 1166 inline int32 1167 BPoseView::IndexOfColumn(const BColumn* column) const 1168 { 1169 return fColumnList->IndexOf(const_cast<BColumn*>(column)); 1170 } 1171 1172 1173 inline int32 1174 BPoseView::IndexOfPose(const BPose* pose) const 1175 { 1176 return CurrentPoseList()->IndexOf(pose); 1177 } 1178 1179 1180 inline BPose* 1181 BPoseView::PoseAtIndex(int32 index) const 1182 { 1183 return CurrentPoseList()->ItemAt(index); 1184 } 1185 1186 1187 inline BColumn* 1188 BPoseView::ColumnAt(int32 index) const 1189 { 1190 return fColumnList->ItemAt(index); 1191 } 1192 1193 1194 inline BColumn* 1195 BPoseView::FirstColumn() const 1196 { 1197 return fColumnList->FirstItem(); 1198 } 1199 1200 1201 inline BColumn* 1202 BPoseView::LastColumn() const 1203 { 1204 return fColumnList->LastItem(); 1205 } 1206 1207 1208 inline int32 1209 BPoseView::CountItems() const 1210 { 1211 return CurrentPoseList()->CountItems(); 1212 } 1213 1214 1215 inline void 1216 BPoseView::SetMultipleSelection(bool state) 1217 { 1218 fMultipleSelection = state; 1219 } 1220 1221 1222 inline void 1223 BPoseView::SetSelectionChangedHook(bool state) 1224 { 1225 fSelectionChangedHook = state; 1226 } 1227 1228 1229 inline void 1230 BPoseView::SetAutoScroll(bool state) 1231 { 1232 fShouldAutoScroll = state; 1233 } 1234 1235 1236 inline void 1237 BPoseView::SetPoseEditing(bool state) 1238 { 1239 fAllowPoseEditing = state; 1240 } 1241 1242 1243 inline void 1244 BPoseView::SetDragEnabled(bool state) 1245 { 1246 fDragEnabled = state; 1247 } 1248 1249 1250 inline void 1251 BPoseView::SetDropEnabled(bool state) 1252 { 1253 fDropEnabled = state; 1254 } 1255 1256 1257 inline void 1258 BPoseView::SetSelectionRectEnabled(bool state) 1259 { 1260 fSelectionRectEnabled = state; 1261 } 1262 1263 1264 inline void 1265 BPoseView::SetAlwaysAutoPlace(bool state) 1266 { 1267 fAlwaysAutoPlace = state; 1268 } 1269 1270 1271 inline void 1272 BPoseView::SetEnsurePosesVisible(bool state) 1273 { 1274 fEnsurePosesVisible = state; 1275 } 1276 1277 1278 inline void 1279 BPoseView::SetSelectionHandler(BLooper* looper) 1280 { 1281 fSelectionHandler = looper; 1282 } 1283 1284 1285 inline void 1286 TScrollBar::SetTitleView(BView* view) 1287 { 1288 fTitleView = view; 1289 } 1290 1291 1292 inline void 1293 BPoseView::SetRefFilter(BRefFilter* filter) 1294 { 1295 fRefFilter = filter; 1296 if (filter != NULL) 1297 FilterChanged(); 1298 } 1299 1300 1301 inline BRefFilter* 1302 BPoseView::RefFilter() const 1303 { 1304 return fRefFilter; 1305 } 1306 1307 1308 inline BPose* 1309 BPoseView::FindPose(const Model* model, int32* index) const 1310 { 1311 return CurrentPoseList()->FindPose(model, index); 1312 } 1313 1314 1315 inline BPose* 1316 BPoseView::FindPose(const node_ref* node, int32* index) const 1317 { 1318 return CurrentPoseList()->FindPose(node, index); 1319 } 1320 1321 1322 inline BPose* 1323 BPoseView::FindPose(const entry_ref* entry, int32* index) const 1324 { 1325 return CurrentPoseList()->FindPose(entry, index); 1326 } 1327 1328 1329 inline bool 1330 BPoseView::HasPosesInClipboard() 1331 { 1332 return fHasPosesInClipboard; 1333 } 1334 1335 1336 inline void 1337 BPoseView::SetHasPosesInClipboard(bool hasPoses) 1338 { 1339 fHasPosesInClipboard = hasPoses; 1340 } 1341 1342 1343 inline PoseList* 1344 BPoseView::CurrentPoseList() const 1345 { 1346 return fFiltering ? fFilteredPoseList : fPoseList; 1347 } 1348 1349 1350 template<class Param1> 1351 void 1352 EachTextWidget(BPose* pose, BPoseView* poseView, 1353 void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*, Param1), Param1 p1) 1354 { 1355 for (int32 index = 0; ;index++) { 1356 BColumn* column = poseView->ColumnAt(index); 1357 if (column == NULL) 1358 break; 1359 1360 BTextWidget* widget = pose->WidgetFor(column->AttrHash()); 1361 if (widget != NULL) 1362 (func)(widget, pose, poseView, column, p1); 1363 } 1364 } 1365 1366 1367 template<class Param1, class Param2> 1368 void 1369 EachTextWidget(BPose* pose, BPoseView* poseView, 1370 void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*, 1371 Param1, Param2), Param1 p1, Param2 p2) 1372 { 1373 for (int32 index = 0; ;index++) { 1374 BColumn* column = poseView->ColumnAt(index); 1375 if (column == NULL) 1376 break; 1377 1378 BTextWidget* widget = pose->WidgetFor(column->AttrHash()); 1379 if (widget != NULL) 1380 (func)(widget, pose, poseView, column, p1, p2); 1381 } 1382 } 1383 1384 1385 template<class Result, class Param1, class Param2> 1386 Result 1387 WhileEachTextWidget(BPose* pose, BPoseView* poseView, 1388 Result (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*, 1389 Param1, Param2), Param1 p1, Param2 p2) 1390 { 1391 for (int32 index = 0; ;index++) { 1392 BColumn* column = poseView->ColumnAt(index); 1393 if (column == NULL) 1394 break; 1395 1396 BTextWidget* widget = pose->WidgetFor(column->AttrHash()); 1397 if (widget != NULL) { 1398 Result result = (func)(widget, pose, poseView, column, p1, p2); 1399 if (result != 0) 1400 return result; 1401 } 1402 } 1403 1404 return 0; 1405 } 1406 1407 1408 } // namespace BPrivate 1409 1410 using namespace BPrivate; 1411 1412 1413 #endif // _POSE_VIEW_H 1414