xref: /haiku/src/kits/tracker/PoseView.h (revision 106388ddbfdd00f4409c86bd3fe8d581bae532ec)
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 SelectPoses(BRect, BList**);
612 	void AddRemoveSelectionRange(BPoint where, bool extendSelection,
613 		BPose* pose);
614 
615 	void _BeginSelectionRect(const BPoint& point, bool extendSelection);
616 	void _UpdateSelectionRect(const BPoint& point);
617 	void _EndSelectionRect();
618 
619 	// view drawing
620 	void SynchronousUpdate(BRect, bool clip = false);
621 
622 	// scrolling
623 	void HandleAutoScroll();
624 	bool CheckAutoScroll(BPoint mouseLoc, bool shouldScroll);
625 
626 	// view extent handling
627 	void RecalcExtent();
628 	void AddToExtent(const BRect&);
629 	void ClearExtent();
630 	void RemoveFromExtent(const BRect&);
631 
632 	virtual void EditQueries();
633 
634 	void HandleAttrMenuItemSelected(BMessage*);
635 	void TryUpdatingBrokenLinks();
636 		// ran a little after a volume gets mounted
637 
638 	void MapToNewIconMode(BPose*, BPoint oldGrid, BPoint oldOffset);
639 	void ResetOrigin();
640 	void PinPointToValidRange(BPoint&);
641 		// used to ensure pose locations make sense after getting them
642 		// in pose info from attributes, etc.
643 
644 	void FinishPendingScroll(float&listViewScrollBy, BRect bounds);
645 		// utility call for CreatePoses
646 
647 	// background AddPoses task calls
648 	static status_t AddPosesTask(void*);
649 	virtual void AddPosesCompleted();
650 	bool IsValidAddPosesThread(thread_id) const;
651 
652 	// typeahead filtering
653 	void EnsurePoseUnselected(BPose* pose);
654 	void RemoveFilteredPose(BPose* pose, int32 index);
655 	void FilterChanged();
656 	void UpdateAfterFilterChange();
657 	bool FilterPose(BPose* pose);
658 	void StartFiltering();
659 	void StopFiltering();
660 	void ClearFilter();
661 	PoseList* CurrentPoseList() const;
662 
663 	// misc
664 	BList* GetDropPointList(BPoint dropPoint, BPoint startPoint,
665 		const PoseList*, bool sourceInListMode, bool dropOnGrid) const;
666 	void SendSelectionAsRefs(uint32 what, bool onlyQueries = false);
667 	void MoveListToTrash(BObjectList<entry_ref>*, bool selectNext,
668 		bool deleteDirectly);
669 	void Delete(BObjectList<entry_ref>*, bool selectNext, bool askUser);
670 	void Delete(const entry_ref&ref, bool selectNext, bool askUser);
671 	void RestoreItemsFromTrash(BObjectList<entry_ref>*, bool selectNext);
672 
673 	void WatchParentOf(const entry_ref*);
674 	void StopWatchingParentsOf(const entry_ref*);
675 
676 	void ExcludeTrashFromSelection();
677 
678 private:
679 	void DrawOpenAnimation(BRect);
680 	void ApplyBackgroundColor();
681 	float BackTint() const;
682 	rgb_color InvertedBackColor() const;
683 
684 	void MoveSelectionOrEntryToTrash(const entry_ref* ref, bool selectNext);
685 
686 protected:
687 	struct node_ref_key {
688 		node_ref_key() {}
689 		node_ref_key(const node_ref& value) : value(value) {}
690 
691 		uint32 GetHashCode() const
692 		{
693 			return (uint32)value.device ^ (uint32)value.node;
694 		}
695 
696 		node_ref_key operator=(const node_ref_key& other)
697 		{
698 			value = other.value;
699 			return *this;
700 		}
701 
702 		bool operator==(const node_ref_key& other) const
703 		{
704 			return (value == other.value);
705 		}
706 
707 		bool operator!=(const node_ref_key& other) const
708 		{
709 			return (value != other.value);
710 		}
711 
712 		node_ref	value;
713 	};
714 
715 protected:
716 	BViewState* fViewState;
717 	bool fStateNeedsSaving;
718 
719 	bool fSavePoseLocations : 1;
720 	bool fMultipleSelection : 1;
721 	bool fDragEnabled : 1;
722 	bool fDropEnabled : 1;
723 
724 	BLooper* fSelectionHandler;
725 
726 	std::set<thread_id> fAddPosesThreads;
727 	PoseList* fPoseList;
728 
729 	PendingNodeMonitorCache pendingNodeMonitorCache;
730 
731 private:
732 	TScrollBar* fHScrollBar;
733 	BScrollBar* fVScrollBar;
734 	Model* fModel;
735 	BPose* fActivePose;
736 	BRect fExtent;
737 	// the following should probably be just member lists, not pointers
738 	PoseList* fFilteredPoseList;
739 	PoseList* fVSPoseList;
740 	PoseList* fSelectionList;
741 	HashSet<node_ref_key> fInsertedNodes;
742 	BObjectList<BString> fMimeTypesInSelectionCache;
743 		// used for mime string based icon highliting during a drag
744 	BObjectList<Model>* fZombieList;
745 	BObjectList<BColumn>* fColumnList;
746 	BObjectList<BString>* fMimeTypeList;
747 	BObjectList<Model>* fBrokenLinks;
748 	bool fMimeTypeListIsDirty;
749 	BCountView* fCountView;
750 	float fListElemHeight;
751 	float fListOffset;
752 	float fIconPoseHeight;
753 	BPose* fDropTarget;
754 	BPose* fAlreadySelectedDropTarget;
755 	BPoint fLastClickPoint;
756 	int32 fLastClickButtons;
757 	const BPose* fLastClickedPose;
758 	BPoint fLastLeftTop;
759 	BRect fLastExtent;
760 	BTitleView* fTitleView;
761 	BRefFilter* fRefFilter;
762 	BPoint fGrid;
763 	BPoint fOffset;
764 	BPoint fHintLocation;
765 	float fAutoScrollInc;
766 	int32 fAutoScrollState;
767 	bool fWidgetTextOutline;
768 	const BPose* fSelectionPivotPose;
769 	const BPose* fRealPivotPose;
770 	BMessageRunner* fKeyRunner;
771 	bool fTrackRightMouseUp;
772 	bool fTrackMouseUp;
773 
774 	struct SelectionRectInfo {
775 		SelectionRectInfo()
776 			:
777 			isDragging(false),
778 			selection(NULL)
779 		{
780 		}
781 
782 		bool isDragging;
783 		BRect rect;
784 		BRect lastRect;
785 		BPoint startPoint;
786 		BPoint lastPoint;
787 		BList* selection;
788 	};
789 	SelectionRectInfo fSelectionRectInfo;
790 
791 	bool fSelectionVisible : 1;
792 	bool fSelectionRectEnabled : 1;
793 	bool fTransparentSelection : 1;
794 	bool fAlwaysAutoPlace : 1;
795 	bool fAllowPoseEditing : 1;
796 	bool fSelectionChangedHook : 1;
797 		// get rid of this
798 	bool fOkToMapIcons : 1;
799 	bool fEnsurePosesVisible : 1;
800 	bool fShouldAutoScroll : 1;
801 	bool fIsDesktopWindow : 1;
802 	bool fIsWatchingDateFormatChange : 1;
803 	bool fHasPosesInClipboard : 1;
804 	bool fCursorCheck : 1;
805 	bool fFiltering : 1;
806 
807 	BObjectList<BString> fFilterStrings;
808 	int32 fLastFilterStringCount;
809 	int32 fLastFilterStringLength;
810 
811 	BRect fStartFrame;
812 
813 	static float sFontHeight;
814 	static font_height sFontInfo;
815 	static BString sMatchString;
816 		// used for typeahead - should be replaced by a typeahead state
817 
818 	bigtime_t fLastKeyTime;
819 	bigtime_t fLastDeskbarFrameCheckTime;
820 	BRect fDeskbarFrame;
821 
822 	static OffscreenBitmap* sOffscreen;
823 
824 	BTextWidget* fTextWidgetToCheck;
825 	BTextWidget* fActiveTextWidget;
826 
827 private:
828 	mutable uint32 fCachedIconSizeFrom;
829 	mutable BSize fCachedIconSize;
830 
831 	typedef BView _inherited;
832 };
833 
834 
835 class TScrollBar : public BScrollBar {
836 public:
837 	TScrollBar(const char*, BView*, float, float);
838 	void SetTitleView(BView*);
839 
840 	// BScrollBar overrides
841 	virtual	void ValueChanged(float);
842 
843 private:
844 	BView* fTitleView;
845 
846 	typedef BScrollBar _inherited;
847 };
848 
849 
850 class TPoseViewFilter : public BMessageFilter {
851 public:
852 	TPoseViewFilter(BPoseView* pose);
853 	~TPoseViewFilter();
854 
855 	filter_result Filter(BMessage*, BHandler**);
856 
857 private:
858 	filter_result ObjectDropFilter(BMessage*, BHandler**);
859 
860 	BPoseView* fPoseView;
861 };
862 
863 
864 extern bool
865 ClearViewOriginOne(const char* name, uint32 type, off_t size, void* data,
866 	void* params);
867 
868 
869 // inlines follow
870 
871 
872 inline BContainerWindow*
873 BPoseView::ContainerWindow() const
874 {
875 	return dynamic_cast<BContainerWindow*>(Window());
876 }
877 
878 
879 inline Model*
880 BPoseView::TargetModel() const
881 {
882 	return fModel;
883 }
884 
885 
886 inline float
887 BPoseView::ListElemHeight() const
888 {
889 	return fListElemHeight;
890 }
891 
892 
893 inline float
894 BPoseView::ListOffset() const
895 {
896 	return fListOffset;
897 }
898 
899 
900 inline float
901 BPoseView::IconPoseHeight() const
902 {
903 	return fIconPoseHeight;
904 }
905 
906 
907 inline uint32
908 BPoseView::UnscaledIconSizeInt() const
909 {
910 	return fViewState->IconSize();
911 }
912 
913 
914 inline uint32
915 BPoseView::IconSizeInt() const
916 {
917 	return IconSize().IntegerWidth() + 1;
918 }
919 
920 
921 inline PoseList*
922 BPoseView::SelectionList() const
923 {
924 	return fSelectionList;
925 }
926 
927 inline int32
928 BPoseView::CountSelected() const
929 {
930 	return fSelectionList->CountItems();
931 }
932 
933 inline BObjectList<BString>*
934 BPoseView::MimeTypesInSelection()
935 {
936 	return &fMimeTypesInSelectionCache;
937 }
938 
939 
940 inline BScrollBar*
941 BPoseView::HScrollBar() const
942 {
943 	return fHScrollBar;
944 }
945 
946 
947 inline BScrollBar*
948 BPoseView::VScrollBar() const
949 {
950 	return fVScrollBar;
951 }
952 
953 
954 inline BCountView*
955 BPoseView::CountView() const
956 {
957 	return fCountView;
958 }
959 
960 
961 inline BTitleView*
962 BPoseView::TitleView() const
963 {
964 	return fTitleView;
965 }
966 
967 
968 inline bool
969 BPoseView::StateNeedsSaving()
970 {
971 	return fStateNeedsSaving || fViewState->StateNeedsSaving();
972 }
973 
974 
975 inline uint32
976 BPoseView::ViewMode() const
977 {
978 	return fViewState->ViewMode();
979 }
980 
981 
982 inline font_height
983 BPoseView::FontInfo() const
984 {
985 	return sFontInfo;
986 }
987 
988 
989 inline float
990 BPoseView::FontHeight() const
991 {
992 	return sFontHeight;
993 }
994 
995 
996 inline BPose*
997 BPoseView::ActivePose() const
998 {
999 	return fActivePose;
1000 }
1001 
1002 
1003 inline void
1004 BPoseView::DisableSaveLocation()
1005 {
1006 	fSavePoseLocations = false;
1007 }
1008 
1009 
1010 inline bool
1011 BPoseView::IsFilePanel() const
1012 {
1013 	return false;
1014 }
1015 
1016 
1017 inline bool
1018 BPoseView::IsDesktopWindow() const
1019 {
1020 	return fIsDesktopWindow;
1021 }
1022 
1023 
1024 inline bool
1025 BPoseView::IsDesktopView() const
1026 {
1027 	return false;
1028 }
1029 
1030 
1031 inline rgb_color
1032 BPoseView::DeskTextColor() const
1033 {
1034 	// The desktop color is chosen independently for the desktop.
1035 	// The text color is chosen globally for all directories.
1036 	// It's fairly easy to get something unreadable (even with the default
1037 	// settings, it's expected that text will be black on white in Tracker
1038 	// folders, but white on blue on the desktop).
1039 	// So here we check if the colors are different enough, and otherwise,
1040 	// force the text to be either white or black.
1041 	rgb_color textColor = HighColor();
1042 	rgb_color viewColor = ViewColor();
1043 
1044 	int textBrightness = BPrivate::perceptual_brightness(textColor);
1045 	int viewBrightness = BPrivate::perceptual_brightness(viewColor);
1046 	if (abs(viewBrightness - textBrightness) > 127) {
1047 		// The colors are different enough, we can use them as is
1048 		return textColor;
1049 	} else {
1050 		if (viewBrightness > 127) {
1051 			textColor.red = 0;
1052 			textColor.green = 0;
1053 			textColor.blue = 0;
1054 		} else {
1055 			textColor.red = 255;
1056 			textColor.green = 255;
1057 			textColor.blue = 255;
1058 		}
1059 
1060 		return textColor;
1061 	}
1062 }
1063 
1064 
1065 inline rgb_color
1066 BPoseView::DeskTextBackColor() const
1067 {
1068 	// returns black or white color depending on the desktop background
1069 	int32 thresh = 0;
1070 	rgb_color color = LowColor();
1071 
1072 	if (color.red > 150)
1073 		thresh++;
1074 
1075 	if (color.green > 150)
1076 		thresh++;
1077 
1078 	if (color.blue > 150)
1079 		thresh++;
1080 
1081 	if (thresh > 1) {
1082 		color.red = 255;
1083 		color.green = 255;
1084 		color.blue = 255;
1085 	} else {
1086 		color.red = 0;
1087 		color.green = 0;
1088 		color.blue = 0;
1089 	}
1090 
1091 	return color;
1092 }
1093 
1094 
1095 inline uint32
1096 BPoseView::PrimarySort() const
1097 {
1098 	return fViewState->PrimarySort();
1099 }
1100 
1101 
1102 inline uint32
1103 BPoseView::PrimarySortType() const
1104 {
1105 	return fViewState->PrimarySortType();
1106 }
1107 
1108 
1109 inline uint32
1110 BPoseView::SecondarySort() const
1111 {
1112 	return fViewState->SecondarySort();
1113 }
1114 
1115 
1116 inline uint32
1117 BPoseView::SecondarySortType() const
1118 {
1119 	return fViewState->SecondarySortType();
1120 }
1121 
1122 
1123 inline bool
1124 BPoseView::ReverseSort() const
1125 {
1126 	return fViewState->ReverseSort();
1127 }
1128 
1129 
1130 inline void
1131 BPoseView::SetIconMapping(bool on)
1132 {
1133 	fOkToMapIcons = on;
1134 }
1135 
1136 
1137 inline void
1138 BPoseView::AddToExtent(const BRect&rect)
1139 {
1140 	fExtent = fExtent | rect;
1141 }
1142 
1143 
1144 inline void
1145 BPoseView::ClearExtent()
1146 {
1147 	fExtent.Set(INT32_MAX, INT32_MAX, INT32_MIN, INT32_MIN);
1148 }
1149 
1150 
1151 inline int32
1152 BPoseView::CountColumns() const
1153 {
1154 	return fColumnList->CountItems();
1155 }
1156 
1157 
1158 inline float
1159 BPoseView::StartOffset() const
1160 {
1161 	return fListOffset + ListIconSize() + kMiniIconSeparator + 1;
1162 }
1163 
1164 
1165 inline int32
1166 BPoseView::IndexOfColumn(const BColumn* column) const
1167 {
1168 	return fColumnList->IndexOf(const_cast<BColumn*>(column));
1169 }
1170 
1171 
1172 inline int32
1173 BPoseView::IndexOfPose(const BPose* pose) const
1174 {
1175 	return CurrentPoseList()->IndexOf(pose);
1176 }
1177 
1178 
1179 inline BPose*
1180 BPoseView::PoseAtIndex(int32 index) const
1181 {
1182 	return CurrentPoseList()->ItemAt(index);
1183 }
1184 
1185 
1186 inline BColumn*
1187 BPoseView::ColumnAt(int32 index) const
1188 {
1189 	return fColumnList->ItemAt(index);
1190 }
1191 
1192 
1193 inline BColumn*
1194 BPoseView::FirstColumn() const
1195 {
1196 	return fColumnList->FirstItem();
1197 }
1198 
1199 
1200 inline BColumn*
1201 BPoseView::LastColumn() const
1202 {
1203 	return fColumnList->LastItem();
1204 }
1205 
1206 
1207 inline int32
1208 BPoseView::CountItems() const
1209 {
1210 	return CurrentPoseList()->CountItems();
1211 }
1212 
1213 
1214 inline void
1215 BPoseView::SetMultipleSelection(bool state)
1216 {
1217 	fMultipleSelection = state;
1218 }
1219 
1220 
1221 inline void
1222 BPoseView::SetSelectionChangedHook(bool state)
1223 {
1224 	fSelectionChangedHook = state;
1225 }
1226 
1227 
1228 inline void
1229 BPoseView::SetAutoScroll(bool state)
1230 {
1231 	fShouldAutoScroll = state;
1232 }
1233 
1234 
1235 inline void
1236 BPoseView::SetPoseEditing(bool state)
1237 {
1238 	fAllowPoseEditing = state;
1239 }
1240 
1241 
1242 inline void
1243 BPoseView::SetDragEnabled(bool state)
1244 {
1245 	fDragEnabled = state;
1246 }
1247 
1248 
1249 inline void
1250 BPoseView::SetDropEnabled(bool state)
1251 {
1252 	fDropEnabled = state;
1253 }
1254 
1255 
1256 inline void
1257 BPoseView::SetSelectionRectEnabled(bool state)
1258 {
1259 	fSelectionRectEnabled = state;
1260 }
1261 
1262 
1263 inline void
1264 BPoseView::SetAlwaysAutoPlace(bool state)
1265 {
1266 	fAlwaysAutoPlace = state;
1267 }
1268 
1269 
1270 inline void
1271 BPoseView::SetEnsurePosesVisible(bool state)
1272 {
1273 	fEnsurePosesVisible = state;
1274 }
1275 
1276 
1277 inline void
1278 BPoseView::SetSelectionHandler(BLooper* looper)
1279 {
1280 	fSelectionHandler = looper;
1281 }
1282 
1283 
1284 inline void
1285 TScrollBar::SetTitleView(BView* view)
1286 {
1287 	fTitleView = view;
1288 }
1289 
1290 
1291 inline void
1292 BPoseView::SetRefFilter(BRefFilter* filter)
1293 {
1294 	fRefFilter = filter;
1295 	if (filter != NULL)
1296 		FilterChanged();
1297 }
1298 
1299 
1300 inline BRefFilter*
1301 BPoseView::RefFilter() const
1302 {
1303 	return fRefFilter;
1304 }
1305 
1306 
1307 inline BPose*
1308 BPoseView::FindPose(const Model* model, int32* index) const
1309 {
1310 	return CurrentPoseList()->FindPose(model, index);
1311 }
1312 
1313 
1314 inline BPose*
1315 BPoseView::FindPose(const node_ref* node, int32* index) const
1316 {
1317 	return CurrentPoseList()->FindPose(node, index);
1318 }
1319 
1320 
1321 inline BPose*
1322 BPoseView::FindPose(const entry_ref* entry, int32* index) const
1323 {
1324 	return CurrentPoseList()->FindPose(entry, index);
1325 }
1326 
1327 
1328 inline bool
1329 BPoseView::HasPosesInClipboard()
1330 {
1331 	return fHasPosesInClipboard;
1332 }
1333 
1334 
1335 inline void
1336 BPoseView::SetHasPosesInClipboard(bool hasPoses)
1337 {
1338 	fHasPosesInClipboard = hasPoses;
1339 }
1340 
1341 
1342 inline PoseList*
1343 BPoseView::CurrentPoseList() const
1344 {
1345 	return fFiltering ? fFilteredPoseList : fPoseList;
1346 }
1347 
1348 
1349 template<class Param1>
1350 void
1351 EachTextWidget(BPose* pose, BPoseView* poseView,
1352 	void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*, Param1), Param1 p1)
1353 {
1354 	for (int32 index = 0; ;index++) {
1355 		BColumn* column = poseView->ColumnAt(index);
1356 		if (column == NULL)
1357 			break;
1358 
1359 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1360 		if (widget != NULL)
1361 			(func)(widget, pose, poseView, column, p1);
1362 	}
1363 }
1364 
1365 
1366 template<class Param1, class Param2>
1367 void
1368 EachTextWidget(BPose* pose, BPoseView* poseView,
1369 	void (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*,
1370 	Param1, Param2), Param1 p1, Param2 p2)
1371 {
1372 	for (int32 index = 0; ;index++) {
1373 		BColumn* column = poseView->ColumnAt(index);
1374 		if (column == NULL)
1375 			break;
1376 
1377 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1378 		if (widget != NULL)
1379 			(func)(widget, pose, poseView, column, p1, p2);
1380 	}
1381 }
1382 
1383 
1384 template<class Result, class Param1, class Param2>
1385 Result
1386 WhileEachTextWidget(BPose* pose, BPoseView* poseView,
1387 	Result (*func)(BTextWidget*, BPose*, BPoseView*, BColumn*,
1388 	Param1, Param2), Param1 p1, Param2 p2)
1389 {
1390 	for (int32 index = 0; ;index++) {
1391 		BColumn* column = poseView->ColumnAt(index);
1392 		if (column == NULL)
1393 			break;
1394 
1395 		BTextWidget* widget = pose->WidgetFor(column->AttrHash());
1396 		if (widget != NULL) {
1397 			Result result = (func)(widget, pose, poseView, column, p1, p2);
1398 			if (result != 0)
1399 				return result;
1400 		}
1401 	}
1402 
1403 	return 0;
1404 }
1405 
1406 
1407 } // namespace BPrivate
1408 
1409 using namespace BPrivate;
1410 
1411 
1412 #endif	// _POSE_VIEW_H
1413