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