/*****************************************************************************/ // ConfigWindow // // Author // Michael Pfeiffer // // This application and all source files used in its construction, except // where noted, are licensed under the MIT License, and have been written // and are: // // Copyright (c) 2002 OpenBeOS Project // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. /*****************************************************************************/ #include "pr_server.h" #include "Printer.h" #include "PrintServerApp.h" #include "ConfigWindow.h" #include "BeUtils.h" // posix #include #include #include #include // BeOS #include #include #include 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 p11x17_width = 792.0; static const float p11x17_height = 1224.0; static struct PageFormat { char *label; float width; float height; } pageFormat[] = { {"Letter", letter_width, letter_height }, {"Legal", legal_width, legal_height }, {"Ledger", ledger_width, ledger_height }, {"p11x17", p11x17_width, p11x17_height }, {"A0", a0_width, a0_height }, {"A1", a1_width, a1_height }, {"A2", a2_width, a2_height }, {"A3", a3_width, a3_height }, {"A4", a4_width, a4_height }, {"A5", a5_width, a5_height }, {"A6", a6_width, a6_height }, {"B5", b5_width, 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 = pf.label; return; } } float unit = 72.0; // currently inc[h]es only label << (w / unit) << "x" << (h / unit) << " in."; } ConfigWindow::ConfigWindow(config_setup_kind kind, Printer* defaultPrinter, BMessage* settings, AutoReply* sender) : BWindow(ConfigWindow::GetWindowFrame(), "Page Setup", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE) , fKind(kind) , fDefaultPrinter(defaultPrinter) , fSettings(settings) , fSender(sender) , fCurrentPrinter(NULL) { MimeTypeForSender(settings, fSenderMimeType); PrinterForMimeType(); if (kind == kJobSetup) SetTitle("Print Setup"); BView* panel = new BBox(Bounds(), "top_panel", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, B_PLAIN_BORDER); AddChild(panel); float left = 10, top = 5; BRect r(left, top, 160, 15); // print selection popup menu BPopUpMenu* menu = new BPopUpMenu("Select a Printer"); SetupPrintersMenu(menu); fPrinters = new BMenuField(r, "Printer", "Printer", menu); fPrinters->SetDivider(40); panel->AddChild(fPrinters); top += fPrinters->Bounds().Height() + 10; // page format button r.OffsetTo(left, top); fPageSetup = AddPictureButton(panel, r, "Page Format", "PAGE_SETUP_ON", "PAGE_SETUP_OFF", MSG_PAGE_SETUP); // add description to button r.OffsetTo(left + fPageSetup->Bounds().Width() + 5, top + 5); AddStringView(panel, r, "Setup page format"); r.OffsetBy(0, 10); fPageFormatText = AddStringView(panel, r, ""); top += fPageSetup->Bounds().Height() + 5; // page selection button fJobSetup = NULL; if (kind == kJobSetup) { r.OffsetTo(left, top); fJobSetup = AddPictureButton(panel, r, "Page Selection", "JOB_SETUP_ON", "JOB_SETUP_OFF", MSG_JOB_SETUP); // add description to button r.OffsetTo(left + fJobSetup->Bounds().Width() + 5, top + 5); AddStringView(panel, r, "Setup print job"); r.OffsetBy(0, 10); fJobSetupText = AddStringView(panel, r, ""); top += fJobSetup->Bounds().Height() + 5; } top += 5; // separator line BRect line(Bounds()); line.OffsetTo(0, top); line.bottom = line.top+1; AddChild(new BBox(line, "line", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP)); top += 10; // Cancel button r.OffsetTo(left, top); BButton* cancel = new BButton(r, "Cancel", "Cancel", new BMessage(B_QUIT_REQUESTED)); panel->AddChild(cancel); cancel->ResizeToPreferred(); left = cancel->Frame().right + 10; // OK button r.OffsetTo(left, top); fOk = new BButton(r, "OK", "OK", new BMessage(MSG_OK)); panel->AddChild(fOk); fOk->ResizeToPreferred(); top += fOk->Bounds().Height() + 10; // resize window ResizeTo(fOk->Frame().right + 10, top); AddShortcut('i', 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); fSender->SetReply(fKind == kPageSetup ? &fPageSettings : &fJobSettings); Quit(); break; case B_ABOUT_REQUESTED: AboutRequested(); break; default: inherited::MessageReceived(m); } } static const char* kAbout = "Printer Server\n" "© 2001, 2002 OpenBeOS\n" "\n" "\tIthamar R. Adema - Initial Implementation\n" "\tMichael Pfeiffer - Release 1 and beyond\n" ; void ConfigWindow::AboutRequested() { BAlert *about = new BAlert("About Printer Server", kAbout, "Cool"); BTextView *v = about->TextView(); if (v) { rgb_color red = {255, 0, 51, 255}; rgb_color blue = {0, 102, 255, 255}; v->SetStylable(true); char *text = (char*)v->Text(); char *s = text; // set all Be in blue and red while ((s = strstr(s, "Be")) != NULL) { int32 i = s - text; v->SetFontAndColor(i, i+1, NULL, 0, &blue); v->SetFontAndColor(i+1, i+2, NULL, 0, &red); s += 2; } // first text line s = strchr(text, '\n'); BFont font; v->GetFontAndColor(0, &font); font.SetSize(12); v->SetFontAndColor(0, s-text+1, &font, B_FONT_SIZE); }; about->Go(); } void ConfigWindow::FrameMoved(BPoint p) { BRect frame = GetWindowFrame(); frame.OffsetTo(p); SetWindowFrame(frame); } BRect ConfigWindow::GetWindowFrame() { BAutolock lock(gLock); if (lock.IsLocked()) { return Settings::GetSettings()->ConfigWindowFrame(); } return BRect(30, 30, 300, 300); } void ConfigWindow::SetWindowFrame(BRect r) { BAutolock lock(gLock); if (lock.IsLocked()) { Settings::GetSettings()->SetConfigWindowFrame(r); } } BPictureButton* ConfigWindow::AddPictureButton(BView* panel, BRect frame, const char* name, const char* on, const char* off, uint32 what) { BBitmap* onBM = LoadBitmap(on); BBitmap* offBM = LoadBitmap(off); BPicture* onPict = BitmapToPicture(panel, onBM); BPicture* offPict = BitmapToPicture(panel, offBM); BPictureButton* button = NULL; if (onPict != NULL && offPict != NULL) { button = new BPictureButton(frame, name, onPict, offPict, new BMessage(what)); button->SetViewColor(B_TRANSPARENT_COLOR); panel->AddChild(button); onBM->Lock(); button->ResizeTo(onBM->Bounds().Width(), onBM->Bounds().Height()); onBM->Unlock(); BPicture* disabled = BitmapToGrayedPicture(panel, offBM); button->SetDisabledOn(disabled); delete disabled; disabled = BitmapToGrayedPicture(panel, onBM); button->SetDisabledOff(disabled); delete disabled; } delete onPict; delete offPict; delete onBM; delete offBM; return button; } BStringView* ConfigWindow::AddStringView(BView* panel, BRect frame, const char* text) { // frame.bottom = frame.top ; BStringView* string = new BStringView(frame, "", text); string->SetViewColor(panel->ViewColor()); string->SetLowColor(panel->ViewColor()); panel->AddChild(string); return string; } 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 for (int i = menu->CountItems() - 1; i >= 0; i --) { delete menu->RemoveItem(i); } // 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("Undefined job settings"); } fOk->SetEnabled(false); fPageFormatText->SetText("Undefined paper format"); } 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 << ", Portrait"; else pageFormat << ", Landscape"; } else { pageFormat << "Undefined paper format"; } fPageFormatText->SetText(pageFormat.String()); // display information about job if (fKind == kJobSetup) { BString job; int32 first, last; if (fJobSettings.FindInt32(PSRV_FIELD_FIRST_PAGE, &first) == B_OK && fJobSettings.FindInt32(PSRV_FIELD_LAST_PAGE, &last) == B_OK) { if (first >= 1 && first <= last && last != INT_MAX) { job << "From page " << first << " to " << last; } else { job << "All pages"; } int32 copies; if (fJobSettings.FindInt32(PSRV_FIELD_COPIES, &copies) == B_OK && copies > 1) { job << ", " << copies << " copies"; } } else { job << "Undefined job settings"; } 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(); } }