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
PreviewPage(int32 page,PrintJobPage * pjp)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
~PreviewPage()51 PreviewPage::~PreviewPage() {
52 delete []fPictures;
53 delete []fPoints;
54 delete []fRects;
55 }
56
InitCheck() const57 status_t PreviewPage::InitCheck() const {
58 return fStatus;
59 }
60
Draw(BView * view)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
PreviewView(BFile * jobFile,BRect rect)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
~PreviewView()81 PreviewView::~PreviewView() {
82 delete fCachedPage;
83 }
84
85 // returns 2 ^ fZoom
ZoomFactor() const86 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
PageRect() const94 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
InitCheck() const101 status_t PreviewView::InitCheck() const {
102 return fReader.InitCheck();
103 }
104
Draw(BRect rect)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
FrameResized(float width,float height)121 void PreviewView::FrameResized(float width, float height) {
122 FixScrollbars();
123 }
124
ShowsFirstPage() const125 bool PreviewView::ShowsFirstPage() const {
126 return fPage == 0;
127 }
128
ShowsLastPage() const129 bool PreviewView::ShowsLastPage() const {
130 return fPage == NumberOfPages() - 1;
131 }
132
NumberOfPages() const133 int PreviewView::NumberOfPages() const {
134 return fReader.NumberOfPages();
135 }
136
ShowNextPage()137 void PreviewView::ShowNextPage() {
138 if (!ShowsLastPage()) {
139 fPage ++; Invalidate();
140 }
141 }
142
ShowPrevPage()143 void PreviewView::ShowPrevPage() {
144 if (!ShowsFirstPage()) {
145 fPage --; Invalidate();
146 }
147 }
148
CanZoomIn() const149 bool PreviewView::CanZoomIn() const {
150 return fZoom < 4;
151 }
152
CanZoomOut() const153 bool PreviewView::CanZoomOut() const {
154 return fZoom > -2;
155 }
156
ZoomIn()157 void PreviewView::ZoomIn() {
158 if (CanZoomIn()) {
159 fZoom ++; FixScrollbars(); Invalidate();
160 }
161 }
162
ZoomOut()163 void PreviewView::ZoomOut() {
164 if (CanZoomOut()) {
165 fZoom --; FixScrollbars(); Invalidate();
166 }
167 }
168
FixScrollbars()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
PreviewWindow(BFile * jobFile)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
UpdateControls()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
MessageReceived(BMessage * m)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:
PreviewApp(const char * sig)283 PreviewApp(const char* sig) : BApplication(sig) { }
284 void ArgvReceived(int32 argc, char* argv[]);
285 };
286
ArgvReceived(int32 argc,char * argv[])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
main(int argc,char * argv[])296 int main(int argc, char* argv[]) {
297 PreviewApp app("application/x-vnd.obos.preview");
298 app.Run();
299 }
300 #endif
301