/* * Copyright 2007-2015 Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: * Ryan Leavengood * John Scipione * Joseph Groover */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static const float kStripeWidth = 30.0; using BPrivate::gSystemCatalog; #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "AboutWindow" namespace BPrivate { class StripeView : public BView { public: StripeView(BBitmap* icon); virtual ~StripeView(); virtual void Draw(BRect updateRect); BBitmap* Icon() const { return fIcon; }; void SetIcon(BBitmap* icon); private: BBitmap* fIcon; }; class AboutView : public BGroupView { public: AboutView(const char* name, const char* signature); virtual ~AboutView(); virtual void AllAttached(); BTextView* InfoView() const { return fInfoView; }; BBitmap* Icon(); status_t SetIcon(BBitmap* icon); const char* Name(); status_t SetName(const char* name); const char* Version(); status_t SetVersion(const char* version); private: BString _GetVersionFromSignature(const char* signature); BBitmap* _GetIconFromSignature(const char* signature); private: BStringView* fNameView; BStringView* fVersionView; BTextView* fInfoView; StripeView* fStripeView; }; // #pragma mark - StripeView StripeView::StripeView(BBitmap* icon) : BView("StripeView", B_WILL_DRAW), fIcon(icon) { SetViewUIColor(B_PANEL_BACKGROUND_COLOR); float width = 0.0f; if (icon != NULL) width += icon->Bounds().Width() + 24.0f; SetExplicitSize(BSize(width, B_SIZE_UNSET)); SetExplicitPreferredSize(BSize(width, B_SIZE_UNLIMITED)); } StripeView::~StripeView() { } void StripeView::Draw(BRect updateRect) { if (fIcon == NULL) return; SetHighColor(ViewColor()); FillRect(updateRect); BRect stripeRect = Bounds(); stripeRect.right = kStripeWidth; SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT)); FillRect(stripeRect); SetDrawingMode(B_OP_ALPHA); SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); DrawBitmapAsync(fIcon, BPoint(15.0f, 10.0f)); } void StripeView::SetIcon(BBitmap* icon) { if (fIcon != NULL) delete fIcon; fIcon = icon; float width = 0.0f; if (icon != NULL) width += icon->Bounds().Width() + 24.0f; SetExplicitSize(BSize(width, B_SIZE_UNSET)); SetExplicitPreferredSize(BSize(width, B_SIZE_UNLIMITED)); }; // #pragma mark - AboutView AboutView::AboutView(const char* appName, const char* signature) : BGroupView("AboutView", B_VERTICAL) { SetViewUIColor(B_PANEL_BACKGROUND_COLOR); fNameView = new BStringView("name", appName); BFont font; fNameView->GetFont(&font); font.SetFace(B_BOLD_FACE); font.SetSize(font.Size() * 2.0); fNameView->SetFont(&font, B_FONT_FAMILY_AND_STYLE | B_FONT_SIZE | B_FONT_FLAGS); fNameView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); fVersionView = new BStringView("version", _GetVersionFromSignature(signature).String()); fVersionView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); rgb_color documentColor = ui_color(B_DOCUMENT_TEXT_COLOR); fInfoView = new BTextView("info", NULL, &documentColor, B_WILL_DRAW); fInfoView->SetExplicitMinSize(BSize(210.0, 160.0)); fInfoView->MakeEditable(false); fInfoView->SetWordWrap(true); fInfoView->SetInsets(5.0, 5.0, 5.0, 5.0); fInfoView->SetStylable(true); BScrollView* infoViewScroller = new BScrollView( "infoViewScroller", fInfoView, B_WILL_DRAW | B_FRAME_EVENTS, false, true, B_PLAIN_BORDER); fStripeView = new StripeView(_GetIconFromSignature(signature)); const char* ok = B_TRANSLATE_MARK("OK"); BButton* closeButton = new BButton("ok", gSystemCatalog.GetString(ok, "AboutWindow"), new BMessage(B_QUIT_REQUESTED)); GroupLayout()->SetSpacing(0); BLayoutBuilder::Group<>(this, B_HORIZONTAL, 0) .Add(fStripeView) .AddGroup(B_VERTICAL) .SetInsets(0, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING) .AddGroup(B_VERTICAL, 0) .Add(fNameView) .Add(fVersionView) .AddStrut(B_USE_SMALL_SPACING) .Add(infoViewScroller) .End() .AddGroup(B_HORIZONTAL, 0) .AddGlue() .Add(closeButton) .End() .End() .View()->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); } AboutView::~AboutView() { } void AboutView::AllAttached() { fNameView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); fInfoView->SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR); fVersionView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR); } // #pragma mark - AboutView private methods BString AboutView::_GetVersionFromSignature(const char* signature) { if (signature == NULL) return NULL; entry_ref ref; if (be_roster->FindApp(signature, &ref) != B_OK) return NULL; BFile file(&ref, B_READ_ONLY); BAppFileInfo appMime(&file); if (appMime.InitCheck() != B_OK) return NULL; version_info versionInfo; if (appMime.GetVersionInfo(&versionInfo, B_APP_VERSION_KIND) == B_OK) { if (versionInfo.major == 0 && versionInfo.middle == 0 && versionInfo.minor == 0) { return NULL; } const char* version = B_TRANSLATE_MARK("Version"); version = gSystemCatalog.GetString(version, "AboutWindow"); BString appVersion(version); appVersion << " " << versionInfo.major << "." << versionInfo.middle; if (versionInfo.minor > 0) appVersion << "." << versionInfo.minor; // Add the version variety const char* variety = NULL; switch (versionInfo.variety) { case B_DEVELOPMENT_VERSION: variety = B_TRANSLATE_MARK("development"); break; case B_ALPHA_VERSION: variety = B_TRANSLATE_MARK("alpha"); break; case B_BETA_VERSION: variety = B_TRANSLATE_MARK("beta"); break; case B_GAMMA_VERSION: variety = B_TRANSLATE_MARK("gamma"); break; case B_GOLDEN_MASTER_VERSION: variety = B_TRANSLATE_MARK("gold master"); break; } if (variety != NULL) { variety = gSystemCatalog.GetString(variety, "AboutWindow"); appVersion << "-" << variety; } return appVersion; } return NULL; } BBitmap* AboutView::_GetIconFromSignature(const char* signature) { if (signature == NULL) return NULL; entry_ref ref; if (be_roster->FindApp(signature, &ref) != B_OK) return NULL; BFile file(&ref, B_READ_ONLY); BAppFileInfo appMime(&file); if (appMime.InitCheck() != B_OK) return NULL; BBitmap* icon = new BBitmap(BRect(0.0, 0.0, 63.0, 63.0), B_RGBA32); if (appMime.GetIcon(icon, (icon_size)64) == B_OK) return icon; delete icon; return NULL; } // #pragma mark - AboutView public methods BBitmap* AboutView::Icon() { if (fStripeView == NULL) return NULL; return fStripeView->Icon(); } status_t AboutView::SetIcon(BBitmap* icon) { if (fStripeView == NULL) return B_NO_INIT; fStripeView->SetIcon(icon); return B_OK; } const char* AboutView::Name() { return fNameView->Text(); } status_t AboutView::SetName(const char* name) { fNameView->SetText(name); return B_OK; } const char* AboutView::Version() { return fVersionView->Text(); } status_t AboutView::SetVersion(const char* version) { fVersionView->SetText(version); return B_OK; } } // namespace BPrivate // #pragma mark - BAboutWindow BAboutWindow::BAboutWindow(const char* appName, const char* signature) : BWindow(BRect(0.0, 0.0, 400.0, 200.0), appName, B_MODAL_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE) { SetLayout(new BGroupLayout(B_VERTICAL)); const char* about = B_TRANSLATE_MARK("About %app%"); about = gSystemCatalog.GetString(about, "AboutWindow"); BString title(about); title.ReplaceFirst("%app%", appName); SetTitle(title.String()); fAboutView = new BPrivate::AboutView(appName, signature); AddChild(fAboutView); MoveTo(AboutPosition(Frame().Width(), Frame().Height())); } BAboutWindow::~BAboutWindow() { fAboutView->RemoveSelf(); delete fAboutView; fAboutView = NULL; } // #pragma mark - BAboutWindow virtual methods void BAboutWindow::Show() { if (IsHidden()) { // move to current workspace SetWorkspaces(B_CURRENT_WORKSPACE); } BWindow::Show(); } // #pragma mark - BAboutWindow public methods BPoint BAboutWindow::AboutPosition(float width, float height) { BPoint result(100, 100); BWindow* window = dynamic_cast(BLooper::LooperForThread(find_thread(NULL))); BScreen screen(window); BRect screenFrame(0, 0, 640, 480); if (screen.IsValid()) screenFrame = screen.Frame(); // Horizontally, we're smack in the middle result.x = screenFrame.left + (screenFrame.Width() / 2.0) - (width / 2.0); // This is probably sooo wrong, but it looks right on 1024 x 768 result.y = screenFrame.top + (screenFrame.Height() / 4.0) - ceil(height / 3.0); return result; } void BAboutWindow::AddDescription(const char* description) { if (description == NULL) return; AddText(description); } void BAboutWindow::AddCopyright(int32 firstCopyrightYear, const char* copyrightHolder, const char** extraCopyrights) { BString copyright(B_UTF8_COPYRIGHT " %years% %holder%"); // Get current year time_t tp; time(&tp); char currentYear[5]; strftime(currentYear, 5, "%Y", localtime(&tp)); BString copyrightYears; copyrightYears << firstCopyrightYear; if (copyrightYears != currentYear) copyrightYears << "-" << currentYear; BString text(""); if (fAboutView->InfoView()->TextLength() > 0) text << "\n\n"; text << copyright; // Fill out the copyright year placeholder text.ReplaceAll("%years%", copyrightYears.String()); // Fill in the copyright holder placeholder text.ReplaceAll("%holder%", copyrightHolder); // Add extra copyright strings if (extraCopyrights != NULL) { // Add optional extra copyright information for (int32 i = 0; extraCopyrights[i]; i++) text << "\n" << B_UTF8_COPYRIGHT << " " << extraCopyrights[i]; } const char* allRightsReserved = B_TRANSLATE_MARK("All Rights Reserved."); allRightsReserved = gSystemCatalog.GetString(allRightsReserved, "AboutWindow"); text << "\n " << allRightsReserved; fAboutView->InfoView()->Insert(text.String()); } void BAboutWindow::AddAuthors(const char** authors) { if (authors == NULL) return; const char* writtenBy = B_TRANSLATE_MARK("Written by:"); writtenBy = gSystemCatalog.GetString(writtenBy, "AboutWindow"); AddText(writtenBy, authors); } void BAboutWindow::AddSpecialThanks(const char** thanks) { if (thanks == NULL) return; const char* specialThanks = B_TRANSLATE_MARK("Special Thanks:"); specialThanks = gSystemCatalog.GetString(specialThanks, "AboutWindow"); AddText(specialThanks, thanks); } void BAboutWindow::AddVersionHistory(const char** history) { if (history == NULL) return; const char* versionHistory = B_TRANSLATE_MARK("Version history:"); versionHistory = gSystemCatalog.GetString(versionHistory, "AboutWindow"); AddText(versionHistory, history); } void BAboutWindow::AddExtraInfo(const char* extraInfo) { if (extraInfo == NULL) return; const char* appExtraInfo = B_TRANSLATE_MARK(extraInfo); appExtraInfo = gSystemCatalog.GetString(extraInfo, "AboutWindow"); BString extra(""); if (fAboutView->InfoView()->TextLength() > 0) extra << "\n\n"; extra << appExtraInfo; fAboutView->InfoView()->Insert(extra.String()); } void BAboutWindow::AddText(const char* header, const char** contents) { BTextView* infoView = fAboutView->InfoView(); int32 textLength = infoView->TextLength(); BString text(""); if (textLength > 0) { text << "\n\n"; textLength += 2; } const char* indent = ""; if (header != NULL) { indent = " "; text << header; } if (contents != NULL) { text << "\n"; for (int32 i = 0; contents[i]; i++) text << indent << contents[i] << "\n"; } infoView->Insert(text.String()); if (contents != NULL && header != NULL) { infoView->SetFontAndColor(textLength, textLength + strlen(header), be_bold_font); } } BBitmap* BAboutWindow::Icon() { return fAboutView->Icon(); } void BAboutWindow::SetIcon(BBitmap* icon) { fAboutView->SetIcon(icon); } const char* BAboutWindow::Name() { return fAboutView->Name(); } void BAboutWindow::SetName(const char* name) { fAboutView->SetName(name); } const char* BAboutWindow::Version() { return fAboutView->Version(); } void BAboutWindow::SetVersion(const char* version) { fAboutView->SetVersion(version); } // FBC padding void BAboutWindow::_ReservedAboutWindow20() {} void BAboutWindow::_ReservedAboutWindow19() {} void BAboutWindow::_ReservedAboutWindow18() {} void BAboutWindow::_ReservedAboutWindow17() {} void BAboutWindow::_ReservedAboutWindow16() {} void BAboutWindow::_ReservedAboutWindow15() {} void BAboutWindow::_ReservedAboutWindow14() {} void BAboutWindow::_ReservedAboutWindow13() {} void BAboutWindow::_ReservedAboutWindow12() {} void BAboutWindow::_ReservedAboutWindow11() {} void BAboutWindow::_ReservedAboutWindow10() {} void BAboutWindow::_ReservedAboutWindow9() {} void BAboutWindow::_ReservedAboutWindow8() {} void BAboutWindow::_ReservedAboutWindow7() {} void BAboutWindow::_ReservedAboutWindow6() {} void BAboutWindow::_ReservedAboutWindow5() {} void BAboutWindow::_ReservedAboutWindow4() {} void BAboutWindow::_ReservedAboutWindow3() {} void BAboutWindow::_ReservedAboutWindow2() {} void BAboutWindow::_ReservedAboutWindow1() {}