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