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