// TLCockpit // Copyright 2017-2018 Norbert Preining // Licensed according to GPLv3+ // // Front end for tlmgr package TLCockpit import TLCockpit.ApplicationMain.{not_implemented_info, stage} import TeXLive.{OsTools, TLOption, TLPaperConf} import com.typesafe.scalalogging.LazyLogging import scalafx.Includes._ import scalafx.collections.ObservableBuffer import scalafx.event.ActionEvent import scalafx.geometry.{HPos, Insets} import scalafx.scene.Node import scalafx.scene.control._ import scalafx.scene.layout._ class OptionsDialog(opts: List[TLOption]) extends LazyLogging { case class Result(selected: Map[String,String]) val dialog = new Dialog[Result]() { initOwner(stage) title = s"General options" headerText = s"General options" resizable = true } dialog.dialogPane().buttonTypes = Seq(ButtonType.OK, ButtonType.Cancel) val grid = new GridPane() { hgap = 10 vgap = 10 padding = Insets(20) } var crow = 0 val optsMap = opts.map(p => (p.name, p)).toMap val orderOpts = Seq("location", "create_formats", "install_srcfiles", "install_docfiles", "backupdir", "autobackup") ++ { if (OsTools.isWindows) Seq("desktop_integration", "file_assocs", "w32_multi_user") else Seq("sys_bin", "sys_info", "sys_man") } val changedValues = scala.collection.mutable.Map[String,String]() val nodes = orderOpts.map( nm => { val tlopt = optsMap(nm) // this is dangerous in case we change the names in TLPDB! grid.add(new Label(tlopt.description), 0, crow) val value = tlopt.value.getOrElse(tlopt.default) val nd: Node = if (tlopt.format.startsWith("b")) new CheckBox() { selected = if (value == "1") true else false selected.onChange( (_,_,newVal) => { changedValues(nm) = if (newVal) "1" else "0" }) } else if (tlopt.format.startsWith("n")) { // parse additional specs if (tlopt.format.startsWith("n:")) { var nrSpec = tlopt.format.substring(2) var splits: Array[String] = nrSpec.split("""\.\.""") val start: Int = splits(0).toInt val end: Option[Int] = if (splits.length > 1) Some(splits(1).toInt) else None new Spinner[Int](start, end.getOrElse(50), value.toInt) { value.onChange( (_,_,newVal) => { changedValues(nm) = newVal.toString }) if (nm == "autobackup") tooltip = new Tooltip("-1 ... arbitrary many backups\n0 ... no backups\notherwise number of backups") } } else { new Spinner[Int](-50, 50, value.toInt) { value.onChange( (_,_,newVal) => { changedValues(nm) = newVal.toString }) } } } else if (tlopt.format == "p") new TextField() { text = value text.onChange( (_,_,newVal) => { changedValues(nm) = newVal }) } else if (tlopt.format == "u") { val locs = value.split(' ') val locsmap = if (locs.length == 1) Map[String,String](("main", value)) else locs.map(p => { val uu = p.split('#') (uu(1), uu(0)) }).toMap val buttonStr = if (locs.length == 1) value else "Multiple repository" new Button(buttonStr) { onAction = (event: ActionEvent) => { val dg = new LocationDialog(locsmap) dg.showAndWait() match { case Some(newlocs) => if (newlocs.toList.length == 1) { changedValues(nm) = newlocs("main") this.text = newlocs("main") } else { changedValues(nm) = newlocs.map(p => p._2 + "#" + p._1).mkString(" ") this.text = "Multiple repository" } case None => } } } } else new Label("Unknown setting") grid.add(nd, 1, crow) crow += 1 (tlopt.name, nd) }).toMap grid.columnConstraints = Seq(new ColumnConstraints(300, 300, 500), new ColumnConstraints(200, 200, 5000, Priority.Always, HPos.LEFT, true)) dialog.dialogPane().content = grid dialog.width = 500 // This seems to be necessary for some old versions of ScalaFX or JavaFX or Java?? // dialog.height = 1500 dialog.resultConverter = dialogButton => if (dialogButton == ButtonType.OK) { // TODO we could check that the values actually have changed Result(changedValues.toMap) } else null def showAndWait(): Option[Map[String,String]] = { val result = dialog.showAndWait() result match { case Some(Result(foo)) => logger.debug("Got result " + foo) Some(foo) case Some(foo) => logger.debug("Got strange result " + foo) None case None => None } } }