1 /* 2 * Copyright (c) 2007, Haiku, Inc. 3 * Distributed under the terms of the MIT license. 4 * 5 * Author: 6 * Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org> 7 */ 8 9 10 #include "PackageImageViewer.h" 11 12 #include <BitmapStream.h> 13 #include <Catalog.h> 14 #include <Locale.h> 15 #include <Message.h> 16 #include <Screen.h> 17 #include <TranslatorRoster.h> 18 19 20 #undef B_TRANSLATE_CONTEXT 21 #define B_TRANSLATE_CONTEXT "PackageImageViewer" 22 23 enum { 24 P_MSG_CLOSE = 'pmic' 25 }; 26 27 28 ImageView::ImageView(BPositionIO *image) 29 : 30 BView(BRect(0, 0, 1, 1), "image_view", B_FOLLOW_NONE, B_WILL_DRAW), 31 fSuccess(true) 32 { 33 if (!image) { 34 fSuccess = false; 35 return; 36 } 37 // Initialize and translate the image 38 BTranslatorRoster *roster = BTranslatorRoster::Default(); 39 BBitmapStream stream; 40 if (roster->Translate(image, NULL, NULL, &stream, B_TRANSLATOR_BITMAP) 41 < B_OK) { 42 fSuccess = false; 43 return; 44 } 45 stream.DetachBitmap(&fImage); 46 } 47 48 49 ImageView::~ImageView() 50 { 51 } 52 53 54 void 55 ImageView::AttachedToWindow() 56 { 57 if (!fSuccess) { 58 ResizeTo(75, 75); 59 return; 60 } 61 62 // We need to resize the view depending on what size has the screen and 63 // the image we will be viewing 64 BScreen screen(Window()); 65 BRect frame = screen.Frame(); 66 BRect image = fImage->Bounds(); 67 68 if (image.Width() > (frame.Width() - 100.0f)) 69 image.right = frame.Width() - 100.0f; 70 if (image.Height() > (frame.Height() - 100.0f)) 71 image.bottom = frame.Height() - 100.f; 72 73 ResizeTo(image.Width(), image.Height()); 74 } 75 76 77 void 78 ImageView::Draw(BRect updateRect) 79 { 80 if (fSuccess) 81 DrawBitmapAsync(fImage, Bounds()); 82 else { 83 float length = StringWidth(B_TRANSLATE("Image not loaded correctly")); 84 DrawString(B_TRANSLATE("Image not loaded correctly"), 85 BPoint((Bounds().Width() - length) / 2.0f, 30.0f)); 86 } 87 } 88 89 90 void 91 ImageView::MouseUp(BPoint point) 92 { 93 BWindow *parent = Window(); 94 if (parent) 95 parent->PostMessage(P_MSG_CLOSE); 96 } 97 98 99 // #pragma mark - 100 101 102 PackageImageViewer::PackageImageViewer(BPositionIO *image) 103 : 104 BWindow(BRect(100, 100, 100, 100), "", B_MODAL_WINDOW, 105 B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_NOT_CLOSABLE) 106 { 107 fBackground = new ImageView(image); 108 AddChild(fBackground); 109 110 ResizeTo(fBackground->Bounds().Width(), fBackground->Bounds().Height()); 111 112 BScreen screen(this); 113 BRect frame = screen.Frame(); 114 MoveTo((frame.Width() - Bounds().Width()) / 2.0f, 115 (frame.Height() - Bounds().Height()) / 2.0f); 116 } 117 118 119 PackageImageViewer::~PackageImageViewer() 120 { 121 } 122 123 124 void 125 PackageImageViewer::Go() 126 { 127 // Since this class can be thought of as a modified BAlert window, no use 128 // to reinvent a well fledged wheel. This concept has been borrowed from 129 // the current BAlert implementation 130 fSemaphore = create_sem(0, "ImageViewer"); 131 if (fSemaphore < B_OK) { 132 Quit(); 133 return; 134 } 135 136 BWindow *parent = 137 dynamic_cast<BWindow *>(BLooper::LooperForThread(find_thread(NULL))); 138 Show(); 139 140 if (parent) { 141 status_t ret; 142 for (;;) { 143 do { 144 ret = acquire_sem_etc(fSemaphore, 1, B_RELATIVE_TIMEOUT, 50000); 145 } while (ret == B_INTERRUPTED); 146 147 if (ret == B_BAD_SEM_ID) 148 break; 149 parent->UpdateIfNeeded(); 150 } 151 } 152 else { 153 // Since there are no spinlocks, wait until the semaphore is free 154 while (acquire_sem(fSemaphore) == B_INTERRUPTED) { 155 } 156 } 157 158 if (Lock()) 159 Quit(); 160 } 161 162 163 void 164 PackageImageViewer::MessageReceived(BMessage *msg) 165 { 166 if (msg->what == P_MSG_CLOSE) { 167 if (fSemaphore >= B_OK) { 168 delete_sem(fSemaphore); 169 fSemaphore = -1; 170 } 171 } else 172 BWindow::MessageReceived(msg); 173 } 174 175