TCP: Fixed RTO update and dup ACKs generation.
[haiku.git] / src / apps / screenshot / ScreenshotWindow.cpp
blobf12b80832908de33f363633e4c4d32e7db789d60
1 /*
2 * Copyright 2010-2014, Haiku Inc. All rights reserved.
3 * Copyright 2010 Wim van der Meer <WPJvanderMeer@gmail.com>
4 * Copyright Karsten Heimrich, host.haiku@gmx.de.
5 * All rights reserved. Distributed under the terms of the MIT License.
7 * Authors:
8 * Karsten Heimrich
9 * Fredrik Modéen
10 * Christophe Huriaux
11 * Wim van der Meer
15 #include "ScreenshotWindow.h"
17 #include <stdlib.h>
19 #include <Alert.h>
20 #include <Application.h>
21 #include <Bitmap.h>
22 #include <Box.h>
23 #include <Button.h>
24 #include <Catalog.h>
25 #include <CheckBox.h>
26 #include <ControlLook.h>
27 #include <File.h>
28 #include <FilePanel.h>
29 #include <FindDirectory.h>
30 #include <LayoutBuilder.h>
31 #include <Locale.h>
32 #include <Menu.h>
33 #include <MenuField.h>
34 #include <MenuItem.h>
35 #include <MessageFilter.h>
36 #include <Path.h>
37 #include <Roster.h>
38 #include <SeparatorView.h>
39 #include <SpaceLayoutItem.h>
40 #include <String.h>
41 #include <StringView.h>
42 #include <TextControl.h>
43 #include <TranslationUtils.h>
44 #include <TranslatorRoster.h>
46 #include "Utility.h"
49 #undef B_TRANSLATION_CONTEXT
50 #define B_TRANSLATION_CONTEXT "ScreenshotWindow"
53 enum {
54 kActiveWindow,
55 kIncludeBorder,
56 kIncludeCursor,
57 kNewScreenshot,
58 kImageFormat,
59 kLocationChanged,
60 kChooseLocation,
61 kSaveScreenshot,
62 kSettings,
63 kCloseTranslatorSettings
67 // #pragma mark - QuitMessageFilter
70 class QuitMessageFilter : public BMessageFilter {
71 public:
72 QuitMessageFilter(BWindow* window)
74 BMessageFilter((uint32)B_QUIT_REQUESTED),
75 fWindow(window)
79 virtual filter_result Filter(BMessage* message, BHandler** target)
81 BMessenger(fWindow).SendMessage(kCloseTranslatorSettings);
82 return B_SKIP_MESSAGE;
85 private:
86 BWindow* fWindow;
90 // #pragma mark - DirectoryRefFilter
93 class DirectoryRefFilter : public BRefFilter {
94 public:
95 virtual ~DirectoryRefFilter()
99 virtual bool Filter(const entry_ref* ref, BNode* node,
100 struct stat_beos* stat, const char* filetype)
102 // ToDo: Fix this properly in Tracker
103 // If you create a folder, then rename it, node is NULL.
104 // The BeBook says: "Note that the function is never sent an
105 // abstract entry, so the node, st, and filetype arguments will
106 // always be valid."
107 return node == NULL ? false : node->IsDirectory();
112 // #pragma mark - ScreenshotWindow
115 ScreenshotWindow::ScreenshotWindow(const Utility& utility, bool silent,
116 bool clipboard)
118 BWindow(BRect(0, 0, 200.0, 100.0), B_TRANSLATE_SYSTEM_NAME("Screenshot"),
119 B_TITLED_WINDOW, B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_AVOID_FRONT
120 | B_QUIT_ON_WINDOW_CLOSE | B_AUTO_UPDATE_SIZE_LIMITS
121 | B_CLOSE_ON_ESCAPE),
122 fUtility(utility),
123 fDelayControl(NULL),
124 fScreenshot(NULL),
125 fOutputPathPanel(NULL),
126 fLastSelectedPath(NULL),
127 fSettingsWindow(NULL),
128 fDelay(0),
129 fIncludeBorder(false),
130 fIncludeCursor(false),
131 fGrabActiveWindow(false),
132 fOutputFilename(NULL),
133 fExtension(""),
134 fImageFileType(B_PNG_FORMAT)
136 // _ReadSettings() needs a valid fOutputPathMenu
137 fOutputPathMenu = new BMenu(B_TRANSLATE("Please select"));
138 _ReadSettings();
140 // _NewScreenshot() needs a valid fNameControl
141 BString name(B_TRANSLATE_NOCOLLECT(fUtility.sDefaultFileNameBase));
142 name << 1;
143 name = _FindValidFileName(name.String());
144 fNameControl = new BTextControl("", B_TRANSLATE("Name:"), name, NULL);
146 // Check if fUtility contains valid data
147 if (fUtility.wholeScreen == NULL) {
148 _NewScreenshot(silent, clipboard, true);
149 return;
152 fScreenshot = fUtility.MakeScreenshot(fIncludeCursor, fGrabActiveWindow,
153 fIncludeBorder);
155 fActiveWindow = new BCheckBox(B_TRANSLATE("Capture active window"),
156 new BMessage(kActiveWindow));
157 if (fGrabActiveWindow)
158 fActiveWindow->SetValue(B_CONTROL_ON);
160 fWindowBorder = new BCheckBox(B_TRANSLATE("Include window border"),
161 new BMessage(kIncludeBorder));
162 if (fIncludeBorder)
163 fWindowBorder->SetValue(B_CONTROL_ON);
164 if (!fGrabActiveWindow)
165 fWindowBorder->SetEnabled(false);
167 fShowCursor = new BCheckBox(B_TRANSLATE("Include mouse pointer"),
168 new BMessage(kIncludeCursor));
169 if (fIncludeCursor)
170 fShowCursor->SetValue(B_CONTROL_ON);
172 BString delay;
173 delay << fDelay / 1000000;
174 fDelayControl = new BTextControl("", B_TRANSLATE("Delay:"), delay.String(),
175 NULL);
176 _DisallowChar(fDelayControl->TextView());
177 fDelayControl->TextView()->SetAlignment(B_ALIGN_RIGHT);
178 BStringView* seconds = new BStringView("", B_TRANSLATE("seconds"));
179 seconds->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
181 BMenuField* menuLocation = new BMenuField(B_TRANSLATE("Save in:"),
182 fOutputPathMenu);
183 menuLocation->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
185 fTranslatorMenu = new BMenu(B_TRANSLATE("Please select"));
186 _SetupTranslatorMenu();
187 BMenuField* menuFormat = new BMenuField(B_TRANSLATE("Save as:"),
188 fTranslatorMenu);
189 menuFormat->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
191 BButton* showSettings = new BButton("",
192 B_TRANSLATE("Settings" B_UTF8_ELLIPSIS), new BMessage(kSettings));
193 showSettings->SetExplicitAlignment(
194 BAlignment(B_ALIGN_RIGHT, B_ALIGN_BOTTOM));
196 BBox* divider = new BBox(B_FANCY_BORDER, NULL);
197 divider->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1));
199 BButton* saveScreenshot = new BButton("", B_TRANSLATE("Save"),
200 new BMessage(kSaveScreenshot));
202 const float kSpacing = be_control_look->DefaultItemSpacing();
203 const float kLabelSpacing = be_control_look->DefaultLabelSpacing();
205 fPreview = new BView("preview", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE);
206 BBox* previewBox = new BBox(B_FANCY_BORDER, fPreview);
208 BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
209 .AddGroup(B_HORIZONTAL)
210 .SetInsets(B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING,
211 B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING)
212 .Add(previewBox)
213 .AddGroup(B_VERTICAL, 0)
214 .Add(fActiveWindow)
215 .Add(fWindowBorder)
216 .Add(fShowCursor)
217 .AddStrut(kSpacing)
218 .AddGrid(0.0, kSpacing / 2)
219 .Add(fDelayControl->CreateLabelLayoutItem(), 0, 0)
220 .Add(fDelayControl->CreateTextViewLayoutItem(), 1, 0)
221 .Add(BSpaceLayoutItem::CreateHorizontalStrut(kLabelSpacing),
222 2, 0)
223 .Add(seconds, 3, 0)
224 .Add(fNameControl->CreateLabelLayoutItem(), 0, 1)
225 .Add(fNameControl->CreateTextViewLayoutItem(), 1, 1, 3, 1)
226 .Add(menuLocation->CreateLabelLayoutItem(), 0, 2)
227 .Add(menuLocation->CreateMenuBarLayoutItem(), 1, 2, 3, 1)
228 .Add(menuFormat->CreateLabelLayoutItem(), 0, 3)
229 .Add(menuFormat->CreateMenuBarLayoutItem(), 1, 3, 3, 1)
230 .End()
231 .AddStrut(kSpacing / 2)
232 .Add(showSettings)
233 .AddGlue()
234 .End()
235 .End()
236 .Add(new BSeparatorView(B_HORIZONTAL))
237 .AddGroup(B_HORIZONTAL)
238 .SetInsets(B_USE_WINDOW_SPACING, B_USE_DEFAULT_SPACING,
239 B_USE_WINDOW_SPACING, B_USE_WINDOW_SPACING)
240 .Add(new BButton("", B_TRANSLATE("Copy to clipboard"),
241 new BMessage(B_COPY)))
242 .Add(new BButton("", B_TRANSLATE("New screenshot"),
243 new BMessage(kNewScreenshot)))
244 .AddGlue()
245 .Add(saveScreenshot);
247 saveScreenshot->MakeDefault(true);
249 _UpdatePreviewPanel();
250 _UpdateFilenameSelection();
252 CenterOnScreen();
253 Show();
257 ScreenshotWindow::~ScreenshotWindow()
259 if (fOutputPathPanel)
260 delete fOutputPathPanel->RefFilter();
262 delete fOutputPathPanel;
263 delete fScreenshot;
267 void
268 ScreenshotWindow::MessageReceived(BMessage* message)
270 switch (message->what) {
271 case kActiveWindow:
272 fGrabActiveWindow = false;
273 if (fActiveWindow->Value() == B_CONTROL_ON)
274 fGrabActiveWindow = true;
276 fWindowBorder->SetEnabled(fGrabActiveWindow);
278 delete fScreenshot;
279 fScreenshot = fUtility.MakeScreenshot(fIncludeCursor,
280 fGrabActiveWindow, fIncludeBorder);
281 _UpdatePreviewPanel();
282 break;
284 case kIncludeBorder:
285 fIncludeBorder = (fWindowBorder->Value() == B_CONTROL_ON);
286 delete fScreenshot;
287 fScreenshot = fUtility.MakeScreenshot(fIncludeCursor,
288 fGrabActiveWindow, fIncludeBorder);
289 _UpdatePreviewPanel();
290 break;
292 case kIncludeCursor:
293 fIncludeCursor = (fShowCursor->Value() == B_CONTROL_ON);
294 delete fScreenshot;
295 fScreenshot = fUtility.MakeScreenshot(fIncludeCursor,
296 fGrabActiveWindow, fIncludeBorder);
297 _UpdatePreviewPanel();
298 break;
300 case kNewScreenshot:
301 fDelay = (atoi(fDelayControl->Text()) * 1000000) + 50000;
302 _NewScreenshot();
303 break;
305 case kImageFormat:
306 message->FindInt32("be:type", &fImageFileType);
307 fNameControl->SetText(_FindValidFileName(
308 fNameControl->Text()).String());
309 _UpdateFilenameSelection();
310 _ShowSettings(false);
311 break;
313 case kLocationChanged:
315 void* source = NULL;
316 if (message->FindPointer("source", &source) == B_OK)
317 fLastSelectedPath = static_cast<BMenuItem*> (source);
319 fNameControl->SetText(_FindValidFileName(
320 fNameControl->Text()).String());
322 _UpdateFilenameSelection();
323 break;
326 case kChooseLocation:
328 if (!fOutputPathPanel) {
329 BMessenger target(this);
330 fOutputPathPanel = new BFilePanel(B_OPEN_PANEL, &target, NULL,
331 B_DIRECTORY_NODE, false, NULL, new DirectoryRefFilter());
332 fOutputPathPanel->Window()->SetTitle(
333 B_TRANSLATE("Choose folder"));
334 fOutputPathPanel->SetButtonLabel(B_DEFAULT_BUTTON,
335 B_TRANSLATE("Select"));
336 fOutputPathPanel->SetButtonLabel(B_CANCEL_BUTTON,
337 B_TRANSLATE("Cancel"));
339 fOutputPathPanel->Show();
340 break;
343 case B_REFS_RECEIVED:
345 entry_ref ref;
346 if (message->FindRef("refs", &ref) == B_OK) {
347 BEntry entry(&ref, true);
348 if (entry.InitCheck() == B_OK) {
349 BPath path;
350 if (entry.GetPath(&path) == B_OK) {
351 BString label(path.Path());
352 _AddItemToPathMenu(path.Path(), label, 3, true);
356 break;
359 case B_CANCEL:
360 fLastSelectedPath->SetMarked(true);
361 break;
363 case kSaveScreenshot:
364 if (_SaveScreenshot() == B_OK)
365 be_app->PostMessage(B_QUIT_REQUESTED);
366 break;
368 case B_COPY:
369 fUtility.CopyToClipboard(fScreenshot);
370 break;
372 case kSettings:
373 _ShowSettings(true);
374 break;
376 case kCloseTranslatorSettings:
377 fSettingsWindow->Lock();
378 fSettingsWindow->Quit();
379 fSettingsWindow = NULL;
380 break;
382 default:
383 BWindow::MessageReceived(message);
384 break;
389 void
390 ScreenshotWindow::Quit()
392 if (fUtility.wholeScreen != NULL)
393 _WriteSettings();
394 BWindow::Quit();
398 void
399 ScreenshotWindow::_NewScreenshot(bool silent, bool clipboard, bool ignoreDelay)
401 BMessage message(B_ARGV_RECEIVED);
402 int32 argc = 1;
403 message.AddString("argv", "screenshot");
405 if (!ignoreDelay) {
406 argc += 2;
407 BString delay;
408 delay << fDelay / 1000000;
409 message.AddString("argv", "--delay");
410 message.AddString("argv", delay);
413 if (silent || clipboard) {
414 if (silent) {
415 argc++;
416 message.AddString("argv", "--silent");
418 if (clipboard) {
419 argc++;
420 message.AddString("argv", "--clipboard");
422 if (fIncludeBorder) {
423 argc++;
424 message.AddString("argv", "--border");
426 if (fIncludeCursor) {
427 argc++;
428 message.AddString("argv", "--mouse-pointer");
430 if (fGrabActiveWindow) {
431 argc++;
432 message.AddString("argv", "--window");
434 if (fLastSelectedPath) {
435 BPath path(_GetDirectory());
436 if (path != NULL) {
437 path.Append(fNameControl->Text());
438 argc++;
439 message.AddString("argv", path.Path());
443 message.AddInt32("argc", argc);
445 be_roster->Launch("application/x-vnd.haiku-screenshot-cli", &message);
446 be_app->PostMessage(B_QUIT_REQUESTED);
450 void
451 ScreenshotWindow::_UpdatePreviewPanel()
453 // Set the height of fPreview to what the layout suggests
454 fPreview->SetExplicitMinSize(BSize());
455 fPreview->SetExplicitMaxSize(BSize());
456 Layout(false);
458 float height = fPreview->Bounds().Height();
459 float width = (fScreenshot->Bounds().Width()
460 / fScreenshot->Bounds().Height()) * height;
462 // to prevent a preview way too wide
463 if (width > 400.0f) {
464 width = 400.0f;
465 height = (fScreenshot->Bounds().Height()
466 / fScreenshot->Bounds().Width()) * width;
469 fPreview->SetExplicitMinSize(BSize(width, height));
470 fPreview->SetExplicitMaxSize(BSize(width, height));
472 fPreview->ClearViewBitmap();
473 fPreview->SetViewBitmap(fScreenshot, fScreenshot->Bounds(),
474 fPreview->Bounds(), B_FOLLOW_ALL, B_FILTER_BITMAP_BILINEAR);
478 void
479 ScreenshotWindow::_DisallowChar(BTextView* textView)
481 for (uint32 i = 0; i < '0'; ++i)
482 textView->DisallowChar(i);
484 for (uint32 i = '9' + 1; i < 255; ++i)
485 textView->DisallowChar(i);
489 void
490 ScreenshotWindow::_SetupOutputPathMenu(const BMessage& settings)
492 fOutputPathMenu->SetLabelFromMarked(true);
494 BString lastSelectedPath;
495 settings.FindString("lastSelectedPath", &lastSelectedPath);
497 BPath path;
498 find_directory(B_USER_DIRECTORY, &path);
500 BString label(B_TRANSLATE("Home folder"));
501 _AddItemToPathMenu(path.Path(), label, 0,
502 path.Path() == lastSelectedPath, 'H');
504 path.Append("Desktop");
505 label.SetTo(B_TRANSLATE("Desktop"));
506 _AddItemToPathMenu(path.Path(), label, 0,
507 path.Path() == lastSelectedPath, 'D');
509 find_directory(B_USER_NONPACKAGED_DATA_DIRECTORY, &path);
510 path.Append("artwork");
512 label.SetTo(B_TRANSLATE("Artwork folder"));
513 _AddItemToPathMenu(path.Path(), label, 2,
514 path.Path() == lastSelectedPath, 'A');
516 int32 i = 0;
517 BString userPath;
518 while (settings.FindString("path", ++i, &userPath) == B_OK) {
519 _AddItemToPathMenu(userPath.String(), userPath, 3,
520 userPath == lastSelectedPath);
523 if (!fLastSelectedPath) {
524 if (settings.IsEmpty() || lastSelectedPath.Length() == 0) {
525 fOutputPathMenu->ItemAt(1)->SetMarked(true);
526 fLastSelectedPath = fOutputPathMenu->ItemAt(1);
527 } else {
528 _AddItemToPathMenu(lastSelectedPath.String(), lastSelectedPath, 3,
529 true);
533 fOutputPathMenu->AddItem(new BSeparatorItem());
534 fOutputPathMenu->AddItem(new BMenuItem(
535 B_TRANSLATE("Choose folder" B_UTF8_ELLIPSIS),
536 new BMessage(kChooseLocation), 'F'));
540 void
541 ScreenshotWindow::_AddItemToPathMenu(const char* path, BString& label,
542 int32 index, bool markItem, uint32 shortcutKey)
544 // Make sure that item won't be a duplicate of an existing one
545 for (int32 i = fOutputPathMenu->CountItems() - 1; i >= 0; --i) {
546 BMenuItem* menuItem = fOutputPathMenu->ItemAt(i);
547 BMessage* message = menuItem->Message();
548 const char* pathFromItem;
549 if (message != NULL && message->what == kLocationChanged
550 && message->FindString("path", &pathFromItem) == B_OK
551 && !strcmp(path, pathFromItem)) {
553 if (markItem) {
554 fOutputPathMenu->ItemAt(i)->SetMarked(true);
555 fLastSelectedPath = fOutputPathMenu->ItemAt(i);
557 return;
561 BMessage* message = new BMessage(kLocationChanged);
562 message->AddString("path", path);
564 fOutputPathMenu->TruncateString(&label, B_TRUNCATE_MIDDLE,
565 fOutputPathMenu->StringWidth("SomethingLongHere"));
567 fOutputPathMenu->AddItem(new BMenuItem(label.String(), message,
568 shortcutKey), index);
570 if (markItem) {
571 fOutputPathMenu->ItemAt(index)->SetMarked(true);
572 fLastSelectedPath = fOutputPathMenu->ItemAt(index);
577 void
578 ScreenshotWindow::_UpdateFilenameSelection()
580 fNameControl->MakeFocus(true);
581 fNameControl->TextView()->Select(0, fNameControl->TextView()->TextLength()
582 - fExtension.Length());
584 fNameControl->TextView()->ScrollToSelection();
588 void
589 ScreenshotWindow::_SetupTranslatorMenu()
591 BMessage message(kImageFormat);
592 fTranslatorMenu = new BMenu("Please select");
593 BTranslationUtils::AddTranslationItems(fTranslatorMenu, B_TRANSLATOR_BITMAP,
594 &message, NULL, NULL, NULL);
596 fTranslatorMenu->SetLabelFromMarked(true);
598 if (fTranslatorMenu->ItemAt(0))
599 fTranslatorMenu->ItemAt(0)->SetMarked(true);
601 int32 imageFileType;
602 for (int32 i = 0; i < fTranslatorMenu->CountItems(); ++i) {
603 BMenuItem* item = fTranslatorMenu->ItemAt(i);
604 if (item != NULL && item->Message()) {
605 item->Message()->FindInt32("be:type", &imageFileType);
606 if (fImageFileType == imageFileType) {
607 item->SetMarked(true);
608 MessageReceived(item->Message());
609 break;
616 void
617 ScreenshotWindow::_DisplaySaveError(BString _message) {
618 BString alertText;
619 alertText.SetToFormat(B_TRANSLATE("Error saving \"%s\":\n\t%s"),
620 fNameControl->Text(), _message.String());
622 BAlert* alert = new BAlert(B_TRANSLATE("Failed to save screenshot"),
623 alertText.String(), B_TRANSLATE("OK"),
624 NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
626 alert->SetShortcut(0, B_ESCAPE);
627 alert->Go();
631 status_t
632 ScreenshotWindow::_SaveScreenshot()
634 if (!fScreenshot || !fLastSelectedPath)
635 return B_ERROR;
637 BPath path(_GetDirectory());
639 if (path == NULL)
640 return B_ERROR;
642 BEntry directoryEntry;
643 directoryEntry.SetTo(path.Path());
645 // create folder if it doesn't exist
646 // necessary, for example, when the user selects the Artwork folder from
647 // the list of predefined folders.
648 if (!directoryEntry.Exists()) {
649 status_t directoryCreateStatus = create_directory(path.Path(), 0755);
650 if (directoryCreateStatus != B_OK) {
651 _DisplaySaveError(strerror(directoryCreateStatus));
653 return directoryCreateStatus;
655 } else if (!directoryEntry.IsDirectory()) {
656 // the entry exists but is not a directory.
657 // not much we can do
658 _DisplaySaveError(
659 B_TRANSLATE("The destination path exists but is not a folder."));
661 return B_NOT_A_DIRECTORY;
664 path.Append(fNameControl->Text());
666 BEntry entry;
667 entry.SetTo(path.Path());
669 if (entry.Exists()) {
670 BAlert* overwriteAlert = new BAlert(
671 B_TRANSLATE("overwrite"),
672 B_TRANSLATE("This file already exists.\n Are you sure you would "
673 "like to overwrite it?"),
674 B_TRANSLATE("Cancel"),
675 B_TRANSLATE("Overwrite"),
676 NULL, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
678 overwriteAlert->SetShortcut(0, B_ESCAPE);
680 if (overwriteAlert->Go() == 0)
681 return B_CANCELED;
684 status_t saveStatus = fUtility.Save(fScreenshot,
685 path.Path(), fImageFileType);
687 if (saveStatus != B_OK) {
688 _DisplaySaveError(strerror(saveStatus));
689 return saveStatus;
691 return B_OK;
695 void
696 ScreenshotWindow::_ShowSettings(bool activate)
698 if (!fSettingsWindow && !activate)
699 return;
701 // Find a translator
702 translator_id translator;
703 if (fUtility.FindTranslator(fImageFileType, translator) != B_OK)
704 return;
706 // Create a window with a configuration view
707 BView* view;
708 BRect rect(0, 0, 239, 239);
710 status_t status = BTranslatorRoster::Default()->MakeConfigurationView(
711 translator, NULL, &view, &rect);
712 if (status != B_OK || view == NULL) {
713 // TODO: proper translation, better error dialog
714 BAlert* alert = new BAlert(NULL, strerror(status), "OK");
715 alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
716 alert->Go();
717 } else if (fSettingsWindow != NULL) {
718 fSettingsWindow->RemoveChild(fSettingsWindow->ChildAt(0));
719 float width, height;
720 view->GetPreferredSize(&width, &height);
721 fSettingsWindow->ResizeTo(width, height);
722 fSettingsWindow->AddChild(view);
723 if (activate)
724 fSettingsWindow->Activate();
725 } else {
726 fSettingsWindow = new BWindow(rect,
727 B_TRANSLATE("Translator Settings"),
728 B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
729 B_NOT_ZOOMABLE | B_NOT_RESIZABLE);
730 fSettingsWindow->AddFilter(new QuitMessageFilter(this));
731 fSettingsWindow->AddChild(view);
732 fSettingsWindow->CenterOnScreen();
733 fSettingsWindow->Show();
738 BString
739 ScreenshotWindow::_FindValidFileName(const char* name)
741 BString baseName(name);
743 if (!fExtension.IsEmpty())
744 baseName.RemoveLast(fExtension);
746 if (!fLastSelectedPath)
747 return baseName;
749 BPath orgPath(_GetDirectory());
750 if (orgPath == NULL)
751 return baseName;
753 fExtension = fUtility.FileNameExtension(fImageFileType);
755 BPath outputPath = orgPath;
756 BString fileName;
757 fileName << baseName << fExtension;
758 outputPath.Append(fileName);
760 if (!BEntry(outputPath.Path()).Exists())
761 return fileName;
763 if (baseName.FindFirst(B_TRANSLATE_NOCOLLECT(
764 fUtility.sDefaultFileNameBase)) == 0)
765 baseName.SetTo(fUtility.sDefaultFileNameBase);
767 BEntry entry;
768 int32 index = 1;
770 do {
771 fileName = "";
772 fileName << baseName << index++ << fExtension;
773 outputPath.SetTo(orgPath.Path());
774 outputPath.Append(fileName);
775 entry.SetTo(outputPath.Path());
776 } while (entry.Exists());
778 return fileName;
782 BPath
783 ScreenshotWindow::_GetDirectory()
785 BPath path;
787 BMessage* message = fLastSelectedPath->Message();
788 const char* stringPath;
789 if (message && message->FindString("path", &stringPath) == B_OK)
790 path.SetTo(stringPath);
792 return path;
796 void
797 ScreenshotWindow::_ReadSettings()
799 BMessage settings;
801 BPath settingsPath;
802 if (find_directory(B_USER_SETTINGS_DIRECTORY, &settingsPath) != B_OK)
803 return;
805 settingsPath.Append("Screenshot_settings");
807 BFile file(settingsPath.Path(), B_READ_ONLY);
808 if (file.InitCheck() == B_OK)
809 settings.Unflatten(&file);
811 if (settings.FindInt32("type", &fImageFileType) != B_OK)
812 fImageFileType = B_PNG_FORMAT;
813 settings.FindBool("includeBorder", &fIncludeBorder);
814 settings.FindBool("includeCursor", &fIncludeCursor);
815 settings.FindBool("grabActiveWindow", &fGrabActiveWindow);
816 settings.FindInt64("delay", &fDelay);
817 settings.FindString("outputFilename", &fOutputFilename);
819 _SetupOutputPathMenu(settings);
823 void
824 ScreenshotWindow::_WriteSettings()
826 if (fDelayControl)
827 fDelay = (atoi(fDelayControl->Text()) * 1000000) + 50000;
829 BMessage settings;
831 settings.AddInt32("type", fImageFileType);
832 settings.AddBool("includeBorder", fIncludeBorder);
833 settings.AddBool("includeCursor", fIncludeCursor);
834 settings.AddBool("grabActiveWindow", fGrabActiveWindow);
835 settings.AddInt64("delay", fDelay);
836 settings.AddString("outputFilename", fOutputFilename);
838 BString path;
839 int32 count = fOutputPathMenu->CountItems();
840 if (count > 5) {
841 for (int32 i = count - 3; i > count - 8 && i > 2; --i) {
842 BMenuItem* item = fOutputPathMenu->ItemAt(i);
843 if (item) {
844 BMessage* msg = item->Message();
845 if (msg && msg->FindString("path", &path) == B_OK)
846 settings.AddString("path", path.String());
851 if (fLastSelectedPath) {
852 BMessage* msg = fLastSelectedPath->Message();
853 if (msg && msg->FindString("path", &path) == B_OK)
854 settings.AddString("lastSelectedPath", path.String());
857 BPath settingsPath;
858 if (find_directory(B_USER_SETTINGS_DIRECTORY, &settingsPath) != B_OK)
859 return;
860 settingsPath.Append("Screenshot_settings");
862 BFile file(settingsPath.Path(), B_CREATE_FILE | B_ERASE_FILE
863 | B_WRITE_ONLY);
864 if (file.InitCheck() == B_OK) {
865 ssize_t size;
866 settings.Flatten(&file, &size);