[haiku-commits] haiku: hrev49481 - src/kits/interface headers/os/interface

  • From: axeld@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 30 Jul 2015 19:50:03 +0200 (CEST)

hrev49481 adds 4 changesets to branch 'master'
old head: 7bdc7eec03d12377f6928b49887697a8f9fbc9dc
new head: 7b0ff5c6e63390406acaffa0a9ebb68334af8485
overview:
http://cgit.haiku-os.org/haiku/log/?qt=range&q=7b0ff5c6e633+%5E7bdc7eec03d1

----------------------------------------------------------------------------

99b4affab6fb: Added BWindow::ResizeToPreferred().

* B_AUTO_UPDATE_SIZE_LIMITS only really makes sense for resizable
windows, and it only sets the minimum/maximum window size.
* ResizeToPreferred() resizes the window to its preferred size, and
also supports height-for-width layouts.

fd3e3e7bfb6e: BTwoDimensionalLayout: Removed duplicated code.

* Probably some refactoring leftovers.

e27a53b231ad: BTextView: implemented height-for-width when read-only.

* This is not an ideal implementation, as it actually relayouts
the text view. IOW it's actually wrong, but it does seem to
work without any issues.

7b0ff5c6e633: 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.

[ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

6 files changed, 424 insertions(+), 381 deletions(-)
headers/os/interface/Alert.h | 153 +++---
headers/os/interface/Window.h | 1 +
src/kits/interface/Alert.cpp | 595 ++++++++++++------------
src/kits/interface/TextView.cpp | 25 +-
src/kits/interface/TwoDimensionalLayout.cpp | 9 -
src/kits/interface/Window.cpp | 22 +-

############################################################################

Commit: 99b4affab6fbabb0917abd76cb9a08b55a128e56
URL: http://cgit.haiku-os.org/haiku/commit/?id=99b4affab6fb
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Jul 30 16:27:13 2015 UTC

Added BWindow::ResizeToPreferred().

* B_AUTO_UPDATE_SIZE_LIMITS only really makes sense for resizable
windows, and it only sets the minimum/maximum window size.
* ResizeToPreferred() resizes the window to its preferred size, and
also supports height-for-width layouts.

----------------------------------------------------------------------------

diff --git a/headers/os/interface/Window.h b/headers/os/interface/Window.h
index b4df13e..dbf0431 100644
--- a/headers/os/interface/Window.h
+++ b/headers/os/interface/Window.h
@@ -165,6 +165,7 @@ public:
void MoveTo(float x, float
y);
void ResizeBy(float dx,
float dy);
void ResizeTo(float width,
float height);
+ void ResizeToPreferred();

void CenterIn(const BRect&
rect);
void CenterOnScreen();
diff --git a/src/kits/interface/Window.cpp b/src/kits/interface/Window.cpp
index bcd07de..141e489 100644
--- a/src/kits/interface/Window.cpp
+++ b/src/kits/interface/Window.cpp
@@ -2521,7 +2521,26 @@ BWindow::ResizeTo(float width, float height)
}


-// Center the window in the passed in rect.
+void
+BWindow::ResizeToPreferred()
+{
+ Layout(false);
+
+ float width = fTopView->PreferredSize().width;
+ width = std::min(width, fTopView->MaxSize().width);
+ width = std::max(width, fTopView->MinSize().width);
+
+ float height = fTopView->PreferredSize().height;
+ height = std::min(width, fTopView->MaxSize().height);
+ height = std::max(width, fTopView->MinSize().height);
+
+ if (GetLayout()->HasHeightForWidth())
+ GetLayout()->GetHeightForWidth(width, NULL, NULL, &height);
+
+ ResizeTo(width, height);
+}
+
+
void
BWindow::CenterIn(const BRect& rect)
{
@@ -2534,7 +2553,6 @@ BWindow::CenterIn(const BRect& rect)
}


