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
DirectoryRefFilter()23 DirectoryRefFilter::DirectoryRefFilter()
24 {
25 }
26
27
28 bool
Filter(const entry_ref * ref,BNode * node,struct stat_beos * stat,const char * mimeType)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
DirectoryFilePanel(file_panel_mode mode,BMessenger * target,const entry_ref * startDirectory,uint32 nodeFlavors,bool allowMultipleSelection,BMessage * message,BRefFilter * filter,bool modal,bool hideWhenDone)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
Show()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
SelectionChanged()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