xref: /haiku/src/tests/kits/interface/pictureprint/Preview.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
1 /*
2 
3 Preview
4 
5 Copyright (c) 2002 Haiku.
6 
7 Author:
8 	Michael Pfeiffer
9 
10 Permission is hereby granted, free of charge, to any person obtaining a copy of
11 this software and associated documentation files (the "Software"), to deal in
12 the Software without restriction, including without limitation the rights to
13 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
14 of the Software, and to permit persons to whom the Software is furnished to do
15 so, subject to the following conditions:
16 
17 The above copyright notice and this permission notice shall be included in all
18 copies or substantial portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 THE SOFTWARE.
27 
28 */
29 
30 #include <Debug.h>
31 
32 #include "Preview.h"
33 
34 // Implementation of PreviewPage
35 PreviewPage::PreviewPage(int32 page, PrintJobPage* pjp)
36 	: fPage(page)
37 	, fPictures(NULL)
38 	, fPoints(NULL)
39 	, fRects(NULL)
40 {
41 	fNumberOfPictures = pjp->NumberOfPictures();
42 	fPictures = new BPicture[fNumberOfPictures];
43 	fPoints = new BPoint[fNumberOfPictures];
44 	fRects = new BRect[fNumberOfPictures];
45 	status_t rc = B_ERROR;
46 	for (int32 i = 0; i < fNumberOfPictures &&
47 		(rc = pjp->NextPicture(fPictures[i], fPoints[i], fRects[i])) == B_OK; i ++);
48 	fStatus = rc;
49 }
50 
51 PreviewPage::~PreviewPage() {
52 	delete []fPictures;
53 	delete []fPoints;
54 	delete []fRects;
55 }
56 
57 status_t PreviewPage::InitCheck() const {
58 	return fStatus;
59 }
60 
61 void PreviewPage::Draw(BView* view) {
62 	ASSERT(fStatus == B_OK);
63 	for (int32 i = 0; i < fNumberOfPictures; i ++) {
64 		view->DrawPicture(&fPictures[i], fPoints[i]);
65 		view->SetHighColor(255, 0, 0);
66 		view->StrokeRect(fRects[i]);
67 	}
68 }
69 
70 // Implementation of PreviewView
71 
72 PreviewView::PreviewView(BFile* jobFile, BRect rect)
73 	: BView(rect, "PreviewView", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS)
74 	, fPage(0)
75 	, fZoom(0)
76 	, fReader(jobFile)
77 	, fCachedPage(NULL)
78 {
79 }
80 
81 PreviewView::~PreviewView() {
82 	delete fCachedPage;
83 }
84 
85 // returns 2 ^ fZoom
86 float PreviewView::ZoomFactor() const {
87 	const int32 b = 4;
88 	int32 zoom;
89 	if (fZoom > 0) zoom = (1 << b) << fZoom;
90 	else zoom = (1 << b) >> -fZoom;
91 	return zoom / (float)(1 << b);
92 }
93 
94 BRect PreviewView::PageRect() const {
95 	float f = ZoomFactor();
96 	BRect r = fReader.PaperRect();
97 	r.left *= f; r.right *= f; r.top *= f; r.bottom *= f;
98 	return r;
99 }
100 
101 status_t PreviewView::InitCheck() const {
102 	return fReader.InitCheck();
103 }
104 
105 void PreviewView::Draw(BRect rect) {
106 	if (fReader.InitCheck() == B_OK) {
107 			// set zoom factor
108 		SetScale(ZoomFactor());
109 			// render picture(s) of current page
110 		if (fCachedPage == NULL || fCachedPage->Page() != fPage) {
111 			delete fCachedPage; fCachedPage = NULL;
112 			PrintJobPage page;
113 			if (fReader.GetPage(fPage, page) == B_OK)
114 				fCachedPage = new PreviewPage(fPage, &page);
115 		}
116 		if (fCachedPage && fCachedPage->InitCheck() == B_OK)
117 			fCachedPage->Draw(this);
118 	}
119 }
120 
121 void PreviewView::FrameResized(float width, float height) {
122 	FixScrollbars();
123 }
124 
125 bool PreviewView::ShowsFirstPage() const {
126 	return fPage == 0;
127 }
128 
129 bool PreviewView::ShowsLastPage() const {
130 	return fPage == NumberOfPages() - 1;
131 }
132 
133 int PreviewView::NumberOfPages() const {
134 	return fReader.NumberOfPages();
135 }
136 
137 void PreviewView::ShowNextPage() {
138 	if (!ShowsLastPage()) {
139 		fPage ++; Invalidate();
140 	}
141 }
142 
143 void PreviewView::ShowPrevPage() {
144 	if (!ShowsFirstPage()) {
145 		fPage --; Invalidate();
146 	}
147 }
148 
149 bool PreviewView::CanZoomIn() const {
150 	return fZoom < 4;
151 }
152 
153 bool PreviewView::CanZoomOut() const {
154 	return fZoom > -2;
155 }
156 
157 void PreviewView::ZoomIn() {
158 	if (CanZoomIn()) {
159 		fZoom ++; FixScrollbars(); Invalidate();
160 	}
161 }
162 
163 void PreviewView::ZoomOut() {
164 	if (CanZoomOut()) {
165 		fZoom --; FixScrollbars(); Invalidate();
166 	}
167 }
168 
169 void PreviewView::FixScrollbars() {
170 	BRect frame = Bounds();
171 	BScrollBar * scroll;
172 	float x, y;
173 	float bigStep, smallStep;
174 	float width = PageRect().Width();
175 	float height = PageRect().Height();
176 	x = width - frame.Width();
177 	if (x < 0.0) {
178 		x = 0.0;
179 	}
180 	y = height - frame.Height();
181 	if (y < 0.0) {
182 		y = 0.0;
183 	}
184 
185 	scroll = ScrollBar (B_HORIZONTAL);
186 	scroll->SetRange (0.0, x);
187 	scroll->SetProportion ((width - x) / width);
188 	bigStep = frame.Width() - 2;
189 	smallStep = bigStep / 10.;
190 	scroll->SetSteps (smallStep, bigStep);
191 
192 	scroll = ScrollBar (B_VERTICAL);
193 	scroll->SetRange (0.0, y);
194 	scroll->SetProportion ((height - y) / height);
195 	bigStep = frame.Height() - 2;
196 	smallStep = bigStep / 10.;
197 	scroll->SetSteps (smallStep, bigStep);
198 }
199 
200 // Implementation of PreviewWindow
201 
202 PreviewWindow::PreviewWindow(BFile* jobFile)
203 	: BWindow(BRect(20, 20, 400, 600), "Preview", B_DOCUMENT_WINDOW, 0)
204 {
205 	float top = 0;
206 	float left = 10;
207 
208 	BRect r = Frame();
209 	r.right = r.IntegerWidth() - B_V_SCROLL_BAR_WIDTH; r.left = 0;
210 	r.bottom = r.IntegerHeight() - B_H_SCROLL_BAR_HEIGHT; r.top = 0;
211 
212 		// add navigation and zoom buttons
213 	fNext = new BButton(BRect(left, top, left+10, top+10), "Next", "Next Page", new BMessage(MSG_NEXT_PAGE));
214 	AddChild(fNext);
215 	fNext->ResizeToPreferred();
216 	left = fNext->Frame().right + 10;
217 
218 	fPrev = new BButton(BRect(left, top, left+10, top+10), "Prev", "Previous Page", new BMessage(MSG_PREV_PAGE));
219 	AddChild(fPrev);
220 	fPrev->ResizeToPreferred();
221 	left = fPrev->Frame().right + 10;
222 
223 	fZoomIn = new BButton(BRect(left, top, left+10, top+10), "ZoomIn", "Zoom In", new BMessage(MSG_ZOOM_IN));
224 	AddChild(fZoomIn);
225 	fZoomIn->ResizeToPreferred();
226 	left = fZoomIn->Frame().right + 10;
227 
228 	fZoomOut = new BButton(BRect(left, top, left+10, top+10), "ZoomOut", "Zoom Out", new BMessage(MSG_ZOOM_OUT));
229 	AddChild(fZoomOut);
230 	fZoomOut->ResizeToPreferred();
231 	left = fZoomOut->Frame().right + 10;
232 
233 	top = fZoomOut->Frame().bottom + 5;
234 
235 		// add preview view
236 	r.top = top;
237 	fPreview = new PreviewView(jobFile, r);
238 	fPreviewScroller = new BScrollView("PreviewScroller", fPreview, B_FOLLOW_ALL, 0, true, true, B_FANCY_BORDER);
239 	fPreviewScroller->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
240 	AddChild(fPreviewScroller);
241 
242 	if (fPreview->InitCheck() == B_OK) {
243 		fPreview->FixScrollbars();
244 		UpdateControls();
245 		Show();
246 	} else {
247 		Quit();
248 	}
249 }
250 
251 void PreviewWindow::UpdateControls() {
252 	fPrev->SetEnabled(!fPreview->ShowsFirstPage());
253 	fNext->SetEnabled(!fPreview->ShowsLastPage());
254 	fZoomIn->SetEnabled(fPreview->CanZoomIn());
255 	fZoomOut->SetEnabled(fPreview->CanZoomOut());
256 }
257 
258 void PreviewWindow::MessageReceived(BMessage* m) {
259 	switch (m->what) {
260 		case MSG_NEXT_PAGE: fPreview->ShowNextPage();
261 			break;
262 		case MSG_PREV_PAGE: fPreview->ShowPrevPage();
263 			break;
264 		case MSG_ZOOM_IN: fPreview->ZoomIn();
265 			break;
266 		case MSG_ZOOM_OUT: fPreview->ZoomOut();
267 			break;
268 		default:
269 			inherited::MessageReceived(m); return;
270 	}
271 	UpdateControls();
272 }
273 
274 #if 1
275 
276 // Standalone test preview application
277 // Note to quit application press Command+Q
278 
279 #include <Application.h>
280 
281 class PreviewApp : public BApplication {
282 public:
283 	PreviewApp(const char* sig) : BApplication(sig) { }
284 	void ArgvReceived(int32 argc, char* argv[]);
285 };
286 
287 void PreviewApp::ArgvReceived(int32 argc, char* argv[]) {
288 	for (int32 i = 1; i < argc; i ++) {
289 		BFile jobFile(argv[i], B_READ_WRITE);
290 		if (jobFile.InitCheck() == B_OK) {
291 			new PreviewWindow(&jobFile);
292 		}
293 	}
294 }
295 
296 int main(int argc, char* argv[]) {
297 	PreviewApp app("application/x-vnd.obos.preview");
298 	app.Run();
299 }
300 #endif
301