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 17 enum { 18 MSG_PANEL_OK, 19 MSG_PANEL_CANCEL, 20 }; 21 22 // constructor 23 AuthenticationPanel::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 53 AuthenticationPanel::~AuthenticationPanel() 54 { 55 delete_sem(fExitSem); 56 } 57 58 // QuitRequested 59 bool 60 AuthenticationPanel::QuitRequested() 61 { 62 fCancelled = true; 63 release_sem(fExitSem); 64 return false; 65 } 66 67 // MessageReceived 68 void 69 AuthenticationPanel::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 85 bool 86 AuthenticationPanel::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 210 void 211 AuthenticationPanel::Cancel() 212 { 213 fCancelled = true; 214 // release_sem(fExitSem); 215 216 Panel::Cancel(); 217 } 218 219 220 // _CalculateFrame 221 BRect 222 AuthenticationPanel::_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