xref: /haiku/src/kits/tracker/PoseView.h (revision 1757f197bd98997256fea2918bfa4603bf81b748)
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 BFont sCurrentFont;
802 	static BString sMatchString;
803 		// used for typeahead - should be replaced by a typeahead state
804 
805 	bigtime_t fLastKeyTime;
806 	bigtime_t fLastDeskbarFrameCheckTime;
807 	BRect fDeskbarFrame;
808 
809 	static OffscreenBitmap* sOffscreen;
810 
811 	BTextWidget* fTextWidgetToCheck;
812 
813 	typedef BView _inherited;
814 };
815 
816 
817 class TScrollBar : public BScrollBar {
818 public:
819 	TScrollBar(const char*, BView*, float, float);
820 	void SetTitleView(BView*);
821 
822 	// BScrollBar overrides
823 	virtual	void ValueChanged(float);
824 
825 private:
826 	BView* fTitleView;
827 
828 	typedef BScrollBar _inherited;
829 };
830 
831 
832 class TPoseViewFilter : public BMessageFilter {
833 public:
834 	TPoseViewFilter(BPoseView* pose);
835 	~TPoseViewFilter();
836 
837 	filter_result Filter(BMessage*, BHandler**);
838 
839 private:
840 	filter_result ObjectDropFilter(BMessage*, BHandler**);
841 
842 	BPoseView* fPoseView;
843 };
844 
845 
846 extern bool
847 ClearViewOriginOne(const char* name, uint32 type, off_t size, void* data,
848 	void* params);
849 
850 
851 // inlines follow
852 
853 
854 inline BContainerWindow*
855 BPoseView::ContainerWindow() const
856 {
857 	return dynamic_cast<BContainerWindow*>(Window());
858 }
859 
860 
861 inline Model*
862 BPoseView::TargetModel() const
863 {
864 	return fModel;
865 }
866 
867 
868 inline float
869 BPoseView::ListElemHeight() const
870 {
871 	return fListElemHeight;
872 }
873 
874 
875 inline float
876 BPoseView::IconPoseHeight() const
877 {
878 	return fIconPoseHeight;
879 }
880 
881 
882 inline uint32
883 BPoseView::IconSizeInt() const
884 {
885 	return fViewState->IconSize();
886 }
887 
888 
889 inline icon_size
890 BPoseView::IconSize() const
891 {
892 	return (icon_size)fViewState->IconSize();
893 }
894 
895 
896 inline PoseList*
897 BPoseView::SelectionList() const
898 {
899 	return fSelectionList;
900 }
901 
902 
903 inline BObjectList<BString>*
904 BPoseView::MimeTypesInSelection()
905 {
906 	return &fMimeTypesInSelectionCache;
907 }
908 
909 
910 inline BScrollBar*
911 BPoseView::HScrollBar() const
912 {
913 	return fHScrollBar;
914 }
915 
916 
917 inline BScrollBar*
918 BPoseView::VScrollBar() const
919 {
920 	return fVScrollBar;
921 }
922 
923 
924 inline BCountView*
925 BPoseView::CountView() const
926 {
927 	return fCountView;
928 }
929 
930 
931 inline BTitleView*
932 BPoseView::TitleView() const
933 {
934 	return fTitleView;
935 }
936 
937 
938 inline bool
939 BPoseView::StateNeedsSaving()
940 {
941 	return fStateNeedsSaving || fViewState->StateNeedsSaving();
942 }
943 
944 
945 inline uint32
946 BPoseView::ViewMode() const
947 {
948 	return fViewState->ViewMode();
949 }
950 
951 
952 inline font_height
953 BPoseView::FontInfo() const
954 {
955 	return sFontInfo;
956 }
957 
958 
959 inline float
960 BPoseView::FontHeight() const
961 {
962 	return sFontHeight;
963 }
964 
965 
966 inline BPose*
967 BPoseView::ActivePose() const
968 {
969 	return fActivePose;
970 }
971 
972 
973 inline void
974 BPoseView::DisableSaveLocation()
975 {
976 	fSavePoseLocations = false;
977 }
978 
979 
980 inline bool
981 BPoseView::IsFilePanel() const
982 {
983 	return false;
984 }
985 
986 
987 inline bool
988 BPoseView::IsDesktopWindow() const
989 {
990 	return fIsDesktopWindow;
991 }
992 
993 
994 inline bool
995 BPoseView::IsDesktopView() const
996 {
997 	return false;
998 }
999 
1000 
1001 inline uint32
1002 BPoseView::PrimarySort() const
1003 {
1004 	return fViewState->PrimarySort();
1005 }
1006 
1007 
1008 inline uint32
1009 BPoseView::PrimarySortType() const
1010 {
1011 	return fViewState->PrimarySortType();
1012 }
1013 
1014 
1015 inline uint32
1016 BPoseView::SecondarySort() const
1017 {
1018 	return fViewState->SecondarySort();
1019 }
1020 
1021 
1022 inline uint32
1023 BPoseView::SecondarySortType() const
1024 {
1025 	return fViewState->SecondarySortType();
1026 }
1027 
1028 
1029 inline bool
1030 BPoseView::ReverseSort() const
1031 {
1032 	return fViewState->ReverseSort();
1033 }
1034 
1035 
1036 inline void
1037 BPoseView::SetShowHideSelection(bool on)
1038 {
1039 	fShowHideSelection = on;
1040 }
1041 
1042 
1043 inline void
1044 BPoseView::SetIconMapping(bool on)
1045 {
1046 	fOkToMapIcons = on;
1047 }
1048 
1049 
1050 inline void
1051 BPoseView::AddToExtent(const BRect&rect)
1052 {
1053 	fExtent = fExtent | rect;
1054 }
1055 
1056 
1057 inline void
1058 BPoseView::ClearExtent()
1059 {
1060 	fExtent.Set(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN);
1061 }
1062 
1063 
1064 inline int32
1065 BPoseView::CountColumns() const
1066 {
1067 	return fColumnList->CountItems();
1068 }
1069 
1070 
1071 inline float
1072 BPoseView::StartOffset() const
1073 {
1074 	return kListOffset + ListIconSize() + kMiniIconSeparator + 1;
1075 }
1076 
1077 
1078 inline int32
1079 BPoseView::IndexOfColumn(const BColumn* column) const
1080 {
1081 	return fColumnList->IndexOf(const_cast<BColumn*>(column));
1082 }
1083 
1084 
1085 inline int32
1086 BPoseView::IndexOfPose(const BPose* pose) const
1087 {
1088 	return CurrentPoseList()->IndexOf(pose);
1089 }
1090 
1091 
1092 inline BPose*
1093 BPoseView::PoseAtIndex(int32 index) const
1094 {
1095 	return CurrentPoseList()->ItemAt(index);
1096 }
1097 
1098 
1099 inline BColumn*
1100 BPoseView::ColumnAt(int32 index) const
1101 {
1102 	return fColumnList->ItemAt(index);
1103 }
1104 
1105 
1106 inline BColumn*
1107 BPoseView::FirstColumn() const
1108 {
1109 	return fColumnList->FirstItem();
1110 }
1111 
1112 
1113 inline BColumn*
1114 BPoseView::LastColumn() const
1115 {
1116 	return fColumnList->LastItem();
1117 }
1118 
1119 
1120 inline int32
1121 BPoseView::CountItems() const
1122 {
1123 	return CurrentPoseList()->CountItems();
1124 }
1125 
1126 
1127 inline void
1128 BPoseView::SetMultipleSelection(bool state)
1129 {
1130 	fMultipleSelection = state;
1131 }
1132 
1133 
1134 inline void
1135 BPoseView::SetSelectionChangedHook(bool state)
1136 {
1137 	fSelectionChangedHook = state;
1138 }
1139 
1140 
1141 inline void
1142 BPoseView::SetAutoScroll(bool state)
1143 {
1144 	fShouldAutoScroll = state;
1145 }
1146 
1147 
1148 inline void
1149 BPoseView::SetPoseEditing(bool state)
1150 {
1151 	fAllowPoseEditing = state;
1152 }
1153 
1154 
1155 inline void
1156 BPoseView::SetDragEnabled(bool state)
1157 {
1158 	fDragEnabled = state;
1159 }
1160 
1161 
1162 inline void
1163 BPoseView::SetDropEnabled(bool state)
1164 {
1165 	fDropEnabled = state;
1166 }
1167 
1168 
1169 inline void
1170 BPoseView::SetSelectionRectEnabled(bool state)
1171 {
1172 	fSelectionRectEnabled = state;
1173 }
1174 
1175 
1176 inline void
1177 BPoseView::SetAlwaysAutoPlace(bool state)
1178 {
1179 	fAlwaysAutoPlace = state;
1180 }
1181 
1182 
1183 inline void
1184 BPoseView::SetEnsurePosesVisible(bool state)
1185 {
1186 	fEnsurePosesVisible = state;
1187 }
1188 
1189 
1190 inline void
1191 BPoseView::SetSelectionHandler(BLooper* looper)
1192 {
1193 	fSelectionHandler = looper;
1194 }
1195 
1196 
1197 inline void
1198 TScrollBar::SetTitleView(BView* view)
1199 {
1200 	fTitleView = view;
1201 }
1202 
1203 
1204 inline void
1205 BPoseView::SetRefFilter(BRefFilter* filter)
1206 {
1207 	fRefFilter = filter;
1208 	if (filter != NULL)
1209 		FilterChanged();
1210 }
1211 
1212 
1213 inline BRefFilter*
1214 BPoseView::RefFilter() const
1215 {
1216 	return fRefFilter;
1217 }
1218 
1219 
1220 inline BPose*
1221 BPoseView::FindPose(const Model* model, int32* index) const
1222 {
1223 	return CurrentPoseList()->FindPose(model, index);
1224 }
1225 
1226 
1227 inline BPose*
1228 BPoseView::FindPose(const node_ref* node, int32* index) const
1229 {
1230 	return CurrentPoseList()->FindPose(node, index);
1231 }
1232 
1233 
1234 inline BPose*
1235 BPoseView::FindPose(const entry_ref* entry, int32* index) const
1236 {
1237 	return CurrentPoseList()->FindPose(entry, index);
1238 }
1239 
1240 
1241 inline bool
1242 BPoseView::HasPosesInClipboard()
1243 {
1244 	return fHasPosesInClipboard;
1245 }
1246 
1247 
1248 inline void
1249 BPoseView::SetHasPosesInClipboard(bool hasPoses)
1250 {
1251 	fHasPosesInClipboard = hasPoses;
1252 }
1253 
1254 
1255 inline PoseList*
1256 BPoseView::CurrentPoseList() const
1257 {
1258 	return fFiltering ? fFilteredPoseList : fPoseList;
1259 }
1260 
1261 
1262 template<class Param1>
1263 void
1264 EachTextWidget(BPose* pose, BPoseView* poseView,
1265 	void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*, Param1), Param1 p1)
1266 {
1267 	for (int32 index = 0; ;index++) {
1268 		BColumn* column = poseView->ColumnAt(index);
1269 		if (column == NULL)
1270 			break;
1271 
1272 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1273 		if (widget != NULL)
1274 			(func)(widget, pose, poseView, column, p1);
1275 	}
1276 }
1277 
1278 
1279 template<class Param1, class Param2>
1280 void
1281 EachTextWidget(BPose* pose, BPoseView* poseView,
1282 	void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*,
1283 	Param1, Param2), Param1 p1, Param2 p2)
1284 {
1285 	for (int32 index = 0; ;index++) {
1286 		BColumn* column = poseView->ColumnAt(index);
1287 		if (column == NULL)
1288 			break;
1289 
1290 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1291 		if (widget != NULL)
1292 			(func)(widget, pose, poseView, column, p1, p2);
1293 	}
1294 }
1295 
1296 
1297 template<class Result, class Param1, class Param2>
1298 Result
1299 WhileEachTextWidget(BPose* pose, BPoseView* poseView,
1300 	Result (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*,
1301 	Param1, Param2), Param1 p1, Param2 p2)
1302 {
1303 	for (int32 index = 0; ;index++) {
1304 		BColumn* column = poseView->ColumnAt(index);
1305 		if (column == NULL)
1306 			break;
1307 
1308 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1309 		if (widget != NULL) {
1310 			Result result = (func)(widget, pose, poseView, column, p1, p2);
1311 			if (result != 0)
1312 				return result;
1313 		}
1314 	}
1315 
1316 	return 0;
1317 }
1318 
1319 
1320 } // namespace BPrivate
1321 
1322 using namespace BPrivate;
1323 
1324 
1325 #endif	// _POSE_VIEW_H
1326