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
23DirectoryRefFilter::DirectoryRefFilter()
24{
25}
26
27
28bool
29DirectoryRefFilter::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
52DirectoryFilePanel::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
64void
65DirectoryFilePanel::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
104void
105DirectoryFilePanel::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