1/* 2 3PDF Writer printer driver. 4 5Version: 12.19.2000 6 7Copyright (c) 2001 OpenBeOS. 8 9Authors: 10 Philippe Houdoin 11 Simon Gauvin 12 Michael Pfeiffer 13 14Permission is hereby granted, free of charge, to any person obtaining a copy of 15this software and associated documentation files (the "Software"), to deal in 16the Software without restriction, including without limitation the rights to 17use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 18of the Software, and to permit persons to whom the Software is furnished to do 19so, subject to the following conditions: 20 21The above copyright notice and this permission notice shall be included in all 22copies or substantial portions of the Software. 23 24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 30THE SOFTWARE. 31 32*/ 33 34#include "PageSetupWindow.h" 35 36#include "AdvancedSettingsWindow.h" 37#include "Fonts.h" 38#include "FontsWindow.h" 39#include "BlockingWindow.h" 40#include "MarginView.h" 41#include "PrinterDriver.h" 42#include "pdflib.h" // for pageFormat constants 43#include "PrintUtils.h" 44 45 46#include <Box.h> 47#include <Button.h> 48#include <GridView.h> 49#include <GroupLayout.h> 50#include <GroupLayoutBuilder.h> 51#include <MenuField.h> 52#include <Message.h> 53#include <PopUpMenu.h> 54#include <Screen.h> 55#include <TextControl.h> 56 57 58// static global variables 59static struct 60{ 61 const char *label; 62 float width; 63 float height; 64} pageFormat[] = 65{ 66 { "Letter", letter_width, letter_height }, 67 { "Legal", legal_width, legal_height }, 68 { "Ledger", ledger_width, ledger_height }, 69 { "p11x17", p11x17_width, p11x17_height }, 70 { "A0", a0_width, a0_height }, 71 { "A1", a1_width, a1_height }, 72 { "A2", a2_width, a2_height }, 73 { "A3", a3_width, a3_height }, 74 { "A4", a4_width, a4_height }, 75 { "A5", a5_width, a5_height }, 76 { "A6", a6_width, a6_height }, 77 { "B5", b5_width, b5_height }, 78 { NULL, 0.0, 0.0 } 79}; 80 81 82static struct 83{ 84 const char *label; 85 int32 orientation; 86} orientation[] = 87{ 88 { "Portrait", PrinterDriver::PORTRAIT_ORIENTATION }, 89 { "Landscape", PrinterDriver::LANDSCAPE_ORIENTATION }, 90 { NULL, 0 } 91}; 92 93// PDFLib 5.x does not support PDF 1.2 anymore! 94static const char *pdf_compatibility[] = { "1.3", "1.4", NULL }; 95 96 97PageSetupWindow::PageSetupWindow(BMessage *msg, const char *printerName) 98 : HWindow(BRect(0, 0, 200, 100), "Page setup", B_TITLED_WINDOW_LOOK, 99 B_MODAL_APP_WINDOW_FEEL, 100 B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE 101 | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), 102 fResult(B_ERROR), 103 fSetupMsg(msg), 104 fAdvancedSettings(*msg), 105 fPrinterDirName(printerName) 106{ 107 fExitSem = create_sem(0, "PageSetup"); 108 109 if (printerName) 110 SetTitle(BString(printerName).Append(" page setup").String()); 111 112 if (fSetupMsg->FindInt32("orientation", &fCurrentOrientation) != B_OK) 113 fCurrentOrientation = PrinterDriver::PORTRAIT_ORIENTATION; 114 115 BRect page; 116 float width = letter_width; 117 float height = letter_height; 118 if (fSetupMsg->FindRect("paper_rect", &page) == B_OK) { 119 width = page.Width(); 120 height = page.Height(); 121 } else { 122 page.Set(0, 0, width, height); 123 } 124 125 BString label; 126 if (fSetupMsg->FindString("pdf_paper_size", &label) != B_OK) 127 label = "Letter"; 128 129 int32 compression; 130 fSetupMsg->FindInt32("pdf_compression", &compression); 131 132 int32 units; 133 if (fSetupMsg->FindInt32("units", &units) != B_OK) 134 units = kUnitInch; 135 136 // re-calculate the margin from the printable rect in points 137 BRect margin = page; 138 if (fSetupMsg->FindRect("printable_rect", &margin) == B_OK) { 139 margin.top -= page.top; 140 margin.left -= page.left; 141 margin.right = page.right - margin.right; 142 margin.bottom = page.bottom - margin.bottom; 143 } else { 144 margin.Set(28.34, 28.34, 28.34, 28.34); // 28.34 dots = 1cm 145 } 146 147 BString setting_value; 148 if (fSetupMsg->FindString("pdf_compatibility", &setting_value) != B_OK) 149 setting_value = "1.3"; 150 151 // Load font settings 152 fFonts = new Fonts(); 153 fFonts->CollectFonts(); 154 BMessage fonts; 155 if (fSetupMsg->FindMessage("fonts", &fonts) == B_OK) 156 fFonts->SetTo(&fonts); 157 158 fMarginView = new MarginView(int32(width), int32(height), margin, 159 MarginUnit(units)); 160 161 BPopUpMenu* pageSize = new BPopUpMenu("Page size"); 162 pageSize->SetRadioMode(true); 163 164 fPageSizeMenu = new BMenuField("page_size", "Page size:", pageSize); 165 fPageSizeMenu->Menu()->SetLabelFromMarked(true); 166 167 for (int32 i = 0; pageFormat[i].label != NULL; i++) { 168 BMessage* message = new BMessage(PAGE_SIZE_CHANGED); 169 message->AddFloat("width", pageFormat[i].width); 170 message->AddFloat("height", pageFormat[i].height); 171 BMenuItem* item = new BMenuItem(pageFormat[i].label, message); 172 pageSize->AddItem(item); 173 174 if (label.Compare(pageFormat[i].label) == 0) 175 item->SetMarked(true); 176 } 177 178 BPopUpMenu* orientationPopUpMenu = new BPopUpMenu("Orientation"); 179 orientationPopUpMenu->SetRadioMode(true); 180 181 fOrientationMenu = new BMenuField("orientation", "Orientation:", 182 orientationPopUpMenu); 183 fOrientationMenu->Menu()->SetLabelFromMarked(true); 184 185 for (int32 i = 0; orientation[i].label != NULL; i++) { 186 BMessage* message = new BMessage(ORIENTATION_CHANGED); 187 message->AddInt32("orientation", orientation[i].orientation); 188 BMenuItem* item = new BMenuItem(orientation[i].label, message); 189 orientationPopUpMenu->AddItem(item); 190 191 if (fCurrentOrientation == orientation[i].orientation) 192 item->SetMarked(true); 193 } 194 195 BPopUpMenu* compatibility = new BPopUpMenu("PDF compatibility"); 196 compatibility->SetRadioMode(true); 197 198 fPDFCompatibilityMenu = new BMenuField("pdf_compatibility", 199 "PDF compatibility:", compatibility); 200 fPDFCompatibilityMenu->Menu()->SetLabelFromMarked(true); 201 202 for (int32 i = 0; pdf_compatibility[i] != NULL; i++) { 203 BMenuItem* item = new BMenuItem(pdf_compatibility[i], NULL); 204 compatibility->AddItem(item); 205 if (setting_value == pdf_compatibility[i]) 206 item->SetMarked(true); 207 } 208 209 fPDFCompressionSlider = new BSlider("pdf_compression", 210 "Compression:", NULL, 0, 9, B_HORIZONTAL); 211 fPDFCompressionSlider->SetLimitLabels("None", "Best"); 212 fPDFCompressionSlider->SetHashMarks(B_HASH_MARKS_BOTTOM); 213 fPDFCompressionSlider->SetValue(compression); 214 215 BBox *separator = new BBox("separator"); 216 separator->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1)); 217 218 BButton *cancel = new BButton("cancel", "Cancel", new BMessage(CANCEL_MSG)); 219 220 BButton *ok = new BButton("ok", "OK", new BMessage(OK_MSG)); 221 ok->MakeDefault(true); 222 223 BButton *fontsButton = new BButton("fonts", "Fonts" B_UTF8_ELLIPSIS, 224 new BMessage(FONTS_MSG)); 225 226 BButton* advancedButton = new BButton("advanced", 227 "Advanced" B_UTF8_ELLIPSIS, 228 new BMessage(ADVANCED_MSG)); 229 230 BGridView* settings = new BGridView(); 231 BGridLayout* settingsLayout = settings->GridLayout(); 232 settingsLayout->AddItem(fPageSizeMenu->CreateLabelLayoutItem(), 0, 0); 233 settingsLayout->AddItem(fPageSizeMenu->CreateMenuBarLayoutItem(), 1, 0); 234 settingsLayout->AddItem(fOrientationMenu->CreateLabelLayoutItem(), 0, 1); 235 settingsLayout->AddItem(fOrientationMenu->CreateMenuBarLayoutItem(), 1, 1); 236 settingsLayout->AddItem(fPDFCompatibilityMenu->CreateLabelLayoutItem(), 0, 2); 237 settingsLayout->AddItem(fPDFCompatibilityMenu->CreateMenuBarLayoutItem(), 1, 2); 238 settingsLayout->AddView(fPDFCompressionSlider, 0, 3, 2); 239 settingsLayout->SetSpacing(0, 0); 240 241 SetLayout(new BGroupLayout(B_VERTICAL)); 242 AddChild(BGroupLayoutBuilder(B_VERTICAL, 0) 243 .AddGroup(B_HORIZONTAL, 5, 1) 244 .AddGroup(B_VERTICAL, 0, 1.0f) 245 .Add(fMarginView) 246 .AddGlue() 247 .End() 248 .AddGroup(B_VERTICAL, 0, 1.0f) 249 .Add(settings) 250 .AddGlue() 251 .End() 252 .End() 253 .Add(separator) 254 .AddGroup(B_HORIZONTAL, 10, 1.0f) 255 .Add(fontsButton) 256 .Add(advancedButton) 257 .AddGlue() 258 .Add(cancel) 259 .Add(ok) 260 .End() 261 .SetInsets(10, 10, 10, 10) 262 ); 263 264 BRect winFrame(Frame()); 265 BRect screenFrame(BScreen().Frame()); 266 MoveTo((screenFrame.right - winFrame.right) / 2, 267 (screenFrame.bottom - winFrame.bottom) / 2); 268} 269 270 271PageSetupWindow::~PageSetupWindow() 272{ 273 delete_sem(fExitSem); 274 delete fFonts; 275} 276 277 278void 279PageSetupWindow::MessageReceived(BMessage *msg) 280{ 281 switch (msg->what) { 282 case OK_MSG: { 283 _UpdateSetupMessage(); 284 fResult = B_OK; 285 release_sem(fExitSem); 286 } break; 287 288 case CANCEL_MSG: { 289 fResult = B_ERROR; 290 release_sem(fExitSem); 291 } break; 292 293 case PAGE_SIZE_CHANGED: { 294 float w, h; 295 msg->FindFloat("width", &w); 296 msg->FindFloat("height", &h); 297 if (fCurrentOrientation == PrinterDriver::PORTRAIT_ORIENTATION) { 298 fMarginView->SetPageSize(w, h); 299 } else { 300 fMarginView->SetPageSize(h, w); 301 } 302 fMarginView->UpdateView(MARGIN_CHANGED); 303 } break; 304 305 case ORIENTATION_CHANGED: { 306 int32 orientation; 307 msg->FindInt32("orientation", &orientation); 308 309 if (fCurrentOrientation != orientation) { 310 fCurrentOrientation = orientation; 311 BPoint p = fMarginView->PageSize(); 312 fMarginView->SetPageSize(p.y, p.x); 313 fMarginView->UpdateView(MARGIN_CHANGED); 314 } 315 } break; 316 317 case FONTS_MSG: { 318 (new FontsWindow(fFonts))->Show(); 319 } break; 320 321 case ADVANCED_MSG: { 322 (new AdvancedSettingsWindow(&fAdvancedSettings))->Show(); 323 } break; 324 325 default: 326 inherited::MessageReceived(msg); 327 break; 328 } 329} 330 331 332bool 333PageSetupWindow::QuitRequested() 334{ 335 release_sem(fExitSem); 336 return true; 337} 338 339 340status_t 341PageSetupWindow::Go() 342{ 343 MoveTo(300,300); 344 Show(); 345 346 while (acquire_sem(fExitSem) == B_INTERRUPTED) { 347 } 348 349 // Have to cache the value since we delete ourself on Quit() 350 status_t result = fResult; 351 if (Lock()) 352 Quit(); 353 354 return result; 355} 356 357 358void 359PageSetupWindow::_UpdateSetupMessage() 360{ 361 SetInt32(fSetupMsg, "orientation", fCurrentOrientation); 362 363 BMenuItem *item = fPDFCompatibilityMenu->Menu()->FindMarked(); 364 if (item) 365 SetString(fSetupMsg, "pdf_compatibility", item->Label()); 366 367 SetInt32(fSetupMsg, "pdf_compression", fPDFCompressionSlider->Value()); 368 369 item = fPageSizeMenu->Menu()->FindMarked(); 370 if (item) { 371 float w, h; 372 BMessage *msg = item->Message(); 373 msg->FindFloat("width", &w); 374 msg->FindFloat("height", &h); 375 BRect r(0, 0, w, h); 376 if (fCurrentOrientation == PrinterDriver::LANDSCAPE_ORIENTATION) 377 r.Set(0, 0, h, w); 378 379 // Save the printable_rect 380 BRect margin = fMarginView->Margin(); 381 if (fCurrentOrientation == PrinterDriver::PORTRAIT_ORIENTATION) { 382 margin.right = w - margin.right; 383 margin.bottom = h - margin.bottom; 384 } else { 385 margin.right = h - margin.right; 386 margin.bottom = w - margin.bottom; 387 } 388 389 SetRect(fSetupMsg, "paper_rect", r); 390 SetRect(fSetupMsg, "printable_rect", margin); 391 SetInt32(fSetupMsg, "units", fMarginView->Unit()); 392 SetString(fSetupMsg, "pdf_paper_size", item->Label()); 393 } 394 395 BMessage fonts; 396 if (fFonts->Archive(&fonts) == B_OK) { 397 fSetupMsg->RemoveName("fonts"); 398 fSetupMsg->AddMessage("fonts", &fonts); 399 } 400 401 // advanced settings 402 BString value; 403 if (fAdvancedSettings.FindString("pdflib_license_key", &value) == B_OK) 404 SetString(fSetupMsg, "pdflib_license_key", value); 405 406 bool webLinks; 407 if (fAdvancedSettings.FindBool("create_web_links", &webLinks) == B_OK) 408 SetBool(fSetupMsg, "create_web_links", webLinks); 409 410 float linkBorder; 411 if (fAdvancedSettings.FindFloat("link_border_width", &linkBorder) == B_OK) 412 SetFloat(fSetupMsg, "link_border_width", linkBorder); 413 414 bool createBookmarks; 415 if (fAdvancedSettings.FindBool("create_bookmarks", &createBookmarks) == B_OK) 416 SetBool(fSetupMsg, "create_bookmarks", createBookmarks); 417 418 if (fAdvancedSettings.FindString("bookmark_definition_file", &value) == B_OK) 419 SetString(fSetupMsg, "bookmark_definition_file", value); 420 421 bool createXrefs; 422 if (fAdvancedSettings.FindBool("create_xrefs", &createXrefs) == B_OK) 423 SetBool(fSetupMsg, "create_xrefs", createXrefs); 424 425 if (fAdvancedSettings.FindString("xrefs_file", &value) == B_OK) 426 SetString(fSetupMsg, "xrefs_file", value.String()); 427 428 int32 closeOption; 429 if (fAdvancedSettings.FindInt32("close_option", &closeOption) == B_OK) 430 SetInt32(fSetupMsg, "close_option", closeOption); 431} 432