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