1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci   Copyright (C) 1997 Jeffrey S. Freedman
3141cc406Sopenharmony_ci   This file is part of the SANE package.
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
6141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
7141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
8141cc406Sopenharmony_ci   License, or (at your option) any later version.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
11141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
12141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13141cc406Sopenharmony_ci   General Public License for more details.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
16141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
19141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
22141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
23141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
24141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
25141cc406Sopenharmony_ci   account of linking the SANE library code into it.
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
28141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
32141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
33141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
36141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
37141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.  */
38141cc406Sopenharmony_ci
39141cc406Sopenharmony_ci/**
40141cc406Sopenharmony_ci **	Jscanimage.java - Java scanner program using SANE.
41141cc406Sopenharmony_ci **
42141cc406Sopenharmony_ci **	Written: 10/31/97 - JSF
43141cc406Sopenharmony_ci **/
44141cc406Sopenharmony_ci
45141cc406Sopenharmony_ciimport java.awt.*;
46141cc406Sopenharmony_ciimport java.awt.event.*;
47141cc406Sopenharmony_ciimport java.util.*;
48141cc406Sopenharmony_ciimport java.awt.image.ImageConsumer;
49141cc406Sopenharmony_ciimport java.awt.image.ColorModel;
50141cc406Sopenharmony_ciimport java.io.File;
51141cc406Sopenharmony_ciimport java.io.FileOutputStream;
52141cc406Sopenharmony_ciimport java.io.IOException;
53141cc406Sopenharmony_ciimport java.text.NumberFormat;
54141cc406Sopenharmony_ciimport javax.swing.*;
55141cc406Sopenharmony_ciimport javax.swing.border.*;
56141cc406Sopenharmony_ciimport javax.swing.event.*;
57141cc406Sopenharmony_ci
58141cc406Sopenharmony_ci/*
59141cc406Sopenharmony_ci *	Main program.
60141cc406Sopenharmony_ci */
61141cc406Sopenharmony_cipublic class Jscanimage extends Frame implements WindowListener,
62141cc406Sopenharmony_ci			ActionListener, ItemListener, ImageCanvasClient
63141cc406Sopenharmony_ci    {
64141cc406Sopenharmony_ci    //
65141cc406Sopenharmony_ci    //	Static data.
66141cc406Sopenharmony_ci    //
67141cc406Sopenharmony_ci    private static Sane sane;		// The main class.
68141cc406Sopenharmony_ci    private static SaneDevice devList[];// List of devices.
69141cc406Sopenharmony_ci    //
70141cc406Sopenharmony_ci    //	Instance data.
71141cc406Sopenharmony_ci    //
72141cc406Sopenharmony_ci    private Font font;			// For dialog items.
73141cc406Sopenharmony_ci    private int saneHandle;		// Handle of open device.
74141cc406Sopenharmony_ci    private ScanIt scanIt = null;	// Does the actual scan.
75141cc406Sopenharmony_ci					// File to output to.
76141cc406Sopenharmony_ci    private FileOutputStream outFile = null;
77141cc406Sopenharmony_ci    private String outDir = null;	// Stores dir. for output dialog.
78141cc406Sopenharmony_ci    private Vector controls;		// Dialog components for SANE controls.
79141cc406Sopenharmony_ci    private double unitLength = 1;	// # of mm for units to display
80141cc406Sopenharmony_ci					//    (mm = 1, cm = 10, in = 25.4).
81141cc406Sopenharmony_ci    private ImageCanvas imageDisplay = null;
82141cc406Sopenharmony_ci					// "Scan", "Preview" buttons.
83141cc406Sopenharmony_ci    private JButton scanButton, previewButton;
84141cc406Sopenharmony_ci    private JButton browseButton;	// For choosing output filename.
85141cc406Sopenharmony_ci    private JTextField outputField;	// Field for output filename.
86141cc406Sopenharmony_ci    private MenuItem exitMenuItem;	// Menu items.
87141cc406Sopenharmony_ci    private CheckboxMenuItem toolTipsMenuItem;
88141cc406Sopenharmony_ci    private CheckboxMenuItem mmMenuItem;
89141cc406Sopenharmony_ci    private CheckboxMenuItem cmMenuItem;
90141cc406Sopenharmony_ci    private CheckboxMenuItem inMenuItem;
91141cc406Sopenharmony_ci
92141cc406Sopenharmony_ci	/*
93141cc406Sopenharmony_ci	 *	Main program.
94141cc406Sopenharmony_ci	 */
95141cc406Sopenharmony_ci    public static void main(String args[])
96141cc406Sopenharmony_ci	{
97141cc406Sopenharmony_ci	if (!initSane())		// Initialize SANE.
98141cc406Sopenharmony_ci		return;
99141cc406Sopenharmony_ci	Jscanimage prog = new Jscanimage();
100141cc406Sopenharmony_ci	prog.pack();
101141cc406Sopenharmony_ci	prog.show();
102141cc406Sopenharmony_ci	}
103141cc406Sopenharmony_ci
104141cc406Sopenharmony_ci	/*
105141cc406Sopenharmony_ci	 *	Create main window.
106141cc406Sopenharmony_ci	 */
107141cc406Sopenharmony_ci    public Jscanimage()
108141cc406Sopenharmony_ci	{
109141cc406Sopenharmony_ci	super("SANE Scanimage");
110141cc406Sopenharmony_ci	addWindowListener(this);
111141cc406Sopenharmony_ci					// Open SANE device.
112141cc406Sopenharmony_ci	saneHandle = initSaneDevice(devList[0].name);
113141cc406Sopenharmony_ci	if (saneHandle == 0)
114141cc406Sopenharmony_ci		System.exit(-1);
115141cc406Sopenharmony_ci					// Create scanner class.
116141cc406Sopenharmony_ci	scanIt = new ScanIt(sane, saneHandle);
117141cc406Sopenharmony_ci	init();
118141cc406Sopenharmony_ci	}
119141cc406Sopenharmony_ci
120141cc406Sopenharmony_ci	/*
121141cc406Sopenharmony_ci	 *	Clean up.
122141cc406Sopenharmony_ci	 */
123141cc406Sopenharmony_ci    public void finalize()
124141cc406Sopenharmony_ci	{
125141cc406Sopenharmony_ci	if (sane != null)
126141cc406Sopenharmony_ci		{
127141cc406Sopenharmony_ci		if (saneHandle != 0)
128141cc406Sopenharmony_ci			sane.close(saneHandle);
129141cc406Sopenharmony_ci		sane.exit();
130141cc406Sopenharmony_ci		sane = null;
131141cc406Sopenharmony_ci		}
132141cc406Sopenharmony_ci	saneHandle = 0;
133141cc406Sopenharmony_ci	if (outFile != null)
134141cc406Sopenharmony_ci		{
135141cc406Sopenharmony_ci		try
136141cc406Sopenharmony_ci			{
137141cc406Sopenharmony_ci			outFile.close();
138141cc406Sopenharmony_ci			}
139141cc406Sopenharmony_ci		catch (IOException e)
140141cc406Sopenharmony_ci			{ }
141141cc406Sopenharmony_ci		outFile = null;
142141cc406Sopenharmony_ci		}
143141cc406Sopenharmony_ci	System.out.println("In finalize()");
144141cc406Sopenharmony_ci	}
145141cc406Sopenharmony_ci
146141cc406Sopenharmony_ci	/*
147141cc406Sopenharmony_ci	 *	Return info.
148141cc406Sopenharmony_ci	 */
149141cc406Sopenharmony_ci    public Sane getSane()
150141cc406Sopenharmony_ci	{ return sane; }
151141cc406Sopenharmony_ci    public int getSaneHandle()
152141cc406Sopenharmony_ci	{ return saneHandle; }
153141cc406Sopenharmony_ci    public double getUnitLength()
154141cc406Sopenharmony_ci	{ return unitLength; }
155141cc406Sopenharmony_ci
156141cc406Sopenharmony_ci	/*
157141cc406Sopenharmony_ci	 *	Initialize SANE.
158141cc406Sopenharmony_ci	 */
159141cc406Sopenharmony_ci    private static boolean initSane()
160141cc406Sopenharmony_ci	{
161141cc406Sopenharmony_ci	sane = new Sane();
162141cc406Sopenharmony_ci	int version[] = new int[1];	// Array to get version #.
163141cc406Sopenharmony_ci	int status = sane.init(version);
164141cc406Sopenharmony_ci	if (status != Sane.STATUS_GOOD)
165141cc406Sopenharmony_ci		{
166141cc406Sopenharmony_ci		System.out.println("getDevices() failed.  Status= " + status);
167141cc406Sopenharmony_ci		return (false);
168141cc406Sopenharmony_ci		}
169141cc406Sopenharmony_ci					// Get list of devices.
170141cc406Sopenharmony_ci					// Allocate room for 50.
171141cc406Sopenharmony_ci	devList = new SaneDevice[50];
172141cc406Sopenharmony_ci	status = sane.getDevices(devList, false);
173141cc406Sopenharmony_ci	if (status != Sane.STATUS_GOOD)
174141cc406Sopenharmony_ci		{
175141cc406Sopenharmony_ci		System.out.println("getDevices() failed.  Status= " + status);
176141cc406Sopenharmony_ci		return (false);
177141cc406Sopenharmony_ci		}
178141cc406Sopenharmony_ci	for (int i = 0; i < 50 && devList[i] != null; i++)
179141cc406Sopenharmony_ci		{
180141cc406Sopenharmony_ci		System.out.println("Device '" + devList[i].name + "' is a " +
181141cc406Sopenharmony_ci			devList[i].vendor + " " + devList[i].model + " " +
182141cc406Sopenharmony_ci			devList[i].type);
183141cc406Sopenharmony_ci		}
184141cc406Sopenharmony_ci	return (true);
185141cc406Sopenharmony_ci	}
186141cc406Sopenharmony_ci
187141cc406Sopenharmony_ci	/*
188141cc406Sopenharmony_ci	 *	Open device.
189141cc406Sopenharmony_ci	 *
190141cc406Sopenharmony_ci	 *	Output:	Handle, or 0 if error.
191141cc406Sopenharmony_ci	 */
192141cc406Sopenharmony_ci    private int initSaneDevice(String name)
193141cc406Sopenharmony_ci	{
194141cc406Sopenharmony_ci	int handle[] = new int[1];
195141cc406Sopenharmony_ci					// Open 1st device, for now.
196141cc406Sopenharmony_ci	int status = sane.open(name, handle);
197141cc406Sopenharmony_ci	if (status != Sane.STATUS_GOOD)
198141cc406Sopenharmony_ci		{
199141cc406Sopenharmony_ci		System.out.println("open() failed.  Status= " + status);
200141cc406Sopenharmony_ci		return (0);
201141cc406Sopenharmony_ci		}
202141cc406Sopenharmony_ci	setTitle("SANE - " + name);
203141cc406Sopenharmony_ci	System.out.println("Open handle=" + handle[0]);
204141cc406Sopenharmony_ci	return (handle[0]);
205141cc406Sopenharmony_ci	}
206141cc406Sopenharmony_ci
207141cc406Sopenharmony_ci	/*
208141cc406Sopenharmony_ci	 *	Add a labeled option to the main dialog.
209141cc406Sopenharmony_ci	 */
210141cc406Sopenharmony_ci    private void addLabeledOption(JPanel group, String title, Component opt,
211141cc406Sopenharmony_ci						GridBagConstraints c)
212141cc406Sopenharmony_ci	{
213141cc406Sopenharmony_ci	JLabel label = new JLabel(title);
214141cc406Sopenharmony_ci	c.gridwidth = GridBagConstraints.RELATIVE;
215141cc406Sopenharmony_ci	c.fill = GridBagConstraints.NONE;
216141cc406Sopenharmony_ci	c.anchor = GridBagConstraints.WEST;
217141cc406Sopenharmony_ci	c.weightx = .1;
218141cc406Sopenharmony_ci	group.add(label, c);
219141cc406Sopenharmony_ci	c.gridwidth = GridBagConstraints.REMAINDER;
220141cc406Sopenharmony_ci	c.fill = GridBagConstraints.HORIZONTAL;
221141cc406Sopenharmony_ci	c.weightx = .4;
222141cc406Sopenharmony_ci	group.add(opt, c);
223141cc406Sopenharmony_ci	}
224141cc406Sopenharmony_ci
225141cc406Sopenharmony_ci	/*
226141cc406Sopenharmony_ci	 *	Get options for device.
227141cc406Sopenharmony_ci	 */
228141cc406Sopenharmony_ci    private boolean initSaneOptions()
229141cc406Sopenharmony_ci	{
230141cc406Sopenharmony_ci	JPanel group = null;
231141cc406Sopenharmony_ci	GridBagConstraints c = new GridBagConstraints();
232141cc406Sopenharmony_ci	c.weightx = .4;
233141cc406Sopenharmony_ci	c.weighty = .4;
234141cc406Sopenharmony_ci					// Get # of device options.
235141cc406Sopenharmony_ci	int numDevOptions[] = new int[1];
236141cc406Sopenharmony_ci	int status = sane.getControlOption(saneHandle, 0, numDevOptions, null);
237141cc406Sopenharmony_ci	if (status != Sane.STATUS_GOOD)
238141cc406Sopenharmony_ci		{
239141cc406Sopenharmony_ci		System.out.println("controlOption() failed.  Status= "
240141cc406Sopenharmony_ci								+ status);
241141cc406Sopenharmony_ci		return (false);
242141cc406Sopenharmony_ci		}
243141cc406Sopenharmony_ci	System.out.println("Number of device options=" + numDevOptions[0]);
244141cc406Sopenharmony_ci					// Do each option.
245141cc406Sopenharmony_ci	for (int i = 0; i < numDevOptions[0]; i++)
246141cc406Sopenharmony_ci		{
247141cc406Sopenharmony_ci		SaneOption opt = sane.getOptionDescriptor(saneHandle, i);
248141cc406Sopenharmony_ci		if (opt == null)
249141cc406Sopenharmony_ci			{
250141cc406Sopenharmony_ci			System.out.println("getOptionDescriptor() failed for "
251141cc406Sopenharmony_ci						+ i);
252141cc406Sopenharmony_ci			continue;
253141cc406Sopenharmony_ci			}
254141cc406Sopenharmony_ci/*
255141cc406Sopenharmony_ci		System.out.println("Option title: " + opt.title);
256141cc406Sopenharmony_ci		System.out.println("Option desc:  " + opt.desc);
257141cc406Sopenharmony_ci		System.out.println("Option type:  " + opt.type);
258141cc406Sopenharmony_ci */
259141cc406Sopenharmony_ci		String title;		// Set up title.
260141cc406Sopenharmony_ci		if (opt.unit == SaneOption.UNIT_NONE)
261141cc406Sopenharmony_ci			title = opt.title;
262141cc406Sopenharmony_ci		else			// Show units.
263141cc406Sopenharmony_ci			title = opt.title + " [" +
264141cc406Sopenharmony_ci					opt.unitString(unitLength) + ']';
265141cc406Sopenharmony_ci		switch (opt.type)
266141cc406Sopenharmony_ci			{
267141cc406Sopenharmony_ci		case SaneOption.TYPE_GROUP:
268141cc406Sopenharmony_ci					// Group for a set of options.
269141cc406Sopenharmony_ci			group = new JPanel(new GridBagLayout());
270141cc406Sopenharmony_ci			c.gridwidth = GridBagConstraints.REMAINDER;
271141cc406Sopenharmony_ci			c.fill = GridBagConstraints.BOTH;
272141cc406Sopenharmony_ci			c.anchor = GridBagConstraints.CENTER;
273141cc406Sopenharmony_ci			add(group, c);
274141cc406Sopenharmony_ci			group.setBorder(new TitledBorder(title));
275141cc406Sopenharmony_ci			break;
276141cc406Sopenharmony_ci		case SaneOption.TYPE_BOOL:
277141cc406Sopenharmony_ci					// A checkbox.
278141cc406Sopenharmony_ci			SaneCheckBox cbox = new SaneCheckBox(opt.title,
279141cc406Sopenharmony_ci						this, i, opt.desc);
280141cc406Sopenharmony_ci			c.gridwidth = GridBagConstraints.REMAINDER;
281141cc406Sopenharmony_ci			c.fill = GridBagConstraints.NONE;
282141cc406Sopenharmony_ci			c.anchor = GridBagConstraints.WEST;
283141cc406Sopenharmony_ci			if (group != null)
284141cc406Sopenharmony_ci				group.add(cbox, c);
285141cc406Sopenharmony_ci			addControl(cbox);
286141cc406Sopenharmony_ci			break;
287141cc406Sopenharmony_ci		case SaneOption.TYPE_FIXED:
288141cc406Sopenharmony_ci					// Fixed-point value.
289141cc406Sopenharmony_ci			if (opt.size != 4)
290141cc406Sopenharmony_ci				break;	// Not sure about this.
291141cc406Sopenharmony_ci			switch (opt.constraintType)
292141cc406Sopenharmony_ci				{
293141cc406Sopenharmony_ci			case SaneOption.CONSTRAINT_RANGE:
294141cc406Sopenharmony_ci					// A scale.
295141cc406Sopenharmony_ci				SaneSlider slider = new FixedSaneSlider(
296141cc406Sopenharmony_ci						opt.rangeConstraint.min,
297141cc406Sopenharmony_ci						opt.rangeConstraint.max,
298141cc406Sopenharmony_ci						opt.unit == SaneOption.UNIT_MM,
299141cc406Sopenharmony_ci						this, i, opt.desc);
300141cc406Sopenharmony_ci				addLabeledOption(group, title, slider, c);
301141cc406Sopenharmony_ci				addControl(slider);
302141cc406Sopenharmony_ci				break;
303141cc406Sopenharmony_ci			case SaneOption.CONSTRAINT_WORD_LIST:
304141cc406Sopenharmony_ci					// Select from a list.
305141cc406Sopenharmony_ci				SaneFixedBox list = new SaneFixedBox(
306141cc406Sopenharmony_ci							this, i, opt.desc);
307141cc406Sopenharmony_ci				addLabeledOption(group, title, list, c);
308141cc406Sopenharmony_ci				addControl(list);
309141cc406Sopenharmony_ci				break;
310141cc406Sopenharmony_ci				}
311141cc406Sopenharmony_ci			break;
312141cc406Sopenharmony_ci		case SaneOption.TYPE_INT:
313141cc406Sopenharmony_ci					// Integer value.
314141cc406Sopenharmony_ci			if (opt.size != 4)
315141cc406Sopenharmony_ci				break;	// Not sure about this.
316141cc406Sopenharmony_ci			switch (opt.constraintType)
317141cc406Sopenharmony_ci				{
318141cc406Sopenharmony_ci			case SaneOption.CONSTRAINT_RANGE:
319141cc406Sopenharmony_ci					// A scale.
320141cc406Sopenharmony_ci				SaneSlider slider = new SaneSlider(
321141cc406Sopenharmony_ci						opt.rangeConstraint.min,
322141cc406Sopenharmony_ci						opt.rangeConstraint.max,
323141cc406Sopenharmony_ci						this, i, opt.desc);
324141cc406Sopenharmony_ci				addLabeledOption(group, title, slider, c);
325141cc406Sopenharmony_ci				addControl(slider);
326141cc406Sopenharmony_ci				break;
327141cc406Sopenharmony_ci			case SaneOption.CONSTRAINT_WORD_LIST:
328141cc406Sopenharmony_ci					// Select from a list.
329141cc406Sopenharmony_ci				SaneIntBox list = new SaneIntBox(
330141cc406Sopenharmony_ci							this, i, opt.desc);
331141cc406Sopenharmony_ci				addLabeledOption(group, title, list, c);
332141cc406Sopenharmony_ci				addControl(list);
333141cc406Sopenharmony_ci				break;
334141cc406Sopenharmony_ci				}
335141cc406Sopenharmony_ci			break;
336141cc406Sopenharmony_ci		case SaneOption.TYPE_STRING:
337141cc406Sopenharmony_ci					// Text entry or choice box.
338141cc406Sopenharmony_ci			switch (opt.constraintType)
339141cc406Sopenharmony_ci				{
340141cc406Sopenharmony_ci			case SaneOption.CONSTRAINT_STRING_LIST:
341141cc406Sopenharmony_ci					// Make a list.
342141cc406Sopenharmony_ci				SaneStringBox list = new SaneStringBox(
343141cc406Sopenharmony_ci							this, i, opt.desc);
344141cc406Sopenharmony_ci				addLabeledOption(group, title, list, c);
345141cc406Sopenharmony_ci				addControl(list);
346141cc406Sopenharmony_ci				break;
347141cc406Sopenharmony_ci			case SaneOption.CONSTRAINT_NONE:
348141cc406Sopenharmony_ci				SaneTextField tfield = new SaneTextField(16,
349141cc406Sopenharmony_ci							this, i, opt.desc);
350141cc406Sopenharmony_ci				addLabeledOption(group, title, tfield, c);
351141cc406Sopenharmony_ci				addControl(tfield);
352141cc406Sopenharmony_ci				break;
353141cc406Sopenharmony_ci				}
354141cc406Sopenharmony_ci			break;
355141cc406Sopenharmony_ci		case SaneOption.TYPE_BUTTON:
356141cc406Sopenharmony_ci			c.gridwidth = GridBagConstraints.REMAINDER;
357141cc406Sopenharmony_ci			c.fill = GridBagConstraints.HORIZONTAL;
358141cc406Sopenharmony_ci			c.anchor = GridBagConstraints.CENTER;
359141cc406Sopenharmony_ci			c.insets = new Insets(8, 4, 4, 4);
360141cc406Sopenharmony_ci			JButton btn = new SaneButton(title, this, i, opt.desc);
361141cc406Sopenharmony_ci			group.add(btn, c);
362141cc406Sopenharmony_ci			c.insets = null;
363141cc406Sopenharmony_ci			break;
364141cc406Sopenharmony_ci		default:
365141cc406Sopenharmony_ci			break;
366141cc406Sopenharmony_ci			}
367141cc406Sopenharmony_ci		}
368141cc406Sopenharmony_ci	return (true);
369141cc406Sopenharmony_ci	}
370141cc406Sopenharmony_ci
371141cc406Sopenharmony_ci	/*
372141cc406Sopenharmony_ci	 *	Set up "Output" panel.
373141cc406Sopenharmony_ci	 */
374141cc406Sopenharmony_ci    private JPanel initOutputPanel()
375141cc406Sopenharmony_ci	{
376141cc406Sopenharmony_ci	JPanel panel = new JPanel(new GridBagLayout());
377141cc406Sopenharmony_ci	GridBagConstraints c = new GridBagConstraints();
378141cc406Sopenharmony_ci					// Want 1 row.
379141cc406Sopenharmony_ci	c.gridx = GridBagConstraints.RELATIVE;
380141cc406Sopenharmony_ci	c.gridy = 0;
381141cc406Sopenharmony_ci	c.anchor = GridBagConstraints.WEST;
382141cc406Sopenharmony_ci//	c.fill = GridBagConstraints.HORIZONTAL;
383141cc406Sopenharmony_ci	c.weightx = .4;
384141cc406Sopenharmony_ci	c.weighty = .4;
385141cc406Sopenharmony_ci	panel.setBorder(new TitledBorder("Output"));
386141cc406Sopenharmony_ci	panel.add(new Label("Filename"), c);
387141cc406Sopenharmony_ci	outputField = new JTextField("out.pnm", 16);
388141cc406Sopenharmony_ci	panel.add(outputField, c);
389141cc406Sopenharmony_ci	c.insets = new Insets(0, 8, 0, 0);
390141cc406Sopenharmony_ci	browseButton = new JButton("Browse");
391141cc406Sopenharmony_ci	browseButton.addActionListener(this);
392141cc406Sopenharmony_ci	panel.add(browseButton, c);
393141cc406Sopenharmony_ci	return (panel);
394141cc406Sopenharmony_ci	}
395141cc406Sopenharmony_ci
396141cc406Sopenharmony_ci	/*
397141cc406Sopenharmony_ci	 *	Initialize main window.
398141cc406Sopenharmony_ci	 */
399141cc406Sopenharmony_ci    private void init()
400141cc406Sopenharmony_ci	{
401141cc406Sopenharmony_ci	controls = new Vector();	// List of SaneComponent's.
402141cc406Sopenharmony_ci					// Try a light blue:
403141cc406Sopenharmony_ci	setBackground(new Color(140, 200, 255));
404141cc406Sopenharmony_ci					// And a larger font.
405141cc406Sopenharmony_ci	font = new Font("Helvetica", Font.PLAIN, 12);
406141cc406Sopenharmony_ci	setFont(font);
407141cc406Sopenharmony_ci	initMenu();
408141cc406Sopenharmony_ci					// Main panel will be 1 column.
409141cc406Sopenharmony_ci	setLayout(new GridBagLayout());
410141cc406Sopenharmony_ci	GridBagConstraints c = new GridBagConstraints();
411141cc406Sopenharmony_ci	c.gridwidth = GridBagConstraints.REMAINDER;
412141cc406Sopenharmony_ci	c.fill = GridBagConstraints.BOTH;
413141cc406Sopenharmony_ci	c.weightx = .4;
414141cc406Sopenharmony_ci	c.weighty = .4;
415141cc406Sopenharmony_ci					// Panel for output:
416141cc406Sopenharmony_ci	JPanel outputPanel = initOutputPanel();
417141cc406Sopenharmony_ci	add(outputPanel, c);
418141cc406Sopenharmony_ci	initSaneOptions();		// Get SANE options, set up dialog.
419141cc406Sopenharmony_ci	initButtons();			// Put buttons at bottom.
420141cc406Sopenharmony_ci	}
421141cc406Sopenharmony_ci
422141cc406Sopenharmony_ci	/*
423141cc406Sopenharmony_ci	 *	Add a control to the dialog and set its initial value.
424141cc406Sopenharmony_ci	 */
425141cc406Sopenharmony_ci    private void addControl(SaneComponent comp)
426141cc406Sopenharmony_ci	{
427141cc406Sopenharmony_ci	controls.addElement(comp);
428141cc406Sopenharmony_ci	comp.setFromControl();		// Get initial value.
429141cc406Sopenharmony_ci	}
430141cc406Sopenharmony_ci
431141cc406Sopenharmony_ci	/*
432141cc406Sopenharmony_ci	 *	Reinitialize components from SANE controls.
433141cc406Sopenharmony_ci	 */
434141cc406Sopenharmony_ci    private void reinit()
435141cc406Sopenharmony_ci	{
436141cc406Sopenharmony_ci	Enumeration ctrls = controls.elements();
437141cc406Sopenharmony_ci	while (ctrls.hasMoreElements())	// Do each control.
438141cc406Sopenharmony_ci		{
439141cc406Sopenharmony_ci		SaneComponent comp = (SaneComponent) ctrls.nextElement();
440141cc406Sopenharmony_ci		comp.setFromControl();
441141cc406Sopenharmony_ci		}
442141cc406Sopenharmony_ci	}
443141cc406Sopenharmony_ci
444141cc406Sopenharmony_ci	/*
445141cc406Sopenharmony_ci	 *	Set up the menubar.
446141cc406Sopenharmony_ci	 */
447141cc406Sopenharmony_ci    private void initMenu()
448141cc406Sopenharmony_ci	{
449141cc406Sopenharmony_ci	MenuBar mbar = new MenuBar();
450141cc406Sopenharmony_ci	Menu file = new Menu("File");
451141cc406Sopenharmony_ci	mbar.add(file);
452141cc406Sopenharmony_ci	exitMenuItem = new MenuItem("Exit");
453141cc406Sopenharmony_ci	exitMenuItem.addActionListener(this);
454141cc406Sopenharmony_ci	file.add(exitMenuItem);
455141cc406Sopenharmony_ci	Menu pref = new Menu("Preferences");
456141cc406Sopenharmony_ci	mbar.add(pref);
457141cc406Sopenharmony_ci	toolTipsMenuItem = new CheckboxMenuItem("Show tooltips", true);
458141cc406Sopenharmony_ci	toolTipsMenuItem.addItemListener(this);
459141cc406Sopenharmony_ci	pref.add(toolTipsMenuItem);
460141cc406Sopenharmony_ci	Menu units = new Menu("Length unit");
461141cc406Sopenharmony_ci	pref.add(units);
462141cc406Sopenharmony_ci	mmMenuItem = new CheckboxMenuItem("millimeters", true);
463141cc406Sopenharmony_ci	mmMenuItem.addItemListener(this);
464141cc406Sopenharmony_ci	units.add(mmMenuItem);
465141cc406Sopenharmony_ci	cmMenuItem = new CheckboxMenuItem("centimeters", false);
466141cc406Sopenharmony_ci	cmMenuItem.addItemListener(this);
467141cc406Sopenharmony_ci	units.add(cmMenuItem);
468141cc406Sopenharmony_ci	inMenuItem = new CheckboxMenuItem("inches", false);
469141cc406Sopenharmony_ci	inMenuItem.addItemListener(this);
470141cc406Sopenharmony_ci	units.add(inMenuItem);
471141cc406Sopenharmony_ci	setMenuBar(mbar);
472141cc406Sopenharmony_ci	}
473141cc406Sopenharmony_ci
474141cc406Sopenharmony_ci	/*
475141cc406Sopenharmony_ci	 *	Set up buttons panel at very bottom.
476141cc406Sopenharmony_ci	 */
477141cc406Sopenharmony_ci    private void initButtons()
478141cc406Sopenharmony_ci	{
479141cc406Sopenharmony_ci					// Buttons are at bottom.
480141cc406Sopenharmony_ci	JPanel bottomPanel = new JPanel(new GridBagLayout());
481141cc406Sopenharmony_ci					// Indent around buttons.
482141cc406Sopenharmony_ci	GridBagConstraints c = new GridBagConstraints();
483141cc406Sopenharmony_ci	c.gridwidth = GridBagConstraints.REMAINDER;
484141cc406Sopenharmony_ci	c.insets = new Insets(8, 8, 8, 8);
485141cc406Sopenharmony_ci	c.weightx = .4;
486141cc406Sopenharmony_ci	c.weighty = .2;
487141cc406Sopenharmony_ci	c.fill = GridBagConstraints.HORIZONTAL;
488141cc406Sopenharmony_ci	add(bottomPanel, c);
489141cc406Sopenharmony_ci	c.weighty = c.weightx = .4;
490141cc406Sopenharmony_ci	c.fill = GridBagConstraints.BOTH;
491141cc406Sopenharmony_ci	c.gridwidth = c.gridheight = 1;
492141cc406Sopenharmony_ci					// Create image display box.
493141cc406Sopenharmony_ci	imageDisplay = new ImageCanvas();
494141cc406Sopenharmony_ci	bottomPanel.add(imageDisplay, c);
495141cc406Sopenharmony_ci					// Put btns. to right in 1 column.
496141cc406Sopenharmony_ci	JPanel buttonsPanel = new JPanel(new GridLayout(0, 1, 8, 8));
497141cc406Sopenharmony_ci	bottomPanel.add(buttonsPanel, c);
498141cc406Sopenharmony_ci	scanButton = new JButton("Scan");
499141cc406Sopenharmony_ci	buttonsPanel.add(scanButton);
500141cc406Sopenharmony_ci	scanButton.addActionListener(this);
501141cc406Sopenharmony_ci	previewButton = new JButton("Preview Window");
502141cc406Sopenharmony_ci	buttonsPanel.add(previewButton);
503141cc406Sopenharmony_ci	previewButton.addActionListener(this);
504141cc406Sopenharmony_ci	}
505141cc406Sopenharmony_ci
506141cc406Sopenharmony_ci	/*
507141cc406Sopenharmony_ci	 *	Set a SANE integer option.
508141cc406Sopenharmony_ci	 */
509141cc406Sopenharmony_ci    public void setControlOption(int optNum, int val)
510141cc406Sopenharmony_ci	{
511141cc406Sopenharmony_ci	int [] info = new int[1];
512141cc406Sopenharmony_ci	if (sane.setControlOption(saneHandle, optNum,
513141cc406Sopenharmony_ci			SaneOption.ACTION_SET_VALUE, val, info)
514141cc406Sopenharmony_ci							!= Sane.STATUS_GOOD)
515141cc406Sopenharmony_ci		System.out.println("setControlOption() failed.");
516141cc406Sopenharmony_ci	checkOptionInfo(info[0]);
517141cc406Sopenharmony_ci	}
518141cc406Sopenharmony_ci
519141cc406Sopenharmony_ci	/*
520141cc406Sopenharmony_ci	 *	Set a SANE text option.
521141cc406Sopenharmony_ci	 */
522141cc406Sopenharmony_ci    public void setControlOption(int optNum, String val)
523141cc406Sopenharmony_ci	{
524141cc406Sopenharmony_ci	int [] info = new int[1];
525141cc406Sopenharmony_ci	if (sane.setControlOption(saneHandle, optNum,
526141cc406Sopenharmony_ci			SaneOption.ACTION_SET_VALUE, val, info)
527141cc406Sopenharmony_ci							!= Sane.STATUS_GOOD)
528141cc406Sopenharmony_ci		System.out.println("setControlOption() failed.");
529141cc406Sopenharmony_ci	checkOptionInfo(info[0]);
530141cc406Sopenharmony_ci	}
531141cc406Sopenharmony_ci
532141cc406Sopenharmony_ci	/*
533141cc406Sopenharmony_ci	 *	Check the 'info' word returned from setControlOption().
534141cc406Sopenharmony_ci	 */
535141cc406Sopenharmony_ci    private void checkOptionInfo(int info)
536141cc406Sopenharmony_ci	{
537141cc406Sopenharmony_ci					// Does everything completely change?
538141cc406Sopenharmony_ci	if ((info & SaneOption.INFO_RELOAD_OPTIONS) != 0)
539141cc406Sopenharmony_ci		reinit();
540141cc406Sopenharmony_ci					// Need to update status line?
541141cc406Sopenharmony_ci	if ((info & SaneOption.INFO_RELOAD_PARAMS) != 0)
542141cc406Sopenharmony_ci		;			// ++++++++FILL IN.
543141cc406Sopenharmony_ci	}
544141cc406Sopenharmony_ci
545141cc406Sopenharmony_ci	/*
546141cc406Sopenharmony_ci	 *	Handle a user action.
547141cc406Sopenharmony_ci	 */
548141cc406Sopenharmony_ci    public void actionPerformed(ActionEvent e)
549141cc406Sopenharmony_ci	{
550141cc406Sopenharmony_ci	if (e.getSource() == scanButton)
551141cc406Sopenharmony_ci		{
552141cc406Sopenharmony_ci		System.out.println("Rescanning");
553141cc406Sopenharmony_ci					// Get file name.
554141cc406Sopenharmony_ci		String fname = outputField.getText();
555141cc406Sopenharmony_ci		if (fname == null || fname.length() == 0)
556141cc406Sopenharmony_ci			fname = "out.pnm";
557141cc406Sopenharmony_ci		try
558141cc406Sopenharmony_ci			{
559141cc406Sopenharmony_ci			outFile = new FileOutputStream(fname);
560141cc406Sopenharmony_ci			}
561141cc406Sopenharmony_ci		catch (IOException oe)
562141cc406Sopenharmony_ci			{
563141cc406Sopenharmony_ci			System.out.println("Error creating file:  " + fname);
564141cc406Sopenharmony_ci			outFile = null;
565141cc406Sopenharmony_ci			return;
566141cc406Sopenharmony_ci			}
567141cc406Sopenharmony_ci					// Disable "Scan" button.
568141cc406Sopenharmony_ci		scanButton.setEnabled(false);
569141cc406Sopenharmony_ci		scanIt.setOutputFile(outFile);
570141cc406Sopenharmony_ci		imageDisplay.setImage(scanIt, this);
571141cc406Sopenharmony_ci		}
572141cc406Sopenharmony_ci	else if (e.getSource() == browseButton)
573141cc406Sopenharmony_ci		{
574141cc406Sopenharmony_ci		File file;		// For working with names.
575141cc406Sopenharmony_ci		FileDialog dlg = new FileDialog(this, "Output Filename",
576141cc406Sopenharmony_ci						FileDialog.SAVE);
577141cc406Sopenharmony_ci		if (outDir != null)	// Set to last directory.
578141cc406Sopenharmony_ci			dlg.setDirectory(outDir);
579141cc406Sopenharmony_ci					// Get current name.
580141cc406Sopenharmony_ci		String fname = outputField.getText();
581141cc406Sopenharmony_ci		if (fname != null)
582141cc406Sopenharmony_ci			{
583141cc406Sopenharmony_ci			file = new File(fname);
584141cc406Sopenharmony_ci			dlg.setFile(file.getName());
585141cc406Sopenharmony_ci			String dname = file.getParent();
586141cc406Sopenharmony_ci			if (dname != null)
587141cc406Sopenharmony_ci				dlg.setDirectory(outDir);
588141cc406Sopenharmony_ci			}
589141cc406Sopenharmony_ci		dlg.show();		// Wait for result.
590141cc406Sopenharmony_ci		fname = dlg.getFile();
591141cc406Sopenharmony_ci					// Store dir. for next time.
592141cc406Sopenharmony_ci		outDir = dlg.getDirectory();
593141cc406Sopenharmony_ci		if (fname != null)
594141cc406Sopenharmony_ci			{
595141cc406Sopenharmony_ci			file = new File(outDir, fname);
596141cc406Sopenharmony_ci			String curDir;
597141cc406Sopenharmony_ci			String fullName;
598141cc406Sopenharmony_ci			try
599141cc406Sopenharmony_ci				{
600141cc406Sopenharmony_ci				curDir = (new File(".")).getCanonicalPath();
601141cc406Sopenharmony_ci				fullName = file.getCanonicalPath();
602141cc406Sopenharmony_ci					// Not in current directory?
603141cc406Sopenharmony_ci				if (!curDir.equals(
604141cc406Sopenharmony_ci					(new File(fullName)).getParent()))
605141cc406Sopenharmony_ci					fname = fullName;
606141cc406Sopenharmony_ci				}
607141cc406Sopenharmony_ci			catch (IOException ex)
608141cc406Sopenharmony_ci				{ curDir = "."; fname = file.getName(); }
609141cc406Sopenharmony_ci			outputField.setText(fname);
610141cc406Sopenharmony_ci			}
611141cc406Sopenharmony_ci		}
612141cc406Sopenharmony_ci	else if (e.getSource() == exitMenuItem)
613141cc406Sopenharmony_ci		{
614141cc406Sopenharmony_ci		finalize();		// Just to be safe.
615141cc406Sopenharmony_ci		System.exit(0);
616141cc406Sopenharmony_ci		}
617141cc406Sopenharmony_ci	}
618141cc406Sopenharmony_ci
619141cc406Sopenharmony_ci	/*
620141cc406Sopenharmony_ci	 *	Handle checkable menu items.
621141cc406Sopenharmony_ci	 */
622141cc406Sopenharmony_ci    public void itemStateChanged(ItemEvent e)
623141cc406Sopenharmony_ci	{
624141cc406Sopenharmony_ci	if (e.getSource() == mmMenuItem)
625141cc406Sopenharmony_ci		{			// Wants mm.
626141cc406Sopenharmony_ci		unitLength = 1;
627141cc406Sopenharmony_ci		if (e.getStateChange() == ItemEvent.SELECTED)
628141cc406Sopenharmony_ci			{
629141cc406Sopenharmony_ci			cmMenuItem.setState(false);
630141cc406Sopenharmony_ci			inMenuItem.setState(false);
631141cc406Sopenharmony_ci			reinit();	// Re-display controls.
632141cc406Sopenharmony_ci			}
633141cc406Sopenharmony_ci		else			// Don't let him deselect.
634141cc406Sopenharmony_ci			mmMenuItem.setState(true);
635141cc406Sopenharmony_ci		}
636141cc406Sopenharmony_ci	if (e.getSource() == cmMenuItem)
637141cc406Sopenharmony_ci		{			// Wants cm.
638141cc406Sopenharmony_ci		unitLength = 10;
639141cc406Sopenharmony_ci		if (e.getStateChange() == ItemEvent.SELECTED)
640141cc406Sopenharmony_ci			{
641141cc406Sopenharmony_ci			mmMenuItem.setState(false);
642141cc406Sopenharmony_ci			inMenuItem.setState(false);
643141cc406Sopenharmony_ci			reinit();	// Re-display controls.
644141cc406Sopenharmony_ci			}
645141cc406Sopenharmony_ci		else
646141cc406Sopenharmony_ci			cmMenuItem.setState(true);
647141cc406Sopenharmony_ci		}
648141cc406Sopenharmony_ci	if (e.getSource() == inMenuItem)
649141cc406Sopenharmony_ci		{			// Wants inches.
650141cc406Sopenharmony_ci		unitLength = 25.4;
651141cc406Sopenharmony_ci		if (e.getStateChange() == ItemEvent.SELECTED)
652141cc406Sopenharmony_ci			{
653141cc406Sopenharmony_ci			mmMenuItem.setState(false);
654141cc406Sopenharmony_ci			cmMenuItem.setState(false);
655141cc406Sopenharmony_ci			reinit();	// Re-display controls.
656141cc406Sopenharmony_ci			}
657141cc406Sopenharmony_ci		else			// Don't let him deselect.
658141cc406Sopenharmony_ci			inMenuItem.setState(true);
659141cc406Sopenharmony_ci		}
660141cc406Sopenharmony_ci	}
661141cc406Sopenharmony_ci
662141cc406Sopenharmony_ci	/*
663141cc406Sopenharmony_ci	 *	Scan is complete.
664141cc406Sopenharmony_ci	 */
665141cc406Sopenharmony_ci    public void imageDone(boolean error)
666141cc406Sopenharmony_ci	{
667141cc406Sopenharmony_ci	if (error)
668141cc406Sopenharmony_ci		System.out.println("Scanning error.");
669141cc406Sopenharmony_ci	if (outFile != null)		// Close file.
670141cc406Sopenharmony_ci		try
671141cc406Sopenharmony_ci			{
672141cc406Sopenharmony_ci			outFile.close();
673141cc406Sopenharmony_ci			}
674141cc406Sopenharmony_ci		catch (IOException e)
675141cc406Sopenharmony_ci			{ }
676141cc406Sopenharmony_ci	scanButton.setEnabled(true);	// Can scan again.
677141cc406Sopenharmony_ci	}
678141cc406Sopenharmony_ci
679141cc406Sopenharmony_ci	/*
680141cc406Sopenharmony_ci	 *	Default window event handlers.
681141cc406Sopenharmony_ci	 */
682141cc406Sopenharmony_ci    public void windowClosed(WindowEvent event)
683141cc406Sopenharmony_ci	{
684141cc406Sopenharmony_ci	finalize();			// Just to be safe.
685141cc406Sopenharmony_ci	}
686141cc406Sopenharmony_ci    public void windowDeiconified(WindowEvent event) { }
687141cc406Sopenharmony_ci    public void windowIconified(WindowEvent event) { }
688141cc406Sopenharmony_ci    public void windowActivated(WindowEvent event) { }
689141cc406Sopenharmony_ci    public void windowDeactivated(WindowEvent event) { }
690141cc406Sopenharmony_ci    public void windowOpened(WindowEvent event) { }
691141cc406Sopenharmony_ci					// Handle closing event.
692141cc406Sopenharmony_ci    public void windowClosing(WindowEvent event)
693141cc406Sopenharmony_ci	{
694141cc406Sopenharmony_ci	finalize();			// Just to be safe.
695141cc406Sopenharmony_ci	System.exit(0);
696141cc406Sopenharmony_ci	}
697141cc406Sopenharmony_ci    }
698141cc406Sopenharmony_ci
699141cc406Sopenharmony_ci/*
700141cc406Sopenharmony_ci *	Interface for our dialog controls.
701141cc406Sopenharmony_ci */
702141cc406Sopenharmony_ciinterface SaneComponent
703141cc406Sopenharmony_ci    {
704141cc406Sopenharmony_ci    public void setFromControl();	// Ask SANE control for current value.
705141cc406Sopenharmony_ci    }
706141cc406Sopenharmony_ci
707141cc406Sopenharmony_ci/*
708141cc406Sopenharmony_ci *	A checkbox in our dialog.
709141cc406Sopenharmony_ci */
710141cc406Sopenharmony_ciclass SaneCheckBox extends JCheckBox implements ActionListener,
711141cc406Sopenharmony_ci					SaneComponent
712141cc406Sopenharmony_ci    {
713141cc406Sopenharmony_ci    private Jscanimage dialog;		// That which created us.
714141cc406Sopenharmony_ci    private int optNum;			// Option #.
715141cc406Sopenharmony_ci
716141cc406Sopenharmony_ci	/*
717141cc406Sopenharmony_ci	 *	Create with given state.
718141cc406Sopenharmony_ci	 */
719141cc406Sopenharmony_ci    public SaneCheckBox(String title, Jscanimage dlg, int opt, String tip)
720141cc406Sopenharmony_ci	{
721141cc406Sopenharmony_ci	super(title, false);
722141cc406Sopenharmony_ci	dialog = dlg;
723141cc406Sopenharmony_ci	optNum = opt;
724141cc406Sopenharmony_ci					// Set tool tip.
725141cc406Sopenharmony_ci	if (tip != null && tip.length() != 0)
726141cc406Sopenharmony_ci		super.setToolTipText(tip);
727141cc406Sopenharmony_ci	addActionListener(this);	// Listen to ourself.
728141cc406Sopenharmony_ci	}
729141cc406Sopenharmony_ci
730141cc406Sopenharmony_ci	/*
731141cc406Sopenharmony_ci	 *	Update Sane device option with current setting.
732141cc406Sopenharmony_ci	 */
733141cc406Sopenharmony_ci    public void actionPerformed(ActionEvent e)
734141cc406Sopenharmony_ci	{
735141cc406Sopenharmony_ci	System.out.println("In SaneCheckBox::actionPerformed()");
736141cc406Sopenharmony_ci	int val = isSelected() ? 1 : 0;
737141cc406Sopenharmony_ci	dialog.setControlOption(optNum, val);
738141cc406Sopenharmony_ci	}
739141cc406Sopenharmony_ci
740141cc406Sopenharmony_ci	/*
741141cc406Sopenharmony_ci	 *	Update from Sane control's value.
742141cc406Sopenharmony_ci	 */
743141cc406Sopenharmony_ci    public void setFromControl()
744141cc406Sopenharmony_ci	{
745141cc406Sopenharmony_ci	int [] val = new int[1];
746141cc406Sopenharmony_ci	if (dialog.getSane().getControlOption(
747141cc406Sopenharmony_ci			dialog.getSaneHandle(), optNum, val, null)
748141cc406Sopenharmony_ci						== Sane.STATUS_GOOD)
749141cc406Sopenharmony_ci		setSelected(val[0] != 0);
750141cc406Sopenharmony_ci	}
751141cc406Sopenharmony_ci    }
752141cc406Sopenharmony_ci
753141cc406Sopenharmony_ci/*
754141cc406Sopenharmony_ci *	A slider in our dialog.  This base class handles integer ranges.
755141cc406Sopenharmony_ci *	It consists of a slider and a label which shows the current value.
756141cc406Sopenharmony_ci */
757141cc406Sopenharmony_ciclass SaneSlider extends JPanel implements SaneComponent, ChangeListener
758141cc406Sopenharmony_ci    {
759141cc406Sopenharmony_ci    protected Jscanimage dialog;	// That which created us.
760141cc406Sopenharmony_ci    protected int optNum;		// Option #.
761141cc406Sopenharmony_ci    protected JSlider slider;		// The slider itself.
762141cc406Sopenharmony_ci    protected JLabel label;		// Shows current value.
763141cc406Sopenharmony_ci
764141cc406Sopenharmony_ci	/*
765141cc406Sopenharmony_ci	 *	Create with given state.
766141cc406Sopenharmony_ci	 */
767141cc406Sopenharmony_ci    public SaneSlider(int min, int max, Jscanimage dlg, int opt, String tip)
768141cc406Sopenharmony_ci	{
769141cc406Sopenharmony_ci	super(new GridBagLayout());	// Create panel.
770141cc406Sopenharmony_ci	dialog = dlg;
771141cc406Sopenharmony_ci	optNum = opt;
772141cc406Sopenharmony_ci	GridBagConstraints c = new GridBagConstraints();
773141cc406Sopenharmony_ci					// Want 1 row.
774141cc406Sopenharmony_ci	c.gridx = GridBagConstraints.RELATIVE;
775141cc406Sopenharmony_ci	c.gridy = 0;
776141cc406Sopenharmony_ci	c.anchor = GridBagConstraints.CENTER;
777141cc406Sopenharmony_ci	c.fill = GridBagConstraints.HORIZONTAL;
778141cc406Sopenharmony_ci	c.weighty = .8;
779141cc406Sopenharmony_ci	c.weightx = .2;			// Give less weight to value label.
780141cc406Sopenharmony_ci	label = new JLabel("00", SwingConstants.RIGHT);
781141cc406Sopenharmony_ci	add(label, c);
782141cc406Sopenharmony_ci	c.weightx = .8;			// Give most weight to slider.
783141cc406Sopenharmony_ci	c.fill = GridBagConstraints.HORIZONTAL;
784141cc406Sopenharmony_ci	slider = new JSlider(JSlider.HORIZONTAL, min, max,
785141cc406Sopenharmony_ci							min + (max - min)/2);
786141cc406Sopenharmony_ci	add(slider, c);
787141cc406Sopenharmony_ci					// Set tool tip.
788141cc406Sopenharmony_ci	if (tip != null && tip.length() != 0)
789141cc406Sopenharmony_ci		super.setToolTipText(tip);
790141cc406Sopenharmony_ci	slider.addChangeListener(this);	// Listen to ourself.
791141cc406Sopenharmony_ci	}
792141cc406Sopenharmony_ci
793141cc406Sopenharmony_ci	/*
794141cc406Sopenharmony_ci	 *	Update Sane device option.
795141cc406Sopenharmony_ci	 */
796141cc406Sopenharmony_ci    public void stateChanged(ChangeEvent e)
797141cc406Sopenharmony_ci	{
798141cc406Sopenharmony_ci	int val = slider.getValue();
799141cc406Sopenharmony_ci	label.setText(String.valueOf(val));
800141cc406Sopenharmony_ci	dialog.setControlOption(optNum, val);
801141cc406Sopenharmony_ci	}
802141cc406Sopenharmony_ci
803141cc406Sopenharmony_ci	/*
804141cc406Sopenharmony_ci	 *	Update from Sane control's value.
805141cc406Sopenharmony_ci	 */
806141cc406Sopenharmony_ci    public void setFromControl()
807141cc406Sopenharmony_ci	{
808141cc406Sopenharmony_ci	int [] val = new int[1];	// Get current SANE control value.
809141cc406Sopenharmony_ci	if (dialog.getSane().getControlOption(
810141cc406Sopenharmony_ci			dialog.getSaneHandle(), optNum, val, null)
811141cc406Sopenharmony_ci						== Sane.STATUS_GOOD)
812141cc406Sopenharmony_ci		{
813141cc406Sopenharmony_ci		slider.setValue(val[0]);
814141cc406Sopenharmony_ci		label.setText(String.valueOf(val[0]));
815141cc406Sopenharmony_ci		}
816141cc406Sopenharmony_ci	}
817141cc406Sopenharmony_ci    }
818141cc406Sopenharmony_ci
819141cc406Sopenharmony_ci/*
820141cc406Sopenharmony_ci *	A slider with fixed-point values:
821141cc406Sopenharmony_ci */
822141cc406Sopenharmony_ciclass FixedSaneSlider extends SaneSlider
823141cc406Sopenharmony_ci    {
824141cc406Sopenharmony_ci    private static final int SCALE_MIN = -32000;
825141cc406Sopenharmony_ci    private static final int SCALE_MAX = 32000;
826141cc406Sopenharmony_ci    double min, max;			// Min, max in floating-point.
827141cc406Sopenharmony_ci    boolean optMM;			// Option is in millimeters, so should
828141cc406Sopenharmony_ci					//   be scaled to user's pref.
829141cc406Sopenharmony_ci    private NumberFormat format;	// For printing label.
830141cc406Sopenharmony_ci	/*
831141cc406Sopenharmony_ci	 *	Create with given fixed-point range.
832141cc406Sopenharmony_ci	 */
833141cc406Sopenharmony_ci    public FixedSaneSlider(int fixed_min, int fixed_max, boolean mm,
834141cc406Sopenharmony_ci					Jscanimage dlg, int opt, String tip)
835141cc406Sopenharmony_ci	{
836141cc406Sopenharmony_ci					// Create with large integer range.
837141cc406Sopenharmony_ci	super(SCALE_MIN, SCALE_MAX, dlg, opt, tip);
838141cc406Sopenharmony_ci	format = NumberFormat.getInstance();
839141cc406Sopenharmony_ci					// For now, show 1 decimal point.
840141cc406Sopenharmony_ci	format.setMinimumFractionDigits(1);
841141cc406Sopenharmony_ci	format.setMaximumFractionDigits(1);
842141cc406Sopenharmony_ci					// Store actual range.
843141cc406Sopenharmony_ci	min = dlg.getSane().unfix(fixed_min);
844141cc406Sopenharmony_ci	max = dlg.getSane().unfix(fixed_max);
845141cc406Sopenharmony_ci	optMM = mm;
846141cc406Sopenharmony_ci	}
847141cc406Sopenharmony_ci
848141cc406Sopenharmony_ci	/*
849141cc406Sopenharmony_ci	 *	Update Sane device option.
850141cc406Sopenharmony_ci	 */
851141cc406Sopenharmony_ci    public void stateChanged(ChangeEvent e)
852141cc406Sopenharmony_ci	{
853141cc406Sopenharmony_ci	double val = (double) slider.getValue();
854141cc406Sopenharmony_ci					// Convert to actual control scale.
855141cc406Sopenharmony_ci	val = min + ((val - SCALE_MIN)/(SCALE_MAX - SCALE_MIN)) * (max - min);
856141cc406Sopenharmony_ci	label.setText(format.format(optMM ?
857141cc406Sopenharmony_ci					val/dialog.getUnitLength() : val));
858141cc406Sopenharmony_ci	dialog.setControlOption(optNum, dialog.getSane().fix(val));
859141cc406Sopenharmony_ci	}
860141cc406Sopenharmony_ci
861141cc406Sopenharmony_ci	/*
862141cc406Sopenharmony_ci	 *	Update from Sane control's value.
863141cc406Sopenharmony_ci	 */
864141cc406Sopenharmony_ci    public void setFromControl()
865141cc406Sopenharmony_ci	{
866141cc406Sopenharmony_ci	int [] ival = new int[1];	// Get current SANE control value.
867141cc406Sopenharmony_ci	if (dialog.getSane().getControlOption(
868141cc406Sopenharmony_ci			dialog.getSaneHandle(), optNum, ival, null)
869141cc406Sopenharmony_ci						== Sane.STATUS_GOOD)
870141cc406Sopenharmony_ci		{
871141cc406Sopenharmony_ci		double val = dialog.getSane().unfix(ival[0]);
872141cc406Sopenharmony_ci					// Show value with user's pref.
873141cc406Sopenharmony_ci		label.setText(format.format(optMM ?
874141cc406Sopenharmony_ci					val/dialog.getUnitLength() : val));
875141cc406Sopenharmony_ci		val = SCALE_MIN + ((val - min)/(max - min)) *
876141cc406Sopenharmony_ci						(SCALE_MAX - SCALE_MIN);
877141cc406Sopenharmony_ci		slider.setValue((int) val);
878141cc406Sopenharmony_ci		}
879141cc406Sopenharmony_ci	}
880141cc406Sopenharmony_ci    }
881141cc406Sopenharmony_ci
882141cc406Sopenharmony_ci/*
883141cc406Sopenharmony_ci *	A Button in our dialog.
884141cc406Sopenharmony_ci */
885141cc406Sopenharmony_ciclass SaneButton extends JButton implements ActionListener
886141cc406Sopenharmony_ci    {
887141cc406Sopenharmony_ci    private Jscanimage dialog;		// That which created us.
888141cc406Sopenharmony_ci    private int optNum;			// Option #.
889141cc406Sopenharmony_ci
890141cc406Sopenharmony_ci	/*
891141cc406Sopenharmony_ci	 *	Create with given state.
892141cc406Sopenharmony_ci	 */
893141cc406Sopenharmony_ci    public SaneButton(String title, Jscanimage dlg, int opt, String tip)
894141cc406Sopenharmony_ci	{
895141cc406Sopenharmony_ci	super(title);
896141cc406Sopenharmony_ci	dialog = dlg;
897141cc406Sopenharmony_ci	optNum = opt;
898141cc406Sopenharmony_ci					// Set tool tip.
899141cc406Sopenharmony_ci	if (tip != null && tip.length() != 0)
900141cc406Sopenharmony_ci		super.setToolTipText(tip);
901141cc406Sopenharmony_ci	addActionListener(this);	// Listen to ourself.
902141cc406Sopenharmony_ci	}
903141cc406Sopenharmony_ci
904141cc406Sopenharmony_ci	/*
905141cc406Sopenharmony_ci	 *	Update Sane device option.
906141cc406Sopenharmony_ci	 */
907141cc406Sopenharmony_ci    public void actionPerformed(ActionEvent e)
908141cc406Sopenharmony_ci	{
909141cc406Sopenharmony_ci	dialog.setControlOption(optNum, 0);
910141cc406Sopenharmony_ci	System.out.println("In SaneButton::actionPerformed()");
911141cc406Sopenharmony_ci	}
912141cc406Sopenharmony_ci    }
913141cc406Sopenharmony_ci
914141cc406Sopenharmony_ci/*
915141cc406Sopenharmony_ci *	A combo-box for showing a list of items.
916141cc406Sopenharmony_ci */
917141cc406Sopenharmony_ciabstract class SaneComboBox extends JComboBox
918141cc406Sopenharmony_ci				implements SaneComponent, ItemListener
919141cc406Sopenharmony_ci    {
920141cc406Sopenharmony_ci    protected Jscanimage dialog;	// That which created us.
921141cc406Sopenharmony_ci    protected int optNum;		// Option #.
922141cc406Sopenharmony_ci
923141cc406Sopenharmony_ci	/*
924141cc406Sopenharmony_ci	 *	Create it.
925141cc406Sopenharmony_ci	 */
926141cc406Sopenharmony_ci    public SaneComboBox(Jscanimage dlg, int opt, String tip)
927141cc406Sopenharmony_ci	{
928141cc406Sopenharmony_ci	dialog = dlg;
929141cc406Sopenharmony_ci	optNum = opt;
930141cc406Sopenharmony_ci					// Set tool tip.
931141cc406Sopenharmony_ci	if (tip != null && tip.length() != 0)
932141cc406Sopenharmony_ci		super.setToolTipText(tip);
933141cc406Sopenharmony_ci	addItemListener(this);
934141cc406Sopenharmony_ci	}
935141cc406Sopenharmony_ci
936141cc406Sopenharmony_ci	/*
937141cc406Sopenharmony_ci	 *	Select desired item by its text.
938141cc406Sopenharmony_ci	 */
939141cc406Sopenharmony_ci    protected void select(String text)
940141cc406Sopenharmony_ci	{
941141cc406Sopenharmony_ci	int cnt = getItemCount();
942141cc406Sopenharmony_ci	for (int i = 0; i < cnt; i++)
943141cc406Sopenharmony_ci		if (text.equals(getItemAt(i)))
944141cc406Sopenharmony_ci			{
945141cc406Sopenharmony_ci			setSelectedIndex(i);
946141cc406Sopenharmony_ci			break;
947141cc406Sopenharmony_ci			}
948141cc406Sopenharmony_ci	}
949141cc406Sopenharmony_ci
950141cc406Sopenharmony_ci    abstract public void setFromControl();
951141cc406Sopenharmony_ci    abstract public void itemStateChanged(ItemEvent e);
952141cc406Sopenharmony_ci    }
953141cc406Sopenharmony_ci
954141cc406Sopenharmony_ci/*
955141cc406Sopenharmony_ci *	A list of strings.
956141cc406Sopenharmony_ci */
957141cc406Sopenharmony_ciclass SaneStringBox extends SaneComboBox
958141cc406Sopenharmony_ci    {
959141cc406Sopenharmony_ci
960141cc406Sopenharmony_ci	/*
961141cc406Sopenharmony_ci	 *	Create it.
962141cc406Sopenharmony_ci	 */
963141cc406Sopenharmony_ci    public SaneStringBox(Jscanimage dlg, int opt, String tip)
964141cc406Sopenharmony_ci	{
965141cc406Sopenharmony_ci	super(dlg, opt, tip);
966141cc406Sopenharmony_ci	}
967141cc406Sopenharmony_ci
968141cc406Sopenharmony_ci	/*
969141cc406Sopenharmony_ci	 *	Update from Sane control's value.
970141cc406Sopenharmony_ci	 */
971141cc406Sopenharmony_ci    public void setFromControl()
972141cc406Sopenharmony_ci	{
973141cc406Sopenharmony_ci					// Let's get the whole list.
974141cc406Sopenharmony_ci	SaneOption opt = dialog.getSane().getOptionDescriptor(
975141cc406Sopenharmony_ci					dialog.getSaneHandle(), optNum);
976141cc406Sopenharmony_ci	if (opt == null)
977141cc406Sopenharmony_ci		return;
978141cc406Sopenharmony_ci	removeAllItems();		// Clear list.
979141cc406Sopenharmony_ci					// Go through list from option.
980141cc406Sopenharmony_ci	for (int i = 0; opt.stringListConstraint[i] != null; i++)
981141cc406Sopenharmony_ci		addItem(opt.stringListConstraint[i]);
982141cc406Sopenharmony_ci					// Get value.
983141cc406Sopenharmony_ci	byte buf[] = new byte[opt.size + 1];
984141cc406Sopenharmony_ci	if (dialog.getSane().getControlOption(
985141cc406Sopenharmony_ci			dialog.getSaneHandle(), optNum, buf, null)
986141cc406Sopenharmony_ci						== Sane.STATUS_GOOD)
987141cc406Sopenharmony_ci		select(new String(buf));
988141cc406Sopenharmony_ci	}
989141cc406Sopenharmony_ci
990141cc406Sopenharmony_ci	/*
991141cc406Sopenharmony_ci	 *	An item was selected.
992141cc406Sopenharmony_ci	 */
993141cc406Sopenharmony_ci    public void itemStateChanged(ItemEvent e)
994141cc406Sopenharmony_ci	{
995141cc406Sopenharmony_ci				// Get current selection.
996141cc406Sopenharmony_ci	String val = (String) getSelectedItem();
997141cc406Sopenharmony_ci	if (val != null)
998141cc406Sopenharmony_ci		dialog.setControlOption(optNum, val);
999141cc406Sopenharmony_ci	}
1000141cc406Sopenharmony_ci    }
1001141cc406Sopenharmony_ci
1002141cc406Sopenharmony_ci/*
1003141cc406Sopenharmony_ci *	A list of integers.
1004141cc406Sopenharmony_ci */
1005141cc406Sopenharmony_ciclass SaneIntBox extends SaneComboBox
1006141cc406Sopenharmony_ci    {
1007141cc406Sopenharmony_ci
1008141cc406Sopenharmony_ci	/*
1009141cc406Sopenharmony_ci	 *	Create it.
1010141cc406Sopenharmony_ci	 */
1011141cc406Sopenharmony_ci    public SaneIntBox(Jscanimage dlg, int opt, String tip)
1012141cc406Sopenharmony_ci	{
1013141cc406Sopenharmony_ci	super(dlg, opt, tip);
1014141cc406Sopenharmony_ci	}
1015141cc406Sopenharmony_ci
1016141cc406Sopenharmony_ci	/*
1017141cc406Sopenharmony_ci	 *	Update from Sane control's value.
1018141cc406Sopenharmony_ci	 */
1019141cc406Sopenharmony_ci    public void setFromControl()
1020141cc406Sopenharmony_ci	{
1021141cc406Sopenharmony_ci					// Let's get the whole list.
1022141cc406Sopenharmony_ci	SaneOption opt = dialog.getSane().getOptionDescriptor(
1023141cc406Sopenharmony_ci					dialog.getSaneHandle(), optNum);
1024141cc406Sopenharmony_ci	if (opt == null)
1025141cc406Sopenharmony_ci		return;
1026141cc406Sopenharmony_ci	removeAllItems();		// Clear list.
1027141cc406Sopenharmony_ci					// Go through list from option.
1028141cc406Sopenharmony_ci	int cnt = opt.wordListConstraint[0];
1029141cc406Sopenharmony_ci	for (int i = 0; i < cnt; i++)
1030141cc406Sopenharmony_ci		addItem(String.valueOf(opt.wordListConstraint[i + 1]));
1031141cc406Sopenharmony_ci					// Get value.
1032141cc406Sopenharmony_ci	int [] val = new int[1];	// Get current SANE control value.
1033141cc406Sopenharmony_ci	if (dialog.getSane().getControlOption(
1034141cc406Sopenharmony_ci			dialog.getSaneHandle(), optNum, val, null)
1035141cc406Sopenharmony_ci						== Sane.STATUS_GOOD)
1036141cc406Sopenharmony_ci		select(String.valueOf(val[0]));
1037141cc406Sopenharmony_ci	}
1038141cc406Sopenharmony_ci
1039141cc406Sopenharmony_ci	/*
1040141cc406Sopenharmony_ci	 *	An item was selected.
1041141cc406Sopenharmony_ci	 */
1042141cc406Sopenharmony_ci    public void itemStateChanged(ItemEvent e)
1043141cc406Sopenharmony_ci	{
1044141cc406Sopenharmony_ci				// Get current selection.
1045141cc406Sopenharmony_ci	String val = (String) getSelectedItem();
1046141cc406Sopenharmony_ci	if (val != null)
1047141cc406Sopenharmony_ci		try
1048141cc406Sopenharmony_ci			{
1049141cc406Sopenharmony_ci			Integer v = Integer.valueOf(val);
1050141cc406Sopenharmony_ci			dialog.setControlOption(optNum, v.intValue());
1051141cc406Sopenharmony_ci			}
1052141cc406Sopenharmony_ci		catch (NumberFormatException ex) {  }
1053141cc406Sopenharmony_ci	}
1054141cc406Sopenharmony_ci    }
1055141cc406Sopenharmony_ci
1056141cc406Sopenharmony_ci/*
1057141cc406Sopenharmony_ci *	A list of fixed-point floating point numbers.
1058141cc406Sopenharmony_ci */
1059141cc406Sopenharmony_ciclass SaneFixedBox extends SaneComboBox
1060141cc406Sopenharmony_ci    {
1061141cc406Sopenharmony_ci
1062141cc406Sopenharmony_ci	/*
1063141cc406Sopenharmony_ci	 *	Create it.
1064141cc406Sopenharmony_ci	 */
1065141cc406Sopenharmony_ci    public SaneFixedBox(Jscanimage dlg, int opt, String tip)
1066141cc406Sopenharmony_ci	{
1067141cc406Sopenharmony_ci	super(dlg, opt, tip);
1068141cc406Sopenharmony_ci	}
1069141cc406Sopenharmony_ci
1070141cc406Sopenharmony_ci	/*
1071141cc406Sopenharmony_ci	 *	Update from Sane control's value.
1072141cc406Sopenharmony_ci	 */
1073141cc406Sopenharmony_ci    public void setFromControl()
1074141cc406Sopenharmony_ci	{
1075141cc406Sopenharmony_ci					// Let's get the whole list.
1076141cc406Sopenharmony_ci	SaneOption opt = dialog.getSane().getOptionDescriptor(
1077141cc406Sopenharmony_ci					dialog.getSaneHandle(), optNum);
1078141cc406Sopenharmony_ci	if (opt == null)
1079141cc406Sopenharmony_ci		return;
1080141cc406Sopenharmony_ci	removeAllItems();		// Clear list.
1081141cc406Sopenharmony_ci					// Go through list from option.
1082141cc406Sopenharmony_ci	int cnt = opt.wordListConstraint[0];
1083141cc406Sopenharmony_ci	for (int i = 0; i < cnt; i++)
1084141cc406Sopenharmony_ci		addItem(String.valueOf(dialog.getSane().unfix(
1085141cc406Sopenharmony_ci					opt.wordListConstraint[i + 1])));
1086141cc406Sopenharmony_ci					// Get value.
1087141cc406Sopenharmony_ci	int [] val = new int[1];	// Get current SANE control value.
1088141cc406Sopenharmony_ci	if (dialog.getSane().getControlOption(
1089141cc406Sopenharmony_ci			dialog.getSaneHandle(), optNum, val, null)
1090141cc406Sopenharmony_ci						== Sane.STATUS_GOOD)
1091141cc406Sopenharmony_ci		select(String.valueOf(dialog.getSane().unfix(val[0])));
1092141cc406Sopenharmony_ci	}
1093141cc406Sopenharmony_ci
1094141cc406Sopenharmony_ci	/*
1095141cc406Sopenharmony_ci	 *	An item was selected.
1096141cc406Sopenharmony_ci	 */
1097141cc406Sopenharmony_ci    public void itemStateChanged(ItemEvent e)
1098141cc406Sopenharmony_ci	{
1099141cc406Sopenharmony_ci				// Get current selection.
1100141cc406Sopenharmony_ci	String val = (String) getSelectedItem();
1101141cc406Sopenharmony_ci	if (val != null)
1102141cc406Sopenharmony_ci		try
1103141cc406Sopenharmony_ci			{
1104141cc406Sopenharmony_ci			Double v = Double.valueOf(val);
1105141cc406Sopenharmony_ci			dialog.setControlOption(optNum,
1106141cc406Sopenharmony_ci					dialog.getSane().fix(v.doubleValue()));
1107141cc406Sopenharmony_ci			}
1108141cc406Sopenharmony_ci		catch (NumberFormatException ex) {  }
1109141cc406Sopenharmony_ci	}
1110141cc406Sopenharmony_ci    }
1111141cc406Sopenharmony_ci
1112141cc406Sopenharmony_ci/*
1113141cc406Sopenharmony_ci *	A text-entry field in our dialog.
1114141cc406Sopenharmony_ci */
1115141cc406Sopenharmony_ciclass SaneTextField extends JTextField implements SaneComponent
1116141cc406Sopenharmony_ci    {
1117141cc406Sopenharmony_ci    private Jscanimage dialog;		// That which created us.
1118141cc406Sopenharmony_ci    private int optNum;			// Option #.
1119141cc406Sopenharmony_ci
1120141cc406Sopenharmony_ci	/*
1121141cc406Sopenharmony_ci	 *	Create with given state.
1122141cc406Sopenharmony_ci	 */
1123141cc406Sopenharmony_ci    public SaneTextField(int width, Jscanimage dlg, int opt, String tip)
1124141cc406Sopenharmony_ci	{
1125141cc406Sopenharmony_ci	super(width);			// Set initial text, # chars.
1126141cc406Sopenharmony_ci	dialog = dlg;
1127141cc406Sopenharmony_ci	optNum = opt;
1128141cc406Sopenharmony_ci					// Set tool tip.
1129141cc406Sopenharmony_ci	if (tip != null && tip.length() != 0)
1130141cc406Sopenharmony_ci		super.setToolTipText(tip);
1131141cc406Sopenharmony_ci	}
1132141cc406Sopenharmony_ci
1133141cc406Sopenharmony_ci	/*
1134141cc406Sopenharmony_ci	 *	Update Sane device option with current setting when user types.
1135141cc406Sopenharmony_ci	 */
1136141cc406Sopenharmony_ci    public void processKeyEvent(KeyEvent e)
1137141cc406Sopenharmony_ci	{
1138141cc406Sopenharmony_ci	super.processKeyEvent(e);	// Handle it normally.
1139141cc406Sopenharmony_ci	if (e.getID() != KeyEvent.KEY_TYPED)
1140141cc406Sopenharmony_ci		return;			// Just do it after keystroke.
1141141cc406Sopenharmony_ci	String userText = getText();	// Get what's there, & save copy.
1142141cc406Sopenharmony_ci	String newText = new String(userText);
1143141cc406Sopenharmony_ci	dialog.setControlOption(optNum, newText);
1144141cc406Sopenharmony_ci	if (!newText.equals(userText))	// Backend may have changed it.
1145141cc406Sopenharmony_ci		setText(newText);
1146141cc406Sopenharmony_ci	}
1147141cc406Sopenharmony_ci
1148141cc406Sopenharmony_ci	/*
1149141cc406Sopenharmony_ci	 *	Update from Sane control's value.
1150141cc406Sopenharmony_ci	 */
1151141cc406Sopenharmony_ci    public void setFromControl()
1152141cc406Sopenharmony_ci	{
1153141cc406Sopenharmony_ci	byte buf[] = new byte[1024];
1154141cc406Sopenharmony_ci	if (dialog.getSane().getControlOption(
1155141cc406Sopenharmony_ci			dialog.getSaneHandle(), optNum, buf, null)
1156141cc406Sopenharmony_ci						== Sane.STATUS_GOOD)
1157141cc406Sopenharmony_ci		{
1158141cc406Sopenharmony_ci		String text = new String(buf);
1159141cc406Sopenharmony_ci		System.out.println("SaneTextField::setFromControl: " + text);
1160141cc406Sopenharmony_ci		setText(text);		// Set text in field.
1161141cc406Sopenharmony_ci		setScrollOffset(0);
1162141cc406Sopenharmony_ci		}
1163141cc406Sopenharmony_ci	}
1164141cc406Sopenharmony_ci    }
1165