All Downloads are FREE. Search and download functionalities are using the official Maven repository.

application.ui.prefs.EmbossSettingsController Maven / Gradle / Ivy

package application.ui.prefs;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import javax.print.PrintService;
import javax.print.PrintServiceLookup;

import org.daisy.braille.utils.api.embosser.Embosser;
import org.daisy.braille.utils.api.embosser.EmbosserFactoryProperties;
import org.daisy.braille.utils.api.factory.FactoryProperties;
import org.daisy.braille.utils.pef.PEFGenerator;

import application.common.Configuration;
import application.common.FactoryPropertiesAdapter;
import application.common.NiceName;
import application.common.Settings;
import application.common.Settings.Keys;
import application.l10n.Messages;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

/**
 * Provides a controller for the embosser settings view.
 * @author Joel Håkansson
 *
 */
public class EmbossSettingsController extends BorderPane {
	private static final Logger logger = Logger.getLogger(EmbossSettingsController.class.getCanonicalName());
	@FXML private Label deviceLabel;
	@FXML private Label embosserLabel;
	@FXML private Label embosserDetailsLabel;
	@FXML private Label printModeLabel;
	@FXML private Label tableLabel;
	@FXML private Label tableDetailsLabel;
	@FXML private Label paperLabel;
	@FXML private Label paperDetailsLabel;
	@FXML private Label orentationLabel;
	@FXML private Label zFoldingLabel;
	@FXML private Label alignLabel;
	@FXML private Button testButton;
	@FXML private ComboBox deviceSelect;
	@FXML private ComboBox embosserSelect;
	@FXML private ComboBox printModeSelect;
	@FXML private ComboBox tableSelect;
	@FXML private ComboBox paperSelect;
	@FXML private ComboBox orentationSelect;
	@FXML private ComboBox zFoldingSelect;
	@FXML private ComboBox alignSelect;
	@FXML private VBox parent;
	private PreferenceItem deviceItem;
	private PreferenceItem makerItem;
	private PreferenceItem embosserItem;
	private PreferenceItem printModeItem;
	private PreferenceItem tableItem;
	private PreferenceItem paperItem;
	private PreferenceItem orientationItem;
	private PreferenceItem zFoldingItem;
	private PreferenceItem alignItem;
	private ExecutorService exeService;
	private final OptionNiceNames nn = new OptionNiceNames();
	private DeviceScanner deviceScanner;
	private File generatedFile;
	private String currentMake = null;

