1/* 2 * Copyright 2003-2010 Haiku Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * J��r��me Duval 7 */ 8 9 10#include "PasswordAlert.h" 11 12#include <string.h> 13 14#include <File.h> 15#include <FindDirectory.h> 16#include <IconUtils.h> 17#include <Path.h> 18#include <Resources.h> 19#include <Screen.h> 20#include <View.h> 21 22 23static const int kWindowIconOffset = 27; 24static const int kIconStripeWidth = 30; 25static const int kTextIconOffset = kWindowIconOffset + kIconStripeWidth - 2; 26static const int kTextTopOffset = 6; 27static const int kSemTimeOut = 50000; 28 29 30class TAlertView : public BView { 31public: 32 TAlertView(BRect frame); 33 TAlertView(BMessage* archive); 34 ~TAlertView(); 35 36 virtual void Draw(BRect updateRect); 37 38 void SetBitmap(BBitmap* Icon) { fIconBitmap = Icon; } 39 BBitmap* Bitmap() { return fIconBitmap; } 40 41private: 42 BBitmap* fIconBitmap; 43}; 44 45 46PasswordAlert::PasswordAlert(const char* title, const char* text) 47 : 48 BWindow(BRect(0, 0, 450, 45), title, B_MODAL_WINDOW, B_NOT_CLOSABLE | B_NOT_RESIZABLE), 49 fTextControl(NULL), 50 fAlertSem(-1) 51{ 52 // Set up the "_master_" view 53 TAlertView* masterView = new TAlertView(Bounds()); 54 masterView->SetBitmap(InitIcon()); 55 AddChild(masterView); 56 57 // Set up the text view 58 BRect textControlRect(kTextIconOffset, kTextTopOffset, 59 Bounds().right - 5, Bounds().bottom); 60 61 fTextControl = new BTextControl(textControlRect, "_password_", text, NULL, new BMessage('pass'), 62 B_FOLLOW_ALL); 63 fTextControl->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 64 fTextControl->TextView()->HideTyping(true); 65 fTextControl->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT); 66 fTextControl->SetDivider(10 + fTextControl->StringWidth(text)); 67 68 masterView->AddChild(fTextControl); 69 70 BRect screenFrame = BScreen(B_MAIN_SCREEN_ID).Frame(); 71 BPoint pt; 72 pt.x = screenFrame.Width() / 2 - Bounds().Width() / 2; 73 pt.y = screenFrame.Height() / 2 - Bounds().Height() / 2; 74 75 if (screenFrame.Contains(pt)) 76 MoveTo(pt); 77 78 fTextControl->MakeFocus(); 79} 80 81 82PasswordAlert::~PasswordAlert() 83{ 84} 85 86 87BBitmap* 88PasswordAlert::InitIcon() 89{ 90 // The alert icons are in the app_server resources 91 BBitmap* icon = NULL; 92 BPath path; 93 if (find_directory(B_BEOS_SERVERS_DIRECTORY, &path) == B_OK) { 94 path.Append("app_server"); 95 BFile file; 96 if (file.SetTo(path.Path(), B_READ_ONLY) == B_OK) { 97 BResources resources; 98 if (resources.SetTo(&file) == B_OK) { 99 // Which icon are we trying to load? 100 const char* iconName = "warn"; 101 102 // Load the raw icon data 103 size_t size; 104 const void* rawIcon = 105 resources.LoadResource(B_VECTOR_ICON_TYPE, iconName, &size); 106 107 if (rawIcon != NULL) { 108 // Now build the bitmap 109 icon = new BBitmap(BRect(0, 0, 31, 31), B_RGBA32); 110 if (BIconUtils::GetVectorIcon((const uint8*)rawIcon, size, 111 icon) != B_OK) { 112 delete icon; 113 return NULL; 114 } 115 } 116 } 117 } 118 } 119 120 return icon; 121} 122 123 124void 125PasswordAlert::Go(BString &password) 126{ 127 fAlertSem = create_sem(0, "AlertSem"); 128 if (fAlertSem < B_OK) { 129 Quit(); 130 return; 131 } 132 133 // Get the originating window, if it exists 134 BWindow* window = 135 dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL))); 136 137 Show(); 138 139 // Heavily modified from TextEntryAlert code; the original didn't let the 140 // blocked window ever draw. 141 if (window) { 142 status_t err; 143 for (;;) { 144 do { 145 err = acquire_sem_etc(fAlertSem, 1, B_RELATIVE_TIMEOUT, 146 kSemTimeOut); 147 // We've (probably) had our time slice taken away from us 148 } while (err == B_INTERRUPTED); 149 150 if (err == B_BAD_SEM_ID) { 151 // Semaphore was finally nuked in MessageReceived 152 break; 153 } 154 window->UpdateIfNeeded(); 155 } 156 } else { 157 // No window to update, so just hang out until we're done. 158 while (acquire_sem(fAlertSem) == B_INTERRUPTED) { 159 } 160 } 161 162 // Have to cache the value since we delete on Quit() 163 password = fTextControl->Text(); 164 if (Lock()) 165 Quit(); 166} 167 168 169void 170PasswordAlert::MessageReceived(BMessage* msg) 171{ 172 if (msg->what != 'pass') 173 return BWindow::MessageReceived(msg); 174 175 delete_sem(fAlertSem); 176 fAlertSem = -1; 177} 178 179 180// #pragma mark - TAlertView 181 182 183TAlertView::TAlertView(BRect frame) 184 : 185 BView(frame, "TAlertView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW), 186 fIconBitmap(NULL) 187{ 188 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 189} 190 191 192TAlertView::~TAlertView() 193{ 194 delete fIconBitmap; 195} 196 197 198void 199TAlertView::Draw(BRect updateRect) 200{ 201 // Here's the fun stuff 202 if (fIconBitmap) { 203 BRect stripeRect = Bounds(); 204 stripeRect.right = kIconStripeWidth; 205 SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT)); 206 FillRect(stripeRect); 207 208 SetDrawingMode(B_OP_ALPHA); 209 DrawBitmapAsync(fIconBitmap, BPoint(18, 6)); 210 SetDrawingMode(B_OP_COPY); 211 } 212} 213