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