	/**
	 * Creates a new embosser settings controller.
	 */
	public EmbossSettingsController() {
		try {
			FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("EmbossSettings.fxml"), Messages.getBundle());
			fxmlLoader.setRoot(this);
			fxmlLoader.setController(this);
			fxmlLoader.load();
		} catch (IOException e) {
			logger.log(Level.WARNING, "Failed to load view", e);
		}
	}

	@FXML void initialize() {
		exeService = Executors.newSingleThreadExecutor();
		deviceScanner = new DeviceScanner();
		deviceScanner.setOnSucceeded(ev -> {
			updateComponents();
		});
		exeService.submit(deviceScanner);
		exeService.shutdown();
	}
	
	void updateComponents() {
		Task readConfig = new Task() {
			@Override
			protected Configuration call() throws Exception {
				return Configuration.getConfiguration();
			}
		};
		readConfig.setOnSucceeded(ev -> {
			Platform.runLater(()-> {
				updateComponentsInner(readConfig.getValue());
			});
		});
		Thread th = new Thread(readConfig);
		th.setDaemon(true);
		th.start();
	}
	
	private void setMake(String value) {
		this.currentMake = value;
	}

	private void updateComponentsInner(Configuration conf) {
		Config config = new Config();
		config.update();
		if (currentMake==null) {
			currentMake = Optional.ofNullable(conf.getEmbosserCatalog().get(config.embosser))
				.map(v->v.getMake())
				.orElse(Optional.ofNullable(makerItem).map(v->v.getKey()).orElse(""));
		}
		parent.getChildren().clear();
		
		deviceItem = new PreferenceItem(Messages.LABEL_DEVICE.localize(), deviceScanner.getValue(), config.device, (o, t0, t1) -> {
			Settings.getSettings().put(Keys.device, t1.getKey());
			updateComponents();
		});
		parent.getChildren().add(deviceItem);

		if (!"".equals(config.device)) {
			makerItem = new PreferenceItem(Messages.LABEL_MAKE.localize(), conf.getEmbossers().stream()
					.map(v->new NiceName(v.getMake(), v.getMake()))
					.sorted((o1, o2)->o1.getDisplayName().compareTo(o2.getDisplayName()))
					.distinct()
					.collect(Collectors.toList()), currentMake, (o, t0, t1) -> {
						setMake(t1.getKey());
						Settings.getSettings().put(Keys.embosser, "");
						updateComponents();
					});
			parent.getChildren().add(makerItem);
			if (!"".equals(currentMake)) {
				conf.getEmbosserCatalog().list(v->true);
				embosserItem = new PreferenceItem(Messages.LABEL_EMBOSSER.localize(), wrapEmbossers(conf.getEmbossers().stream()
						.filter(v->v.getMake().equals(currentMake)).collect(Collectors.toList())), config.embosser, (o, t0, t1) -> {
					Settings.getSettings().put(Keys.embosser, t1.getKey());
					updateComponents();
				});
				parent.getChildren().add(embosserItem);
				if (!"".equals(config.embosser)) {
					Embosser em = conf.getConfiguredEmbosser();
					//TODO: Don't use fixed line spacing value 
					parent.getChildren().add(new DriverDetails(em.supports8dot(), em.supportsVolumes(), false));
					if (conf.supportsBothPrintModes()) {
						printModeItem = new PreferenceItem(Messages.LABEL_PRINT_MODE.localize(), nn.getPrintModeNN(), config.printMode, (o, t0, t1) -> {
							Settings.getSettings().put(Keys.printMode, t1.getKey());
							updateComponents();
						});
						parent.getChildren().add(printModeItem);
					} else {
						printModeItem = null;
					}
			
					if (conf.getSupportedTables().size()>1) {
						tableItem = new PreferenceItem(Messages.LABEL_TABLE.localize(), wrap(conf.getSupportedTables()), config.table, (o, t0, t1) -> {
							Settings.getSettings().put(Keys.table, t1.getKey());
							updateComponents();
						});
						parent.getChildren().add(tableItem);
					} else {
						tableItem = null;
					}
					
					paperItem = new PreferenceItem(Messages.LABEL_PAPER.localize(), wrap(conf.getSupportedPapers()), config.paper, (o, t0, t1) -> {
						Settings.getSettings().put(Keys.paper, t1.getKey());
						updateComponents();
					});
					parent.getChildren().add(paperItem);
		
					if (conf.isRollPaper()) {
						parent.getChildren().add(new PreferenceItem(Messages.LABEL_CUT_LENGTH.localize(), nn.getLengthNN(), config.lengthValue, config.lengthUnit, (f1, f2)->{
							Settings.getSettings().put(Keys.cutLengthValue, f1);
							Settings.getSettings().put(Keys.cutLengthUnit, f2);
							updateComponents();
						}));
					}
					
					if (conf.supportsOrientation()) {
						orientationItem = new PreferenceItem(Messages.LABEL_ORIENTATION.localize(), nn.getOrientationNN(), config.orientation, (o, t0, t1) -> {
									Settings.getSettings().put(Keys.orientation, t1.getKey());
									updateComponents();
								});
						parent.getChildren().add(orientationItem);
					} else {
						orientationItem = null;
					}
	
	    			if (conf.settingOK()) {
	    				// this is a way to add a second description which isn't dependent on any of the above
	    				parent.getChildren().add(
	    						new PreferenceItem(null, Messages.LABEL_PAPER_DIMENSIONS.localize( 
	    								conf.getShape()==null?"":nn.getShapeNN().get(conf.getShape().name()),
	    										conf.getPaperWidth(), conf.getPaperHeight(), conf.getMaxWidth(), conf.getMaxHeight()), null, null, null)
	    						
	    				);
	    			}
					
					if (conf.supportsZFolding()) {
						zFoldingItem = new PreferenceItem(Messages.LABEL_Z_FOLDING.localize(), nn.getZfoldingNN(), config.zFolding, (o, t0, t1) -> {
							Settings.getSettings().put(Keys.zFolding, t1.getKey());
							updateComponents();
						});
						parent.getChildren().add(zFoldingItem);
					} else {
						zFoldingItem = null;
					}
					if (conf.supportsAligning()) {
						alignItem = new PreferenceItem(Messages.LABEL_ALIGNMENT.localize(), nn.getAlignNN(), config.align, (o, t0, t1) -> {
							Settings.getSettings().put(Keys.align, t1.getKey());
							updateComponents();
						});
						parent.getChildren().add(alignItem);
					} else {
						alignItem = null;
					}
				}
			}
		}
		
		if (conf.settingOK()) {
			testButton.setDisable(false);
			testButton.setText(Messages.LABEL_CREATE_TEST_DOCUMENT.localize());
			testButton.setOnAction(ev->{
				if (conf.settingOK() && generatedFile==null) {
					Map keys = new HashMap<>();
			        keys.put(PEFGenerator.KEY_COLS, String.valueOf(conf.getMaxWidth()));
			        keys.put(PEFGenerator.KEY_ROWS, String.valueOf(conf.getMaxHeight()));
			        keys.put(PEFGenerator.KEY_DUPLEX, String.valueOf(true));
			        keys.put(PEFGenerator.KEY_EIGHT_DOT, String.valueOf(false));
			        PEFGenerator generator = new PEFGenerator(keys);
			        try {
						File file = File.createTempFile("generated-", ".pef");
						file.deleteOnExit();
			            generator.generateTestPages(file);
			            generatedFile = file;
			            ((Stage)testButton.getScene().getWindow()).close();
			        } catch (Exception e) {
			        	logger.log(Level.WARNING, "Failed to generate document.", e);
			        }
				}
			});
		} else {
			testButton.setDisable(true);
			testButton.setText(Messages.LABEL_SETUP_INVALID.localize());
		}
	}

	File generatedTestFile() {
		return generatedFile;
	}

	private static List wrap(Collection props) {
		return props.stream().sorted((o1, o2)->o1.getDisplayName().compareTo(o2.getDisplayName())).map(p->new FactoryPropertiesAdapter(p)).collect(Collectors.toList());
	}
	
	private static List wrapEmbossers(Collection props) {
		return props.stream().sorted((o1, o2)->o1.getModel().compareTo(o2.getModel())).map(p->new NiceName(p.getIdentifier(), p.getModel(), p.getDescription())).collect(Collectors.toList());
	}

	private static class DeviceScanner extends Task> {
		@Override
		protected List call() throws Exception {
			PrintService[] printers = PrintServiceLookup.lookupPrintServices(null, null);
			List ret = new ArrayList<>();
			for (PrintService p : printers) {
				ret.add(new PrintServiceAdapter(p));
			}
			return ret;
		}
	}
	
	private class Config {
		String device;
		String embosser;
		String printMode;
		String paper;
		String lengthValue;
		String lengthUnit;
		String align;
		String table;
		String orientation;
		String zFolding;
		private void update() {
			Settings settings = Settings.getSettings();
	    	device = settings.getString(Keys.device, "");
	    	embosser = settings.getString(Keys.embosser, "");
	    	printMode = settings.getString(Keys.printMode, "");
	    	paper = settings.getString(Keys.paper, "");
	    	lengthValue = settings.getString(Keys.cutLengthValue, "");
	    	lengthUnit = settings.getString(Keys.cutLengthUnit, "");
	    	align = settings.getString(Keys.align, "");
	    	table = settings.getString(Keys.table, "");
	    	orientation = settings.getString(Keys.orientation, "DEFAULT");
	    	zFolding = settings.getString(Keys.zFolding, "OFF");
		}
	}
	
	private static class PrintServiceAdapter extends NiceName {
		private PrintServiceAdapter(PrintService p) {
			super(p.getName(), p.getName());
		}
	}	

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy