mirror of
https://gitlab.com/cc-ru/ocelot/ocelot-desktop.git
synced 2025-12-20 11:09:20 +01:00
Remove the old slot implementation
Yahoo.
This commit is contained in:
parent
82dead6b9b
commit
861c752fb8
@ -15,7 +15,7 @@ import ocelot.desktop.ui.event.sources.KeyEvents
|
|||||||
import ocelot.desktop.ui.event.{BrainEvent, ClickEvent, MouseEvent}
|
import ocelot.desktop.ui.event.{BrainEvent, ClickEvent, MouseEvent}
|
||||||
import ocelot.desktop.ui.widget.Label
|
import ocelot.desktop.ui.widget.Label
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuSubmenu}
|
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuSubmenu}
|
||||||
import ocelot.desktop.ui.widget.slot.reimpl._
|
import ocelot.desktop.ui.widget.slot._
|
||||||
import ocelot.desktop.util.{Logging, Messages, TierColor}
|
import ocelot.desktop.util.{Logging, Messages, TierColor}
|
||||||
import ocelot.desktop.windows.ComputerWindow
|
import ocelot.desktop.windows.ComputerWindow
|
||||||
import org.lwjgl.input.Keyboard
|
import org.lwjgl.input.Keyboard
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import ocelot.desktop.graphics.Graphics
|
|||||||
import ocelot.desktop.inventory.SyncedInventory
|
import ocelot.desktop.inventory.SyncedInventory
|
||||||
import ocelot.desktop.inventory.item.{FloppyItem, FloppyItemFactory}
|
import ocelot.desktop.inventory.item.{FloppyItem, FloppyItemFactory}
|
||||||
import ocelot.desktop.node.Node
|
import ocelot.desktop.node.Node
|
||||||
import ocelot.desktop.ui.widget.slot.reimpl.FloppySlotWidget
|
import ocelot.desktop.ui.widget.slot.FloppySlotWidget
|
||||||
import ocelot.desktop.windows.DiskDriveWindow
|
import ocelot.desktop.windows.DiskDriveWindow
|
||||||
import totoro.ocelot.brain.entity.FloppyDiskDrive
|
import totoro.ocelot.brain.entity.FloppyDiskDrive
|
||||||
import totoro.ocelot.brain.entity.traits.Inventory
|
import totoro.ocelot.brain.entity.traits.Inventory
|
||||||
|
|||||||
@ -1,76 +0,0 @@
|
|||||||
package ocelot.desktop.ui.widget.slot
|
|
||||||
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
|
||||||
import ocelot.desktop.node.nodes.ComputerNode
|
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuSubmenu}
|
|
||||||
import totoro.ocelot.brain.entity.machine.MachineAPI
|
|
||||||
import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU, Inventory}
|
|
||||||
import totoro.ocelot.brain.entity.{APU, CPU}
|
|
||||||
import totoro.ocelot.brain.util.Tier
|
|
||||||
import totoro.ocelot.brain.util.Tier.Tier
|
|
||||||
|
|
||||||
class CPUSlot(owner: Inventory#Slot, node: ComputerNode, val tier: Tier) extends InventorySlot[GenericCPU with Entity](owner) {
|
|
||||||
|
|
||||||
override def itemIcon: Option[IconDef] = item match {
|
|
||||||
case Some(cpu: CPU) => Some(Icons.Cpu(cpu.tier))
|
|
||||||
case Some(apu: APU) => Some(Icons.Apu(apu.tier))
|
|
||||||
case _ => None
|
|
||||||
}
|
|
||||||
|
|
||||||
override def icon: IconDef = Icons.CpuIcon
|
|
||||||
override def tierIcon: Option[IconDef] = Some(Icons.TierIcon(tier))
|
|
||||||
|
|
||||||
override def fillLmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
for (tier <- Tier.One to Tier.Three if this.tier >= tier) {
|
|
||||||
menu.addEntry(new ContextMenuEntry(s"CPU (${tier.label})",
|
|
||||||
() => item = new CPU(tier),
|
|
||||||
icon = Some(Icons.Cpu(tier))))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tier < Tier.Two) return
|
|
||||||
|
|
||||||
menu.addEntry(new ContextMenuSubmenu("APU (CPU + GPU)", icon = Some(Icons.GraphicsCard(Tier.Two))) {
|
|
||||||
addEntry(new ContextMenuEntry("Tier 2",
|
|
||||||
() => item = new APU(Tier.One),
|
|
||||||
icon = Some(Icons.Apu(Tier.One))))
|
|
||||||
|
|
||||||
if (tier >= Tier.Three) {
|
|
||||||
addEntry(new ContextMenuEntry("Tier 3",
|
|
||||||
() => item = new APU(Tier.Two),
|
|
||||||
icon = Some(Icons.Apu(Tier.Two))))
|
|
||||||
|
|
||||||
addEntry(new ContextMenuEntry("Creative",
|
|
||||||
() => item = new APU(Tier.Three),
|
|
||||||
icon = Some(Icons.Apu(Tier.Three))))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
if (item.isEmpty) return
|
|
||||||
|
|
||||||
val cpu = item.get
|
|
||||||
|
|
||||||
menu.addEntry(new ContextMenuSubmenu("Set architecture") {
|
|
||||||
for (arch <- cpu.allArchitectures) {
|
|
||||||
val name = MachineAPI.getArchitectureName(arch) +
|
|
||||||
(if (arch == cpu.architecture) " (current)" else "")
|
|
||||||
|
|
||||||
addEntry(new ContextMenuEntry(name, () => {
|
|
||||||
val machine = node.computer.machine
|
|
||||||
if (machine.isRunning) {
|
|
||||||
machine.stop()
|
|
||||||
cpu.setArchitecture(arch)
|
|
||||||
machine.start()
|
|
||||||
} else {
|
|
||||||
cpu.setArchitecture(arch)
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
super.fillRmbMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def lmbMenuEnabled: Boolean = true
|
|
||||||
}
|
|
||||||
@ -1,72 +0,0 @@
|
|||||||
package ocelot.desktop.ui.widget.slot
|
|
||||||
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
|
||||||
import totoro.ocelot.brain.entity.sound_card.SoundCard
|
|
||||||
import totoro.ocelot.brain.entity.traits.{Entity, Tiered, TieredPersistable}
|
|
||||||
import totoro.ocelot.brain.entity.{DataCard, GraphicsCard, InternetCard, LinkedCard, NetworkCard, Redstone, SelfDestructingCard, WirelessNetworkCard}
|
|
||||||
import totoro.ocelot.brain.util.Tier
|
|
||||||
import totoro.ocelot.brain.util.Tier.Tier
|
|
||||||
|
|
||||||
import scala.collection.mutable
|
|
||||||
import scala.reflect.{ClassTag, classTag}
|
|
||||||
|
|
||||||
object CardRegistry {
|
|
||||||
case class Entry(name: String, tier: Tier, icon: IconDef, factory: () => Entity)
|
|
||||||
|
|
||||||
val iconByClass: mutable.HashMap[String, IconDef] = mutable.HashMap()
|
|
||||||
val tierByClass: mutable.HashMap[String, Tier] = mutable.HashMap()
|
|
||||||
val iconByClassAndTier: mutable.HashMap[(String, Tier), IconDef] = mutable.HashMap()
|
|
||||||
val entries: mutable.ArrayBuffer[Entry] = mutable.ArrayBuffer()
|
|
||||||
|
|
||||||
def addEntry[T <: Entity : ClassTag](name: String, tier: Tier, icon: IconDef, factory: () => T): Unit = {
|
|
||||||
val entry = Entry(name, tier, icon, factory)
|
|
||||||
entries += entry
|
|
||||||
val clazz = classTag[T].runtimeClass.getName
|
|
||||||
iconByClass.addOne((clazz, icon))
|
|
||||||
tierByClass.addOne((clazz, tier))
|
|
||||||
iconByClassAndTier.addOne(((clazz, entry.tier), icon))
|
|
||||||
}
|
|
||||||
|
|
||||||
def getIcon(entity: Entity): Option[IconDef] = {
|
|
||||||
val clazz = entity.getClass.getName
|
|
||||||
entity match {
|
|
||||||
case t: TieredPersistable => iconByClassAndTier.get((clazz, t.tier))
|
|
||||||
case _ => iconByClass.get(clazz)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def getTier(entity: Entity): Tier = {
|
|
||||||
val clazz = entity.getClass.getName
|
|
||||||
entity match {
|
|
||||||
case t: Tiered => t.tier
|
|
||||||
case _ => tierByClass.getOrElse(clazz, Tier.One)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (tier <- Tier.One to Tier.Three) {
|
|
||||||
addEntry("Graphics Card", tier, Icons.GraphicsCard(tier), () => new GraphicsCard(tier))
|
|
||||||
}
|
|
||||||
|
|
||||||
addEntry("Network Card", Tier.One, Icons.NetworkCard, () => new NetworkCard)
|
|
||||||
|
|
||||||
addEntry("Wireless Net. Card", Tier.One, Icons.WirelessNetworkCard(Tier.One),
|
|
||||||
() => new WirelessNetworkCard.Tier1)
|
|
||||||
addEntry("Wireless Net. Card", Tier.Two, Icons.WirelessNetworkCard(Tier.Two),
|
|
||||||
() => new WirelessNetworkCard.Tier2)
|
|
||||||
|
|
||||||
addEntry("Linked Card", Tier.Three, Icons.LinkedCard, () => new LinkedCard)
|
|
||||||
|
|
||||||
addEntry("Internet Card", Tier.Two, Icons.InternetCard, () => new InternetCard)
|
|
||||||
|
|
||||||
addEntry("Redstone Card", Tier.One, Icons.RedstoneCard(Tier.One), () => new Redstone.Tier1)
|
|
||||||
addEntry("Redstone Card", Tier.Two, Icons.RedstoneCard(Tier.Two), () => new Redstone.Tier2)
|
|
||||||
|
|
||||||
addEntry("Data Card", Tier.One, Icons.DataCard(Tier.One), () => new DataCard.Tier1)
|
|
||||||
addEntry("Data Card", Tier.Two, Icons.DataCard(Tier.Two), () => new DataCard.Tier2)
|
|
||||||
addEntry("Data Card", Tier.Three, Icons.DataCard(Tier.Three), () => new DataCard.Tier3)
|
|
||||||
|
|
||||||
addEntry("Sound Card", Tier.Two, Icons.SoundCard, () => new SoundCard)
|
|
||||||
|
|
||||||
addEntry("Self-Destructing Card", Tier.Two, Icons.SelfDestructingCard, () => new SelfDestructingCard)
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
package ocelot.desktop.ui.widget.slot
|
|
||||||
|
|
||||||
import ocelot.desktop.color.Color
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
|
||||||
import ocelot.desktop.ui.UiHandler
|
|
||||||
import ocelot.desktop.ui.widget.card.{Redstone1Window, Redstone2Window, SoundCardWindow}
|
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuSubmenu}
|
|
||||||
import ocelot.desktop.ui.widget.{Label, TunnelDialog, Widget}
|
|
||||||
import totoro.ocelot.brain.entity.sound_card.SoundCard
|
|
||||||
import totoro.ocelot.brain.entity.traits.{Entity, Inventory}
|
|
||||||
import totoro.ocelot.brain.entity.{LinkedCard, Redstone}
|
|
||||||
import totoro.ocelot.brain.util.Tier.Tier
|
|
||||||
|
|
||||||
class CardSlot(owner: Inventory#Slot, val tier: Tier) extends InventorySlot[Entity](owner) {
|
|
||||||
override def itemIcon: Option[IconDef] = item.flatMap(it => CardRegistry.getIcon(it))
|
|
||||||
|
|
||||||
override def icon: IconDef = Icons.CardIcon
|
|
||||||
override def tierIcon: Option[IconDef] = Some(Icons.TierIcon(tier))
|
|
||||||
|
|
||||||
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
val pool = UiHandler.root.workspaceView.windowPool
|
|
||||||
item match {
|
|
||||||
case Some(card: Redstone.Tier2) =>
|
|
||||||
menu.addEntry(new ContextMenuEntry("Redstone I/O", () => pool.openWindow(new Redstone1Window(card))))
|
|
||||||
menu.addEntry(new ContextMenuEntry("Bundled I/O", () => pool.openWindow(new Redstone2Window(card))))
|
|
||||||
case Some(card: Redstone.Tier1) =>
|
|
||||||
menu.addEntry(new ContextMenuEntry("Redstone I/O", () => pool.openWindow(new Redstone1Window(card))))
|
|
||||||
case Some(card: LinkedCard) =>
|
|
||||||
menu.addEntry(new ContextMenuEntry("Set channel", () => new TunnelDialog(
|
|
||||||
tunnel => card.tunnel = tunnel,
|
|
||||||
card.tunnel
|
|
||||||
).show()))
|
|
||||||
case Some(card: SoundCard) =>
|
|
||||||
menu.addEntry(new ContextMenuEntry("Open", () => pool.openWindow(new SoundCardWindow(card))))
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
super.fillRmbMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def fillLmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
val entries = CardRegistry.entries
|
|
||||||
|
|
||||||
var i = 0
|
|
||||||
while (i < entries.length) {
|
|
||||||
val entry = entries(i)
|
|
||||||
val nextEntry = entries.lift(i + 1)
|
|
||||||
|
|
||||||
if (nextEntry.isDefined && nextEntry.get.name == entry.name) {
|
|
||||||
val groupName = entry.name
|
|
||||||
if (tier >= entry.tier) {
|
|
||||||
menu.addEntry(new ContextMenuSubmenu(groupName, icon = Some(nextEntry.get.icon)) {
|
|
||||||
entries.view.slice(i, entries.length).takeWhile(_.name == groupName).foreach(entry => {
|
|
||||||
if (tier >= entry.tier) {
|
|
||||||
addEntry(new ContextMenuEntry(entry.tier.label, () => item = entry.factory(), Some(entry.icon)))
|
|
||||||
}
|
|
||||||
i += 1
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (tier >= entry.tier) {
|
|
||||||
menu.addEntry(new ContextMenuEntry(entry.name, () => item = entry.factory(), Some(entry.icon)))
|
|
||||||
}
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def lmbMenuEnabled: Boolean = true
|
|
||||||
|
|
||||||
override def tooltipChildrenAdder(inner: Widget): Unit = {
|
|
||||||
super.tooltipChildrenAdder(inner)
|
|
||||||
|
|
||||||
item match {
|
|
||||||
case Some(card: LinkedCard) =>
|
|
||||||
inner.children :+= new Label {
|
|
||||||
override def text: String = s"Channel: ${card.tunnel}"
|
|
||||||
override def color: Color = Color.Grey
|
|
||||||
}
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ocelot.desktop.ui.widget.slot.reimpl
|
package ocelot.desktop.ui.widget.slot
|
||||||
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
import ocelot.desktop.graphics.{IconDef, Icons}
|
||||||
import ocelot.desktop.inventory.Inventory
|
import ocelot.desktop.inventory.Inventory
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ocelot.desktop.ui.widget.slot.reimpl
|
package ocelot.desktop.ui.widget.slot
|
||||||
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
import ocelot.desktop.graphics.{IconDef, Icons}
|
||||||
import ocelot.desktop.inventory.Inventory
|
import ocelot.desktop.inventory.Inventory
|
||||||
@ -1,29 +0,0 @@
|
|||||||
package ocelot.desktop.ui.widget.slot
|
|
||||||
|
|
||||||
import ocelot.desktop.OcelotDesktop
|
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
|
||||||
import totoro.ocelot.brain.entity.traits.{DiskManaged, Entity}
|
|
||||||
|
|
||||||
import javax.swing.JFileChooser
|
|
||||||
import scala.util.Try
|
|
||||||
|
|
||||||
trait DiskOrFloppySlot {
|
|
||||||
def addSetDirectoryEntryToRmbMenu(menu: ContextMenu, slot: InventorySlot[DiskManaged with Entity]): Unit = {
|
|
||||||
menu.addEntry(new ContextMenuEntry(
|
|
||||||
"Set directory",
|
|
||||||
() => OcelotDesktop.showFileChooserDialog(JFileChooser.OPEN_DIALOG, JFileChooser.DIRECTORIES_ONLY) { dir =>
|
|
||||||
Try {
|
|
||||||
if (dir.isDefined && slot.item.isDefined) {
|
|
||||||
val item = slot.item
|
|
||||||
// first - unload the item with old filesystem (triggers 'component_removed' signal)
|
|
||||||
slot.item = None
|
|
||||||
// then - trigger filesystem rebuild with a new path
|
|
||||||
item.get.customRealPath = Some(dir.get.toPath.toAbsolutePath)
|
|
||||||
// finally - add the item back (triggers 'component_added' signal)
|
|
||||||
slot.item = item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
package ocelot.desktop.ui.widget.slot
|
|
||||||
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
|
||||||
import totoro.ocelot.brain.entity.HDDManaged
|
|
||||||
import totoro.ocelot.brain.entity.traits.{DiskManaged, Entity, Inventory}
|
|
||||||
import totoro.ocelot.brain.util.Tier
|
|
||||||
import totoro.ocelot.brain.util.Tier.Tier
|
|
||||||
|
|
||||||
class DiskSlot(owner: Inventory#Slot, val tier: Tier) extends InventorySlot[HDDManaged](owner) with DiskOrFloppySlot {
|
|
||||||
override def itemIcon: Option[IconDef] = item.map(disk => Icons.HardDiskDrive(disk.tier))
|
|
||||||
|
|
||||||
override def icon: IconDef = Icons.HddIcon
|
|
||||||
override def tierIcon: Option[IconDef] = Some(Icons.TierIcon(tier))
|
|
||||||
|
|
||||||
override def fillLmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
for (tier <- Tier.One to Tier.Three if this.tier >= tier) {
|
|
||||||
menu.addEntry(new ContextMenuEntry(s"HDD (${tier.label})",
|
|
||||||
() => item = new HDDManaged(tier),
|
|
||||||
icon = Some(Icons.HardDiskDrive(tier))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def lmbMenuEnabled: Boolean = true
|
|
||||||
|
|
||||||
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
addSetDirectoryEntryToRmbMenu(menu, this.asInstanceOf[InventorySlot[DiskManaged with Entity]])
|
|
||||||
|
|
||||||
super.fillRmbMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def tooltipLine1Text: String = getTooltipDeviceInfoText(item.get.fileSystem, item.get.tier)
|
|
||||||
}
|
|
||||||
@ -1,102 +0,0 @@
|
|||||||
package ocelot.desktop.ui.widget.slot
|
|
||||||
|
|
||||||
import ocelot.desktop.OcelotDesktop.showFileChooserDialog
|
|
||||||
import ocelot.desktop.color.Color
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuSubmenu}
|
|
||||||
import ocelot.desktop.ui.widget.{InputDialog, Label, Widget}
|
|
||||||
import totoro.ocelot.brain.entity.EEPROM
|
|
||||||
import totoro.ocelot.brain.entity.traits.Inventory
|
|
||||||
import totoro.ocelot.brain.loot.Loot
|
|
||||||
|
|
||||||
import java.net.{MalformedURLException, URL}
|
|
||||||
import javax.swing.JFileChooser
|
|
||||||
import scala.util.Try
|
|
||||||
|
|
||||||
class EEPROMSlot(owner: Inventory#Slot) extends InventorySlot[EEPROM](owner) {
|
|
||||||
override def itemIcon: Option[IconDef] = item.map(_ => Icons.Eeprom)
|
|
||||||
|
|
||||||
override def icon: IconDef = Icons.EepromIcon
|
|
||||||
|
|
||||||
override def lmbMenuEnabled: Boolean = true
|
|
||||||
|
|
||||||
override def fillLmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
menu.addEntry(new ContextMenuEntry("Lua BIOS",
|
|
||||||
() => item = Loot.LuaBiosEEPROM.create(),
|
|
||||||
icon = Some(Icons.Eeprom)
|
|
||||||
))
|
|
||||||
|
|
||||||
menu.addEntry(new ContextMenuEntry("AdvLoader",
|
|
||||||
() => item = Loot.AdvLoaderEEPROM.create(),
|
|
||||||
icon = Some(Icons.Eeprom)
|
|
||||||
))
|
|
||||||
|
|
||||||
menu.addEntry(new ContextMenuEntry("Cyan BIOS",
|
|
||||||
() => item = Loot.CyanBIOSEEPROM.create(),
|
|
||||||
icon = Some(Icons.Eeprom)
|
|
||||||
))
|
|
||||||
|
|
||||||
menu.addEntry(new ContextMenuEntry("Empty",
|
|
||||||
() => item = new EEPROM,
|
|
||||||
icon = Some(Icons.Eeprom)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
val dataSourceMenu = new ContextMenuSubmenu("External data source")
|
|
||||||
|
|
||||||
dataSourceMenu.addEntry(new ContextMenuEntry(
|
|
||||||
"Local file",
|
|
||||||
() => showFileChooserDialog(JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY) { file =>
|
|
||||||
Try {
|
|
||||||
if (file.isDefined)
|
|
||||||
item.get.codePath = Some(file.get.toPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
))
|
|
||||||
|
|
||||||
dataSourceMenu.addEntry(new ContextMenuEntry("File via URL", () =>
|
|
||||||
new InputDialog(
|
|
||||||
title = "File via URL",
|
|
||||||
text => item.get.codeURL = Some(new URL(text)),
|
|
||||||
inputValidator = text => {
|
|
||||||
try {
|
|
||||||
new URL(text)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
case _: MalformedURLException => false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
).show()
|
|
||||||
))
|
|
||||||
|
|
||||||
if (item.get.codePath.isDefined || item.get.codeURL.isDefined)
|
|
||||||
dataSourceMenu.addEntry(new ContextMenuEntry("Detach", () => item.get.codeBytes = Some(Array.empty[Byte])))
|
|
||||||
|
|
||||||
menu.addEntry(dataSourceMenu)
|
|
||||||
|
|
||||||
super.fillRmbMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def tooltipLine1Text: String = getTooltipSuffixedText(getTooltipDeviceInfoText(item.get), item.get.label)
|
|
||||||
|
|
||||||
override def tooltipChildrenAdder(inner: Widget): Unit = {
|
|
||||||
super.tooltipChildrenAdder(inner)
|
|
||||||
|
|
||||||
if (item.get.codePath.isEmpty && item.get.codeURL.isEmpty)
|
|
||||||
return
|
|
||||||
|
|
||||||
inner.children :+= new Label {
|
|
||||||
override def text: String = {
|
|
||||||
if (item.isDefined) {
|
|
||||||
if (item.get.codePath.isDefined) s"Source path: ${item.get.codePath.get.toString}"
|
|
||||||
else if (item.get.codeURL.isDefined) s"Source URL: ${item.get.codeURL.get.toString}"
|
|
||||||
else ""
|
|
||||||
} else ""
|
|
||||||
}
|
|
||||||
|
|
||||||
override def color: Color = Color.Grey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ocelot.desktop.ui.widget.slot.reimpl
|
package ocelot.desktop.ui.widget.slot
|
||||||
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
import ocelot.desktop.graphics.{IconDef, Icons}
|
||||||
import ocelot.desktop.inventory.Inventory
|
import ocelot.desktop.inventory.Inventory
|
||||||
@ -1,64 +0,0 @@
|
|||||||
package ocelot.desktop.ui.widget.slot
|
|
||||||
|
|
||||||
import ocelot.desktop.audio.{SoundBuffers, SoundCategory, SoundSource}
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
|
||||||
import totoro.ocelot.brain.entity.FloppyManaged
|
|
||||||
import totoro.ocelot.brain.entity.traits.{DiskManaged, Entity, Floppy, Inventory}
|
|
||||||
import totoro.ocelot.brain.loot.Loot
|
|
||||||
import totoro.ocelot.brain.loot.Loot.LootFloppy
|
|
||||||
import totoro.ocelot.brain.util.DyeColor
|
|
||||||
|
|
||||||
class FloppySlot(owner: Inventory#Slot) extends InventorySlot[Floppy](owner) with DiskOrFloppySlot {
|
|
||||||
private val soundFloppyInsert = SoundSource.fromBuffer(SoundBuffers.MachineFloppyInsert, SoundCategory.Environment)
|
|
||||||
private val soundFloppyEject = SoundSource.fromBuffer(SoundBuffers.MachineFloppyEject, SoundCategory.Environment)
|
|
||||||
|
|
||||||
override def itemIcon: Option[IconDef] = item.map(fl => Icons.FloppyDisk(fl.color))
|
|
||||||
|
|
||||||
override def icon: IconDef = Icons.FloppyIcon
|
|
||||||
|
|
||||||
override def fillLmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
for (f <- FloppySlot.FloppyFactories) {
|
|
||||||
menu.addEntry(new ContextMenuEntry(f.name,
|
|
||||||
f.create,
|
|
||||||
icon = Some(Icons.FloppyDisk(f.color))))
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.addEntry(new ContextMenuEntry("Empty",
|
|
||||||
() => item = new FloppyManaged(None, DyeColor.Gray),
|
|
||||||
icon = Some(Icons.FloppyDisk(DyeColor.Gray))))
|
|
||||||
}
|
|
||||||
|
|
||||||
override def lmbMenuEnabled: Boolean = true
|
|
||||||
|
|
||||||
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
item match {
|
|
||||||
case Some(_: LootFloppy) =>
|
|
||||||
// don't allow mounting a directory for loot floppies (it's just too weird)
|
|
||||||
|
|
||||||
case Some(_: FloppyManaged) =>
|
|
||||||
addSetDirectoryEntryToRmbMenu(menu, this.asInstanceOf[InventorySlot[DiskManaged with Entity]])
|
|
||||||
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
|
|
||||||
super.fillRmbMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onAdded(item: Floppy): Unit = {
|
|
||||||
super.onAdded(item)
|
|
||||||
soundFloppyInsert.play()
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onRemoved(item: Floppy): Unit = {
|
|
||||||
super.onRemoved(item)
|
|
||||||
soundFloppyEject.play()
|
|
||||||
}
|
|
||||||
|
|
||||||
override def tooltipLine1Text: String = item.get.label.labelOption.getOrElse("Floppy Disk")
|
|
||||||
}
|
|
||||||
|
|
||||||
object FloppySlot {
|
|
||||||
private val FloppyFactories = Array(Loot.OpenOsFloppy, Loot.Plan9kFloppy, Loot.OPPMFloppy,
|
|
||||||
Loot.OpenLoaderFloppy, Loot.NetworkFloppy, Loot.IrcFloppy, Loot.DataFloppy, Loot.HpmFloppy)
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ocelot.desktop.ui.widget.slot.reimpl
|
package ocelot.desktop.ui.widget.slot
|
||||||
|
|
||||||
import ocelot.desktop.audio.{SoundBuffers, SoundCategory, SoundSource}
|
import ocelot.desktop.audio.{SoundBuffers, SoundCategory, SoundSource}
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
import ocelot.desktop.graphics.{IconDef, Icons}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ocelot.desktop.ui.widget.slot.reimpl
|
package ocelot.desktop.ui.widget.slot
|
||||||
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
import ocelot.desktop.graphics.{IconDef, Icons}
|
||||||
import ocelot.desktop.inventory.Inventory
|
import ocelot.desktop.inventory.Inventory
|
||||||
@ -1,127 +0,0 @@
|
|||||||
package ocelot.desktop.ui.widget.slot
|
|
||||||
|
|
||||||
import ocelot.desktop.color.Color
|
|
||||||
import ocelot.desktop.geometry.Padding2D
|
|
||||||
import ocelot.desktop.ui.UiHandler
|
|
||||||
import ocelot.desktop.ui.layout.LinearLayout
|
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
|
||||||
import ocelot.desktop.ui.widget.tooltip.Tooltip
|
|
||||||
import ocelot.desktop.ui.widget.{Label, PaddingBox, Widget}
|
|
||||||
import ocelot.desktop.util.Orientation
|
|
||||||
import totoro.ocelot.brain.entity.HDDManaged
|
|
||||||
import totoro.ocelot.brain.entity.traits.{DeviceInfo, Entity, Environment, Inventory, Tiered}
|
|
||||||
import totoro.ocelot.brain.util.Tier
|
|
||||||
import totoro.ocelot.brain.util.Tier.Tier
|
|
||||||
|
|
||||||
abstract class InventorySlot[T <: Entity](val owner: Inventory#Slot) extends SlotWidget[T] {
|
|
||||||
reloadItem()
|
|
||||||
|
|
||||||
override def onAdded(item: T): Unit = {
|
|
||||||
super.onAdded(item)
|
|
||||||
owner.put(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onRemoved(item: T): Unit = {
|
|
||||||
super.onRemoved(item)
|
|
||||||
owner.remove()
|
|
||||||
}
|
|
||||||
|
|
||||||
override def fillRmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
item match {
|
|
||||||
case Some(env: Environment) =>
|
|
||||||
menu.addEntry(new ContextMenuEntry("Copy address", () => {
|
|
||||||
UiHandler.clipboard = env.node.address
|
|
||||||
}))
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
super.fillRmbMenu(menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
// --------------------------- Tooltip ---------------------------
|
|
||||||
|
|
||||||
private var tooltip: Option[Tooltip] = None
|
|
||||||
|
|
||||||
def tooltipLine1Color: Color = item match {
|
|
||||||
case Some(tiered: Tiered) =>
|
|
||||||
tiered.tier match {
|
|
||||||
case Tier.Two => Color.Yellow
|
|
||||||
case Tier.Three => Color.Cyan
|
|
||||||
// TODO: creative???
|
|
||||||
case _ => Color.White
|
|
||||||
}
|
|
||||||
case _ => Color.White
|
|
||||||
}
|
|
||||||
|
|
||||||
final protected def getTooltipSuffixedText(part1: String, part2: String): String = s"$part1 ($part2)"
|
|
||||||
final protected def getTooltipTieredText(tier: Tier): String = tier.label
|
|
||||||
final protected def getTooltipDeviceInfoText(deviceInfo: DeviceInfo): String =
|
|
||||||
deviceInfo.getDeviceInfo(DeviceInfo.DeviceAttribute.Description)
|
|
||||||
final protected def getTooltipDeviceInfoText(deviceInfo: DeviceInfo, part2: String): String =
|
|
||||||
getTooltipSuffixedText(getTooltipDeviceInfoText(deviceInfo), part2)
|
|
||||||
final protected def getTooltipDeviceInfoText(deviceInfo: DeviceInfo, tier: Tier): String =
|
|
||||||
getTooltipDeviceInfoText(deviceInfo, getTooltipTieredText(tier))
|
|
||||||
|
|
||||||
def tooltipLine1Text: String = item.get match {
|
|
||||||
case deviceInfoTiered: DeviceInfo with Tiered =>
|
|
||||||
getTooltipDeviceInfoText(deviceInfoTiered, deviceInfoTiered.tier)
|
|
||||||
case deviceInfo: DeviceInfo =>
|
|
||||||
deviceInfo.getDeviceInfo(DeviceInfo.DeviceAttribute.Description)
|
|
||||||
case _ =>
|
|
||||||
""
|
|
||||||
}
|
|
||||||
|
|
||||||
def tooltipChildrenAdder(inner: Widget): Unit = {
|
|
||||||
inner.children :+= new Label {
|
|
||||||
override def text: String = tooltipLine1Text
|
|
||||||
override def color: Color = tooltipLine1Color
|
|
||||||
}
|
|
||||||
|
|
||||||
item match {
|
|
||||||
case Some(environment: Environment) =>
|
|
||||||
inner.children :+= new Label {
|
|
||||||
override def text: String = s"Address: ${environment.node.address}"
|
|
||||||
override def color: Color = Color.Grey
|
|
||||||
}
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
|
|
||||||
item match {
|
|
||||||
case Some(hddManaged: HDDManaged) =>
|
|
||||||
if (hddManaged.customRealPath.isDefined) {
|
|
||||||
inner.children :+= new Label {
|
|
||||||
override def text: String = s"Source path: ${hddManaged.customRealPath.get}"
|
|
||||||
override def color: Color = Color.Grey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case _ =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onHoverEnter(): Unit = {
|
|
||||||
super.onHoverEnter()
|
|
||||||
|
|
||||||
// Showing tooltip only if item is present in slot
|
|
||||||
if (item.isEmpty)
|
|
||||||
return
|
|
||||||
|
|
||||||
tooltip = Some(new Tooltip())
|
|
||||||
|
|
||||||
val inner: Widget = new Widget {
|
|
||||||
override val layout = new LinearLayout(this, orientation = Orientation.Vertical)
|
|
||||||
}
|
|
||||||
|
|
||||||
tooltipChildrenAdder(inner)
|
|
||||||
|
|
||||||
tooltip.get.children :+= new PaddingBox(inner, Padding2D.equal(5))
|
|
||||||
|
|
||||||
root.get.tooltipPool.addTooltip(tooltip.get)
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onHoverLeave(): Unit = {
|
|
||||||
super.onHoverLeave()
|
|
||||||
|
|
||||||
tooltip.foreach(root.get.tooltipPool.closeTooltip(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
def reloadItem(): Unit = _item = owner.get.map(_.asInstanceOf[T])
|
|
||||||
}
|
|
||||||
@ -3,7 +3,6 @@ package ocelot.desktop.ui.widget.slot
|
|||||||
import ocelot.desktop.inventory.item._
|
import ocelot.desktop.inventory.item._
|
||||||
import ocelot.desktop.inventory.{Item, ItemFactory}
|
import ocelot.desktop.inventory.{Item, ItemFactory}
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuSubmenu}
|
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuSubmenu}
|
||||||
import ocelot.desktop.ui.widget.slot.reimpl.SlotWidget
|
|
||||||
import totoro.ocelot.brain.loot.Loot
|
import totoro.ocelot.brain.loot.Loot
|
||||||
import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier
|
import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier
|
||||||
import totoro.ocelot.brain.util.{ExtendedTier, Tier}
|
import totoro.ocelot.brain.util.{ExtendedTier, Tier}
|
||||||
|
|||||||
@ -1,39 +0,0 @@
|
|||||||
package ocelot.desktop.ui.widget.slot
|
|
||||||
|
|
||||||
import ocelot.desktop.color.Color
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
|
||||||
import totoro.ocelot.brain.entity.Memory
|
|
||||||
import totoro.ocelot.brain.entity.traits.{Inventory, Tiered}
|
|
||||||
import totoro.ocelot.brain.util.Tier.Tier
|
|
||||||
import totoro.ocelot.brain.util.{ExtendedTier, Tier}
|
|
||||||
|
|
||||||
class MemorySlot(owner: Inventory#Slot, val tier: Tier) extends InventorySlot[Memory](owner) {
|
|
||||||
override def itemIcon: Option[IconDef] = item.map(_.memoryTier).map(Icons.Memory)
|
|
||||||
|
|
||||||
override def icon: IconDef = Icons.MemoryIcon
|
|
||||||
override def tierIcon: Option[IconDef] = Some(Icons.TierIcon(tier))
|
|
||||||
|
|
||||||
override def fillLmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
for (tier <- ExtendedTier.One to ExtendedTier.ThreeHalf if this.tier >= tier.toTier) {
|
|
||||||
menu.addEntry(new ContextMenuEntry(s"RAM (${tier.label})",
|
|
||||||
() => item = new Memory(tier),
|
|
||||||
icon = Some(Icons.Memory(tier))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override def lmbMenuEnabled: Boolean = true
|
|
||||||
|
|
||||||
override def tooltipLine1Color: Color = item.get match {
|
|
||||||
case tiered: Tiered => tiered.tier match {
|
|
||||||
case Tier.One => Color.White
|
|
||||||
case Tier.Two => Color.Yellow
|
|
||||||
case Tier.Three => Color.Cyan
|
|
||||||
case _ => Color.Cyan
|
|
||||||
}
|
|
||||||
|
|
||||||
case _ => Color.White
|
|
||||||
}
|
|
||||||
|
|
||||||
override def tooltipLine1Text: String = getTooltipDeviceInfoText(item.get, item.get.memoryTier.label)
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package ocelot.desktop.ui.widget.slot.reimpl
|
package ocelot.desktop.ui.widget.slot
|
||||||
|
|
||||||
import ocelot.desktop.graphics.{IconDef, Icons}
|
import ocelot.desktop.graphics.{IconDef, Icons}
|
||||||
import ocelot.desktop.inventory.Inventory
|
import ocelot.desktop.inventory.Inventory
|
||||||
@ -2,84 +2,151 @@ package ocelot.desktop.ui.widget.slot
|
|||||||
|
|
||||||
import ocelot.desktop.audio.SoundSources
|
import ocelot.desktop.audio.SoundSources
|
||||||
import ocelot.desktop.geometry.Size2D
|
import ocelot.desktop.geometry.Size2D
|
||||||
import ocelot.desktop.graphics.{Graphics, IconDef}
|
import ocelot.desktop.graphics.{Graphics, IconDef, Icons}
|
||||||
|
import ocelot.desktop.inventory.{Inventory, Item, ItemFactory}
|
||||||
import ocelot.desktop.ui.event.handlers.{ClickHandler, HoverHandler}
|
import ocelot.desktop.ui.event.handlers.{ClickHandler, HoverHandler}
|
||||||
import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent}
|
import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent}
|
||||||
import ocelot.desktop.ui.widget.Widget
|
import ocelot.desktop.ui.widget.Widget
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
||||||
|
import ocelot.desktop.ui.widget.tooltip.Tooltip
|
||||||
|
import totoro.ocelot.brain.util.Tier
|
||||||
|
import totoro.ocelot.brain.util.Tier.Tier
|
||||||
|
|
||||||
abstract class SlotWidget[T] extends Widget with ClickHandler with HoverHandler {
|
import scala.math.Ordering.Implicits.infixOrderingOps
|
||||||
def icon: IconDef
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
def tierIcon: Option[IconDef] = None
|
class SlotWidget[I <: Item](private val slot: Inventory#Slot)(implicit slotItemTag: ClassTag[I])
|
||||||
|
extends Widget
|
||||||
|
with ClickHandler
|
||||||
|
with HoverHandler {
|
||||||
|
|
||||||
def itemIcon: Option[IconDef] = None
|
slotWidget =>
|
||||||
|
|
||||||
def onRemoved(item: T): Unit = {}
|
// NOTE: this must remain as a separate object
|
||||||
|
// (i. e. don't you dare inline it into the addObserver call below):
|
||||||
def onAdded(item: T): Unit = {}
|
// this is the only strong reference to the observer
|
||||||
|
private val observer = new Inventory.SlotObserver {
|
||||||
def fillLmbMenu(menu: ContextMenu): Unit = {}
|
override def onItemAdded(): Unit = {
|
||||||
|
slotWidget.onItemAdded()
|
||||||
def fillRmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
menu.addEntry(new ContextMenuEntry("Remove", () => item = None, sound = SoundSources.InterfaceClickLow))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def lmbMenuEnabled: Boolean = false
|
override def onItemRemoved(removedItem: Item, replacedBy: Option[Item]): Unit = {
|
||||||
|
slotWidget.onItemRemoved(removedItem.asInstanceOf[I], replacedBy.map(_.asInstanceOf[I]))
|
||||||
def rmbMenuEnabled: Boolean = _item.isDefined
|
|
||||||
|
|
||||||
final var _item: Option[T] = None
|
|
||||||
|
|
||||||
final def item_=(v: Option[T]): Unit = {
|
|
||||||
if (_item.isDefined)
|
|
||||||
onRemoved(_item.get)
|
|
||||||
|
|
||||||
_item = v
|
|
||||||
|
|
||||||
if (v.isDefined)
|
|
||||||
onAdded(v.get)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final def item_=(v: T): Unit = item = Some(v)
|
override def onItemSpecificEvent(payload: AnyRef): Unit = {
|
||||||
|
slotWidget.onItemSpecificEvent(payload)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final def item: Option[T] = _item
|
slot.addObserver(observer)
|
||||||
|
|
||||||
final override def minimumSize: Size2D = Size2D(36, 36)
|
def dispose(): Unit = {
|
||||||
final override def maximumSize: Size2D = minimumSize
|
closeTooltip()
|
||||||
|
slot.removeObserver(observer)
|
||||||
|
}
|
||||||
|
|
||||||
final override def receiveMouseEvents: Boolean = true
|
def ghostIcon: Option[IconDef] = None
|
||||||
|
|
||||||
|
def slotTier: Option[Tier] = None
|
||||||
|
|
||||||
|
def tierIcon: Option[IconDef] = slotTier.map(Icons.TierIcon)
|
||||||
|
|
||||||
|
def itemIcon: Option[IconDef] = item.map(_.icon)
|
||||||
|
|
||||||
|
def item: Option[I] = slot.get.map(_.asInstanceOf[I])
|
||||||
|
|
||||||
|
def item_=(item: Option[I]): Unit = {
|
||||||
|
slot.set(item.map(_.asInstanceOf[slot.inventory.I]))
|
||||||
|
}
|
||||||
|
|
||||||
|
def item_=(item: I): Unit = {
|
||||||
|
slot.put(item.asInstanceOf[slot.inventory.I])
|
||||||
|
}
|
||||||
|
|
||||||
|
def isItemAccepted(factory: ItemFactory): Boolean = {
|
||||||
|
// yes, you can compare Options. isn't it nice?
|
||||||
|
slotItemTag.runtimeClass.isAssignableFrom(factory.itemClass) && factory.tier.map(_ min Tier.Three) <= slotTier
|
||||||
|
}
|
||||||
|
|
||||||
|
protected def onItemAdded(): Unit = {}
|
||||||
|
|
||||||
|
protected def onItemRemoved(removedItem: I, replacedBy: Option[I]): Unit = {
|
||||||
|
closeTooltip()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected def onItemSpecificEvent(payload: AnyRef): Unit = {}
|
||||||
|
|
||||||
|
final override val minimumSize, maximumSize = Size2D(36, 36)
|
||||||
|
final override val receiveMouseEvents: Boolean = true
|
||||||
|
|
||||||
|
protected def lmbMenuEnabled: Boolean = true
|
||||||
|
|
||||||
|
protected def rmbMenuEnabled: Boolean = item.nonEmpty
|
||||||
|
|
||||||
|
protected def fillRmbMenu(menu: ContextMenu): Unit = {
|
||||||
|
for (item <- item) {
|
||||||
|
item.fillRmbMenu(menu)
|
||||||
|
menu.addEntry(
|
||||||
|
ContextMenuEntry("Remove", sound = SoundSources.InterfaceClickLow) {
|
||||||
|
slot.remove()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var _tooltip: Option[Tooltip] = None
|
||||||
|
|
||||||
|
def onHoverEnter(): Unit = {
|
||||||
|
for (item <- item) {
|
||||||
|
// just in case
|
||||||
|
// closeTooltip()
|
||||||
|
|
||||||
|
val tooltip = item.tooltip
|
||||||
|
_tooltip = Some(tooltip)
|
||||||
|
root.get.tooltipPool.addTooltip(tooltip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def onHoverLeave(): Unit = {
|
||||||
|
closeTooltip()
|
||||||
|
}
|
||||||
|
|
||||||
|
private def closeTooltip(): Unit = {
|
||||||
|
for (tooltip <- _tooltip) {
|
||||||
|
root.get.tooltipPool.closeTooltip(tooltip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
eventHandlers += {
|
eventHandlers += {
|
||||||
case ClickEvent(MouseEvent.Button.Left, _) if lmbMenuEnabled =>
|
case ClickEvent(MouseEvent.Button.Left, _) if lmbMenuEnabled =>
|
||||||
val menu = new ContextMenu
|
root.get.contextMenus.open(new ItemChooser(this))
|
||||||
fillLmbMenu(menu)
|
|
||||||
root.get.contextMenus.open(menu)
|
|
||||||
case ClickEvent(MouseEvent.Button.Right, _) if rmbMenuEnabled =>
|
case ClickEvent(MouseEvent.Button.Right, _) if rmbMenuEnabled =>
|
||||||
val menu = new ContextMenu
|
val menu = new ContextMenu
|
||||||
fillRmbMenu(menu)
|
fillRmbMenu(menu)
|
||||||
root.get.contextMenus.open(menu)
|
root.get.contextMenus.open(menu)
|
||||||
case HoverEvent(state) =>
|
|
||||||
if (state == HoverEvent.State.Enter)
|
case HoverEvent(HoverEvent.State.Enter) => onHoverEnter()
|
||||||
onHoverEnter()
|
case HoverEvent(HoverEvent.State.Leave) => onHoverLeave()
|
||||||
else
|
|
||||||
onHoverLeave()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def onHoverEnter(): Unit = {}
|
|
||||||
|
|
||||||
def onHoverLeave(): Unit = {}
|
|
||||||
|
|
||||||
final override def draw(g: Graphics): Unit = {
|
final override def draw(g: Graphics): Unit = {
|
||||||
g.sprite("EmptySlot", bounds)
|
g.sprite("EmptySlot", bounds)
|
||||||
|
|
||||||
val iconBounds = bounds.inflate(-2)
|
val iconBounds = bounds.inflate(-2)
|
||||||
|
|
||||||
if (itemIcon.isDefined) {
|
itemIcon match {
|
||||||
g.sprite(itemIcon.get, iconBounds)
|
case Some(itemIcon) => g.sprite(itemIcon, iconBounds)
|
||||||
} else {
|
|
||||||
if (tierIcon.isDefined) g.sprite(tierIcon.get, iconBounds)
|
case None =>
|
||||||
g.sprite(icon, iconBounds)
|
for (tierIcon <- tierIcon) {
|
||||||
|
g.sprite(tierIcon, iconBounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ghostIcon <- ghostIcon) {
|
||||||
|
g.sprite(ghostIcon, iconBounds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,153 +0,0 @@
|
|||||||
package ocelot.desktop.ui.widget.slot.reimpl
|
|
||||||
|
|
||||||
import ocelot.desktop.audio.SoundSources
|
|
||||||
import ocelot.desktop.geometry.Size2D
|
|
||||||
import ocelot.desktop.graphics.{Graphics, IconDef, Icons}
|
|
||||||
import ocelot.desktop.inventory.{Inventory, Item, ItemFactory}
|
|
||||||
import ocelot.desktop.ui.event.handlers.{ClickHandler, HoverHandler}
|
|
||||||
import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent}
|
|
||||||
import ocelot.desktop.ui.widget.Widget
|
|
||||||
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
|
|
||||||
import ocelot.desktop.ui.widget.slot.ItemChooser
|
|
||||||
import ocelot.desktop.ui.widget.tooltip.Tooltip
|
|
||||||
import totoro.ocelot.brain.util.Tier
|
|
||||||
import totoro.ocelot.brain.util.Tier.Tier
|
|
||||||
|
|
||||||
import scala.math.Ordering.Implicits.infixOrderingOps
|
|
||||||
import scala.reflect.ClassTag
|
|
||||||
|
|
||||||
class SlotWidget[I <: Item](private val slot: Inventory#Slot)(implicit slotItemTag: ClassTag[I])
|
|
||||||
extends Widget
|
|
||||||
with ClickHandler
|
|
||||||
with HoverHandler {
|
|
||||||
|
|
||||||
slotWidget =>
|
|
||||||
|
|
||||||
// NOTE: this must remain as a separate object
|
|
||||||
// (i. e. don't you dare inline it into the addObserver call below):
|
|
||||||
// this is the only strong reference to the observer
|
|
||||||
private val observer = new Inventory.SlotObserver {
|
|
||||||
override def onItemAdded(): Unit = {
|
|
||||||
slotWidget.onItemAdded()
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onItemRemoved(removedItem: Item, replacedBy: Option[Item]): Unit = {
|
|
||||||
slotWidget.onItemRemoved(removedItem.asInstanceOf[I], replacedBy.map(_.asInstanceOf[I]))
|
|
||||||
}
|
|
||||||
|
|
||||||
override def onItemSpecificEvent(payload: AnyRef): Unit = {
|
|
||||||
slotWidget.onItemSpecificEvent(payload)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
slot.addObserver(observer)
|
|
||||||
|
|
||||||
def dispose(): Unit = {
|
|
||||||
closeTooltip()
|
|
||||||
slot.removeObserver(observer)
|
|
||||||
}
|
|
||||||
|
|
||||||
def ghostIcon: Option[IconDef] = None
|
|
||||||
|
|
||||||
def slotTier: Option[Tier] = None
|
|
||||||
|
|
||||||
def tierIcon: Option[IconDef] = slotTier.map(Icons.TierIcon)
|
|
||||||
|
|
||||||
def itemIcon: Option[IconDef] = item.map(_.icon)
|
|
||||||
|
|
||||||
def item: Option[I] = slot.get.map(_.asInstanceOf[I])
|
|
||||||
|
|
||||||
def item_=(item: Option[I]): Unit = {
|
|
||||||
slot.set(item.map(_.asInstanceOf[slot.inventory.I]))
|
|
||||||
}
|
|
||||||
|
|
||||||
def item_=(item: I): Unit = {
|
|
||||||
slot.put(item.asInstanceOf[slot.inventory.I])
|
|
||||||
}
|
|
||||||
|
|
||||||
def isItemAccepted(factory: ItemFactory): Boolean = {
|
|
||||||
// yes, you can compare Options. isn't it nice?
|
|
||||||
slotItemTag.runtimeClass.isAssignableFrom(factory.itemClass) && factory.tier.map(_ min Tier.Three) <= slotTier
|
|
||||||
}
|
|
||||||
|
|
||||||
protected def onItemAdded(): Unit = {}
|
|
||||||
|
|
||||||
protected def onItemRemoved(removedItem: I, replacedBy: Option[I]): Unit = {
|
|
||||||
closeTooltip()
|
|
||||||
}
|
|
||||||
|
|
||||||
protected def onItemSpecificEvent(payload: AnyRef): Unit = {}
|
|
||||||
|
|
||||||
final override val minimumSize, maximumSize = Size2D(36, 36)
|
|
||||||
final override val receiveMouseEvents: Boolean = true
|
|
||||||
|
|
||||||
protected def lmbMenuEnabled: Boolean = true
|
|
||||||
|
|
||||||
protected def rmbMenuEnabled: Boolean = item.nonEmpty
|
|
||||||
|
|
||||||
protected def fillRmbMenu(menu: ContextMenu): Unit = {
|
|
||||||
for (item <- item) {
|
|
||||||
item.fillRmbMenu(menu)
|
|
||||||
menu.addEntry(
|
|
||||||
ContextMenuEntry("Remove", sound = SoundSources.InterfaceClickLow) {
|
|
||||||
slot.remove()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var _tooltip: Option[Tooltip] = None
|
|
||||||
|
|
||||||
def onHoverEnter(): Unit = {
|
|
||||||
for (item <- item) {
|
|
||||||
// just in case
|
|
||||||
// closeTooltip()
|
|
||||||
|
|
||||||
val tooltip = item.tooltip
|
|
||||||
_tooltip = Some(tooltip)
|
|
||||||
root.get.tooltipPool.addTooltip(tooltip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def onHoverLeave(): Unit = {
|
|
||||||
closeTooltip()
|
|
||||||
}
|
|
||||||
|
|
||||||
private def closeTooltip(): Unit = {
|
|
||||||
for (tooltip <- _tooltip) {
|
|
||||||
root.get.tooltipPool.closeTooltip(tooltip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eventHandlers += {
|
|
||||||
case ClickEvent(MouseEvent.Button.Left, _) if lmbMenuEnabled =>
|
|
||||||
root.get.contextMenus.open(new ItemChooser(this))
|
|
||||||
|
|
||||||
case ClickEvent(MouseEvent.Button.Right, _) if rmbMenuEnabled =>
|
|
||||||
val menu = new ContextMenu
|
|
||||||
fillRmbMenu(menu)
|
|
||||||
root.get.contextMenus.open(menu)
|
|
||||||
|
|
||||||
case HoverEvent(HoverEvent.State.Enter) => onHoverEnter()
|
|
||||||
case HoverEvent(HoverEvent.State.Leave) => onHoverLeave()
|
|
||||||
}
|
|
||||||
|
|
||||||
final override def draw(g: Graphics): Unit = {
|
|
||||||
g.sprite("EmptySlot", bounds)
|
|
||||||
|
|
||||||
val iconBounds = bounds.inflate(-2)
|
|
||||||
|
|
||||||
itemIcon match {
|
|
||||||
case Some(itemIcon) => g.sprite(itemIcon, iconBounds)
|
|
||||||
|
|
||||||
case None =>
|
|
||||||
for (tierIcon <- tierIcon) {
|
|
||||||
g.sprite(tierIcon, iconBounds)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ghostIcon <- ghostIcon) {
|
|
||||||
g.sprite(ghostIcon, iconBounds)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user