diff --git a/app/src/main/scala/app/logorrr/conf/mut/MutLogFileSettings.scala b/app/src/main/scala/app/logorrr/conf/mut/MutLogFileSettings.scala index 6bc18fde..2f0b8d6b 100644 --- a/app/src/main/scala/app/logorrr/conf/mut/MutLogFileSettings.scala +++ b/app/src/main/scala/app/logorrr/conf/mut/MutLogFileSettings.scala @@ -28,24 +28,32 @@ object MutLogFileSettings { } class MutLogFileSettings extends Petrify[LogFileSettings] { - def getFontSize(): Int = fontSizeProperty.get() - def getFilters() = filtersProperty.asScala.toSeq private val pathAsStringProperty = new SimpleStringProperty() private val firstOpenedProperty = new SimpleLongProperty() val selectedIndexProperty = new SimpleIntegerProperty() val dividerPositionProperty = new SimpleDoubleProperty() val fontSizeProperty = new SimpleIntegerProperty() + val autoScrollProperty = new SimpleBooleanProperty() val filtersProperty = new SimpleListProperty[Filter](FXCollections.observableArrayList()) val someLogEntrySettings = new SimpleObjectProperty[Option[LogEntryInstantFormat]]() val blockWidthSettingsProperty = new SimpleIntegerProperty() val fontStyle: ObservableValue[_ <: String] = new StringBinding { bind(fontSizeProperty) + override def computeValue(): String = LogoRRRFonts.jetBrainsMono(fontSizeProperty.get()) } + def setAutoScroll(autoScroll: Boolean): Unit = autoScrollProperty.set(autoScroll) + + def isAutoScroll(): Boolean = autoScrollProperty.get() + + def getFontSize(): Int = fontSizeProperty.get() + + def getFilters() = filtersProperty.asScala.toSeq + def setBlockSettings(bs: BlockSettings): Unit = blockWidthSettingsProperty.set(bs.width) def setPathAsString(path: String): Unit = pathAsStringProperty.set(path) @@ -65,6 +73,7 @@ class MutLogFileSettings extends Petrify[LogFileSettings] { , fontSizeProperty.get() , filtersProperty.get().asScala.toSeq , BlockSettings(blockWidthSettingsProperty.get()) - , someLogEntrySettings.get()) + , someLogEntrySettings.get() + , autoScrollProperty.get()) } diff --git a/app/src/main/scala/app/logorrr/model/LogFileSettings.scala b/app/src/main/scala/app/logorrr/model/LogFileSettings.scala index 8406cf8c..752fe505 100644 --- a/app/src/main/scala/app/logorrr/model/LogFileSettings.scala +++ b/app/src/main/scala/app/logorrr/model/LogFileSettings.scala @@ -20,6 +20,7 @@ object LogFileSettings { val DefaultDividerPosition = 0.5 val DefaultBlockSettings = BlockSettings(10) val DefaultLogFormat: Option[LogEntryInstantFormat] = None + val DefaultAutoScroll = false val finest: Filter = new Filter("FINEST", Color.GREY.toString) val info: Filter = new Filter("INFO", Color.GREEN.toString) @@ -37,7 +38,8 @@ object LogFileSettings { , DefaultFontSize , DefaultFilter , DefaultBlockSettings - , DefaultLogFormat) + , DefaultLogFormat + , DefaultAutoScroll) } @@ -58,7 +60,8 @@ case class LogFileSettings(pathAsString: String , fontSize: Int , filters: Seq[Filter] , blockSettings: BlockSettings - , someLogEntrySetting: Option[LogEntryInstantFormat]) extends CanLog { + , someLogEntrySetting: Option[LogEntryInstantFormat] + , autoScroll: Boolean) extends CanLog { val path: Path = Paths.get(pathAsString) diff --git a/app/src/main/scala/app/logorrr/model/LogIdAware.scala b/app/src/main/scala/app/logorrr/model/LogIdAware.scala new file mode 100644 index 00000000..ecc45771 --- /dev/null +++ b/app/src/main/scala/app/logorrr/model/LogIdAware.scala @@ -0,0 +1,6 @@ +package app.logorrr.model + +trait LogIdAware { + + def pathAsString: String +} diff --git a/app/src/main/scala/app/logorrr/views/LogFileTab.scala b/app/src/main/scala/app/logorrr/views/LogFileTab.scala index a702ea98..25bb77bc 100644 --- a/app/src/main/scala/app/logorrr/views/LogFileTab.scala +++ b/app/src/main/scala/app/logorrr/views/LogFileTab.scala @@ -3,12 +3,14 @@ package app.logorrr.views import app.logorrr.conf.{BlockSettings, LogoRRRGlobals} import app.logorrr.model.{LogEntry, LogFileSettings} import app.logorrr.util._ +import app.logorrr.views.autoscroll.LogTailer import app.logorrr.views.ops.{OpsRegion, SettingsOps} import app.logorrr.views.search.{Filter, FiltersToolBar, Fltr, OpsToolBar} import app.logorrr.views.text.LogTextView import app.logorrr.views.visual.LogVisualView import javafx.beans.binding.{Bindings, StringExpression} -import javafx.beans.property.{SimpleListProperty, SimpleObjectProperty} +import javafx.beans.property.SimpleListProperty +import javafx.beans.{InvalidationListener, Observable} import javafx.collections.transformation.FilteredList import javafx.collections.{ListChangeListener, ObservableList} import javafx.scene.control._ @@ -67,7 +69,6 @@ class LogFileTab(val pathAsString: String extends Tab with CanLog { - selectedProperty().addListener(JfxUtils.onNew[java.lang.Boolean](b => { if (b) { setStyle(LogFileTab.BackgroundSelectedStyle) @@ -76,7 +77,8 @@ class LogFileTab(val pathAsString: String } })) - val logoRRRTailer = LogoRRRTailer(pathAsString, logEntries) + // lazy since only if autoscroll is set start tailer + lazy val logTailer = LogTailer(pathAsString, logEntries) def repaint(): Unit = logVisualView.repaint() @@ -136,8 +138,35 @@ class LogFileTab(val pathAsString: String private val logTextView = new LogTextView(pathAsString, filteredList, timings) + // val selectedEntryProperty = new SimpleObjectProperty[LogEntry]() + + lazy val scrollToEndEventListener: InvalidationListener = (observable: Observable) => logTextView.scrollToEnd() + + private def startTailer(): Unit = { + filteredList.addListener(scrollToEndEventListener) + logTailer.start() + } + + private def stopTailer(): Unit = { + filteredList.removeListener(scrollToEndEventListener) + logTailer.stop() + } + + def initAutoScroll(): Unit = { + LogoRRRGlobals.getLogFileSettings(pathAsString).autoScrollProperty.addListener(JfxUtils.onNew[java.lang.Boolean] { + b => + if (b) { + startTailer() + } else { + stopTailer() + } + }) + + if (LogoRRRGlobals.getLogFileSettings(pathAsString).isAutoScroll()) { + startTailer() + } - val selectedEntryProperty = new SimpleObjectProperty[LogEntry]() + } /** if a change event for filtersList Property occurs, save it to disc */ @@ -188,11 +217,11 @@ class LogFileTab(val pathAsString: String /** don't monitor file anymore if tab is closed, free invalidation listeners */ setOnClosed(_ => closeTab()) textProperty.bind(computeTabTitle) - val tooltip = new Tooltip("jodel") + val tooltip = new Tooltip() tooltip.textProperty().bind(Bindings.concat(Bindings.size(logEntries).asString, " lines")) setTooltip(tooltip) - selectedEntryProperty.bind(logVisualView.selectedEntryProperty) + // selectedEntryProperty.bind(logVisualView.selectedEntryProperty) // if user changes selected item in listview, change footer as well //logTextView.listView.getSelectionModel.selectedItemProperty.addListener(logEntryChangeListener) @@ -208,7 +237,7 @@ class LogFileTab(val pathAsString: String t1: Number => LogoRRRGlobals.setDividerPosition(pathAsString, t1.doubleValue()) }) - logoRRRTailer.start() + initAutoScroll() setDivider(LogoRRRGlobals.getLogFileSettings(pathAsString).dividerPositionProperty.get()) initFiltersPropertyListChangeListener() @@ -230,8 +259,10 @@ class LogFileTab(val pathAsString: String } def shutdown(): Unit = { + if (LogoRRRGlobals.getLogFileSettings(pathAsString).isAutoScroll()) { + stopTailer() + } LogoRRRGlobals.removeLogFile(pathAsString) - logoRRRTailer.stop() } diff --git a/app/src/main/scala/app/logorrr/views/LogoRRRTailer.scala b/app/src/main/scala/app/logorrr/views/LogoRRRTailer.scala deleted file mode 100644 index e2d387bd..00000000 --- a/app/src/main/scala/app/logorrr/views/LogoRRRTailer.scala +++ /dev/null @@ -1,18 +0,0 @@ -package app.logorrr.views - -import app.logorrr.model.LogEntry -import app.logorrr.util.LogEntryListener -import javafx.collections.ObservableList -import org.apache.commons.io.input.Tailer - -import java.nio.file.Paths - -case class LogoRRRTailer(pathAsString: String - , logEntries: ObservableList[LogEntry]) - extends Tailer(Paths.get(pathAsString).toFile, new LogEntryListener(pathAsString, logEntries), 1000, true) { - - /** start observing log file for changes */ - def start(): Unit = new Thread(this).start() - - -} diff --git a/app/src/main/scala/app/logorrr/views/autoscroll/AutoScrollCheckBox.scala b/app/src/main/scala/app/logorrr/views/autoscroll/AutoScrollCheckBox.scala new file mode 100644 index 00000000..2d80b981 --- /dev/null +++ b/app/src/main/scala/app/logorrr/views/autoscroll/AutoScrollCheckBox.scala @@ -0,0 +1,13 @@ +package app.logorrr.views.autoscroll + +import app.logorrr.conf.LogoRRRGlobals +import app.logorrr.model.LogIdAware +import javafx.scene.control.{CheckBox, Tooltip} + + +class AutoScrollCheckBox(val pathAsString: String) extends CheckBox with LogIdAware { + setTooltip(new Tooltip("autoscroll")) + + selectedProperty().bindBidirectional(LogoRRRGlobals.getLogFileSettings(pathAsString).autoScrollProperty) + +} diff --git a/app/src/main/scala/app/logorrr/views/autoscroll/AutoScroller.scala b/app/src/main/scala/app/logorrr/views/autoscroll/AutoScroller.scala new file mode 100644 index 00000000..5670ddbf --- /dev/null +++ b/app/src/main/scala/app/logorrr/views/autoscroll/AutoScroller.scala @@ -0,0 +1,13 @@ +package app.logorrr.views.autoscroll + +import app.logorrr.conf.LogoRRRGlobals +import app.logorrr.model.LogIdAware + +trait AutoScroller { + autoScroller: LogIdAware => + + def setAutoScroll(autoScroll: Boolean): Unit = LogoRRRGlobals.getLogFileSettings(pathAsString).setAutoScroll(autoScroll) + + def isAutoScroll(): Boolean = LogoRRRGlobals.getLogFileSettings(pathAsString).isAutoScroll() + +} diff --git a/app/src/main/scala/app/logorrr/util/LogEntryListener.scala b/app/src/main/scala/app/logorrr/views/autoscroll/LogEntryListener.scala similarity index 93% rename from app/src/main/scala/app/logorrr/util/LogEntryListener.scala rename to app/src/main/scala/app/logorrr/views/autoscroll/LogEntryListener.scala index 16504c17..dc311ec4 100644 --- a/app/src/main/scala/app/logorrr/util/LogEntryListener.scala +++ b/app/src/main/scala/app/logorrr/views/autoscroll/LogEntryListener.scala @@ -1,7 +1,8 @@ -package app.logorrr.util +package app.logorrr.views.autoscroll import app.logorrr.conf.LogoRRRGlobals import app.logorrr.model.LogEntry +import app.logorrr.util.{CanLog, JfxUtils} import app.logorrr.views.search.Filter import javafx.collections.ObservableList import org.apache.commons.io.input.{Tailer, TailerListener} diff --git a/app/src/main/scala/app/logorrr/views/autoscroll/LogTailer.scala b/app/src/main/scala/app/logorrr/views/autoscroll/LogTailer.scala new file mode 100644 index 00000000..a84c36d1 --- /dev/null +++ b/app/src/main/scala/app/logorrr/views/autoscroll/LogTailer.scala @@ -0,0 +1,43 @@ +package app.logorrr.views.autoscroll + +import app.logorrr.model.LogEntry +import app.logorrr.util.CanLog +import javafx.collections.ObservableList +import org.apache.commons.io.input.Tailer + +import java.nio.file.Paths + +/** + * If active, this class adds entries to the given logEntries observable list. + * @param pathAsString path to log file + * @param logEntries list which will be modified if log file changes + */ +case class LogTailer(pathAsString: String + , logEntries: ObservableList[LogEntry]) + extends CanLog { + + var currentTailer: Option[Tailer] = None + + private def mkTailer(): Tailer = new Tailer(Paths.get(pathAsString).toFile, new LogEntryListener(pathAsString, logEntries), 40, true) + + /** start observing log file for changes */ + def start(): Unit = synchronized { + currentTailer match { + case Some(value) => logWarn("Not starting new LogTailer, already one in progress ...") + case None => + currentTailer = Option(mkTailer()) + timeR(currentTailer.foreach(t => new Thread(t).start()), s"Started LogTailer for file $pathAsString") + } + } + + def stop(): Unit = timeR({ + currentTailer match { + case Some(tailer) => + tailer.stop() + currentTailer = None + case None => + logWarn("No LogTailer was active, ignoring ...") + } + }, s"Stopped LogTailer for file $pathAsString") + +} diff --git a/app/src/main/scala/app/logorrr/views/search/FiltersToolBar.scala b/app/src/main/scala/app/logorrr/views/search/FiltersToolBar.scala index 8543f8cf..a85bbc09 100644 --- a/app/src/main/scala/app/logorrr/views/search/FiltersToolBar.scala +++ b/app/src/main/scala/app/logorrr/views/search/FiltersToolBar.scala @@ -5,9 +5,7 @@ import app.logorrr.util.JfxUtils import javafx.beans.property.SimpleListProperty import javafx.collections.ListChangeListener import javafx.collections.transformation.FilteredList -import javafx.scene.control.{Button, ToolBar} -import org.kordamp.ikonli.fontawesome5.FontAwesomeSolid -import org.kordamp.ikonli.javafx.FontIcon +import javafx.scene.control.ToolBar import scala.jdk.CollectionConverters._ @@ -21,11 +19,6 @@ object FiltersToolBar { |-fx-border-color: RED; |""".stripMargin - class RemoveButton(filter: Filter, removeFilter: Filter => Unit) extends Button { - setGraphic(new FontIcon(FontAwesomeSolid.TIMES_CIRCLE)) - setOnAction(_ => removeFilter(filter)) - } - } diff --git a/app/src/main/scala/app/logorrr/views/search/OpsToolBar.scala b/app/src/main/scala/app/logorrr/views/search/OpsToolBar.scala index 9c4b107d..7f80da89 100644 --- a/app/src/main/scala/app/logorrr/views/search/OpsToolBar.scala +++ b/app/src/main/scala/app/logorrr/views/search/OpsToolBar.scala @@ -1,5 +1,6 @@ package app.logorrr.views.search +import app.logorrr.views.autoscroll.AutoScrollCheckBox import app.logorrr.views.block.HasBlockSizeProperty import app.logorrr.views.ops.{DecreaseBlockSizeButton, IncreaseBlockSizeButton} import app.logorrr.views.text.{DecreaseTextSizeButton, IncreaseTextSizeButton} @@ -38,7 +39,7 @@ class OpsToolBar(pathAsString: String, addFilterFn: Filter => Unit) //setStyle(SearchToolBar.BackgroundSelectedStyle) setStyle("""-fx-padding: 0px 0px 0px 4px;""") - val width = 490 + val width = 510 setMaxWidth(width) setMinWidth(width) @@ -55,6 +56,8 @@ class OpsToolBar(pathAsString: String, addFilterFn: Filter => Unit) private val searchButton = new SearchButton(searchTextField, regexToggleButton, colorPicker, addFilterFn) + val autoScrollCheckBox = new AutoScrollCheckBox(pathAsString) + def execSearchOnHitEnter(event: KeyEvent): Unit = { if (event.getCode == KeyCode.ENTER) { searchButton.fire() @@ -75,6 +78,10 @@ class OpsToolBar(pathAsString: String, addFilterFn: Filter => Unit) Seq(decreaseBlockSizeButton, increaseBlockSizeButton, decreaseTextSizeButton, increaseTextSizeButton) } - getItems.addAll(searchItems ++ sizeItems: _*) + val otherItems: Seq[Control] = { + Seq(autoScrollCheckBox) + } + + getItems.addAll(searchItems ++ sizeItems ++ otherItems: _*) } diff --git a/app/src/main/scala/app/logorrr/views/text/HasFontSizeProperty.scala b/app/src/main/scala/app/logorrr/views/text/HasFontSizeProperty.scala index 08e4da4b..0c2c347e 100644 --- a/app/src/main/scala/app/logorrr/views/text/HasFontSizeProperty.scala +++ b/app/src/main/scala/app/logorrr/views/text/HasFontSizeProperty.scala @@ -1,10 +1,10 @@ package app.logorrr.views.text import app.logorrr.conf.LogoRRRGlobals +import app.logorrr.model.LogIdAware -trait HasFontSizeProperty { - def pathAsString: String +trait HasFontSizeProperty extends LogIdAware { def setFontSize(fontSize: Int): Unit = LogoRRRGlobals.getLogFileSettings(pathAsString).setFontSize(fontSize) diff --git a/app/src/main/scala/app/logorrr/views/text/LogTextView.scala b/app/src/main/scala/app/logorrr/views/text/LogTextView.scala index abdcea20..4dd8aed8 100644 --- a/app/src/main/scala/app/logorrr/views/text/LogTextView.scala +++ b/app/src/main/scala/app/logorrr/views/text/LogTextView.scala @@ -84,6 +84,7 @@ class LogTextView(pathAsString: String private val fixedCellSize = 26 + /** 'pragmatic way' to determine width of max elems in this view */ val maxLength = filteredList.size().toString.length @@ -114,6 +115,12 @@ class LogTextView(pathAsString: String setCenter(listView) + + /** scroll to end of listview */ + def scrollToEnd(): Unit = { + listView.scrollTo(listView.getItems.size) + } + class LogEntryListCell extends ListCell[LogEntry] { styleProperty().bind(LogoRRRGlobals.getLogFileSettings(pathAsString).fontStyle) //setStyle(LogoRRRFonts.jetBrainsMono(LogTextView.fontSize)) diff --git a/app/src/main/scala/app/logorrr/views/visual/LogVisualView.scala b/app/src/main/scala/app/logorrr/views/visual/LogVisualView.scala index f423f98f..f748c650 100644 --- a/app/src/main/scala/app/logorrr/views/visual/LogVisualView.scala +++ b/app/src/main/scala/app/logorrr/views/visual/LogVisualView.scala @@ -12,10 +12,7 @@ import javafx.scene.layout.BorderPane class LogVisualView(pathAsString: String, entries: ObservableList[LogEntry], canvasWidth: Int) extends BorderPane with CanLog { - def repaint() = blockViewPane.repaint() - - - // require(canvasWidth > 0, "canvasWidth must be greater than 0") + def repaint(): Unit = blockViewPane.repaint() val selectedEntryProperty = new SimpleObjectProperty[LogEntry]() diff --git a/app/src/test/scala/app/logorrr/LogProducer.scala b/app/src/test/scala/app/logorrr/LogProducer.scala new file mode 100644 index 00000000..87fc6353 --- /dev/null +++ b/app/src/test/scala/app/logorrr/LogProducer.scala @@ -0,0 +1,47 @@ +package app.logorrr + +import java.nio.file.{Files, Path, Paths, StandardOpenOption} +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter +import java.util +import java.util.Scanner + +case class SimpleWriter(path: Path) extends Runnable { + var running = true + val dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss A"); + + def stop(): Unit = running = false + + override def run(): Unit = { + var linenumber = 1 + while (running) { + Thread.sleep(100) + val now = LocalDateTime.now(); + val str = s"${dtf.format(now)} $linenumber testlog " + linenumber += 1 + Files.write(path, util.Arrays.asList(str), StandardOpenOption.CREATE, StandardOpenOption.APPEND) + } + } + +} + +object LogProducer { + + def main(args: Array[String]): Unit = { + if (args.nonEmpty) { + + val path = Paths.get(args(0)) + Files.deleteIfExists(path) + val writer = SimpleWriter(path) + new Thread(writer).start() + + val keyboard = new Scanner(System.in) + System.out.println(s"producing log entries in ${path.toAbsolutePath.toString}, press enter to stop") + keyboard.nextLine() + writer.stop() + } else { + println("Usage: LogProducer ") + } + + } +} diff --git a/app/src/test/scala/app/logorrr/conf/CoreGen.scala b/app/src/test/scala/app/logorrr/conf/CoreGen.scala new file mode 100644 index 00000000..862aaa29 --- /dev/null +++ b/app/src/test/scala/app/logorrr/conf/CoreGen.scala @@ -0,0 +1,8 @@ +package app.logorrr.conf + +import org.scalacheck.Gen + +object CoreGen { + val booleanGen: Gen[Boolean] = Gen.oneOf(false, true) + +} diff --git a/app/src/test/scala/app/logorrr/conf/mut/FilterSpec.scala b/app/src/test/scala/app/logorrr/conf/mut/FilterSpec.scala new file mode 100644 index 00000000..d330f891 --- /dev/null +++ b/app/src/test/scala/app/logorrr/conf/mut/FilterSpec.scala @@ -0,0 +1,13 @@ +package app.logorrr.conf.mut + +import app.logorrr.model.LogFileSettings +import app.logorrr.views.search.Filter +import org.scalacheck.Gen + +object FilterSpec { + + val gen: Gen[Filter] = for { + f <- Gen.oneOf(LogFileSettings.DefaultFilter) + } yield f + +} diff --git a/app/src/test/scala/app/logorrr/conf/mut/LogEntryInstantFormatSpec.scala b/app/src/test/scala/app/logorrr/conf/mut/LogEntryInstantFormatSpec.scala new file mode 100644 index 00000000..18480c3c --- /dev/null +++ b/app/src/test/scala/app/logorrr/conf/mut/LogEntryInstantFormatSpec.scala @@ -0,0 +1,12 @@ +package app.logorrr.conf.mut + +import app.logorrr.model.LogEntryInstantFormat +import org.scalacheck.Gen + +object LogEntryInstantFormatSpec { + val gen: Gen[LogEntryInstantFormat] = for { + sr <- SimpleRangeSpec.gen + dtp <- Gen.const(LogEntryInstantFormat.DefaultPattern) + zo <- Gen.const("+1") + } yield LogEntryInstantFormat(sr, dtp, zo) +} diff --git a/app/src/test/scala/app/logorrr/conf/mut/LogFileSettingsSpec.scala b/app/src/test/scala/app/logorrr/conf/mut/LogFileSettingsSpec.scala new file mode 100644 index 00000000..2df997d7 --- /dev/null +++ b/app/src/test/scala/app/logorrr/conf/mut/LogFileSettingsSpec.scala @@ -0,0 +1,22 @@ +package app.logorrr.conf.mut + +import app.logorrr.conf.CoreGen +import app.logorrr.model.LogFileSettings +import org.scalacheck.Gen + + +object LogFileSettingsSpec { + + val gen: Gen[LogFileSettings] = for { + pathAsString <- Gen.identifier + selectedIndex <- Gen.posNum[Int] + firstOpened <- Gen.posNum[Long] + dPos <- Gen.posNum[Double] + filters <- Gen.listOf(FilterSpec.gen) + leif <- LogEntryInstantFormatSpec.gen + someLogEntryInstantFormat <- Gen.oneOf(None, Option(leif)) + blockSettings <- BlockSettingsSpec.gen + fontSize <- Gen.posNum[Int] + autoScroll <- CoreGen.booleanGen + } yield LogFileSettings(pathAsString, selectedIndex, firstOpened, dPos, fontSize, filters, blockSettings, someLogEntryInstantFormat, autoScroll) +} diff --git a/app/src/test/scala/app/logorrr/conf/mut/RecentFileSettingsSpec.scala b/app/src/test/scala/app/logorrr/conf/mut/RecentFileSettingsSpec.scala deleted file mode 100644 index 0ac54d82..00000000 --- a/app/src/test/scala/app/logorrr/conf/mut/RecentFileSettingsSpec.scala +++ /dev/null @@ -1,49 +0,0 @@ -package app.logorrr.conf.mut - -import app.logorrr.model.{LogEntryInstantFormat, LogFileSettings} -import app.logorrr.views.SimpleRange -import app.logorrr.views.search.Filter -import org.scalacheck.Gen - -import scala.util.Random - -object FilterSpec { - - val gen: Gen[Filter] = for { - f <- Gen.oneOf(LogFileSettings.DefaultFilter) - } yield f - -} - -object SimpleRangeSpec { - - val gen: Gen[SimpleRange] = for { - start <- Gen.posNum[Int] - end <- Gen.chooseNum(start, Random.nextInt(start + 100) + start) - } yield SimpleRange(start, end) -} - -object LogEntryInstantFormatSpec { - val gen: Gen[LogEntryInstantFormat] = for { - sr <- SimpleRangeSpec.gen - dtp <- Gen.const(LogEntryInstantFormat.DefaultPattern) - zo <- Gen.const("+1") - } yield LogEntryInstantFormat(sr, dtp, zo) -} - -object LogFileSettingsSpec { - - val gen: Gen[LogFileSettings] = for { - pathAsString <- Gen.identifier - selectedIndex <- Gen.posNum[Int] - firstOpened <- Gen.posNum[Long] - dPos <- Gen.posNum[Double] - filters <- Gen.listOf(FilterSpec.gen) - leif <- LogEntryInstantFormatSpec.gen - someLogEntryInstantFormat <- Gen.oneOf(None, Option(leif)) - blockSettings <- BlockSettingsSpec.gen - fontSize <- Gen.posNum[Int] - } yield LogFileSettings(pathAsString, selectedIndex, firstOpened, dPos, fontSize, filters, blockSettings, someLogEntryInstantFormat) -} - - diff --git a/app/src/test/scala/app/logorrr/conf/mut/SimpleRangeSpec.scala b/app/src/test/scala/app/logorrr/conf/mut/SimpleRangeSpec.scala new file mode 100644 index 00000000..88f43d07 --- /dev/null +++ b/app/src/test/scala/app/logorrr/conf/mut/SimpleRangeSpec.scala @@ -0,0 +1,21 @@ +package app.logorrr.conf.mut + +import app.logorrr.views.SimpleRange +import org.scalacheck.Gen + +import scala.util.Random + + +object SimpleRangeSpec { + + val gen: Gen[SimpleRange] = for { + start <- Gen.posNum[Int] + end <- Gen.chooseNum(start, Random.nextInt(start + 100) + start) + } yield SimpleRange(start, end) +} + + + + + +