-// Centers the window on the screen the window is currently on.
void
BWindow::CenterOnScreen()
{

############################################################################

Commit: fd3e3e7bfb6e31cced1a98fc6a24c45f2feeba93
URL: http://cgit.haiku-os.org/haiku/commit/?id=fd3e3e7bfb6e
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Jul 30 16:29:27 2015 UTC

BTwoDimensionalLayout: Removed duplicated code.

* Probably some refactoring leftovers.

----------------------------------------------------------------------------

diff --git a/src/kits/interface/TwoDimensionalLayout.cpp
b/src/kits/interface/TwoDimensionalLayout.cpp
index a37f67a..ffb93b0 100644
--- a/src/kits/interface/TwoDimensionalLayout.cpp
+++ b/src/kits/interface/TwoDimensionalLayout.cpp
@@ -21,8 +21,6 @@
#include "CollapsingLayouter.h"


-
-
// Some words of explanation:
//
// This class is the base class for BLayouts that organize their items
@@ -923,13 +921,6 @@
BTwoDimensionalLayout::VerticalCompoundLayouter::InternalGetHeightForWidth(
}

updateCachedInfo = true;
-
- // get the height for width info
- fCachedMinHeightForWidth = fHeightForWidthLayouter->MinSize();
- fCachedMaxHeightForWidth = fHeightForWidthLayouter->MaxSize();
- fCachedPreferredHeightForWidth
- = fHeightForWidthLayouter->PreferredSize();
-
} else if (localLayouter->HasHeightForWidth()) {
// There is a height for width layouter and it has been
initialized
// in the current layout context. So we just add the height for
width

############################################################################

Commit: e27a53b231ad97ed357932f329ad975bccdafcd2
URL: http://cgit.haiku-os.org/haiku/commit/?id=e27a53b231ad
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Thu Jul 30 16:33:24 2015 UTC

BTextView: implemented height-for-width when read-only.

* This is not an ideal implementation, as it actually relayouts
the text view. IOW it's actually wrong, but it does seem to
work without any issues.

----------------------------------------------------------------------------

diff --git a/src/kits/interface/TextView.cpp b/src/kits/interface/TextView.cpp
index bdf7fa6..f5625d9 100644
--- a/src/kits/interface/TextView.cpp
+++ b/src/kits/interface/TextView.cpp
@@ -2577,9 +2577,11 @@ BTextView::PreferredSize()
bool
BTextView::HasHeightForWidth()
{
- // ToDo: When not editable and not embedded in a scroll view, we should
- // assume that all text is supposed to be visible.
- return BView::HasHeightForWidth();
+ if (IsEditable())
+ return BView::HasHeightForWidth();
+
+ // When not editable, we assume that all text is supposed to be visible.
+ return true;
}


@@ -2587,8 +2589,21 @@ void
BTextView::GetHeightForWidth(float width, float* min, float* max,
float* preferred)
{
- // ToDo: See above and implement.
- BView::GetHeightForWidth(width, min, max, preferred);
+ if (IsEditable()) {
+ BView::GetHeightForWidth(width, min, max, preferred);
+ return;
+ }
+
+ // TODO: don't change the actual text rect!
+ fTextRect.right = fTextRect.left + width;
+ _Refresh(0, TextLength(), false);
+
+ if (min != NULL)
+ *min = fTextRect.Height();
+ if (max != NULL)
+ *max = fTextRect.Height();
+ if (preferred != NULL)
+ *preferred = fTextRect.Height();
}



############################################################################

Revision: hrev49481
Commit: 7b0ff5c6e63390406acaffa0a9ebb68334af8485
URL: http://cgit.haiku-os.org/haiku/commit/?id=7b0ff5c6e633
Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date: Wed Jul 29 16:13:51 2015 UTC

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.

----------------------------------------------------------------------------

diff --git a/headers/os/interface/Alert.h b/headers/os/interface/Alert.h
index 3020b41..3ac2441 100644
--- a/headers/os/interface/Alert.h
+++ b/headers/os/interface/Alert.h
@@ -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.
*/
#ifndef _ALERT_H
#define _ALERT_H


+#include <vector>
+
#include <Window.h>


@@ -26,78 +28,97 @@ enum button_spacing {

class BBitmap;
class BButton;
+class BGroupLayout;
class BInvoker;
class BTextView;
+class TAlertView;
+

class BAlert : public BWindow {
public:
- BAlert(const char*
title, const char* text,
- const char*
button1, const char* button2 = NULL,
- const char*
button3 = NULL,
- button_width
width = B_WIDTH_AS_USUAL,
- alert_type type
= B_INFO_ALERT);
- BAlert(const char*
title, const char* text,
- const char*
button1, const char* button2,
- const char*
button3, button_width width,
- 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();
- status_t Go(BInvoker* invoker);
-
- virtual void MessageReceived(BMessage* message);
- virtual void FrameResized(float new_width, float
new_height);
- BButton* ButtonAt(int32 index) const;
- BTextView* TextView() const;
-
- virtual BHandler* ResolveSpecifier(BMessage* message,
int32 index,
- BMessage*
specifier, int32 what,
- const char*
property);
- virtual status_t GetSupportedSuites(BMessage* data);
-
- virtual void DispatchMessage(BMessage* message,
BHandler* handler);
- virtual void Quit();
- virtual bool QuitRequested();
-
- static BPoint AlertPosition(float width, float
height);
-
- virtual status_t Perform(perform_code d, void* arg);
+ BAlert();
+ BAlert(const
char* title, const char* text,
+ const
char* button1,
+ const
char* button2 = NULL,
+ const
char* button3 = NULL,
+
button_width width = B_WIDTH_AS_USUAL,
+
alert_type type = B_INFO_ALERT);
+ BAlert(const
char* title, const char* text,
+ const
char* button1, const char* button2,
+ const
char* button3, button_width width,
+
button_spacing spacing,
+
alert_type type = B_INFO_ALERT);
+
BAlert(BMessage* data);
+ virtual ~BAlert();
+
+ // Archiving
+ static BArchivable* Instantiate(BMessage* data);
+ virtual status_t Archive(BMessage* data, bool
deep = true) const;
+
+ // BAlert guts
+ alert_type Type() 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);
+
+ void SetShortcut(int32
buttonIndex, char key);
+ char Shortcut(int32
buttonIndex) const;
+
+ int32 Go();
+ status_t Go(BInvoker* invoker);
+
+ virtual void MessageReceived(BMessage*
message);
+ virtual void FrameResized(float newWidth,
float newHeight);
+
+ void AddButton(const char*
label, char key = 0);
+ int32 CountButtons() const;
+ BButton* ButtonAt(int32 index)
const;
+
+ BTextView* TextView() const;
+
+ 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:
- friend class _BAlertFilter_;
-
- virtual void _ReservedAlert1();
- virtual void _ReservedAlert2();
- virtual void _ReservedAlert3();
-
- void _InitObject(const char* text,
const char* button1,
- 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();
- 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];
+ virtual void _ReservedAlert1();
+ virtual void _ReservedAlert2();
+ virtual void _ReservedAlert3();
+
+ void _Init(const char* text,
const char* button1,
+ const
char* button2, const char* button3,
+
button_width width, button_spacing spacing,
+
alert_type type);
+ BBitmap* _CreateTypeIcon();
+ BButton* _CreateButton(int32
which, const char* label);
+ void _Prepare();
+
+private:
+ sem_id fAlertSem;
+ int32 fAlertValue;
+ TAlertView* fIconView;
+ BTextView* fTextView;
+ BGroupLayout* fButtonLayout;
+ std::vector<BButton*> fButtons;
+ std::vector<char> fKeys;
+ uint8 fType;
+ uint8 fButtonSpacing;
+ uint8 fButtonWidth;
+ BInvoker* fInvoker;
+ uint32 _reserved[1];
};

+
#endif // _ALERT_H
diff --git a/src/kits/interface/Alert.cpp b/src/kits/interface/Alert.cpp
index 19d093a..8c373fd 100644
--- a/src/kits/interface/Alert.cpp
+++ b/src/kits/interface/Alert.cpp
@@ -9,31 +9,28 @@
*/


-// BAlert displays a modal alert window.
+//! BAlert displays a modal alert window.


+#include <Alert.h>
+
#include <new>
+
#include <stdio.h>
-#include <string.h>

-#include <Alert.h>
-#include <Autolock.h>
-#include <Beep.h>
#include <Bitmap.h>
#include <Button.h>
-#include <File.h>
+#include <ControlLook.h>
#include <FindDirectory.h>
-#include <Font.h>
#include <IconUtils.h>
-#include <Invoker.h>
-#include <Looper.h>
-#include <Message.h>
+#include <LayoutBuilder.h>
+#include <MenuField.h>
#include <MessageFilter.h>
#include <Path.h>
#include <Resources.h>
#include <Screen.h>
-#include <TextView.h>
-#include <View.h>
+#include <String.h>
+#include <Window.h>

#include <binary_compatibility/Interface.h>

@@ -42,111 +39,102 @@
#ifdef DEBUG_ALERT
# define FTRACE(x) fprintf(x)
#else
-# define FTRACE(x) /* nothing */
+# define FTRACE(x) ;
#endif

-// Default size of the Alert window.
-#define DEFAULT_RECT BRect(0, 0, 310, 75)
-#define max(LHS, RHS) ((LHS) > (RHS) ? (LHS) : (RHS))
+
+class TAlertView : public BView {
+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 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 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 kWindowOffsetMinWidth = 335;

-static const int kIconStripeWidth = 30;
-
-static const int kTextButtonOffset = 10;

static inline int32
icon_layout_scale()
{
-#ifdef __HAIKU__
return max_c(1, ((int32)be_plain_font->Size() + 15) / 16);
-#endif
- return 1;
}


-class TAlertView : public BView {
- 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);
+// #pragma mark -

- // 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,
const char *button2, const char *button3, button_width width,
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)
{
- _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,
const char *button2, const char *button3, button_width width,
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)
{
- _InitObject(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);
+ _Init(text, button1, button2, button3, width, spacing, type);
}


BAlert::BAlert(BMessage* data)
- : BWindow(data)
+ :
+ BWindow(data)
{
fInvoker = NULL;
fAlertSem = -1;
@@ -154,20 +142,12 @@ BAlert::BAlert(BMessage* data)

fTextView = (BTextView*)FindView("_tv_");

- fButtons[0] = (BButton*)FindView("_b0_");
- fButtons[1] = (BButton*)FindView("_b1_");
- 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]);
+ // TODO: window loses default button on dearchive!
+ // TODO: ButtonAt() doesn't work afterwards (also affects shortcuts)

TAlertView* view = (TAlertView*)FindView("_master_");
if (view)
- view->SetBitmap(_InitIcon());
+ view->SetBitmap(_CreateTypeIcon());

// Get keys
char key;
@@ -176,16 +156,15 @@ BAlert::BAlert(BMessage* data)
fKeys[i] = key;
}

