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