xref: /haiku/src/kits/tracker/PoseView.h (revision 445d4fd926c569e7b9ae28017da86280aaecbae2)
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,
292 		bool askUser = true);
293 	virtual void MoveEntryToTrash(const entry_ref*,
294 		bool selectNext = true);
295 
296 	void RestoreSelectionFromTrash(bool selectNext = true);
297 
298 	// selection
299 	PoseList* SelectionList() const;
300 	void SelectAll();
301 	void InvertSelection();
302 	int32 SelectMatchingEntries(const BMessage*);
303 	void ShowSelectionWindow();
304 	void ClearSelection();
305 	void ShowSelection(bool);
306 	void AddRemovePoseFromSelection(BPose* pose, int32 index,
307 		bool select);
308 	int32 CountSelected() const;
309 	bool SelectedVolumeIsReadOnly() const;
310 	bool TargetVolumeIsReadOnly() const;
311 
312 	void SetSelectionHandler(BLooper* looper);
313 
314 	BObjectList<BString>*MimeTypesInSelection();
315 
316 	// pose selection
317 	void SelectPose(BPose*, int32 index, bool scrollIntoView = true);
318 	void AddPoseToSelection(BPose*, int32 index,
319 		bool scrollIntoView = true);
320 	void RemovePoseFromSelection(BPose*);
321 	void SelectPoseAtLocation(BPoint);
322 	void SelectPoses(int32 start, int32 end);
323 	void MoveOrChangePoseSelection(int32 to);
324 
325 	// pose handling
326 	void ScrollIntoView(BPose* pose, int32 index);
327 	void ScrollIntoView(BRect poseRect);
328 	void SetActivePose(BPose*);
329 	BPose* ActivePose() const;
330 	void CommitActivePose(bool saveChanges = true);
331 	static bool PoseVisible(const Model*, const PoseInfo*);
332 	bool FrameForPose(BPose* targetPose, bool convert, BRect* poseRect);
333 	bool CreateSymlinkPoseTarget(Model* symlink);
334 		// used to complete a symlink pose; returns true if
335 		// target symlink should not be shown
336 	void ResetPosePlacementHint();
337 	void PlaceFolder(const entry_ref*, const BMessage*);
338 
339 	// clipboard handling for poses
340 	inline bool HasPosesInClipboard();
341 	inline void SetHasPosesInClipboard(bool hasPoses);
342 	void SetPosesClipboardMode(uint32 clipboardMode);
343 	void UpdatePosesClipboardModeFromClipboard(
344 		BMessage* clipboardReport = NULL);
345 
346 	// filtering
347 	void SetRefFilter(BRefFilter*);
348 	BRefFilter* RefFilter() const;
349 
350 	// access for mime types represented in the pose view
351 	void AddMimeType(const char* mimeType);
352 	const char* MimeTypeAt(int32 index);
353 	int32 CountMimeTypes();
354 	void RefreshMimeTypeList();
355 
356 	// drag&drop handling
357 	virtual bool HandleMessageDropped(BMessage*);
358 	static bool HandleDropCommon(BMessage* dragMessage, Model* target,
359 		BPose*, BView* view, BPoint dropPoint);
360 		// used by pose views and info windows
361 	static bool CanHandleDragSelection(const Model* target,
362 		const BMessage* dragMessage, bool ignoreTypes);
363 	virtual void DragSelectedPoses(const BPose* clickedPose, BPoint);
364 
365 	void MoveSelectionInto(Model* destFolder, BContainerWindow* srcWindow,
366 		bool forceCopy, bool forceMove = false, bool createLink = false,
367 		bool relativeLink = false);
368 	static void MoveSelectionInto(Model* destFolder,
369 		BContainerWindow* srcWindow, BContainerWindow* destWindow,
370 		uint32 buttons, BPoint loc, bool forceCopy,
371 		bool forceMove = false, bool createLink = false,
372 		bool relativeLink = false, BPoint clickPoint = BPoint(0, 0),
373 		bool pinToGrid = false);
374 
375 	bool UpdateDropTarget(BPoint, const BMessage*,
376 		bool trackingContextMenu);
377 		// return true if drop target changed
378 	void HiliteDropTarget(bool hiliteState);
379 
380 	void DragStop();
381 		// throw away cached up structures
382 
383 	static bool MenuTrackingHook(BMenu* menu, void* castToThis);
384 		// hook for spring loaded nav-menus
385 
386 	// scripting
387 	virtual BHandler* ResolveSpecifier(BMessage* message, int32 index,
388 		BMessage* specifier, int32 form, const char* property);
389 	virtual status_t GetSupportedSuites(BMessage*);
390 
391 	// string width calls that use local width caches, faster than using
392 	// the general purpose BView::StringWidth
393 	float StringWidth(const char*) const;
394 	float StringWidth(const char*, int32) const;
395 		// deliberately hide the BView StringWidth here - this makes it
396 		// easy to have the right StringWidth picked up by
397 		// template instantiation, as used by WidgetAttributeText
398 
399 	// show/hide barberpole while a background task is filling
400 	// up the view, etc.
401 	void ShowBarberPole();
402 	void HideBarberPole();
403 
404 	bool fShowSelectionWhenInactive;
405 	bool fIsDrawingSelectionRect;
406 
407 	bool IsWatchingDateFormatChange();
408 	void StartWatchDateFormatChange();
409 	void StopWatchDateFormatChange();
410 
411 	// type ahead filtering
412 	bool IsFiltering() const;
413 
414 	void UpdateDateColumns(BMessage*);
415 	virtual void AdaptToVolumeChange(BMessage*);
416 	virtual void AdaptToDesktopIntegrationChange(BMessage*);
417 
418 	void SetTextWidgetToCheck(BTextWidget*, BTextWidget* = NULL);
419 
420 	BTextWidget* ActiveTextWidget() { return fActiveTextWidget; };
421 	void SetActiveTextWidget(BTextWidget* w) { fActiveTextWidget = w; };
422 
423 protected:
424 	// view setup
425 	virtual void SetUpDefaultColumnsIfNeeded();
426 
427 	virtual EntryListBase* InitDirentIterator(const entry_ref*);
428 		// sets up an entry iterator for _add_poses_
429 		// overriden by QueryPoseView, etc. to provide different iteration
430 	virtual void ReturnDirentIterator(EntryListBase* iterator);
431 		// returns the entry iterator after _add_poses_ is done
432 
433 	void Cleanup(bool doAll = false);
434 		// clean up poses
435 	void NewFolder(const BMessage*);
436 		// create a new folder, optionally specify a location
437 
438 	void NewFileFromTemplate(const BMessage*);
439 		// create a new file based on a template, optionally specify
440 		// a location
441 
442 	void ShowContextMenu(BPoint);
443 
444 	// scripting handlers
445 	virtual bool HandleScriptingMessage(BMessage* message);
446 	bool SetProperty(BMessage* message, BMessage* specifier, int32 form,
447 		const char* property, BMessage* reply);
448 	bool GetProperty(BMessage*, int32, const char*, BMessage*);
449 	bool CreateProperty(BMessage* message, BMessage* specifier, int32,
450 		const char*, BMessage* reply);
451 	bool ExecuteProperty(BMessage* specifier, int32, const char*,
452 		BMessage* reply);
453 	bool CountProperty(BMessage*, int32, const char*, BMessage*);
454 	bool DeleteProperty(BMessage*, int32, const char*, BMessage*);
455 
456 	void ClearPoses();
457 		// remove all the current poses from the view
458 
459 	// pose info read/write calls
460 	void ReadPoseInfo(Model*, PoseInfo*);
461 	ExtendedPoseInfo* ReadExtendedPoseInfo(Model*);
462 
463 	void _CheckPoseSortOrder(PoseList* list, BPose*, int32 index);
464 
465 	// pose creation
466 	BPose* EntryCreated(const node_ref*, const node_ref*, const char*,
467 		int32* index = 0);
468 
469 	void AddPoseToList(PoseList* list, bool visibleList,
470 		bool insertionSort, BPose* pose, BRect&viewBounds,
471 		float& listViewScrollBy, bool forceDraw, int32* indexPtr = NULL);
472 	BPose* CreatePose(Model*, PoseInfo*, bool insertionSort = true,
473 		int32* index = 0, BRect* boundsPointer = 0, bool forceDraw = true);
474 	virtual void CreatePoses(Model**models, PoseInfo* poseInfoArray,
475 		int32 count, BPose** resultingPoses, bool insertionSort = true,
476 		int32* lastPoseIndexPointer = 0, BRect* boundsPointer = 0,
477 		bool forceDraw = false);
478 	virtual bool ShouldShowPose(const Model*, const PoseInfo*);
479 		// filter, subclasses override to control which poses show up
480 		// subclasses should always call inherited
481 	void CreateVolumePose(BVolume*, bool watchIndividually);
482 
483 	void CreateTrashPose();
484 
485 	virtual bool AddPosesThreadValid(const entry_ref*) const;
486 		// verifies whether or not the current set of AddPoses threads
487 		// are valid and allowed to be adding poses -- returns false
488 		// in the case where the directory has been switched while
489 		// populating the view
490 
491 	virtual void AddPoses(Model* model = NULL);
492 		// if <model> is zero, PoseView has other means of iterating
493 		// through all the entries thaat it adds
494 
495 	virtual void AddRootPoses(bool watchIndividually, bool mountShared);
496 		// watchIndividually is used when placing a volume pose onto
497 		// the Desktop where unlike in the Root window it will not be
498 		// watched by the folder representing root. If set, each volume
499 		// will therefore be watched individually
500 	virtual void RemoveRootPoses();
501 	virtual void AddTrashPoses();
502 
503 	virtual bool DeletePose(const node_ref*, BPose* pose = NULL,
504 		int32 index = 0);
505 	virtual void DeleteSymLinkPoseTarget(const node_ref* itemNode,
506 		BPose* pose, int32 index);
507 		// the pose itself wasn't deleted but it's target node was - the
508 		// pose must be a symlink
509 	static void PoseHandleDeviceUnmounted(BPose* pose, Model* model,
510 		int32 index, BPoseView* poseView, dev_t device);
511 	static void RemoveNonBootDesktopModels(BPose*, Model* model, int32,
512 		BPoseView* poseView, dev_t);
513 
514 	// pose placement
515 	void CheckAutoPlacedPoses();
516 		// find poses that need placing and place them in a new spot
517 	void PlacePose(BPose*, BRect&);
518 		// find a new place for a pose, starting at fHintLocation
519 		// and place it
520 	bool IsValidLocation(const BPose* pose);
521 	bool IsValidLocation(const BRect& rect);
522 	status_t GetDeskbarFrame(BRect* frame);
523 	bool SlotOccupied(BRect poseRect, BRect viewBounds) const;
524 	void NextSlot(BPose*, BRect&poseRect, BRect viewBounds);
525 	void TrySettingPoseLocation(BNode* node, BPoint point);
526 	BPoint PinToGrid(BPoint, BPoint grid, BPoint offset) const;
527 
528 	// zombie pose handling
529 	Model* FindZombie(const node_ref*, int32* index = 0);
530 	BPose* ConvertZombieToPose(Model* zombie, int32 index);
531 
532 	// pose handling
533 	BRect CalcPoseRect(const BPose*, int32 index,
534 		bool firstColumnOnly = false) const;
535 	BRect CalcPoseRectIcon(const BPose*) const;
536 	BRect CalcPoseRectList(const BPose*, int32 index,
537 		bool firstColumnOnly = false) const;
538 	void DrawPose(BPose*, int32 index, bool fullDraw = true);
539 	void DrawViewCommon(const BRect&updateRect);
540 
541 	// pose list handling
542 	int32 BSearchList(PoseList* poseList, const BPose*, int32* index,
543 		int32 oldIndex);
544 	void InsertPoseAfter(BPose* pose, int32* index, int32 orientation,
545 		BRect* invalidRect);
546 		// does a CopyBits to scroll poses making room for a new pose,
547 		// returns rectangle that needs invalidating
548 	void CloseGapInList(BRect* invalidRect);
549 	int32 FirstIndexAtOrBelow(int32 y, bool constrainIndex = true) const;
550 	void AddToVSList(BPose*);
551 	int32 RemoveFromVSList(const BPose*);
552 	BPose* FindNearbyPose(char arrow, int32* index);
553 	BPose* FindBestMatch(int32* index);
554 	BPose* FindNextMatch(int32* index, bool reverse = false);
555 
556 	// node monitoring calls
557 	virtual void StartWatching();
558 	virtual void StopWatching();
559 
560 	status_t WatchNewNode(const node_ref* item);
561 		// the above would ideally be the only call of these three and
562 		// it would be a virtual, overriding the specific watch mask in
563 		// query pose view, etc. however we need to call WatchNewNode
564 		// from inside AddPosesTask while the window is unlocked - we
565 		// have to use the static and a cached messenger and masks.
566 	static status_t WatchNewNode(const node_ref*, uint32, BMessenger);
567 	virtual uint32 WatchNewNodeMask();
568 		// override to change different watch modes for query pose
569 		// view, etc.
570 
571 	// drag&drop handling
572 	static bool EachItemInDraggedSelection(const BMessage* message,
573 		bool (*)(BPose*, BPoseView*, void*), BPoseView* poseView,
574 		void* = NULL);
575 		// iterates through each pose in current selectiond in the source
576 		// window of the current drag message; locks the window
577 		// add const version
578 	BRect GetDragRect(int32 clickedPoseIndex);
579 	BBitmap* MakeDragBitmap(BRect dragRect, BPoint clickedPoint,
580 		int32 clickedPoseIndex, BPoint&offset);
581 	static bool FindDragNDropAction(const BMessage* dragMessage,
582 		bool&canCopy, bool&canMove, bool&canLink, bool&canErase);
583 
584 	static bool CanTrashForeignDrag(const Model*);
585 	static bool CanCopyOrMoveForeignDrag(const Model*, const BMessage*);
586 	static bool DragSelectionContains(const BPose* target,
587 		const BMessage* dragMessage);
588 	static status_t CreateClippingFile(BPoseView* poseView, BFile&result,
589 		char* resultingName, BDirectory* directory, BMessage* message,
590 		const char* fallbackName, bool setLocation = false,
591 		BPoint dropPoint = BPoint(0, 0));
592 
593 	// opening files, lanunching
594 	void OpenSelectionCommon(BPose*, int32*, bool);
595 		// used by OpenSelection and OpenSelectionUsing
596 	static void LaunchAppWithSelection(Model*, const BMessage*,
597 		bool checkTypes = true);
598 
599 	// node monitoring calls
600 	virtual bool EntryMoved(const BMessage*);
601 	virtual bool AttributeChanged(const BMessage*);
602 	virtual bool NoticeMetaMimeChanged(const BMessage*);
603 	virtual void MetaMimeChanged(const char*, const char*);
604 
605 	// click handling
606 	bool WasDoubleClick(const BPose*, BPoint point, int32 buttons);
607 	bool WasClickInPath(const BPose*, int32 index,
608 		BPoint mouseLocation) const;
609 
610 	// selection
611 	void SelectPosesListMode(BRect, BList**);
612 	void SelectPosesIconMode(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 askUser);
671 	void Delete(const entry_ref&ref, bool selectNext, bool askUser);
672 	void RestoreItemsFromTrash(BObjectList<entry_ref>*, bool selectNext);
673 
674 	void WatchParentOf(const entry_ref*);
675 	void StopWatchingParentsOf(const entry_ref*);
676 
677 	void ExcludeTrashFromSelection();
678 
679 private:
680 	void DrawOpenAnimation(BRect);
681 	void ApplyBackgroundColor();
682 	float BackTint() const;
683 	rgb_color InvertedBackColor() const;
684 
685 	void MoveSelectionOrEntryToTrash(const entry_ref* ref, bool selectNext);
686 
687 protected:
688 	struct node_ref_key {
689 		node_ref_key() {}
690 		node_ref_key(const node_ref& value) : value(value) {}
691 
692 		uint32 GetHashCode() const
693 		{
694 			return (uint32)value.device ^ (uint32)value.node;
695 		}
696 
697 		node_ref_key operator=(const node_ref_key& other)
698 		{
699 			value = other.value;
700 			return *this;
701 		}
702 
703 		bool operator==(const node_ref_key& other) const
704 		{
705 			return (value == other.value);
706 		}
707 
708 		bool operator!=(const node_ref_key& other) const
709 		{
710 			return (value != other.value);
711 		}
712 
713 		node_ref	value;
714 	};
715 
716 protected:
717 	BViewState* fViewState;
718 	bool fStateNeedsSaving;
719 
720 	bool fSavePoseLocations : 1;
721 	bool fMultipleSelection : 1;
722 	bool fDragEnabled : 1;
723 	bool fDropEnabled : 1;
724 
725 	BLooper* fSelectionHandler;
726 
727 	std::set<thread_id> fAddPosesThreads;
728 	PoseList* fPoseList;
729 
730 	PendingNodeMonitorCache pendingNodeMonitorCache;
731 
732 private:
733 	TScrollBar* fHScrollBar;
734 	BScrollBar* fVScrollBar;
735 	Model* fModel;
736 	BPose* fActivePose;
737 	BRect fExtent;
738 	// the following should probably be just member lists, not pointers
739 	PoseList* fFilteredPoseList;
740 	PoseList* fVSPoseList;
741 	PoseList* fSelectionList;
742 	HashSet<node_ref_key> fInsertedNodes;
743 	BObjectList<BString> fMimeTypesInSelectionCache;
744 		// used for mime string based icon highliting during a drag
745 	BObjectList<Model>* fZombieList;
746 	BObjectList<BColumn>* fColumnList;
747 	BObjectList<BString>* fMimeTypeList;
748 	BObjectList<Model>* fBrokenLinks;
749 	bool fMimeTypeListIsDirty;
750 	BCountView* fCountView;
751 	float fListElemHeight;
752 	float fListOffset;
753 	float fIconPoseHeight;
754 	BPose* fDropTarget;
755 	BPose* fAlreadySelectedDropTarget;
756 	BPoint fLastClickPoint;
757 	int32 fLastClickButtons;
758 	const BPose* fLastClickedPose;
759 	BPoint fLastLeftTop;
760 	BRect fLastExtent;
761 	BTitleView* fTitleView;
762 	BRefFilter* fRefFilter;
763 	BPoint fGrid;
764 	BPoint fOffset;
765 	BPoint fHintLocation;
766 	float fAutoScrollInc;
767 	int32 fAutoScrollState;
768 	bool fWidgetTextOutline;
769 	const BPose* fSelectionPivotPose;
770 	const BPose* fRealPivotPose;
771 	BMessageRunner* fKeyRunner;
772 	bool fTrackRightMouseUp;
773 	bool fTrackMouseUp;
774 
775 	struct SelectionRectInfo {
776 		SelectionRectInfo()
777 			:
778 			isDragging(false),
779 			selection(NULL)
780 		{
781 		}
782 
783 		bool isDragging;
784 		BRect rect;
785 		BRect lastRect;
786 		BPoint startPoint;
787 		BPoint lastPoint;
788 		BList* selection;
789 	};
790 	SelectionRectInfo fSelectionRectInfo;
791 
792 	bool fSelectionVisible : 1;
793 	bool fSelectionRectEnabled : 1;
794 	bool fTransparentSelection : 1;
795 	bool fAlwaysAutoPlace : 1;
796 	bool fAllowPoseEditing : 1;
797 	bool fSelectionChangedHook : 1;
798 		// get rid of this
799 	bool fOkToMapIcons : 1;
800 	bool fEnsurePosesVisible : 1;
801 	bool fShouldAutoScroll : 1;
802 	bool fIsDesktopWindow : 1;
803 	bool fIsWatchingDateFormatChange : 1;
804 	bool fHasPosesInClipboard : 1;
805 	bool fCursorCheck : 1;
806 	bool fFiltering : 1;
807 
808 	BObjectList<BString> fFilterStrings;
809 	int32 fLastFilterStringCount;
810 	int32 fLastFilterStringLength;
811 
812 	BRect fStartFrame;
813 
814 	static float sFontHeight;
815 	static font_height sFontInfo;
816 	static BString sMatchString;
817 		// used for typeahead - should be replaced by a typeahead state
818 
819 	bigtime_t fLastKeyTime;
820 	bigtime_t fLastDeskbarFrameCheckTime;
821 	BRect fDeskbarFrame;
822 
823 	static OffscreenBitmap* sOffscreen;
824 
825 	BTextWidget* fTextWidgetToCheck;
826 	BTextWidget* fActiveTextWidget;
827 
828 private:
829 	mutable uint32 fCachedIconSizeFrom;
830 	mutable BSize fCachedIconSize;
831 
832 	typedef BView _inherited;
833 };
834 
835 
836 class TScrollBar : public BScrollBar {
837 public:
838 	TScrollBar(const char*, BView*, float, float);
839 	void SetTitleView(BView*);
840 
841 	// BScrollBar overrides
842 	virtual	void ValueChanged(float);
843 
844 private:
845 	BView* fTitleView;
846 
847 	typedef BScrollBar _inherited;
848 };
849 
850 
851 class TPoseViewFilter : public BMessageFilter {
852 public:
853 	TPoseViewFilter(BPoseView* pose);
854 	~TPoseViewFilter();
855 
856 	filter_result Filter(BMessage*, BHandler**);
857 
858 private:
859 	filter_result ObjectDropFilter(BMessage*, BHandler**);
860 
861 	BPoseView* fPoseView;
862 };
863 
864 
865 extern bool
866 ClearViewOriginOne(const char* name, uint32 type, off_t size, void* data,
867 	void* params);
868 
869 
870 // inlines follow
871 
872 
873 inline BContainerWindow*
874 BPoseView::ContainerWindow() const
875 {
876 	return dynamic_cast<BContainerWindow*>(Window());
877 }
878 
879 
880 inline Model*
881 BPoseView::TargetModel() const
882 {
883 	return fModel;
884 }
885 
886 
887 inline float
888 BPoseView::ListElemHeight() const
889 {
890 	return fListElemHeight;
891 }
892 
893 
894 inline float
895 BPoseView::ListOffset() const
896 {
897 	return fListOffset;
898 }
899 
900 
901 inline float
902 BPoseView::IconPoseHeight() const
903 {
904 	return fIconPoseHeight;
905 }
906 
907 
908 inline uint32
909 BPoseView::UnscaledIconSizeInt() const
910 {
911 	return fViewState->IconSize();
912 }
913 
914 
915 inline uint32
916 BPoseView::IconSizeInt() const
917 {
918 	return IconSize().IntegerWidth() + 1;
919 }
920 
921 
922 inline PoseList*
923 BPoseView::SelectionList() const
924 {
925 	return fSelectionList;
926 }
927 
928 inline int32
929 BPoseView::CountSelected() const
930 {
931 	return fSelectionList->CountItems();
932 }
933 
934 inline BObjectList<BString>*
935 BPoseView::MimeTypesInSelection()
936 {
937 	return &fMimeTypesInSelectionCache;
938 }
939 
940 
941 inline BScrollBar*
942 BPoseView::HScrollBar() const
943 {
944 	return fHScrollBar;
945 }
946 
947 
948 inline BScrollBar*
949 BPoseView::VScrollBar() const
950 {
951 	return fVScrollBar;
952 }
953 
954 
955 inline BCountView*
956 BPoseView::CountView() const
957 {
958 	return fCountView;
959 }
960 
961 
962 inline BTitleView*
963 BPoseView::TitleView() const
964 {
965 	return fTitleView;
966 }
967 
968 
969 inline bool
970 BPoseView::StateNeedsSaving()
971 {
972 	return fStateNeedsSaving || fViewState->StateNeedsSaving();
973 }
974 
975 
976 inline uint32
977 BPoseView::ViewMode() const
978 {
979 	return fViewState->ViewMode();
980 }
981 
982 
983 inline font_height
984 BPoseView::FontInfo() const
985 {
986 	return sFontInfo;
987 }
988 
989 
990 inline float
991 BPoseView::FontHeight() const
992 {
993 	return sFontHeight;
994 }
995 
996 
997 inline BPose*
998 BPoseView::ActivePose() const
999 {
1000 	return fActivePose;
1001 }
1002 
1003 
1004 inline void
1005 BPoseView::DisableSaveLocation()
1006 {
1007 	fSavePoseLocations = false;
1008 }
1009 
1010 
1011 inline bool
1012 BPoseView::IsFilePanel() const
1013 {
1014 	return false;
1015 }
1016 
1017 
1018 inline bool
1019 BPoseView::IsDesktopWindow() const
1020 {
1021 	return fIsDesktopWindow;
1022 }
1023 
1024 
1025 inline bool
1026 BPoseView::IsDesktopView() const
1027 {
1028 	return false;
1029 }
1030 
1031 
1032 inline rgb_color
1033 BPoseView::DeskTextColor() const
1034 {
1035 	// The desktop color is chosen independently for the desktop.
1036 	// The text color is chosen globally for all directories.
1037 	// It's fairly easy to get something unreadable (even with the default
1038 	// settings, it's expected that text will be black on white in Tracker
1039 	// folders, but white on blue on the desktop).
1040 	// So here we check if the colors are different enough, and otherwise,
1041 	// force the text to be either white or black.
1042 	rgb_color textColor = HighColor();
1043 	rgb_color viewColor = ViewColor();
1044 
1045 	int textBrightness = BPrivate::perceptual_brightness(textColor);
1046 	int viewBrightness = BPrivate::perceptual_brightness(viewColor);
1047 	if (abs(viewBrightness - textBrightness) > 127) {
1048 		// The colors are different enough, we can use them as is
1049 		return textColor;
1050 	} else {
1051 		if (viewBrightness > 127) {
1052 			textColor.red = 0;
1053 			textColor.green = 0;
1054 			textColor.blue = 0;
1055 		} else {
1056 			textColor.red = 255;
1057 			textColor.green = 255;
1058 			textColor.blue = 255;
1059 		}
1060 
1061 		return textColor;
1062 	}
1063 }
1064 
1065 
1066 inline rgb_color
1067 BPoseView::DeskTextBackColor() const
1068 {
1069 	// returns black or white color depending on the desktop background
1070 	int32 thresh = 0;
1071 	rgb_color color = LowColor();
1072 
1073 	if (color.red > 150)
1074 		thresh++;
1075 
1076 	if (color.green > 150)
1077 		thresh++;
1078 
1079 	if (color.blue > 150)
1080 		thresh++;
1081 
1082 	if (thresh > 1) {
1083 		color.red = 255;
1084 		color.green = 255;
1085 		color.blue = 255;
1086 	} else {
1087 		color.red = 0;
1088 		color.green = 0;
1089 		color.blue = 0;
1090 	}
1091 
1092 	return color;
1093 }
1094 
1095 
1096 inline uint32
1097 BPoseView::PrimarySort() const
1098 {
1099 	return fViewState->PrimarySort();
1100 }
1101 
1102 
1103 inline uint32
1104 BPoseView::PrimarySortType() const
1105 {
1106 	return fViewState->PrimarySortType();
1107 }
1108 
1109 
1110 inline uint32
1111 BPoseView::SecondarySort() const
1112 {
1113 	return fViewState->SecondarySort();
1114 }
1115 
1116 
1117 inline uint32
1118 BPoseView::SecondarySortType() const
1119 {
1120 	return fViewState->SecondarySortType();
1121 }
1122 
1123 
1124 inline bool
1125 BPoseView::ReverseSort() const
1126 {
1127 	return fViewState->ReverseSort();
1128 }
1129 
1130 
1131 inline void
1132 BPoseView::SetIconMapping(bool on)
1133 {
1134 	fOkToMapIcons = on;
1135 }
1136 
1137 
1138 inline void
1139 BPoseView::AddToExtent(const BRect&rect)
1140 {
1141 	fExtent = fExtent | rect;
1142 }
1143 
1144 
1145 inline void
1146 BPoseView::ClearExtent()
1147 {
1148 	fExtent.Set(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN);
1149 }
1150 
1151 
1152 inline int32
1153 BPoseView::CountColumns() const
1154 {
1155 	return fColumnList->CountItems();
1156 }
1157 
1158 
1159 inline float
1160 BPoseView::StartOffset() const
1161 {
1162 	return fListOffset + ListIconSize() + kMiniIconSeparator + 1;
1163 }
1164 
1165 
1166 inline int32
1167 BPoseView::IndexOfColumn(const BColumn* column) const
1168 {
1169 	return fColumnList->IndexOf(const_cast<BColumn*>(column));
1170 }
1171 
1172 
1173 inline int32
1174 BPoseView::IndexOfPose(const BPose* pose) const
1175 {
1176 	return CurrentPoseList()->IndexOf(pose);
1177 }
1178 
1179 
1180 inline BPose*
1181 BPoseView::PoseAtIndex(int32 index) const
1182 {
1183 	return CurrentPoseList()->ItemAt(index);
1184 }
1185 
1186 
1187 inline BColumn*
1188 BPoseView::ColumnAt(int32 index) const
1189 {
1190 	return fColumnList->ItemAt(index);
1191 }
1192 
1193 
1194 inline BColumn*
1195 BPoseView::FirstColumn() const
1196 {
1197 	return fColumnList->FirstItem();
1198 }
1199 
1200 
1201 inline BColumn*
1202 BPoseView::LastColumn() const
1203 {
1204 	return fColumnList->LastItem();
1205 }
1206 
1207 
1208 inline int32
1209 BPoseView::CountItems() const
1210 {
1211 	return CurrentPoseList()->CountItems();
1212 }
1213 
1214 
1215 inline void
1216 BPoseView::SetMultipleSelection(bool state)
1217 {
1218 	fMultipleSelection = state;
1219 }
1220 
1221 
1222 inline void
1223 BPoseView::SetSelectionChangedHook(bool state)
1224 {
1225 	fSelectionChangedHook = state;
1226 }
1227 
1228 
1229 inline void
1230 BPoseView::SetAutoScroll(bool state)
1231 {
1232 	fShouldAutoScroll = state;
1233 }
1234 
1235 
1236 inline void
1237 BPoseView::SetPoseEditing(bool state)
1238 {
1239 	fAllowPoseEditing = state;
1240 }
1241 
1242 
1243 inline void
1244 BPoseView::SetDragEnabled(bool state)
1245 {
1246 	fDragEnabled = state;
1247 }
1248 
1249 
1250 inline void
1251 BPoseView::SetDropEnabled(bool state)
1252 {
1253 	fDropEnabled = state;
1254 }
1255 
1256 
1257 inline void
1258 BPoseView::SetSelectionRectEnabled(bool state)
1259 {
1260 	fSelectionRectEnabled = state;
1261 }
1262 
1263 
1264 inline void
1265 BPoseView::SetAlwaysAutoPlace(bool state)
1266 {
1267 	fAlwaysAutoPlace = state;
1268 }
1269 
1270 
1271 inline void
1272 BPoseView::SetEnsurePosesVisible(bool state)
1273 {
1274 	fEnsurePosesVisible = state;
1275 }
1276 
1277 
1278 inline void
1279 BPoseView::SetSelectionHandler(BLooper* looper)
1280 {
1281 	fSelectionHandler = looper;
1282 }
1283 
1284 
1285 inline void
1286 TScrollBar::SetTitleView(BView* view)
1287 {
1288 	fTitleView = view;
1289 }
1290 
1291 
1292 inline void
1293 BPoseView::SetRefFilter(BRefFilter* filter)
1294 {
1295 	fRefFilter = filter;
1296 	if (filter != NULL)
1297 		FilterChanged();
1298 }
1299 
1300 
1301 inline BRefFilter*
1302 BPoseView::RefFilter() const
1303 {
1304 	return fRefFilter;
1305 }
1306 
1307 
1308 inline BPose*
1309 BPoseView::FindPose(const Model* model, int32* index) const
1310 {
1311 	return CurrentPoseList()->FindPose(model, index);
1312 }
1313 
1314 
1315 inline BPose*
1316 BPoseView::FindPose(const node_ref* node, int32* index) const
1317 {
1318 	return CurrentPoseList()->FindPose(node, index);
1319 }
1320 
1321 
1322 inline BPose*
1323 BPoseView::FindPose(const entry_ref* entry, int32* index) const
1324 {
1325 	return CurrentPoseList()->FindPose(entry, index);
1326 }
1327 
1328 
1329 inline bool
1330 BPoseView::HasPosesInClipboard()
1331 {
1332 	return fHasPosesInClipboard;
1333 }
1334 
1335 
1336 inline void
1337 BPoseView::SetHasPosesInClipboard(bool hasPoses)
1338 {
1339 	fHasPosesInClipboard = hasPoses;
1340 }
1341 
1342 
1343 inline PoseList*
1344 BPoseView::CurrentPoseList() const
1345 {
1346 	return fFiltering ? fFilteredPoseList : fPoseList;
1347 }
1348 
1349 
1350 template<class Param1>
1351 void
1352 EachTextWidget(BPose* pose, BPoseView* poseView,
1353 	void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*, Param1), Param1 p1)
1354 {
1355 	for (int32 index = 0; ;index++) {
1356 		BColumn* column = poseView->ColumnAt(index);
1357 		if (column == NULL)
1358 			break;
1359 
1360 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1361 		if (widget != NULL)
1362 			(func)(widget, pose, poseView, column, p1);
1363 	}
1364 }
1365 
1366 
1367 template<class Param1, class Param2>
1368 void
1369 EachTextWidget(BPose* pose, BPoseView* poseView,
1370 	void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*,
1371 	Param1, Param2), Param1 p1, Param2 p2)
1372 {
1373 	for (int32 index = 0; ;index++) {
1374 		BColumn* column = poseView->ColumnAt(index);
1375 		if (column == NULL)
1376 			break;
1377 
1378 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1379 		if (widget != NULL)
1380 			(func)(widget, pose, poseView, column, p1, p2);
1381 	}
1382 }
1383 
1384 
1385 template<class Result, class Param1, class Param2>
1386 Result
1387 WhileEachTextWidget(BPose* pose, BPoseView* poseView,
1388 	Result (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*,
1389 	Param1, Param2), Param1 p1, Param2 p2)
1390 {
1391 	for (int32 index = 0; ;index++) {
1392 		BColumn* column = poseView->ColumnAt(index);
1393 		if (column == NULL)
1394 			break;
1395 
1396 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1397 		if (widget != NULL) {
1398 			Result result = (func)(widget, pose, poseView, column, p1, p2);
1399 			if (result != 0)
1400 				return result;
1401 		}
1402 	}
1403 
1404 	return 0;
1405 }
1406 
1407 
1408 } // namespace BPrivate
1409 
1410 using namespace BPrivate;
1411 
1412 
1413 #endif	// _POSE_VIEW_H
1414