- int32 temp;
- // Get alert type
- if (data->FindInt32("_atype", &temp) == B_OK)
- fMsgType = (alert_type)temp;
+ AddCommonFilter(new(std::nothrow) _BAlertFilter_(this));
+}

- // Get button width
- if (data->FindInt32("_but_width", &temp) == B_OK)
- fButtonWidth = (button_width)temp;

- AddCommonFilter(new(std::nothrow) _BAlertFilter_(this));
+BAlert::~BAlert()
+{
+ // Probably not necessary, but it makes me feel better.
+ if (fAlertSem >= B_OK)
+ delete_sem(fAlertSem);
}


@@ -210,7 +189,7 @@ BAlert::Archive(BMessage* data, bool deep) const

// Stow the alert type
if (ret == B_OK)
- ret = data->AddInt32("_atype", fMsgType);
+ ret = data->AddInt32("_atype", fType);

// Stow the button width
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
BAlert::SetShortcut(int32 index, char key)
{
- if (index >= 0 && index < 3)
+ if (index >= 0 && (size_t)index < fKeys.size())
fKeys[index] = key;
}

@@ -243,7 +264,8 @@ BAlert::SetShortcut(int32 index, char key)
char
BAlert::Shortcut(int32 index) const
{
- if (index >= 0 && index < 3)
+
+ if (index >= 0 && (size_t)index < fKeys.size())
return fKeys[index];

return 0;
@@ -254,29 +276,28 @@ int32
BAlert::Go()
{
fAlertSem = create_sem(0, "AlertSem");
- if (fAlertSem < B_OK) {
+ if (fAlertSem < 0) {
Quit();
return -1;
}

// Get the originating window, if it exists
- BWindow* window =
-
dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
+ BWindow* window = dynamic_cast<BWindow*>(
+ BLooper::LooperForThread(find_thread(NULL)));

+ _Prepare();
Show();

- // Heavily modified from TextEntryAlert code; the original didn't let
the
- // blocked window ever draw.
- if (window) {
- status_t err;
+ if (window != NULL) {
+ status_t status;
for (;;) {
do {
- err = acquire_sem_etc(fAlertSem, 1,
B_RELATIVE_TIMEOUT,
-
kSemTimeOut);
+ status = acquire_sem_etc(fAlertSem, 1,
B_RELATIVE_TIMEOUT,
+ kSemTimeOut);
// 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
break;
}
@@ -301,19 +322,20 @@ status_t
BAlert::Go(BInvoker* invoker)
{
fInvoker = invoker;
+ _Prepare();
Show();
return B_OK;
}


void
-BAlert::MessageReceived(BMessage* message)
+BAlert::MessageReceived(BMessage* msg)
{
- if (message->what != kAlertButtonMsg)
- return BWindow::MessageReceived(message);
+ if (msg->what != kAlertButtonMsg)
+ return BWindow::MessageReceived(msg);

int32 which;
- if (message->FindInt32("which", &which) == B_OK) {
+ if (msg->FindInt32("which", &which) == B_OK) {
if (fAlertSem < B_OK) {
// Semaphore hasn't been created; we're running
asynchronous
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*
BAlert::ButtonAt(int32 index) const
{
- if (index >= 0 && index < 3)
+ if (index >= 0 && (size_t)index < fButtons.size())
return fButtons[index];

return NULL;
@@ -364,11 +407,10 @@ BAlert::TextView() const


BHandler*
-BAlert::ResolveSpecifier(BMessage* message, int32 index,
- BMessage* specifier, int32 what, const char* property)
+BAlert::ResolveSpecifier(BMessage* msg, int32 index,
+ BMessage* specifier, int32 form, const char* property)
{
- return BWindow::ResolveSpecifier(message, index, specifier, what,
- property);
+ return BWindow::ResolveSpecifier(msg, index, specifier, form, 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
BAlert::AlertPosition(float width, float height)
{
@@ -429,11 +471,9 @@ BAlert::Perform(perform_code code, void* _data)
{
switch (code) {
case PERFORM_CODE_SET_LAYOUT:
- {
perform_data_set_layout* data =
(perform_data_set_layout*)_data;
BAlert::SetLayout(data->layout);
return B_OK;
-}
}

return BWindow::Perform(code, _data);
@@ -446,185 +486,79 @@ void BAlert::_ReservedAlert3() {}


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,
alert_type type)
{
- fInvoker = NULL;
- 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;
+ fIconView = new TAlertView();

+ fTextView = new BTextView("_tv_");
fTextView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
rgb_color textColor = ui_color(B_PANEL_TEXT_COLOR);
fTextView->SetFontAndColor(be_plain_font, B_FONT_ALL, &textColor);
- fTextView->SetText(text, strlen(text));
fTextView->MakeEditable(false);
fTextView->MakeSelectable(false);
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
- 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);
+ fButtonLayout = new BGroupLayout(B_HORIZONTAL);

- 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
- // horizontally in the parent window's frame or, if unavailable, the
- // screen frame.
- BWindow* parent =
-
dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
- const BRect frame = parent != NULL ? parent->Frame() :
BScreen(this).Frame();
- MoveTo(dynamic_cast<BWindow*>(this)->AlertPosition(frame));
+ BLayoutBuilder::Group<>(this, B_HORIZONTAL, 0)
+ .Add(fIconView)
+ .AddGroup(B_VERTICAL)
+ .SetInsets(B_USE_DEFAULT_SPACING)
+ .Add(fTextView)
+ .AddGroup(B_HORIZONTAL, 0)
+ .AddGlue()
+ .Add(fButtonLayout);
+
+ AddButton(button0);
+ AddButton(button1);
+ AddButton(button2);
}


BBitmap*
-BAlert::_InitIcon()
+BAlert::_CreateTypeIcon()
{
- // Save the desired alert type and set it to "empty" until
- // loading the icon was successful
- alert_type alertType = fMsgType;
- fMsgType = B_EMPTY_ALERT;
+ if (Type() == B_EMPTY_ALERT)
+ return NULL;

- // 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;
BPath path;
status_t status = find_directory(B_BEOS_SERVERS_DIRECTORY, &path);
- if (status < B_OK) {
- FTRACE((stderr, "BAlert::_InitIcon() - find_directory failed:
%s\n",
- strerror(status)));
+ if (status != B_OK) {
+ FTRACE((stderr, "BAlert::_CreateTypeIcon() - find_directory "
+ "failed: %s\n", strerror(status)));
return NULL;
}

path.Append("app_server");
BFile file;
status = file.SetTo(path.Path(), B_READ_ONLY);
- if (status < B_OK) {
- FTRACE((stderr, "BAlert::_InitIcon() - BFile init failed: %s\n",
+ if (status != B_OK) {
+ FTRACE((stderr, "BAlert::_CreateTypeIcon() - BFile init failed:
%s\n",
strerror(status)));
return NULL;
}

BResources resources;
status = resources.SetTo(&file);
- if (status < B_OK) {
- FTRACE((stderr, "BAlert::_InitIcon() - BResources init failed:
%s\n",
- strerror(status)));
+ if (status != B_OK) {
+ FTRACE((stderr, "BAlert::_CreateTypeIcon() - BResources init "
+ "failed: %s\n", strerror(status)));
return NULL;
}

// Which icon are we trying to load?
- const char* iconName = ""; // Don't want any seg faults
- switch (alertType) {
+ const char* iconName;
+ switch (fType) {
case B_INFO_ALERT:
iconName = "info";
break;
@@ -649,7 +583,7 @@ BAlert::_InitIcon()
icon = new(std::nothrow) BBitmap(BRect(0, 0, iconSize - 1, iconSize -
1),
0, B_RGBA32);
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;
return NULL;
}
@@ -658,39 +592,28 @@ BAlert::_InitIcon()
size_t size = 0;
const uint8* rawIcon;

-#ifdef __HAIKU__
// Try to load vector icon
rawIcon = (const uint8*)resources.LoadResource(B_VECTOR_ICON_TYPE,
iconName, &size);
if (rawIcon != NULL
&& BIconUtils::GetVectorIcon(rawIcon, size, icon) == B_OK) {
- // We have an icon, restore the saved alert type
- fMsgType = alertType;
return icon;
}
-#endif

// Fall back to bitmap icon
rawIcon = (const uint8*)resources.LoadResource(B_LARGE_ICON_TYPE,
iconName, &size);
if (rawIcon == NULL) {
- FTRACE((stderr, "BAlert::_InitIcon() - Icon resource not
found\n"));
+ FTRACE((stderr, "BAlert::_CreateTypeIcon() - Icon resource not
found\n"));
delete icon;
return NULL;
}

// Handle color space conversion
-#ifdef __HAIKU__
if (icon->ColorSpace() != B_CMAP8) {
BIconUtils::ConvertFromCMAP8(rawIcon, iconSize, iconSize,
iconSize, icon);
}
-#else
- icon->SetBits(rawIcon, iconSize, 0, B_CMAP8);
-#endif
-
- // We have an icon, restore the saved alert type
- fMsgType = alertType;

return icon;
}
@@ -705,46 +628,95 @@ BAlert::_CreateButton(int32 which, const char* label)

message->AddInt32("which", which);

- BRect rect;
- rect.top = Bounds().bottom - kBottomOffset;
- rect.bottom = rect.top;
-
char name[32];
snprintf(name, sizeof(name), "_b%" B_PRId32 "_", which);

- BButton* button = new(std::nothrow) BButton(rect, name, label, message,
- B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
- if (button == NULL)
- return NULL;
+ return new(std::nothrow) BButton(name, label, message);
+}
+
+
+/*! 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;

- float width, height;
- button->GetPreferredSize(&width, &height);
+ if (fIconView->Bitmap() == NULL)
+ fIconView->SetBitmap(_CreateTypeIcon());

if (fButtonWidth == B_WIDTH_AS_USUAL) {
- float fontFactor = be_plain_font->Size() / 11.0f;
- width = max_c(width, kButtonUsualWidth * fontFactor);
+ float usualWidth = 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);
- button->MoveBy(0.0f, -height);
- return button;
+ if (fButtonSpacing == B_OFFSET_SPACING && CountButtons() > 1) {
+ // Insert some strut
+ 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


-TAlertView::TAlertView(BRect frame)
- : BView(frame, "TAlertView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
- fIconBitmap(NULL)
+TAlertView::TAlertView()
+ :
+ BView("TAlertView", B_WILL_DRAW),
+ fIconBitmap(NULL)
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
}


TAlertView::TAlertView(BMessage* archive)
- : BView(archive),
- fIconBitmap(NULL)
+ :
+ BView(archive),
+ fIconBitmap(NULL)
{
}

@@ -773,9 +745,36 @@ 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
TAlertView::Draw(BRect updateRect)
{
- if (!fIconBitmap)
+ if (fIconBitmap == NULL)
return;

// Here's the fun stuff
@@ -789,11 +788,9 @@ TAlertView::Draw(BRect updateRect)
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
DrawBitmapAsync(fIconBitmap, BPoint(18 * iconLayoutScale,
6 * iconLayoutScale));
-
}


-//------------------------------------------------------------------------------
// #pragma mark - _BAlertFilter_




Other related posts: