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:
+67
-115
@@ -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
|
|
||||||
BAlert(BMessage *data);
|
|
||||||
static BArchivable *Instantiate(BMessage *data);
|
|
||||||
virtual status_t Archive(BMessage *data, bool deep = true) const;
|
|
||||||
|
|
||||||
// BAlert guts
|
|
||||||
void SetShortcut(int32 button_index, char key);
|
|
||||||
char Shortcut(int32 button_index) const;
|
|
||||||
|
|
||||||
int32 Go();
|
// Archiving
|
||||||
status_t Go(BInvoker *invoker);
|
BAlert(BMessage *data);
|
||||||
|
static BArchivable *Instantiate(BMessage *data);
|
||||||
|
virtual status_t Archive(BMessage *data, bool deep = true) const;
|
||||||
|
|
||||||
virtual void MessageReceived(BMessage *an_event);
|
// BAlert guts
|
||||||
virtual void FrameResized(float new_width, float new_height);
|
void SetShortcut(int32 button_index, char key);
|
||||||
BButton *ButtonAt(int32 index) const;
|
char Shortcut(int32 button_index) const;
|
||||||
BTextView *TextView() const;
|
|
||||||
|
|
||||||
virtual BHandler *ResolveSpecifier(BMessage *msg,
|
int32 Go();
|
||||||
int32 index,
|
status_t Go(BInvoker *invoker);
|
||||||
BMessage *specifier,
|
|
||||||
int32 form,
|
|
||||||
const char *property);
|
|
||||||
virtual status_t GetSupportedSuites(BMessage *data);
|
|
||||||
|
|
||||||
virtual void DispatchMessage(BMessage *msg, BHandler *handler);
|
virtual void MessageReceived(BMessage *an_event);
|
||||||
virtual void Quit();
|
virtual void FrameResized(float new_width, float new_height);
|
||||||
virtual bool QuitRequested();
|
BButton* ButtonAt(int32 index) const;
|
||||||
|
BTextView* TextView() const;
|
||||||
|
|
||||||
static BPoint AlertPosition(float width, float height);
|
virtual BHandler* ResolveSpecifier(BMessage* message, int32 index,
|
||||||
|
BMessage* specifier, int32 form,
|
||||||
|
const char* property);
|
||||||
|
virtual status_t GetSupportedSuites(BMessage *data);
|
||||||
|
|
||||||
// Private or reserved ---------------------------------------------------------
|
virtual void DispatchMessage(BMessage* message, BHandler* handler);
|
||||||
virtual status_t Perform(perform_code d, void *arg);
|
virtual void Quit();
|
||||||
|
virtual bool QuitRequested();
|
||||||
|
|
||||||
private:
|
static BPoint AlertPosition(float width, float height);
|
||||||
friend class _BAlertFilter_;
|
|
||||||
|
|
||||||
virtual void _ReservedAlert1();
|
virtual status_t Perform(perform_code d, void *arg);
|
||||||
virtual void _ReservedAlert2();
|
|
||||||
virtual void _ReservedAlert3();
|
|
||||||
|
|
||||||
void InitObject(const char *text,
|
private:
|
||||||
const char *button1,
|
friend class _BAlertFilter_;
|
||||||
const char *button2 = NULL,
|
|
||||||
const char *button3 = NULL,
|
|
||||||
button_width width = B_WIDTH_AS_USUAL,
|
|
||||||
button_spacing spacing = B_EVEN_SPACING,
|
|
||||||
alert_type type = B_INFO_ALERT);
|
|
||||||
BBitmap *InitIcon();
|
|
||||||
|
|
||||||
sem_id fAlertSem;
|
virtual void _ReservedAlert1();
|
||||||
int32 fAlertVal;
|
virtual void _ReservedAlert2();
|
||||||
BButton *fButtons[3];
|
virtual void _ReservedAlert3();
|
||||||
BTextView *fTextView;
|
|
||||||
char fKeys[3];
|
void _InitObject(const char* text, const char* button1,
|
||||||
alert_type fMsgType;
|
const char* button2 = NULL,
|
||||||
button_width fButtonWidth;
|
const char* button3 = NULL,
|
||||||
BInvoker *fInvoker;
|
button_width width = B_WIDTH_AS_USUAL,
|
||||||
uint32 _reserved[4];
|
button_spacing spacing = B_EVEN_SPACING,
|
||||||
|
alert_type type = B_INFO_ALERT);
|
||||||
|
BBitmap* _InitIcon();
|
||||||
|
BButton* _CreateButton(int32 which, const char* label);
|
||||||
|
|
||||||
|
sem_id fAlertSem;
|
||||||
|
int32 fAlertValue;
|
||||||
|
BButton* fButtons[3];
|
||||||
|
BTextView* fTextView;
|
||||||
|
char fKeys[3];
|
||||||
|
alert_type fMsgType;
|
||||||
|
button_width fButtonWidth;
|
||||||
|
BInvoker* fInvoker;
|
||||||
|
uint32 _reserved[4];
|
||||||
};
|
};
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#endif // _ALERT_H
|
#endif // _ALERT_H
|
||||||
|
|
||||||
/*
|
|
||||||
* $Log $
|
|
||||||
*
|
|
||||||
* $Id $
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|||||||
+147
-191
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user