1/*
2 * Copyright 2003-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Michael Pfeiffer, laplace@haiku-os.org
7 */
8
9#include "PrintOptionsWindow.h"
10
11#include <stdio.h> // for sprintf
12#include <stdlib.h> // for atof
13
14#include <Box.h>
15#include <Button.h>
16#include <Catalog.h>
17#include <ControlLook.h>
18#include <GridLayoutBuilder.h>
19#include <GroupLayoutBuilder.h>
20#include <LayoutBuilder.h>
21#include <Locale.h>
22#include <String.h>
23
24#include "ShowImageConstants.h"
25
26
27#undef B_TRANSLATION_CONTEXT
28#define B_TRANSLATION_CONTEXT "PrintOptionsWindow"
29
30
31PrintOptions::PrintOptions()
32	:
33	fOption(kFitToPage),
34	fZoomFactor(1.0),
35	fDPI(72.0),
36	fWidth(1024 / 72.0),
37	fHeight(768 / 72.0)
38{
39}
40
41
42void
43PrintOptions::SetBounds(BRect rect)
44{
45	fBounds = rect;
46}
47
48
49void
50PrintOptions::SetZoomFactor(float f)
51{
52	fZoomFactor = f;
53	fDPI = 72.0 / fZoomFactor;
54}
55
56
57void
58PrintOptions::SetDPI(float dpi)
59{
60	fDPI = dpi;
61	fZoomFactor = 72.0 / dpi;
62}
63
64
65void
66PrintOptions::SetWidth(float w)
67{
68	fWidth = w;
69	fHeight = (fBounds.Height() + 1) * w / (fBounds.Width() + 1);
70}
71
72
73void
74PrintOptions::SetHeight(float h)
75{
76	fWidth = (fBounds.Width() + 1) * h / (fBounds.Height() + 1);
77	fHeight = h;
78}
79
80
81PrintOptionsWindow::PrintOptionsWindow(BPoint at, PrintOptions* options,
82	BWindow* listener)
83	:
84	BWindow(BRect(at.x, at.y, at.x + 300, at.y + 200),
85		B_TRANSLATE("Print options"),
86		B_TITLED_WINDOW_LOOK, B_MODAL_SUBSET_WINDOW_FEEL,
87		B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS),
88	fPrintOptions(options),
89	fCurrentOptions(*options),
90	fListener(listener),
91	fStatus(B_ERROR)
92{
93	AddToSubset(listener);
94	Setup();
95	Show();
96}
97
98
99PrintOptionsWindow::~PrintOptionsWindow()
100{
101	BMessage msg(MSG_PRINT);
102	msg.AddInt32("status", fStatus);
103	fListener.SendMessage(&msg);
104}
105
106
107BRadioButton*
108PrintOptionsWindow::AddRadioButton(const char* name,
109	const char* label, uint32 what, bool selected)
110{
111	BRadioButton* button;
112	button = new BRadioButton(name, label, new BMessage(what));
113	button->SetValue(selected ? B_CONTROL_ON : B_CONTROL_OFF);
114	return button;
115}
116
117
118BTextControl*
119PrintOptionsWindow::AddTextControl(const char* name,
120	const char* label, float value, uint32 what)
121{
122	BTextControl* text;
123	text = new BTextControl(name, label, "", new BMessage(what));
124	text->SetModificationMessage(new BMessage(what));
125	SetValue(text, value);
126	return text;
127}
128
129
130void
131PrintOptionsWindow::Setup()
132{
133	BString value;
134	enum PrintOptions::Option op = fCurrentOptions.Option();
135	BRadioButton* rbFit;
136	BRadioButton* rbZoom;
137	BRadioButton* rbDpi;
138	BRadioButton* rbResize;
139	BBox* line;
140	BButton* button;
141
142	rbFit = AddRadioButton("fit_to_page", B_TRANSLATE("Fit image to page"),
143		kMsgFitToPageSelected, op == PrintOptions::kFitToPage);
144
145	rbZoom = AddRadioButton("zoom_factor", B_TRANSLATE("Zoom factor in %:"),
146		kMsgZoomFactorSelected, op == PrintOptions::kZoomFactor);
147
148	fZoomFactor = AddTextControl("zoom_factor_text", "",
149		fCurrentOptions.ZoomFactor() * 100, kMsgZoomFactorChanged);
150
151	rbDpi = AddRadioButton("dpi", B_TRANSLATE("DPI:"), kMsgDPISelected,
152		op == PrintOptions::kDPI);
153
154	fDPI = AddTextControl("dpi_text", "", fCurrentOptions.DPI(),
155		kMsgDPIChanged);
156
157	rbResize = AddRadioButton("width_and_height",
158		B_TRANSLATE("Resize to (in 1/72 inches):"), kMsgWidthAndHeightSelected,
159		op == PrintOptions::kWidth || op == PrintOptions::kHeight);
160
161	fWidth = AddTextControl("width", B_TRANSLATE("Width:"),
162		fCurrentOptions.Width(), kMsgWidthChanged);
163
164	fHeight = AddTextControl("height", B_TRANSLATE("Height: "),
165		fCurrentOptions.Height(), kMsgHeightChanged);
166
167	line = new BBox(B_EMPTY_STRING, B_WILL_DRAW | B_FRAME_EVENTS,
168		B_FANCY_BORDER);
169	line->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1));
170
171	button = new BButton("job setup", B_TRANSLATE("Job setup"),
172		new BMessage(kMsgJobSetup));
173	SetDefaultButton(button);
174
175	const float spacing = be_control_look->DefaultItemSpacing();
176
177	SetLayout(new BGroupLayout(B_HORIZONTAL));
178	AddChild(BGroupLayoutBuilder(B_VERTICAL, 0)
179		.Add(BGridLayoutBuilder()
180				.Add(rbFit, 0, 0)
181				.Add(rbZoom, 0, 1)
182				.Add(fZoomFactor, 1, 1)
183				.Add(rbDpi, 0, 2)
184				.Add(fDPI, 1, 2)
185				.Add(rbResize, 0, 3)
186				)
187		.AddGroup(B_HORIZONTAL, spacing)
188			.Add(fWidth)
189			.Add(fHeight)
190			.AddGlue()
191			.SetInsets(22, 0, 0, 0)
192		.End()
193		.Add(line)
194		.AddGroup(B_HORIZONTAL, 0)
195			.Add(button)
196		.End()
197		.SetInsets(spacing, spacing, spacing, spacing)
198	);
199}
200
201
202enum PrintOptions::Option
203PrintOptionsWindow::MsgToOption(uint32 what)
204{
205	switch (what) {
206		case kMsgFitToPageSelected: return PrintOptions::kFitToPage;
207		case kMsgZoomFactorSelected: return PrintOptions::kZoomFactor;
208		case kMsgDPISelected: return PrintOptions::kDPI;
209		case kMsgWidthAndHeightSelected: return PrintOptions::kWidth;
210	}
211	return PrintOptions::kFitToPage;
212}
213
214
215bool
216PrintOptionsWindow::GetValue(BTextControl* text, float* value)
217{
218	*value = atof(text->Text());
219	return true;
220}
221
222
223void
224PrintOptionsWindow::SetValue(BTextControl* text, float value)
225{
226	BMessage* msg;
227	char s[80];
228	snprintf(s, sizeof(s), "%0.0f", value);
229	// prevent sending a notification when text is set
230	msg = new BMessage(*text->ModificationMessage());
231	text->SetModificationMessage(NULL);
232	text->SetText(s);
233	text->SetModificationMessage(msg);
234}
235
236
237void
238PrintOptionsWindow::MessageReceived(BMessage* msg)
239{
240	float value;
241	switch (msg->what) {
242		case kMsgFitToPageSelected:
243		case kMsgZoomFactorSelected:
244		case kMsgDPISelected:
245		case kMsgWidthAndHeightSelected:
246			fCurrentOptions.SetOption(MsgToOption(msg->what));
247			break;
248
249		case kMsgZoomFactorChanged:
250			if (GetValue(fZoomFactor, &value)
251				&& fCurrentOptions.ZoomFactor() != value) {
252				fCurrentOptions.SetZoomFactor(value / 100);
253				SetValue(fDPI, fCurrentOptions.DPI());
254			}
255			break;
256		case kMsgDPIChanged:
257			if (GetValue(fDPI, &value) && fCurrentOptions.DPI() != value) {
258				fCurrentOptions.SetDPI(value);
259				SetValue(fZoomFactor, 100 * fCurrentOptions.ZoomFactor());
260			}
261			break;
262		case kMsgWidthChanged:
263			if (GetValue(fWidth, &value) && fCurrentOptions.Width() != value) {
264				fCurrentOptions.SetWidth(value);
265				SetValue(fHeight, fCurrentOptions.Height());
266			}
267			break;
268		case kMsgHeightChanged:
269			if (GetValue(fHeight, &value) && fCurrentOptions.Height() != value) {
270				fCurrentOptions.SetHeight(value);
271				SetValue(fWidth, fCurrentOptions.Width());
272			}
273			break;
274
275		case kMsgJobSetup:
276			*fPrintOptions = fCurrentOptions;
277			fStatus = B_OK;
278			PostMessage(B_QUIT_REQUESTED);
279			break;
280
281		default:
282			BWindow::MessageReceived(msg);
283	}
284}
285
286