1// AuthenticationPanel.cpp 2 3#include <stdio.h> 4 5#include <Screen.h> 6 7#include <Box.h> 8#include <Button.h> 9#include <CheckBox.h> 10#include <Message.h> 11#include <String.h> 12#include <StringView.h> 13#include <TextControl.h> 14 15#include "AuthenticationPanel.h" 16 17enum { 18 MSG_PANEL_OK, 19 MSG_PANEL_CANCEL, 20}; 21 22// constructor 23AuthenticationPanel::AuthenticationPanel(BRect frame) 24 : Panel(frame, "Name Panel", 25 B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, 26 B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_ZOOMABLE), 27 fCancelled(false), 28 fExitSem(B_ERROR) 29{ 30 fExitSem = create_sem(0, "Authentication Panel"); 31 32 BRect controlFrame(0.0, 0.0, frame.Width(), 15.0); 33 34 fNameTC = new BTextControl(controlFrame, "name", "Username", "", NULL, 35 B_FOLLOW_LEFT | B_FOLLOW_RIGHT); 36 37 fPassTC = new BTextControl(controlFrame, "pass", "Password", "", NULL, 38 B_FOLLOW_LEFT | B_FOLLOW_RIGHT); 39 40 fKeepUsingCB = new BCheckBox(controlFrame, "again", 41 "Use login for all shares of this host", 42 NULL, B_FOLLOW_LEFT | B_FOLLOW_RIGHT); 43 44 BRect buttonFrame(0.0, 0.0, 20.0, 15.0); 45 fOkB = new BButton(buttonFrame, "ok", "OK", 46 new BMessage(MSG_PANEL_OK)); 47 fCancelB = new BButton(buttonFrame, "cancel", "Cancel", 48 new BMessage(MSG_PANEL_CANCEL)); 49 50} 51 52// destructor 53AuthenticationPanel::~AuthenticationPanel() 54{ 55 delete_sem(fExitSem); 56} 57 58// QuitRequested 59bool 60AuthenticationPanel::QuitRequested() 61{ 62 fCancelled = true; 63 release_sem(fExitSem); 64 return false; 65} 66 67// MessageReceived 68void 69AuthenticationPanel::MessageReceived(BMessage* message) 70{ 71 switch (message->what) { 72 case MSG_PANEL_CANCEL: 73 Cancel(); 74 break; 75 case MSG_PANEL_OK: { 76 release_sem(fExitSem); 77 break; 78 } 79 default: 80 Panel::MessageReceived(message); 81 } 82} 83 84// GetAuthentication 85bool 86AuthenticationPanel::GetAuthentication(const char* server, 87 const char* share, 88 const char* previousUser, 89 const char* previousPass, 90 bool previousKeep, 91 bool badPassword, 92 char* user, char* pass, bool* keep) 93{ 94 // configure panel and layout controls 95 BString helper("Enter login for: "); 96 helper << (server ? server : "<unkown host>") << "/"; 97 helper << (share ? share : "<unkown share>"); 98 99 // ignore the previous password, if it didn't work 100 if (badPassword) 101 previousPass = NULL; 102 103 SetTitle(helper.String()); 104 105 BPoint offset(0.0, 5.0); 106 107 fNameTC->SetText(previousUser ? previousUser : ""); 108 fNameTC->ResizeToPreferred(); 109 fNameTC->MoveTo(BPoint(10.0, 10.0)); 110 111 fPassTC->SetText(previousPass ? previousPass : ""); 112 fPassTC->ResizeToPreferred(); 113 fPassTC->MoveTo(fNameTC->Frame().LeftBottom() + offset); 114 115 fKeepUsingCB->SetValue(previousKeep); 116 fKeepUsingCB->ResizeToPreferred(); 117 fKeepUsingCB->MoveTo(fPassTC->Frame().LeftBottom() + offset); 118 119 fCancelB->ResizeToPreferred(); 120 121 fOkB->ResizeToPreferred(); 122 fOkB->MoveTo(fKeepUsingCB->Frame().RightBottom() + offset + offset - fOkB->Frame().RightTop()); 123 124 fCancelB->MoveTo(fOkB->Frame().LeftTop() - BPoint(10.0, 0.0) - fCancelB->Frame().RightTop()); 125 126 BRect frame(fNameTC->Frame().LeftTop(), fOkB->Frame().RightBottom()); 127 128 // work arround buggy BTextControl resizing 129 BRect nameFrame = fNameTC->Frame(); 130 BRect passFrame = fPassTC->Frame(); 131 132 nameFrame.right = nameFrame.left + frame.Width(); 133 passFrame.right = passFrame.left + frame.Width(); 134 135 float divider = fNameTC->Divider(); 136 137 if (fPassTC->Divider() > divider) 138 divider = fPassTC->Divider(); 139 140 delete fNameTC; 141 fNameTC = new BTextControl(nameFrame, "name", "Username", "", NULL, 142 B_FOLLOW_LEFT | B_FOLLOW_RIGHT); 143 fNameTC->SetText(previousUser ? previousUser : ""); 144 145 delete fPassTC; 146 fPassTC = new BTextControl(passFrame, "pass", "Password", "", NULL, 147 B_FOLLOW_LEFT | B_FOLLOW_RIGHT); 148 149 fPassTC->TextView()->HideTyping(true); 150 fPassTC->SetText(previousPass ? previousPass : ""); 151 152 fNameTC->SetDivider(divider); 153 fPassTC->SetDivider(divider); 154 155 156 // create background view 157 frame.InsetBy(-10.0, -10.0); 158 159 BBox* bg = new BBox(frame, "bg", B_FOLLOW_ALL, 160 B_FRAME_EVENTS | B_WILL_DRAW | B_NAVIGABLE_JUMP, 161 B_PLAIN_BORDER); 162 163 bg->AddChild(fNameTC); 164 bg->AddChild(fPassTC); 165 bg->AddChild(fKeepUsingCB); 166 167 bg->AddChild(fOkB); 168 bg->AddChild(fCancelB); 169 170 frame.OffsetTo(-10000.0, -10000.0); 171 frame = _CalculateFrame(frame); 172 MoveTo(frame.LeftTop()); 173 ResizeTo(frame.Width(), frame.Height()); 174 175 AddChild(bg); 176 SetDefaultButton(fOkB); 177 fNameTC->MakeFocus(true); 178 179 // start window thread 180 Show(); 181 182 // let the window jitter, if the previous password was invalid 183 if (badPassword) { 184 BPoint leftTop = Frame().LeftTop(); 185 const float jitterOffsets[] = { -10, 0, 10, 0 }; 186 const int32 jitterOffsetCount = sizeof(jitterOffsets) / sizeof(float); 187 for (int32 i = 0; i < 30; i++) { 188 float offset = jitterOffsets[i % jitterOffsetCount]; 189 MoveTo(leftTop.x + offset, leftTop.y); 190 snooze(10000); 191 } 192 MoveTo(leftTop); 193 } 194 195 // block calling thread 196 acquire_sem(fExitSem); 197 198 // window wants to quit 199 Lock(); 200 201 strcpy(user, fNameTC->Text()); 202 strcpy(pass, fPassTC->Text()); 203 *keep = fKeepUsingCB->Value() == B_CONTROL_ON; 204 205 Quit(); 206 return fCancelled; 207} 208 209// Cancel 210void 211AuthenticationPanel::Cancel() 212{ 213 fCancelled = true; 214// release_sem(fExitSem); 215 216 Panel::Cancel(); 217} 218 219 220// _CalculateFrame 221BRect 222AuthenticationPanel::_CalculateFrame(BRect frame) 223{ 224 BScreen screen(B_MAIN_SCREEN_ID); 225 BRect screenFrame = screen.Frame(); 226 if (!screenFrame.Contains(frame)) { 227 float width = frame.Width(); 228 float height = frame.Height(); 229 BPoint center; 230 center.x = screenFrame.left + screenFrame.Width() / 2.0; 231 center.y = screenFrame.top + screenFrame.Height() / 4.0; 232 frame.left = center.x - width / 2.0; 233 frame.right = frame.left + width; 234 frame.top = center.y - height / 2.0; 235 frame.bottom = frame.top + height; 236 } 237 return frame; 238} 239