xref: /haiku/src/apps/expander/DirectoryFilePanel.cpp (revision 5ac9b506412b11afb993bb52d161efe7666958a5)
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 <Catalog.h>
13 #include <Locale.h>
14 #include <Window.h>
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 
20 #include <compat/sys/stat.h>
21 
22 
23 DirectoryRefFilter::DirectoryRefFilter()
24 {
25 }
26 
27 
28 bool
29 DirectoryRefFilter::Filter(const entry_ref* ref, BNode* node,
30 	struct stat_beos* stat, const char* mimeType)
31 {
32 	if (S_ISDIR(stat->st_mode))
33 		return true;
34 
35 	if (S_ISLNK(stat->st_mode)) {
36 		// Traverse symlinks
37 		BEntry entry(ref, true);
38 		return entry.IsDirectory();
39 	}
40 
41 	return false;
42 }
43 
44 
45 //	#pragma mark - DirectoryFilePanel
46 
47 
48 #undef B_TRANSLATION_CONTEXT
49 #define B_TRANSLATION_CONTEXT "DirectoryFilePanel"
50 
51 
52 DirectoryFilePanel::DirectoryFilePanel(file_panel_mode mode,
53 	BMessenger* target, const entry_ref* startDirectory, uint32 nodeFlavors,
54 	bool allowMultipleSelection, BMessage* message, BRefFilter* filter,
55 	bool modal, bool hideWhenDone)
56 	:
57 	BFilePanel(mode, target, startDirectory, nodeFlavors,
58 		allowMultipleSelection, message, filter, modal, hideWhenDone),
59 	fCurrentButton(NULL)
60 {
61 }
62 
63 
64 void
65 DirectoryFilePanel::Show()
66 {
67 	if (fCurrentButton == NULL && Window()->Lock()) {
68 		BView* background = Window()->ChildAt(0);
69 		BView* cancel = background->FindView("cancel button");
70 
71 		BRect rect;
72 		if (cancel != NULL)
73 			rect = cancel->Frame();
74 		else {
75 			rect = background->Bounds();
76 			rect.left = rect.right;
77 			rect.top = rect.bottom - 35;
78 			rect.bottom -= 10;
79 		}
80 
81 		rect.right = rect.left -= 30;
82 		float width = be_plain_font->StringWidth(
83 			B_TRANSLATE("Select current")) + 20;
84 		rect.left = width > 75 ? rect.right - width : rect.right - 75;
85 		fCurrentButton = new BButton(rect, "directoryButton",
86 			B_TRANSLATE("Select current"), new BMessage(MSG_DIRECTORY),
87 			B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
88 
89 		background->AddChild(fCurrentButton);
90 		fCurrentButton->SetTarget(Messenger());
91 
92 		SetButtonLabel(B_DEFAULT_BUTTON, B_TRANSLATE("Select"));
93 		Window()->SetTitle(B_TRANSLATE("Expander: Choose destination"));
94 
95 		Window()->Unlock();
96 
97 		SelectionChanged();
98 	}
99 
100 	BFilePanel::Show();
101 }
102 
103 
104 void
105 DirectoryFilePanel::SelectionChanged()
106 {
107 	// Resize button so that the label fits
108 	// maximum width is dictated by the window's size limits
109 
110 	if (Window()->Lock()) {
111 		float dummy;
112 		float maxWidth;
113 		Window()->GetSizeLimits(&maxWidth, &dummy, &dummy, &dummy);
114 		maxWidth -= Window()->Bounds().Width() + 8
115 			- fCurrentButton->Frame().right;
116 
117 		BRect oldBounds = fCurrentButton->Bounds();
118 
119 		char* label;
120 		entry_ref ref;
121 		GetPanelDirectory(&ref);
122 		if (asprintf(&label, B_TRANSLATE("Select '%s'" B_UTF8_ELLIPSIS),
123 				ref.name) != -1) {
124 			fCurrentButton->SetLabel(label);
125 			free(label);
126 		}
127 
128 		float width;
129 		float height;
130 		fCurrentButton->GetPreferredSize(&width, &height);
131 		if (width > maxWidth)
132 			width = maxWidth;
133 
134 		fCurrentButton->ResizeTo(width, oldBounds.Height());
135 		fCurrentButton->MoveBy(oldBounds.Width() - width, 0);
136 
137 		Window()->Unlock();
138 	}
139 
140 	BFilePanel::SelectionChanged();
141 }
142