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