package ocelot.desktop.ui.window import ocelot.desktop.color.{IntColor, RGBAColor, RGBAColorNorm} import ocelot.desktop.geometry.{Rect2D, Size2D, Vector2D} import ocelot.desktop.graphics.Graphics import ocelot.desktop.ui.event.{KeyEvent, MouseEvent, ScrollEvent} import ocelot.desktop.ui.{MouseEvents, UiHandler} import ocelot.desktop.util.{DrawUtils, Logging} import org.apache.commons.lang3.StringUtils import totoro.ocelot.brain.entity.Screen import totoro.ocelot.brain.user.User import totoro.ocelot.brain.util.PackedColor class ScreenWindow(screen: Screen) extends BasicWindow with Logging { private val fontWidth = 8f private val fontHeight = 16f private def screenWidth: Int = screen.getWidth private def screenHeight: Int = screen.getHeight override def minimumSize: Size2D = Size2D(screenWidth * fontWidth + 32, screenHeight * fontHeight + 20) override def maximumSize: Size2D = minimumSize private var lastMousePos = Vector2D(0, 0) private var sentTouchEvent = false eventHandlers += { case event: KeyEvent => event.state match { case KeyEvent.State.Press | KeyEvent.State.Repeat => screen.keyDown(event.char, event.code, User("myself")) if (event.code == 1) hide() // note: in opencomputers, key_down signal is fired __before__ clipboard signal if (event.code == 210) screen.clipboard(UiHandler.clipboard, User("myself")) case KeyEvent.State.Release => screen.keyUp(event.char, event.code, User("myself")) } case event: MouseEvent => val pos = convertMousePos(UiHandler.mousePosition) val inside = checkBounds(pos) if (inside) lastMousePos = pos event.state match { case MouseEvent.State.Press if inside => screen.mouseDown(pos.x, pos.y, event.button.id, User("myself")) sentTouchEvent = true case MouseEvent.State.Release => if (event.button == MouseEvent.Button.Middle && inside) screen.clipboard(UiHandler.clipboard, User("myself")) if (sentTouchEvent) { screen.mouseUp(lastMousePos.x, lastMousePos.y, event.button.id, User("myself")) sentTouchEvent = false } else if (closeButtonBounds.contains(UiHandler.mousePosition)) { hide() } case _ => } case event: ScrollEvent => screen.mouseScroll(lastMousePos.x, lastMousePos.y, event.offset, User("myself")) } private def checkBounds(p: Vector2D): Boolean = p.x >= 0 && p.y >= 0 && p.x < screenWidth && p.y < screenHeight private def convertMousePos(p: Vector2D): Vector2D = { Vector2D( math.floor((p.x - 16f - position.x) / fontWidth), math.floor((p.y - 16f - position.y) / fontHeight) ) } override def dragRegions: Iterator[Rect2D] = Iterator(Rect2D(position.x, position.y, size.width, 20)) override def update(): Unit = { super.update() val currentMousePos = convertMousePos(UiHandler.mousePosition) if (!checkBounds(currentMousePos) || currentMousePos == lastMousePos) return lastMousePos = currentMousePos for (button <- MouseEvents.pressedButtons) { screen.mouseDrag(lastMousePos.x, lastMousePos.y, button.id, User("myself")) } } private def closeButtonBounds: Rect2D = Rect2D( position.x + fontWidth * screenWidth + 2, position.y - 2, 22, 22) override def draw(g: Graphics): Unit = { val sx = position.x + 16 val sy = position.y + 20 val w = fontWidth * screenWidth val h = fontHeight * screenHeight DrawUtils.shadow(g, sx - 22, sy - 22, w + 44, h + 52, shadowAlpha) DrawUtils.screenBorder(g, sx, sy, w, h, RGBAColorNorm(1, 1, 1, backgroundAlpha)) for (y <- 0 until screenHeight) { for (x <- 0 until screenWidth) { val char = screen.data.buffer(y)(x) val color = screen.data.color(y)(x) val bg = PackedColor.unpackBackground(color, screen.data.format) val fg = PackedColor.unpackForeground(color, screen.data.format) g.background = IntColor(bg).toRGBANorm.withAlpha(backgroundAlpha) g.foreground = IntColor(fg).toRGBANorm.withAlpha(backgroundAlpha) g.char(sx + x * fontWidth, sy + y * fontHeight, char) } } g.setSmallFont() g.background = RGBAColor(0, 0, 0, 0) val col = (backgroundAlpha * 110).toShort val alpha = (backgroundAlpha * 255).toShort g.foreground = RGBAColor(col, col, col, alpha) val freeSpace = ((w - 15) / 8).toInt val addr = screen.node.address val text = if (addr.length <= freeSpace) addr else StringUtils.substring(addr, 0, (freeSpace - 1).max(0).min(addr.length)) + "…" g.text(sx - 4, sy - 14, text) g.setNormalFont() g.sprite("window/CloseButton", sx + w - 7, sy - 13, 7, 6, color = RGBAColor(255, 255, 255, alpha)) } }