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