xref: /haiku/src/kits/tracker/PoseView.h (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
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 <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 
65 class BRefFilter;
66 class BList;
67 
68 namespace BPrivate {
69 
70 class BCountView;
71 class BContainerWindow;
72 class EntryListBase;
73 class TScrollBar;
74 
75 
76 const uint32 kMiniIconMode = 'Tmic';
77 const uint32 kIconMode = 'Ticn';
78 const uint32 kListMode = 'Tlst';
79 
80 const uint32 kCheckTypeahead = 'Tcty';
81 
82 class BPoseView : public BView {
83 public:
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 
424 protected:
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 
681 private:
682 	void DrawOpenAnimation(BRect);
683 	void ApplyBackgroundColor();
684 	rgb_color InvertedBackColor() const;
685 
686 	void MoveSelectionOrEntryToTrash(const entry_ref* ref, bool selectNext);
687 
688 protected:
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 
717 protected:
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 
733 private:
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 
829 private:
830 	mutable uint32 fCachedIconSizeFrom;
831 	mutable BSize fCachedIconSize;
832 
833 	typedef BView _inherited;
834 };
835 
836 
837 class TScrollBar : public BScrollBar {
838 public:
839 	TScrollBar(const char*, BView*, float, float);
840 	void SetTitleView(BView*);
841 
842 	// BScrollBar overrides
843 	virtual	void ValueChanged(float);
844 
845 private:
846 	BView* fTitleView;
847 
848 	typedef BScrollBar _inherited;
849 };
850 
851 
852 class TPoseViewFilter : public BMessageFilter {
853 public:
854 	TPoseViewFilter(BPoseView* pose);
855 	~TPoseViewFilter();
856 
857 	filter_result Filter(BMessage*, BHandler**);
858 
859 private:
860 	filter_result ObjectDropFilter(BMessage*, BHandler**);
861 
862 	BPoseView* fPoseView;
863 };
864 
865 
866 extern bool
867 ClearViewOriginOne(const char* name, uint32 type, off_t size, void* data,
868 	void* params);
869 
870 
871 // inlines follow
872 
873 
874 inline BContainerWindow*
875 BPoseView::ContainerWindow() const
876 {
877 	return dynamic_cast<BContainerWindow*>(Window());
878 }
879 
880 
881 inline Model*
882 BPoseView::TargetModel() const
883 {
884 	return fModel;
885 }
886 
887 
888 inline float
889 BPoseView::ListElemHeight() const
890 {
891 	return fListElemHeight;
892 }
893 
894 
895 inline float
896 BPoseView::ListOffset() const
897 {
898 	return fListOffset;
899 }
900 
901 
902 inline float
903 BPoseView::IconPoseHeight() const
904 {
905 	return fIconPoseHeight;
906 }
907 
908 
909 inline uint32
910 BPoseView::UnscaledIconSizeInt() const
911 {
912 	return fViewState->IconSize();
913 }
914 
915 
916 inline uint32
917 BPoseView::IconSizeInt() const
918 {
919 	return IconSize().IntegerWidth() + 1;
920 }
921 
922 
923 inline PoseList*
924 BPoseView::SelectionList() const
925 {
926 	return fSelectionList;
927 }
928 
929 inline int32
930 BPoseView::CountSelected() const
931 {
932 	return fSelectionList->CountItems();
933 }
934 
935 inline BObjectList<BString>*
936 BPoseView::MimeTypesInSelection()
937 {
938 	return &fMimeTypesInSelectionCache;
939 }
940 
941 
942 inline BScrollBar*
943 BPoseView::HScrollBar() const
944 {
945 	return fHScrollBar;
946 }
947 
948 
949 inline BScrollBar*
950 BPoseView::VScrollBar() const
951 {
952 	return fVScrollBar;
953 }
954 
955 
956 inline BCountView*
957 BPoseView::CountView() const
958 {
959 	return fCountView;
960 }
961 
962 
963 inline BTitleView*
964 BPoseView::TitleView() const
965 {
966 	return fTitleView;
967 }
968 
969 
970 inline bool
971 BPoseView::StateNeedsSaving()
972 {
973 	return fStateNeedsSaving || fViewState->StateNeedsSaving();
974 }
975 
976 
977 inline uint32
978 BPoseView::ViewMode() const
979 {
980 	return fViewState->ViewMode();
981 }
982 
983 
984 inline font_height
985 BPoseView::FontInfo() const
986 {
987 	return sFontInfo;
988 }
989 
990 
991 inline float
992 BPoseView::FontHeight() const
993 {
994 	return sFontHeight;
995 }
996 
997 
998 inline BPose*
999 BPoseView::ActivePose() const
1000 {
1001 	return fActivePose;
1002 }
1003 
1004 
1005 inline void
1006 BPoseView::DisableSaveLocation()
1007 {
1008 	fSavePoseLocations = false;
1009 }
1010 
1011 
1012 inline bool
1013 BPoseView::IsFilePanel() const
1014 {
1015 	return false;
1016 }
1017 
1018 
1019 inline bool
1020 BPoseView::IsDesktopWindow() const
1021 {
1022 	return fIsDesktopWindow;
1023 }
1024 
1025 
1026 inline bool
1027 BPoseView::IsDesktopView() const
1028 {
1029 	return false;
1030 }
1031 
1032 
1033 inline rgb_color
1034 BPoseView::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 
1054 inline rgb_color
1055 BPoseView::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 
1084 inline uint32
1085 BPoseView::PrimarySort() const
1086 {
1087 	return fViewState->PrimarySort();
1088 }
1089 
1090 
1091 inline uint32
1092 BPoseView::PrimarySortType() const
1093 {
1094 	return fViewState->PrimarySortType();
1095 }
1096 
1097 
1098 inline uint32
1099 BPoseView::SecondarySort() const
1100 {
1101 	return fViewState->SecondarySort();
1102 }
1103 
1104 
1105 inline uint32
1106 BPoseView::SecondarySortType() const
1107 {
1108 	return fViewState->SecondarySortType();
1109 }
1110 
1111 
1112 inline bool
1113 BPoseView::ReverseSort() const
1114 {
1115 	return fViewState->ReverseSort();
1116 }
1117 
1118 
1119 inline void
1120 BPoseView::SetIconMapping(bool on)
1121 {
1122 	fOkToMapIcons = on;
1123 }
1124 
1125 
1126 inline void
1127 BPoseView::AddToExtent(const BRect&rect)
1128 {
1129 	fExtent = fExtent | rect;
1130 }
1131 
1132 
1133 inline void
1134 BPoseView::ClearExtent()
1135 {
1136 	fExtent.Set(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN);
1137 }
1138 
1139 
1140 inline int32
1141 BPoseView::CountColumns() const
1142 {
1143 	return fColumnList->CountItems();
1144 }
1145 
1146 
1147 inline float
1148 BPoseView::StartOffset() const
1149 {
1150 	return fListOffset + ListIconSize() + kMiniIconSeparator + 1;
1151 }
1152 
1153 
1154 inline int32
1155 BPoseView::IndexOfColumn(const BColumn* column) const
1156 {
1157 	return fColumnList->IndexOf(const_cast<BColumn*>(column));
1158 }
1159 
1160 
1161 inline int32
1162 BPoseView::IndexOfPose(const BPose* pose) const
1163 {
1164 	return CurrentPoseList()->IndexOf(pose);
1165 }
1166 
1167 
1168 inline BPose*
1169 BPoseView::PoseAtIndex(int32 index) const
1170 {
1171 	return CurrentPoseList()->ItemAt(index);
1172 }
1173 
1174 
1175 inline BColumn*
1176 BPoseView::ColumnAt(int32 index) const
1177 {
1178 	return fColumnList->ItemAt(index);
1179 }
1180 
1181 
1182 inline BColumn*
1183 BPoseView::FirstColumn() const
1184 {
1185 	return fColumnList->FirstItem();
1186 }
1187 
1188 
1189 inline BColumn*
1190 BPoseView::LastColumn() const
1191 {
1192 	return fColumnList->LastItem();
1193 }
1194 
1195 
1196 inline int32
1197 BPoseView::CountItems() const
1198 {
1199 	return CurrentPoseList()->CountItems();
1200 }
1201 
1202 
1203 inline void
1204 BPoseView::SetMultipleSelection(bool state)
1205 {
1206 	fMultipleSelection = state;
1207 }
1208 
1209 
1210 inline void
1211 BPoseView::SetSelectionChangedHook(bool state)
1212 {
1213 	fSelectionChangedHook = state;
1214 }
1215 
1216 
1217 inline void
1218 BPoseView::SetAutoScroll(bool state)
1219 {
1220 	fShouldAutoScroll = state;
1221 }
1222 
1223 
1224 inline void
1225 BPoseView::SetPoseEditing(bool state)
1226 {
1227 	fAllowPoseEditing = state;
1228 }
1229 
1230 
1231 inline void
1232 BPoseView::SetDragEnabled(bool state)
1233 {
1234 	fDragEnabled = state;
1235 }
1236 
1237 
1238 inline void
1239 BPoseView::SetDropEnabled(bool state)
1240 {
1241 	fDropEnabled = state;
1242 }
1243 
1244 
1245 inline void
1246 BPoseView::SetSelectionRectEnabled(bool state)
1247 {
1248 	fSelectionRectEnabled = state;
1249 }
1250 
1251 
1252 inline void
1253 BPoseView::SetAlwaysAutoPlace(bool state)
1254 {
1255 	fAlwaysAutoPlace = state;
1256 }
1257 
1258 
1259 inline void
1260 BPoseView::SetEnsurePosesVisible(bool state)
1261 {
1262 	fEnsurePosesVisible = state;
1263 }
1264 
1265 
1266 inline void
1267 BPoseView::SetSelectionHandler(BLooper* looper)
1268 {
1269 	fSelectionHandler = looper;
1270 }
1271 
1272 
1273 inline void
1274 TScrollBar::SetTitleView(BView* view)
1275 {
1276 	fTitleView = view;
1277 }
1278 
1279 
1280 inline void
1281 BPoseView::SetRefFilter(BRefFilter* filter)
1282 {
1283 	fRefFilter = filter;
1284 	if (filter != NULL)
1285 		FilterChanged();
1286 }
1287 
1288 
1289 inline BRefFilter*
1290 BPoseView::RefFilter() const
1291 {
1292 	return fRefFilter;
1293 }
1294 
1295 
1296 inline BPose*
1297 BPoseView::FindPose(const Model* model, int32* index) const
1298 {
1299 	return CurrentPoseList()->FindPose(model, index);
1300 }
1301 
1302 
1303 inline BPose*
1304 BPoseView::FindPose(const node_ref* node, int32* index) const
1305 {
1306 	return CurrentPoseList()->FindPose(node, index);
1307 }
1308 
1309 
1310 inline BPose*
1311 BPoseView::FindPose(const entry_ref* entry, int32* index) const
1312 {
1313 	return CurrentPoseList()->FindPose(entry, index);
1314 }
1315 
1316 
1317 inline bool
1318 BPoseView::HasPosesInClipboard()
1319 {
1320 	return fHasPosesInClipboard;
1321 }
1322 
1323 
1324 inline void
1325 BPoseView::SetHasPosesInClipboard(bool hasPoses)
1326 {
1327 	fHasPosesInClipboard = hasPoses;
1328 }
1329 
1330 
1331 inline PoseList*
1332 BPoseView::CurrentPoseList() const
1333 {
1334 	return fFiltering ? fFilteredPoseList : fPoseList;
1335 }
1336 
1337 
1338 template<class Param1>
1339 void
1340 EachTextWidget(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 
1355 template<class Param1, class Param2>
1356 void
1357 EachTextWidget(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 
1373 template<class Result, class Param1, class Param2>
1374 Result
1375 WhileEachTextWidget(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 
1398 using namespace BPrivate;
1399 
1400 
1401 #endif	// _POSE_VIEW_H
1402