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