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