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