libroot/posix/stdio: Remove unused portions.
[haiku.git] / src / apps / expander / ExpanderWindow.cpp
blobd4acf6a555270a373b5193ebe4f42a270fe7d30e
1 /*
2 * Copyright 2004-2006, Jérôme DUVAL. All rights reserved.
3 * Copyright 2010, Karsten Heimrich. All rights reserved.
4 * Copyright 2013, Rene Gollent, rene@gollent.com.
5 * Distributed under the terms of the MIT License.
6 */
9 #include "ExpanderWindow.h"
11 #include <algorithm>
13 #include <Alert.h>
14 #include <Box.h>
15 #include <Button.h>
16 #include <Catalog.h>
17 #include <CheckBox.h>
18 #include <ControlLook.h>
19 #include <Entry.h>
20 #include <File.h>
21 #include <LayoutBuilder.h>
22 #include <Locale.h>
23 #include <Menu.h>
24 #include <MenuBar.h>
25 #include <MenuItem.h>
26 #include <Path.h>
27 #include <Screen.h>
28 #include <ScrollView.h>
29 #include <StringView.h>
30 #include <TextView.h>
32 #include "ExpanderApp.h"
33 #include "ExpanderThread.h"
34 #include "ExpanderPreferences.h"
35 #include "PasswordAlert.h"
38 const uint32 MSG_SOURCE = 'mSOU';
39 const uint32 MSG_DEST = 'mDES';
40 const uint32 MSG_EXPAND = 'mEXP';
41 const uint32 MSG_SHOW = 'mSHO';
42 const uint32 MSG_STOP = 'mSTO';
43 const uint32 MSG_PREFERENCES = 'mPRE';
44 const uint32 MSG_SOURCETEXT = 'mSTX';
45 const uint32 MSG_DESTTEXT = 'mDTX';
46 const uint32 MSG_SHOWCONTENTS = 'mSCT';
49 class StatusView : public BStringView {
50 public:
51 StatusView()
53 BStringView(NULL, "")
57 virtual ~StatusView()
61 void SetStatus(const BString &text)
63 fStatus = text;
64 Invalidate();
67 void Draw(BRect updateRect)
69 BString truncated = fStatus;
70 if(fStatus.IsEmpty() == false) {
71 be_plain_font->TruncateString(&truncated, B_TRUNCATE_END,
72 Bounds().Width());
75 SetText(truncated);
76 BStringView::Draw(updateRect);
79 private:
80 BString fStatus;
84 #undef B_TRANSLATION_CONTEXT
85 #define B_TRANSLATION_CONTEXT "ExpanderWindow"
88 ExpanderWindow::ExpanderWindow(BRect frame, const entry_ref* ref,
89 BMessage* settings)
91 BWindow(frame, B_TRANSLATE_SYSTEM_NAME("Expander"), B_TITLED_WINDOW,
92 B_NORMAL_WINDOW_FEEL),
93 fSourcePanel(NULL),
94 fDestPanel(NULL),
95 fSourceChanged(true),
96 fListingThread(NULL),
97 fListingStarted(false),
98 fExpandingThread(NULL),
99 fExpandingStarted(false),
100 fSettings(*settings),
101 fPreferences(NULL)
103 _CreateMenuBar();
105 fDestButton = new BButton(B_TRANSLATE("Destination"),
106 new BMessage(MSG_DEST));
107 fSourceButton = new BButton(B_TRANSLATE("Source"),
108 new BMessage(MSG_SOURCE));
109 fExpandButton = new BButton(B_TRANSLATE("Expand"),
110 new BMessage(MSG_EXPAND));
112 BSize size = fDestButton->PreferredSize();
113 size.width = std::max(size.width, fSourceButton->PreferredSize().width);
114 size.width = std::max(size.width, fExpandButton->PreferredSize().width);
116 fDestButton->SetExplicitSize(size);
117 fSourceButton->SetExplicitSize(size);
118 fExpandButton->SetExplicitSize(size);
120 fListingText = new BTextView("listingText");
121 fListingText->SetText("");
122 fListingText->MakeEditable(false);
123 fListingText->SetStylable(false);
124 fListingText->SetWordWrap(false);
125 BFont font = be_fixed_font;
126 fListingText->SetFontAndColor(&font);
127 fScrollView = new BScrollView("", fListingText, B_INVALIDATE_AFTER_LAYOUT,
128 true, true);
130 const float spacing = be_control_look->DefaultItemSpacing();
131 BGroupLayout* pathLayout;
132 BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
133 .Add(fBar)
134 .AddGroup(B_VERTICAL, B_USE_ITEM_SPACING)
135 .AddGroup(B_HORIZONTAL, B_USE_ITEM_SPACING)
136 .Add(fSourceButton)
137 .Add(fSourceText = new BTextControl(NULL, NULL,
138 new BMessage(MSG_SOURCETEXT)))
139 .End()
140 .AddGroup(B_HORIZONTAL, B_USE_ITEM_SPACING)
141 .Add(fDestButton)
142 .Add(fDestText = new BTextControl(NULL, NULL,
143 new BMessage(MSG_DESTTEXT)))
144 .End()
145 .AddGroup(B_HORIZONTAL, B_USE_ITEM_SPACING)
146 .Add(fExpandButton)
147 .AddGroup(B_HORIZONTAL, B_USE_ITEM_SPACING)
148 .GetLayout(&pathLayout)
149 .Add(fShowContents = new BCheckBox(
150 B_TRANSLATE("Show contents"),
151 new BMessage(MSG_SHOWCONTENTS)))
152 .Add(fStatusView = new StatusView())
153 .End()
154 .End()
155 .Add(fScrollView)
156 .SetInsets(B_USE_WINDOW_SPACING)
157 .End();
159 pathLayout->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
160 size = GetLayout()->View()->PreferredSize();
161 fSizeLimit = size.Height() - fScrollView->PreferredSize().height - spacing;
163 fStatusView->SetExplicitMinSize(BSize(50.0f, B_SIZE_UNSET));
164 fStatusView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
166 ResizeTo(Bounds().Width(), fSizeLimit);
167 SetSizeLimits(size.Width(), 32767.0f, fSizeLimit, fSizeLimit);
168 SetZoomLimits(Bounds().Width(), fSizeLimit);
169 fPreviousHeight = -1;
171 fScrollView->Hide();
173 Show();
177 ExpanderWindow::~ExpanderWindow()
179 if (fDestPanel && fDestPanel->RefFilter())
180 delete fDestPanel->RefFilter();
182 if (fSourcePanel && fSourcePanel->RefFilter())
183 delete fSourcePanel->RefFilter();
185 delete fDestPanel;
186 delete fSourcePanel;
190 bool
191 ExpanderWindow::ValidateDest()
193 BEntry entry(fDestText->Text(), true);
194 BVolume volume;
195 if (!entry.Exists()) {
196 BAlert* alert = new BAlert("destAlert",
197 B_TRANSLATE("Destination folder doesn't exist. "
198 "Would you like to create it?"),
199 B_TRANSLATE("Create"), B_TRANSLATE("Cancel"), NULL,
200 B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
201 alert->SetShortcut(0, B_ESCAPE);
203 if (alert->Go() != 0)
204 return false;
206 if (create_directory(fDestText->Text(), 0755) != B_OK) {
207 BAlert* alert = new BAlert("stopAlert",
208 B_TRANSLATE("Failed to create the destination folder."),
209 B_TRANSLATE("Cancel"), NULL, NULL,
210 B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
211 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
212 alert->Go();
213 return false;
216 BEntry newEntry(fDestText->Text(), true);
217 newEntry.GetRef(&fDestRef);
218 return true;
222 if (!entry.IsDirectory()) {
223 BAlert* alert = new BAlert("destAlert",
224 B_TRANSLATE("The destination is not a folder."),
225 B_TRANSLATE("Cancel"), NULL, NULL,
226 B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
227 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
228 alert->Go();
229 return false;
232 if (entry.GetVolume(&volume) != B_OK || volume.IsReadOnly()) {
233 BAlert* alert = new BAlert("destAlert",
234 B_TRANSLATE("The destination is read only."),
235 B_TRANSLATE("Cancel"), NULL, NULL, B_WIDTH_AS_USUAL,
236 B_EVEN_SPACING, B_WARNING_ALERT);
237 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
238 alert->Go();
239 return false;
242 entry.GetRef(&fDestRef);
243 return true;
247 void
248 ExpanderWindow::MessageReceived(BMessage* message)
250 switch (message->what) {
251 case MSG_SOURCE:
253 BEntry entry(fSourceText->Text(), true);
254 entry_ref srcRef;
255 if (entry.Exists() && entry.IsDirectory())
256 entry.GetRef(&srcRef);
257 if (!fSourcePanel) {
258 BMessenger messenger(this);
259 fSourcePanel = new BFilePanel(B_OPEN_PANEL, &messenger, &srcRef,
260 B_FILE_NODE, false, NULL, new RuleRefFilter(fRules), true);
261 (fSourcePanel->Window())->SetTitle(
262 B_TRANSLATE("Expander: Open"));
263 } else
264 fSourcePanel->SetPanelDirectory(&srcRef);
265 fSourcePanel->Show();
266 break;
269 case MSG_DEST:
271 BEntry entry(fDestText->Text(), true);
272 entry_ref destRef;
273 if (entry.Exists() && entry.IsDirectory())
274 entry.GetRef(&destRef);
275 if (!fDestPanel) {
276 BMessenger messenger(this);
277 fDestPanel = new DirectoryFilePanel(B_OPEN_PANEL, &messenger,
278 &destRef, B_DIRECTORY_NODE, false, NULL,
279 new DirectoryRefFilter(), true);
280 } else
281 fDestPanel->SetPanelDirectory(&destRef);
282 fDestPanel->Show();
283 break;
286 case MSG_DIRECTORY:
288 entry_ref ref;
289 fDestPanel->GetPanelDirectory(&ref);
290 fDestRef = ref;
291 BEntry entry(&ref);
292 BPath path(&entry);
293 fDestText->SetText(path.Path());
294 fDestPanel->Hide();
295 break;
298 case B_SIMPLE_DATA:
299 case B_REFS_RECEIVED:
300 RefsReceived(message);
301 break;
303 case MSG_EXPAND:
304 if (!ValidateDest())
305 break;
306 if (!fExpandingStarted) {
307 StartExpanding();
308 break;
310 // supposed to fall through
311 case MSG_STOP:
312 if (fExpandingStarted) {
313 fExpandingThread->SuspendExternalExpander();
314 BAlert* alert = new BAlert("stopAlert",
315 B_TRANSLATE("Are you sure you want to stop expanding this\n"
316 "archive? The expanded items may not be complete."),
317 B_TRANSLATE("Stop"), B_TRANSLATE("Continue"), NULL,
318 B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
319 alert->SetShortcut(0, B_ESCAPE);
320 if (alert->Go() == 0) {
321 fExpandingThread->ResumeExternalExpander();
322 StopExpanding();
323 } else
324 fExpandingThread->ResumeExternalExpander();
326 break;
328 case MSG_SHOW:
329 fShowContents->SetValue(fShowContents->Value() == B_CONTROL_OFF
330 ? B_CONTROL_ON : B_CONTROL_OFF);
331 // supposed to fall through
332 case MSG_SHOWCONTENTS:
333 // change menu item label
334 fShowItem->SetLabel(fShowContents->Value() == B_CONTROL_OFF
335 ? B_TRANSLATE("Show contents") : B_TRANSLATE("Hide contents"));
337 if (fShowContents->Value() == B_CONTROL_OFF) {
338 if (fListingStarted)
339 StopListing();
341 fScrollView->Hide();
342 _UpdateWindowSize(false);
343 } else {
344 fScrollView->Show();
345 StartListing();
347 break;
349 case MSG_SOURCETEXT:
351 BEntry entry(fSourceText->Text(), true);
352 if (!entry.Exists()) {
353 BAlert* alert = new BAlert("srcAlert",
354 B_TRANSLATE("The file doesn't exist"),
355 B_TRANSLATE("Cancel"), NULL, NULL,
356 B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
357 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
358 alert->Go();
359 break;
362 entry_ref ref;
363 entry.GetRef(&ref);
364 ExpanderRule* rule = fRules.MatchingRule(&ref);
365 if (rule) {
366 fSourceChanged = true;
367 fSourceRef = ref;
368 fShowContents->SetEnabled(true);
369 fExpandButton->SetEnabled(true);
370 fExpandItem->SetEnabled(true);
371 fShowItem->SetEnabled(true);
372 break;
375 BString string = "The file : ";
376 string += fSourceText->Text();
377 string += B_TRANSLATE_MARK(" is not supported");
378 BAlert* alert = new BAlert("srcAlert", string.String(),
379 B_TRANSLATE("Cancel"),
380 NULL, NULL, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_INFO_ALERT);
381 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
382 alert->Go();
384 fShowContents->SetEnabled(false);
385 fExpandButton->SetEnabled(false);
386 fExpandItem->SetEnabled(false);
387 fShowItem->SetEnabled(false);
388 break;
391 case MSG_DESTTEXT:
392 ValidateDest();
393 break;
395 case MSG_PREFERENCES:
396 if (fPreferences == NULL)
397 fPreferences = new ExpanderPreferences(&fSettings);
399 fPreferences->Show();
400 break;
402 case 'outp':
403 if (!fExpandingStarted && fListingStarted) {
404 // Check if the vertical scroll bar is at the end
405 float max, pos;
406 fScrollView->ScrollBar(B_VERTICAL)->GetRange(NULL, &max);
407 pos = fScrollView->ScrollBar(B_VERTICAL)->Value();
408 bool atEnd = (pos == max);
410 BString string;
411 int32 i = 0;
412 while (message->FindString("output", i++, &string) == B_OK) {
413 float length = fListingText->StringWidth(string.String());
415 if (length > fLongestLine)
416 fLongestLine = length;
418 fListingText->Insert(string.String());
421 if (atEnd && fScrollView->ScrollBar(B_VERTICAL)->Value() == pos) {
422 fScrollView->ScrollBar(B_VERTICAL)->GetRange(NULL, &max);
423 fScrollView->ScrollBar(B_VERTICAL)->SetValue(max);
425 } else if (fExpandingStarted) {
426 BString string;
427 int32 i = 0;
428 while (message->FindString("output", i++, &string) == B_OK) {
429 if (strstr(string.String(), "Enter password") != NULL) {
430 fExpandingThread->SuspendExternalExpander();
431 BString password;
432 PasswordAlert* alert =
433 new PasswordAlert("passwordAlert", string);
434 alert->Go(password);
435 fExpandingThread->ResumeExternalExpander();
436 fExpandingThread->PushInput(password);
440 break;
442 case 'errp':
444 BString string;
445 if (message->FindString("error", &string) == B_OK
446 && fExpandingStarted) {
447 fExpandingThread->SuspendExternalExpander();
448 if (strstr(string.String(), "password") != NULL) {
449 BString password;
450 PasswordAlert* alert = new PasswordAlert("passwordAlert",
451 string);
452 alert->Go(password);
453 fExpandingThread->ResumeExternalExpander();
454 fExpandingThread->PushInput(password);
455 } else {
456 BAlert* alert = new BAlert("stopAlert", string,
457 B_TRANSLATE("Stop"), B_TRANSLATE("Continue"), NULL,
458 B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
459 alert->SetShortcut(0, B_ESCAPE);
460 if (alert->Go() == 0) {
461 fExpandingThread->ResumeExternalExpander();
462 StopExpanding();
463 } else
464 fExpandingThread->ResumeExternalExpander();
467 break;
470 case 'exit':
471 // thread has finished
472 // (finished, quit, killed, we don't know)
473 // reset window state
474 if (fExpandingStarted) {
475 fStatusView->SetStatus(B_TRANSLATE("File expanded"));
476 StopExpanding();
477 OpenDestFolder();
478 CloseWindowOrKeepOpen();
479 } else if (fListingStarted) {
480 fSourceChanged = false;
481 StopListing();
482 _ExpandListingText();
483 } else
484 fStatusView->SetStatus("");
485 break;
487 case 'exrr':
488 // thread has finished
489 // reset window state
491 fStatusView->SetStatus(B_TRANSLATE("Error when expanding archive"));
492 CloseWindowOrKeepOpen();
493 break;
495 default:
496 BWindow::MessageReceived(message);
501 bool
502 ExpanderWindow::CanQuit()
504 if ((fSourcePanel && fSourcePanel->IsShowing())
505 || (fDestPanel && fDestPanel->IsShowing())) {
506 return false;
509 if (fExpandingStarted) {
510 fExpandingThread->SuspendExternalExpander();
511 BAlert* alert = new BAlert("stopAlert",
512 B_TRANSLATE("Are you sure you want to stop expanding this\n"
513 "archive? The expanded items may not be complete."),
514 B_TRANSLATE("Stop"), B_TRANSLATE("Continue"), NULL,
515 B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
516 alert->SetShortcut(0, B_ESCAPE);
518 if (alert->Go() == 0) {
519 fExpandingThread->ResumeExternalExpander();
520 StopExpanding();
521 } else {
522 fExpandingThread->ResumeExternalExpander();
523 return false;
527 return true;
531 bool
532 ExpanderWindow::QuitRequested()
534 if (!CanQuit())
535 return false;
537 if (fListingStarted)
538 StopListing();
540 be_app->PostMessage(B_QUIT_REQUESTED);
541 fSettings.ReplacePoint("window_position", Frame().LeftTop());
542 ((ExpanderApp*)(be_app))->UpdateSettingsFrom(&fSettings);
544 return true;
548 void
549 ExpanderWindow::RefsReceived(BMessage* message)
551 entry_ref ref;
552 int32 i = 0;
553 int8 destinationFolder = 0x63;
554 fSettings.FindInt8("destination_folder", &destinationFolder);
556 while (message->FindRef("refs", i++, &ref) == B_OK) {
557 BEntry entry(&ref, true);
558 BPath path(&entry);
559 BNode node(&entry);
561 if (node.IsFile()) {
562 fSourceChanged = true;
563 fSourceRef = ref;
564 fSourceText->SetText(path.Path());
565 if (destinationFolder == 0x63) {
566 BPath parent;
567 path.GetParent(&parent);
568 fDestText->SetText(parent.Path());
569 get_ref_for_path(parent.Path(), &fDestRef);
570 } else if (destinationFolder == 0x65) {
571 fSettings.FindRef("destination_folder_use", &fDestRef);
572 BEntry dEntry(&fDestRef, true);
573 BPath dPath(&dEntry);
574 fDestText->SetText(dPath.Path());
577 BEntry dEntry(&fDestRef, true);
578 if (dEntry.Exists()) {
579 fExpandButton->SetEnabled(true);
580 fExpandItem->SetEnabled(true);
583 if (fShowContents->Value() == B_CONTROL_ON) {
584 StopListing();
585 StartListing();
586 } else {
587 fShowContents->SetEnabled(true);
588 fShowItem->SetEnabled(true);
591 bool fromApp;
592 if (message->FindBool("fromApp", &fromApp) == B_OK) {
593 AutoExpand();
594 } else
595 AutoListing();
596 } else if (node.IsDirectory()) {
597 fDestRef = ref;
598 fDestText->SetText(path.Path());
604 #undef B_TRANSLATION_CONTEXT
605 #define B_TRANSLATION_CONTEXT "ExpanderMenu"
607 void
608 ExpanderWindow::_CreateMenuBar()
610 fBar = new BMenuBar("menu_bar", B_ITEMS_IN_ROW, B_INVALIDATE_AFTER_LAYOUT);
611 BMenu* menu = new BMenu(B_TRANSLATE("File"));
612 menu->AddItem(fSourceItem
613 = new BMenuItem(B_TRANSLATE("Set source" B_UTF8_ELLIPSIS),
614 new BMessage(MSG_SOURCE), 'O'));
615 menu->AddItem(fDestItem
616 = new BMenuItem(B_TRANSLATE("Set destination" B_UTF8_ELLIPSIS),
617 new BMessage(MSG_DEST), 'D'));
618 menu->AddSeparatorItem();
619 menu->AddItem(fExpandItem = new BMenuItem(B_TRANSLATE("Expand"),
620 new BMessage(MSG_EXPAND), 'E'));
621 fExpandItem->SetEnabled(false);
622 menu->AddItem(fShowItem = new BMenuItem(B_TRANSLATE("Show contents"),
623 new BMessage(MSG_SHOW), 'L'));
624 fShowItem->SetEnabled(false);
625 menu->AddSeparatorItem();
626 menu->AddItem(fStopItem = new BMenuItem(B_TRANSLATE("Stop"),
627 new BMessage(MSG_STOP), 'K'));
628 fStopItem->SetEnabled(false);
629 menu->AddSeparatorItem();
630 menu->AddItem(new BMenuItem(B_TRANSLATE("Close"),
631 new BMessage(B_QUIT_REQUESTED), 'W'));
632 fBar->AddItem(menu);
634 menu = new BMenu(B_TRANSLATE("Settings"));
635 menu->AddItem(fPreferencesItem
636 = new BMenuItem(B_TRANSLATE("Settings" B_UTF8_ELLIPSIS),
637 new BMessage(MSG_PREFERENCES), 'S'));
638 fBar->AddItem(menu);
642 #undef B_TRANSLATION_CONTEXT
643 #define B_TRANSLATION_CONTEXT "ExpanderWindow"
645 void
646 ExpanderWindow::StartExpanding()
648 ExpanderRule* rule = fRules.MatchingRule(&fSourceRef);
649 if (!rule)
650 return;
652 BEntry destEntry(fDestText->Text(), true);
653 if (!destEntry.Exists()) {
654 BAlert* alert = new BAlert("destAlert",
655 B_TRANSLATE("The folder was either moved, renamed or not\nsupported."),
656 B_TRANSLATE("Cancel"), NULL, NULL,
657 B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
658 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
659 alert->Go();
660 return;
663 BMessage message;
664 message.AddString("cmd", rule->ExpandCmd());
665 message.AddRef("srcRef", &fSourceRef);
666 message.AddRef("destRef", &fDestRef);
668 fExpandButton->SetLabel(B_TRANSLATE("Stop"));
669 fSourceButton->SetEnabled(false);
670 fDestButton->SetEnabled(false);
671 fShowContents->SetEnabled(false);
672 fSourceItem->SetEnabled(false);
673 fDestItem->SetEnabled(false);
674 fExpandItem->SetEnabled(false);
675 fShowItem->SetEnabled(false);
676 fStopItem->SetEnabled(true);
677 fPreferencesItem->SetEnabled(false);
679 BEntry entry(&fSourceRef);
680 BPath path(&entry);
681 BString text(B_TRANSLATE("Expanding '%s'" B_UTF8_ELLIPSIS));
682 text.ReplaceFirst("%s", path.Leaf());
683 fStatusView->SetStatus(text.String());
685 fExpandingThread = new ExpanderThread(&message, new BMessenger(this));
686 fExpandingThread->Start();
688 fExpandingStarted = true;
692 void
693 ExpanderWindow::StopExpanding(void)
695 if (fExpandingThread) {
696 fExpandingThread->InterruptExternalExpander();
697 fExpandingThread = NULL;
700 fExpandingStarted = false;
702 fExpandButton->SetLabel(B_TRANSLATE("Expand"));
703 fSourceButton->SetEnabled(true);
704 fDestButton->SetEnabled(true);
705 fShowContents->SetEnabled(true);
706 fSourceItem->SetEnabled(true);
707 fDestItem->SetEnabled(true);
708 fExpandItem->SetEnabled(true);
709 fShowItem->SetEnabled(true);
710 fStopItem->SetEnabled(false);
711 fPreferencesItem->SetEnabled(true);
715 void
716 ExpanderWindow::_ExpandListingText()
718 float delta = fLongestLine - fListingText->Frame().Width();
720 if (delta > 0) {
721 BScreen screen;
722 BRect screenFrame = screen.Frame();
724 if (Frame().right + delta > screenFrame.right)
725 delta = screenFrame.right - Frame().right - 4.0f;
727 ResizeBy(delta, 0.0f);
730 float minWidth, maxWidth, minHeight, maxHeight;
731 GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
733 if (minWidth < Frame().Width() + delta) {
734 // set the Zoom limit as the minimal required size
735 SetZoomLimits(Frame().Width() + delta,
736 std::min(fSizeLimit + fListingText->TextRect().Height()
737 + fLineHeight + B_H_SCROLL_BAR_HEIGHT + 1.0f,
738 maxHeight));
739 } else {
740 // set the zoom limit based on minimal window size allowed
741 SetZoomLimits(minWidth,
742 std::min(fSizeLimit + fListingText->TextRect().Height()
743 + fLineHeight + B_H_SCROLL_BAR_HEIGHT + 1.0f,
744 maxHeight));
749 void
750 ExpanderWindow::_UpdateWindowSize(bool showContents)
752 float minWidth, maxWidth, minHeight, maxHeight;
753 GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight);
755 float bottom = fSizeLimit;
757 if (showContents) {
758 if (fPreviousHeight < 0.0) {
759 BFont font;
760 font_height fontHeight;
761 fListingText->GetFont(&font);
762 font.GetHeight(&fontHeight);
763 fLineHeight = ceilf(fontHeight.ascent + fontHeight.descent
764 + fontHeight.leading);
765 fPreviousHeight = bottom + 10.0 * fLineHeight;
767 minHeight = bottom + 5.0 * fLineHeight;
768 maxHeight = 32767.0;
770 bottom = std::max(fPreviousHeight, minHeight);
771 } else {
772 minHeight = fSizeLimit;
773 maxHeight = fSizeLimit;
774 fPreviousHeight = Frame().Height();
777 SetSizeLimits(minWidth, maxWidth, minHeight, maxHeight);
778 ResizeTo(Frame().Width(), bottom);
782 void
783 ExpanderWindow::StartListing()
785 _UpdateWindowSize(true);
787 if (!fSourceChanged)
788 return;
790 fPreviousHeight = -1.0;
792 fLongestLine = 0.0f;
794 ExpanderRule* rule = fRules.MatchingRule(&fSourceRef);
795 if (!rule)
796 return;
798 BMessage message;
799 message.AddString("cmd", rule->ListingCmd());
800 message.AddRef("srcRef", &fSourceRef);
802 fShowContents->SetEnabled(true);
803 fSourceItem->SetEnabled(false);
804 fDestItem->SetEnabled(false);
805 fExpandItem->SetEnabled(false);
806 fShowItem->SetEnabled(true);
807 fShowItem->SetLabel(B_TRANSLATE("Hide contents"));
808 fStopItem->SetEnabled(false);
809 fPreferencesItem->SetEnabled(false);
811 fSourceButton->SetEnabled(false);
812 fDestButton->SetEnabled(false);
813 fExpandButton->SetEnabled(false);
815 BEntry entry(&fSourceRef);
816 BPath path(&entry);
817 BString text(B_TRANSLATE("Creating listing for '%s'" B_UTF8_ELLIPSIS));
818 text.ReplaceFirst("%s", path.Leaf());
819 fStatusView->SetStatus(text.String());
820 fListingText->SetText("");
822 fListingThread = new ExpanderThread(&message, new BMessenger(this));
823 fListingThread->Start();
825 fListingStarted = true;
829 void
830 ExpanderWindow::StopListing(void)
832 if (fListingThread) {
833 fListingThread->InterruptExternalExpander();
834 fListingThread = NULL;
837 fListingStarted = false;
839 fShowContents->SetEnabled(true);
840 fSourceItem->SetEnabled(true);
841 fDestItem->SetEnabled(true);
842 fExpandItem->SetEnabled(true);
843 fShowItem->SetEnabled(true);
844 fStopItem->SetEnabled(false);
845 fPreferencesItem->SetEnabled(true);
847 fSourceButton->SetEnabled(true);
848 fDestButton->SetEnabled(true);
849 fExpandButton->SetEnabled(true);
850 fStatusView->SetStatus("");
854 void
855 ExpanderWindow::CloseWindowOrKeepOpen()
857 bool expandFiles = false;
858 fSettings.FindBool("automatically_expand_files", &expandFiles);
860 bool closeWhenDone = false;
861 fSettings.FindBool("close_when_done", &closeWhenDone);
863 if (expandFiles || closeWhenDone)
864 PostMessage(B_QUIT_REQUESTED);
868 void
869 ExpanderWindow::OpenDestFolder()
871 bool openFolder = true;
872 fSettings.FindBool("open_destination_folder", &openFolder);
874 if (!openFolder)
875 return;
877 BMessage* message = new BMessage(B_REFS_RECEIVED);
878 message->AddRef("refs", &fDestRef);
879 BPath path(&fDestRef);
880 BMessenger tracker("application/x-vnd.Be-TRAK");
881 tracker.SendMessage(message);
885 void
886 ExpanderWindow::AutoListing()
888 bool showContents = false;
889 fSettings.FindBool("show_contents_listing", &showContents);
891 if (!showContents)
892 return;
894 fShowContents->SetValue(B_CONTROL_ON);
895 fShowContents->Invoke();
899 void
900 ExpanderWindow::AutoExpand()
902 bool expandFiles = false;
903 fSettings.FindBool("automatically_expand_files", &expandFiles);
905 if (!expandFiles) {
906 AutoListing();
907 return;
910 fExpandButton->Invoke();