218 lines
4.6 KiB
C++
218 lines
4.6 KiB
C++
/*
|
|
* Copyright 2003-2010 Haiku, Inc. All rights reserved.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Jérôme Duval
|
|
*/
|
|
|
|
|
|
#include "PasswordAlert.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <File.h>
|
|
#include <FindDirectory.h>
|
|
#include <IconUtils.h>
|
|
#include <Path.h>
|
|
#include <Resources.h>
|
|
#include <Screen.h>
|
|
#include <View.h>
|
|
|
|
|
|
static const int kWindowIconOffset = 27;
|
|
static const int kIconStripeWidth = 30;
|
|
static const int kTextIconOffset = kWindowIconOffset + kIconStripeWidth - 2;
|
|
static const int kTextTopOffset = 6;
|
|
static const int kSemTimeOut = 50000;
|
|
|
|
|
|
class TAlertView : public BView {
|
|
public:
|
|
TAlertView(BRect frame);
|
|
TAlertView(BMessage* archive);
|
|
~TAlertView();
|
|
|
|
virtual void Draw(BRect updateRect);
|
|
|
|
void SetBitmap(BBitmap* Icon) { fIconBitmap = Icon; }
|
|
BBitmap* Bitmap() { return fIconBitmap; }
|
|
|
|
private:
|
|
BBitmap* fIconBitmap;
|
|
};
|
|
|
|
|
|
// #pragma mark - PasswordAlert
|
|
|
|
|
|
PasswordAlert::PasswordAlert(const char* title, const char* text)
|
|
:
|
|
BWindow(BRect(0, 0, 450, 45), title, B_MODAL_WINDOW,
|
|
B_NOT_CLOSABLE | B_NOT_RESIZABLE),
|
|
fTextControl(NULL),
|
|
fAlertSem(-1)
|
|
{
|
|
// Set up the "_master_" view
|
|
TAlertView* masterView = new TAlertView(Bounds());
|
|
masterView->SetBitmap(InitIcon());
|
|
AddChild(masterView);
|
|
|
|
// Set up the text view
|
|
BRect textControlRect(kTextIconOffset, kTextTopOffset,
|
|
Bounds().right - 5, Bounds().bottom);
|
|
|
|
fTextControl = new BTextControl(textControlRect, "_password_", text,
|
|
NULL, new BMessage('pass'), B_FOLLOW_ALL);
|
|
fTextControl->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
|
|
fTextControl->TextView()->HideTyping(true);
|
|
fTextControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
|
|
fTextControl->SetDivider(10 + fTextControl->StringWidth(text));
|
|
|
|
masterView->AddChild(fTextControl);
|
|
|
|
BRect screenFrame = BScreen(B_MAIN_SCREEN_ID).Frame();
|
|
BPoint point;
|
|
point.x = screenFrame.Width() / 2 - Bounds().Width() / 2;
|
|
point.y = screenFrame.Height() / 2 - Bounds().Height() / 2;
|
|
if (screenFrame.Contains(point))
|
|
MoveTo(point);
|
|
|
|
fTextControl->MakeFocus();
|
|
}
|
|
|
|
|
|
PasswordAlert::~PasswordAlert()
|
|
{
|
|
}
|
|
|
|
|
|
BBitmap*
|
|
PasswordAlert::InitIcon()
|
|
{
|
|
// The alert icons are in the app_server resources
|
|
BBitmap* icon = NULL;
|
|
BPath path;
|
|
if (find_directory(B_BEOS_SERVERS_DIRECTORY, &path) == B_OK) {
|
|
path.Append("app_server");
|
|
BFile file;
|
|
if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK) {
|
|
BResources resources;
|
|
if (resources.SetTo(&file) == B_OK) {
|
|
// Which icon are we trying to load?
|
|
const char* iconName = "warn";
|
|
|
|
// Load the raw icon data
|
|
size_t size;
|
|
const void* rawIcon
|
|
= resources.LoadResource(B_VECTOR_ICON_TYPE, iconName,
|
|
&size);
|
|
|
|
if (rawIcon != NULL) {
|
|
// Now build the bitmap
|
|
icon = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32);
|
|
if (BIconUtils::GetVectorIcon((const uint8*)rawIcon, size,
|
|
icon) != B_OK) {
|
|
delete icon;
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return icon;
|
|
}
|
|
|
|
|
|
void
|
|
PasswordAlert::Go(BString& password)
|
|
{
|
|
fAlertSem = create_sem(0, "AlertSem");
|
|
if (fAlertSem < B_OK) {
|
|
Quit();
|
|
return;
|
|
}
|
|
|
|
// Get the originating window, if it exists
|
|
BWindow* window
|
|
= dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
|
|
|
|
Show();
|
|
|
|
// Heavily modified from TextEntryAlert code; the original didn't let the
|
|
// blocked window ever draw.
|
|
if (window != NULL) {
|
|
status_t result;
|
|
for (;;) {
|
|
do {
|
|
result = acquire_sem_etc(fAlertSem, 1, B_RELATIVE_TIMEOUT,
|
|
kSemTimeOut);
|
|
// We've (probably) had our time slice taken away from us
|
|
} while (result == B_INTERRUPTED);
|
|
|
|
if (result == B_BAD_SEM_ID) {
|
|
// Semaphore was finally nuked in MessageReceived
|
|
break;
|
|
}
|
|
window->UpdateIfNeeded();
|
|
}
|
|
} else {
|
|
// No window to update, so just hang out until we're done.
|
|
while (acquire_sem(fAlertSem) == B_INTERRUPTED) {
|
|
;
|
|
}
|
|
}
|
|
|
|
// Have to cache the value since we delete on Quit()
|
|
password = fTextControl->Text();
|
|
if (Lock())
|
|
Quit();
|
|
}
|
|
|
|
|
|
void
|
|
PasswordAlert::MessageReceived(BMessage* msg)
|
|
{
|
|
if (msg->what != 'pass')
|
|
return BWindow::MessageReceived(msg);
|
|
|
|
delete_sem(fAlertSem);
|
|
fAlertSem = -1;
|
|
}
|
|
|
|
|
|
// #pragma mark - TAlertView
|
|
|
|
|
|
TAlertView::TAlertView(BRect frame)
|
|
:
|
|
BView(frame, "TAlertView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
|
|
fIconBitmap(NULL)
|
|
{
|
|
SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
|
|
}
|
|
|
|
|
|
TAlertView::~TAlertView()
|
|
{
|
|
delete fIconBitmap;
|
|
}
|
|
|
|
|
|
void
|
|
TAlertView::Draw(BRect updateRect)
|
|
{
|
|
// Here's the fun stuff
|
|
if (fIconBitmap != NULL) {
|
|
BRect stripeRect = Bounds();
|
|
stripeRect.right = kIconStripeWidth;
|
|
SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
|
|
FillRect(stripeRect);
|
|
|
|
SetDrawingMode(B_OP_ALPHA);
|
|
DrawBitmapAsync(fIconBitmap, BPoint(18, 6));
|
|
SetDrawingMode(B_OP_COPY);
|
|
}
|
|
}
|