xref: /haiku/src/apps/expander/DirectoryFilePanel.cpp (revision adb0d19d561947362090081e81d90dde59142026)
1 /*
2  * Copyright 2004-2009, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Jérôme Duval
7  */
8 
9 
10 #include "DirectoryFilePanel.h"
11 
12 #include <Window.h>
13 
14 #include <stdio.h>
15 #include <string.h>
16 
17 
18 DirectoryRefFilter::DirectoryRefFilter()
19 {
20 }
21 
22 
23 bool
24 DirectoryRefFilter::Filter(const entry_ref *ref, BNode* node, struct stat *st,
25 	const char *filetype)
26 {
27 	if (S_ISDIR(st->st_mode))
28 		return true;
29 
30 	if (S_ISLNK(st->st_mode)) {
31 		// Traverse symlinks
32 		BEntry entry(ref, true);
33 		return entry.IsDirectory();
34 	}
35 
36 	return false;
37 }
38 
39 
40 //	#pragma mark -
41 
42 
43 DirectoryFilePanel::DirectoryFilePanel(file_panel_mode mode, BMessenger *target,
44 		const entry_ref *startDirectory, uint32 nodeFlavors,
45 		bool allowMultipleSelection, BMessage *message, BRefFilter *filter,
46 		bool modal,	bool hideWhenDone)
47 	: BFilePanel(mode, target, startDirectory, nodeFlavors,
48 		allowMultipleSelection, message, filter, modal, hideWhenDone),
49 	fCurrentButton(NULL)
50 {
51 }
52 
53 
54 void
55 DirectoryFilePanel::Show()
56 {
57 	if (fCurrentButton == NULL) {
58 		Window()->Lock();
59 		BView* background = Window()->ChildAt(0);
60 		BView* cancel = background->FindView("cancel button");
61 
62 		BRect rect;
63 		if (cancel != NULL)
64 			rect = cancel->Frame();
65 		else {
66 			rect = background->Bounds();
67 			rect.left = rect.right;
68 			rect.top = rect.bottom - 35;
69 			rect.bottom -= 10;
70 		}
71 
72 		rect.right = rect.left -= 30;
73 		float width = be_plain_font->StringWidth("Select current") + 20;
74 		rect.left = width > 75 ? rect.right - width : rect.right - 75;
75 		fCurrentButton = new BButton(rect, "directoryButton", "Select current",
76 			new BMessage(MSG_DIRECTORY), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
77 
78 		background->AddChild(fCurrentButton);
79 		fCurrentButton->SetTarget(Messenger());
80 
81 		SetButtonLabel(B_DEFAULT_BUTTON, "Select");
82 		Window()->Unlock();
83 
84 		SelectionChanged();
85 	}
86 
87 	BFilePanel::Show();
88 }
89 
90 
91 void
92 DirectoryFilePanel::SelectionChanged()
93 {
94 	Window()->Lock();
95 
96 	char label[64];
97 	entry_ref ref;
98 	GetPanelDirectory(&ref);
99 	if (snprintf(label, sizeof(label), "Select '%s'", ref.name) >= (int)sizeof(label))
100 		strcpy(label + sizeof(label) - 5, B_UTF8_ELLIPSIS "'");
101 
102 	// Resize button so that the label fits
103 	// maximum width is dictated by the window's size limits
104 
105 	float dummy, maxWidth;
106 	Window()->GetSizeLimits(&maxWidth, &dummy, &dummy, &dummy);
107 	maxWidth -= Window()->Bounds().Width() + 8 - fCurrentButton->Frame().right;
108 
109 	BRect oldBounds = fCurrentButton->Bounds();
110 	fCurrentButton->SetLabel(label);
111 	float width, height;
112 	fCurrentButton->GetPreferredSize(&width, &height);
113 	if (width > maxWidth)
114 		width = maxWidth;
115 	fCurrentButton->ResizeTo(width, oldBounds.Height());
116 	fCurrentButton->MoveBy(oldBounds.Width() - width, 0);
117 
118 	Window()->Unlock();
119 
120 	BFilePanel::SelectionChanged();
121 }
122