xref: /haiku/src/apps/packageinstaller/PackageImageViewer.cpp (revision e6b30aee0fd7a23d6a6baab9f3718945a0cd838a)
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