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