/* * Copyright 2002-2011, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Michael Pfeiffer */ #include "ConfigWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pr_server.h" #include "Printer.h" #include "PrintServerApp.h" #include "PrintUtils.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "ConfigWindow" static const float a0_width = 2380.0; static const float a0_height = 3368.0; static const float a1_width = 1684.0; static const float a1_height = 2380.0; static const float a2_width = 1190.0; static const float a2_height = 1684.0; static const float a3_width = 842.0; static const float a3_height = 1190.0; static const float a4_width = 595.0; static const float a4_height = 842.0; static const float a5_width = 421.0; static const float a5_height = 595.0; static const float a6_width = 297.0; static const float a6_height = 421.0; static const float b5_width = 501.0; static const float b5_height = 709.0; static const float letter_width = 612.0; static const float letter_height = 792.0; static const float legal_width = 612.0; static const float legal_height = 1008.0; static const float ledger_width = 1224.0; static const float ledger_height = 792.0; static const float tabloid_width = 792.0; static const float tabloid_height = 1224.0; static const float jis_b5_width = 516.0; static const float jis_b5_height = 729.0; static struct PageFormat { const char *label; float width; float height; } pageFormat[] = { {B_TRANSLATE_MARK_COMMENT("Letter", "ANSI A (letter), a North American " "paper size"), letter_width, letter_height }, {B_TRANSLATE_MARK_COMMENT("Legal", "A North American paper size (216 x 356" " mm, or 8.5 x 14 in)"), legal_width, legal_height }, {B_TRANSLATE_MARK_COMMENT("Ledger", "ANSI B (ledger), a North American " "paper size"), ledger_width, ledger_height }, {B_TRANSLATE_MARK_COMMENT("Tabloid", "ANSI B (tabloid), a North American " "paper size"), tabloid_width, tabloid_height }, {B_TRANSLATE_MARK_COMMENT("A0", "ISO 216 paper size"), a0_width, a0_height }, {B_TRANSLATE_MARK_COMMENT("A1", "ISO 216 paper size"), a1_width, a1_height }, {B_TRANSLATE_MARK_COMMENT("A2", "ISO 216 paper size"), a2_width, a2_height }, {B_TRANSLATE_MARK_COMMENT("A3", "ISO 216 paper size"), a3_width, a3_height }, {B_TRANSLATE_MARK_COMMENT("A4", "ISO 216 paper size"), a4_width, a4_height }, {B_TRANSLATE_MARK_COMMENT("A5", "ISO 216 paper size"), a5_width, a5_height }, {B_TRANSLATE_MARK_COMMENT("A6", "ISO 216 paper size"), a6_width, a6_height }, {B_TRANSLATE_MARK_COMMENT("B5", "ISO 216 paper size"), b5_width, b5_height }, {B_TRANSLATE_MARK_COMMENT("B5 (JIS)", "JIS P0138 B5, a Japanese " "paper size"), jis_b5_width, jis_b5_height }, }; static void GetPageFormat(float w, float h, BString& label) { w = floor(w + 0.5); h = floor(h + 0.5); for (uint i = 0; i < sizeof(pageFormat) / sizeof(struct PageFormat); i ++) { struct PageFormat& pf = pageFormat[i]; if ((pf.width == w && pf.height == h) || (pf.width == h && pf.height == w)) { label = B_TRANSLATE_NOCOLLECT(pf.label); return; } } float unit = 72.0; // currently inches only label << (w / unit) << "x" << (h / unit) << " in."; } static BGroupLayoutBuilder LeftAlign(BView* view) { return BGroupLayoutBuilder(B_HORIZONTAL) .Add(view) .AddGlue() .SetInsets(0, 0, 0, 0); } ConfigWindow::ConfigWindow(config_setup_kind kind, Printer* defaultPrinter, BMessage* settings, AutoReply* sender) : BWindow(ConfigWindow::GetWindowFrame(), B_TRANSLATE("Page setup"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), fKind(kind), fDefaultPrinter(defaultPrinter), fSettings(settings), fSender(sender), fCurrentPrinter(NULL), fPageFormatText(NULL), fJobSetupText(NULL) { MimeTypeForSender(settings, fSenderMimeType); PrinterForMimeType(); if (kind == kJobSetup) SetTitle(B_TRANSLATE("Print setup")); BView* panel = new BBox(Bounds(), "temporary", B_FOLLOW_ALL, B_WILL_DRAW); AddChild(panel); // print selection pop up menu BPopUpMenu* menu = new BPopUpMenu(B_TRANSLATE("Select a printer")); SetupPrintersMenu(menu); fPrinters = new BMenuField(B_TRANSLATE("Printer:"), menu); // page format button fPageSetup = AddPictureButton(panel, "Paper setup", "PAGE_SETUP", MSG_PAGE_SETUP); // add description to button BStringView *pageFormatTitle = new BStringView("paperSetupTitle", B_TRANSLATE("Paper setup:")); fPageFormatText = new BStringView("pageSetupText", ""); // page selection button fJobSetup = NULL; BStringView* jobSetupTitle = NULL; if (kind == kJobSetup) { fJobSetup = AddPictureButton(panel, "Job setup", "JOB_SETUP", MSG_JOB_SETUP); // add description to button jobSetupTitle = new BStringView("jobSetupTitle", B_TRANSLATE("Print job setup:")); fJobSetupText = new BStringView("jobSetupText", ""); } // separator line BBox* separator = new BBox("separator"); separator->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1)); // Cancel & OK button BButton* cancel = new BButton("Cancel", B_TRANSLATE("Cancel"), new BMessage(B_QUIT_REQUESTED)); fOk = new BButton("OK", B_TRANSLATE("OK"), new BMessage(MSG_OK)); RemoveChild(panel); SetLayout(new BGroupLayout(B_VERTICAL)); BGroupLayoutBuilder builder(B_VERTICAL); builder .Add(fPrinters) .Add(BGroupLayoutBuilder(B_HORIZONTAL, 10) .Add(fPageSetup) .Add(BGroupLayoutBuilder(B_VERTICAL, 0) .Add(LeftAlign(pageFormatTitle)) .Add(LeftAlign(fPageFormatText)) .SetInsets(0, 0, 0, 0) ) .AddGlue() ); if (fJobSetup != NULL) { builder .Add(BGroupLayoutBuilder(B_HORIZONTAL, 10) .Add(fJobSetup) .Add(BGroupLayoutBuilder(B_VERTICAL, 0) .Add(LeftAlign(jobSetupTitle)) .Add(LeftAlign(fJobSetupText)) .SetInsets(0, 0, 0, 0) ) .AddGlue() ); } builder .AddGlue() .Add(separator) .Add(BGroupLayoutBuilder(B_HORIZONTAL) .AddGlue() .Add(cancel) .Add(fOk) ) .SetInsets(5, 5, 5, 5); AddChild(builder); AddShortcut('a', 0, new BMessage(B_ABOUT_REQUESTED)); SetDefaultButton(fOk); fPrinters->MakeFocus(true); UpdateSettings(true); } ConfigWindow::~ConfigWindow() { if (fCurrentPrinter) fCurrentPrinter->Release(); release_sem(fFinished); } void ConfigWindow::Go() { sem_id sid = create_sem(0, "finished"); if (sid >= 0) { fFinished = sid; Show(); acquire_sem(sid); delete_sem(sid); } else { Quit(); } } void ConfigWindow::MessageReceived(BMessage* m) { switch (m->what) { case MSG_PAGE_SETUP: Setup(kPageSetup); break; case MSG_JOB_SETUP: Setup(kJobSetup); break; case MSG_PRINTER_SELECTED: { BString printer; if (m->FindString("name", &printer) == B_OK) { UpdateAppSettings(fSenderMimeType.String(), printer.String()); PrinterForMimeType(); UpdateSettings(true); } break; } case MSG_OK: UpdateSettings(false); if (fKind == kPageSetup) fSender->SetReply(&fPageSettings); else fSender->SetReply(&fJobSettings); Quit(); break; case B_ABOUT_REQUESTED: AboutRequested(); break; default: BWindow::MessageReceived(m); } } void ConfigWindow::AboutRequested() { BString text = B_TRANSLATE("Printer server"); text << "\n" "© 2001-2010 Haiku, Inc.\n" "\n" "\tIthamar R. Adema\n" "\tMichael Pfeiffer\n"; BAlert *about = new BAlert("About printer server", text.String(), B_TRANSLATE("OK")); about->SetFlags(about->Flags() | B_CLOSE_ON_ESCAPE); about->Go(); } void ConfigWindow::FrameMoved(BPoint p) { BRect frame = GetWindowFrame(); frame.OffsetTo(p); SetWindowFrame(frame); } BRect ConfigWindow::GetWindowFrame() { BRect frame(0, 0, 10, 10); BAutolock lock(gLock); if (lock.IsLocked()) frame.OffsetBy(Settings::GetSettings()->ConfigWindowFrame().LeftTop()); frame.OffsetBy(30, 30); return frame; } void ConfigWindow::SetWindowFrame(BRect r) { BAutolock lock(gLock); if (lock.IsLocked()) Settings::GetSettings()->SetConfigWindowFrame(r); } BButton* ConfigWindow::AddPictureButton(BView* panel, const char* name, const char* picture, uint32 what) { BResources *res = BApplication::AppResources(); if (res == NULL) return NULL; size_t length; const void *bits = res->LoadResource('VICN', picture, &length); BButton* button = NULL; BBitmap* onBM = new BBitmap(BRect(0, 0, 24, 24), B_RGBA32); if (onBM != NULL) { if (BIconUtils::GetVectorIcon((uint8*)bits, length, onBM) != B_OK) { delete onBM; return NULL; } button = new BButton(name, new BMessage(what)); button->SetIcon(onBM, B_TRIM_ICON_BITMAP_KEEP_ASPECT); button->SetViewColor(B_TRANSPARENT_COLOR); button->SetLabel(NULL); } delete onBM; return button; } void ConfigWindow::PrinterForMimeType() { BAutolock lock(gLock); if (fCurrentPrinter) { fCurrentPrinter->Release(); fCurrentPrinter = NULL; } if (lock.IsLocked()) { Settings* s = Settings::GetSettings(); AppSettings* app = s->FindAppSettings(fSenderMimeType.String()); if (app) fPrinterName = app->GetPrinter(); else fPrinterName = fDefaultPrinter ? fDefaultPrinter->Name() : ""; fCurrentPrinter = Printer::Find(fPrinterName); if (fCurrentPrinter) fCurrentPrinter->Acquire(); } } void ConfigWindow::SetupPrintersMenu(BMenu* menu) { // clear menu while (menu->CountItems() != 0) delete menu->RemoveItem((int32)0); // fill menu with printer names BAutolock lock(gLock); if (lock.IsLocked()) { BString n; BMessage* m; BMenuItem* item; for (int i = 0; i < Printer::CountPrinters(); i ++) { Printer::At(i)->GetName(n); m = new BMessage(MSG_PRINTER_SELECTED); m->AddString("name", n.String()); menu->AddItem(item = new BMenuItem(n.String(), m)); if (n == fPrinterName) item->SetMarked(true); } } } void ConfigWindow::UpdateAppSettings(const char* mime, const char* printer) { BAutolock lock(gLock); if (lock.IsLocked()) { Settings* s = Settings::GetSettings(); AppSettings* app = s->FindAppSettings(mime); if (app) app->SetPrinter(printer); else s->AddAppSettings(new AppSettings(mime, printer)); } } void ConfigWindow::UpdateSettings(bool read) { BAutolock lock(gLock); if (lock.IsLocked()) { Settings* s = Settings::GetSettings(); PrinterSettings* p = s->FindPrinterSettings(fPrinterName.String()); if (p == NULL) { p = new PrinterSettings(fPrinterName.String()); s->AddPrinterSettings(p); } ASSERT(p != NULL); if (read) { fPageSettings = *p->GetPageSettings(); fJobSettings = *p->GetJobSettings(); } else { p->SetPageSettings(&fPageSettings); p->SetJobSettings(&fJobSettings); } } UpdateUI(); } void ConfigWindow::UpdateUI() { if (fCurrentPrinter == NULL) { fPageSetup->SetEnabled(false); if (fJobSetup) { fJobSetup->SetEnabled(false); fJobSetupText->SetText(B_TRANSLATE("Undefined")); } fOk->SetEnabled(false); fPageFormatText->SetText(B_TRANSLATE("Undefined")); } else { fPageSetup->SetEnabled(true); if (fJobSetup) fJobSetup->SetEnabled(fKind == kJobSetup && !fPageSettings.IsEmpty()); fOk->SetEnabled((fKind == kJobSetup && !fJobSettings.IsEmpty()) || (fKind == kPageSetup && !fPageSettings.IsEmpty())); // display information about page format BRect paperRect; BString pageFormat; if (fPageSettings.FindRect(PSRV_FIELD_PAPER_RECT, &paperRect) == B_OK) { GetPageFormat(paperRect.Width(), paperRect.Height(), pageFormat); int32 orientation = 0; fPageSettings.FindInt32(PSRV_FIELD_ORIENTATION, &orientation); if (orientation == 0) pageFormat << ", " << B_TRANSLATE("Portrait"); else pageFormat << ", " << B_TRANSLATE("Landscape"); } else pageFormat << B_TRANSLATE("Undefined"); fPageFormatText->SetText(pageFormat.String()); // display information about job if (fKind == kJobSetup) { BString job; int32 first, last, copies; if (fJobSettings.FindInt32(PSRV_FIELD_FIRST_PAGE, &first) == B_OK && fJobSettings.FindInt32(PSRV_FIELD_LAST_PAGE, &last) == B_OK) { bool printRange = first >= 1 && first <= last && last != INT_MAX; char number[12]; if (fJobSettings.FindInt32(PSRV_FIELD_COPIES, &copies) == B_OK && copies > 1) { if (printRange) { job = B_TRANSLATE("Page %1 to %2, %3 copies"); snprintf(number, sizeof(number), "%d", (int)first); job.ReplaceFirst("%1", number); snprintf(number, sizeof(number), "%d", (int)last); job.ReplaceFirst("%2", number); snprintf(number, sizeof(number), "%d", (int)copies); job.ReplaceFirst("%3", number); } else { job = B_TRANSLATE("All pages, %1 copies"); snprintf(number, sizeof(number), "%d", (int)copies); job.ReplaceFirst("%1", number); } } else { if (printRange) { job = B_TRANSLATE("Page %1 to %2"); snprintf(number, sizeof(number), "%d", (int)first); job.ReplaceFirst("%1", number); snprintf(number, sizeof(number), "%d", (int)last); job.ReplaceFirst("%2", number); } else job = B_TRANSLATE("All pages"); } } else job << B_TRANSLATE("Undefined"); fJobSetupText->SetText(job.String()); } } } void ConfigWindow::Setup(config_setup_kind kind) { if (fCurrentPrinter) { Hide(); if (kind == kPageSetup) { BMessage settings = fPageSettings; if (fCurrentPrinter->ConfigurePage(settings) == B_OK) { fPageSettings = settings; if (!fJobSettings.IsEmpty()) AddFields(&fJobSettings, &fPageSettings); } } else { BMessage settings; if (fJobSettings.IsEmpty()) settings = fPageSettings; else settings = fJobSettings; if (fCurrentPrinter->ConfigureJob(settings) == B_OK) fJobSettings = settings; } UpdateUI(); Show(); } }