Add context menu to Ocelot component log entries

This commit is contained in:
UnicornFreedom 2025-08-22 14:24:11 +02:00
parent 6db5ff3f37
commit cf088ce9f7
No known key found for this signature in database
GPG Key ID: B4ED0DB6B940024F

View File

@ -3,9 +3,13 @@ package ocelot.desktop.ui.widget
import ocelot.desktop.ColorScheme
import ocelot.desktop.color.RGBAColorNorm
import ocelot.desktop.geometry.{Padding2D, Rect2D, Size2D, Vector2D}
import ocelot.desktop.graphics.Graphics
import ocelot.desktop.graphics.{Graphics, IconSource}
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.{ClickEvent, MouseEvent}
import ocelot.desktop.ui.event.handlers.MouseHandler
import ocelot.desktop.ui.layout.{Layout, LinearLayout}
import ocelot.desktop.ui.widget.LogWidget.{BorderThickness, EntryMargin, EntryPadding, LogEntry}
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.util.{DrawUtils, Orientation}
import scala.annotation.tailrec
@ -14,13 +18,27 @@ import scala.collection.mutable
abstract class LogWidget extends Widget {
override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
private object MessageListWidget extends Widget { messageList =>
private object MessageListWidget extends Widget with MouseHandler { messageList =>
override protected val layout: Layout = new Layout(this)
private val entries = mutable.ArrayDeque.empty[Entry]
val dummyEntry: Entry = new RxEntry("", nextMessageY)
override def receiveClickEvents: Boolean = true
eventHandlers += {
case ClickEvent(MouseEvent.Button.Right, mouse) =>
visibleEntries.find(_.absoluteBounds.contains(mouse)).foreach {
case entry: MessageEntry =>
val menu = new ContextMenu
menu.addEntry(ContextMenuEntry("Copy", IconSource.Icons.Copy) {
UiHandler.clipboard = entry.message
})
root.get.contextMenus.open(menu)
}
}
private def removedOffset: Float = entries.headOption.map(_.y - EntryMargin).getOrElse(0)
private def applyRemovedOffset(): Unit = {
@ -72,15 +90,16 @@ abstract class LogWidget extends Widget {
}
}
private def visibleEntries: Iterator[Entry] = {
val firstVisibleIdx = firstVisibleIdxSearch(parent.get.asInstanceOf[ScrollView].offset.y)
entries.iterator.drop(firstVisibleIdx).takeWhile(_.absoluteBounds.y <= clippedBounds.max.y)
}
override def draw(g: Graphics): Unit = {
applyRemovedOffset()
val firstVisibleIdx = firstVisibleIdxSearch(parent.get.asInstanceOf[ScrollView].offset.y)
for (entry <- entries.iterator.drop(firstVisibleIdx).takeWhile(_.absoluteBounds.y <= clippedBounds.max.y)) {
for (entry <- visibleEntries) {
entry.draw(g)
}
super.draw(g)
}
@ -100,7 +119,7 @@ abstract class LogWidget extends Widget {
final def absoluteBounds: Rect2D = Rect2D(position + messageList.position, size)
}
private abstract class MessageEntry(message: String, override var y: Float) extends Entry {
private abstract class MessageEntry(val message: String, override var y: Float) extends Entry {
private val lines = Text.wrap(message, Some(textWidth))
def minimumSize: Size2D = Size2D(