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