xref: /haiku/src/kits/tracker/PoseView.h (revision 1978089f7cec856677e46204e992c7273d70b9af)
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 	int textBrightness = BPrivate::perceptual_brightness(textColor);
1047 	int viewBrightness = BPrivate::perceptual_brightness(viewColor);
1048 	if (abs(viewBrightness - textBrightness) > 127) {
1049 		// The colors are different enough, we can use them as is
1050 		return textColor;
1051 	} else {
1052 		if (viewBrightness > 127) {
1053 			textColor.red = 0;
1054 			textColor.green = 0;
1055 			textColor.blue = 0;
1056 		} else {
1057 			textColor.red = 255;
1058 			textColor.green = 255;
1059 			textColor.blue = 255;
1060 		}
1061 
1062 		return textColor;
1063 	}
1064 }
1065 
1066 
1067 inline rgb_color
1068 BPoseView::DeskTextBackColor() const
1069 {
1070 	// returns black or white color depending on the desktop background
1071 	int32 thresh = 0;
1072 	rgb_color color = LowColor();
1073 
1074 	if (color.red > 150)
1075 		thresh++;
1076 
1077 	if (color.green > 150)
1078 		thresh++;
1079 
1080 	if (color.blue > 150)
1081 		thresh++;
1082 
1083 	if (thresh > 1) {
1084 		color.red = 255;
1085 		color.green = 255;
1086 		color.blue = 255;
1087 	} else {
1088 		color.red = 0;
1089 		color.green = 0;
1090 		color.blue = 0;
1091 	}
1092 
1093 	return color;
1094 }
1095 
1096 
1097 inline uint32
1098 BPoseView::PrimarySort() const
1099 {
1100 	return fViewState->PrimarySort();
1101 }
1102 
1103 
1104 inline uint32
1105 BPoseView::PrimarySortType() const
1106 {
1107 	return fViewState->PrimarySortType();
1108 }
1109 
1110 
1111 inline uint32
1112 BPoseView::SecondarySort() const
1113 {
1114 	return fViewState->SecondarySort();
1115 }
1116 
1117 
1118 inline uint32
1119 BPoseView::SecondarySortType() const
1120 {
1121 	return fViewState->SecondarySortType();
1122 }
1123 
1124 
1125 inline bool
1126 BPoseView::ReverseSort() const
1127 {
1128 	return fViewState->ReverseSort();
1129 }
1130 
1131 
1132 inline void
1133 BPoseView::SetIconMapping(bool on)
1134 {
1135 	fOkToMapIcons = on;
1136 }
1137 
1138 
1139 inline void
1140 BPoseView::AddToExtent(const BRect&rect)
1141 {
1142 	fExtent = fExtent | rect;
1143 }
1144 
1145 
1146 inline void
1147 BPoseView::ClearExtent()
1148 {
1149 	fExtent.Set(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN);
1150 }
1151 
1152 
1153 inline int32
1154 BPoseView::CountColumns() const
1155 {
1156 	return fColumnList->CountItems();
1157 }
1158 
1159 
1160 inline float
1161 BPoseView::StartOffset() const
1162 {
1163 	return fListOffset + ListIconSize() + kMiniIconSeparator + 1;
1164 }
1165 
1166 
1167 inline int32
1168 BPoseView::IndexOfColumn(const BColumn* column) const
1169 {
1170 	return fColumnList->IndexOf(const_cast<BColumn*>(column));
1171 }
1172 
1173 
1174 inline int32
1175 BPoseView::IndexOfPose(const BPose* pose) const
1176 {
1177 	return CurrentPoseList()->IndexOf(pose);
1178 }
1179 
1180 
1181 inline BPose*
1182 BPoseView::PoseAtIndex(int32 index) const
1183 {
1184 	return CurrentPoseList()->ItemAt(index);
1185 }
1186 
1187 
1188 inline BColumn*
1189 BPoseView::ColumnAt(int32 index) const
1190 {
1191 	return fColumnList->ItemAt(index);
1192 }
1193 
1194 
1195 inline BColumn*
1196 BPoseView::FirstColumn() const
1197 {
1198 	return fColumnList->FirstItem();
1199 }
1200 
1201 
1202 inline BColumn*
1203 BPoseView::LastColumn() const
1204 {
1205 	return fColumnList->LastItem();
1206 }
1207 
1208 
1209 inline int32
1210 BPoseView::CountItems() const
1211 {
1212 	return CurrentPoseList()->CountItems();
1213 }
1214 
1215 
1216 inline void
1217 BPoseView::SetMultipleSelection(bool state)
1218 {
1219 	fMultipleSelection = state;
1220 }
1221 
1222 
1223 inline void
1224 BPoseView::SetSelectionChangedHook(bool state)
1225 {
1226 	fSelectionChangedHook = state;
1227 }
1228 
1229 
1230 inline void
1231 BPoseView::SetAutoScroll(bool state)
1232 {
1233 	fShouldAutoScroll = state;
1234 }
1235 
1236 
1237 inline void
1238 BPoseView::SetPoseEditing(bool state)
1239 {
1240 	fAllowPoseEditing = state;
1241 }
1242 
1243 
1244 inline void
1245 BPoseView::SetDragEnabled(bool state)
1246 {
1247 	fDragEnabled = state;
1248 }
1249 
1250 
1251 inline void
1252 BPoseView::SetDropEnabled(bool state)
1253 {
1254 	fDropEnabled = state;
1255 }
1256 
1257 
1258 inline void
1259 BPoseView::SetSelectionRectEnabled(bool state)
1260 {
1261 	fSelectionRectEnabled = state;
1262 }
1263 
1264 
1265 inline void
1266 BPoseView::SetAlwaysAutoPlace(bool state)
1267 {
1268 	fAlwaysAutoPlace = state;
1269 }
1270 
1271 
1272 inline void
1273 BPoseView::SetEnsurePosesVisible(bool state)
1274 {
1275 	fEnsurePosesVisible = state;
1276 }
1277 
1278 
1279 inline void
1280 BPoseView::SetSelectionHandler(BLooper* looper)
1281 {
1282 	fSelectionHandler = looper;
1283 }
1284 
1285 
1286 inline void
1287 TScrollBar::SetTitleView(BView* view)
1288 {
1289 	fTitleView = view;
1290 }
1291 
1292 
1293 inline void
1294 BPoseView::SetRefFilter(BRefFilter* filter)
1295 {
1296 	fRefFilter = filter;
1297 	if (filter != NULL)
1298 		FilterChanged();
1299 }
1300 
1301 
1302 inline BRefFilter*
1303 BPoseView::RefFilter() const
1304 {
1305 	return fRefFilter;
1306 }
1307 
1308 
1309 inline BPose*
1310 BPoseView::FindPose(const Model* model, int32* index) const
1311 {
1312 	return CurrentPoseList()->FindPose(model, index);
1313 }
1314 
1315 
1316 inline BPose*
1317 BPoseView::FindPose(const node_ref* node, int32* index) const
1318 {
1319 	return CurrentPoseList()->FindPose(node, index);
1320 }
1321 
1322 
1323 inline BPose*
1324 BPoseView::FindPose(const entry_ref* entry, int32* index) const
1325 {
1326 	return CurrentPoseList()->FindPose(entry, index);
1327 }
1328 
1329 
1330 inline bool
1331 BPoseView::HasPosesInClipboard()
1332 {
1333 	return fHasPosesInClipboard;
1334 }
1335 
1336 
1337 inline void
1338 BPoseView::SetHasPosesInClipboard(bool hasPoses)
1339 {
1340 	fHasPosesInClipboard = hasPoses;
1341 }
1342 
1343 
1344 inline PoseList*
1345 BPoseView::CurrentPoseList() const
1346 {
1347 	return fFiltering ? fFilteredPoseList : fPoseList;
1348 }
1349 
1350 
1351 template<class Param1>
1352 void
1353 EachTextWidget(BPose* pose, BPoseView* poseView,
1354 	void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*, Param1), Param1 p1)
1355 {
1356 	for (int32 index = 0; ;index++) {
1357 		BColumn* column = poseView->ColumnAt(index);
1358 		if (column == NULL)
1359 			break;
1360 
1361 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1362 		if (widget != NULL)
1363 			(func)(widget, pose, poseView, column, p1);
1364 	}
1365 }
1366 
1367 
1368 template<class Param1, class Param2>
1369 void
1370 EachTextWidget(BPose* pose, BPoseView* poseView,
1371 	void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*,
1372 	Param1, Param2), Param1 p1, Param2 p2)
1373 {
1374 	for (int32 index = 0; ;index++) {
1375 		BColumn* column = poseView->ColumnAt(index);
1376 		if (column == NULL)
1377 			break;
1378 
1379 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1380 		if (widget != NULL)
1381 			(func)(widget, pose, poseView, column, p1, p2);
1382 	}
1383 }
1384 
1385 
1386 template<class Result, class Param1, class Param2>
1387 Result
1388 WhileEachTextWidget(BPose* pose, BPoseView* poseView,
1389 	Result (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*,
1390 	Param1, Param2), Param1 p1, Param2 p2)
1391 {
1392 	for (int32 index = 0; ;index++) {
1393 		BColumn* column = poseView->ColumnAt(index);
1394 		if (column == NULL)
1395 			break;
1396 
1397 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1398 		if (widget != NULL) {
1399 			Result result = (func)(widget, pose, poseView, column, p1, p2);
1400 			if (result != 0)
1401 				return result;
1402 		}
1403 	}
1404 
1405 	return 0;
1406 }
1407 
1408 
1409 } // namespace BPrivate
1410 
1411 using namespace BPrivate;
1412 
1413 
1414 #endif	// _POSE_VIEW_H
1415