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