Modify about window to take an app signature.

* Grabs the app icon and version from the resource file.
* Allow you to specify the copyright holder instead of hardcoding
  "Haiku, Inc."
* Support multiple extra copyright fields.
* Modify BAlert to take a custom icon.
* Set the custom icon of the BAlert to the app icon.
* Also set the app version.

* Convert BAboutWindow to derive from BWindow
* Place a 128x128 icon and fill out a scrolling BTextView
  with options such as authors, version history, copyright,
  license, etc. Still needs some work but is coming along.

* Add the word Version to the version line, i8n'ed of course,
  and tweak the info box and default sizes.
This commit is contained in:
John Scipione 2012-08-01 07:25:56 -04:00
parent 1a5df674c1
commit 0046f44436
8 changed files with 439 additions and 72 deletions

View File

@ -1,28 +1,45 @@
/*
* Copyright 2007-2009 Haiku, Inc.
* Copyright 2007-2012 Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ryan Leavengood, leavengood@gmail.com
*/
#ifndef B_ABOUT_WINDOW_H
#define B_ABOUT_WINDOW_H
#include <String.h>
#include <GroupView.h>
#include <Window.h>
#include <View.h>
class BAboutWindow {
public:
BAboutWindow(const char *appName, int32 firstCopyrightYear,
const char **authors, const char *extraInfo = NULL);
virtual ~BAboutWindow();
class AboutView;
class BPoint;
void Show();
class BAboutWindow : public BWindow {
public:
BAboutWindow(const char* appName,
int32 firstCopyrightYear,
const char** authors = NULL,
const char* extraInfo = NULL);
BAboutWindow(const char* appName,
const char* signature);
virtual ~BAboutWindow();
private:
BString* fAppName;
BString* fText;
void AddDescription(const char* description);
void AddCopyright(int32 firstCopyrightYear,
const char* copyrightHolder,
const char** extraCopyrights = NULL);
void AddAuthors(const char** authors);
void AddSpecialThanks(const char** thanks);
void AddVersionHistory(const char** history);
void AddExtraInfo(const char* extraInfo);
BPoint AboutPosition(float width, float height);
protected:
void _Init(const char* appName, const char* signature);
private:
AboutView* fAboutView;
};
#endif // B_ABOUT_WINDOW_H

View File

@ -30,6 +30,7 @@
static const char* kSettingsFileName = "DeskCalc_settings";
const char* kAppName = B_TRANSLATE_SYSTEM_NAME("DeskCalc");
const char* kAppSig = "application/x-vnd.Haiku-DeskCalc";
static const float kDefaultWindowWidth = 220.0;

View File

@ -15,6 +15,7 @@
#include <Application.h>
extern const char* kAppName;
extern const char* kAppSig;
class BFile;

View File

@ -712,15 +712,14 @@ CalcView::FrameResized(float width, float height)
void
CalcView::AboutRequested()
{
const char* authors[] = {
"Timothy Wayper",
"Stephan Aßmus",
"Ingo Weinhold",
const char* extraCopyrights[] = {
"1997, 1998 R3 Software Ltd.",
NULL
};
BAboutWindow about(B_TRANSLATE_SYSTEM_NAME("DeskCalc"), 2006, authors,
B_UTF8_COPYRIGHT "1997, 1998 R3 Software Ltd.");
about.Show();
BAboutWindow* about = new BAboutWindow(kAppName, kAppSig);
about->AddCopyright(2006, "Haiku, Inc.", extraCopyrights);
about->Show();
}
@ -1289,6 +1288,9 @@ CalcView::_CreatePopUpMenu(bool addKeypadModeMenuItems)
fKeypadModeScientificItem = new BMenuItem(B_TRANSLATE("Scientific"),
new BMessage(MSG_OPTIONS_KEYPAD_MODE_SCIENTIFIC), '2');
}
BMenuItem* aboutItem
= new BMenuItem(B_TRANSLATE("About DeskCalc" B_UTF8_ELLIPSIS),
new BMessage(B_ABOUT_REQUESTED));
// apply current settings
fAutoNumlockItem->SetMarked(fOptions->auto_num_lock);
@ -1313,6 +1315,8 @@ CalcView::_CreatePopUpMenu(bool addKeypadModeMenuItems)
fPopUpMenu->AddItem(fKeypadModeScientificItem);
_MarkKeypadItems(fOptions->keypad_mode);
}
fPopUpMenu->AddSeparatorItem();
fPopUpMenu->AddItem(aboutItem);
}

