diff --git a/src/add-ons/print/drivers/preview/Driver.cpp b/src/add-ons/print/drivers/preview/Driver.cpp new file mode 100644 index 0000000000..cdfe864f53 --- /dev/null +++ b/src/add-ons/print/drivers/preview/Driver.cpp @@ -0,0 +1,144 @@ +/* + +PDF Writer printer driver. + +Copyright (c) 2001 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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 +#include + +#include + +#include "Driver.h" +#include "PrinterDriver.h" + +// -------------------------------------------------- +BMessage* +take_job(BFile *spoolFile, BNode *spoolDir, BMessage *msg) +{ + PrinterDriver *driver; + + driver = instanciate_driver(spoolDir); + if (driver->PrintJob(spoolFile, msg) == B_OK) { + msg = new BMessage('okok'); + } else { + msg = new BMessage('baad'); + } + delete driver; + + return msg; +} + + +// -------------------------------------------------- +BMessage* +config_page(BNode *spoolDir, BMessage *msg) +{ + BMessage *pagesetupMsg = new BMessage(*msg); + PrinterDriver *driver; + const char *printerName; + char buffer[B_ATTR_NAME_LENGTH+1]; + + // retrieve the printer (spool) name. + printerName = NULL; + if (spoolDir->ReadAttr("Printer Name", B_STRING_TYPE, 1, buffer, B_ATTR_NAME_LENGTH+1) > 0) { + printerName = buffer; + } + + driver = instanciate_driver(spoolDir); + if (driver->PageSetup(pagesetupMsg, printerName) == B_OK) { + pagesetupMsg->what = 'okok'; + } else { + delete pagesetupMsg; + pagesetupMsg = NULL; + } + + delete driver; + + return pagesetupMsg; +} + + +// -------------------------------------------------- +BMessage* +config_job(BNode *spoolDir, BMessage *msg) +{ + BMessage *jobsetupMsg = new BMessage(*msg); + PrinterDriver *driver; + const char *printerName; + char buffer[B_ATTR_NAME_LENGTH+1]; + + // retrieve the printer (spool) name. + printerName = NULL; + if (spoolDir->ReadAttr("Printer Name", B_STRING_TYPE, 1, buffer, B_ATTR_NAME_LENGTH+1) > 0) { + printerName = buffer; + } + driver = instanciate_driver(spoolDir); + if (driver->JobSetup(jobsetupMsg, printerName) == B_OK) { + jobsetupMsg->what = 'okok'; + } else { + delete jobsetupMsg; + jobsetupMsg = NULL; + } + + delete driver; + + return jobsetupMsg; +} + + +// -------------------------------------------------- +char* +add_printer(char *printerName) +{ + PrinterDriver* driver; + driver = instanciate_driver(NULL); + if (driver->PrinterSetup(printerName) == B_OK) { + return printerName; + } else { + return NULL; + } +} + +/** + * default_settings + * + * @param BNode* printer spool directory + * @return BMessage* the settings + */ +BMessage* +default_settings(BNode* spoolDir) +{ + PrinterDriver* driver; + BMessage* settings; + driver = instanciate_driver(spoolDir); + settings = driver->GetDefaultSettings(); + delete driver; + return settings; +} diff --git a/src/add-ons/print/drivers/preview/Driver.h b/src/add-ons/print/drivers/preview/Driver.h new file mode 100644 index 0000000000..c0858ce82d --- /dev/null +++ b/src/add-ons/print/drivers/preview/Driver.h @@ -0,0 +1,47 @@ +/* + +PDF Writer printer driver. + +Copyright (c) 2002 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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 + +extern "C" +{ +__declspec(dllexport) BMessage * take_job(BFile * spool_file, BNode * spool_dir, BMessage * msg); +__declspec(dllexport) BMessage * config_page(BNode * spool_dir, BMessage * msg); +__declspec(dllexport) BMessage * config_job(BNode * spool_dir, BMessage * msg); +__declspec(dllexport) char * add_printer(char * printer_name); +__declspec(dllexport) BMessage * default_settings(BNode * printer); +} + +class PrinterDriver; + +// instanciate_driver has to be implemented by the printer driver +PrinterDriver *instanciate_driver(BNode *spoolDir); + diff --git a/src/add-ons/print/drivers/preview/DriverTemplate.cpp b/src/add-ons/print/drivers/preview/DriverTemplate.cpp new file mode 100644 index 0000000000..2668388a1d --- /dev/null +++ b/src/add-ons/print/drivers/preview/DriverTemplate.cpp @@ -0,0 +1,19 @@ +extern "C" _EXPORT char * add_printer(char * printer_name) { + return printer_name; +} + +extern "C" _EXPORT BMessage * config_page(BNode * spool_dir, BMessage * msg) { + return NULL; +} + +extern "C" _EXPORT BMessage * config_job(BNode * spool_dir, BMessage * msg) { + return NULL; +} + +extern "C" _EXPORT BMessage * default_settings(BNode * printer) { + return NULL; +} + +extern "C" _EXPORT BMessage * take_job(BFile * spool_file, BNode * spool_dir, BMessage * msg) { + return NULL; +} diff --git a/src/add-ons/print/drivers/preview/InterfaceUtils.cpp b/src/add-ons/print/drivers/preview/InterfaceUtils.cpp new file mode 100644 index 0000000000..10bef48900 --- /dev/null +++ b/src/add-ons/print/drivers/preview/InterfaceUtils.cpp @@ -0,0 +1,341 @@ +/* + +InterfaceUtils.cpp + +Copyright (c) 2002 OpenBeOS. + +Author: + Michael Pfeiffer + +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 +#include +#include "InterfaceUtils.h" +#include "Utils.h" + +// Implementation of HWindow + +// -------------------------------------------------- +HWindow::HWindow(BRect frame, const char *title, window_type type, uint32 flags, uint32 workspace, uint32 escape_msg) + : BWindow(frame, title, type, flags, workspace) +{ + Init(escape_msg); +} + + +// -------------------------------------------------- +HWindow::HWindow(BRect frame, const char *title, window_look look, window_feel feel, uint32 flags, uint32 workspace, uint32 escape_msg) + : BWindow(frame, title, look, feel, flags, workspace) +{ + Init(escape_msg); +} + + +// -------------------------------------------------- +void +HWindow::Init(uint32 escape_msg) +{ + AddShortcut('i', 0, new BMessage(B_ABOUT_REQUESTED)); + AddCommonFilter(new EscapeMessageFilter(this, escape_msg)); +} + + +// -------------------------------------------------- +void +HWindow::MessageReceived(BMessage* msg) +{ + if (msg->what == B_ABOUT_REQUESTED) { + AboutRequested(); + } else { + inherited::MessageReceived(msg); + } +} + +// -------------------------------------------------- +void +HWindow::AboutRequested() +{ + BAlert *about = new BAlert("About Preview", 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); // font.SetFace(B_OUTLINED_FACE); + v->SetFontAndColor(0, s-text+1, &font, B_FONT_SIZE); + }; + about->Go(); +} + + +// Implementation of BlockingWindow + +BlockingWindow::BlockingWindow(BRect frame, const char *title, window_type type, uint32 flags, uint32 workspace, uint32 escape_msg) + : HWindow(frame, title, type, flags, workspace) +{ + Init(title); +} + +BlockingWindow::BlockingWindow(BRect frame, const char *title, window_look look, window_feel feel, uint32 flags, uint32 workspace, uint32 escape_msg) + : HWindow(frame, title, look, feel, flags, workspace) +{ + Init(title); +} + +BlockingWindow::~BlockingWindow() +{ + delete_sem(fExitSem); +} + +void +BlockingWindow::Init(const char* title) +{ + fResult = NULL; + fExitSem = create_sem(0, title); + fReadyToQuit = false; +} + +bool +BlockingWindow::QuitRequested() { + if (fReadyToQuit) { + return true; + } else { + release_sem(fExitSem); + return false; + } +} + +void +BlockingWindow::Quit() { + fReadyToQuit = false; // finally allow window to quit + inherited::Quit(); // and quit it +} + +void +BlockingWindow::Quit(status_t result) { + if (fResult) { + *fResult = result; + } + release_sem(fExitSem); +} + +status_t +BlockingWindow::Go() { + status_t result = B_ERROR; + fResult = &result; + Show(); + acquire_sem(fExitSem); + // here the window still exists, because QuitRequested returns false if fReadyToQuit is false + // now we can quit the window and am sure that the window thread dies before this thread + if (Lock()) { + Quit(); + } else { + ASSERT(false); // should not reach here!!! + } + // here the window does not exist, good to have the result in a local variable + return result; +} + +// Impelementation of TextView + +// -------------------------------------------------- +TextView::TextView(BRect frame, + const char *name, + BRect textRect, + uint32 rmask, + uint32 flags) + : BTextView(frame, name, textRect, rmask, flags) +{ +} + + +// -------------------------------------------------- +TextView::TextView(BRect frame, + const char *name, + BRect textRect, + const BFont *font, const rgb_color *color, + uint32 rmask, + uint32 flags) + : BTextView(frame, name, textRect, font, color, rmask, flags) +{ +} + + +// -------------------------------------------------- +void +TextView::KeyDown(const char *bytes, int32 numBytes) +{ + if (numBytes == 1 && *bytes == B_TAB) { + BView::KeyDown(bytes, numBytes); + return; + } + inherited::KeyDown(bytes, numBytes); +} + + +// -------------------------------------------------- +void +TextView::Draw(BRect update) +{ + inherited::Draw(update); + if (IsFocus()) { + // stroke focus rectangle + SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); + StrokeRect(Bounds()); + } +} + + +// -------------------------------------------------- +void +TextView::MakeFocus(bool focus) +{ + Invalidate(); + inherited::MakeFocus(focus); + // notify TextControl + BView* parent = Parent(); // BBox + if (focus && parent) { + parent = parent->Parent(); // TextControl + TextControl* control = dynamic_cast(parent); + if (control) control->FocusSetTo(this); + } +} + + +// Impelementation of TextControl + +// -------------------------------------------------- +TextControl::TextControl(BRect frame, + const char *name, + const char *label, + const char *initial_text, + BMessage *message, + uint32 rmask, + uint32 flags) + : BView(frame, name, rmask, flags) +{ + SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + BRect r(0, 0, frame.Width() / 2 -1, frame.Height()); + fLabel = new BStringView(r, "", label); + BRect f(r); + f.OffsetTo(frame.Width() / 2 + 1, 0); + // box around TextView + BBox *box = new BBox(f, "", B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW); + f.OffsetTo(0, 0); + f.InsetBy(1,1); + r.InsetBy(2,2); + fText = new TextView(f, "", r, rmask, flags | B_NAVIGABLE); + fText->SetWordWrap(false); + fText->DisallowChar('\n'); + fText->Insert(initial_text); + AddChild(fLabel); + AddChild(box); + box->AddChild(fText); +} + + +// -------------------------------------------------- +void +TextControl::ConvertToParent(BView* parent, BView* child, BRect &rect) +{ + do { + child->ConvertToParent(&rect); + child = child->Parent(); + } while (child != NULL && child != parent); +} + + +// -------------------------------------------------- +void +TextControl::FocusSetTo(BView *child) +{ + BRect r; + BView* parent = Parent(); // Table + if (parent) { + ConvertToParent(parent, child, r); + parent->ScrollTo(0, r.top); + } +} + + +// Impelementation of Implementation of Table + +// -------------------------------------------------- +Table::Table(BRect frame, const char *name, uint32 rmode, uint32 flags) + : BView(frame, name, rmode, flags) +{ +} + + +// -------------------------------------------------- +void +Table::ScrollTo(BPoint p) +{ + float h = Frame().Height()+1; + if (Parent()) { + BScrollView* scrollView = dynamic_cast(Parent()); + if (scrollView) { + BScrollBar *sb = scrollView->ScrollBar(B_VERTICAL); + float min, max; + sb->GetRange(&min, &max); + if (p.y < (h/2)) p.y = 0; + else if (p.y > max) p.y = max; + } + } + inherited::ScrollTo(p); +} + + +// Impelementation of DragListView + +// -------------------------------------------------- +DragListView::DragListView(BRect frame, const char *name, + list_view_type type, + uint32 resizingMode, uint32 flags) + : BListView(frame, name, type, resizingMode, flags) +{ +} + +// -------------------------------------------------- +bool DragListView::InitiateDrag(BPoint point, int32 index, bool wasSelected) +{ + BMessage m; + DragMessage(&m, ItemFrame(index), this); + return true; +} + + + diff --git a/src/add-ons/print/drivers/preview/InterfaceUtils.h b/src/add-ons/print/drivers/preview/InterfaceUtils.h new file mode 100644 index 0000000000..dbd923fd6b --- /dev/null +++ b/src/add-ons/print/drivers/preview/InterfaceUtils.h @@ -0,0 +1,147 @@ +/* + +InterfaceUtils.cpp + +Copyright (c) 2002 OpenBeOS. + +Author: + Michael Pfeiffer + +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. + +*/ + +#ifndef _INTERFACE_UTILS_H +#define _INTERFACE_UTILS_H + +#include + +// Text to be displayed in About window, declared in the application +// that uses HWindow class!!! +extern const char* kAbout; + +// -------------------------------------------------- +class HWindow : public BWindow +{ +protected: + void Init(uint32 escape_msg); + +public: + typedef BWindow inherited; + + HWindow(BRect frame, const char *title, window_type type, uint32 flags, uint32 workspace = B_CURRENT_WORKSPACE, uint32 escape_msg = B_QUIT_REQUESTED); + HWindow(BRect frame, const char *title, window_look look, window_feel feel, uint32 flags, uint32 workspace = B_CURRENT_WORKSPACE, uint32 escape_msg = B_QUIT_REQUESTED); + + virtual void MessageReceived(BMessage* m); + virtual void AboutRequested(); +}; + +// -------------------------------------------------- +class BlockingWindow : public HWindow +{ +public: + BlockingWindow(BRect frame, const char *title, window_type type, uint32 flags, uint32 workspace = B_CURRENT_WORKSPACE, uint32 escape_msg = B_QUIT_REQUESTED); + BlockingWindow(BRect frame, const char *title, window_look look, window_feel feel, uint32 flags, uint32 workspace = B_CURRENT_WORKSPACE, uint32 escape_msg = B_QUIT_REQUESTED); + ~BlockingWindow(); + + bool QuitRequested(); + // Quit() is called by child class with result code + void Quit(status_t result); + // Show window and wait for it to quit, returns result code + status_t Go(); + // Or quit window e.g. something went wrong in constructor + void Quit(); + + typedef HWindow inherited; + +private: + void Init(const char* title); + + bool fReadyToQuit; + sem_id fExitSem; + status_t* fResult; +}; + +// -------------------------------------------------- +class TextView : public BTextView +{ +public: + typedef BTextView inherited; + + TextView(BRect frame, + const char *name, + BRect textRect, + uint32 rmask = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + + TextView(BRect frame, + const char *name, + BRect textRect, + const BFont *font, const rgb_color *color, + uint32 rmask = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + + void KeyDown(const char *bytes, int32 numBytes); + void MakeFocus(bool focus = true); + void Draw(BRect r); +}; + + +// -------------------------------------------------- +class TextControl : public BView +{ + BStringView *fLabel; + TextView *fText; +public: + TextControl(BRect frame, + const char *name, + const char *label, + const char *initial_text, + BMessage *message, + uint32 rmask = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE); + const char *Label() { return fLabel->Text(); } + const char *Text() { return fText->Text(); } + void MakeFocus(bool focus = true) { fText->MakeFocus(focus); } + void ConvertToParent(BView* parent, BView* child, BRect &rect); + void FocusSetTo(BView* child); +}; + + +// -------------------------------------------------- +class Table : public BView +{ +public: + typedef BView inherited; + + Table(BRect frame, const char *name, uint32 rmode, uint32 flags); + void ScrollTo(BPoint p); +}; + +class DragListView : public BListView +{ +public: + DragListView(BRect frame, const char *name, + list_view_type type = B_SINGLE_SELECTION_LIST, + uint32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, + uint32 flags = B_WILL_DRAW | B_NAVIGABLE | B_FRAME_EVENTS); + bool InitiateDrag(BPoint point, int32 index, bool wasSelected); +}; + +#endif diff --git a/src/add-ons/print/drivers/preview/Jamfile b/src/add-ons/print/drivers/preview/Jamfile new file mode 100644 index 0000000000..38a732dd22 --- /dev/null +++ b/src/add-ons/print/drivers/preview/Jamfile @@ -0,0 +1,20 @@ +SubDir OBOS_TOP src add-ons print drivers preview ; + +UsePrivateHeaders interface print ; + +AddResources Preview : Preview.rsrc ; + +Addon Preview : print : + Utils.cpp + InterfaceUtils.cpp + MarginView.cpp + PrinterSetupWindow.cpp + PageSetupWindow.cpp + JobSetupWindow.cpp + Driver.cpp + PrinterDriver.cpp + Preview.cpp +; + +LinkSharedOSLibs Preview : be root libprint.a ; + diff --git a/src/add-ons/print/drivers/preview/JobSetupWindow.cpp b/src/add-ons/print/drivers/preview/JobSetupWindow.cpp new file mode 100644 index 0000000000..7b27a4b829 --- /dev/null +++ b/src/add-ons/print/drivers/preview/JobSetupWindow.cpp @@ -0,0 +1,276 @@ +/* + +Preview printer driver. + +Copyright (c) 2003 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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 +#include +#include + +#include "PrinterDriver.h" +#include "JobSetupWindow.h" + +// -------------------------------------------------- +JobSetupWindow::JobSetupWindow(BMessage *msg, const char * printerName) + : BlockingWindow(BRect(0, 0, 320, 160), "Job Setup", B_TITLED_WINDOW_LOOK, + B_MODAL_APP_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | + B_NOT_ZOOMABLE) +{ + MoveTo(300, 300); + + fSetupMsg = msg; + + if (printerName) { + BString title; + title << printerName << " Job Setup"; + SetTitle(title.String()); + fPrinterName = printerName; + } + + // ---- Ok, build a default job setup user interface + BRect r; + BBox *panel; + BBox *line; + BButton *ok; + BButton *cancel; + BStringView *sv; + float x, y, w, h; + float indent; + int32 copies; + int32 firstPage; + int32 lastPage; + bool allPages; + char buffer[80]; + + // PrinterDriver ensures that property exists + fSetupMsg->FindInt32("copies", &copies); + fSetupMsg->FindInt32("first_page", &firstPage); + fSetupMsg->FindInt32("last_page", &lastPage); + + allPages = firstPage == 1 && lastPage == MAX_INT32; + + r = Bounds(); + + // add a *dialog* background + panel = new BBox(r, "top_panel", B_FOLLOW_ALL, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, + B_PLAIN_BORDER); + + const int kMargin = 6; + + //const char *kCopiesLabel = "Copies:"; + const char *kCopiesLabelExtraSpace = "Copies:##"; + const char *kPagesRangeLabel = "Pages:"; + const char *kAllPagesLabel = "All"; + const char *kPagesRangeSelectionLabel = ""; + const char *kFromLabel = "From:"; + const char *kFromLabelExtraSpace = "From:##"; + const char *kToLabel = "To:"; + const char *kToLabelExtraSpace = "To:##"; + + r = panel->Bounds(); + + x = r.left + kMargin; + y = r.top + kMargin; + + + // add a "copies" input field + +/* Simon: temporarily removed this code + sprintf(buffer, "%d", (int)copies); + fCopies = new BTextControl(BRect(x, y, x+100, y+20), "copies", kCopiesLabel, + buffer, new BMessage(NB_COPIES_MSG)); + fCopies->SetAlignment(B_ALIGN_LEFT, B_ALIGN_RIGHT); + fCopies->ResizeToPreferred(); + fCopies->GetPreferredSize(&w, &h); + panel->AddChild(fCopies); + + y += h + kMargin; // "new line" +*/ + // add a "pages" label + sv = new BStringView(BRect(x, y, x+100, y+20), "pages_range", kPagesRangeLabel); + panel->AddChild(sv); + sv->ResizeToPreferred(); + sv->GetPreferredSize(&w, &h); + + // align "copies" textcontrol field on the "allPages" radiobutton bellow... + indent = be_plain_font->StringWidth(kCopiesLabelExtraSpace); + w += kMargin; + if ( w > indent ) + indent = w; + // fCopies->SetDivider(indent); + + x += indent; + + // add a "all" radiobutton + fAll = new BRadioButton(BRect(x, y, x+100, y+20), "all_pages", kAllPagesLabel, + new BMessage(ALL_PAGES_MGS)); + fAll->ResizeToPreferred(); + fAll->GetPreferredSize(&w, &h); + fAll->SetValue(allPages); + panel->AddChild(fAll); + + y += h + kMargin; // "new line" + + // add a range selection raddiobutton + fRange = new BRadioButton(BRect(x, y, x+100, y+20), "pages_range_selection", kPagesRangeSelectionLabel, + new BMessage(RANGE_SELECTION_MSG)); + fRange->ResizeToPreferred(); + fRange->GetPreferredSize(&w, &h); + fRange->SetValue(!allPages); + panel->AddChild(fRange); + + x += w + kMargin; + + // add a "from" field + if (allPages) { + buffer[0] = 0; + } else { + sprintf(buffer, "%d", (int)firstPage); + } + fFrom = new BTextControl(BRect(x, y, x+100, y+20), "from_field", kFromLabel, buffer, + new BMessage(RANGE_FROM_MSG)); + fFrom->SetAlignment(B_ALIGN_LEFT, B_ALIGN_RIGHT); + fFrom->SetDivider(be_plain_font->StringWidth(kFromLabelExtraSpace)); + fFrom->ResizeToPreferred(); + fFrom->GetPreferredSize(&w, &h); + panel->AddChild(fFrom); + + x += w + kMargin; + + // add a "to" field + if (allPages) { + buffer[0] = 0; + } else { + sprintf(buffer, "%d", (int)lastPage); + } + fTo = new BTextControl(BRect(x, y, x+100, y+20), "to_field", kToLabel, buffer, + new BMessage(RANGE_TO_MSG)); + fTo->SetAlignment(B_ALIGN_LEFT, B_ALIGN_RIGHT); + fTo->SetDivider(be_plain_font->StringWidth(kToLabelExtraSpace)); + fTo->ResizeToPreferred(); + fTo->GetPreferredSize(&w, &h); + panel->AddChild(fTo); + + y += h + kMargin + kMargin; // "new line" + x = r.left + kMargin; + + // add a separator line... + line = new BBox(BRect(r.left, y - 1, r.right, y), NULL, + B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP ); + panel->AddChild(line); + + y += 2 + kMargin + kMargin; // "new line" + + // add a "OK" button, and make it default + ok = new BButton(BRect(x, y, x+100, y+20), NULL, "OK", new BMessage(OK_MSG), B_FOLLOW_RIGHT | B_FOLLOW_TOP); + ok->MakeDefault(true); + ok->ResizeToPreferred(); + ok->GetPreferredSize(&w, &h); + x = r.right - w - kMargin; + ok->MoveTo(x, ok->Frame().top); // put the ok bottom at bottom right corner + panel->AddChild(ok); + + // add a "Cancel" button + cancel = new BButton(BRect(x, y, x + 100, y + 20), NULL, "Cancel", new BMessage(CANCEL_MSG), B_FOLLOW_RIGHT | B_FOLLOW_TOP); + cancel->ResizeToPreferred(); + cancel->GetPreferredSize(&w, &h); + cancel->MoveTo(x - w - kMargin, y); // put cancel button left next the ok button + panel->AddChild(cancel); + + // Finally, add our panel to window + AddChild(panel); + + // Auto resize window + ResizeTo(ok->Frame().right + kMargin, ok->Frame().bottom + kMargin); +} + + +// -------------------------------------------------- +void +JobSetupWindow::UpdateJobMessage() +{ + int32 copies = 1; + + int32 from; + int32 to; + if (fAll->Value() == B_CONTROL_ON) { + from = 1; to = MAX_INT32; + } else { + from = atoi(fFrom->Text()); + to = atoi(fTo->Text()); + if (from <= 0) from = 1; + if (to < from) to = from; + } + + if (fSetupMsg->HasInt32("copies")) { + fSetupMsg->ReplaceInt32("copies", copies); + } else { + fSetupMsg->AddInt32("copies", copies); + } + if (fSetupMsg->HasInt32("first_page")) { + fSetupMsg->ReplaceInt32("first_page", from); + } else { + fSetupMsg->AddInt32("first_page", from); + } + if (fSetupMsg->HasInt32("last_page")) { + fSetupMsg->ReplaceInt32("last_page", to); + } else { + fSetupMsg->AddInt32("last_page", to); + } +} + + +// -------------------------------------------------- +void +JobSetupWindow::MessageReceived(BMessage *msg) +{ + switch (msg->what) { + case OK_MSG: + UpdateJobMessage(); + Quit(B_OK); + break; + + case CANCEL_MSG: + Quit(B_ERROR); + break; + + case RANGE_FROM_MSG: + case RANGE_TO_MSG: + fRange->SetValue(B_CONTROL_ON); + break; + + default: + inherited::MessageReceived(msg); + break; + } +} + + + diff --git a/src/add-ons/print/drivers/preview/JobSetupWindow.h b/src/add-ons/print/drivers/preview/JobSetupWindow.h new file mode 100644 index 0000000000..57d76ab9d3 --- /dev/null +++ b/src/add-ons/print/drivers/preview/JobSetupWindow.h @@ -0,0 +1,76 @@ +/* + +Preview printer driver. + +Copyright (c) 2003 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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. + +*/ + +#ifndef JOBSETUPWINDOW_H +#define JOBSETUPWINDOW_H + +#include +#include "InterfaceUtils.h" +#include "Utils.h" + +class JobSetupWindow : public BlockingWindow +{ +public: + // Constructors, destructors, operators... + + JobSetupWindow(BMessage *msg, const char *printer_name = NULL); + + typedef BlockingWindow inherited; + + // public constantes + enum { + NB_COPIES_MSG = 'copy', + ALL_PAGES_MGS = 'all_', + RANGE_SELECTION_MSG = 'rnge', + RANGE_FROM_MSG = 'from', + RANGE_TO_MSG = 'to__', + OK_MSG = 'ok__', + CANCEL_MSG = 'cncl', + }; + + // Virtual function overrides +public: + virtual void MessageReceived(BMessage *msg); + + // From here, it's none of your business! ;-) +private: + BString fPrinterName; + BMessage *fSetupMsg; + BRadioButton *fAll; + BRadioButton *fRange; + BTextControl *fFrom; + BTextControl *fTo; + + void UpdateJobMessage(); +}; + +#endif + diff --git a/src/add-ons/print/drivers/preview/MarginView.cpp b/src/add-ons/print/drivers/preview/MarginView.cpp new file mode 100644 index 0000000000..74f910f27c --- /dev/null +++ b/src/add-ons/print/drivers/preview/MarginView.cpp @@ -0,0 +1,694 @@ +/* + +MarginView.cpp + +Copyright (c) 2002 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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. + + Todo: + + 2 Make Strings constants or UI resources + +*/ + +#ifndef MARGIN_VIEW_H +#include "MarginView.h" +#endif + +#include +#include + +#include +#include + +/*----------------- MarginView Private Constants --------------------*/ + +const int Y_OFFSET = 20; +const int X_OFFSET = 10; +const int STRING_SIZE = 50; +const int _WIDTH = 50; +const int NUM_COUNT = 10; + +const static float _pointUnits = 1; // 1 point = 1 point +const static float _inchUnits = 72; // 1" = 72 points +const static float _cmUnits = 28.346; // 72/2.54 1cm = 28.346 points + +const static float _minFieldWidth = 100; // pixels +const static float _minUnitHeight = 30; // pixels +const static float _drawInset = 10; // pixels + +const static float unitFormat[] = { _inchUnits, _cmUnits, _pointUnits }; +const static char *unitNames[] = { "Inch", "cm", "Points", NULL }; +const static uint32 unitMsg[] = { MarginView::UNIT_INCH, + MarginView::UNIT_CM, + MarginView::UNIT_POINT }; + +const pattern dots = {{ 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }}; + +const rgb_color black = { 0,0,0,0 }; +const rgb_color red = { 255,0,0,0 }; +const rgb_color white = { 255,255,255,0 }; +const rgb_color gray = { 220,220,220,0 }; + +/*----------------- MarginView Public Methods --------------------*/ + +/** + * Constructor + * + * @param frame, BRect that is the size of the view passed to the superclase + * @param pageWidth, float that is the points value of the page width + * @param pageHeight, float that is the points value of the page height + * @param margins, BRect values of margins + * @param units, unit32 enum for units used in view + * @return void + */ +MarginView::MarginView(BRect frame, + int32 pageWidth, + int32 pageHeight, + BRect margins, + uint32 units) + + :BBox(frame, NULL, B_FOLLOW_ALL) +{ + fUnits = units; + fUnitValue = unitFormat[units]; + + SetLabel("Margins"); + + fMaxPageHeight = frame.Height() - _minUnitHeight - Y_OFFSET; + fMaxPageWidth = frame.Width() - _minFieldWidth - X_OFFSET; + + fMargins = margins; + + fPageWidth = pageWidth; + fPageHeight = pageHeight; +} + +/** + * Destructor + * + * @param none + * @return void + */ +MarginView::~MarginView() { +} + +/*----------------- MarginView Public BeOS Hook Methods --------------------*/ + +/** + * Draw + * + * @param BRect, the draw bounds + * @return void + */ +void MarginView::Draw(BRect rect) +{ + BBox::Draw(rect); + + float y_offset = (float)Y_OFFSET; + float x_offset = (float)X_OFFSET; + BRect r; + + // Calculate offsets depending on orientation + if (fPageWidth < fPageHeight) { // Portrait + x_offset = (fMaxPageWidth/2 + X_OFFSET) - fViewWidth/2; + } else { // landscape + y_offset = (fMaxPageHeight/2 + Y_OFFSET) - fViewHeight/2; + } + + // draw the page + SetHighColor(white); + r = BRect(0, 0, fViewWidth, fViewHeight); + r.OffsetBy(x_offset, y_offset); + FillRect(r); + SetHighColor(black); + StrokeRect(r); + + // draw margin + SetHighColor(red); + SetLowColor(white); + r.top += fMargins.top; + r.right -= fMargins.right; + r.bottom -= fMargins.bottom; + r.left += fMargins.left; + StrokeRect(r, dots); + + // draw the page size label + SetHighColor(black); + SetLowColor(gray); + char str[STRING_SIZE]; + sprintf(str, "%2.1f x %2.1f", fPageWidth/fUnitValue, fPageHeight/fUnitValue); + SetFontSize(10); + DrawString((const char *)str, BPoint(x_offset, fMaxPageHeight + 40)); +} + + +/** + * BeOS Hook Function, change the size of the margin display + * + * @param width of the page + * @param height the page + * @return void + */ +void MarginView::FrameResized(float width, float height) +{ + fMaxPageHeight = height - _minUnitHeight - X_OFFSET; + fMaxPageWidth = width - _minFieldWidth - Y_OFFSET; + + CalculateViewSize(MARGIN_CHANGED); + Invalidate(); +} + +/** + * AttachToWindow + * + * @param none + * @return void + */ +void MarginView::AttachedToWindow() +{ + if (Parent()) { + SetViewColor(Parent()->ViewColor()); + } + ConstructGUI(); +} + +/*----------------- MarginView Public Methods --------------------*/ + +/** + * GetUnits + * + * @param none + * @return uint32 enum, units in inches, cm, points + */ +uint32 MarginView::GetUnits(void) { + return fUnits; +} + +/** + * UpdateView, recalculate and redraw the view + * + * @param msg is a message to the calculate size to tell which field caused + * the update to occur, or it is a general update. + * @return void + */ +void MarginView::UpdateView(uint32 msg) +{ + Window()->Lock(); + CalculateViewSize(msg); + Invalidate(); + Window()->Unlock(); +} + +/** + * SetPageSize + * + * @param pageWidth, float that is the unit value of the page width + * @param pageHeight, float that is the unit value of the page height + * @return void + */ +void MarginView::SetPageSize(float pageWidth, float pageHeight) +{ + fPageWidth = pageWidth; + fPageHeight = pageHeight; +} + +/** + * GetPageSize + * + * @param none + * @return BPoint, contains actual point values of page in x, y of point + */ +BPoint MarginView::GetPageSize(void) { + return BPoint(fPageWidth, fPageHeight); +} + +/** + * GetMargin + * + * @param none + * @return rect, return margin values always in points + */ +BRect MarginView::GetMargin(void) +{ + BRect margin; + + // convert the field text to values + float ftop = atof(fTop->Text()); + float fright = atof(fRight->Text()); + float fleft = atof(fLeft->Text()); + float fbottom = atof(fBottom->Text()); + + // convert to units to points + switch (fUnits) + { + case UNIT_INCH: + // convert to points + ftop *= _inchUnits; + fright *= _inchUnits; + fleft *= _inchUnits; + fbottom *= _inchUnits; + break; + case UNIT_CM: + // convert to points + ftop *= _cmUnits; + fright *= _cmUnits; + fleft *= _cmUnits; + fbottom *= _cmUnits; + break; + } + + margin.Set(fleft, ftop, fright, fbottom); + + return margin; +} + +/** + * MesssageReceived() + * + * Receive messages for the view + * + * @param BMessage* , the message being received + * @return void + */ +void MarginView::MessageReceived(BMessage *msg) +{ + switch (msg->what) + { + case CHANGE_PAGE_SIZE: { + float w; + float h; + msg->FindFloat("width", &w); + msg->FindFloat("height", &h); + SetPageSize(w, h); + UpdateView(MARGIN_CHANGED); + } + break; + + case FLIP_PAGE: { + BPoint p; + p = GetPageSize(); + SetPageSize(p.y, p.x); + UpdateView(MARGIN_CHANGED); + } + break; + + case MARGIN_CHANGED: + UpdateView(MARGIN_CHANGED); + break; + + case TOP_MARGIN_CHANGED: + UpdateView(TOP_MARGIN_CHANGED); + break; + + case LEFT_MARGIN_CHANGED: + UpdateView(LEFT_MARGIN_CHANGED); + break; + + case RIGHT_MARGIN_CHANGED: + UpdateView(RIGHT_MARGIN_CHANGED); + break; + + case BOTTOM_MARGIN_CHANGED: + UpdateView(BOTTOM_MARGIN_CHANGED); + break; + + case UNIT_INCH: + case UNIT_CM: + case UNIT_POINT: + SetUnits(msg->what); + break; + + default: + BView::MessageReceived(msg); + break; + } +} +/*----------------- MarginView Private Methods --------------------*/ + +/** + * ConstructGUI() + * + * Creates the GUI for the View. MUST be called AFTER the View is attached to + * the Window, or will crash and/or create strange behaviour + * + * @param none + * @return void + */ +void MarginView::ConstructGUI() +{ + BMessage *msg; + BString str; + BMenuItem *item; + BMenuField *mf; + BPopUpMenu *menu; + +// Create text fields + msg = new BMessage(MARGIN_CHANGED); + BRect r(Frame().Width() - be_plain_font->StringWidth("Top#") - _WIDTH, + Y_OFFSET, Frame().Width() - X_OFFSET, _WIDTH); + + // top + msg = new BMessage(TOP_MARGIN_CHANGED); + str << fMargins.top/fUnitValue; + fTop = new BTextControl( r, "top", "Top", str.String(), msg, + B_FOLLOW_RIGHT); + fTop->SetDivider(be_plain_font->StringWidth("Top#")); + fTop->SetTarget(this); + AllowOnlyNumbers(fTop, NUM_COUNT); + AddChild(fTop); + + //left + r.OffsetBy(0, Y_OFFSET); + r.left = Frame().Width() - be_plain_font->StringWidth("Left#") - _WIDTH; + str = ""; + str << fMargins.left/fUnitValue; + msg = new BMessage(LEFT_MARGIN_CHANGED); + fLeft = new BTextControl( r, "left", "Left", str.String(), msg, + B_FOLLOW_RIGHT); + fLeft->SetDivider(be_plain_font->StringWidth("Left#")); + fLeft->SetTarget(this); + AllowOnlyNumbers(fLeft, NUM_COUNT); + AddChild(fLeft); + + //bottom + r.OffsetBy(0, Y_OFFSET); + r.left = Frame().Width() - be_plain_font->StringWidth("Bottom#") - _WIDTH; + str = ""; + str << fMargins.bottom/fUnitValue; + msg = new BMessage(BOTTOM_MARGIN_CHANGED); + fBottom = new BTextControl( r, "bottom", "Bottom", str.String(), msg, + B_FOLLOW_RIGHT); + fBottom->SetDivider(be_plain_font->StringWidth("Bottom#")); + fBottom->SetTarget(this); + + AllowOnlyNumbers(fBottom, NUM_COUNT); + AddChild(fBottom); + + //right + r.OffsetBy(0, Y_OFFSET); + r.left = Frame().Width() - be_plain_font->StringWidth("Right#") - _WIDTH; + str = ""; + str << fMargins.right/fUnitValue; + msg = new BMessage(RIGHT_MARGIN_CHANGED); + fRight = new BTextControl( r, "right", "Right", str.String(), msg, + B_FOLLOW_RIGHT); + fRight->SetDivider(be_plain_font->StringWidth("Right#")); + fRight->SetTarget(this); + AllowOnlyNumbers(fRight, NUM_COUNT); + AddChild(fRight); + +// Create Units popup + r.OffsetBy(-X_OFFSET,Y_OFFSET); + r.right += Y_OFFSET; + + menu = new BPopUpMenu("units"); + mf = new BMenuField(r, "units", "Units", menu, + B_FOLLOW_BOTTOM|B_FOLLOW_RIGHT|B_WILL_DRAW); + mf->ResizeToPreferred(); + mf->SetDivider(be_plain_font->StringWidth("Units#")); + + // Construct menu items + for (int i=0; unitNames[i] != NULL; i++ ) + { + msg = new BMessage(unitMsg[i]); + menu->AddItem(item = new BMenuItem(unitNames[i], msg)); + item->SetTarget(this); + if (fUnits == unitMsg[i]) { + item->SetMarked(true); + } + } + AddChild(mf); + + // calculate the sizes for drawing page view + CalculateViewSize(MARGIN_CHANGED); +} + + +/** + * AllowOnlyNumbers() + * + * @param BTextControl, the control we want to only allow numbers + * @param maxNum, the maximun number of characters allowed + * @return void + */ +void MarginView::AllowOnlyNumbers(BTextControl *textControl, int maxNum) +{ + BTextView *tv = textControl->TextView(); + + for (long i = 0; i < 256; i++) { + tv->DisallowChar(i); + } + for (long i = '0'; i <= '9'; i++) { + tv->AllowChar(i); + } + tv->AllowChar(B_BACKSPACE); + tv->AllowChar('.'); + tv->SetMaxBytes(maxNum); +} + +/** + * SetMargin + * + * @param brect, margin values in rect + * @return void + */ +void MarginView::SetMargin(BRect margin) { + fMargins = margin; +} + +/** + * SetUnits, called by the MarginMgr when the units popup is selected + * + * @param uint32, the enum that identifies the units requested to change to. + * @return void + */ +void MarginView::SetUnits(uint32 unit) +{ + // do nothing if the current units are the same as requested + if (unit == fUnits) { + return; + } + + // set the units Format + fUnitValue = unitFormat[unit]; + + // convert the field text to values + float ftop = atof(fTop->Text()); + float fright = atof(fRight->Text()); + float fleft = atof(fLeft->Text()); + float fbottom = atof(fBottom->Text()); + + // convert to target units + switch (fUnits) + { + case UNIT_INCH: + // convert to points + ftop *= _inchUnits; + fright *= _inchUnits; + fleft *= _inchUnits; + fbottom *= _inchUnits; + // check for target unit is cm + if (unit == UNIT_CM) { + ftop /= _cmUnits; + fright /= _cmUnits; + fleft /= _cmUnits; + fbottom /= _cmUnits; + } + break; + case UNIT_CM: + // convert to points + ftop *= _cmUnits; + fright *= _cmUnits; + fleft *= _cmUnits; + fbottom *= _cmUnits; + // check for target unit is inches + if (unit == UNIT_INCH) { + ftop /= _inchUnits; + fright /= _inchUnits; + fleft /= _inchUnits; + fbottom /= _inchUnits; + } + break; + case UNIT_POINT: + // check for target unit is cm + if (unit == UNIT_CM) { + ftop /= _cmUnits; + fright /= _cmUnits; + fleft /= _cmUnits; + fbottom /= _cmUnits; + } + // check for target unit is inches + if (unit == UNIT_INCH) { + ftop /= _inchUnits; + fright /= _inchUnits; + fleft /= _inchUnits; + fbottom /= _inchUnits; + } + break; + } + fUnits = unit; + + // lock Window since these changes are from another thread + Window()->Lock(); + + // set the fields to new units + BString str; + str << ftop; + fTop->SetText(str.String()); + + str = ""; + str << fleft; + fLeft->SetText(str.String()); + + str = ""; + str << fright; + fRight->SetText(str.String()); + + str = ""; + str << fbottom; + fBottom->SetText(str.String()); + + // update UI + CalculateViewSize(MARGIN_CHANGED); + Invalidate(); + + Window()->Unlock(); +} + +/** + * CalculateViewSize + * + * calculate the size of the view that is used + * to show the page inside the margin box. This is dependent + * on the size of the box and the room we have to show it and + * the units that we are using and the orientation of the page. + * + * @param msg, the message for which field changed to check value bounds + * @return void + */ +void MarginView::CalculateViewSize(uint32 msg) +{ + // determine page orientation + if (fPageHeight < fPageWidth) { // LANDSCAPE + fViewWidth = fMaxPageWidth; + fViewHeight = fPageHeight * (fViewWidth/fPageWidth); + float hdiff = fViewHeight - fMaxPageHeight; + if (hdiff > 0) { + fViewHeight -= hdiff; + fViewWidth -= hdiff; + } + } else { // PORTRAIT + fViewHeight = fMaxPageHeight; + fViewWidth = fPageWidth * (fViewHeight/fPageHeight); + float wdiff = fViewWidth - fMaxPageWidth; + if (wdiff > 0) { + fViewHeight -= wdiff; + fViewWidth -= wdiff; + } + } + + // calculate margins based on view size + + // find the length of 1 pixel in points + // ex: 80px/800pt = 0.1px/pt + float pixelLength = fViewHeight/fPageHeight; + + // convert the margins to points + // The text field will have a number that us in the current unit + // ex 0.2" * 72pt = 14.4pts + float ftop = atof(fTop->Text()) * fUnitValue; + float fright = atof(fRight->Text()) * fUnitValue; + float fbottom = atof(fBottom->Text()) * fUnitValue; + float fleft = atof(fLeft->Text()) * fUnitValue; + + // Check that the margins don't overlap each other... + float ph = fPageHeight; + float pw = fPageWidth; + BString str; + + // Bounds calculation rules: + if (msg == TOP_MARGIN_CHANGED) + { + // top must be <= bottom + if (ftop > (ph - fbottom)) { + ftop = ph - fbottom; + str = ""; + str << ftop / fUnitValue; + Window()->Lock(); + fTop->SetText(str.String()); + Window()->Unlock(); + } + + } + + if (msg == BOTTOM_MARGIN_CHANGED) + { + // bottom must be <= pageHeight + if (fbottom > (ph - ftop)) { + fbottom = ph - ftop; + str = ""; + str << fbottom / fUnitValue; + Window()->Lock(); + fBottom->SetText(str.String()); + Window()->Unlock(); + } + } + + if (msg == LEFT_MARGIN_CHANGED) + { + // left must be <= right + if (fleft > (pw - fright)) { + fleft = pw - fright; + str = ""; + str << fleft / fUnitValue; + Window()->Lock(); + fLeft->SetText(str.String()); + Window()->Unlock(); + } + } + + if (msg == RIGHT_MARGIN_CHANGED) + { + // right must be <= fPageWidth + if (fright > (pw - fleft)) { + fright = pw - fleft; + str = ""; + str << fright / fUnitValue; + Window()->Lock(); + fRight->SetText(str.String()); + Window()->Unlock(); + } + } + + // convert the unit value to pixels + // ex: 14.4pt * 0.1px/pt = 1.44px + fMargins.top = ftop * pixelLength; + fMargins.right = fright * pixelLength; + fMargins.bottom = fbottom * pixelLength; + fMargins.left = fleft * pixelLength; +} + + diff --git a/src/add-ons/print/drivers/preview/MarginView.h b/src/add-ons/print/drivers/preview/MarginView.h new file mode 100644 index 0000000000..ca342e697f --- /dev/null +++ b/src/add-ons/print/drivers/preview/MarginView.h @@ -0,0 +1,226 @@ +/* + +MarginView.h + +Copyright (c) 2002 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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. + + Documentation: + + The MarginView is designed to be a self contained component that manages + the display of a BBox control that shows a graphic of a page and its' + margings. The component also includes text fields that are used to mofify + the margin values and a popup to change the units used for the margins. + + There are two interfaces for the MarginView component: + + 1) Set methods: + - page size + - orientation + + Get methods to retrieve: + - margins + - page size + + The method interface is available for the parent Component to call on + the MarginView in response to the Window receiveing messages from + other BControls that it contains, such as a Page Size popup. The + Get methods are used to extract the page size and margins so that + the printer driver may put these values into a BMessage for printing. + + 2) 'Optional' Message interface: + - Set Page Size + - Flip Orientation + + The message interface is available for GUI Controls, BPopupMenu to send + messages to the MarginView if the parent Window is not used to handle + the messages. + + General Use of MarginView component: + + 1) Simply construct a new MarginView object with the margins + you want as defaults and add this view to the parent view + of the dialog. + + MarginView *mv; + mv = new MarginView(viewSizeRect, pageWidth, pageHeight); + parentView->AddChild(mv); + + * you can also set the margins in the constructor, and the units: + + mv = new MarginView(viewSizeRect, pageWidth, pageHeight + marginRect, UNIT_POINTS); + + ! but remeber to have the marginRect values match the UNITS :-) + + 2) Set Page Size with methods: + + mv-SetPageSize( pageWidth, pageHeight ); + mv->UpdateView(); + + 3) Set Page Size with BMessage: + + BMessage* msg = new BMessage(CHANGE_PAGE_SIZE); + msg->AddFloat("width", pageWidth); + msg->AddFloat("height", pageHeight); + mv->PostMessage(msg); + + 4) Flip Page with methods: + + mv-SetPageSize( pageHeight, pageWidth ); + mv->UpdateView(); + + 5) Flip Page with BMessage: + + BMessage* msg = new BMessage(FLIP_PAGE); + mv->Looper()->PostMessage(msg); + + Note: the MarginView DOES NOT keep track of the orientation. This + should be done by the code for the Page setup dialog. + + 6) Get Page Size + + BPoint pageSize = mv->GetPageSize(); + + 7) Get Margins + + BRect margins = mv->GetMargins(); + + 8) Get Units + + uint32 units = mv->GetUnits(); + + where units is one of: + UNIT_INCH, 72 points/in + UNIT_CM, 28.346 points/cm + UNIT_POINT, 1 point/point +*/ + +#ifndef MARGIN_VIEW_H +#define MARGIN_VIEW_H + +#include +#include + +class MarginManager; + +// Messages that the MarginManager accepts +const uint32 TOP_MARGIN_CHANGED = 'tchg'; +const uint32 RIGHT_MARGIN_CHANGED = 'rchg'; +const uint32 LEFT_MARGIN_CHANGED = 'lchg'; +const uint32 BOTTOM_MARGIN_CHANGED = 'bchg'; +const uint32 MARGIN_CHANGED = 'mchg'; +const uint32 CHANGE_PAGE_SIZE = 'chps'; +const uint32 FLIP_PAGE = 'flip'; + +/** + * Class MarginView + */ +class MarginView : public BBox +{ +friend MarginManager; + +public: + // used to index unitFormat array + typedef enum { + UNIT_INCH = 0, + UNIT_CM, + UNIT_POINT + }; + +private: + + // GUI components + BTextControl *fTop, *fBottom, *fLeft, *fRight; + + // rect that holds the margins for the page as a set of point offsets + BRect fMargins; + + // the maximum size of the page view calculated from the view size + float fMaxPageWidth; + float fMaxPageHeight; + + // the actual size of the page in points + float fPageHeight; + float fPageWidth; + + // the units used to calculate the page size + uint32 fUnits; + float fUnitValue; + + // the size of the drawing area we have to draw the view in pixels + float fViewHeight; + float fViewWidth; + + // Calculate the view size for the margins + void CalculateViewSize(uint32 msg); + + // performed internally using the supplied popup + void SetUnits(uint32 unit); + + // performed internally using text fields + void SetMargin(BRect margin); + + // utility method + void AllowOnlyNumbers(BTextControl *textControl, int maxNum); + +public: + MarginView(BRect rect, + int32 pageWidth = 0, + int32 pageHeight = 0, + BRect margins = BRect(1, 1, 1, 1), // default to 1 inch + uint32 units = UNIT_INCH); + + ~MarginView(); + + /// all the GUI construction code + void ConstructGUI(); + + // page size + void SetPageSize(float pageWidth, float pageHeight); + // point.x = width, point.y = height + BPoint GetPageSize(void); + + // margin + BRect GetMargin(void); + + // orientation + // None, this state should be saved elsewhere in the page setup code + // and not here. See the FLIP_PAGE message to perform this function. + + // units + uint32 GetUnits(void); + + // will cause a recalc and redraw + void UpdateView(uint32 msg); + + // BeOS Hook methods + virtual void AttachedToWindow(void); + void Draw(BRect rect); + void FrameResized(float width, float height); + void MessageReceived(BMessage *msg); +}; + +#endif //MARGIN_VIEW_H diff --git a/src/add-ons/print/drivers/preview/PageSetupWindow.cpp b/src/add-ons/print/drivers/preview/PageSetupWindow.cpp new file mode 100644 index 0000000000..e8ba4b0616 --- /dev/null +++ b/src/add-ons/print/drivers/preview/PageSetupWindow.cpp @@ -0,0 +1,379 @@ +/* + +Preview printer driver. + +Copyright (c) 2003 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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 +#include +#include "PrinterDriver.h" +#include "PageSetupWindow.h" + +#include "MarginView.h" + + +// static global variables +static struct +{ + 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 }, + {NULL, 0.0, 0.0 } +}; + + +static struct +{ + char *label; + int32 orientation; +} orientation[] = +{ + {"Portrait", PrinterDriver::PORTRAIT_ORIENTATION}, + {"Landscape", PrinterDriver::LANDSCAPE_ORIENTATION}, + {NULL, 0} +}; + + +/** + * Constuctor + * + * @param + * @return + */ +PageSetupWindow::PageSetupWindow(BMessage *msg, const char *printerName) + : BlockingWindow(BRect(0,0,400,220), "Page Setup", B_TITLED_WINDOW_LOOK, + B_MODAL_APP_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | + B_NOT_ZOOMABLE) +{ + MoveTo(300, 300); + + fSetupMsg = msg; + + if ( printerName ) { + BString title; + + title << printerName << " Page Setup"; + SetTitle( title.String() ); + + // save the printer name + fPrinterDirName = printerName; + } + + // ---- Ok, build a default page setup user interface + BRect r(0, 0, letter_width, letter_height); + BBox *panel; + BButton *button; + float x, y, w, h; + int i; + BMenuItem *item; + float width, height; + int32 orient; + BRect page; + BRect margin(0,0,0,0); + int32 units = MarginView::UNIT_INCH; + BString setting_value; + + // load orientation + fSetupMsg->FindInt32("orientation", &orient); +// (new BAlert("", "orientation not in msg", "Shit"))->Go(); + + // load page rect + fSetupMsg->FindRect("paper_rect", &r); + width = r.Width(); + height = r.Height(); + page = r; + + // Load units + fSetupMsg->FindInt32("units", &units); + + // add a *dialog* background + r = Bounds(); + panel = new BBox(r, "top_panel", B_FOLLOW_ALL, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, + B_PLAIN_BORDER); + + ////////////// Create the margin view ////////////////////// + + // re-calculate the margin from the printable rect in points + margin = page; + fSetupMsg->FindRect("printable_rect", &margin); + + margin.top -= page.top; + margin.left -= page.left; + margin.right = page.right - margin.right; + margin.bottom = page.bottom - margin.bottom; + + fMarginView = new MarginView(BRect(20,20,200,160), width, height, + margin, units); + panel->AddChild(fMarginView); + + // add page format menu + // Simon Changed to OFFSET popups + x = r.left + kMargin * 2 + kOffset; y = r.top + kMargin * 2; + + BPopUpMenu* m = new BPopUpMenu("page_size"); + m->SetRadioMode(true); + + // Simon changed width 200->140 + BMenuField *mf = new BMenuField(BRect(x, y, x + 140, y + 20), "page_size", + "Page Size:", m); + fPageSizeMenu = mf; + mf->ResizeToPreferred(); + mf->GetPreferredSize(&w, &h); + + // Simon added: SetDivider + mf->SetDivider(be_plain_font->StringWidth("Page Size#")); + + panel->AddChild(mf); + + item = NULL; + for (i = 0; pageFormat[i].label != NULL; i++) + { + BMessage* msg = new BMessage('pgsz'); + msg->AddFloat("width", pageFormat[i].width); + msg->AddFloat("height", pageFormat[i].height); + BMenuItem* mi = new BMenuItem(pageFormat[i].label, msg); + m->AddItem(mi); + + if (width == pageFormat[i].width && height == pageFormat[i].height) { + item = mi; + } + if (height == pageFormat[i].width && width == pageFormat[i].height) { + item = mi; + } + } + mf->Menu()->SetLabelFromMarked(true); + if (!item) { + item = m->ItemAt(0); + } + item->SetMarked(true); + mf->MenuItem()->SetLabel(item->Label()); + + // add orientation menu + y += h + kMargin; + + m = new BPopUpMenu("orientation"); + m->SetRadioMode(true); + + // Simon changed 200->140 + mf = new BMenuField(BRect(x, y, x + 140, y + 20), "orientation", "Orientation:", m); + + // Simon added: SetDivider + mf->SetDivider(be_plain_font->StringWidth("Orientation#")); + + fOrientationMenu = mf; + mf->ResizeToPreferred(); + panel->AddChild(mf); + r.top += h; + item = NULL; + for (int i = 0; orientation[i].label != NULL; i++) + { + BMessage* msg = new BMessage('ornt'); + msg->AddInt32("orientation", orientation[i].orientation); + BMenuItem* mi = new BMenuItem(orientation[i].label, msg); + m->AddItem(mi); + + if (orient == orientation[i].orientation) { + item = mi; + } + } + mf->Menu()->SetLabelFromMarked(true); +// SHOULD BE REMOVED + if (!item) { + item = m->ItemAt(0); + } +/////////////////// + item->SetMarked(true); + mf->MenuItem()->SetLabel(item->Label()); + + // add a "OK" button, and make it default + button = new BButton(r, NULL, "OK", new BMessage(OK_MSG), + B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + button->ResizeToPreferred(); + button->GetPreferredSize(&w, &h); + x = r.right - w - 8; + y = r.bottom - h - 8; + button->MoveTo(x, y); + panel->AddChild(button); + button->MakeDefault(true); + + // add a "Cancel button + button = new BButton(r, NULL, "Cancel", new BMessage(CANCEL_MSG), + B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + button->GetPreferredSize(&w, &h); + button->ResizeToPreferred(); + button->MoveTo(x - w - 8, y); + panel->AddChild(button); + + // add a separator line... + BBox * line = new BBox(BRect(r.left, y - 9, r.right, y - 8), NULL, + B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM ); + panel->AddChild(line); + + // Finally, add our panel to window + AddChild(panel); +} + + +// -------------------------------------------------- +void +PageSetupWindow::UpdateSetupMessage() +{ + BMenuItem *item; + int32 orientation = 0; + + item = fOrientationMenu->Menu()->FindMarked(); + if (item) { + BMessage *msg = item->Message(); + msg->FindInt32("orientation", &orientation); + if (fSetupMsg->HasInt32("orientation", orientation)) { + fSetupMsg->ReplaceInt32("orientation", orientation); + } else { + fSetupMsg->AddInt32("orientation", orientation); + } + } + + item = fPageSizeMenu->Menu()->FindMarked(); + if (item) { + float w, h; + BMessage *msg = item->Message(); + msg->FindFloat("width", &w); + msg->FindFloat("height", &h); + BRect r; + if (orientation == 0) + r.Set(0, 0, w, h); + else + r.Set(0, 0, h, w); + if (fSetupMsg->HasRect("paper_rect")) { + fSetupMsg->ReplaceRect("paper_rect", r); + } else { + fSetupMsg->AddRect("paper_rect", r); + } + + // Save the printable_rect + BRect margin = fMarginView->GetMargin(); + if (orientation == 0) { + margin.right = w - margin.right; + margin.bottom = h - margin.bottom; + } else { + margin.right = h - margin.right; + margin.bottom = w - margin.bottom; + } + if (fSetupMsg->HasRect("printable_rect")) { + fSetupMsg->ReplaceRect("printable_rect", margin); + } else { + fSetupMsg->AddRect("printable_rect", margin); + } + + // save the units used + int32 units = fMarginView->GetUnits(); + if (fSetupMsg->HasInt32("units")) { + fSetupMsg->ReplaceInt32("units", units); + } else { + fSetupMsg->AddInt32("units", units); + } + } +} + + +// -------------------------------------------------- +void +PageSetupWindow::MessageReceived(BMessage *msg) +{ + switch (msg->what){ + case OK_MSG: + UpdateSetupMessage(); + Quit(B_OK); + break; + + case CANCEL_MSG: + Quit(B_ERROR); + break; + + // Simon added + case 'pgsz': + { + float w, h; + msg->FindFloat("width", &w); + msg->FindFloat("height", &h); + BMenuItem *item = fOrientationMenu->Menu()->FindMarked(); + if (item) { + int32 orientation = 0; + BMessage *m = item->Message(); + m->FindInt32("orientation", &orientation); + if (orientation == PrinterDriver::PORTRAIT_ORIENTATION) { + fMarginView->SetPageSize(w, h); + } else { + fMarginView->SetPageSize(h, w); + } + fMarginView->UpdateView(MARGIN_CHANGED); + } + } + break; + + // Simon added + case 'ornt': + { + BPoint p = fMarginView->GetPageSize(); + int32 orientation; + msg->FindInt32("orientation", &orientation); + if (orientation == PrinterDriver::LANDSCAPE_ORIENTATION + && p.y > p.x) { + fMarginView->SetPageSize(p.y, p.x); + fMarginView->UpdateView(MARGIN_CHANGED); + } + if (orientation == PrinterDriver::PORTRAIT_ORIENTATION + && p.x > p.y) { + fMarginView->SetPageSize(p.y, p.x); + fMarginView->UpdateView(MARGIN_CHANGED); + } + } + break; + + default: + inherited::MessageReceived(msg); + break; + } +} + + + diff --git a/src/add-ons/print/drivers/preview/PageSetupWindow.h b/src/add-ons/print/drivers/preview/PageSetupWindow.h new file mode 100644 index 0000000000..b9d69540c7 --- /dev/null +++ b/src/add-ons/print/drivers/preview/PageSetupWindow.h @@ -0,0 +1,84 @@ +/* + +Preview printer driver. + +Copyright (c) 2003 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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. + +*/ + +#ifndef PAGESETUPWINDOW_H +#define PAGESETUPWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include "InterfaceUtils.h" +#include "Utils.h" + +class MarginView; + +class PageSetupWindow : public BlockingWindow +{ +public: + // Constructors, destructors, operators... + + PageSetupWindow(BMessage *msg, const char *printerName = NULL); + + typedef BlockingWindow inherited; + + // public constantes + enum { + OK_MSG = 'ok__', + CANCEL_MSG = 'cncl', + }; + + // Virtual function overrides +public: + virtual void MessageReceived(BMessage *msg); + + // From here, it's none of your business! ;-) +private: + BMessage * fSetupMsg; + BMenuField * fPageSizeMenu; + BMenuField * fOrientationMenu; + + void UpdateSetupMessage(); + + MarginView * fMarginView; + + // used for saving settings + BString fPrinterDirName; + + //private class constants + static const int kMargin = 10; + static const int kOffset = 200; +}; + +#endif diff --git a/src/add-ons/print/drivers/preview/Preview.cpp b/src/add-ons/print/drivers/preview/Preview.cpp new file mode 100644 index 0000000000..e536a165e7 --- /dev/null +++ b/src/add-ons/print/drivers/preview/Preview.cpp @@ -0,0 +1,400 @@ +/* + +Preview + +Copyright (c) 2002, 2003 OpenBeOS. + +Author: + Michael Pfeiffer + +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 + +#include "Preview.h" + +// Implementation of PreviewPage +PreviewPage::PreviewPage(int32 page, PrintJobPage* pjp) + : fPage(page) + , fPictures(NULL) + , fPoints(NULL) + , fRects(NULL) +{ + fNumberOfPictures = pjp->NumberOfPictures(); + fPictures = new BPicture[fNumberOfPictures]; + fPoints = new BPoint[fNumberOfPictures]; + fRects = new BRect[fNumberOfPictures]; + status_t rc = B_ERROR; + for (int32 i = 0; i < fNumberOfPictures && + (rc = pjp->NextPicture(fPictures[i], fPoints[i], fRects[i])) == B_OK; i ++); + fStatus = rc; +} + +PreviewPage::~PreviewPage() { + delete []fPictures; + delete []fPoints; + delete []fRects; +} + +status_t PreviewPage::InitCheck() const { + return fStatus; +} + +void PreviewPage::Draw(BView* view) { + ASSERT(fStatus == B_OK); + for (int32 i = 0; i < fNumberOfPictures; i ++) { + view->DrawPicture(&fPictures[i], fPoints[i]); + } +} + +// Implementation of PreviewView + +const float kPreviewTopMargin = 10; +const float kPreviewBottomMargin = 30; +const float kPreviewLeftMargin = 10; +const float kPreviewRightMargin = 30; + +PreviewView::PreviewView(BFile* jobFile, BRect rect) + : BView(rect, "PreviewView", B_FOLLOW_ALL, B_WILL_DRAW | B_FRAME_EVENTS) + , fPage(0) + , fZoom(0) + , fReader(jobFile) + , fCachedPage(NULL) +{ +} + +PreviewView::~PreviewView() { + delete fCachedPage; +} + +// returns 2 ^ fZoom +float PreviewView::ZoomFactor() const { + const int32 b = 4; + int32 zoom; + if (fZoom > 0) zoom = (1 << b) << fZoom; + else zoom = (1 << b) >> -fZoom; + return zoom / (float)(1 << b); +} + +BRect PreviewView::PageRect() const { + float f = ZoomFactor(); + BRect r = fReader.PaperRect(); + r.left *= f; r.right *= f; r.top *= f; r.bottom *= f; + return r; +} + +BRect PreviewView::ViewRect() const { + BRect r(PageRect()); + r.right += kPreviewLeftMargin + kPreviewRightMargin; + r.bottom += kPreviewTopMargin + kPreviewBottomMargin; + return r; +} + +status_t PreviewView::InitCheck() const { + return fReader.InitCheck(); +} + +bool PreviewView::IsPageLoaded(int32 page) const { + return fCachedPage != NULL && fCachedPage->Page() == page; +} + +bool PreviewView::IsPageValid() const { + return fCachedPage && fCachedPage->InitCheck() == B_OK; +} + +void PreviewView::LoadPage(int32 page) { + delete fCachedPage; fCachedPage = NULL; + PrintJobPage pjp; + if (fReader.GetPage(page, pjp) == B_OK) { + fCachedPage = new PreviewPage(page, &pjp); + } +} + +void PreviewView::DrawPageFrame(BRect rect) { + const float kShadowIndent = 3; + const float kShadowWidth = 3; + float x, y; + float right, bottom; + rgb_color frameColor = {0, 0, 0, 0}; + rgb_color shadowColor = {90, 90, 90, 0}; + BRect r(PageRect()); + + PushState(); + // draw page border around page + r.InsetBy(-1, -1); + r.OffsetTo(kPreviewLeftMargin-1, kPreviewTopMargin-1); + SetHighColor(frameColor); + StrokeRect(r); + + // draw page shadow + SetHighColor(shadowColor); + + x = r.right + 1; + right = x + kShadowWidth; + bottom = r.bottom + 1 + kShadowWidth; + y = r.top + kShadowIndent; + FillRect(BRect(x, y, right, bottom)); + + x = r.left + kShadowIndent; + y = r.bottom + 1; + FillRect(BRect(x, y, r.right, bottom)); + PopState(); +} + +void PreviewView::DrawPage(BRect rect) { + // constrain clipping region to paper dimensions + BRect r(PageRect()); + r.OffsetBy(kPreviewLeftMargin, kPreviewTopMargin); + BRegion clip(r); + ConstrainClippingRegion(&clip); + + // draw page contents + PushState(); + SetOrigin(kPreviewLeftMargin, kPreviewTopMargin); + SetScale(ZoomFactor()); + fCachedPage->Draw(this); + PopState(); +} + +void PreviewView::Draw(BRect rect) { + if (fReader.InitCheck() == B_OK) { + if (!IsPageLoaded(fPage)) { + LoadPage(fPage); + } + if (IsPageValid()) { + DrawPageFrame(rect); + DrawPage(rect); + } + } +} + +void PreviewView::FrameResized(float width, float height) { + FixScrollbars(); +} + +bool PreviewView::ShowsFirstPage() const { + return fPage == 0; +} + +bool PreviewView::ShowsLastPage() const { + return fPage == NumberOfPages() - 1; +} + +int PreviewView::NumberOfPages() const { + return fReader.NumberOfPages(); +} + +void PreviewView::ShowNextPage() { + if (!ShowsLastPage()) { + fPage ++; Invalidate(); + } +} + +void PreviewView::ShowPrevPage() { + if (!ShowsFirstPage()) { + fPage --; Invalidate(); + } +} + +bool PreviewView::CanZoomIn() const { + return fZoom < 4; +} + +bool PreviewView::CanZoomOut() const { + return fZoom > -2; +} + +void PreviewView::ZoomIn() { + if (CanZoomIn()) { + fZoom ++; FixScrollbars(); Invalidate(); + } +} + +void PreviewView::ZoomOut() { + if (CanZoomOut()) { + fZoom --; FixScrollbars(); Invalidate(); + } +} + +void PreviewView::FixScrollbars() { + BRect frame = Bounds(); + BScrollBar * scroll; + float x, y; + float bigStep, smallStep; + float width = PageRect().Width() + kPreviewLeftMargin + kPreviewRightMargin; + float height = PageRect().Height() + kPreviewTopMargin + kPreviewBottomMargin; + x = width - frame.Width(); + if (x < 0.0) { + x = 0.0; + } + y = height - frame.Height(); + if (y < 0.0) { + y = 0.0; + } + + scroll = ScrollBar (B_HORIZONTAL); + scroll->SetRange (0.0, x); + scroll->SetProportion ((width - x) / width); + bigStep = frame.Width() - 2; + smallStep = bigStep / 10.; + scroll->SetSteps (smallStep, bigStep); + + scroll = ScrollBar (B_VERTICAL); + scroll->SetRange (0.0, y); + scroll->SetProportion ((height - y) / height); + bigStep = frame.Height() - 2; + smallStep = bigStep / 10.; + scroll->SetSteps (smallStep, bigStep); +} + +// Implementation of PreviewWindow + +PreviewWindow::PreviewWindow(BFile* jobFile) + : BlockingWindow(BRect(20, 24, 400, 600), "Preview", B_DOCUMENT_WINDOW, 0) +{ + float top = 7; + float left = 20; + float width, height; + + BRect r = Frame(); + r.right = r.IntegerWidth() - B_V_SCROLL_BAR_WIDTH; r.left = 0; + r.bottom = r.IntegerHeight() - B_H_SCROLL_BAR_HEIGHT; r.top = 0; + + // add navigation and zoom buttons + fPrev = new BButton(BRect(left, top, left+10, top+10), "Prev", "Previous Page", new BMessage(MSG_PREV_PAGE)); + AddChild(fPrev); + fPrev->ResizeToPreferred(); + width = fPrev->Bounds().Width()+1; + height = fPrev->Bounds().Height()+1; + left = fPrev->Frame().right + 30; + + fNext = new BButton(BRect(left, top, left+10, top+10), "Next", "Next Page", new BMessage(MSG_NEXT_PAGE)); + AddChild(fNext); + fNext->ResizeTo(width, height); + left = fNext->Frame().right + 70; + + fZoomIn = new BButton(BRect(left, top, left+10, top+10), "ZoomIn", "Zoom In", new BMessage(MSG_ZOOM_IN)); + AddChild(fZoomIn); + fZoomIn->ResizeTo(width, height); + left = fZoomIn->Frame().right + 30; + + fZoomOut = new BButton(BRect(left, top, left+10, top+10), "ZoomOut", "Zoom Out", new BMessage(MSG_ZOOM_OUT)); + AddChild(fZoomOut); + fZoomOut->ResizeTo(width, height); + + fButtonBarHeight = fZoomOut->Frame().bottom + 7; + + // add preview view + r.top = fButtonBarHeight; + fPreview = new PreviewView(jobFile, r); + fPreviewScroller = new BScrollView("PreviewScroller", fPreview, B_FOLLOW_ALL, 0, true, true, B_FANCY_BORDER); + fPreviewScroller->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); + AddChild(fPreviewScroller); + + if (fPreview->InitCheck() == B_OK) { + ResizeToPage(); + fPreview->FixScrollbars(); + UpdateControls(); + } +} + +void PreviewWindow::ResizeToPage() { + BScreen screen; + BRect r(fPreview->ViewRect()); + float width, height; + float maxWidth, maxHeight, minWidth; + const float windowBorderWidth = 5; + const float windowBorderHeight = 5; + + if (screen.Frame().right == 0.0) { + return; // invalid screen object + } + + width = r.Width() + 1 + B_V_SCROLL_BAR_WIDTH; + height = r.Height() + 1 + fButtonBarHeight + B_H_SCROLL_BAR_HEIGHT; + + // dimensions so that window does not reach outside of screen + maxWidth = screen.Frame().Width() + 1 - windowBorderWidth - Frame().left; + maxHeight = screen.Frame().Height() + 1 - windowBorderHeight - Frame().top; + + // width so that all buttons are visible + minWidth = fZoomOut->Frame().right + 10; + + if (width < minWidth) width = minWidth; + + if (width > maxWidth) width = maxWidth; + if (height > maxHeight) height = maxHeight; + + ResizeTo(width, height); +} + +void PreviewWindow::UpdateControls() { + fPrev->SetEnabled(!fPreview->ShowsFirstPage()); + fNext->SetEnabled(!fPreview->ShowsLastPage()); + fZoomIn->SetEnabled(fPreview->CanZoomIn()); + fZoomOut->SetEnabled(fPreview->CanZoomOut()); +} + +void PreviewWindow::MessageReceived(BMessage* m) { + switch (m->what) { + case MSG_NEXT_PAGE: fPreview->ShowNextPage(); + break; + case MSG_PREV_PAGE: fPreview->ShowPrevPage(); + break; + case MSG_ZOOM_IN: fPreview->ZoomIn(); ResizeToPage(); + break; + case MSG_ZOOM_OUT: fPreview->ZoomOut(); ResizeToPage(); + break; + default: + inherited::MessageReceived(m); return; + } + UpdateControls(); +} + +status_t PreviewDriver::PrintJob(BFile *jobFile, BMessage *jobMsg) { + PreviewWindow* w; + status_t st; + w = new PreviewWindow(jobFile); + st = w->InitCheck(); + if (st == B_OK) { + w->Go(); + } else { + w->Quit(); + } + return st; +} + +PrinterDriver* instanciate_driver(BNode *spoolDir) +{ + return new PreviewDriver(spoolDir); +} + +// About dialog text: +const char* +kAbout = +"Preview for BeOS\n" +"© 2003 OpenBeOS\n" +"by Michael Pfeiffer\n" +"\n" +"Based on PDF Writer by\nPhilippe Houdoin, Simon Gauvin, Michael Pfeiffer\n" +; + + diff --git a/src/add-ons/print/drivers/preview/Preview.h b/src/add-ons/print/drivers/preview/Preview.h new file mode 100644 index 0000000000..c54a2cc686 --- /dev/null +++ b/src/add-ons/print/drivers/preview/Preview.h @@ -0,0 +1,119 @@ +/* + +Preview + +Copyright (c) 2002, 2003 OpenBeOS. + +Author: + Michael Pfeiffer + +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 +#include "PrintJobReader.h" +#include "PrinterDriver.h" +#include "InterfaceUtils.h" + +class PreviewPage { + int32 fPage; + int32 fNumberOfPictures; + BPicture* fPictures; + BPoint* fPoints; + BRect* fRects; + status_t fStatus; + +public: + PreviewPage(int32 page, PrintJobPage* pjp); + ~PreviewPage(); + status_t InitCheck() const; + + int32 Page() const { return fPage; } + void Draw(BView* view); +}; + +class PreviewView : public BView { + int32 fPage; + int32 fZoom; + PrintJobReader fReader; + PreviewPage* fCachedPage; + + float ZoomFactor() const; + BRect PageRect() const; + +public: + PreviewView(BFile* jobFile, BRect rect); + ~PreviewView(); + status_t InitCheck() const; + + BRect ViewRect() const; + + bool IsPageLoaded(int32 page) const; + bool IsPageValid() const; + void LoadPage(int32 page); + void DrawPageFrame(BRect r); + void DrawPage(BRect r); + void Draw(BRect r); + void FrameResized(float width, float height); + + void FixScrollbars(); + + bool ShowsFirstPage() const; + bool ShowsLastPage() const; + int NumberOfPages() const; + void ShowNextPage(); + void ShowPrevPage(); + + bool CanZoomIn() const; + bool CanZoomOut() const; + void ZoomIn(); + void ZoomOut(); +}; + +class PreviewWindow : public BlockingWindow { + BButton *fNext, *fPrev, *fZoomIn, *fZoomOut; + PreviewView* fPreview; + BScrollView* fPreviewScroller; + float fButtonBarHeight; + + enum { + MSG_NEXT_PAGE = 'pwnp', + MSG_PREV_PAGE = 'pwpp', + MSG_ZOOM_IN = 'pwzi', + MSG_ZOOM_OUT = 'pwzo' + }; + + void ResizeToPage(); + void UpdateControls(); + + typedef BlockingWindow inherited; + +public: + PreviewWindow(BFile* jobFile); + status_t InitCheck() const { return fPreview->InitCheck(); } + void MessageReceived(BMessage* m); +}; + +class PreviewDriver : public PrinterDriver { +public: + PreviewDriver(BNode* spoolDir) : PrinterDriver(spoolDir) {}; + ~PreviewDriver() {}; + virtual status_t PrintJob(BFile *jobFile, BMessage *jobMsg); +}; diff --git a/src/add-ons/print/drivers/preview/Preview.rsrc b/src/add-ons/print/drivers/preview/Preview.rsrc new file mode 100644 index 0000000000..5c25d41b31 Binary files /dev/null and b/src/add-ons/print/drivers/preview/Preview.rsrc differ diff --git a/src/add-ons/print/drivers/preview/PrinterDriver.cpp b/src/add-ons/print/drivers/preview/PrinterDriver.cpp new file mode 100644 index 0000000000..9fc9525f6e --- /dev/null +++ b/src/add-ons/print/drivers/preview/PrinterDriver.cpp @@ -0,0 +1,401 @@ +/* + +Preview printer driver. + +Copyright (c) 2003 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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 +#include // for memset() + +#include + +#include "PrinterDriver.h" + +#include "PrinterSetupWindow.h" +#include "PageSetupWindow.h" +#include "JobSetupWindow.h" + +// Private prototypes +// ------------------ + +#ifdef CODEWARRIOR + #pragma mark [Constructor & destructor] +#endif + +// Constructor & destructor +// ------------------------ + +// -------------------------------------------------- +PrinterDriver::PrinterDriver(BNode* printerNode) + : fJobFile(NULL), + fPrinterNode(printerNode), + fJobMsg(NULL), + + fTransport(NULL), + fTransportAddOn(-1), + fTransportInitProc(NULL), + fTransportExitProc(NULL) +{ +} + + +// -------------------------------------------------- +PrinterDriver::~PrinterDriver() +{ +} + +#ifdef CODEWARRIOR + #pragma mark [Public methods] +#endif + +#ifdef B_BEOS_VERSION_DANO +struct print_file_header { + int32 version; + int32 page_count; + off_t first_page; + int32 _reserved_3_; + int32 _reserved_4_; + int32 _reserved_5_; +}; +#endif + + +// Public methods +// -------------- + +status_t +PrinterDriver::PrintJob + ( + BFile *jobFile, // spool file + BMessage *jobMsg // job message + ) +{ + print_file_header pfh; + status_t status; + BMessage *msg; + int32 page; + uint32 copy; + uint32 copies; + const int32 passes = 2; + + fJobFile = jobFile; + fJobMsg = jobMsg; + + if (!fJobFile || !fPrinterNode) + return B_ERROR; + + // open transport + if (OpenTransport() != B_OK) { + return B_ERROR; + } + if (PrintToFileCanceled()) { + return B_OK; + } + + // read print file header + fJobFile->Seek(0, SEEK_SET); + fJobFile->Read(&pfh, sizeof(pfh)); + + // read job message + fJobMsg = msg = new BMessage(); + msg->Unflatten(fJobFile); + + if (msg->HasInt32("copies")) { + copies = msg->FindInt32("copies"); + } else { + copies = 1; + } + + status = BeginJob(); + + fPrinting = true; + for (fPass = 0; fPass < passes && status == B_OK && fPrinting; fPass++) { + for (copy = 0; copy < copies && status == B_OK && fPrinting; copy++) + { + for (page = 1; page <= pfh.page_count && status == B_OK && fPrinting; page++) { + status = PrintPage(page, pfh.page_count); + } + + // re-read job message for next page + fJobFile->Seek(sizeof(pfh), SEEK_SET); + msg->Unflatten(fJobFile); + } + } + + status_t s = EndJob(); + if (status == B_OK) status = s; + + CloseTransport(); + + delete fJobMsg; + + return status; +} + +/** + * This will stop the printing loop + * + * @param none + * @return void + */ +void +PrinterDriver::StopPrinting() +{ + fPrinting = false; +} + + +// -------------------------------------------------- +status_t +PrinterDriver::BeginJob() +{ + return B_OK; +} + + +// -------------------------------------------------- +status_t +PrinterDriver::PrintPage(int32 pageNumber, int32 pageCount) +{ + char text[128]; + + sprintf(text, "Faking print of page %ld/%ld...", pageNumber, pageCount); + BAlert *alert = new BAlert("PrinterDriver::PrintPage()", text, "Hmm?"); + alert->Go(); + return B_OK; +} + + +// -------------------------------------------------- +status_t +PrinterDriver::EndJob() +{ + return B_OK; +} + + +BlockingWindow* PrinterDriver::NewPrinterSetupWindow(char* printerName) { + return NULL; +} + +BlockingWindow* PrinterDriver::NewPageSetupWindow(BMessage *setupMsg, const char *printerName) { + return new PageSetupWindow(setupMsg, printerName); +} + +BlockingWindow* PrinterDriver::NewJobSetupWindow(BMessage *jobMsg, const char *printerName) { + return new JobSetupWindow(jobMsg, printerName); +} + +status_t PrinterDriver::Go(BlockingWindow* w) { + if (w) { + return w->Go(); + } else { + return B_OK; + } +} + +// -------------------------------------------------- +status_t +PrinterDriver::PrinterSetup(char *printerName) + // name of printer, to attach printer settings +{ + return Go(NewPrinterSetupWindow(printerName)); +} + + +// -------------------------------------------------- +status_t +PrinterDriver::PageSetup(BMessage *setupMsg, const char *printerName) +{ + // check to see if the messag is built correctly... + if (setupMsg->HasFloat("scaling") != B_OK) { +#if HAS_PRINTER_SETTINGS + PrinterSettings *ps = new PrinterSettings(printerName); + + if (ps->InitCheck() == B_OK) { + // first read the settings from the spool dir + if (ps->ReadSettings(setupMsg) != B_OK) { + // if there were none, then create a default set... + ps->GetDefaults(setupMsg); + // ...and save them + ps->WriteSettings(setupMsg); + } + } +#endif + } + + return Go(NewPageSetupWindow(setupMsg, printerName)); +} + + +// -------------------------------------------------- +status_t +PrinterDriver::JobSetup(BMessage *jobMsg, const char *printerName) +{ + // set default value if property not set + if (!jobMsg->HasInt32("copies")) + jobMsg->AddInt32("copies", 1); + + if (!jobMsg->HasInt32("first_page")) + jobMsg->AddInt32("first_page", 1); + + if (!jobMsg->HasInt32("last_page")) + jobMsg->AddInt32("last_page", MAX_INT32); + + return Go(NewJobSetupWindow(jobMsg, printerName)); +} + +// -------------------------------------------------- +BMessage* +PrinterDriver::GetDefaultSettings() +{ + BMessage* msg = new BMessage(); + BRect paperRect(0, 0, letter_width, letter_height); + BRect printableRect(paperRect); + printableRect.InsetBy(10, 10); + msg->AddRect("paper_rect", paperRect); + msg->AddRect("printable_rect", printableRect); + msg->AddInt32("orientation", 0); + msg->AddInt32("xres", 300); + msg->AddInt32("yres", 300); + return msg; +} + +// -------------------------------------------------- +status_t +PrinterDriver::OpenTransport() +{ + char buffer[512]; + BPath *path; + + + if (!fPrinterNode) + return B_ERROR; + + // first, find & load transport add-on + path = new BPath(); + + // find name of this printer transport add-on + fPrinterNode->ReadAttr("transport", B_STRING_TYPE, 0, buffer, sizeof(buffer)); + + // try first on user add-ons directory + find_directory(B_USER_ADDONS_DIRECTORY, path); + path->Append("Print/transport"); + path->Append(buffer); + fTransportAddOn = load_add_on(path->Path()); + + if (fTransportAddOn < 0) { + // add-on not in user add-ons directory. try system one + find_directory(B_BEOS_ADDONS_DIRECTORY, path); + path->Append("Print/transport"); + path->Append(buffer); + fTransportAddOn = load_add_on(path->Path()); + } + + if (fTransportAddOn < 0) { + BAlert * alert = new BAlert("Uh oh!", "Couldn't find transport add-on.", "OK"); + alert->Go(); + return B_ERROR; + } + + // get init & exit proc + get_image_symbol(fTransportAddOn, "init_transport", B_SYMBOL_TYPE_TEXT, (void **) &fTransportInitProc); + get_image_symbol(fTransportAddOn, "exit_transport", B_SYMBOL_TYPE_TEXT, (void **) &fTransportExitProc); + + if (!fTransportInitProc || !fTransportExitProc) { + BAlert * alert = new BAlert("Uh oh!", "Couldn't resolve transport symbols.", "OK"); + alert->Go(); + return B_ERROR; + } + + delete path; + + // now, init transport add-on + node_ref ref; + BDirectory dir; + + fPrinterNode->GetNodeRef(&ref); + dir.SetTo(&ref); + + path = new BPath(&dir, NULL); + strcpy(buffer, path->Path()); + + // create BMessage for init_transport() + BMessage *msg = new BMessage('TRIN'); + msg->AddString("printer_file", buffer); + + fTransport = (*fTransportInitProc)(msg); + + delete msg; + delete path; + + if (fTransport == 0) { + BAlert *alert = new BAlert("Uh oh!", "Couldn't open transport.", "OK"); + alert->Go(); + return B_ERROR; + } + + return B_OK; +} + + +// -------------------------------------------------- +bool +PrinterDriver::PrintToFileCanceled() +{ + // The BeOS "Print To File" transport returns a non-NULL BDataIO * + // even after user filepanel cancellation! + BFile* file = dynamic_cast(fTransport); + return file && file->InitCheck() != B_OK; +} + + +// -------------------------------------------------- +status_t +PrinterDriver::CloseTransport() +{ + if (!fTransportAddOn) + return B_ERROR; + + if (fTransportExitProc) + (*fTransportExitProc)(); + + unload_add_on(fTransportAddOn); + fTransportAddOn = 0; + fTransport = NULL; + + return B_OK; +} + +#ifdef CODEWARRIOR + #pragma mark [Privates routines] +#endif + +// Private routines +// ---------------- diff --git a/src/add-ons/print/drivers/preview/PrinterDriver.h b/src/add-ons/print/drivers/preview/PrinterDriver.h new file mode 100644 index 0000000000..37facfe0d6 --- /dev/null +++ b/src/add-ons/print/drivers/preview/PrinterDriver.h @@ -0,0 +1,145 @@ +/* + +Preview printer driver. + +Copyright (c) 2001 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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. + +*/ + +#ifndef PRINTERDRIVER_H +#define PRINTERDRIVER_H + +#include +#include +#include "InterfaceUtils.h" + +#ifndef ROUND_UP + #define ROUND_UP(x, y) (((x) + (y) - 1) & ~((y) - 1)) +#endif + +#define MAX_INT32 ((int32)0x7fffffffL) + +/* copied from PDFlib.h: */ +#define a0_width (float) 2380.0 +#define a0_height (float) 3368.0 +#define a1_width (float) 1684.0 +#define a1_height (float) 2380.0 +#define a2_width (float) 1190.0 +#define a2_height (float) 1684.0 +#define a3_width (float) 842.0 +#define a3_height (float) 1190.0 +#define a4_width (float) 595.0 +#define a4_height (float) 842.0 +#define a5_width (float) 421.0 +#define a5_height (float) 595.0 +#define a6_width (float) 297.0 +#define a6_height (float) 421.0 +#define b5_width (float) 501.0 +#define b5_height (float) 709.0 +#define letter_width (float) 612.0 +#define letter_height (float) 792.0 +#define legal_width (float) 612.0 +#define legal_height (float) 1008.0 +#define ledger_width (float) 1224.0 +#define ledger_height (float) 792.0 +#define p11x17_width (float) 792.0 +#define p11x17_height (float) 1224.0 + +// transport add-on calls definition +extern "C" { + typedef BDataIO *(*init_transport_proc)(BMessage *); + typedef void (*exit_transport_proc)(void); +}; + + +/** + * Class PrinterDriver + */ +class PrinterDriver +{ +public: + // constructors / destructor + PrinterDriver(BNode* printerNode); + virtual ~PrinterDriver(); + + void StopPrinting(); + + virtual status_t PrintJob(BFile *jobFile, BMessage *jobMsg); + virtual status_t BeginJob(); + virtual status_t PrintPage(int32 pageNumber, int32 pageCount); + virtual status_t EndJob(); + + // configuration window getters + virtual BlockingWindow* NewPrinterSetupWindow(char* printerName); + virtual BlockingWindow* NewPageSetupWindow(BMessage *setupMsg, const char *printerName); + virtual BlockingWindow* NewJobSetupWindow(BMessage *setupMsg, const char *printerName); + + // configuration default methods + virtual status_t PrinterSetup(char *printerName); + virtual status_t PageSetup(BMessage *msg, const char *printerName = NULL); + virtual status_t JobSetup(BMessage *msg, const char *printerName = NULL); + virtual BMessage* GetDefaultSettings(); + + // transport-related methods + status_t OpenTransport(); + status_t CloseTransport(); + bool PrintToFileCanceled(); + + // accessors + inline BFile *JobFile() { return fJobFile; } + inline BNode *PrinterNode() { return fPrinterNode; } + inline BMessage *JobMsg() { return fJobMsg; } + inline BDataIO *Transport() { return fTransport; } + inline int32 Pass() const { return fPass; } + + // publics status code + typedef enum { + PORTRAIT_ORIENTATION, + LANDSCAPE_ORIENTATION + } Orientation; + + +private: + status_t Go(BlockingWindow* w); + + BFile *fJobFile; + BNode *fPrinterNode; + BMessage *fJobMsg; + + volatile Orientation fOrientation; + + bool fPrinting; + int32 fPass; + + // transport-related + BDataIO *fTransport; + image_id fTransportAddOn; + init_transport_proc fTransportInitProc; + exit_transport_proc fTransportExitProc; +}; + +#endif // #ifndef PRINTERDRIVER_H + diff --git a/src/add-ons/print/drivers/preview/PrinterSetupWindow.cpp b/src/add-ons/print/drivers/preview/PrinterSetupWindow.cpp new file mode 100644 index 0000000000..1c7f9421b7 --- /dev/null +++ b/src/add-ons/print/drivers/preview/PrinterSetupWindow.cpp @@ -0,0 +1,215 @@ +/* + +Preview printer driver. + +Copyright (c) 2003 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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 +#include +#include + +#include "PrinterSetupWindow.h" + +// -------------------------------------------------- +PrinterSetupWindow::PrinterSetupWindow(char *printerName) + : BlockingWindow(BRect(0,0,300,300), printerName, B_TITLED_WINDOW_LOOK, + B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE) +{ + MoveTo(300, 300); + + fPrinterName = printerName; + + if (printerName) { + BString title; + title << printerName << " Printer Setup"; + SetTitle(title.String()); + } else + SetTitle("Printer Setup"); + + // ---- Ok, build a default job setup user interface + BRect r; + BButton *button; + float x, y, w, h; + font_height fh; + + r = Bounds(); + + // add a *dialog* background + BBox *panel = new BBox(r, "top_panel", B_FOLLOW_ALL, + B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, + B_PLAIN_BORDER); + + + const int kInterSpace = 8; + const int kHorzMargin = 10; + const int kVertMargin = 10; + + x = kHorzMargin; + y = kVertMargin; + + // add a label before the list + const char *kModelLabel = "Printer model"; + + be_plain_font->GetHeight(&fh); + + w = Bounds().Width(); + w -= 2 * kHorzMargin; + h = 150; + + BBox * model_group = new BBox(BRect(x, y, x+w, y+h), "model_group", B_FOLLOW_ALL_SIDES); + model_group->SetLabel(kModelLabel); + + BRect rlv = model_group->Bounds(); + + rlv.InsetBy(kHorzMargin, kVertMargin); + rlv.top += fh.ascent + fh.descent + fh.leading; + rlv.right -= B_V_SCROLL_BAR_WIDTH; + fModelList = new BListView(rlv, "model_list", + B_SINGLE_SELECTION_LIST, B_FOLLOW_ALL_SIDES ); + + BScrollView * sv = new BScrollView( "model_list_scrollview", fModelList, + B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_FRAME_EVENTS, false, true ); + model_group->AddChild(sv); + + panel->AddChild(model_group); + + y += (h + kInterSpace); + + x = r.right - kHorzMargin; + + // add a "OK" button, and make it default + fOkButton = new BButton(BRect(x, y, x + 400, y), NULL, "OK", new BMessage(OK_MSG), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + fOkButton->ResizeToPreferred(); + fOkButton->GetPreferredSize(&w, &h); + x -= w; + fOkButton->MoveTo(x, y); + fOkButton->MakeDefault(true); + fOkButton->SetEnabled(false); + + panel->AddChild(fOkButton); + + x -= kInterSpace; + + // add a "Cancel" button + button = new BButton(BRect(x, y, x + 400, y), NULL, "Cancel", new BMessage(CANCEL_MSG), B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM); + button->ResizeToPreferred(); + button->GetPreferredSize(&w, &h); + x -= w; + button->MoveTo(x, y); + panel->AddChild(button); + + y += (h + kInterSpace); + + panel->ResizeTo(Bounds().Width(), y); + ResizeTo(Bounds().Width(), y); + + float minWidth, maxWidth, minHeight, maxHeight; + + GetSizeLimits(&minWidth, &maxWidth, &minHeight, &maxHeight); + SetSizeLimits(panel->Frame().Width(), panel->Frame().Width(), + panel->Frame().Height(), maxHeight); + + // Finally, add our panel to window + AddChild(panel); + + BDirectory Folder; + BEntry entry; + + Folder.SetTo ("/boot/beos/etc/bubblejet"); + if (Folder.InitCheck() != B_OK) + return; + + while (Folder.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND) { + char name[B_FILE_NAME_LENGTH]; + if (entry.GetName(name) == B_NO_ERROR) + fModelList->AddItem (new BStringItem(name)); + } + + fModelList->SetSelectionMessage(new BMessage(MODEL_MSG)); + fModelList->SetInvocationMessage(new BMessage(OK_MSG)); +} + + +// -------------------------------------------------- +void +PrinterSetupWindow::MessageReceived(BMessage *msg) +{ + switch (msg->what) { + case OK_MSG: + { + // Test model selection (if any), save it in printerName node and return + BNode spoolDir; + BPath * path; + status_t result = B_ERROR; + + if (fModelList->CurrentSelection() < 0) + break; + + BStringItem * item = dynamic_cast + (fModelList->ItemAt(fModelList->CurrentSelection())); + + if (!item) + break; + + path = new BPath(); + + find_directory(B_USER_SETTINGS_DIRECTORY, path); + path->Append("printers"); + path->Append(fPrinterName); + + spoolDir.SetTo(path->Path()); + delete path; + + if (spoolDir.InitCheck() != B_OK) { + BAlert * alert = new BAlert("Uh oh!", + "Couldn't find printer spool directory.", "OK"); + alert->Go(); + } else { + spoolDir.WriteAttr("printer_model", B_STRING_TYPE, 0, item->Text(), + strlen(item->Text())); + result = B_OK; + } + + Quit(result); + break; + } + + case CANCEL_MSG: + Quit(B_ERROR); + break; + + case MODEL_MSG: + fOkButton->SetEnabled((fModelList->CurrentSelection() >= 0)); + break; + + default: + inherited::MessageReceived(msg); + break; + }; +} + diff --git a/src/add-ons/print/drivers/preview/PrinterSetupWindow.h b/src/add-ons/print/drivers/preview/PrinterSetupWindow.h new file mode 100644 index 0000000000..be370be183 --- /dev/null +++ b/src/add-ons/print/drivers/preview/PrinterSetupWindow.h @@ -0,0 +1,66 @@ +/* + +Preview printer driver. + +Copyright (c) 2003 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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. + +*/ + +#ifndef PRINTERSETUPWINDOW_H +#define PRINTERSETUPWINDOW_H + +#include +#include "InterfaceUtils.h" + +class PrinterSetupWindow : public BlockingWindow +{ +public: + // Constructors, destructors, operators... + + PrinterSetupWindow(char *printerName); + + typedef BlockingWindow inherited; + + // public constantes + enum { + OK_MSG = 'ok__', + CANCEL_MSG = 'cncl', + MODEL_MSG = 'modl' + }; + + // Virtual function overrides +public: + virtual void MessageReceived(BMessage *msg); + + // From here, it's none of your business! ;-) +private: + BButton *fOkButton; + BListView *fModelList; + char *fPrinterName; +}; + +#endif + diff --git a/src/add-ons/print/drivers/preview/Utils.cpp b/src/add-ons/print/drivers/preview/Utils.cpp new file mode 100644 index 0000000000..f104d35ba8 --- /dev/null +++ b/src/add-ons/print/drivers/preview/Utils.cpp @@ -0,0 +1,107 @@ +/* + +PDF Writer printer driver. + +Copyright (c) 2001, 2002 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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 "Utils.h" + +// -------------------------------------------------- +EscapeMessageFilter::EscapeMessageFilter(BWindow *window, int32 what) + : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, '_KYD') + , fWindow(window), + fWhat(what) +{ +} + + +// -------------------------------------------------- +filter_result +EscapeMessageFilter::Filter(BMessage *msg, BHandler **target) +{ + int32 key; + // notify window with message fWhat if Escape key is hit + if (B_OK == msg->FindInt32("key", &key) && key == 1) { + fWindow->PostMessage(fWhat); + return B_SKIP_MESSAGE; + } + return B_DISPATCH_MESSAGE; +} + +// -------------------------------------------------- +// copied from BeUtils.cpp +static bool InList(const char* list[], const char* name) { + for (int i = 0; list[i] != NULL; i ++) { + if (strcmp(list[i], name) == 0) return true; + } + return false; +} + +#include + +// -------------------------------------------------- +// copied from BeUtils.cpp +void AddFields(BMessage* to, const BMessage* from, const char* excludeList[], const char* includeList[]) { + if (to == from) return; + char* name; + type_code type; + int32 count; + for (int32 i = 0; from->GetInfo(B_ANY_TYPE, i, &name, &type, &count) == B_OK; i ++) { + if (excludeList && InList(excludeList, name)) continue; + if (includeList && !InList(includeList, name)) continue; + // replace existing data + to->RemoveName(name); + + const void* data; + ssize_t size; + for (int32 j = 0; j < count; j ++) { + if (from->FindData(name, type, j, &data, &size) == B_OK) { + // WTF why works AddData not for B_STRING_TYPE in R5.0.3? + if (type == B_STRING_TYPE) { + to->AddString(name, (const char*)data); + } else if (type == B_MESSAGE_TYPE) { + BMessage m; + from->FindMessage(name, j, &m); + to->AddMessage(name, &m); + } else { + to->AddData(name, type, data, size); + } + } + } + } +} + +void AddString(BMessage* m, const char* name, const char* value) { + if (m->HasString(name, 0)) { + m->ReplaceString(name, value); + } else { + m->AddString(name, value); + } +} + + diff --git a/src/add-ons/print/drivers/preview/Utils.h b/src/add-ons/print/drivers/preview/Utils.h new file mode 100644 index 0000000000..663728d13a --- /dev/null +++ b/src/add-ons/print/drivers/preview/Utils.h @@ -0,0 +1,155 @@ +/* + +PDF Writer printer driver. + +Copyright (c) 2001, 2002 OpenBeOS. + +Authors: + Philippe Houdoin + Simon Gauvin + Michael Pfeiffer + +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. + +*/ + +#ifndef _UTILS_H +#define _UTILS_H + +#include +#include +#include + + +// adds fields to message or replaces existing fields (copy BeUtils.h) +void AddFields(BMessage* to, const BMessage* from, const char* excludeList[] = NULL, const char* includeList[] = NULL); +void AddString(BMessage* m, const char* name, const char* value); + +class EscapeMessageFilter : public BMessageFilter +{ +private: + BWindow *fWindow; + int32 fWhat; + +public: + EscapeMessageFilter(BWindow *window, int32 what); + filter_result Filter(BMessage *msg, BHandler **target); +}; + + +#define BEGINS_CHAR(byte) ((byte & 0xc0) != 0x80) + + +template +class TList { +private: + BList fList; + typedef int (*sort_func)(const void*, const void*); + +public: + virtual ~TList(); + void MakeEmpty(); + int32 CountItems() const; + T* ItemAt(int32 index) const; + void AddItem(T* p); + T* RemoveItem(int i); + T* Items(); + void SortItems(int (*comp)(const T**, const T**)); +}; + +// TList +template +TList::~TList() { + MakeEmpty(); +} + + +template +void TList::MakeEmpty() { + const int32 n = CountItems(); + for (int i = 0; i < n; i++) { + delete ItemAt(i); + } + fList.MakeEmpty(); +} + + +template +int32 TList::CountItems() const { + return fList.CountItems(); +} + + +template +T* TList::ItemAt(int32 index) const { + return (T*)fList.ItemAt(index); +} + + +template +void TList::AddItem(T* p) { + fList.AddItem(p); +} + +template +T* TList::RemoveItem(int i) { + return (T*)fList.RemoveItem(i); +} + + +template +T* TList::Items() { + return (T*)fList.Items(); +} + + +template +void TList::SortItems(int (*comp)(const T**, const T**)) { + sort_func sort = (sort_func)comp; + fList.SortItems(sort); +} + +// PDF coordinate system +class PDFSystem { +private: + float fHeight; + float fX; + float fY; + float fScale; + +public: + PDFSystem() + : fHeight(0), fX(0), fY(0), fScale(1) { } + PDFSystem(float h, float x, float y, float s) + : fHeight(h), fX(x), fY(y), fScale(s) { } + + void SetHeight(float h) { fHeight = h; } + void SetOrigin(float x, float y) { fX = x; fY = y; } + void SetScale(float scale) { fScale = scale; } + float Height() const { return fHeight; } + BPoint Origin() const { return BPoint(fX, fY); } + float Scale() const { return fScale; } + + inline float tx(float x) { return fX + fScale*x; } + inline float ty(float y) { return fHeight - (fY + fScale * y); } + inline float scale(float f) { return fScale * f; } +}; + + +#endif