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 <Message.h> 14 #include <Screen.h> 15 #include <TranslatorRoster.h> 16 17 18 // Reserved 19 #define T(x) x 20 21 22 enum { 23 P_MSG_CLOSE = 'pmic' 24 }; 25 26 27 28 ImageView::ImageView(BPositionIO *image) 29 : BView(BRect(0, 0, 1, 1), "image_view", B_FOLLOW_NONE, B_WILL_DRAW), 30 fSuccess(true) 31 { 32 if (!image) { 33 fSuccess = false; 34 return; 35 } 36 // Initialize and translate the image 37 BTranslatorRoster *roster = BTranslatorRoster::Default(); 38 BBitmapStream stream; 39 if (roster->Translate(image, NULL, NULL, &stream, B_TRANSLATOR_BITMAP) 40 < B_OK) { 41 fSuccess = false; 42 return; 43 } 44 stream.DetachBitmap(&fImage); 45 } 46 47 48 ImageView::~ImageView() 49 { 50 } 51 52 53 void 54 ImageView::AttachedToWindow() 55 { 56 if (!fSuccess) { 57 ResizeTo(75, 75); 58 return; 59 } 60 61 // We need to resize the view depending on what size has the screen and 62 // the image we will be viewing 63 BScreen screen(Window()); 64 BRect frame = screen.Frame(); 65 BRect image = fImage->Bounds(); 66 67 if (image.Width() > (frame.Width() - 100.0f)) { 68 image.right = frame.Width() - 100.0f; 69 } 70 if (image.Height() > (frame.Height() - 100.0f)) { 71 image.bottom = frame.Height() - 100.f; 72 } 73 74 ResizeTo(image.Width(), image.Height()); 75 } 76 77 78 void 79 ImageView::Draw(BRect updateRect) 80 { 81 if (fSuccess) 82 DrawBitmapAsync(fImage, Bounds()); 83 else { 84 float length = StringWidth(T("Image not loaded correctly")); 85 DrawString(T("Image not loaded correctly"), 86 BPoint((Bounds().Width() - length) / 2.0f, 30.0f)); 87 } 88 } 89 90 91 void 92 ImageView::MouseUp(BPoint point) 93 { 94 BWindow *parent = Window(); 95 if (parent) 96 parent->PostMessage(P_MSG_CLOSE); 97 } 98 99 100 // #pragma mark - 101 102 103 PackageImageViewer::PackageImageViewer(BPositionIO *image) 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 } 172 else 173 BWindow::MessageReceived(msg); 174 } 175 176