xref: /haiku/src/apps/expander/DirectoryFilePanel.cpp (revision 62f5ba006a08b0df30631375878effaf67ae5dbc)
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 TR_CONTEXT
47 #define TR_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(TR("Select current")) + 20;
81 		rect.left = width > 75 ? rect.right - width : rect.right - 75;
82 		fCurrentButton = new BButton(rect, "directoryButton", TR("Select current"),
83 			new BMessage(MSG_DIRECTORY), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
84 
85 		background->AddChild(fCurrentButton);
86 		fCurrentButton->SetTarget(Messenger());
87 
88 		SetButtonLabel(B_DEFAULT_BUTTON, TR("Select"));
89 		Window()->SetTitle(TR("Expander: Choose destination"));
90 
91 		Window()->Unlock();
92 
93 		SelectionChanged();
94 	}
95 
96 	BFilePanel::Show();
97 }
98 
99 
100 void
101 DirectoryFilePanel::SelectionChanged()
102 {
103 	Window()->Lock();
104 
105 	char label[64];
106 	entry_ref ref;
107 	GetPanelDirectory(&ref);
108 	if (snprintf(label, sizeof(label),
109 		TR("Select '%s'"), ref.name) >= (int)sizeof(label))
110 			strcpy(label + sizeof(label) - 5, B_UTF8_ELLIPSIS "'");
111 
112 	// Resize button so that the label fits
113 	// maximum width is dictated by the window's size limits
114 
115 	float dummy, maxWidth;
116 	Window()->GetSizeLimits(&maxWidth, &dummy, &dummy, &dummy);
117 	maxWidth -= Window()->Bounds().Width() + 8 - fCurrentButton->Frame().right;
118 
119 	BRect oldBounds = fCurrentButton->Bounds();
120 	fCurrentButton->SetLabel(label);
121 	float width, height;
122 	fCurrentButton->GetPreferredSize(&width, &height);
123 	if (width > maxWidth)
124 		width = maxWidth;
125 	fCurrentButton->ResizeTo(width, oldBounds.Height());
126 	fCurrentButton->MoveBy(oldBounds.Width() - width, 0);
127 
128 	Window()->Unlock();
129 
130 	BFilePanel::SelectionChanged();
131 }
132