View File

@ -31,6 +31,7 @@ static const float kMaximumWidthBasic = 400.0f;
static const float kMinimumHeightBasic = 130.0f;
static const float kMaximumHeightBasic = 400.0f;
class BAboutWindow;
class BString;
class BMenuItem;
class BPopUpMenu;

View File

@ -21,6 +21,7 @@
#include <Dragger.h>
#include <Screen.h>
#include "CalcApplication.h"
#include "CalcOptions.h"
#include "CalcView.h"
@ -31,8 +32,8 @@
CalcWindow::CalcWindow(BRect frame, BMessage* settings)
:
BWindow(frame, B_TRANSLATE_SYSTEM_NAME("DeskCalc"), B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_NOT_ANCHORED_ON_ACTIVATE)
BWindow(frame, kAppName, B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS
| B_NOT_ANCHORED_ON_ACTIVATE)
{
// create calculator view with calculator description and
// desktop background color

View File

@ -5,14 +5,14 @@ resource app_name_catalog_entry "x-vnd.Haiku-DeskCalc:System name:DeskCalc";
resource app_version {
major = 2,
middle = 2,
middle = 4,
minor = 0,
variety = B_APPV_ALPHA,
internal = 1,
short_info = "DeskCalc",
long_info = "DeskCalc ©2006-2012 Haiku, Inc."
long_info = "DeskCalc ©1997, 1998 R3 Software Ltd. ©2006-2012 Haiku, Inc."
};
resource app_flags B_SINGLE_LAUNCH;
@ -31,4 +31,3 @@ resource vector_icon {
$"011001178400040A010102000A050105000A06030806071001178122040A0201"
$"03000A030104000A0706090A0B0D0E0C100117810004"
};

View File

@ -1,39 +1,292 @@
/*
* Copyright 2007-2009 Haiku, Inc.
* Copyright 2007-2012 Haiku, Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ryan Leavengood, leavengood@gmail.com
* John Scipione, jscipione@gmail.com
*/
#include <AboutWindow.h>
#include <stdarg.h>
#include <time.h>
#include <Alert.h>
#include <AppFileInfo.h>
#include <Bitmap.h>
#include <File.h>
#include <Font.h>
#include <GroupLayoutBuilder.h>
#include <GroupView.h>
#include <LayoutBuilder.h>
#include <Point.h>
#include <Roster.h>
#include <Screen.h>
#include <ScrollView.h>
#include <Size.h>
#include <String.h>
#include <StringView.h>
#include <SystemCatalog.h>
#include <TextView.h>
#include <View.h>
static const float kStripeWidth = 30.0;
using BPrivate::gSystemCatalog;
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "AboutWindow"
BAboutWindow::BAboutWindow(const char *appName, int32 firstCopyrightYear,
const char **authors, const char *extraInfo)
{
fAppName = new BString(appName);
class StripeView : public BView {
public:
StripeView(BBitmap* icon);
virtual ~StripeView();
const char* copyright = gSystemCatalog.GetString(
B_TRANSLATE_MARK("Copyright " B_UTF8_COPYRIGHT " %years% Haiku, Inc."),
"AboutWindow");
const char* writtenBy = gSystemCatalog.GetString(
B_TRANSLATE_MARK("Written by:"), "AboutWindow");
virtual void Draw(BRect updateRect);
private:
BBitmap* fIcon;
};
class AboutView : public BGroupView {
public:
AboutView(const char* name,
const char* signature);
virtual ~AboutView();
BTextView* InfoView() const { return fInfoView; };
protected:
const char* AppVersion(const char* signature);
BBitmap* AppIcon(const char* signature);
private:
BStringView* fNameView;
BStringView* fVersionView;
BTextView* fInfoView;
};
// #pragma mark -
StripeView::StripeView(BBitmap* icon)
:
BView("StripeView", B_WILL_DRAW),
fIcon(icon)
{
SetExplicitMinSize(BSize(160.0, B_SIZE_UNSET));
SetExplicitPreferredSize(BSize(160.0, B_SIZE_UNLIMITED));
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
}
StripeView::~StripeView()
{
}
void
StripeView::Draw(BRect updateRect)
{
SetHighColor(ViewColor());
FillRect(updateRect);
BRect stripeRect = Bounds();
stripeRect.right = kStripeWidth;
SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
FillRect(stripeRect);
if (fIcon == NULL)
return;
SetDrawingMode(B_OP_ALPHA);
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
DrawBitmapAsync(fIcon, BPoint(15.0, 5.0));
}
// #pragma mark -
AboutView::AboutView(const char* appName, const char* signature)
:
BGroupView("AboutView", B_VERTICAL)
{
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);
fVersionView = new BStringView("version", AppVersion(signature));
fInfoView = new BTextView("info", B_WILL_DRAW);
fInfoView->SetExplicitMinSize(BSize(210.0, 100.0));
fInfoView->MakeEditable(false);
fInfoView->SetWordWrap(true);
fInfoView->SetInsets(5.0, 5.0, 5.0, 5.0);
fInfoView->SetViewColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
fInfoView->SetHighColor(ui_color(B_DOCUMENT_TEXT_COLOR));
BScrollView* infoViewScroller = new BScrollView(
"infoViewScroller", fInfoView, B_WILL_DRAW | B_FRAME_EVENTS,
false, true, B_PLAIN_BORDER);
GroupLayout()->SetSpacing(0);
BLayoutBuilder::Group<>(this)
.AddGroup(B_HORIZONTAL, 0)
.Add(new StripeView(AppIcon(signature)))
.AddGroup(B_VERTICAL, B_USE_SMALL_SPACING)
.SetInsets(0, B_USE_DEFAULT_SPACING,
B_USE_DEFAULT_SPACING, B_USE_DEFAULT_SPACING)
.Add(fNameView)
.Add(fVersionView)
.Add(infoViewScroller)
.End()
.AddGlue()
.End();
}
AboutView::~AboutView()
{
}
const char*
AboutView::AppVersion(const char* signature)
{
if (signature == NULL)
return NULL;
app_info appInfo;
if (be_roster->GetAppInfo(signature, &appInfo) != B_OK)
return NULL;
BFile file(&appInfo.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;
return appVersion.String();
}
return NULL;
}
BBitmap*
AboutView::AppIcon(const char* signature)
{
if (signature == NULL)
return NULL;
app_info appInfo;
if (be_roster->GetAppInfo(signature, &appInfo) != B_OK)
return NULL;
BFile file(&appInfo.ref, B_READ_ONLY);
BAppFileInfo appMime(&file);
if (appMime.InitCheck() != B_OK)
return NULL;
// fetch the app icon
BBitmap* icon = new BBitmap(BRect(0.0, 0.0, 127.0, 127.0), B_RGBA32);
if (appMime.GetIcon(icon, B_LARGE_ICON) == B_OK)
return icon;
// couldn't find the app icon
// fetch the generic 3 boxes icon
BMimeType defaultAppMime;
defaultAppMime.SetTo(B_APP_MIME_TYPE);
if (defaultAppMime.GetIcon(icon, B_LARGE_ICON) == B_OK)
return icon;
return NULL;
}
// #pragma mark -
BAboutWindow::BAboutWindow(const char* appName, int32 firstCopyrightYear,
const char** authors, const char* extraInfo)
: BWindow(BRect(0.0, 0.0, 300.0, 140.0), appName, B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_NOT_RESIZABLE
| B_AUTO_UPDATE_SIZE_LIMITS)
{
_Init(appName, NULL);
AddCopyright(firstCopyrightYear, "Haiku, Inc.", NULL);
AddAuthors(authors);
AddExtraInfo(extraInfo);
}
BAboutWindow::BAboutWindow(const char* appName, const char* signature)
: BWindow(BRect(0.0, 0.0, 310.0, 140.0), appName, B_TITLED_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE | B_NOT_RESIZABLE
| B_AUTO_UPDATE_SIZE_LIMITS)
{
_Init(appName, signature);
}
BAboutWindow::~BAboutWindow()
{
fAboutView->RemoveSelf();
delete fAboutView;
fAboutView = NULL;
}
void
BAboutWindow::AddDescription(const char* description)
{
if (description == NULL)
return;
const char* appDesc = B_TRANSLATE_MARK(description);
appDesc = gSystemCatalog.GetString(appDesc, "AboutWindow");
BString desc(appDesc);
desc << "\n\n";
fAboutView->InfoView()->Insert(desc.String());
}
void
BAboutWindow::AddCopyright(int32 firstCopyrightYear,
const char* copyrightHolder, const char** extraCopyrights)
{
BString copyright(B_UTF8_COPYRIGHT " %years%");
if (copyrightHolder != NULL)
copyright << " " << copyrightHolder;
const char* firstCopyright = B_TRANSLATE_MARK(copyright.String());
firstCopyright = gSystemCatalog.GetString(copyright, "AboutWindow");
// Get current year
time_t tp;
@ -45,50 +298,140 @@ BAboutWindow::BAboutWindow(const char *appName, int32 firstCopyrightYear,
if (copyrightYears != currentYear)
copyrightYears << "-" << currentYear;
// Build the text to display
BString text(appName);
text << "\n\n";
text << copyright;
text << "\n\n";
BString text(firstCopyright);
// Replace the copyright year with the current year
text.ReplaceAll("%years%", copyrightYears.String());
text << writtenBy << "\n";
for (int32 i = 0; authors[i]; i++) {
text << " " << authors[i] << "\n";
// 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];
}
text << "\n";
// The extra information is optional
if (extraInfo != NULL) {
text << "\n" << extraInfo << "\n";
}
const char* allRightsReserved = B_TRANSLATE_MARK("All Rights Reserved.");
allRightsReserved = gSystemCatalog.GetString(allRightsReserved,
"AboutWindow");
text << " " << allRightsReserved << "\n\n";
fText = new BString(text);
}
BAboutWindow::~BAboutWindow()
{
delete fText;
delete fAppName;
fAboutView->InfoView()->Insert(text.String());
}
void
BAboutWindow::Show()
BAboutWindow::AddAuthors(const char** authors)
{
const char* aboutTitle = gSystemCatalog.GetString(
B_TRANSLATE_MARK("About" B_UTF8_ELLIPSIS), "AboutWindow");
const char* closeLabel = gSystemCatalog.GetString(
B_TRANSLATE_MARK("Close"), "AboutWindow");
if (authors == NULL)
return;
BAlert *alert = new BAlert(aboutTitle, fText->String(), closeLabel);
BTextView *view = alert->TextView();
BFont font;
view->SetStylable(true);
view->GetFont(&font);
font.SetFace(B_BOLD_FACE);
font.SetSize(font.Size() * 1.7);
view->SetFontAndColor(0, fAppName->Length(), &font);
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
alert->Go();
const char* writtenBy = B_TRANSLATE_MARK("Written by:");
writtenBy = gSystemCatalog.GetString(writtenBy, "AboutWindow");
BString text(writtenBy);
text << "\n";
for (int32 i = 0; authors[i]; i++)
text << " " << authors[i] << "\n";
text << "\n";
fAboutView->InfoView()->Insert(text.String());
}
void
BAboutWindow::AddSpecialThanks(const char** thanks)
{
if (thanks == NULL)
return;
const char* specialThanks = B_TRANSLATE_MARK("Special Thanks:");
specialThanks = gSystemCatalog.GetString(specialThanks, "AboutWindow");
BString text(specialThanks);
text << "\n";
for (int32 i = 0; thanks[i]; i++)
text << " " << thanks[i] << "\n";
text << "\n";
fAboutView->InfoView()->Insert(text.String());
}
void
BAboutWindow::AddVersionHistory(const char** history)
{
if (history == NULL)
return;
const char* versionHistory = B_TRANSLATE_MARK("Version history:");
versionHistory = gSystemCatalog.GetString(versionHistory, "AboutWindow");
BString text(versionHistory);
text << "\n";
for (int32 i = 0; history[i]; i++)
text << " " << history[i] << "\n";
text << "\n";
fAboutView->InfoView()->Insert(text.String());
}
void
BAboutWindow::AddExtraInfo(const char* extraInfo)
{
if (extraInfo == NULL)
return;
const char* appExtraInfo = B_TRANSLATE_MARK(extraInfo);
appExtraInfo = gSystemCatalog.GetString(extraInfo, "AboutWindow");
BString extra(appExtraInfo);
extra << "\n";
fAboutView->InfoView()->Insert(extra.String());
}
BPoint
BAboutWindow::AboutPosition(float width, float height)
{
BPoint result(100, 100);
BWindow* window =
dynamic_cast<BWindow*>(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;
}
// #pragma mark -
void
BAboutWindow::_Init(const char* appName, const char* signature)
{
SetLayout(new BGroupLayout(B_VERTICAL));
const char* about = B_TRANSLATE_MARK("About");
about = gSystemCatalog.GetString(about, "AboutWindow");
BString title(about);
title << " " << appName;
SetTitle(title.String());
fAboutView = new AboutView(appName, signature);
AddChild(fAboutView);
MoveTo(AboutPosition(Frame().Width(), Frame().Height()));
}