1 /* 2 * Copyright 2007-2012, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ryan Leavengood 7 * François Revol <revol@free.fr> 8 */ 9 10 11 #include <Application.h> 12 #include <Alert.h> 13 #include <Button.h> 14 #include <Font.h> 15 #include <Screen.h> 16 #include <ScreenSaver.h> 17 #include <Shelf.h> 18 #include <String.h> 19 #include <StringView.h> 20 #include <View.h> 21 #include <Window.h> 22 #include <Debug.h> 23 24 25 const rgb_color kMediumBlue = {0, 0, 100}; 26 const rgb_color kWhite = {255, 255, 255}; 27 28 const char *kInConfigName = "InConfig"; 29 const char *kShelfArchiveName = "Shelf"; 30 31 32 // Inspired by the classic BeOS screensaver, of course 33 class Shelf : public BScreenSaver 34 { 35 public: 36 Shelf(BMessage *archive, image_id); 37 void Draw(BView *view, int32 frame); 38 void StartConfig(BView *view); 39 void StopConfig(); 40 status_t StartSaver(BView *view, bool preview); 41 void StopSaver(); 42 status_t SaveState(BMessage *state) const; 43 44 private: 45 BShelf *fShelf; 46 BWindow *fConfigWindow; 47 bool fInConfig; 48 bool fInEdit; 49 BMallocIO fShelfData; 50 }; 51 52 53 BScreenSaver *instantiate_screen_saver(BMessage *msg, image_id image) 54 { 55 PRINT(("%s()\n", __FUNCTION__)); 56 return new Shelf(msg, image); 57 } 58 59 60 Shelf::Shelf(BMessage *archive, image_id id) 61 : BScreenSaver(archive, id) 62 , fShelf(NULL) 63 , fConfigWindow(NULL) 64 , fInConfig(false) 65 , fInEdit(false) 66 , fShelfData() 67 { 68 archive->PrintToStream(); 69 if (archive->FindBool(kInConfigName, &fInConfig) < B_OK) 70 fInConfig = false; 71 72 status_t status; 73 const void *data; 74 ssize_t length; 75 76 status = archive->FindData(kShelfArchiveName, 'shlf', &data, &length); 77 if (status == B_OK) { 78 fShelfData.WriteAt(0LL, data, length); 79 fShelfData.Seek(SEEK_SET, 0LL); 80 } 81 82 83 /* 84 if (fInConfig) { 85 fInEdit = true; 86 fInConfig = false; 87 } 88 */} 89 90 91 void 92 Shelf::StartConfig(BView *view) 93 { 94 PRINT(("%p:%s()\n", this, __FUNCTION__)); 95 fInConfig = true; 96 view->AddChild(new BStringView(BRect(20, 10, 200, 35), "", 97 "Shelf, by François Revol.")); 98 99 BScreen screen; 100 fConfigWindow = new BWindow(screen.Frame(), "Shelf Config", 101 B_UNTYPED_WINDOW, B_NOT_MOVABLE | B_NOT_CLOSABLE | B_NOT_ZOOMABLE 102 | B_NOT_MINIMIZABLE | B_NOT_RESIZABLE | B_AVOID_FRONT | B_AVOID_FOCUS); 103 104 BView *shelfView = new BView(fConfigWindow->Bounds(), "ShelfView", 105 B_FOLLOW_NONE, B_WILL_DRAW | B_FRAME_EVENTS); 106 shelfView->SetViewColor(216, 216, 216, 0); 107 108 fConfigWindow->AddChild(shelfView); 109 110 fShelfData.Seek(SEEK_SET, 0LL); 111 fShelf = new BShelf(&fShelfData, shelfView); 112 fShelf->SetDisplaysZombies(true); 113 fShelfData.Seek(SEEK_SET, 0LL); 114 115 // start the Looper 116 fConfigWindow->Show(); 117 118 fConfigWindow->Lock(); 119 fConfigWindow->SendBehind(view->Window()); 120 fConfigWindow->Unlock(); 121 122 //"\nDrop replicants on me!" 123 } 124 125 126 void 127 Shelf::StopConfig() 128 { 129 fInConfig = false; 130 PRINT(("%p:%s()\n", this, __FUNCTION__)); 131 fConfigWindow->Lock(); 132 fConfigWindow->Quit(); 133 fShelf = NULL; 134 135 BScreenSaver::StopConfig(); 136 } 137 138 139 status_t 140 Shelf::StartSaver(BView *view, bool preview) 141 { 142 PRINT(("%p:%s(, %d)\n", this, __FUNCTION__, preview)); 143 if (!preview) { 144 view->SetViewColor(216, 216, 216, 0); 145 fShelfData.Seek(SEEK_SET, 0LL); 146 fShelf = new BShelf(&fShelfData, view); 147 148 } 149 BString s; 150 s << "preview: " << preview << " "; 151 s << "BView:Name: " << view->Name() << " "; 152 s << "BApp:Name: " << be_app->Name(); 153 154 PRINT(("%p:%s:%s\n", this, __FUNCTION__, s.String())); 155 //BAlert *a = new BAlert("debug", s.String(), "Ok"); 156 //a->Go(); 157 return B_ERROR; 158 #if 0 159 float width = view->Bounds().Width(); 160 float height = view->Bounds().Height(); 161 162 BFont font; 163 view->GetFont(&font); 164 font.SetSize(height / 2.5); 165 view->SetFont(&font); 166 167 BRect rect; 168 escapement_delta delta; 169 delta.nonspace = 0; 170 delta.space = 0; 171 // If anyone has suggestions for how to clean this up, speak up 172 font.GetBoundingBoxesForStrings(&fLine1, 1, B_SCREEN_METRIC, &delta, &rect); 173 float y = ((height - (rect.Height() * 2 + height / 10)) / 2) + rect.Height(); 174 fLine1Start.Set((width - rect.Width()) / 2, y); 175 font.GetBoundingBoxesForStrings(&fLine2, 1, B_SCREEN_METRIC, &delta, &rect); 176 fLine2Start.Set((width - rect.Width()) / 2, y + rect.Height() + height / 10); 177 178 #endif 179 return B_OK; 180 } 181 182 183 void 184 Shelf::StopSaver() 185 { 186 PRINT(("%p:%s()\n", this, __FUNCTION__)); 187 //if (fShelf) 188 //delete fShelf; 189 //fShelf = NULL; 190 } 191 192 193 status_t 194 Shelf::SaveState(BMessage *state) const 195 { 196 status_t status; 197 198 PRINT(("%p:%s()\n", this, __FUNCTION__)); 199 state->PrintToStream(); 200 201 if (fInConfig) 202 state->AddBool(kInConfigName, fInConfig); 203 if (!fInConfig) 204 state->RemoveData(kInConfigName); 205 if (fInConfig && fShelf) { 206 status = state->AddBool("got it", true); 207 208 fShelf->LockLooper(); 209 status = fShelf->Save(); 210 fShelf->UnlockLooper(); 211 if (status < B_OK) 212 return status; 213 status = state->AddData(kShelfArchiveName, 'shlf', fShelfData.Buffer(), 214 fShelfData.BufferLength()); 215 216 // return B_OK; 217 //fShelfData.SetSize(0LL); 218 #if 0 219 BMallocIO mio; 220 status = fShelf->SetSaveLocation(&mio); 221 if (status < B_OK) 222 return status; 223 status = fShelf->Save(); 224 fShelf->SetSaveLocation((BDataIO *)NULL); 225 if (status < B_OK) 226 return status; 227 status = state->AddData(kShelfArchiveName, 'shlf', mio.Buffer(), 228 mio.BufferLength()); 229 #endif 230 if (status < B_OK) 231 return status; 232 } 233 return B_OK; 234 } 235 236 237 void 238 Shelf::Draw(BView *view, int32 frame) 239 { 240 PRINT(("%p:%s(, %d)\n", this, __FUNCTION__, frame)); 241 BScreenSaver::Draw(view, frame); 242 #if 0 243 if (frame == 0) { 244 // fill with blue on first frame 245 view->SetLowColor(kMediumBlue); 246 view->FillRect(view->Bounds(), B_SOLID_LOW); 247 248 // Set tick size to 500,000 microseconds = 0.5 second 249 SetTickSize(500000); 250 } else { 251 // Drawing the background color every other frame to make the text blink 252 if (frame % 2 == 1) 253 view->SetHighColor(kWhite); 254 else 255 view->SetHighColor(kMediumBlue); 256 257 view->DrawString(fLine1, fLine1Start); 258 view->DrawString(fLine2, fLine2Start); 259 } 260 #endif 261 } 262 263 264