xref: /haiku/src/apps/showimage/PrintOptionsWindow.cpp (revision 9760dcae2038d47442f4658c2575844c6cf92c40)
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 <String.h>
17 
18 #include "ShowImageConstants.h"
19 
20 
21 PrintOptions::PrintOptions()
22 	:
23 	fOption(kFitToPage),
24 	fZoomFactor(1.0),
25 	fDPI(72.0),
26 	fWidth(1024/72.0),
27 	fHeight(768/72.0)
28 {
29 }
30 
31 
32 void
33 PrintOptions::SetBounds(BRect rect)
34 {
35 	fBounds = rect;
36 }
37 
38 
39 void
40 PrintOptions::SetZoomFactor(float f)
41 {
42 	fZoomFactor = f;
43 	fDPI = 72.0 / fZoomFactor;
44 }
45 
46 
47 void
48 PrintOptions::SetDPI(float dpi)
49 {
50 	fDPI = dpi;
51 	fZoomFactor = 72.0 / dpi;
52 }
53 
54 
55 void
56 PrintOptions::SetWidth(float w)
57 {
58 	fWidth = w;
59 	fHeight = (fBounds.Height() + 1) * w / (fBounds.Width() + 1);
60 }
61 
62 
63 void
64 PrintOptions::SetHeight(float h)
65 {
66 	fWidth = (fBounds.Width()+1) * h / (fBounds.Height()+1);
67 	fHeight = h;
68 }
69 
70 
71 PrintOptionsWindow::PrintOptionsWindow(BPoint at, PrintOptions *options,
72 	BWindow* listener)
73 	:
74 	BWindow(BRect(at.x, at.y, at.x + 300, at.y + 200), "Print options",
75 		B_TITLED_WINDOW_LOOK, B_MODAL_SUBSET_WINDOW_FEEL,
76 		B_NOT_ZOOMABLE | B_NOT_RESIZABLE),
77 	fPrintOptions(options),
78 	fCurrentOptions(*options),
79 	fListener(listener),
80 	fStatus(B_ERROR)
81 {
82 	AddToSubset(listener);
83 	Setup();
84 	Show();
85 }
86 
87 
88 PrintOptionsWindow::~PrintOptionsWindow()
89 {
90 	BMessage msg(MSG_PRINT);
91 	msg.AddInt32("status", fStatus);
92 	fListener.SendMessage(&msg);
93 }
94 
95 
96 BRadioButton*
97 PrintOptionsWindow::AddRadioButton(BView* view, BPoint& at, const char* name,
98 	const char* label, uint32 what, bool selected)
99 {
100 	BRect rect(0, 0, 100, 20);
101 	BRadioButton* button;
102 	rect.OffsetBy(at);
103 	button = new BRadioButton(rect, name, label, new BMessage(what));
104 	view->AddChild(button);
105 	button->ResizeToPreferred();
106 	at.y += button->Bounds().Height() + kLineSkip;
107 	button->SetValue(selected ? B_CONTROL_ON : B_CONTROL_OFF);
108 	return button;
109 }
110 
111 
112 BTextControl*
113 PrintOptionsWindow::AddTextControl(BView* view, BPoint& at, const char* name,
114 	const char* label, float value, float divider, uint32 what)
115 {
116 	BRect rect(0, 0, divider + 45, 20);
117 	BTextControl* text;
118 	rect.OffsetBy(at);
119 	text = new BTextControl(rect, name, label, "", new BMessage(what));
120 	view->AddChild(text);
121 	text->SetModificationMessage(new BMessage(what));
122 	text->SetDivider(divider);
123 	text->SetAlignment(B_ALIGN_LEFT, B_ALIGN_RIGHT);
124 	SetValue(text, value);
125 	at.y += text->Bounds().Height() + kLineSkip;
126 	return text;
127 }
128 
129 
130 void
131 PrintOptionsWindow::Setup()
132 {
133 	BRect rect(Bounds());
134 	BPoint at(kIndent, kIndent), textAt;
135 	BString value;
136 	enum PrintOptions::Option op = fCurrentOptions.Option();
137 	BRadioButton* rb;
138 	BBox* line;
139 	BButton* button;
140 
141 	BBox *panel = new BBox(rect, "top_panel", B_FOLLOW_ALL,
142 		B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP,
143 		B_PLAIN_BORDER);
144 	AddChild(panel);
145 
146 	AddRadioButton(panel, at, "fit_to_page", "Fit image to page",
147 		kMsgFitToPageSelected, op == PrintOptions::kFitToPage);
148 	textAt = at;
149 	rb = AddRadioButton(panel, at, "zoom_factor", "Zoom factor in %: ",
150 		kMsgZoomFactorSelected, op == PrintOptions::kZoomFactor);
151 	textAt.x = rb->Bounds().right + 5;
152 	fZoomFactor = AddTextControl(panel, textAt, "zoom_factor_text", "",
153 		fCurrentOptions.ZoomFactor()*100, 0, kMsgZoomFactorChanged);
154 
155 	textAt = at;
156 	rb = AddRadioButton(panel, at, "dpi", "DPI: ", kMsgDPISelected,
157 		op == PrintOptions::kDPI);
158 	textAt.x = rb->Bounds().right + 5;
159 	fDPI = AddTextControl(panel, textAt, "dpi_text", "", fCurrentOptions.DPI(),
160 		0, kMsgDPIChanged);
161 
162 	rb = AddRadioButton(panel, at, "width_and_height",
163 		"Resize to (in 1/72 inches):", kMsgWidthAndHeightSelected,
164 		op == PrintOptions::kWidth || op == PrintOptions::kHeight);
165 	at.x += 15;
166 	textAt = at;
167 	fWidth = AddTextControl(panel, textAt, "width", "Width: ",
168 		fCurrentOptions.Width(), 40, kMsgWidthChanged);
169 	textAt = at;
170 	textAt.x += fWidth->Bounds().Width() + 5;
171 	fHeight = AddTextControl(panel, textAt, "height", "Height: ",
172 		fCurrentOptions.Height(), 40, kMsgHeightChanged);
173 
174 	at.x = 0;
175 	at.y = textAt.y;
176 	line = new BBox(BRect(rect.left+3, at.y, rect.right-3, at.y + 1), NULL,
177 		B_FOLLOW_LEFT | B_FOLLOW_TOP);
178 	panel->AddChild(line);
179 
180 	at.y += 10;
181 	rect.OffsetBy(at);
182 	button = new BButton(rect, "job setup", "Job setup",
183 		new BMessage(kMsgJobSetup));
184 	panel->AddChild(button);
185 	button->ResizeToPreferred();
186 
187 	SetDefaultButton(button);
188 
189 	// resize window
190 	ResizeTo(fHeight->Frame().right + kIndent, button->Frame().bottom + kIndent);
191 
192 	// center button
193 	button->MoveTo((Bounds().Width()-button->Bounds().Width())/2,
194 		button->Frame().top);
195 }
196 
197 
198 enum PrintOptions::Option
199 PrintOptionsWindow::MsgToOption(uint32 what)
200 {
201 	switch (what) {
202 		case kMsgFitToPageSelected: return PrintOptions::kFitToPage;
203 		case kMsgZoomFactorSelected: return PrintOptions::kZoomFactor;
204 		case kMsgDPISelected: return PrintOptions::kDPI;
205 		case kMsgWidthAndHeightSelected: return PrintOptions::kWidth;
206 	}
207 	return PrintOptions::kFitToPage;
208 }
209 
210 
211 bool
212 PrintOptionsWindow::GetValue(BTextControl* text, float* value)
213 {
214 	*value = atof(text->Text());
215 	return true;
216 }
217 
218 
219 void
220 PrintOptionsWindow::SetValue(BTextControl* text, float value)
221 {
222 	BMessage* msg;
223 	char s[80];
224 	sprintf(s, "%0.0f", value);
225 	// prevent sending a notification when text is set
226 	msg = new BMessage(*text->ModificationMessage());
227 	text->SetModificationMessage(NULL);
228 	text->SetText(s);
229 	text->SetModificationMessage(msg);
230 }
231 
232 
233 void
234 PrintOptionsWindow::MessageReceived(BMessage* msg)
235 {
236 	float value;
237 	switch (msg->what) {
238 		case kMsgFitToPageSelected:
239 		case kMsgZoomFactorSelected:
240 		case kMsgDPISelected:
241 		case kMsgWidthAndHeightSelected:
242 			fCurrentOptions.SetOption(MsgToOption(msg->what));
243 			break;
244 
245 		case kMsgZoomFactorChanged:
246 			if (GetValue(fZoomFactor, &value)
247 				&& fCurrentOptions.ZoomFactor() != value) {
248 				fCurrentOptions.SetZoomFactor(value/100);
249 				SetValue(fDPI, fCurrentOptions.DPI());
250 			}
251 			break;
252 		case kMsgDPIChanged:
253 			if (GetValue(fDPI, &value) && fCurrentOptions.DPI() != value) {
254 				fCurrentOptions.SetDPI(value);
255 				SetValue(fZoomFactor, 100*fCurrentOptions.ZoomFactor());
256 			}
257 			break;
258 		case kMsgWidthChanged:
259 			if (GetValue(fWidth, &value) && fCurrentOptions.Width() != value) {
260 				fCurrentOptions.SetWidth(value);
261 				SetValue(fHeight, fCurrentOptions.Height());
262 			}
263 			break;
264 		case kMsgHeightChanged:
265 			if (GetValue(fHeight, &value) && fCurrentOptions.Height() != value) {
266 				fCurrentOptions.SetHeight(value);
267 				SetValue(fWidth, fCurrentOptions.Width());
268 			}
269 			break;
270 
271 		case kMsgJobSetup:
272 			*fPrintOptions = fCurrentOptions;
273 			fStatus = B_OK;
274 			PostMessage(B_QUIT_REQUESTED);
275 			break;
276 
277 		default:
278 			BWindow::MessageReceived(msg);
279 	}
280 }
281 
282