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 SelectPosesListMode(BRect, BList**); 612 void SelectPosesIconMode(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 askUser); 671 void Delete(const entry_ref&ref, bool selectNext, bool askUser); 672 void RestoreItemsFromTrash(BObjectList<entry_ref>*, bool selectNext); 673 674 void WatchParentOf(const entry_ref*); 675 void StopWatchingParentsOf(const entry_ref*); 676 677 void ExcludeTrashFromSelection(); 678 679 private: 680 void DrawOpenAnimation(BRect); 681 void ApplyBackgroundColor(); 682 float BackTint() const; 683 rgb_color InvertedBackColor() const; 684 685 void MoveSelectionOrEntryToTrash(const entry_ref* ref, bool selectNext); 686 687 protected: 688 struct node_ref_key { 689 node_ref_key() {} 690 node_ref_key(const node_ref& value) : value(value) {} 691 692 uint32 GetHashCode() const 693 { 694 return (uint32)value.device ^ (uint32)value.node; 695 } 696 697 node_ref_key operator=(const node_ref_key& other) 698 { 699 value = other.value; 700 return *this; 701 } 702 703 bool operator==(const node_ref_key& other) const 704 { 705 return (value == other.value); 706 } 707 708 bool operator!=(const node_ref_key& other) const 709 { 710 return (value != other.value); 711 } 712 713 node_ref value; 714 }; 715 716 protected: 717 BViewState* fViewState; 718 bool fStateNeedsSaving; 719 720 bool fSavePoseLocations : 1; 721 bool fMultipleSelection : 1; 722 bool fDragEnabled : 1; 723 bool fDropEnabled : 1; 724 725 BLooper* fSelectionHandler; 726 727 std::set<thread_id> fAddPosesThreads; 728 PoseList* fPoseList; 729 730 PendingNodeMonitorCache pendingNodeMonitorCache; 731 732 private: 733 TScrollBar* fHScrollBar; 734 BScrollBar* fVScrollBar; 735 Model* fModel; 736 BPose* fActivePose; 737 BRect fExtent; 738 // the following should probably be just member lists, not pointers 739 PoseList* fFilteredPoseList; 740 PoseList* fVSPoseList; 741 PoseList* fSelectionList; 742 HashSet<node_ref_key> fInsertedNodes; 743 BObjectList<BString> fMimeTypesInSelectionCache; 744 // used for mime string based icon highliting during a drag 745 BObjectList<Model>* fZombieList; 746 BObjectList<BColumn>* fColumnList; 747 BObjectList<BString>* fMimeTypeList; 748 BObjectList<Model>* fBrokenLinks; 749 bool fMimeTypeListIsDirty; 750 BCountView* fCountView; 751 float fListElemHeight; 752 float fListOffset; 753 float fIconPoseHeight; 754 BPose* fDropTarget; 755 BPose* fAlreadySelectedDropTarget; 756 BPoint fLastClickPoint; 757 int32 fLastClickButtons; 758 const BPose* fLastClickedPose; 759 BPoint fLastLeftTop; 760 BRect fLastExtent; 761 BTitleView* fTitleView; 762 BRefFilter* fRefFilter; 763 BPoint fGrid; 764 BPoint fOffset; 765 BPoint fHintLocation; 766 float fAutoScrollInc; 767 int32 fAutoScrollState; 768 bool fWidgetTextOutline; 769 const BPose* fSelectionPivotPose; 770 const BPose* fRealPivotPose; 771 BMessageRunner* fKeyRunner; 772 bool fTrackRightMouseUp; 773 bool fTrackMouseUp; 774 775 struct SelectionRectInfo { 776 SelectionRectInfo() 777 : 778 isDragging(false), 779 selection(NULL) 780 { 781 } 782 783 bool isDragging; 784 BRect rect; 785 BRect lastRect; 786 BPoint startPoint; 787 BPoint lastPoint; 788 BList* selection; 789 }; 790 SelectionRectInfo fSelectionRectInfo; 791 792 bool fSelectionVisible : 1; 793 bool fSelectionRectEnabled : 1; 794 bool fTransparentSelection : 1; 795 bool fAlwaysAutoPlace : 1; 796 bool fAllowPoseEditing : 1; 797 bool fSelectionChangedHook : 1; 798 // get rid of this 799 bool fOkToMapIcons : 1; 800 bool fEnsurePosesVisible : 1; 801 bool fShouldAutoScroll : 1; 802 bool fIsDesktopWindow : 1; 803 bool fIsWatchingDateFormatChange : 1; 804 bool fHasPosesInClipboard : 1; 805 bool fCursorCheck : 1; 806 bool fFiltering : 1; 807 808 BObjectList<BString> fFilterStrings; 809 int32 fLastFilterStringCount; 810 int32 fLastFilterStringLength; 811 812 BRect fStartFrame; 813 814 static float sFontHeight; 815 static font_height sFontInfo; 816 static BString sMatchString; 817 // used for typeahead - should be replaced by a typeahead state 818 819 bigtime_t fLastKeyTime; 820 bigtime_t fLastDeskbarFrameCheckTime; 821 BRect fDeskbarFrame; 822 823 static OffscreenBitmap* sOffscreen; 824 825 BTextWidget* fTextWidgetToCheck; 826 BTextWidget* fActiveTextWidget; 827 828 private: 829 mutable uint32 fCachedIconSizeFrom; 830 mutable BSize fCachedIconSize; 831 832 typedef BView _inherited; 833 }; 834 835 836 class TScrollBar : public BScrollBar { 837 public: 838 TScrollBar(const char*, BView*, float, float); 839 void SetTitleView(BView*); 840 841 // BScrollBar overrides 842 virtual void ValueChanged(float); 843 844 private: 845 BView* fTitleView; 846 847 typedef BScrollBar _inherited; 848 }; 849 850 851 class TPoseViewFilter : public BMessageFilter { 852 public: 853 TPoseViewFilter(BPoseView* pose); 854 ~TPoseViewFilter(); 855 856 filter_result Filter(BMessage*, BHandler**); 857 858 private: 859 filter_result ObjectDropFilter(BMessage*, BHandler**); 860 861 BPoseView* fPoseView; 862 }; 863 864 865 extern bool 866 ClearViewOriginOne(const char* name, uint32 type, off_t size, void* data, 867 void* params); 868 869 870 // inlines follow 871 872 873 inline BContainerWindow* 874 BPoseView::ContainerWindow() const 875 { 876 return dynamic_cast<BContainerWindow*>(Window()); 877 } 878 879 880 inline Model* 881 BPoseView::TargetModel() const 882 { 883 return fModel; 884 } 885 886 887 inline float 888 BPoseView::ListElemHeight() const 889 { 890 return fListElemHeight; 891 } 892 893 894 inline float 895 BPoseView::ListOffset() const 896 { 897 return fListOffset; 898 } 899 900 901 inline float 902 BPoseView::IconPoseHeight() const 903 { 904 return fIconPoseHeight; 905 } 906 907 908 inline uint32 909 BPoseView::UnscaledIconSizeInt() const 910 { 911 return fViewState->IconSize(); 912 } 913 914 915 inline uint32 916 BPoseView::IconSizeInt() const 917 { 918 return IconSize().IntegerWidth() + 1; 919 } 920 921 922 inline PoseList* 923 BPoseView::SelectionList() const 924 { 925 return fSelectionList; 926 } 927 928 inline int32 929 BPoseView::CountSelected() const 930 { 931 return fSelectionList->CountItems(); 932 } 933 934 inline BObjectList<BString>* 935 BPoseView::MimeTypesInSelection() 936 { 937 return &fMimeTypesInSelectionCache; 938 } 939 940 941 inline BScrollBar* 942 BPoseView::HScrollBar() const 943 { 944 return fHScrollBar; 945 } 946 947 948 inline BScrollBar* 949 BPoseView::VScrollBar() const 950 { 951 return fVScrollBar; 952 } 953 954 955 inline BCountView* 956 BPoseView::CountView() const 957 { 958 return fCountView; 959 } 960 961 962 inline BTitleView* 963 BPoseView::TitleView() const 964 { 965 return fTitleView; 966 } 967 968 969 inline bool 970 BPoseView::StateNeedsSaving() 971 { 972 return fStateNeedsSaving || fViewState->StateNeedsSaving(); 973 } 974 975 976 inline uint32 977 BPoseView::ViewMode() const 978 { 979 return fViewState->ViewMode(); 980 } 981 982 983 inline font_height 984 BPoseView::FontInfo() const 985 { 986 return sFontInfo; 987 } 988 989 990 inline float 991 BPoseView::FontHeight() const 992 { 993 return sFontHeight; 994 } 995 996 997 inline BPose* 998 BPoseView::ActivePose() const 999 { 1000 return fActivePose; 1001 } 1002 1003 1004 inline void 1005 BPoseView::DisableSaveLocation() 1006 { 1007 fSavePoseLocations = false; 1008 } 1009 1010 1011 inline bool 1012 BPoseView::IsFilePanel() const 1013 { 1014 return false; 1015 } 1016 1017 1018 inline bool 1019 BPoseView::IsDesktopWindow() const 1020 { 1021 return fIsDesktopWindow; 1022 } 1023 1024 1025 inline bool 1026 BPoseView::IsDesktopView() const 1027 { 1028 return false; 1029 } 1030 1031 1032 inline rgb_color 1033 BPoseView::DeskTextColor() const 1034 { 1035 // The desktop color is chosen independently for the desktop. 1036 // The text color is chosen globally for all directories. 1037 // It's fairly easy to get something unreadable (even with the default 1038 // settings, it's expected that text will be black on white in Tracker 1039 // folders, but white on blue on the desktop). 1040 // So here we check if the colors are different enough, and otherwise, 1041 // force the text to be either white or black. 1042 rgb_color textColor = HighColor(); 1043 rgb_color viewColor = ViewColor(); 1044 1045 int textBrightness = BPrivate::perceptual_brightness(textColor); 1046 int viewBrightness = BPrivate::perceptual_brightness(viewColor); 1047 if (abs(viewBrightness - textBrightness) > 127) { 1048 // The colors are different enough, we can use them as is 1049 return textColor; 1050 } else { 1051 if (viewBrightness > 127) { 1052 textColor.red = 0; 1053 textColor.green = 0; 1054 textColor.blue = 0; 1055 } else { 1056 textColor.red = 255; 1057 textColor.green = 255; 1058 textColor.blue = 255; 1059 } 1060 1061 return textColor; 1062 } 1063 } 1064 1065 1066 inline rgb_color 1067 BPoseView::DeskTextBackColor() const 1068 { 1069 // returns black or white color depending on the desktop background 1070 int32 thresh = 0; 1071 rgb_color color = LowColor(); 1072 1073 if (color.red > 150) 1074 thresh++; 1075 1076 if (color.green > 150) 1077 thresh++; 1078 1079 if (color.blue > 150) 1080 thresh++; 1081 1082 if (thresh > 1) { 1083 color.red = 255; 1084 color.green = 255; 1085 color.blue = 255; 1086 } else { 1087 color.red = 0; 1088 color.green = 0; 1089 color.blue = 0; 1090 } 1091 1092 return color; 1093 } 1094 1095 1096 inline uint32 1097 BPoseView::PrimarySort() const 1098 { 1099 return fViewState->PrimarySort(); 1100 } 1101 1102 1103 inline uint32 1104 BPoseView::PrimarySortType() const 1105 { 1106 return fViewState->PrimarySortType(); 1107 } 1108 1109 1110 inline uint32 1111 BPoseView::SecondarySort() const 1112 { 1113 return fViewState->SecondarySort(); 1114 } 1115 1116 1117 inline uint32 1118 BPoseView::SecondarySortType() const 1119 { 1120 return fViewState->SecondarySortType(); 1121 } 1122 1123 1124 inline bool 1125 BPoseView::ReverseSort() const 1126 { 1127 return fViewState->ReverseSort(); 1128 } 1129 1130 1131 inline void 1132 BPoseView::SetIconMapping(bool on) 1133 { 1134 fOkToMapIcons = on; 1135 } 1136 1137 1138 inline void 1139 BPoseView::AddToExtent(const BRect&rect) 1140 { 1141 fExtent = fExtent | rect; 1142 } 1143 1144 1145 inline void 1146 BPoseView::ClearExtent() 1147 { 1148 fExtent.Set(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN); 1149 } 1150 1151 1152 inline int32 1153 BPoseView::CountColumns() const 1154 { 1155 return fColumnList->CountItems(); 1156 } 1157 1158 1159 inline float 1160 BPoseView::StartOffset() const 1161 { 1162 return fListOffset + ListIconSize() + kMiniIconSeparator + 1; 1163 } 1164 1165 1166 inline int32 1167 BPoseView::IndexOfColumn(const BColumn* column) const 1168 { 1169 return fColumnList->IndexOf(const_cast<BColumn*>(column)); 1170 } 1171 1172 1173 inline int32 1174 BPoseView::IndexOfPose(const BPose* pose) const 1175 { 1176 return CurrentPoseList()->IndexOf(pose); 1177 } 1178 1179 1180 inline BPose* 1181 BPoseView::PoseAtIndex(int32 index) const 1182 { 1183 return CurrentPoseList()->ItemAt(index); 1184 } 1185 1186 1187 inline BColumn* 1188 BPoseView::ColumnAt(int32 index) const 1189 { 1190 return fColumnList->ItemAt(index); 1191 } 1192 1193 1194 inline BColumn* 1195 BPoseView::FirstColumn() const 1196 { 1197 return fColumnList->FirstItem(); 1198 } 1199 1200 1201 inline BColumn* 1202 BPoseView::LastColumn() const 1203 { 1204 return fColumnList->LastItem(); 1205 } 1206 1207 1208 inline int32 1209 BPoseView::CountItems() const 1210 { 1211 return CurrentPoseList()->CountItems(); 1212 } 1213 1214 1215 inline void 1216 BPoseView::SetMultipleSelection(bool state) 1217 { 1218 fMultipleSelection = state; 1219 } 1220 1221 1222 inline void 1223 BPoseView::SetSelectionChangedHook(bool state) 1224 { 1225 fSelectionChangedHook = state; 1226 } 1227 1228 1229 inline void 1230 BPoseView::SetAutoScroll(bool state) 1231 { 1232 fShouldAutoScroll = state; 1233 } 1234 1235 1236 inline void 1237 BPoseView::SetPoseEditing(bool state) 1238 { 1239 fAllowPoseEditing = state; 1240 } 1241 1242 1243 inline void 1244 BPoseView::SetDragEnabled(bool state) 1245 { 1246 fDragEnabled = state; 1247 } 1248 1249 1250 inline void 1251 BPoseView::SetDropEnabled(bool state) 1252 { 1253 fDropEnabled = state; 1254 } 1255 1256 1257 inline void 1258 BPoseView::SetSelectionRectEnabled(bool state) 1259 { 1260 fSelectionRectEnabled = state; 1261 } 1262 1263 1264 inline void 1265 BPoseView::SetAlwaysAutoPlace(bool state) 1266 { 1267 fAlwaysAutoPlace = state; 1268 } 1269 1270 1271 inline void 1272 BPoseView::SetEnsurePosesVisible(bool state) 1273 { 1274 fEnsurePosesVisible = state; 1275 } 1276 1277 1278 inline void 1279 BPoseView::SetSelectionHandler(BLooper* looper) 1280 { 1281 fSelectionHandler = looper; 1282 } 1283 1284 1285 inline void 1286 TScrollBar::SetTitleView(BView* view) 1287 { 1288 fTitleView = view; 1289 } 1290 1291 1292 inline void 1293 BPoseView::SetRefFilter(BRefFilter* filter) 1294 { 1295 fRefFilter = filter; 1296 if (filter != NULL) 1297 FilterChanged(); 1298 } 1299 1300 1301 inline BRefFilter* 1302 BPoseView::RefFilter() const 1303 { 1304 return fRefFilter; 1305 } 1306 1307 1308 inline BPose* 1309 BPoseView::FindPose(const Model* model, int32* index) const 1310 { 1311 return CurrentPoseList()->FindPose(model, index); 1312 } 1313 1314 1315 inline BPose* 1316 BPoseView::FindPose(const node_ref* node, int32* index) const 1317 { 1318 return CurrentPoseList()->FindPose(node, index); 1319 } 1320 1321 1322 inline BPose* 1323 BPoseView::FindPose(const entry_ref* entry, int32* index) const 1324 { 1325 return CurrentPoseList()->FindPose(entry, index); 1326 } 1327 1328 1329 inline bool 1330 BPoseView::HasPosesInClipboard() 1331 { 1332 return fHasPosesInClipboard; 1333 } 1334 1335 1336 inline void 1337 BPoseView::SetHasPosesInClipboard(bool hasPoses) 1338 { 1339 fHasPosesInClipboard = hasPoses; 1340 } 1341 1342 1343 inline PoseList* 1344 BPoseView::CurrentPoseList() const 1345 { 1346 return fFiltering ? fFilteredPoseList : fPoseList; 1347 } 1348 1349 1350 template<class Param1> 1351 void 1352 EachTextWidget(BPose* pose, BPoseView* poseView, 1353 void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*, Param1), Param1 p1) 1354 { 1355 for (int32 index = 0; ;index++) { 1356 BColumn* column = poseView->ColumnAt(index); 1357 if (column == NULL) 1358 break; 1359 1360 BTextWidget* widget = pose->WidgetFor(column->AttrHash()); 1361 if (widget != NULL) 1362 (func)(widget, pose, poseView, column, p1); 1363 } 1364 } 1365 1366 1367 template<class Param1, class Param2> 1368 void 1369 EachTextWidget(BPose* pose, BPoseView* poseView, 1370 void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*, 1371 Param1, Param2), Param1 p1, Param2 p2) 1372 { 1373 for (int32 index = 0; ;index++) { 1374 BColumn* column = poseView->ColumnAt(index); 1375 if (column == NULL) 1376 break; 1377 1378 BTextWidget* widget = pose->WidgetFor(column->AttrHash()); 1379 if (widget != NULL) 1380 (func)(widget, pose, poseView, column, p1, p2); 1381 } 1382 } 1383 1384 1385 template<class Result, class Param1, class Param2> 1386 Result 1387 WhileEachTextWidget(BPose* pose, BPoseView* poseView, 1388 Result (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*, 1389 Param1, Param2), Param1 p1, Param2 p2) 1390 { 1391 for (int32 index = 0; ;index++) { 1392 BColumn* column = poseView->ColumnAt(index); 1393 if (column == NULL) 1394 break; 1395 1396 BTextWidget* widget = pose->WidgetFor(column->AttrHash()); 1397 if (widget != NULL) { 1398 Result result = (func)(widget, pose, poseView, column, p1, p2); 1399 if (result != 0) 1400 return result; 1401 } 1402 } 1403 1404 return 0; 1405 } 1406 1407 1408 } // namespace BPrivate 1409 1410 using namespace BPrivate; 1411 1412 1413 #endif // _POSE_VIEW_H 1414