Skip to content

Commit

Permalink
#43: adds new toolbar and sliders to filter based on the timestamp of…
Browse files Browse the repository at this point in the history
… a log entry
  • Loading branch information
rladstaetter committed Aug 9, 2024
1 parent 52b9c61 commit 65e4bc5
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 34 deletions.
12 changes: 4 additions & 8 deletions app/src/main/scala/app/logorrr/model/LogEntryInstantFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ object LogEntryInstantFormat extends CanLog {
val dateTimeAsString = line.substring(entrySetting.startCol, entrySetting.endCol)
val dtf: DateTimeFormatter = entrySetting.dateTimeFormatter
Try {
LocalDateTime.parse(dateTimeAsString, dtf).toInstant(ZoneOffset.of(entrySetting.zoneOffset))
LocalDateTime.parse(dateTimeAsString, dtf).atZone(ZoneId.systemDefault).toInstant
} match {
case Success(value) => Option(value)
case Failure(_) =>
// retrying with localtime as fallback for entries which don't have any
// date information (for example: '08:34:33' representing today morning)
Try {
LocalDateTime.of(LocalDate.now(), LocalTime.parse(dateTimeAsString, dtf)).toInstant(ZoneOffset.of(entrySetting.zoneOffset))
LocalDateTime.of(LocalDate.now(), LocalTime.parse(dateTimeAsString, dtf)).atZone(ZoneId.systemDefault()).toInstant
} match {
case Success(value) => Option(value)
case Failure(exception) =>
Expand All @@ -45,12 +45,8 @@ object LogEntryInstantFormat extends CanLog {

}

case class LogEntryInstantFormat(range: SimpleRange
, dateTimePattern: String
, zoneOffset: String = "+1") {
case class LogEntryInstantFormat(range: SimpleRange, dateTimePattern: String) {
val startCol: Int = range.start
val endCol: Int = range.end
val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern(dateTimePattern).withZone(ZoneId.of(zoneOffset))


val dateTimeFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern(dateTimePattern).withZone(ZoneId.systemDefault)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import app.logorrr.io.FileId
import app.logorrr.model.LogEntry
import app.logorrr.views.block.ChunkListView
import app.logorrr.views.ops.OpsRegion
import app.logorrr.views.ops.time.TimeOpsToolBar
import app.logorrr.views.search.{Filter, FiltersToolBar, OpsToolBar}
import app.logorrr.views.text.LogTextView
import javafx.beans.{InvalidationListener, Observable}
Expand All @@ -30,14 +31,12 @@ class LogFileTabContent(fileId: FileId
// graphical display to the left
private val chunkListView = ChunkListView(filteredList, mutLogFileSettings, logTextView.scrollToItem)


private val blockSizeSlider = {
val bs = new BlockSizeSlider(mutLogFileSettings.getFileId)
bs.valueProperty().bindBidirectional(mutLogFileSettings.blockSizeProperty)
bs
}


private val blockPane = {
val bBp = new BorderPane(chunkListView, blockSizeSlider, null, null, null)
// vBox.setStyle("-fx-background-color: #b6ff7a;")
Expand All @@ -62,16 +61,18 @@ class LogFileTabContent(fileId: FileId
, addFilter
, entries
, filteredList
, mutLogFileSettings.blockSizeProperty
, chunkListView)
, mutLogFileSettings.blockSizeProperty)

private val filtersToolBar = {
val fbtb = new FiltersToolBar(fileId, filteredList, removeFilter)
fbtb.filtersProperty.bind(mutLogFileSettings.filtersProperty)
fbtb
}

private val opsRegion: OpsRegion = new OpsRegion(opsToolBar, filtersToolBar)
val timeOpsToolBar = new TimeOpsToolBar(mutLogFileSettings
, chunkListView
, entries // we write on this list potentially
, filteredList)
private val opsRegion: OpsRegion = new OpsRegion(opsToolBar, filtersToolBar, timeOpsToolBar)

private val pane = new SplitPane(blockPane, logTextView)

Expand Down
18 changes: 9 additions & 9 deletions app/src/main/scala/app/logorrr/views/ops/OpsRegion.scala
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package app.logorrr.views.ops

import app.logorrr.views.ops.time.TimeOpsToolBar
import app.logorrr.views.search.{FiltersToolBar, OpsToolBar}
import javafx.geometry.Pos
import javafx.scene.layout.HBox
import javafx.scene.layout.VBox


/**
* Container to horizontally align search, filters and settings
*/
class OpsRegion(opsToolBar: OpsToolBar, filtersToolBar: FiltersToolBar) extends HBox {

HBox.setHgrow(filtersToolBar, javafx.scene.layout.Priority.ALWAYS)
setAlignment(Pos.CENTER_LEFT)
opsToolBar.setMaxHeight(Double.PositiveInfinity)
filtersToolBar.setMaxHeight(Double.PositiveInfinity)
getChildren.addAll(opsToolBar, filtersToolBar)
class OpsRegion(opsToolBar: OpsToolBar
, filtersToolBar: FiltersToolBar
, timeOpsToolBar: TimeOpsToolBar) extends VBox {
getChildren.addAll(timeOpsToolBar, new StdOpsToolBar(opsToolBar, filtersToolBar))

}




15 changes: 15 additions & 0 deletions app/src/main/scala/app/logorrr/views/ops/StdOpsToolBar.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package app.logorrr.views.ops

import app.logorrr.views.search.{FiltersToolBar, OpsToolBar}
import javafx.geometry.Pos
import javafx.scene.layout.HBox

class StdOpsToolBar(opsToolBar: OpsToolBar, filtersToolBar: FiltersToolBar) extends HBox {

HBox.setHgrow(filtersToolBar, javafx.scene.layout.Priority.ALWAYS)
setAlignment(Pos.CENTER_LEFT)
opsToolBar.setMaxHeight(Double.PositiveInfinity)
filtersToolBar.setMaxHeight(Double.PositiveInfinity)
getChildren.addAll(opsToolBar, filtersToolBar)

}
71 changes: 71 additions & 0 deletions app/src/main/scala/app/logorrr/views/ops/time/TimeOpsToolBar.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package app.logorrr.views.ops.time

import app.logorrr.conf.LogoRRRGlobals
import app.logorrr.conf.mut.MutLogFileSettings
import app.logorrr.io.FileId
import app.logorrr.model.LogEntry
import app.logorrr.views.block.ChunkListView
import javafx.collections.ObservableList
import javafx.collections.transformation.FilteredList
import javafx.scene.control.{Label, ToolBar}

import java.time.format.DateTimeFormatter

object TimeOpsToolBar {

private def updateFilteredList(filteredList: FilteredList[LogEntry], lower: Long, higher: Long): Unit = {
filteredList.setPredicate((t: LogEntry) => {
t.someInstant match {
case Some(value) =>
val asMilli = value.toEpochMilli
lower <= asMilli && asMilli <= higher
case None => false
}
})
}

}

class TimeOpsToolBar(mutLogFileSettings: MutLogFileSettings
, chunkListView: ChunkListView
, logEntries: ObservableList[LogEntry]
, filteredList: FilteredList[LogEntry]) extends ToolBar {

val formatter: DateTimeFormatter = mutLogFileSettings.someLogEntrySettingsProperty.get().map(_.dateTimeFormatter).getOrElse(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"))
val fileId: FileId = mutLogFileSettings.getFileId

/**
* To configure the logformat of the timestamp used in a logfile
*/
val timestampSettingsButton = new TimestampSettingsButton(LogoRRRGlobals.getLogFileSettings(fileId), chunkListView, logEntries)

val lowSlider = new TimerSlider(filteredList)
lowSlider.setValue(lowSlider.getMin)
lowSlider.disableProperty().bind(mutLogFileSettings.hasLogEntrySettingBinding.not)
val highSlider = new TimerSlider(filteredList)
highSlider.setValue(highSlider.getMax)
highSlider.disableProperty().bind(mutLogFileSettings.hasLogEntrySettingBinding.not)
val leftLabel = new Label()
leftLabel.setText(TimerSlider.format(lowSlider.getValue.longValue(), formatter))
leftLabel.visibleProperty().bind(mutLogFileSettings.hasLogEntrySettingBinding)
val rightLabel = new Label()
rightLabel.setText(TimerSlider.format(highSlider.getValue.longValue(), formatter))
rightLabel.visibleProperty().bind(mutLogFileSettings.hasLogEntrySettingBinding)
lowSlider.valueProperty.addListener((_, _, newValue) => {
if (newValue.doubleValue > highSlider.getValue) lowSlider.setValue(highSlider.getValue)
leftLabel.setText(TimerSlider.format(newValue.longValue, formatter))
TimeOpsToolBar.updateFilteredList(filteredList, newValue.longValue(), highSlider.getValue.longValue)
})

highSlider.valueProperty.addListener((_, _, newValue) => {
if (newValue.doubleValue < lowSlider.getValue) highSlider.setValue(lowSlider.getValue)
rightLabel.setText(TimerSlider.format(newValue.longValue, formatter))
TimeOpsToolBar.updateFilteredList(filteredList, lowSlider.getValue.longValue, newValue.longValue())
})

getItems.addAll(Seq(timestampSettingsButton, leftLabel, lowSlider, highSlider, rightLabel): _*)

}



52 changes: 52 additions & 0 deletions app/src/main/scala/app/logorrr/views/ops/time/TimerSlider.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package app.logorrr.views.ops.time

import app.logorrr.model.LogEntry
import javafx.collections.ObservableList
import javafx.scene.control.Slider

import java.time.format.DateTimeFormatter
import java.time.{Instant, LocalDateTime, ZoneId}

object TimerSlider {
def format(epochMilli: Long, formatter: DateTimeFormatter): String = {
val instant = Instant.ofEpochMilli(epochMilli)
val dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault)
dateTime.format(formatter)
}
}

class TimerSlider(filteredList: ObservableList[LogEntry]) extends Slider {
/*
def onChange(c: ListChangeListener.Change[_ <: LogEntry]): Unit = {
while (c.next()) {
updateMinMax()
}
} */

private def updateMinMax(): Unit = {
if (2 <= filteredList.size) {
var minInstant = Instant.MAX
var maxInstant = Instant.MIN
filteredList.forEach((e: LogEntry) => {
e.someInstant match {
case Some(instant) =>
if (instant.isBefore(minInstant)) {
minInstant = instant
}
if (instant.isAfter(maxInstant)) {
maxInstant = instant
}
case None =>
}
})
setMin(minInstant.toEpochMilli.toDouble)
setMax(maxInstant.toEpochMilli.toDouble)
}
}

setPrefWidth(500)
updateMinMax()
// filteredList.addListener(JfxUtils.mkListChangeListener(onChange))


}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package app.logorrr.views.search
package app.logorrr.views.ops.time

import app.logorrr.conf.mut.MutLogFileSettings
import app.logorrr.model.LogEntry
Expand Down
13 changes: 3 additions & 10 deletions app/src/main/scala/app/logorrr/views/search/OpsToolBar.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package app.logorrr.views.search

import app.logorrr.conf.LogoRRRGlobals
import app.logorrr.io.FileId
import app.logorrr.model.LogEntry
import app.logorrr.util.OsUtil
import app.logorrr.views.autoscroll.AutoScrollCheckBox
import app.logorrr.views.block.{ChunkListView, HasBlockSizeProperty}
import app.logorrr.views.block.HasBlockSizeProperty
import app.logorrr.views.ops.{ClearLogButton, CopyLogButton, DecreaseBlockSizeButton, IncreaseBlockSizeButton}
import app.logorrr.views.text.toolbaractions.{DecreaseTextSizeButton, IncreaseTextSizeButton}
import javafx.beans.property.SimpleIntegerProperty
Expand All @@ -18,7 +17,6 @@ import javafx.scene.input.{KeyCode, KeyEvent}

object OpsToolBar {


/** increment / decrement font size */
val fontSizeStep: Int = 1

Expand All @@ -33,8 +31,7 @@ class OpsToolBar(fileId: FileId
, addFilterFn: Filter => Unit
, logEntries: ObservableList[LogEntry]
, filteredList: FilteredList[LogEntry]
, val blockSizeProperty: SimpleIntegerProperty
, chunkListView: ChunkListView)
, val blockSizeProperty: SimpleIntegerProperty)
extends ToolBar
with HasBlockSizeProperty {

Expand Down Expand Up @@ -64,10 +61,6 @@ class OpsToolBar(fileId: FileId

private val copySelectionButton = new CopyLogButton(fileId, filteredList)

/**
* To configure the logformat of the timestamp used in a logfile
*/
val timestampSettingsButton = new TimestampSettingsButton(LogoRRRGlobals.getLogFileSettings(fileId), chunkListView, logEntries)

def execSearchOnHitEnter(event: KeyEvent): Unit = {
if (event.getCode == KeyCode.ENTER) {
Expand All @@ -89,7 +82,7 @@ class OpsToolBar(fileId: FileId
}

val otherItems: Seq[Node] = {
Seq(autoScrollCheckBox, clearLogButton, copySelectionButton, timestampSettingsButton)
Seq(autoScrollCheckBox, clearLogButton, copySelectionButton)
}

getItems.addAll(searchItems ++ sizeItems ++ otherItems: _*)
Expand Down

0 comments on commit 65e4bc5

Please sign in to comment.