Rewrote BAlert button layout routine. Made it much simpler, and it's now

also font sensitive (really, it wasn't before).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17861 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-06-16 16:22:53 +00:00
parent 60d1530802
commit 9a3c8b14fd
2 changed files with 214 additions and 306 deletions
+65 -113
View File
@@ -1,52 +1,24 @@
//------------------------------------------------------------------------------ /*
// Copyright (c) 2001-2002, OpenBeOS * Copyright 2001-2006, Haiku.
// * Distributed under the terms of the MIT License.
// Permission is hereby granted, free of charge, to any person obtaining a *
// copy of this software and associated documentation files (the "Software"), * Authors:
// to deal in the Software without restriction, including without limitation * Erik Jaesler ([email protected])
// the rights to use, copy, modify, merge, publish, distribute, sublicense, */
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: Alert.h
// Author: Erik Jaesler ([email protected])
// Description: BAlert displays a modal alert window.
//------------------------------------------------------------------------------
#ifndef _ALERT_H #ifndef _ALERT_H
#define _ALERT_H #define _ALERT_H
// Standard Includes -----------------------------------------------------------
// System Includes -------------------------------------------------------------
#include <BeBuild.h> #include <BeBuild.h>
#include <Window.h> #include <Window.h>
// Project Includes ------------------------------------------------------------
// Local Includes --------------------------------------------------------------
// Local Defines ---------------------------------------------------------------
// Globals ---------------------------------------------------------------------
class BBitmap; class BBitmap;
class BButton; class BButton;
class BInvoker; class BInvoker;
class BTextView; class BTextView;
// enum for flavors of alert --------------------------------------------------- // enum for flavors of alert
enum alert_type { enum alert_type {
B_EMPTY_ALERT = 0, B_EMPTY_ALERT = 0,
B_INFO_ALERT, B_INFO_ALERT,
@@ -55,101 +27,81 @@ enum alert_type {
B_STOP_ALERT B_STOP_ALERT
}; };
enum button_spacing { enum button_spacing {
B_EVEN_SPACING = 0, B_EVEN_SPACING = 0,
B_OFFSET_SPACING B_OFFSET_SPACING
}; };
// BAlert class ----------------------------------------------------------------
class BAlert : public BWindow
{
public:
BAlert( const char *title, class BAlert : public BWindow {
const char *text, public:
const char *button1, BAlert(const char* title, const char* text,
const char *button2 = NULL, const char* button1, const char* button2 = NULL,
const char *button3 = NULL, const char* button3 = NULL,
button_width width = B_WIDTH_AS_USUAL, button_width width = B_WIDTH_AS_USUAL,
alert_type type = B_INFO_ALERT); alert_type type = B_INFO_ALERT);
BAlert( const char *title, BAlert(const char *title, const char *text,
const char *text, const char *button1, const char *button2,
const char *button1, const char *button3, button_width width,
const char *button2, button_spacing spacing,
const char *button3, alert_type type = B_INFO_ALERT);
button_width width, virtual ~BAlert();
button_spacing spacing,
alert_type type = B_INFO_ALERT);
virtual ~BAlert();
// Archiving // Archiving
BAlert(BMessage *data); BAlert(BMessage *data);
static BArchivable *Instantiate(BMessage *data); static BArchivable *Instantiate(BMessage *data);
virtual status_t Archive(BMessage *data, bool deep = true) const; virtual status_t Archive(BMessage *data, bool deep = true) const;
// BAlert guts // BAlert guts
void SetShortcut(int32 button_index, char key); void SetShortcut(int32 button_index, char key);
char Shortcut(int32 button_index) const; char Shortcut(int32 button_index) const;
int32 Go(); int32 Go();
status_t Go(BInvoker *invoker); status_t Go(BInvoker *invoker);
virtual void MessageReceived(BMessage *an_event); virtual void MessageReceived(BMessage *an_event);
virtual void FrameResized(float new_width, float new_height); virtual void FrameResized(float new_width, float new_height);
BButton *ButtonAt(int32 index) const; BButton* ButtonAt(int32 index) const;
BTextView *TextView() const; BTextView* TextView() const;
virtual BHandler *ResolveSpecifier(BMessage *msg, virtual BHandler* ResolveSpecifier(BMessage* message, int32 index,
int32 index, BMessage* specifier, int32 form,
BMessage *specifier, const char* property);
int32 form, virtual status_t GetSupportedSuites(BMessage *data);
const char *property);
virtual status_t GetSupportedSuites(BMessage *data);
virtual void DispatchMessage(BMessage *msg, BHandler *handler); virtual void DispatchMessage(BMessage* message, BHandler* handler);
virtual void Quit(); virtual void Quit();
virtual bool QuitRequested(); virtual bool QuitRequested();
static BPoint AlertPosition(float width, float height); static BPoint AlertPosition(float width, float height);
// Private or reserved --------------------------------------------------------- virtual status_t Perform(perform_code d, void *arg);
virtual status_t Perform(perform_code d, void *arg);
private: private:
friend class _BAlertFilter_; friend class _BAlertFilter_;
virtual void _ReservedAlert1(); virtual void _ReservedAlert1();
virtual void _ReservedAlert2(); virtual void _ReservedAlert2();
virtual void _ReservedAlert3(); virtual void _ReservedAlert3();
void InitObject(const char *text, void _InitObject(const char* text, const char* button1,
const char *button1, const char* button2 = NULL,
const char *button2 = NULL, const char* button3 = NULL,
const char *button3 = NULL, button_width width = B_WIDTH_AS_USUAL,
button_width width = B_WIDTH_AS_USUAL, button_spacing spacing = B_EVEN_SPACING,
button_spacing spacing = B_EVEN_SPACING, alert_type type = B_INFO_ALERT);
alert_type type = B_INFO_ALERT); BBitmap* _InitIcon();
BBitmap *InitIcon(); BButton* _CreateButton(int32 which, const char* label);
sem_id fAlertSem; sem_id fAlertSem;
int32 fAlertVal; int32 fAlertValue;
BButton *fButtons[3]; BButton* fButtons[3];
BTextView *fTextView; BTextView* fTextView;
char fKeys[3]; char fKeys[3];
alert_type fMsgType; alert_type fMsgType;
button_width fButtonWidth; button_width fButtonWidth;
BInvoker *fInvoker; BInvoker* fInvoker;
uint32 _reserved[4]; uint32 _reserved[4];
}; };
//------------------------------------------------------------------------------
#endif // _ALERT_H #endif // _ALERT_H
/*
* $Log $
*
* $Id $
*
*/
+147 -191
View File
@@ -1,91 +1,69 @@
//------------------------------------------------------------------------------ /*
// Copyright (c) 2001-2002, OpenBeOS * Copyright 2001-2006, Haiku.
// * Distributed under the terms of the MIT License.
// Permission is hereby granted, free of charge, to any person obtaining a *
// copy of this software and associated documentation files (the "Software"), * Authors:
// to deal in the Software without restriction, including without limitation * Erik Jaesler ([email protected])
// the rights to use, copy, modify, merge, publish, distribute, sublicense, * Axel Dörfler, [email protected]
// and/or sell copies of the Software, and to permit persons to whom the */
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// File Name: Alert.cpp
// Author: Erik Jaesler ([email protected])
// Description: BAlert displays a modal alert window.
//------------------------------------------------------------------------------
// Standard Includes ----------------------------------------------------------- //! BAlert displays a modal alert window.
#include <string.h>
// System Includes ------------------------------------------------------------- #include <Alert.h>
#include <Autolock.h>
#include <Beep.h>
#include <Bitmap.h>
#include <Button.h>
#include <File.h>
#include <FindDirectory.h>
#include <Invoker.h> #include <Invoker.h>
#include <Looper.h> #include <Looper.h>
#include <Message.h> #include <Message.h>
#include <MessageFilter.h> #include <MessageFilter.h>
#include <Path.h>
#include <Alert.h> #include <Resources.h>
#include <Bitmap.h>
#include <Button.h>
#include <Screen.h> #include <Screen.h>
#include <TextView.h> #include <TextView.h>
#include <View.h> #include <View.h>
#include <File.h> #include <new>
#include <FindDirectory.h> #include <stdio.h>
#include <Path.h> #include <string.h>
#include <Resources.h>
#include <Beep.h>
#include <Autolock.h>
//#define DEBUG_ALERT //#define DEBUG_ALERT
#ifdef DEBUG_ALERT #ifdef DEBUG_ALERT
#define FTRACE(x) fprintf(x) # define FTRACE(x) fprintf(x)
#else #else
#define FTRACE(x) /* nothing */ # define FTRACE(x) /* nothing */
#endif #endif
// Default size of the Alert window. // Default size of the Alert window.
#define DEFAULT_RECT BRect(0, 0, 310, 75) #define DEFAULT_RECT BRect(0, 0, 310, 75)
#define max(LHS, RHS) ((LHS) > (RHS) ? (LHS) : (RHS)) #define max(LHS, RHS) ((LHS) > (RHS) ? (LHS) : (RHS))
// Globals ---------------------------------------------------------------------
static const unsigned int kAlertButtonMsg = 'ALTB'; static const unsigned int kAlertButtonMsg = 'ALTB';
static const int kSemTimeOut = 50000; static const int kSemTimeOut = 50000;
static const int kButtonBottomOffset = 9; static const int kLeftOffset = 10;
static const int kDefButtonBottomOffset = 6; static const int kTopOffset = 6;
static const int kButtonRightOffset = 6; static const int kBottomOffset = 8;
static const int kButtonSpaceOffset = 6; static const int kRightOffset = 8;
static const int kButtonOffsetSpaceOffset = 26;
static const int kButtonMinOffsetSpaceOffset = kButtonOffsetSpaceOffset / 2; static const int kButtonSpacing = 6;
static const int kButtonLeftOffset = 62; static const int kButtonOffsetSpacing = 62;
static const int kButtonUsualWidth = 75; static const int kButtonUsualWidth = 75;
static const int kWindowIconOffset = 27; static const int kWindowIconOffset = 27;
static const int kWindowMinWidth = 310;
static const int kWindowMinOffset = 12; static const int kWindowMinOffset = 12;
static const int kWindowMinWidth = 310;
static const int kWindowOffsetMinWidth = 335; static const int kWindowOffsetMinWidth = 335;
static const int kIconStripeWidth = 30; static const int kIconStripeWidth = 30;
static const int kTextLeftOffset = 10;
static const int kTextIconOffset = kWindowIconOffset + kIconStripeWidth - 2; static const int kTextIconOffset = kWindowIconOffset + kIconStripeWidth - 2;
static const int kTextTopOffset = 6; static const int kTextButtonOffset = 10;
static const int kTextRightOffset = 10;
static const int kTextBottomOffset = 45;
//------------------------------------------------------------------------------
class TAlertView : public BView { class TAlertView : public BView {
public: public:
TAlertView(BRect frame); TAlertView(BRect frame);
@@ -108,11 +86,6 @@ class TAlertView : public BView {
BBitmap* fIconBitmap; BBitmap* fIconBitmap;
}; };
//------------------------------------------------------------------------------
// I'm making a guess based on the name and TextEntryAlert's implementation that
// this is a BMessageFilter. I'm not sure, but I think I actually prefer how
// TextEntryAlert does it, but there are clearly no message filtering functions
// on BAlert so here we go.
class _BAlertFilter_ : public BMessageFilter { class _BAlertFilter_ : public BMessageFilter {
public: public:
_BAlertFilter_(BAlert* Alert); _BAlertFilter_(BAlert* Alert);
@@ -125,35 +98,26 @@ class _BAlertFilter_ : public BMessageFilter {
}; };
static float
width_from_label(BButton *button)
{
// BButton::GetPreferredSize() does not return the minimum width
// required to fit the label. Thus, the width is computed here.
return button->StringWidth(button->Label()) + 20.0f;
}
// #pragma mark - BAlert // #pragma mark - BAlert
BAlert::BAlert(const char *title, const char *text, const char *button1, BAlert::BAlert(const char *title, const char *text, const char *button1,
const char *button2, const char *button3, button_width width, const char *button2, const char *button3, button_width width,
alert_type type) alert_type type)
: BWindow(DEFAULT_RECT, title, B_MODAL_WINDOW, : BWindow(DEFAULT_RECT, title, B_MODAL_WINDOW,
B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS) B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS)
{ {
InitObject(text, button1, button2, button3, width, B_EVEN_SPACING, type); _InitObject(text, button1, button2, button3, width, B_EVEN_SPACING, type);
} }
BAlert::BAlert(const char *title, const char *text, const char *button1, BAlert::BAlert(const char *title, const char *text, const char *button1,
const char *button2, const char *button3, button_width width, const char *button2, const char *button3, button_width width,
button_spacing spacing, alert_type type) button_spacing spacing, alert_type type)
: BWindow(DEFAULT_RECT, title, B_MODAL_WINDOW, : BWindow(DEFAULT_RECT, title, B_MODAL_WINDOW,
B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS) B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS)
{ {
InitObject(text, button1, button2, button3, width, spacing, type); _InitObject(text, button1, button2, button3, width, spacing, type);
} }
@@ -170,7 +134,7 @@ BAlert::BAlert(BMessage* data)
{ {
fInvoker = NULL; fInvoker = NULL;
fAlertSem = -1; fAlertSem = -1;
fAlertVal = -1; fAlertValue = -1;
fTextView = (BTextView*)FindView("_tv_"); fTextView = (BTextView*)FindView("_tv_");
@@ -185,9 +149,9 @@ BAlert::BAlert(BMessage* data)
else if (fButtons[0]) else if (fButtons[0])
SetDefaultButton(fButtons[0]); SetDefaultButton(fButtons[0]);
TAlertView* master = (TAlertView*)FindView("_master_"); TAlertView* view = (TAlertView*)FindView("_master_");
if (master) if (view)
master->SetBitmap(InitIcon()); view->SetBitmap(_InitIcon());
// Get keys // Get keys
char key; char key;
@@ -309,7 +273,7 @@ BAlert::Go()
} }
// Have to cache the value since we delete on Quit() // Have to cache the value since we delete on Quit()
int32 value = fAlertVal; int32 value = fAlertValue;
if (Lock()) if (Lock())
Quit(); Quit();
@@ -345,7 +309,7 @@ BAlert::MessageReceived(BMessage* msg)
PostMessage(B_QUIT_REQUESTED); PostMessage(B_QUIT_REQUESTED);
} else { } else {
// Created semaphore means were running synchronously // Created semaphore means were running synchronously
fAlertVal = which; fAlertValue = which;
// TextAlertVar does release_sem() below, and then sets the // TextAlertVar does release_sem() below, and then sets the
// member var. That doesn't make much sense to me, since we // member var. That doesn't make much sense to me, since we
@@ -455,23 +419,23 @@ void BAlert::_ReservedAlert3() {}
void void
BAlert::InitObject(const char* text, const char* button0, const char* button1, BAlert::_InitObject(const char* text, const char* button0, const char* button1,
const char* button2, button_width width, button_spacing spacing, const char* button2, button_width buttonWidth, button_spacing spacing,
alert_type type) alert_type type)
{ {
fInvoker = NULL; fInvoker = NULL;
fAlertSem = -1; fAlertSem = -1;
fAlertVal = -1; fAlertValue = -1;
fButtons[0] = fButtons[1] = fButtons[2] = NULL; fButtons[0] = fButtons[1] = fButtons[2] = NULL;
fTextView = NULL; fTextView = NULL;
fKeys[0] = fKeys[1] = fKeys[2] = 0; fKeys[0] = fKeys[1] = fKeys[2] = 0;
fMsgType = type; fMsgType = type;
fButtonWidth = width; fButtonWidth = buttonWidth;
// Set up the "_master_" view // Set up the "_master_" view
TAlertView* masterView = new TAlertView(Bounds()); TAlertView* view = new TAlertView(Bounds());
AddChild(masterView); AddChild(view);
masterView->SetBitmap(InitIcon()); view->SetBitmap(_InitIcon());
// Must have at least one button // Must have at least one button
if (button0 == NULL) { if (button0 == NULL) {
@@ -479,132 +443,89 @@ BAlert::InitObject(const char* text, const char* button0, const char* button1,
button0 = ""; button0 = "";
} }
BMessage protoMsg(kAlertButtonMsg);
protoMsg.AddInt32("which", 0);
// Set up the buttons // Set up the buttons
int buttonCount = 0;
fButtons[buttonCount] = new BButton(BRect(0, 0, 0, 0), "_b0_", button0,
new BMessage(protoMsg), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
masterView->AddChild(fButtons[buttonCount]);
++buttonCount;
if (button1) { int32 buttonCount = 1;
protoMsg.ReplaceInt32("which", 1); view->AddChild(fButtons[0] = _CreateButton(0, button0));
fButtons[buttonCount] = new BButton(BRect(0, 0, 0, 0), "_b1_", button1,
new BMessage(protoMsg), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
masterView->AddChild(fButtons[buttonCount]); if (button1 != NULL) {
++buttonCount; view->AddChild(fButtons[1] = _CreateButton(1, button1));
} buttonCount++;
if (button2) {
protoMsg.ReplaceInt32("which", 2);
fButtons[buttonCount] = new BButton(BRect(0, 0, 0, 0), "_b2_", button2,
new BMessage(protoMsg), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
masterView->AddChild(fButtons[buttonCount]);
++buttonCount;
} }
SetDefaultButton(fButtons[buttonCount - 1]); if (button2 != NULL) {
view->AddChild(fButtons[2] = _CreateButton(2, button2));
buttonCount++;
}
// Find the widest button only if the widest value needs to be known. // Find the widest button only if the widest value needs to be known.
float maxWidth = 0;
if (fButtonWidth == B_WIDTH_FROM_WIDEST) { if (fButtonWidth == B_WIDTH_FROM_WIDEST) {
for (int i = 0; i < buttonCount; ++i) { float maxWidth = 0;
float temp = width_from_label(fButtons[i]); for (int i = 0; i < buttonCount; i++) {
maxWidth = max(maxWidth, temp); float width = fButtons[i]->Bounds().Width();
if (width > maxWidth)
maxWidth = width;
}
// resize buttons
for (int i = 0; i < buttonCount; i++) {
fButtons[i]->ResizeTo(maxWidth, fButtons[i]->Bounds().Height());
} }
} }
for (int i = buttonCount - 1; i >= 0; --i) { float defaultButtonFrameWidth = -fButtons[buttonCount - 1]->Bounds().Width() / 2.0f;
// Determine the button's size SetDefaultButton(fButtons[buttonCount - 1]);
float buttonWidth = 0, buttonHeight = 0; defaultButtonFrameWidth += fButtons[buttonCount - 1]->Bounds().Width() / 2.0f;
fButtons[i]->GetPreferredSize(&buttonWidth, &buttonHeight);
if (fButtonWidth == B_WIDTH_FROM_WIDEST)
buttonWidth = maxWidth;
else if (fButtonWidth == B_WIDTH_FROM_LABEL)
buttonWidth = width_from_label(fButtons[i]);
else // B_WIDTH_AS_USUAL
buttonWidth = max(buttonWidth, kButtonUsualWidth);
fButtons[i]->ResizeTo(buttonWidth, buttonHeight);
// Determine the button's placement // Layout buttons
float buttonX, buttonY;
buttonY = Bounds().bottom - buttonHeight; float fontFactor = be_plain_font->Size() / 11.0f;
if (i == buttonCount - 1) {
// The right-most button for (int i = buttonCount - 1; i >= 0; --i) {
buttonX = Bounds().right - fButtons[i]->Frame().Width() - float x = -fButtons[i]->Bounds().Width();
kButtonRightOffset; if (i + 1 == buttonCount)
buttonY -= kDefButtonBottomOffset; x += Bounds().right - kRightOffset + defaultButtonFrameWidth;
} else { else
buttonX = fButtons[i + 1]->Frame().left - x += fButtons[i + 1]->Frame().left - kButtonSpacing;
fButtons[i]->Frame().Width() - kButtonSpaceOffset;
buttonY -= kButtonBottomOffset; if (buttonCount > 1 && i == 0 && spacing == B_OFFSET_SPACING)
if (i == 0) { x -= kButtonOffsetSpacing * fontFactor;
if (spacing == B_OFFSET_SPACING) {
if (buttonCount == 3) fButtons[i]->MoveTo(x, fButtons[i]->Frame().top);
buttonX -= kButtonOffsetSpaceOffset; }
else {
// If there are two buttons, the left wall of
// button0 needs to line up with the left wall
// of the TextView.
buttonX = (masterView->Bitmap()) ?
kTextIconOffset : kTextLeftOffset;
if (fButtons[i + 1]->Frame().left -
(buttonX + fButtons[i]->Frame().Width()) <
kButtonMinOffsetSpaceOffset) {
// Recompute buttonX using min offset space
// if using the current buttonX would not
// provide enough space or cause an overlap.
buttonX = fButtons[i + 1]->Frame().left -
fButtons[i]->Frame().Width() -
kButtonMinOffsetSpaceOffset;
}
}
} else if (buttonCount == 3)
buttonX -= 3;
}
}
fButtons[i]->MoveTo(buttonX, buttonY);
} // for (int i = buttonCount - 1; i >= 0; --i)
// Adjust the window's width, if necessary // Adjust the window's width, if necessary
float totalWidth = kButtonRightOffset;
totalWidth += fButtons[buttonCount - 1]->Frame().right - float totalWidth = kRightOffset + fButtons[buttonCount - 1]->Frame().right
fButtons[0]->Frame().left; - defaultButtonFrameWidth - fButtons[0]->Frame().left;
if (masterView->Bitmap()) if (view->Bitmap())
totalWidth += kIconStripeWidth + kWindowIconOffset; totalWidth += kIconStripeWidth + kWindowIconOffset;
else else
totalWidth += kWindowMinOffset; totalWidth += kWindowMinOffset;
if (spacing == B_OFFSET_SPACING) { float width = (spacing == B_OFFSET_SPACING
totalWidth -= 2; ? kWindowOffsetMinWidth : kWindowMinWidth) * fontFactor;
if (buttonCount == 3)
totalWidth = max(kWindowOffsetMinWidth, totalWidth); ResizeTo(max_c(totalWidth, width), Bounds().Height());
else
totalWidth = max(kWindowMinWidth, totalWidth);
} else {
totalWidth += 5;
totalWidth = max(kWindowMinWidth, totalWidth);
}
ResizeTo(totalWidth, Bounds().Height());
// Set up the text view // Set up the text view
BRect textViewRect(kTextLeftOffset, kTextTopOffset,
Bounds().right - kTextRightOffset, BRect textViewRect(kLeftOffset, kTopOffset,
Bounds().bottom - kTextBottomOffset); Bounds().right - kRightOffset,
if (masterView->Bitmap()) fButtons[0]->Frame().top - kTextButtonOffset);
if (view->Bitmap())
textViewRect.left = kTextIconOffset; textViewRect.left = kTextIconOffset;
fTextView = new BTextView(textViewRect, "_tv_", textViewRect, fTextView = new BTextView(textViewRect, "_tv_",
textViewRect.OffsetByCopy(B_ORIGIN),
B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW); B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW);
masterView->AddChild(fTextView);
fTextView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); fTextView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
fTextView->SetText(text, strlen(text)); fTextView->SetText(text, strlen(text));
fTextView->MakeEditable(false); fTextView->MakeEditable(false);
fTextView->MakeSelectable(false); fTextView->MakeSelectable(false);
fTextView->SetWordWrap(true); fTextView->SetWordWrap(true);
view->AddChild(fTextView);
// Now resize the TextView vertically so that all the text is visible // Now resize the TextView vertically so that all the text is visible
float textHeight = fTextView->TextHeight(0, fTextView->CountLines()); float textHeight = fTextView->TextHeight(0, fTextView->CountLines());
@@ -622,7 +543,7 @@ BAlert::InitObject(const char* text, const char* button0, const char* button1,
BBitmap* BBitmap*
BAlert::InitIcon() BAlert::_InitIcon()
{ {
// After a bit of a search, I found the icons in app_server. =P // After a bit of a search, I found the icons in app_server. =P
BBitmap* icon = NULL; BBitmap* icon = NULL;
@@ -665,8 +586,9 @@ BAlert::InitIcon()
if (rawIcon) { if (rawIcon) {
// Now build the bitmap // Now build the bitmap
icon = new BBitmap(BRect(0, 0, 31, 31), 0, B_CMAP8); icon = new (std::nothrow) BBitmap(BRect(0, 0, 31, 31), 0, B_CMAP8);
icon->SetBits(rawIcon, size, 0, B_CMAP8); if (icon != NULL)
icon->SetBits(rawIcon, size, 0, B_CMAP8);
} else { } else {
FTRACE((stderr, "BAlert::InitIcon() - Icon resource not found\n")); FTRACE((stderr, "BAlert::InitIcon() - Icon resource not found\n"));
} }
@@ -680,7 +602,7 @@ BAlert::InitIcon()
FTRACE((stderr, "BAlert::InitIcon() - find_directory failed: %s\n", strerror(status))); FTRACE((stderr, "BAlert::InitIcon() - find_directory failed: %s\n", strerror(status)));
} }
if (!icon) { if (icon == NULL) {
// If there's no icon, it's an empty alert indeed. // If there's no icon, it's an empty alert indeed.
fMsgType = B_EMPTY_ALERT; fMsgType = B_EMPTY_ALERT;
} }
@@ -689,7 +611,41 @@ BAlert::InitIcon()
} }
//------------------------------------------------------------------------------ BButton*
BAlert::_CreateButton(int32 which, const char* label)
{
BMessage* message = new BMessage(kAlertButtonMsg);
if (message == NULL)
return NULL;
message->AddInt32("which", which);
BRect rect;
rect.top = Bounds().bottom - kBottomOffset;
rect.bottom = rect.top;
char name[32];
snprintf(name, sizeof(name), "_b%ld_", which);
BButton* button = new (std::nothrow) BButton(rect, name, label, message,
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
if (button == NULL)
return NULL;
float width, height;
button->GetPreferredSize(&width, &height);
if (fButtonWidth == B_WIDTH_AS_USUAL) {
float fontFactor = be_plain_font->Size() / 11.0f;
width = max_c(width, kButtonUsualWidth * fontFactor);
}
button->ResizeTo(width, height);
button->MoveBy(0.0f, -height);
return button;
}
// #pragma mark - TAlertView // #pragma mark - TAlertView