BAlert: use layout API, allow any number of buttons.
* Added default constructor; you can now alter the complete behavior via setters, and also add buttons afterwards.
This commit is contained in:
@@ -1,11 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2001-2014 Haiku, Inc. All rights reserved.
|
* Copyright 2001-2015 Haiku, Inc. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _ALERT_H
|
#ifndef _ALERT_H
|
||||||
#define _ALERT_H
|
#define _ALERT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <Window.h>
|
#include <Window.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -26,78 +28,97 @@ enum button_spacing {
|
|||||||
|
|
||||||
class BBitmap;
|
class BBitmap;
|
||||||
class BButton;
|
class BButton;
|
||||||
|
class BGroupLayout;
|
||||||
class BInvoker;
|
class BInvoker;
|
||||||
class BTextView;
|
class BTextView;
|
||||||
|
class TAlertView;
|
||||||
|
|
||||||
|
|
||||||
class BAlert : public BWindow {
|
class BAlert : public BWindow {
|
||||||
public:
|
public:
|
||||||
BAlert(const char* title, const char* text,
|
BAlert();
|
||||||
const char* button1, const char* button2 = NULL,
|
BAlert(const char* title, const char* text,
|
||||||
const char* button3 = NULL,
|
const char* button1,
|
||||||
button_width width = B_WIDTH_AS_USUAL,
|
const char* button2 = NULL,
|
||||||
alert_type type = B_INFO_ALERT);
|
const char* button3 = NULL,
|
||||||
BAlert(const char* title, const char* text,
|
button_width width = B_WIDTH_AS_USUAL,
|
||||||
const char* button1, const char* button2,
|
alert_type type = B_INFO_ALERT);
|
||||||
const char* button3, button_width width,
|
BAlert(const char* title, const char* text,
|
||||||
button_spacing spacing,
|
const char* button1, const char* button2,
|
||||||
alert_type type = B_INFO_ALERT);
|
const char* button3, button_width width,
|
||||||
virtual ~BAlert();
|
button_spacing spacing,
|
||||||
|
alert_type type = B_INFO_ALERT);
|
||||||
|
BAlert(BMessage* data);
|
||||||
|
virtual ~BAlert();
|
||||||
|
|
||||||
// Archiving
|
// Archiving
|
||||||
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);
|
alert_type Type() const;
|
||||||
char Shortcut(int32 button_index) const;
|
void SetType(alert_type type);
|
||||||
|
void SetIcon(BBitmap* bitmap);
|
||||||
|
void SetText(const char* text);
|
||||||
|
void SetButtonSpacing(button_spacing spacing);
|
||||||
|
void SetButtonWidth(button_width width);
|
||||||
|
|
||||||
int32 Go();
|
void SetShortcut(int32 buttonIndex, char key);
|
||||||
status_t Go(BInvoker* invoker);
|
char Shortcut(int32 buttonIndex) const;
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage* message);
|
int32 Go();
|
||||||
virtual void FrameResized(float new_width, float new_height);
|
status_t Go(BInvoker* invoker);
|
||||||
BButton* ButtonAt(int32 index) const;
|
|
||||||
BTextView* TextView() const;
|
|
||||||
|
|
||||||
virtual BHandler* ResolveSpecifier(BMessage* message, int32 index,
|
virtual void MessageReceived(BMessage* message);
|
||||||
BMessage* specifier, int32 what,
|
virtual void FrameResized(float newWidth, float newHeight);
|
||||||
const char* property);
|
|
||||||
virtual status_t GetSupportedSuites(BMessage* data);
|
|
||||||
|
|
||||||
virtual void DispatchMessage(BMessage* message, BHandler* handler);
|
void AddButton(const char* label, char key = 0);
|
||||||
virtual void Quit();
|
int32 CountButtons() const;
|
||||||
virtual bool QuitRequested();
|
BButton* ButtonAt(int32 index) const;
|
||||||
|
|
||||||
static BPoint AlertPosition(float width, float height);
|
BTextView* TextView() const;
|
||||||
|
|
||||||
virtual status_t Perform(perform_code d, void* arg);
|
virtual BHandler* ResolveSpecifier(BMessage* message, int32 index,
|
||||||
|
BMessage* specifier, int32 form,
|
||||||
|
const char* property);
|
||||||
|
virtual status_t GetSupportedSuites(BMessage* data);
|
||||||
|
|
||||||
|
virtual void DispatchMessage(BMessage* message,
|
||||||
|
BHandler* handler);
|
||||||
|
virtual void Quit();
|
||||||
|
virtual bool QuitRequested();
|
||||||
|
|
||||||
|
virtual status_t Perform(perform_code d, void* arg);
|
||||||
|
|
||||||
|
static BPoint AlertPosition(float width, float height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class _BAlertFilter_;
|
virtual void _ReservedAlert1();
|
||||||
|
virtual void _ReservedAlert2();
|
||||||
|
virtual void _ReservedAlert3();
|
||||||
|
|
||||||
virtual void _ReservedAlert1();
|
void _Init(const char* text, const char* button1,
|
||||||
virtual void _ReservedAlert2();
|
const char* button2, const char* button3,
|
||||||
virtual void _ReservedAlert3();
|
button_width width, button_spacing spacing,
|
||||||
|
alert_type type);
|
||||||
|
BBitmap* _CreateTypeIcon();
|
||||||
|
BButton* _CreateButton(int32 which, const char* label);
|
||||||
|
void _Prepare();
|
||||||
|
|
||||||
void _InitObject(const char* text, const char* button1,
|
private:
|
||||||
const char* button2 = NULL,
|
sem_id fAlertSem;
|
||||||
const char* button3 = NULL,
|
int32 fAlertValue;
|
||||||
button_width width = B_WIDTH_AS_USUAL,
|
TAlertView* fIconView;
|
||||||
button_spacing spacing = B_EVEN_SPACING,
|
BTextView* fTextView;
|
||||||
alert_type type = B_INFO_ALERT);
|
BGroupLayout* fButtonLayout;
|
||||||
BBitmap* _InitIcon();
|
std::vector<BButton*> fButtons;
|
||||||
BButton* _CreateButton(int32 which, const char* label);
|
std::vector<char> fKeys;
|
||||||
|
uint8 fType;
|
||||||
sem_id fAlertSem;
|
uint8 fButtonSpacing;
|
||||||
int32 fAlertValue;
|
uint8 fButtonWidth;
|
||||||
BButton* fButtons[3];
|
BInvoker* fInvoker;
|
||||||
BTextView* fTextView;
|
uint32 _reserved[1];
|
||||||
char fKeys[3];
|
|
||||||
alert_type fMsgType;
|
|
||||||
button_width fButtonWidth;
|
|
||||||
BInvoker* fInvoker;
|
|
||||||
uint32 _reserved[4];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif // _ALERT_H
|
#endif // _ALERT_H
|
||||||
|
|||||||
+299
-302
@@ -9,31 +9,28 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
// BAlert displays a modal alert window.
|
//! BAlert displays a modal alert window.
|
||||||
|
|
||||||
|
|
||||||
#include <new>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <Alert.h>
|
#include <Alert.h>
|
||||||
#include <Autolock.h>
|
|
||||||
#include <Beep.h>
|
#include <new>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <Bitmap.h>
|
#include <Bitmap.h>
|
||||||
#include <Button.h>
|
#include <Button.h>
|
||||||
#include <File.h>
|
#include <ControlLook.h>
|
||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
#include <Font.h>
|
|
||||||
#include <IconUtils.h>
|
#include <IconUtils.h>
|
||||||
#include <Invoker.h>
|
#include <LayoutBuilder.h>
|
||||||
#include <Looper.h>
|
#include <MenuField.h>
|
||||||
#include <Message.h>
|
|
||||||
#include <MessageFilter.h>
|
#include <MessageFilter.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <Resources.h>
|
#include <Resources.h>
|
||||||
#include <Screen.h>
|
#include <Screen.h>
|
||||||
#include <TextView.h>
|
#include <String.h>
|
||||||
#include <View.h>
|
#include <Window.h>
|
||||||
|
|
||||||
#include <binary_compatibility/Interface.h>
|
#include <binary_compatibility/Interface.h>
|
||||||
|
|
||||||
@@ -42,111 +39,102 @@
|
|||||||
#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) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Default size of the Alert window.
|
|
||||||
#define DEFAULT_RECT BRect(0, 0, 310, 75)
|
class TAlertView : public BView {
|
||||||
#define max(LHS, RHS) ((LHS) > (RHS) ? (LHS) : (RHS))
|
public:
|
||||||
|
TAlertView();
|
||||||
|
TAlertView(BMessage* archive);
|
||||||
|
~TAlertView();
|
||||||
|
|
||||||
|
static TAlertView* Instantiate(BMessage* archive);
|
||||||
|
virtual status_t Archive(BMessage* archive,
|
||||||
|
bool deep = true) const;
|
||||||
|
|
||||||
|
virtual void GetPreferredSize(float* _width, float* _height);
|
||||||
|
virtual BSize MaxSize();
|
||||||
|
virtual void Draw(BRect updateRect);
|
||||||
|
|
||||||
|
void SetBitmap(BBitmap* Icon)
|
||||||
|
{ fIconBitmap = Icon; }
|
||||||
|
BBitmap* Bitmap()
|
||||||
|
{ return fIconBitmap; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
BBitmap* fIconBitmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class _BAlertFilter_ : public BMessageFilter {
|
||||||
|
public:
|
||||||
|
_BAlertFilter_(BAlert* Alert);
|
||||||
|
~_BAlertFilter_();
|
||||||
|
|
||||||
|
virtual filter_result Filter(BMessage* msg, BHandler** target);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BAlert* fAlert;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
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 kLeftOffset = 10;
|
|
||||||
static const int kTopOffset = 6;
|
|
||||||
static const int kBottomOffset = 8;
|
|
||||||
static const int kRightOffset = 8;
|
|
||||||
|
|
||||||
static const int kButtonSpacing = 6;
|
|
||||||
static const int kButtonOffsetSpacing = 62;
|
static const int kButtonOffsetSpacing = 62;
|
||||||
static const int kButtonUsualWidth = 75;
|
static const int kButtonUsualWidth = 55;
|
||||||
|
static const int kIconStripeWidth = 30;
|
||||||
|
|
||||||
static const int kWindowIconOffset = 27;
|
|
||||||
static const int kWindowMinOffset = 12;
|
|
||||||
static const int kWindowMinWidth = 310;
|
static const int kWindowMinWidth = 310;
|
||||||
static const int kWindowOffsetMinWidth = 335;
|
static const int kWindowOffsetMinWidth = 335;
|
||||||
|
|
||||||
static const int kIconStripeWidth = 30;
|
|
||||||
|
|
||||||
static const int kTextButtonOffset = 10;
|
|
||||||
|
|
||||||
static inline int32
|
static inline int32
|
||||||
icon_layout_scale()
|
icon_layout_scale()
|
||||||
{
|
{
|
||||||
#ifdef __HAIKU__
|
|
||||||
return max_c(1, ((int32)be_plain_font->Size() + 15) / 16);
|
return max_c(1, ((int32)be_plain_font->Size() + 15) / 16);
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class TAlertView : public BView {
|
// #pragma mark -
|
||||||
public:
|
|
||||||
TAlertView(BRect frame);
|
|
||||||
TAlertView(BMessage* archive);
|
|
||||||
~TAlertView();
|
|
||||||
|
|
||||||
static TAlertView* Instantiate(BMessage* archive);
|
|
||||||
virtual status_t Archive(BMessage* archive, bool deep = true) const;
|
|
||||||
|
|
||||||
virtual void Draw(BRect updateRect);
|
|
||||||
|
|
||||||
// These functions (or something analogous) are missing from libbe.so's
|
|
||||||
// dump. I can only assume that the bitmap is a public var in the
|
|
||||||
// original implementation -- or BAlert is a friend of TAlertView.
|
|
||||||
// Neither one is necessary, since I can just add these.
|
|
||||||
void SetBitmap(BBitmap* Icon) { fIconBitmap = Icon; }
|
|
||||||
BBitmap* Bitmap() { return fIconBitmap; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
BBitmap* fIconBitmap;
|
|
||||||
};
|
|
||||||
|
|
||||||
class _BAlertFilter_ : public BMessageFilter {
|
|
||||||
public:
|
|
||||||
_BAlertFilter_(BAlert* Alert);
|
|
||||||
~_BAlertFilter_();
|
|
||||||
|
|
||||||
virtual filter_result Filter(BMessage* msg, BHandler** target);
|
|
||||||
|
|
||||||
private:
|
|
||||||
BAlert* fAlert;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - BAlert
|
BAlert::BAlert()
|
||||||
|
:
|
||||||
|
BWindow(BRect(0, 0, 100, 100), "", B_MODAL_WINDOW,
|
||||||
|
B_NOT_CLOSABLE | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS)
|
||||||
|
{
|
||||||
|
_Init(NULL, NULL, NULL, NULL, B_WIDTH_FROM_WIDEST, B_EVEN_SPACING,
|
||||||
|
B_INFO_ALERT);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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(BRect(0, 0, 100, 100), 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);
|
_Init(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(BRect(0, 0, 100, 100), 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);
|
_Init(text, button1, button2, button3, width, spacing, type);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BAlert::~BAlert()
|
|
||||||
{
|
|
||||||
// Probably not necessary, but it makes me feel better.
|
|
||||||
if (fAlertSem >= B_OK)
|
|
||||||
delete_sem(fAlertSem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BAlert::BAlert(BMessage* data)
|
BAlert::BAlert(BMessage* data)
|
||||||
: BWindow(data)
|
:
|
||||||
|
BWindow(data)
|
||||||
{
|
{
|
||||||
fInvoker = NULL;
|
fInvoker = NULL;
|
||||||
fAlertSem = -1;
|
fAlertSem = -1;
|
||||||
@@ -154,20 +142,12 @@ BAlert::BAlert(BMessage* data)
|
|||||||
|
|
||||||
fTextView = (BTextView*)FindView("_tv_");
|
fTextView = (BTextView*)FindView("_tv_");
|
||||||
|
|
||||||
fButtons[0] = (BButton*)FindView("_b0_");
|
// TODO: window loses default button on dearchive!
|
||||||
fButtons[1] = (BButton*)FindView("_b1_");
|
// TODO: ButtonAt() doesn't work afterwards (also affects shortcuts)
|
||||||
fButtons[2] = (BButton*)FindView("_b2_");
|
|
||||||
|
|
||||||
if (fButtons[2])
|
|
||||||
SetDefaultButton(fButtons[2]);
|
|
||||||
else if (fButtons[1])
|
|
||||||
SetDefaultButton(fButtons[1]);
|
|
||||||
else if (fButtons[0])
|
|
||||||
SetDefaultButton(fButtons[0]);
|
|
||||||
|
|
||||||
TAlertView* view = (TAlertView*)FindView("_master_");
|
TAlertView* view = (TAlertView*)FindView("_master_");
|
||||||
if (view)
|
if (view)
|
||||||
view->SetBitmap(_InitIcon());
|
view->SetBitmap(_CreateTypeIcon());
|
||||||
|
|
||||||
// Get keys
|
// Get keys
|
||||||
char key;
|
char key;
|
||||||
@@ -176,19 +156,18 @@ BAlert::BAlert(BMessage* data)
|
|||||||
fKeys[i] = key;
|
fKeys[i] = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 temp;
|
|
||||||
// Get alert type
|
|
||||||
if (data->FindInt32("_atype", &temp) == B_OK)
|
|
||||||
fMsgType = (alert_type)temp;
|
|
||||||
|
|
||||||
// Get button width
|
|
||||||
if (data->FindInt32("_but_width", &temp) == B_OK)
|
|
||||||
fButtonWidth = (button_width)temp;
|
|
||||||
|
|
||||||
AddCommonFilter(new(std::nothrow) _BAlertFilter_(this));
|
AddCommonFilter(new(std::nothrow) _BAlertFilter_(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BAlert::~BAlert()
|
||||||
|
{
|
||||||
|
// Probably not necessary, but it makes me feel better.
|
||||||
|
if (fAlertSem >= B_OK)
|
||||||
|
delete_sem(fAlertSem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BArchivable*
|
BArchivable*
|
||||||
BAlert::Instantiate(BMessage* data)
|
BAlert::Instantiate(BMessage* data)
|
||||||
{
|
{
|
||||||
@@ -210,7 +189,7 @@ BAlert::Archive(BMessage* data, bool deep) const
|
|||||||
|
|
||||||
// Stow the alert type
|
// Stow the alert type
|
||||||
if (ret == B_OK)
|
if (ret == B_OK)
|
||||||
ret = data->AddInt32("_atype", fMsgType);
|
ret = data->AddInt32("_atype", fType);
|
||||||
|
|
||||||
// Stow the button width
|
// Stow the button width
|
||||||
if (ret == B_OK)
|
if (ret == B_OK)
|
||||||
@@ -232,10 +211,52 @@ BAlert::Archive(BMessage* data, bool deep) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
alert_type
|
||||||
|
BAlert::Type() const
|
||||||
|
{
|
||||||
|
return (alert_type)fType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BAlert::SetType(alert_type type)
|
||||||
|
{
|
||||||
|
fType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BAlert::SetText(const char* text)
|
||||||
|
{
|
||||||
|
TextView()->SetText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BAlert::SetIcon(BBitmap* bitmap)
|
||||||
|
{
|
||||||
|
fIconView->SetBitmap(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BAlert::SetButtonSpacing(button_spacing spacing)
|
||||||
|
{
|
||||||
|
fButtonSpacing = spacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BAlert::SetButtonWidth(button_width width)
|
||||||
|
{
|
||||||
|
fButtonWidth = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BAlert::SetShortcut(int32 index, char key)
|
BAlert::SetShortcut(int32 index, char key)
|
||||||
{
|
{
|
||||||
if (index >= 0 && index < 3)
|
if (index >= 0 && (size_t)index < fKeys.size())
|
||||||
fKeys[index] = key;
|
fKeys[index] = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +264,8 @@ BAlert::SetShortcut(int32 index, char key)
|
|||||||
char
|
char
|
||||||
BAlert::Shortcut(int32 index) const
|
BAlert::Shortcut(int32 index) const
|
||||||
{
|
{
|
||||||
if (index >= 0 && index < 3)
|
|
||||||
|
if (index >= 0 && (size_t)index < fKeys.size())
|
||||||
return fKeys[index];
|
return fKeys[index];
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -254,29 +276,28 @@ int32
|
|||||||
BAlert::Go()
|
BAlert::Go()
|
||||||
{
|
{
|
||||||
fAlertSem = create_sem(0, "AlertSem");
|
fAlertSem = create_sem(0, "AlertSem");
|
||||||
if (fAlertSem < B_OK) {
|
if (fAlertSem < 0) {
|
||||||
Quit();
|
Quit();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the originating window, if it exists
|
// Get the originating window, if it exists
|
||||||
BWindow* window =
|
BWindow* window = dynamic_cast<BWindow*>(
|
||||||
dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
|
BLooper::LooperForThread(find_thread(NULL)));
|
||||||
|
|
||||||
|
_Prepare();
|
||||||
Show();
|
Show();
|
||||||
|
|
||||||
// Heavily modified from TextEntryAlert code; the original didn't let the
|
if (window != NULL) {
|
||||||
// blocked window ever draw.
|
status_t status;
|
||||||
if (window) {
|
|
||||||
status_t err;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
do {
|
do {
|
||||||
err = acquire_sem_etc(fAlertSem, 1, B_RELATIVE_TIMEOUT,
|
status = acquire_sem_etc(fAlertSem, 1, B_RELATIVE_TIMEOUT,
|
||||||
kSemTimeOut);
|
kSemTimeOut);
|
||||||
// We've (probably) had our time slice taken away from us
|
// We've (probably) had our time slice taken away from us
|
||||||
} while (err == B_INTERRUPTED);
|
} while (status == B_INTERRUPTED);
|
||||||
|
|
||||||
if (err == B_BAD_SEM_ID) {
|
if (status == B_BAD_SEM_ID) {
|
||||||
// Semaphore was finally nuked in MessageReceived
|
// Semaphore was finally nuked in MessageReceived
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -301,19 +322,20 @@ status_t
|
|||||||
BAlert::Go(BInvoker* invoker)
|
BAlert::Go(BInvoker* invoker)
|
||||||
{
|
{
|
||||||
fInvoker = invoker;
|
fInvoker = invoker;
|
||||||
|
_Prepare();
|
||||||
Show();
|
Show();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BAlert::MessageReceived(BMessage* message)
|
BAlert::MessageReceived(BMessage* msg)
|
||||||
{
|
{
|
||||||
if (message->what != kAlertButtonMsg)
|
if (msg->what != kAlertButtonMsg)
|
||||||
return BWindow::MessageReceived(message);
|
return BWindow::MessageReceived(msg);
|
||||||
|
|
||||||
int32 which;
|
int32 which;
|
||||||
if (message->FindInt32("which", &which) == B_OK) {
|
if (msg->FindInt32("which", &which) == B_OK) {
|
||||||
if (fAlertSem < B_OK) {
|
if (fAlertSem < B_OK) {
|
||||||
// Semaphore hasn't been created; we're running asynchronous
|
// Semaphore hasn't been created; we're running asynchronous
|
||||||
if (fInvoker) {
|
if (fInvoker) {
|
||||||
@@ -346,10 +368,31 @@ BAlert::FrameResized(float newWidth, float newHeight)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BAlert::AddButton(const char* label, char key)
|
||||||
|
{
|
||||||
|
if (label == NULL || label[0] == '\0')
|
||||||
|
return;
|
||||||
|
|
||||||
|
BButton* button = _CreateButton(fButtons.size(), label);
|
||||||
|
fButtons.push_back(button);
|
||||||
|
fKeys.push_back(key);
|
||||||
|
|
||||||
|
fButtonLayout->AddView(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
BAlert::CountButtons() const
|
||||||
|
{
|
||||||
|
return (int32)fButtons.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BButton*
|
BButton*
|
||||||
BAlert::ButtonAt(int32 index) const
|
BAlert::ButtonAt(int32 index) const
|
||||||
{
|
{
|
||||||
if (index >= 0 && index < 3)
|
if (index >= 0 && (size_t)index < fButtons.size())
|
||||||
return fButtons[index];
|
return fButtons[index];
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -364,11 +407,10 @@ BAlert::TextView() const
|
|||||||
|
|
||||||
|
|
||||||
BHandler*
|
BHandler*
|
||||||
BAlert::ResolveSpecifier(BMessage* message, int32 index,
|
BAlert::ResolveSpecifier(BMessage* msg, int32 index,
|
||||||
BMessage* specifier, int32 what, const char* property)
|
BMessage* specifier, int32 form, const char* property)
|
||||||
{
|
{
|
||||||
return BWindow::ResolveSpecifier(message, index, specifier, what,
|
return BWindow::ResolveSpecifier(msg, index, specifier, form, property);
|
||||||
property);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -400,7 +442,7 @@ BAlert::QuitRequested()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This method is deprecated, do not use
|
//! This method is deprecated, do not use - use BWindow::CenterIn() instead.
|
||||||
BPoint
|
BPoint
|
||||||
BAlert::AlertPosition(float width, float height)
|
BAlert::AlertPosition(float width, float height)
|
||||||
{
|
{
|
||||||
@@ -429,11 +471,9 @@ BAlert::Perform(perform_code code, void* _data)
|
|||||||
{
|
{
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case PERFORM_CODE_SET_LAYOUT:
|
case PERFORM_CODE_SET_LAYOUT:
|
||||||
{
|
|
||||||
perform_data_set_layout* data = (perform_data_set_layout*)_data;
|
perform_data_set_layout* data = (perform_data_set_layout*)_data;
|
||||||
BAlert::SetLayout(data->layout);
|
BAlert::SetLayout(data->layout);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return BWindow::Perform(code, _data);
|
return BWindow::Perform(code, _data);
|
||||||
@@ -446,185 +486,79 @@ void BAlert::_ReservedAlert3() {}
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BAlert::_InitObject(const char* text, const char* button0, const char* button1,
|
BAlert::_Init(const char* text, const char* button0, const char* button1,
|
||||||
const char* button2, button_width buttonWidth, button_spacing spacing,
|
const char* button2, button_width buttonWidth, button_spacing spacing,
|
||||||
alert_type type)
|
alert_type type)
|
||||||
{
|
{
|
||||||
fInvoker = NULL;
|
fIconView = new TAlertView();
|
||||||
fAlertSem = -1;
|
|
||||||
fAlertValue = -1;
|
|
||||||
fButtons[0] = fButtons[1] = fButtons[2] = NULL;
|
|
||||||
fTextView = NULL;
|
|
||||||
fKeys[0] = fKeys[1] = fKeys[2] = 0;
|
|
||||||
fMsgType = type;
|
|
||||||
fButtonWidth = buttonWidth;
|
|
||||||
|
|
||||||
// Set up the "_master_" view
|
|
||||||
TAlertView* view = new(std::nothrow) TAlertView(Bounds());
|
|
||||||
if (view == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddChild(view);
|
|
||||||
view->SetBitmap(_InitIcon());
|
|
||||||
|
|
||||||
// Must have at least one button
|
|
||||||
if (button0 == NULL) {
|
|
||||||
debugger("BAlerts must have at least one button.");
|
|
||||||
button0 = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up the buttons
|
|
||||||
|
|
||||||
int32 buttonCount = 1;
|
|
||||||
view->AddChild(fButtons[0] = _CreateButton(0, button0));
|
|
||||||
|
|
||||||
if (button1 != NULL) {
|
|
||||||
view->AddChild(fButtons[1] = _CreateButton(1, button1));
|
|
||||||
buttonCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (button2 != NULL) {
|
|
||||||
view->AddChild(fButtons[2] = _CreateButton(2, button2));
|
|
||||||
buttonCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the widest button only if the widest value needs to be known.
|
|
||||||
|
|
||||||
if (fButtonWidth == B_WIDTH_FROM_WIDEST) {
|
|
||||||
float maxWidth = 0;
|
|
||||||
for (int i = 0; i < buttonCount; i++) {
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float defaultButtonFrameWidth
|
|
||||||
= -fButtons[buttonCount - 1]->Bounds().Width() / 2.0f;
|
|
||||||
SetDefaultButton(fButtons[buttonCount - 1]);
|
|
||||||
defaultButtonFrameWidth
|
|
||||||
+= fButtons[buttonCount - 1]->Bounds().Width() / 2.0f;
|
|
||||||
|
|
||||||
// Layout buttons
|
|
||||||
|
|
||||||
float fontFactor = be_plain_font->Size() / 11.0f;
|
|
||||||
|
|
||||||
for (int i = buttonCount - 1; i >= 0; --i) {
|
|
||||||
float x = -fButtons[i]->Bounds().Width();
|
|
||||||
if (i + 1 == buttonCount)
|
|
||||||
x += Bounds().right - kRightOffset + defaultButtonFrameWidth;
|
|
||||||
else
|
|
||||||
x += fButtons[i + 1]->Frame().left - kButtonSpacing;
|
|
||||||
|
|
||||||
if (buttonCount > 1 && i == 0 && spacing == B_OFFSET_SPACING)
|
|
||||||
x -= kButtonOffsetSpacing * fontFactor;
|
|
||||||
|
|
||||||
fButtons[i]->MoveTo(x, fButtons[i]->Frame().top);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjust the window's width, if necessary
|
|
||||||
|
|
||||||
int32 iconLayoutScale = icon_layout_scale();
|
|
||||||
float totalWidth = kRightOffset + fButtons[buttonCount - 1]->Frame().right
|
|
||||||
- defaultButtonFrameWidth - fButtons[0]->Frame().left;
|
|
||||||
if (view->Bitmap())
|
|
||||||
totalWidth += (kIconStripeWidth + kWindowIconOffset) * iconLayoutScale;
|
|
||||||
else
|
|
||||||
totalWidth += kWindowMinOffset;
|
|
||||||
|
|
||||||
float width = (spacing == B_OFFSET_SPACING
|
|
||||||
? kWindowOffsetMinWidth : kWindowMinWidth) * fontFactor;
|
|
||||||
|
|
||||||
ResizeTo(max_c(totalWidth, width), Bounds().Height());
|
|
||||||
|
|
||||||
// Set up the text view
|
|
||||||
|
|
||||||
BRect textViewRect(kLeftOffset, kTopOffset,
|
|
||||||
Bounds().right - kRightOffset,
|
|
||||||
fButtons[0]->Frame().top - kTextButtonOffset);
|
|
||||||
if (view->Bitmap())
|
|
||||||
textViewRect.left = (kWindowIconOffset
|
|
||||||
+ kIconStripeWidth) * iconLayoutScale - 2;
|
|
||||||
|
|
||||||
fTextView = new(std::nothrow) BTextView(textViewRect, "_tv_",
|
|
||||||
textViewRect.OffsetByCopy(B_ORIGIN),
|
|
||||||
B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW);
|
|
||||||
if (fTextView == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
fTextView = new BTextView("_tv_");
|
||||||
fTextView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
fTextView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
|
rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
|
||||||
fTextView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
|
fTextView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
|
||||||
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);
|
fTextView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED));
|
||||||
|
|
||||||
// Now resize the TextView vertically so that all the text is visible
|
fButtonLayout = new BGroupLayout(B_HORIZONTAL);
|
||||||
float textHeight = fTextView->TextHeight(0, fTextView->CountLines());
|
|
||||||
textViewRect.OffsetTo(0, 0);
|
|
||||||
textHeight -= textViewRect.Height();
|
|
||||||
ResizeBy(0, textHeight);
|
|
||||||
fTextView->ResizeBy(0, textHeight);
|
|
||||||
textViewRect.bottom += textHeight;
|
|
||||||
fTextView->SetTextRect(textViewRect);
|
|
||||||
|
|
||||||
AddCommonFilter(new(std::nothrow) _BAlertFilter_(this));
|
SetType(type);
|
||||||
|
SetButtonWidth(buttonWidth);
|
||||||
|
SetButtonSpacing(spacing);
|
||||||
|
SetText(text);
|
||||||
|
|
||||||
// Position the alert so that it is centered vertically but offset a bit
|
BLayoutBuilder::Group<>(this, B_HORIZONTAL, 0)
|
||||||
// horizontally in the parent window's frame or, if unavailable, the
|
.Add(fIconView)
|
||||||
// screen frame.
|
.AddGroup(B_VERTICAL)
|
||||||
BWindow* parent =
|
.SetInsets(B_USE_DEFAULT_SPACING)
|
||||||
dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
|
.Add(fTextView)
|
||||||
const BRect frame = parent != NULL ? parent->Frame() : BScreen(this).Frame();
|
.AddGroup(B_HORIZONTAL, 0)
|
||||||
MoveTo(dynamic_cast<BWindow*>(this)->AlertPosition(frame));
|
.AddGlue()
|
||||||
|
.Add(fButtonLayout);
|
||||||
|
|
||||||
|
AddButton(button0);
|
||||||
|
AddButton(button1);
|
||||||
|
AddButton(button2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BBitmap*
|
BBitmap*
|
||||||
BAlert::_InitIcon()
|
BAlert::_CreateTypeIcon()
|
||||||
{
|
{
|
||||||
// Save the desired alert type and set it to "empty" until
|
if (Type() == B_EMPTY_ALERT)
|
||||||
// loading the icon was successful
|
return NULL;
|
||||||
alert_type alertType = fMsgType;
|
|
||||||
fMsgType = B_EMPTY_ALERT;
|
|
||||||
|
|
||||||
// After a bit of a search, I found the icons in app_server. =P
|
// The icons are in the app_server resources
|
||||||
BBitmap* icon = NULL;
|
BBitmap* icon = NULL;
|
||||||
BPath path;
|
BPath path;
|
||||||
status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path);
|
status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path);
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
FTRACE((stderr, "BAlert::_InitIcon() - find_directory failed: %s\n",
|
FTRACE((stderr, "BAlert::_CreateTypeIcon() - find_directory "
|
||||||
strerror(status)));
|
"failed: %s\n", strerror(status)));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
path.Append("app_server");
|
path.Append("app_server");
|
||||||
BFile file;
|
BFile file;
|
||||||
status = file.SetTo(path.Path(), B_READ_ONLY);
|
status = file.SetTo(path.Path(), B_READ_ONLY);
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
FTRACE((stderr, "BAlert::_InitIcon() - BFile init failed: %s\n",
|
FTRACE((stderr, "BAlert::_CreateTypeIcon() - BFile init failed: %s\n",
|
||||||
strerror(status)));
|
strerror(status)));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
BResources resources;
|
BResources resources;
|
||||||
status = resources.SetTo(&file);
|
status = resources.SetTo(&file);
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
FTRACE((stderr, "BAlert::_InitIcon() - BResources init failed: %s\n",
|
FTRACE((stderr, "BAlert::_CreateTypeIcon() - BResources init "
|
||||||
strerror(status)));
|
"failed: %s\n", strerror(status)));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Which icon are we trying to load?
|
// Which icon are we trying to load?
|
||||||
const char* iconName = ""; // Don't want any seg faults
|
const char* iconName;
|
||||||
switch (alertType) {
|
switch (fType) {
|
||||||
case B_INFO_ALERT:
|
case B_INFO_ALERT:
|
||||||
iconName = "info";
|
iconName = "info";
|
||||||
break;
|
break;
|
||||||
@@ -649,7 +583,7 @@ BAlert::_InitIcon()
|
|||||||
icon = new(std::nothrow) BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1),
|
icon = new(std::nothrow) BBitmap(BRect(0, 0, iconSize - 1, iconSize - 1),
|
||||||
0, B_RGBA32);
|
0, B_RGBA32);
|
||||||
if (icon == NULL || icon->InitCheck() < B_OK) {
|
if (icon == NULL || icon->InitCheck() < B_OK) {
|
||||||
FTRACE((stderr, "BAlert::_InitIcon() - No memory for bitmap\n"));
|
FTRACE((stderr, "BAlert::_CreateTypeIcon() - No memory for bitmap\n"));
|
||||||
delete icon;
|
delete icon;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -658,39 +592,28 @@ BAlert::_InitIcon()
|
|||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
const uint8* rawIcon;
|
const uint8* rawIcon;
|
||||||
|
|
||||||
#ifdef __HAIKU__
|
|
||||||
// Try to load vector icon
|
// Try to load vector icon
|
||||||
rawIcon = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE,
|
rawIcon = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE,
|
||||||
iconName, &size);
|
iconName, &size);
|
||||||
if (rawIcon != NULL
|
if (rawIcon != NULL
|
||||||
&& BIconUtils::GetVectorIcon(rawIcon, size, icon) == B_OK) {
|
&& BIconUtils::GetVectorIcon(rawIcon, size, icon) == B_OK) {
|
||||||
// We have an icon, restore the saved alert type
|
|
||||||
fMsgType = alertType;
|
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fall back to bitmap icon
|
// Fall back to bitmap icon
|
||||||
rawIcon = (const uint8*)resources.LoadResource(B_LARGE_ICON_TYPE,
|
rawIcon = (const uint8*)resources.LoadResource(B_LARGE_ICON_TYPE,
|
||||||
iconName, &size);
|
iconName, &size);
|
||||||
if (rawIcon == NULL) {
|
if (rawIcon == NULL) {
|
||||||
FTRACE((stderr, "BAlert::_InitIcon() - Icon resource not found\n"));
|
FTRACE((stderr, "BAlert::_CreateTypeIcon() - Icon resource not found\n"));
|
||||||
delete icon;
|
delete icon;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle color space conversion
|
// Handle color space conversion
|
||||||
#ifdef __HAIKU__
|
|
||||||
if (icon->ColorSpace() != B_CMAP8) {
|
if (icon->ColorSpace() != B_CMAP8) {
|
||||||
BIconUtils::ConvertFromCMAP8(rawIcon, iconSize, iconSize,
|
BIconUtils::ConvertFromCMAP8(rawIcon, iconSize, iconSize,
|
||||||
iconSize, icon);
|
iconSize, icon);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
icon->SetBits(rawIcon, iconSize, 0, B_CMAP8);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// We have an icon, restore the saved alert type
|
|
||||||
fMsgType = alertType;
|
|
||||||
|
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
@@ -705,46 +628,95 @@ BAlert::_CreateButton(int32 which, const char* label)
|
|||||||
|
|
||||||
message->AddInt32("which", which);
|
message->AddInt32("which", which);
|
||||||
|
|
||||||
BRect rect;
|
|
||||||
rect.top = Bounds().bottom - kBottomOffset;
|
|
||||||
rect.bottom = rect.top;
|
|
||||||
|
|
||||||
char name[32];
|
char name[32];
|
||||||
snprintf(name, sizeof(name), "_b%" B_PRId32 "_", which);
|
snprintf(name, sizeof(name), "_b%" B_PRId32 "_", which);
|
||||||
|
|
||||||
BButton* button = new(std::nothrow) BButton(rect, name, label, message,
|
return new(std::nothrow) BButton(name, label, message);
|
||||||
B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
|
}
|
||||||
if (button == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
float width, height;
|
|
||||||
button->GetPreferredSize(&width, &height);
|
/*! Tweaks the layout according to the configuration.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
BAlert::_Prepare()
|
||||||
|
{
|
||||||
|
// Must have at least one button
|
||||||
|
if (CountButtons() == 0)
|
||||||
|
debugger("BAlerts must have at least one button.");
|
||||||
|
|
||||||
|
SetDefaultButton(ButtonAt(CountButtons() - 1));
|
||||||
|
|
||||||
|
float fontFactor = be_plain_font->Size() / 11.0f;
|
||||||
|
|
||||||
|
if (fIconView->Bitmap() == NULL)
|
||||||
|
fIconView->SetBitmap(_CreateTypeIcon());
|
||||||
|
|
||||||
if (fButtonWidth == B_WIDTH_AS_USUAL) {
|
if (fButtonWidth == B_WIDTH_AS_USUAL) {
|
||||||
float fontFactor = be_plain_font->Size() / 11.0f;
|
float usualWidth = kButtonUsualWidth * fontFactor;
|
||||||
width = max_c(width, kButtonUsualWidth * fontFactor);
|
|
||||||
|
for (int32 index = 0; index < CountButtons(); index++) {
|
||||||
|
BButton* button = ButtonAt(index);
|
||||||
|
if (button->MinSize().width < usualWidth)
|
||||||
|
button->SetExplicitSize(BSize(usualWidth, B_SIZE_UNSET));
|
||||||
|
}
|
||||||
|
} else if (fButtonWidth == B_WIDTH_FROM_WIDEST) {
|
||||||
|
// Get width of widest label
|
||||||
|
float maxWidth = 0;
|
||||||
|
for (int32 index = 0; index < CountButtons(); index++) {
|
||||||
|
BButton* button = ButtonAt(index);
|
||||||
|
float width;
|
||||||
|
button->GetPreferredSize(&width, NULL);
|
||||||
|
|
||||||
|
if (width > maxWidth)
|
||||||
|
maxWidth = width;
|
||||||
|
}
|
||||||
|
for (int32 index = 0; index < CountButtons(); index++) {
|
||||||
|
BButton* button = ButtonAt(index);
|
||||||
|
button->SetExplicitSize(BSize(maxWidth, B_SIZE_UNSET));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
button->ResizeTo(width, height);
|
if (fButtonSpacing == B_OFFSET_SPACING && CountButtons() > 1) {
|
||||||
button->MoveBy(0.0f, -height);
|
// Insert some strut
|
||||||
return button;
|
fButtonLayout->AddItem(1, BSpaceLayoutItem::CreateHorizontalStrut(
|
||||||
|
kButtonOffsetSpacing * fontFactor));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position the alert so that it is centered vertically but offset a bit
|
||||||
|
// horizontally in the parent window's frame or, if unavailable, the
|
||||||
|
// screen frame.
|
||||||
|
float minWindowWidth = (fButtonSpacing == B_OFFSET_SPACING
|
||||||
|
? kWindowOffsetMinWidth : kWindowMinWidth) * fontFactor;
|
||||||
|
GetLayout()->SetExplicitMinSize(BSize(minWindowWidth, B_SIZE_UNSET));
|
||||||
|
|
||||||
|
ResizeToPreferred();
|
||||||
|
|
||||||
|
BWindow* parent = dynamic_cast<BWindow*>(BLooper::LooperForThread(
|
||||||
|
find_thread(NULL)));
|
||||||
|
const BRect frame = parent != NULL ? parent->Frame()
|
||||||
|
: BScreen(this).Frame();
|
||||||
|
|
||||||
|
MoveTo(static_cast<BWindow*>(this)->AlertPosition(frame));
|
||||||
|
// Hidden by BAlert::AlertPosition()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - TAlertView
|
// #pragma mark - TAlertView
|
||||||
|
|
||||||
|
|
||||||
TAlertView::TAlertView(BRect frame)
|
TAlertView::TAlertView()
|
||||||
: BView(frame, "TAlertView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
|
:
|
||||||
fIconBitmap(NULL)
|
BView("TAlertView", B_WILL_DRAW),
|
||||||
|
fIconBitmap(NULL)
|
||||||
{
|
{
|
||||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TAlertView::TAlertView(BMessage* archive)
|
TAlertView::TAlertView(BMessage* archive)
|
||||||
: BView(archive),
|
:
|
||||||
fIconBitmap(NULL)
|
BView(archive),
|
||||||
|
fIconBitmap(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -772,10 +744,37 @@ TAlertView::Archive(BMessage* archive, bool deep) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TAlertView::GetPreferredSize(float* _width, float* _height)
|
||||||
|
{
|
||||||
|
int32 scale = icon_layout_scale();
|
||||||
|
|
||||||
|
if (_width != NULL) {
|
||||||
|
if (fIconBitmap != NULL)
|
||||||
|
*_width = 18 * scale + fIconBitmap->Bounds().Width();
|
||||||
|
else
|
||||||
|
*_width = 0;
|
||||||
|
}
|
||||||
|
if (_height != NULL) {
|
||||||
|
if (fIconBitmap != NULL)
|
||||||
|
*_height = 6 * scale + fIconBitmap->Bounds().Height();
|
||||||
|
else
|
||||||
|
*_height = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BSize
|
||||||
|
TAlertView::MaxSize()
|
||||||
|
{
|
||||||
|
return BSize(MinSize().width, B_SIZE_UNLIMITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TAlertView::Draw(BRect updateRect)
|
TAlertView::Draw(BRect updateRect)
|
||||||
{
|
{
|
||||||
if (!fIconBitmap)
|
if (fIconBitmap == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Here's the fun stuff
|
// Here's the fun stuff
|
||||||
@@ -789,11 +788,9 @@ TAlertView::Draw(BRect updateRect)
|
|||||||
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
||||||
DrawBitmapAsync(fIconBitmap, BPoint(18 * iconLayoutScale,
|
DrawBitmapAsync(fIconBitmap, BPoint(18 * iconLayoutScale,
|
||||||
6 * iconLayoutScale));
|
6 * iconLayoutScale));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
// #pragma mark - _BAlertFilter_
|
// #pragma mark - _BAlertFilter_
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user