From 26c1085f1b7300676f83e29f6a13da6036af1f17 Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Fri, 8 Jun 2007 04:59:14 +0000 Subject: [PATCH] Inspired by Daniel Sandler's Mac OS X recreation of Message, I've added a little rounded box on the bottom with the full message in it. Given that currently this version only uses fortune to get it's message this allows maximum enjoyment of the little anecdotes and jokes provided by fortune. Though after testing this 60+ times today I'm starting to get sick of fortunes. I've implemented everything myself here, including breaking the string up on newlines and drawing each line of text with the right vertical spacing. I suppose some clever use of BTextView would have been better. But this works fine and wasn't that much code. I'm not sure if this was the most productive use of the last 5 hours, but I learned quite a bit. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21347 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/screen_savers/message/Message.cpp | 82 +++++++++++++++++-- 1 file changed, 76 insertions(+), 6 deletions(-) diff --git a/src/add-ons/screen_savers/message/Message.cpp b/src/add-ons/screen_savers/message/Message.cpp index 849c681d1f..b9982c53cf 100644 --- a/src/add-ons/screen_savers/message/Message.cpp +++ b/src/add-ons/screen_savers/message/Message.cpp @@ -52,6 +52,39 @@ BString *get_message() } +int get_lines(BString *message, BString*** result, int *longestLine) +{ + // First count how many newlines there are + int count = 0; + int start = 0; + while ((start = message->FindFirst('\n', start)) != B_ERROR) { + start++; // To move past the new line + count++; + } + + // Now break the string up and put in result + BString **lines = new BString*[count]; + start = 0; + int end = 0; + int maxLength = 0; + for (int i = 0; ((end = message->FindFirst('\n', start)) != B_ERROR) && i < count; i++) { + lines[i] = new BString(); + message->CopyInto(*lines[i], start, end - start); + // Convert tabs to 4 spaces + lines[i]->ReplaceAll("\t", " "); + // Look for longest line + if (lines[i]->Length() > maxLength) { + maxLength = lines[i]->Length(); + *longestLine = i; + } + start = end + 1; + } + *result = lines; + + return count; +} + + // Inspired by the classic BeOS screensaver, of course. // Thanks to Jon Watte for writing the original. class Message : public BScreenSaver @@ -66,6 +99,7 @@ class Message : public BScreenSaver private: BList *fFontFamilies; float fScaleFactor; + bool fPreview; }; @@ -105,6 +139,7 @@ Message::StartConfig(BView *view) status_t Message::StartSaver(BView *view, bool preview) { + fPreview = preview; // Scale factor is based on the system I developed this on, in // other words other factors below depend on this. fScaleFactor = view->Bounds().Height() / 1024; @@ -168,17 +203,17 @@ Message::Draw(BView *view, int32 frame) offscreen.SetFont(&font); // Get the message - // TODO: Display the whole message at the bottom of the screen - // in a translucent rect BString *message = get_message(); + BString *origMessage = new BString(); + message->CopyInto(*origMessage, 0, message->Length()); // Replace newlines and tabs with spaces message->ReplaceSet("\n\t", ' '); int height = (int) offscreen.Bounds().Height(); int width = (int) offscreen.Bounds().Width(); - // From 8 to 16 iterations - int32 iterations = (rand() % 9) + 8; + // From 14 to 22 iterations + int32 iterations = (rand() % 8) + 14; for (int32 i = 0; i < iterations; i++) { // Randomly set font size and shear BFont font; @@ -193,9 +228,8 @@ Message::Draw(BView *view, int32 frame) offscreen.SetFont(&font); // Randomly set drawing location - // TODO: Improve this int x = (rand() % width) - (rand() % width/((rand() % 8)+1)); - int y = (rand() % height) - (rand() % height/((rand() % 8)+1)); + int y = rand() % height; // Draw new text offscreen.SetHighColor(colors[rand() % 8]); @@ -215,6 +249,42 @@ Message::Draw(BView *view, int32 frame) delete toDraw; } + // Now draw the full message in a nice translucent box, but only + // if this isn't preview mode + if (!fPreview) { + BFont font(be_fixed_font); + font.SetSize(14.0); + offscreen.SetFont(&font); + font_height fontHeight; + font.GetHeight(&fontHeight); + float lineHeight = fontHeight.ascent + fontHeight.descent + fontHeight.leading; + + BString **result = NULL; + int longestLine = 0; + int count = get_lines(origMessage, &result, &longestLine); + float stringWidth = font.StringWidth(result[longestLine]->String()); + BRect box(0, 0, stringWidth + 20, (lineHeight * count) + 20); + box.OffsetTo((width - box.Width()) / 2, height - box.Height() - 40); + + offscreen.SetDrawingMode(B_OP_ALPHA); + base_color.alpha = 128; + offscreen.SetHighColor(base_color); + offscreen.FillRoundRect(box, 8, 8); + offscreen.SetHighColor(205, 205, 205); + BPoint start = box.LeftTop(); + start.x += 10; + start.y += 10 + fontHeight.ascent + fontHeight.leading; + for (int i = 0; i < count; i++) { + offscreen.DrawString(result[i]->String(), start); + start.y += lineHeight; + delete result[i]; + } + delete[] result; + } + + delete origMessage; + delete message; + offscreen.Sync(); buffer.Unlock(); view->DrawBitmap(&buffer);