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