Add localization support

This commit is contained in:
UnicornFreedom 2025-03-01 12:18:08 +01:00
parent 0f333a6f26
commit fb3d510b0e
124 changed files with 1523 additions and 550 deletions

@ -1 +1 @@
Subproject commit 4b2d2fcec19f8e238dd1c4bdb09d42b11e9bb6e6 Subproject commit 6aaded3ec6405c442fc7fec4381213494d20d162

View File

@ -24,6 +24,8 @@ Tier3 = #c354cd
Label = #333333 Label = #333333
LabelError = #aa0000 LabelError = #aa0000
LabelUpdateAvailable = #33aa33
Scrollbar = #e5e5e526 Scrollbar = #e5e5e526
ScrollbarThumb = #cc3f72 ScrollbarThumb = #cc3f72

View File

@ -0,0 +1,359 @@
# This is the English master file for localizations. It will always be the most
# up-to-date version, so other localizations should be based on this one.
# Use [nl] to for a line break.
# Buttons
button.ok = Ok
button.cancel = Cancel
button.yes = Yes
button.no = No
button.proceed = Proceed
button.download = Download
button.apply = Apply
# Loading screen
label.loading.brain = Initializing brain...
label.loading.gui = Initializing GUI...
label.loading.resources = Loading resources...
label.loading.workspace = Loading workspace...
# Titles
title.profiler = Profiler
# Windows
label.window.computer = Computer
label.window.server = Server
label.window.microcontroller = Microcontroller
label.window.computer.toggleStats = Toggle computer usage histogram
label.window.computer.componentUsage = Component usage
label.window.computer.memoryUsage = Memory
label.window.computer.cpuUsage = CPU
label.window.computer.callBudget = Call budget
label.window.disk.used = Used
label.window.disk.capacity = Capacity
label.window.disk.label = Label
label.window.disk.makeReadOnly = Make read-only
label.window.disk.make.managed = Make managed
label.window.disk.make.unmanaged = Make unmanaged
label.window.ocelot.messages = Messages
label.window.ocelot.limit = Limit
label.window.ocelot.scrollToEnd = Scroll to end
label.window.ocelot.clear = Clear
label.window.rack.enabled = Enabled
label.window.rack.disabled = Disabled
label.window.raid.warning.addingDisk = Adding a disk wipes it.
label.window.raid.warning.removingDisk = Removing a disk wipes the raid.
label.window.radio.screenColor = Screen color
label.window.radio.screenText = Screen text
label.window.relay.cycleRate = Cycle rate
label.window.relay.packetsPerCycle = Packets / cycle
label.window.relay.queueSize = Queue size
label.window.tapeDrive.unnamedTape = Unnamed tape
label.window.tapeDrive.noTape = No tape
# Menu
label.menu.file = File
label.menu.file.new = New
label.menu.file.open = Open
label.menu.file.save = Save
label.menu.file.saveAs = Save as
label.menu.file.exit = Exit
label.menu.player = Player
label.menu.player.new = Create new
label.menu.player.remove = Remove
label.menu.settings = Settings
label.menu.help = Help
label.menu.help.updates = Check for Updates
label.menu.help.manual = Manual
label.menu.help.about = About
label.menu.copyAddress = Copy address
label.menu.disconnect = Disconnect
label.menu.remove = Remove
label.menu.setLabel = Set label
label.menu.turnOn = Turn on
label.menu.turnOff = Turn off
label.menu.reboot = Reboot
label.menu.ejectFloppy = Eject floppy
label.menu.changeFloppy = Change floppy
label.menu.setFloppy = Set floppy
label.menu.changeSimulationSpeed = Change simulation speed
label.menu.resetSimulationSpeed = Reset simulation speed
label.menu.setup = Set up
label.menu.instrument = Instrument
label.menu.setAspectRatio = Set aspect ratio
label.menu.removeKeyboard = Remove keyboard
label.menu.addKeyboard = Add keyboard
label.menu.changeTier = Change tier
label.menu.eject = Eject
label.menu.setArchitecture = Set architecture
label.menu.currentArchitecture = current
label.menu.externalDataSource = External data source
label.menu.localFile = Local file
label.menu.fileViaUrl = File via URL
label.menu.detach = Detach
label.menu.setDirectory = Set directory
label.menu.changeDirectory = Change directory
label.menu.resetDirectory = Reset directory
label.menu.editDisk = Edit disk
label.menu.setChannel = Set channel
label.menu.openConsole = Open console
label.menu.redstoneIO = Redstone I/O
label.menu.bundledIO = Bundled I/O
label.menu.openCardInterface = Open card interface
# Status bar
label.bar.menu = Menu
label.bar.addNode = Add node
label.bar.moveNode = Move node
label.bar.connectDisconnect = Connect/Disconnect
label.bar.turnServerOnOff = Turn server on/off
label.bar.playSample = Play sample
label.bar.open = Open
label.bar.close = Close
label.bar.closeWindow = Close window
label.bar.rotateView = Rotate view
label.bar.panView = Pan view
label.bar.resetCamera = Reset camera
label.bar.showGrid = Show grid
label.bar.closeSelector = Close selector
label.bar.moveCamera = Move camera
label.bar.scaleScreen = Scale screen
label.bar.scaleScreenMagnify = Scale screen (magnify)
# Settings
label.settings.ui = UI
label.settings.ui.language = Language:
label.settings.ui.pinWindows = Pin newly opened windows
label.settings.ui.fullscreen = Fullscreen mode
label.settings.ui.saveOnExit = Save workspace on exit
label.settings.ui.openLastWorkspace = Re-open last workspace on startup
label.settings.ui.screenPreview = Show previews on screen blocks
label.settings.ui.mipmaps = Enable mipmaps for screen windows
label.settings.ui.festiveDecorations = Enable festive decorations
label.settings.ui.scale = Interface scale
label.settings.ui.tooltipDelay = Tooltip delays:
label.settings.ui.tooltip.items = Items
label.settings.ui.tooltip.ui = UI Elements
label.settings.sound = Sound
label.settings.sound.master = Master volume
label.settings.sound.music = Music blocks volume
label.settings.sound.environment = Environment volume
label.settings.sound.beep = Beep volume
label.settings.sound.ui = Interface volume
label.settings.sound.positional = Use positional sound
label.settings.system = System
label.settings.system.confPath = Set OpenComputers configuration file path:
label.settings.system.confPathPlaceholder = not set / using default OpenComputers configuration
label.settings.system.confSearch = Search for OpenComputers configuration file
label.settings.system.confGenerate = Generate new OpenComputers configuration file in:
label.settings.system.currentDir = Current Directory
label.settings.system.configDir = Config Directory
label.settings.system.customDir = Custom Path
label.settings.system.autosave = Workspace autosave
label.settings.system.autosavePeriod = Workspace autosave period (seconds):
label.settings.system.restart = Restart Ocelot to apply new configuration
# Dialogs
label.dialog.addNewPlayer = Add new player
label.dialog.about.subtitle = OpenComputers Emulator
label.dialog.about.version = Version
label.dialog.about.website = Website
label.dialog.aspect.width = Width:
label.dialog.aspect.height = Height:
label.dialog.speed.msPerTick = Milliseconds per tick:
label.dialog.speed.ticksPerSecond = Ticks per second:
label.dialog.tunnel = Set channel name/code
label.dialog.tunnel.random = Generate random channel name
label.dialog.tunnel.copy = Copy channel name to the clipboard
label.dialog.updates.checking = Checking development news...
label.dialog.updates.release = Release
label.dialog.updates.upToDate = Up to date
label.dialog.updates.releaseUpdateAvailable = New release version is available!
label.dialog.updates.devBuild = Dev build
label.dialog.updates.devUpdateAvailable = New dev build from
label.dialog.updates.unavailable = Ocelot website is unavailable...
label.dialog.updates.checkLogs = Check the log file for a full stacktrace.
# Notifications
notification.saveBeforeExit = Save workspace before exiting?
notification.saveBeforeOpeningNew = Save workspace before opening a new one?
# Ocelot error messages
error.ocelot.cannotOpenSpecifiedWorkspace = Could not open the specified workspace...
error.ocelot.cannotOpenRecentWorkspace = Could not open the recent workspace...
error.ocelot.defaultWorkspaceCreation = I will create a default one
error.ocelot.somethingWentWrong = Something went wrong!
error.ocelot.checkTheLogs = Check the log file for a full stacktrace.
error.ocelot.savePathNotEmpty = Chosen save path is not empty.[nl]Files in the save directory will be included in the workspace.[nl]They may be overwritten, causing loss of data.[nl]Proceed with saving anyway?
error.ocelot.overriding = You are overriding an existing file!
# Computer error codes
Error.NoCPU = No CPU is installed in the computer.
Error.ComponentOverflow = Too many components connected to the computer.
Error.NoRAM = No RAM is installed in the computer.
Error.OutOfMemory = Out of memory.
Error.InternalError = Internal error, please see the log file. This is probably a bug.
# Tooltips
tooltip.address = Address
tooltip.components = Components
tooltip.bytes = bytes
tooltip.bit = bit
tooltip.dataCard.softLimit = Soft limit
tooltip.dataCard.softLimitExplanation = sec slowdown
tooltip.dataCard.hardLimit = Hard limit (fail)
tooltip.disk.missingFloppy = Floppy: none
tooltip.disk.floppy = Floppy
tooltip.disk.label = Label
tooltip.disk.sourcePath = Source path
tooltip.disk.managedMode = Mode: managed
tooltip.disk.unmanagedMode = Mode: unmanaged
tooltip.disk.capacity = Capacity
tooltip.eeprom.sourcePath = Source path
tooltip.eeprom.sourceUrl = Source URL
tooltip.eeprom.code = Code
tooltip.eeprom.data = Data
tooltip.eeprom.data.readonly = Readonly
tooltip.gpu.maxResolution = Max resolution
tooltip.gpu.maxColorDepth = Max color depth
tooltip.gpu.vram = VRAM
tooltip.tunnel.channel = Channel
tooltip.ram.capacity.infinite = Capacity: infinite
tooltip.ram.capacity = Capacity
tooltip.modem.openPortsNone = Open ports: none
tooltip.modem.openPorts = Open ports
tooltip.modem.maxOpenPorts = Max open ports
tooltip.redstone.wakeThreshold = Wake threshold
tooltip.selfDestruct.fuseNotSet = Fuse has not been set
tooltip.selfDestruct.boom = BOOM!
tooltip.tape.label = Label
tooltip.tape.ID = ID
tooltip.tape.size = Size
tooltip.tape.length = Length
# Selector
selector.group.original = Original
selector.group.addons = Addons
selector.group.custom = Custom
# Tiers
tier.one = Tier 1
tier.oneHalf = Tier 1.5
tier.two = Tier 2
tier.twoHalf = Tier 2.5
tier.three = Tier 3
tier.threeHalf = Tier 3.5
tier.creative = Creative
# Directions
direction.up = Up
direction.down = Down
direction.top = Top
direction.bottom = Bottom
direction.left = Left
direction.right = Right
direction.front = Front
direction.back = Back
# Colors
color.white = White
color.orange = Orange
color.magenta = Magenta
color.lightBlue = LightBlue
color.yellow = Yellow
color.lime = Lime
color.pink = Pink
color.gray = Gray
color.silver = Silver
color.cyan = Cyan
color.purple = Purple
color.blue = Blue
color.brown = Brown
color.green = Green
color.red = Red
color.black = Black
# Components
component.APU = APU
component.bundledIO = Bundled I/O
component.cable = Cable
component.camera = Camera
component.camera.notAvailable = <No webcam available>
component.camera.flipHorizontally = Flip image horizontally
component.camera.flipVertically = Flip image horizontally
component.camera.unlimitedCallBudget = Unlimited call budget
component.chest = Chest
component.colorfulLamp = Colorful Lamp
component.componentBus = Component Bus
component.computer = Computer Case
component.CPU = CPU
component.dataCard = Data Card
component.diskDrive = Disk Drive
component.EEPROM = EEPROM
component.filesystem.floppy = Floppy
component.filesystem.floppyDisk = Floppy Disk
component.filesystem.hdd = HDD
component.filesystem.hardDiskDrive = Hard Disk Drive
component.graphicsCard = Graphics Card
component.hologramProjector = Hologram Projector
component.internetCard = Internet Card
component.ironNoteBlock = Iron Note Block
component.microcontroller = Microcontroller
component.modem = Network Card
component.modem.wireless = Wireless Net. Card
component.noteBlock = Note Block
component.noteBlock.bass = Bass (Wood)
component.noteBlock.snare = Snare Drum (Sand)
component.noteBlock.hat = Hi-hat (Glass)
component.noteBlock.basedrum = Bass Drum (Stone)
component.noteBlock.bell = Glockenspiel (Gold)
component.noteBlock.flute = Flute (Clay)
component.noteBlock.chime = Chimes (Packed Ice)
component.noteBlock.guitar = Guitar (Wool)
component.noteBlock.xylophone = Xylophone (Bone)
component.noteBlock.ironXylophone = Vibraphone (Iron)
component.noteBlock.cowBell = Cow Bell (Soul Sand)
component.noteBlock.didgeridoo = Didgeridoo (Pumpkin)
component.noteBlock.bit = Square Wave (Emerald)
component.noteBlock.banjo = Banjo (Hay Bale)
component.noteBlock.pling = Electric Piano (Glowstone)
component.noteBlock.harp = Harp
component.ocelot.block = Ocelot Block
component.ocelot.card = Ocelot Card
component.openFmRadio = OpenFM Radio
component.rack = Rack
component.raid = Raid
component.ram.magical = Magical Memory (Creative)
component.ram = Memory
component.relay = Relay
component.redstoneIO = Redstone I/O
component.redstoneCard = Redstone Card
component.screen = Screen
component.selfDestructingCard = Self-Destructing Card
component.server = Server
component.soundCard = Sound Card
component.tape = Tape
component.tapeDrive = Tape Drive
component.tunnel = Linked Card

View File

@ -0,0 +1,2 @@
en_US = English
ru_RU = Русский

View File

@ -0,0 +1,359 @@
# This is the Russian localization file.
# Use [nl] to for a line break.
# Buttons
button.ok = Ок
button.cancel = Отмена
button.yes = Да
button.no = Нет
button.proceed = Продолжить
button.download = Скачать
button.apply = Применить
# Loading screen
label.loading.brain = Инициализация движка...
label.loading.gui = Инициализация интерфейса...
label.loading.resources = Загрузка ресурсов...
label.loading.workspace = Загрузка проекта...
# Titles
title.profiler = Профайлер
# Windows
label.window.computer = Компьютер
label.window.server = Сервер
label.window.microcontroller = Микроконтроллер
label.window.computer.toggleStats = Открыть статистику использования ресурсов
label.window.computer.componentUsage = Лимит компонентов
label.window.computer.memoryUsage = Оперативная память
label.window.computer.cpuUsage = Процессор
label.window.computer.callBudget = Бюджет вызовов
label.window.disk.used = Занято
label.window.disk.capacity = Размер
label.window.disk.label = Метка
label.window.disk.makeReadOnly = Запретить запись
label.window.disk.make.managed = Файловый режим
label.window.disk.make.unmanaged = Блочный режим
label.window.ocelot.messages = Сообщения
label.window.ocelot.limit = Количество (максимум)
label.window.ocelot.scrollToEnd = Листать в конец
label.window.ocelot.clear = Очистить
label.window.rack.enabled = Включено
label.window.rack.disabled = Выключено
label.window.raid.warning.addingDisk = При добавлении диск очищается.
label.window.raid.warning.removingDisk = При удалении диска стирается весь массив.
label.window.radio.screenColor = Цвет экрана
label.window.radio.screenText = Текст на экране
label.window.relay.cycleRate = Цикличность
label.window.relay.packetsPerCycle = Пакеты / цикл
label.window.relay.queueSize = Размер очереди
label.window.tapeDrive.unnamedTape = Безымянная кассета
label.window.tapeDrive.noTape = Нет кассеты
# Menu
label.menu.file = Файл
label.menu.file.new = Новый
label.menu.file.open = Открыть
label.menu.file.save = Сохранить
label.menu.file.saveAs = Сохранить как
label.menu.file.exit = Выход
label.menu.player = Игрок
label.menu.player.new = Создать
label.menu.player.remove = Удалить
label.menu.settings = Настройки
label.menu.help = Помощь
label.menu.help.updates = Проверить обновления
label.menu.help.manual = Руководство
label.menu.help.about = О программе
label.menu.copyAddress = Скопировать адрес
label.menu.disconnect = Отсоединить
label.menu.remove = Удалить
label.menu.turnOn = Включить
label.menu.turnOff = Выключить
label.menu.reboot = Перезагрузить
label.menu.setLabel = Добавить метку
label.menu.ejectFloppy = Извлечь дискету
label.menu.changeFloppy = Поменять дискету
label.menu.setFloppy = Установить дискету
label.menu.changeSimulationSpeed = Изменить скорость симуляции
label.menu.resetSimulationSpeed = Сбросить скорость симуляции
label.menu.setup = Настроить
label.menu.instrument = Инструмент
label.menu.setAspectRatio = Изменить соотношение сторон
label.menu.removeKeyboard = Удалить клавиатуру
label.menu.addKeyboard = Добавить клавиатуру
label.menu.changeTier = Изменить уровень
label.menu.eject = Извлечь
label.menu.setArchitecture = Задать архитектуру
label.menu.currentArchitecture = текущая
label.menu.externalDataSource = Внешний источник данных
label.menu.localFile = Локальный файл
label.menu.fileViaUrl = Файл через URL
label.menu.detach = Сбросить
label.menu.setDirectory = Указать папку
label.menu.changeDirectory = Изменить папку
label.menu.resetDirectory = Сбросить папку
label.menu.editDisk = Редактировать диск
label.menu.setChannel = Изменить канал
label.menu.openConsole = Открыть консоль
label.menu.redstoneIO = Сигналы красного камня
label.menu.bundledIO = Цветные сигналы
label.menu.openCardInterface = Открыть интерфейс карты
# Status bar
label.bar.menu = Меню
label.bar.addNode = Добавить блок
label.bar.moveNode = Передвинуть блок
label.bar.connectDisconnect = Присоединить/Отсоединить
label.bar.turnServerOnOff = Включить/выключить сервер
label.bar.playSample = Послушать образец
label.bar.open = Открыть
label.bar.close = Закрыть
label.bar.closeWindow = Закрыть окно
label.bar.rotateView = Вращать камеру
label.bar.panView = Перемещать камеру
label.bar.resetCamera = Вернуться в центр
label.bar.showGrid = Показать сетку
label.bar.closeSelector = Закрыть меню блоков
label.bar.moveCamera = Перемещаться по проекту
label.bar.scaleScreen = Уменьшить экран
label.bar.scaleScreenMagnify = Увеличить экран
# Settings
label.settings.ui = Интерфейс
label.settings.ui.language = Язык:
label.settings.ui.pinWindows = Закреплять новые открытые окна
label.settings.ui.fullscreen = Полноэкранный режим
label.settings.ui.saveOnExit = Сохранять проект при выходе
label.settings.ui.openLastWorkspace = Открыть последний проект при запуске Ocelot
label.settings.ui.screenPreview = Показывать превью на блоках экрана
label.settings.ui.mipmaps = Использовать MIP-текстурирование для экранов
label.settings.ui.festiveDecorations = Включить праздничные декорации
label.settings.ui.scale = Масштаб интерфейса
label.settings.ui.tooltipDelay = Таймер подсказок:
label.settings.ui.tooltip.items = На предметах
label.settings.ui.tooltip.ui = В интерфейсе
label.settings.sound = Звук
label.settings.sound.master = Общая громкость
label.settings.sound.music = Громкость нотных блоков
label.settings.sound.environment = Громкость фоновых звуков
label.settings.sound.beep = Громкость спикера
label.settings.sound.ui = Громкость интерфейса
label.settings.sound.positional = Использовать позиционный звук
label.settings.system = Система
label.settings.system.confPath = Задать путь к файлу конфигурации OpenComputers:
label.settings.system.confPathPlaceholder = не задан / используется конфигурация по-умолчанию
label.settings.system.confSearch = Искать файл конфигурации OpenComputers
label.settings.system.confGenerate = Сгенерировать новый файл конфигурации OpenComputers в:
label.settings.system.currentDir = Текущей папке
label.settings.system.configDir = Папке с конфигом
label.settings.system.customDir = Выбрать
label.settings.system.autosave = Авто сохранение проекта
label.settings.system.autosavePeriod = Период авто сохранения (в секундах):
label.settings.system.restart = Перезапустите Ocelot чтобы применить новую конфигурацию
# Dialogs
label.dialog.addNewPlayer = Добавить нового игрока
label.dialog.about.subtitle = Эмулятор OpenComputers
label.dialog.about.version = Версия
label.dialog.about.website = Вебсайт
label.dialog.aspect.width = Ширина:
label.dialog.aspect.height = Высота:
label.dialog.speed.msPerTick = Миллисекунд в тик:
label.dialog.speed.ticksPerSecond = Тик в секунду:
label.dialog.tunnel = Изменить название/код канала
label.dialog.tunnel.random = Сгенерировать случайное название
label.dialog.tunnel.copy = Скопировать название
label.dialog.updates.checking = Проверяем новости разработки...
label.dialog.updates.release = Релиз
label.dialog.updates.upToDate = Последняя версия
label.dialog.updates.releaseUpdateAvailable = Доступен новый релиз!
label.dialog.updates.devBuild = Бета
label.dialog.updates.devUpdateAvailable = Новая бета от
label.dialog.updates.unavailable = Вебсайт Ocelot недоступен...
label.dialog.updates.checkLogs = Полный стек-трейс можно найти в логах.
# Notifications
notification.saveBeforeExit = Сохранить проект перед выходом?
notification.saveBeforeOpeningNew = Сохранить проект прежде чем открыть новый?
# Ocelot error messages
error.ocelot.cannotOpenSpecifiedWorkspace = Не могу открыть указанный проект...
error.ocelot.cannotOpenRecentWorkspace = Не могу открыть последний проект...
error.ocelot.defaultWorkspaceCreation = Я создам новый
error.ocelot.somethingWentWrong = Что-то пошло не так!
error.ocelot.checkTheLogs = Полный стек-трейс можно найти в логах.
error.ocelot.savePathNotEmpty = Выбранная папка не пуста.[nl]Файлы в этой папке будут включены в проект.[nl]Конфликтующие файлы могут быть утеряны.[nl]Продолжить сохранение?
error.ocelot.overriding = Вы пытаетесь перезаписать существующий файл!
# Computer error codes
Error.NoCPU = Не установлен процессор.
Error.ComponentOverflow = Слишком много компонентов подключено к компьютеру.
Error.NoRAM = Не установлена оперативная память.
Error.OutOfMemory = Не хватает оперативной памяти.
Error.InternalError = Внутренняя ошибка. Пожалуйста проверьте логи. Возможно это баг.
# Tooltips
tooltip.address = Адрес
tooltip.components = Компоненты
tooltip.bytes = байт
tooltip.bit = бит
tooltip.dataCard.softLimit = Мягкий лимит
tooltip.dataCard.softLimitExplanation = сек замедление
tooltip.dataCard.hardLimit = Жёсткий лимит (отказ)
tooltip.disk.missingFloppy = Дискета: нет
tooltip.disk.floppy = Дискета
tooltip.disk.label = Метка
tooltip.disk.sourcePath = Источник
tooltip.disk.managedMode = Режим: файловый
tooltip.disk.unmanagedMode = Режим: блочный
tooltip.disk.capacity = Размер
tooltip.eeprom.sourcePath = Источник
tooltip.eeprom.sourceUrl = Источник
tooltip.eeprom.code = Код
tooltip.eeprom.data = Данные
tooltip.eeprom.data.readonly = Только чтение
tooltip.gpu.maxResolution = Макс. разрешение
tooltip.gpu.maxColorDepth = Макс. глубина цвета
tooltip.gpu.vram = Видеопамять
tooltip.tunnel.channel = Канал
tooltip.ram.capacity.infinite = Объём: бесконечный
tooltip.ram.capacity = Объём
tooltip.modem.openPortsNone = Открытые порты: нет
tooltip.modem.openPorts = Открытые порты
tooltip.modem.maxOpenPorts = Макс. открытых портов
tooltip.redstone.wakeThreshold = Порог пробуждения
tooltip.selfDestruct.fuseNotSet = Фитиль не подожжён
tooltip.selfDestruct.boom = БУМ!
tooltip.tape.label = Метка
tooltip.tape.ID = ID
tooltip.tape.size = Размер
tooltip.tape.length = Длина
# Selector
selector.group.original = Ванильные
selector.group.addons = Дополнения
selector.group.custom = Экстра
# Tiers
tier.one = Уровень 1
tier.oneHalf = Уровень 1.5
tier.two = Уровень 2
tier.twoHalf = Уровень 2.5
tier.three = Уровень 3
tier.threeHalf = Уровень 3.5
tier.creative = Креативный
# Directions
direction.up = Вверх
direction.down = Вниз
direction.top = Верхняя
direction.bottom = Нижняя
direction.left = Левая
direction.right = Правая
direction.front = Передняя
direction.back = Задняя
# Colors
color.white = Белая
color.orange = Оранжевая
color.magenta = Пурпурная
color.lightBlue = Светло-синяя
color.yellow = Жёлтая
color.lime = Лаймовая
color.pink = Розовая
color.gray = Серая
color.silver = Светло-серая
color.cyan = Бирюзовая
color.purple = Фиолетовая
color.blue = Синяя
color.brown = Коричневая
color.green = Зелёная
color.red = Красная
color.black = Чёрная
# Components
component.APU = APU
component.bundledIO = Цветной контроллер
component.cable = Кабель
component.camera = Камера
component.camera.notAvailable = <Веб-камера недоступна>
component.camera.flipHorizontally = Отразить горизонтально
component.camera.flipVertically = Отразить вертикально
component.camera.unlimitedCallBudget = Неограниченный бюджет вызовов
component.chest = Сундук
component.colorfulLamp = Цветная лампа
component.componentBus = Шина компонентов
component.computer = Корпус компьютера
component.CPU = CPU
component.dataCard = Карта данных
component.diskDrive = Дисковод
component.EEPROM = EEPROM
component.filesystem.floppy = Дискета
component.filesystem.floppyDisk = Дискета
component.filesystem.hdd = HDD
component.filesystem.hardDiskDrive = Жёсткий диск
component.graphicsCard = Видеокарта
component.hologramProjector = Голографический проектор
component.internetCard = Интернет карта
component.ironNoteBlock = Железный нотный блок
component.microcontroller = Микроконтроллер
component.modem = Сетевая карта
component.modem.wireless = Плата беспроводной сети
component.noteBlock = Нотный блок
component.noteBlock.bass = Бас-гитара (Дерево)
component.noteBlock.snare = Малый барабан (Песок)
component.noteBlock.hat = Палочки (Стекло)
component.noteBlock.basedrum = Большой барабан (Булыжник)
component.noteBlock.bell = Колокольчики (Золото)
component.noteBlock.flute = Флейта (Глина)
component.noteBlock.chime = Бар чаймс (Плотный лёд)
component.noteBlock.guitar = Гитара (Шерсть)
component.noteBlock.xylophone = Ксилофон (Кость)
component.noteBlock.ironXylophone = Вибрафон (Железо)
component.noteBlock.cowBell = Коровий колокольчик (Песок душ)
component.noteBlock.didgeridoo = Диджериду (Тыква)
component.noteBlock.bit = Квадратная волна (Изумруд)
component.noteBlock.banjo = Банджо (Сноп сена)
component.noteBlock.pling = Электронное пианино (Светокамень)
component.noteBlock.harp = Пианино / Арфа
component.ocelot.block = Блок Ocelot
component.ocelot.card = Ocelot карта
component.openFmRadio = Радио OpenFM
component.rack = Серверная стойка
component.raid = RAID
component.ram.magical = Магическая память (Креатив)
component.ram = Оперативная память
component.relay = Ретранслятор
component.redstoneIO = Красный контроллер
component.redstoneCard = Плата на красном камне
component.screen = Монитор
component.selfDestructingCard = Карта саморазрушения
component.server = Сервер
component.soundCard = Звуковая карта
component.tape = Кассета
component.tapeDrive = Стример
component.tunnel = Соединённая карта

View File

@ -2,6 +2,11 @@
# Try setting your syntax highlighting to Ruby, to help readability. At least # Try setting your syntax highlighting to Ruby, to help readability. At least
# in Sublime Text that works really well. # in Sublime Text that works really well.
ocelot { ocelot {
general {
# Language used for UI. Defaults to "en_US" if Ocelot cannot find specified lang file.
language: "en_US"
}
brain { brain {
# This is the path to OpenComputers configuration file, that Ocelot Brain can use # This is the path to OpenComputers configuration file, that Ocelot Brain can use
# to apply the settings which can be applicable in emulation context (like `bufferChanges: false`). # to apply the settings which can be applicable in emulation context (like `bufferChanges: false`).

View File

@ -14,7 +14,7 @@ class ColorScheme extends Logging {
def add(key: String, color: RGBAColorNorm): Unit = entries.addOne((key, color)) def add(key: String, color: RGBAColorNorm): Unit = entries.addOne((key, color))
def load(source: Source): Unit = { def load(source: Source): Unit = {
logger.info(s"Loading color scheme") logger.info(s"Loading color scheme...")
val oldSize = entries.size val oldSize = entries.size

View File

@ -8,6 +8,7 @@ import ocelot.desktop.ui.swing.SplashScreen
import ocelot.desktop.ui.widget._ import ocelot.desktop.ui.widget._
import ocelot.desktop.ui.widget.modal.notification.{NotificationDialog, NotificationType} import ocelot.desktop.ui.widget.modal.notification.{NotificationDialog, NotificationType}
import ocelot.desktop.util.CommandLine.Argument import ocelot.desktop.util.CommandLine.Argument
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util._ import ocelot.desktop.util._
import org.apache.commons.io.FileUtils import org.apache.commons.io.FileUtils
import org.apache.commons.lang3.SystemUtils import org.apache.commons.lang3.SystemUtils
@ -100,10 +101,10 @@ object OcelotDesktop extends LoggingConfiguration with Logging {
Settings.load(desktopConfigPath) Settings.load(desktopConfigPath)
Messages.load(Source.fromURL(getClass.getResource("/ocelot/desktop/messages.txt"))) Messages.load(Settings.get.language)
ColorScheme.load(Source.fromURL(getClass.getResource("/ocelot/desktop/colorscheme.txt"))) ColorScheme.load(Source.fromURL(getClass.getResource("/ocelot/desktop/colorscheme.txt")))
splashScreen.setStatus("Initializing brain...", 0.20f) splashScreen.setStatus(m"label.loading.brain", 0.20f)
Ocelot.configPath = Settings.get.brainCustomConfigPath.map(Paths.get(_)) Ocelot.configPath = Settings.get.brainCustomConfigPath.map(Paths.get(_))
Ocelot.librariesPath = Some(OcelotPaths.libraries) Ocelot.librariesPath = Some(OcelotPaths.libraries)
Ocelot.isPlayerOnlinePredicate = Some(player => players.exists(_.nickname == player)) Ocelot.isPlayerOnlinePredicate = Some(player => players.exists(_.nickname == player))
@ -111,12 +112,12 @@ object OcelotDesktop extends LoggingConfiguration with Logging {
Items.init() Items.init()
splashScreen.setStatus("Initializing GUI...", 0.30f) splashScreen.setStatus(m"label.loading.gui", 0.30f)
createWorkspace() createWorkspace()
UiHandler.loadLibraries() UiHandler.loadLibraries()
splashScreen.setStatus("Loading resources...", 0.60f) splashScreen.setStatus(m"label.loading.resources", 0.60f)
UiHandler.init() UiHandler.init()
val loadRecentWorkspace = Settings.get.recentWorkspace.isDefined && Settings.get.openLastWorkspace val loadRecentWorkspace = Settings.get.recentWorkspace.isDefined && Settings.get.openLastWorkspace
@ -125,7 +126,7 @@ object OcelotDesktop extends LoggingConfiguration with Logging {
root.size = Size2D(Display.getWidth / Settings.get.scaleFactor, Display.getHeight / Settings.get.scaleFactor) root.size = Size2D(Display.getWidth / Settings.get.scaleFactor, Display.getHeight / Settings.get.scaleFactor)
UiHandler.setRoot(root) UiHandler.setRoot(root)
splashScreen.setStatus("Loading workspace...", 0.90f) splashScreen.setStatus(m"label.loading.workspace", 0.90f)
val cmdLineWorkspaceArgument = args.get(CommandLine.WorkspacePath).flatten val cmdLineWorkspaceArgument = args.get(CommandLine.WorkspacePath).flatten
if (loadRecentWorkspace || cmdLineWorkspaceArgument.isDefined) { if (loadRecentWorkspace || cmdLineWorkspaceArgument.isDefined) {
val result = cmdLineWorkspaceArgument val result = cmdLineWorkspaceArgument
@ -137,14 +138,15 @@ object OcelotDesktop extends LoggingConfiguration with Logging {
result match { result match {
case Failure(exception) => case Failure(exception) =>
val errorMessage = if (cmdLineWorkspaceArgument.isDefined) val errorMessage = if (cmdLineWorkspaceArgument.isDefined) {
"Could not open the specified workspace..." logger.error("Could not open the specified workspace...", exception)
else "error.ocelot.cannotOpenSpecifiedWorkspace"
"Could not open the recent workspace..." } else {
logger.error("Could not open the recent workspace...", exception)
"error.ocelot.cannotOpenRecentWorkspace"
}
logger.error(errorMessage, exception) new NotificationDialog(s"${Message(errorMessage)}\n($exception)\n${m"error.ocelot.defaultWorkspaceCreation"}", NotificationType.Info)
new NotificationDialog(s"$errorMessage\n($exception)\nI will create a default one", NotificationType.Info)
.addCloseButton() .addCloseButton()
.show() .show()
@ -281,7 +283,7 @@ object OcelotDesktop extends LoggingConfiguration with Logging {
} }
})) }))
def newWorkspace(): Unit = showCloseConfirmationDialog("Save workspace before opening a new one?") { def newWorkspace(): Unit = showCloseConfirmationDialog(m"notification.saveBeforeOpeningNew") {
root.workspaceView.newWorkspace() root.workspaceView.newWorkspace()
savePath = None savePath = None
Settings.get.recentWorkspace = None Settings.get.recentWorkspace = None
@ -428,13 +430,13 @@ object OcelotDesktop extends LoggingConfiguration with Logging {
logger.error("File operation failed", exception) logger.error("File operation failed", exception)
new NotificationDialog( new NotificationDialog(
s"Something went wrong!\n($exception)\nCheck the log file for a full stacktrace.", s"${m"error.ocelot.somethingWentWrong"}\n($exception)\n${m"error.ocelot.checkTheLogs"}",
NotificationType.Error, NotificationType.Error,
).addCloseButton().show() ).addCloseButton().show()
} }
def showAddPlayerDialog(): Unit = new InputDialog( def showAddPlayerDialog(): Unit = new InputDialog(
"Add new player", m"label.dialog.addNewPlayer",
text => OcelotDesktop.selectPlayer(text), text => OcelotDesktop.selectPlayer(text),
).show() ).show()
@ -481,17 +483,11 @@ object OcelotDesktop extends LoggingConfiguration with Logging {
} }
if (nonEmpty) { if (nonEmpty) {
new NotificationDialog( new NotificationDialog(m"error.ocelot.savePathNotEmpty", NotificationType.Warning) {
"""Chosen save path is not empty. addButton(m"button.cancel") {
|Files in the save directory will be included in the workspace.
|They may be overwritten, causing loss of data.
|Proceed with saving anyway?""".stripMargin,
NotificationType.Warning,
) {
addButton("Cancel") {
close() close()
} }
addButton("Yes") { addButton(m"button.yes") {
close() close()
continuation continuation
} }
@ -522,7 +518,7 @@ object OcelotDesktop extends LoggingConfiguration with Logging {
} }
} }
private def showCloseConfirmationDialog(prompt: Option[String])(continuation: => Unit): Unit = { private def showCloseConfirmationDialog(prompt: Option[Message])(continuation: => Unit): Unit = {
if (UiHandler.root.modalDialogPool.children.exists(_.isInstanceOf[CloseConfirmationDialog])) { if (UiHandler.root.modalDialogPool.children.exists(_.isInstanceOf[CloseConfirmationDialog])) {
return return
} }
@ -537,7 +533,7 @@ object OcelotDesktop extends LoggingConfiguration with Logging {
val prompt_ = prompt val prompt_ = prompt
new CloseConfirmationDialog { new CloseConfirmationDialog {
override def prompt: String = prompt_.getOrElse(super.prompt) override def prompt: Message = prompt_.getOrElse(super.prompt)
override def onSaveSelected(): Unit = save { override def onSaveSelected(): Unit = save {
close() close()
@ -551,7 +547,7 @@ object OcelotDesktop extends LoggingConfiguration with Logging {
}.show() }.show()
} }
private def showCloseConfirmationDialog(prompt: String)(continuation: => Unit): Unit = private def showCloseConfirmationDialog(prompt: Message)(continuation: => Unit): Unit =
showCloseConfirmationDialog(Some(prompt))(continuation) showCloseConfirmationDialog(Some(prompt))(continuation)
private def showCloseConfirmationDialog()(continuation: => Unit): Unit = private def showCloseConfirmationDialog()(continuation: => Unit): Unit =

View File

@ -2,7 +2,7 @@ package ocelot.desktop
import com.typesafe.config.{Config, ConfigFactory, ConfigRenderOptions, ConfigValueFactory} import com.typesafe.config.{Config, ConfigFactory, ConfigRenderOptions, ConfigValueFactory}
import ocelot.desktop.Settings.ExtendedConfig import ocelot.desktop.Settings.ExtendedConfig
import ocelot.desktop.util.{Logging, SettingsData} import ocelot.desktop.util.{Language, Logging, SettingsData}
import org.apache.commons.lang3.SystemUtils import org.apache.commons.lang3.SystemUtils
import java.io.InputStream import java.io.InputStream
@ -45,6 +45,9 @@ class Settings(val config: Config) extends SettingsData {
} }
recentWorkspace = config.getOptionalString("ocelot.workspace.recent") recentWorkspace = config.getOptionalString("ocelot.workspace.recent")
language = config.getOptionalString("ocelot.general.language").getOrElse(Language.DefaultCode)
pinNewWindows = config.getBooleanOrElse("ocelot.workspace.pinNewWindows", default = true) pinNewWindows = config.getBooleanOrElse("ocelot.workspace.pinNewWindows", default = true)
unfocusedWindowTransparency = config.getDoubleOrElse("ocelot.workspace.unfocusedWindowTransparency", 0.5) unfocusedWindowTransparency = config.getDoubleOrElse("ocelot.workspace.unfocusedWindowTransparency", 0.5)
saveOnExit = config.getBooleanOrElse("ocelot.workspace.saveOnExit", default = true) saveOnExit = config.getBooleanOrElse("ocelot.workspace.saveOnExit", default = true)
@ -187,6 +190,7 @@ object Settings extends Logging {
.withValuePreserveOrigin("ocelot.window.disableVsync", settings.disableVsync) .withValuePreserveOrigin("ocelot.window.disableVsync", settings.disableVsync)
.withValuePreserveOrigin("ocelot.window.debugLwjgl", settings.debugLwjgl) .withValuePreserveOrigin("ocelot.window.debugLwjgl", settings.debugLwjgl)
.withValue("ocelot.workspace.recent", settings.recentWorkspace) .withValue("ocelot.workspace.recent", settings.recentWorkspace)
.withValuePreserveOrigin("ocelot.general.language", settings.language)
.withValuePreserveOrigin("ocelot.workspace.pinNewWindows", settings.pinNewWindows) .withValuePreserveOrigin("ocelot.workspace.pinNewWindows", settings.pinNewWindows)
.withValuePreserveOrigin("ocelot.workspace.unfocusedWindowTransparency", settings.unfocusedWindowTransparency) .withValuePreserveOrigin("ocelot.workspace.unfocusedWindowTransparency", settings.unfocusedWindowTransparency)
.withValuePreserveOrigin("ocelot.workspace.saveOnExit", settings.saveOnExit) .withValuePreserveOrigin("ocelot.workspace.saveOnExit", settings.saveOnExit)

View File

@ -9,6 +9,7 @@ import totoro.ocelot.brain.util.Tier.Tier
case class IconSource( case class IconSource(
path: String, path: String,
tierTint: Boolean = false,
animation: Option[IconSource.Animation] = None, animation: Option[IconSource.Animation] = None,
) )
@ -207,7 +208,7 @@ object IconSource {
object Computer extends PowerIconSource with DiskActivityIconSource { object Computer extends PowerIconSource with DiskActivityIconSource {
override protected def prefix: String = "nodes/computer" override protected def prefix: String = "nodes/computer"
val Default: IconSource = IconSource(s"$prefix/Default") val Default: IconSource = IconSource(s"$prefix/Default", tierTint = true)
} }
object DiskDrive extends DiskActivityIconSource with FloppyDriveIconSource { object DiskDrive extends DiskActivityIconSource with FloppyDriveIconSource {
@ -276,7 +277,7 @@ object IconSource {
object Screen { object Screen {
protected val prefix: String = "nodes/screen" protected val prefix: String = "nodes/screen"
val Standalone: IconSource = IconSource(s"$prefix/Standalone") val Standalone: IconSource = IconSource(s"$prefix/Standalone", tierTint = true)
val PowerOnOverlay: IconSource = IconSource(s"$prefix/PowerOnOverlay") val PowerOnOverlay: IconSource = IconSource(s"$prefix/PowerOnOverlay")
val ColumnTop: IconSource = IconSource(s"$prefix/ColumnTop") val ColumnTop: IconSource = IconSource(s"$prefix/ColumnTop")

View File

@ -8,7 +8,7 @@ import org.lwjgl.opengl.GL20
import scala.io.Source import scala.io.Source
class ShaderProgram(name: String) extends Logging with Resource { class ShaderProgram(name: String) extends Logging with Resource {
logger.info(s"Loading shader program ($name)") logger.info(s"Loading shader program ($name)...")
private val fragmentShader: Int = createShader( private val fragmentShader: Int = createShader(
Source.fromResource(s"ocelot/desktop/shader/$name.frag", getClass.getClassLoader), Source.fromResource(s"ocelot/desktop/shader/$name.frag", getClass.getClassLoader),

View File

@ -7,7 +7,7 @@ import ocelot.desktop.ui.event.EventAware
import ocelot.desktop.ui.widget.Updatable import ocelot.desktop.ui.widget.Updatable
import ocelot.desktop.ui.widget.contextmenu.ContextMenu import ocelot.desktop.ui.widget.contextmenu.ContextMenu
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Disposable import ocelot.desktop.util.{Disposable, Message}
import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
@ -49,7 +49,7 @@ trait Item extends EventAware with Updatable with Disposable {
protected def onRemoved(): Unit = {} protected def onRemoved(): Unit = {}
/** The name of the item (as shown in the tooltip). */ /** The name of the item (as shown in the tooltip). */
def name: String = factory.name def name: Message = factory.name.toString
/** The icon used to draw the item in a slot. */ /** The icon used to draw the item in a slot. */
def icon: IconSource = factory.icon def icon: IconSource = factory.icon

View File

@ -1,6 +1,7 @@
package ocelot.desktop.inventory package ocelot.desktop.inventory
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.util.Message
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
/** Provides information about a class of [[Item]]s and allows to build an item instance. /** Provides information about a class of [[Item]]s and allows to build an item instance.
@ -27,7 +28,7 @@ trait ItemFactory {
* *
* Used by the [[ocelot.desktop.ui.widget.slot.ItemChooser ItemChooser]] in its entries. * Used by the [[ocelot.desktop.ui.widget.slot.ItemChooser ItemChooser]] in its entries.
*/ */
def name: String def name: Message
/** The tier of an item this factory will construct in its [[build]] method. /** The tier of an item this factory will construct in its [[build]] method.
* *

View File

@ -35,7 +35,7 @@ object Items extends Logging {
} }
def registerSingleton(factory: ItemFactory): Unit = { def registerSingleton(factory: ItemFactory): Unit = {
_groups += SingletonItemGroup(factory.name, factory) _groups += SingletonItemGroup(factory.name.toString, factory)
registerItemFactoryRecoverers(factory) registerItemFactoryRecoverers(factory)
} }
@ -108,7 +108,7 @@ object Items extends Logging {
case ExtendedTier.Creative => new MagicalMemoryItem.Factory() case ExtendedTier.Creative => new MagicalMemoryItem.Factory()
case tier => new MemoryItem.Factory(tier) case tier => new MemoryItem.Factory(tier)
} }
.map(factory => (factory.name, factory)), .map(factory => (factory.name.toString, factory)),
) )
registerTiered("HDD", Tier.One to Tier.Three)(new HddItem.Factory(managed = true, _)) registerTiered("HDD", Tier.One to Tier.Three)(new HddItem.Factory(managed = true, _))
@ -118,7 +118,7 @@ object Items extends Logging {
FloppyItem.Factory.Empty.icon, FloppyItem.Factory.Empty.icon,
Loot.Floppies.iterator Loot.Floppies.iterator
.map(new FloppyItem.Factory.Loot(_)) .map(new FloppyItem.Factory.Loot(_))
.map(factory => (factory.name, factory)) ++ Some(("Empty", FloppyItem.Factory.Empty)), .map(factory => (factory.name.toString, factory)) ++ Some(("Empty", FloppyItem.Factory.Empty)),
) )
registerArbitrary( registerArbitrary(
@ -126,7 +126,7 @@ object Items extends Logging {
EepromItem.Factory.Empty.icon, EepromItem.Factory.Empty.icon,
Loot.Eeproms.iterator Loot.Eeproms.iterator
.map(new EepromItem.Factory.Loot(_)) .map(new EepromItem.Factory.Loot(_))
.map(factory => (factory.name, factory)) ++ Some(("Empty", EepromItem.Factory.Empty)), .map(factory => (factory.name.toString, factory)) ++ Some(("Empty", EepromItem.Factory.Empty)),
) )
registerTiered("Graphics Card", Tier.One to Tier.Three)(new GraphicsCardItem.Factory(_)) registerTiered("Graphics Card", Tier.One to Tier.Three)(new GraphicsCardItem.Factory(_))

View File

@ -3,6 +3,8 @@ package ocelot.desktop.inventory.item
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{ComponentItem, CpuLikeItem, GpuLikeItem, PersistableItem} import ocelot.desktop.inventory.traits.{ComponentItem, CpuLikeItem, GpuLikeItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.APU import totoro.ocelot.brain.entity.APU
import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU, GenericGPU} import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU, GenericGPU}
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
@ -19,7 +21,7 @@ object ApuItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = s"APU (${tier.get.label})" override def name: Message = s"${m"component.APU"} (${m"${tier.get.label}"})"
// there are T2, T3, and creative APUs // there are T2, T3, and creative APUs
// however, the APU class starts counting from one (so it's actually T1, T2, and T3) // however, the APU class starts counting from one (so it's actually T1, T2, and T3)

View File

@ -4,6 +4,8 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.EntityItem import ocelot.desktop.inventory.traits.EntityItem
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.ComponentBus import totoro.ocelot.brain.entity.ComponentBus
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
@ -14,7 +16,7 @@ class ComponentBusItem(val componentBus: ComponentBus) extends Item with EntityI
override def fillTooltip(tooltip: ItemTooltip): Unit = { override def fillTooltip(tooltip: ItemTooltip): Unit = {
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
if (componentBus != null) { if (componentBus != null) {
tooltip.addLine(s"Components: ${componentBus.supportedComponents}") tooltip.addLine(s"${m"tooltip.components"}: ${componentBus.supportedComponents}")
} }
} }
} }
@ -25,7 +27,7 @@ object ComponentBusItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = s"Component Bus (${_tier.label})" override def name: Message = s"${m"component.componentBus"} (${m"${_tier.label}"})"
override def tier: Option[Tier] = Some(_tier) override def tier: Option[Tier] = Some(_tier)

View File

@ -3,6 +3,8 @@ package ocelot.desktop.inventory.item
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{ComponentItem, CpuLikeItem, PersistableItem} import ocelot.desktop.inventory.traits.{ComponentItem, CpuLikeItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.CPU import totoro.ocelot.brain.entity.CPU
import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU} import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU}
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
@ -19,7 +21,7 @@ object CpuItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = s"CPU (${_tier.label})" override def name: Message = s"${m"component.CPU"} (${m"${_tier.label}"})"
override def tier: Option[Tier] = Some(_tier) override def tier: Option[Tier] = Some(_tier)

View File

@ -4,6 +4,8 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem} import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.Settings import totoro.ocelot.brain.Settings
import totoro.ocelot.brain.entity.DataCard import totoro.ocelot.brain.entity.DataCard
import totoro.ocelot.brain.entity.traits.{Entity, Environment} import totoro.ocelot.brain.entity.traits.{Entity, Environment}
@ -14,15 +16,15 @@ abstract class DataCardItem extends Item with ComponentItem with PersistableItem
override def fillTooltip(tooltip: ItemTooltip): Unit = { override def fillTooltip(tooltip: ItemTooltip): Unit = {
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
tooltip.addLine( tooltip.addLine(
s"Soft limit (${Settings.get.dataCardTimeout} sec slowdown): ${Settings.get.dataCardSoftLimit} bytes" s"${m"tooltip.dataCard.softLimit"} (${Settings.get.dataCardTimeout} ${m"tooltip.dataCard.softLimitExplanation"}): ${Settings.get.dataCardSoftLimit} ${m"tooltip.bytes"}"
) )
tooltip.addLine(s"Hard limit (fail): ${Settings.get.dataCardHardLimit} bytes") tooltip.addLine(s"${m"tooltip.dataCard.hardLimit"}: ${Settings.get.dataCardHardLimit} ${m"tooltip.bytes"}")
} }
} }
object DataCardItem { object DataCardItem {
abstract class Factory extends ItemFactory { abstract class Factory extends ItemFactory {
override def name: String = s"Data Card (${tier.get.label})" override def name: Message = s"${m"component.dataCard"} (${m"${tier.get.label}"})"
override def icon: IconSource = IconSource.Items.DataCard(tier.get) override def icon: IconSource = IconSource.Items.DataCard(tier.get)
} }

View File

@ -4,7 +4,8 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.RackMountableItem import ocelot.desktop.inventory.traits.RackMountableItem
import ocelot.desktop.inventory.{ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.DiskDriveAware import ocelot.desktop.util.{DiskDriveAware, Message}
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.traits.Floppy import totoro.ocelot.brain.entity.traits.Floppy
import totoro.ocelot.brain.entity.{DiskDriveMountable, FloppyDiskDrive} import totoro.ocelot.brain.entity.{DiskDriveMountable, FloppyDiskDrive}
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
@ -19,8 +20,8 @@ class DiskDriveMountableItem(val diskDriveMountable: DiskDriveMountable) extends
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
if (diskDriveMountable != null) { if (diskDriveMountable != null) {
diskDriveMountable.inventory(0).get match { diskDriveMountable.inventory(0).get match {
case None => tooltip.addLine("Floppy: none") case None => tooltip.addLine(m"tooltip.disk.missingFloppy")
case Some(floppy: Floppy) if floppy.name.isDefined => tooltip.addLine(s"Floppy: ${floppy.name.get}") case Some(floppy: Floppy) if floppy.name.isDefined => tooltip.addLine(s"${m"tooltip.disk.floppy"}: ${floppy.name.get}")
case _ => case _ =>
} }
} }
@ -35,7 +36,7 @@ object DiskDriveMountableItem {
override def tier: Option[Tier] = None override def tier: Option[Tier] = None
override def name: String = "Disk Drive" override def name: Message = m"component.diskDrive"
override def icon: IconSource = IconSource.Items.DiskDriveMountable override def icon: IconSource = IconSource.Items.DiskDriveMountable

View File

@ -7,6 +7,8 @@ import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.InputDialog import ocelot.desktop.ui.widget.InputDialog
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuIcon, ContextMenuSubmenu} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuIcon, ContextMenuSubmenu}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.Settings import totoro.ocelot.brain.Settings
import totoro.ocelot.brain.entity.EEPROM import totoro.ocelot.brain.entity.EEPROM
import totoro.ocelot.brain.entity.traits.{Entity, Environment} import totoro.ocelot.brain.entity.traits.{Entity, Environment}
@ -24,8 +26,8 @@ class EepromItem(val eeprom: EEPROM) extends Item with ComponentItem with Persis
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
val source = eeprom.codePath val source = eeprom.codePath
.map(path => s"Source path: $path") .map(path => s"${m"tooltip.eeprom.sourcePath"}: $path")
.orElse(eeprom.codeURL.map(url => s"Source URL: $url")) .orElse(eeprom.codeURL.map(url => s"${m"tooltip.eeprom.sourceUrl"}: $url"))
for (source <- source) { for (source <- source) {
tooltip.addLine(source) tooltip.addLine(source)
@ -34,19 +36,19 @@ class EepromItem(val eeprom: EEPROM) extends Item with ComponentItem with Persis
if (source.isEmpty && eeprom != null) { if (source.isEmpty && eeprom != null) {
if (eeprom.codeBytes != null) { if (eeprom.codeBytes != null) {
tooltip.addLine( tooltip.addLine(
s"Code: ${eeprom.codeBytes.map(_.length).getOrElse(0)} bytes / ${Settings.get.eepromSize} bytes" s"${m"tooltip.eeprom.code"}: ${eeprom.codeBytes.map(_.length).getOrElse(0)} ${m"tooltip.bytes"} / ${Settings.get.eepromSize} ${m"tooltip.bytes"}"
) )
} }
if (eeprom.volatileData != null) if (eeprom.volatileData != null)
tooltip.addLine(s"Data: ${eeprom.volatileData.length} bytes / ${Settings.get.eepromDataSize} bytes") tooltip.addLine(s"${m"tooltip.eeprom.data"}: ${eeprom.volatileData.length} ${m"tooltip.bytes"} / ${Settings.get.eepromDataSize} ${m"tooltip.bytes"}")
if (eeprom.readonly) if (eeprom.readonly)
tooltip.addLine("Readonly") tooltip.addLine(m"tooltip.eeprom.data.readonly")
} }
} }
override def fillRmbMenu(menu: ContextMenu): Unit = { override def fillRmbMenu(menu: ContextMenu): Unit = {
menu.addEntry(new ContextMenuSubmenu("External data source", Some(ContextMenuIcon(IconSource.Code))) { menu.addEntry(new ContextMenuSubmenu(m"label.menu.externalDataSource", Some(ContextMenuIcon(IconSource.Code))) {
addEntry(ContextMenuEntry("Local file", IconSource.File) { addEntry(ContextMenuEntry(m"label.menu.localFile", IconSource.File) {
OcelotDesktop.showFileChooserDialog(JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY) { file => OcelotDesktop.showFileChooserDialog(JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY) { file =>
Try { Try {
for (file <- file) { for (file <- file) {
@ -56,9 +58,9 @@ class EepromItem(val eeprom: EEPROM) extends Item with ComponentItem with Persis
} }
}) })
addEntry(ContextMenuEntry("File via URL", IconSource.Link) { addEntry(ContextMenuEntry(m"label.menu.fileViaUrl", IconSource.Link) {
new InputDialog( new InputDialog(
title = "File via URL", title = m"label.menu.fileViaUrl",
onConfirmed = { text => onConfirmed = { text =>
eeprom.codeURL = Some(new URL(text)) eeprom.codeURL = Some(new URL(text))
}, },
@ -74,7 +76,7 @@ class EepromItem(val eeprom: EEPROM) extends Item with ComponentItem with Persis
}) })
if (eeprom.codePath.nonEmpty || eeprom.codeURL.nonEmpty) { if (eeprom.codePath.nonEmpty || eeprom.codeURL.nonEmpty) {
addEntry(ContextMenuEntry("Detach", IconSource.LinkSlash) { addEntry(ContextMenuEntry(m"label.menu.detach", IconSource.LinkSlash) {
eeprom.codeBytes = Some(Array.empty) eeprom.codeBytes = Some(Array.empty)
}) })
} }
@ -105,16 +107,16 @@ object EepromItem {
object Factory { object Factory {
class Loot(factory: LootEepromFactory) extends Factory { class Loot(factory: LootEepromFactory) extends Factory {
override def name: String = factory.label override def name: Message = factory.label
override def build(): EepromItem = new EepromItem(factory.create()) override def build(): EepromItem = new EepromItem(factory.create())
} }
class Code(code: Array[Byte], override val name: String, readonly: Boolean) extends Factory { class Code(code: Array[Byte], override val name: Message, readonly: Boolean) extends Factory {
override def build(): EepromItem = { override def build(): EepromItem = {
val eeprom = new EEPROM val eeprom = new EEPROM
eeprom.codeBytes = Some(code) eeprom.codeBytes = Some(code)
eeprom.label = name eeprom.label = name.toString
eeprom.readonly = readonly eeprom.readonly = readonly
new EepromItem(eeprom) new EepromItem(eeprom)
@ -122,7 +124,7 @@ object EepromItem {
} }
object Empty extends Factory { object Empty extends Factory {
override def name: String = "EEPROM" override def name: Message = m"component.EEPROM"
override def build(): EepromItem = new EepromItem(new EEPROM) override def build(): EepromItem = new EepromItem(new EEPROM)
} }

View File

@ -4,19 +4,21 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{ComponentItem, DiskItem, PersistableItem} import ocelot.desktop.inventory.traits.{ComponentItem, DiskItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.fs.ReadWriteLabel import totoro.ocelot.brain.entity.fs.ReadWriteLabel
import totoro.ocelot.brain.entity.traits.{Disk, Entity, Floppy} import totoro.ocelot.brain.entity.traits.{Disk, Entity, Floppy}
import totoro.ocelot.brain.entity.{FloppyManaged, FloppyUnmanaged} import totoro.ocelot.brain.entity.{FloppyManaged, FloppyUnmanaged}
import totoro.ocelot.brain.loot.Loot.{FloppyFactory => LootFloppyFactory, LootFloppy} import totoro.ocelot.brain.loot.Loot.{LootFloppy, FloppyFactory => LootFloppyFactory}
import totoro.ocelot.brain.util.DyeColor import totoro.ocelot.brain.util.DyeColor
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
class FloppyItem(var floppy: Floppy) extends Item with ComponentItem with PersistableItem with DiskItem { class FloppyItem(var floppy: Floppy) extends Item with ComponentItem with PersistableItem with DiskItem {
override def entity: Entity with Disk = floppy override def entity: Entity with Disk = floppy
override def diskKind: String = "Floppy" override def diskKind: Message = m"component.filesystem.floppy"
override def name: String = floppy.name.getOrElse(super.name) override def name: Message = floppy.name.map(Message(_)).getOrElse(super.name)
override def label: Option[String] = floppy.label.labelOption override def label: Option[String] = floppy.label.labelOption
@ -80,7 +82,7 @@ object FloppyItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = label.getOrElse("Floppy Disk") override def name: Message = label.map(Message(_)).getOrElse(m"component.filesystem.floppyDisk")
override def tier: Option[Tier] = None override def tier: Option[Tier] = None
@ -91,7 +93,7 @@ object FloppyItem {
object Factory { object Factory {
class Loot(factory: LootFloppyFactory) extends Factory(Some(factory.name), factory.color, managed = true) { class Loot(factory: LootFloppyFactory) extends Factory(Some(factory.name), factory.color, managed = true) {
override def name: String = factory.name override def name: Message = factory.name
override def build(): FloppyItem = new FloppyItem(factory.create()) override def build(): FloppyItem = new FloppyItem(factory.create())
} }

View File

@ -3,6 +3,8 @@ package ocelot.desktop.inventory.item
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, GpuLikeItem, PersistableItem} import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, GpuLikeItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.GraphicsCard import totoro.ocelot.brain.entity.GraphicsCard
import totoro.ocelot.brain.entity.traits.{Entity, GenericGPU} import totoro.ocelot.brain.entity.traits.{Entity, GenericGPU}
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
@ -20,7 +22,7 @@ object GraphicsCardItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = s"Graphics Card (${_tier.label})" override def name: Message = s"${m"component.graphicsCard"} (${m"${_tier.label}"})"
override def tier: Option[Tier] = Some(_tier) override def tier: Option[Tier] = Some(_tier)
override def icon: IconSource = IconSource.Items.GraphicsCard(_tier) override def icon: IconSource = IconSource.Items.GraphicsCard(_tier)

View File

@ -5,6 +5,8 @@ import ocelot.desktop.inventory.item.HddItem.Hdd
import ocelot.desktop.inventory.traits.{ComponentItem, DiskItem, PersistableItem} import ocelot.desktop.inventory.traits.{ComponentItem, DiskItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.fs.{Label, ReadWriteLabel} import totoro.ocelot.brain.entity.fs.{Label, ReadWriteLabel}
import totoro.ocelot.brain.entity.traits.{Disk, Entity} import totoro.ocelot.brain.entity.traits.{Disk, Entity}
import totoro.ocelot.brain.entity.{HDDManaged, HDDUnmanaged} import totoro.ocelot.brain.entity.{HDDManaged, HDDUnmanaged}
@ -22,7 +24,7 @@ class HddItem(var hdd: Hdd) extends Item with ComponentItem with PersistableItem
override def entity: Entity with Disk = hdd.hdd override def entity: Entity with Disk = hdd.hdd
override def diskKind: String = "HDD" override def diskKind: Message = m"component.filesystem.hdd"
private def fsLabel: Label = hdd match { private def fsLabel: Label = hdd match {
case Hdd.Managed(hdd) => hdd.fileSystem.label case Hdd.Managed(hdd) => hdd.fileSystem.label
@ -72,7 +74,7 @@ object HddItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = s"Hard Disk Drive (${_tier.label})" override def name: Message = s"${m"component.filesystem.hardDiskDrive"} (${m"${_tier.label}"})"
override def tier: Option[Tier] = Some(_tier) override def tier: Option[Tier] = Some(_tier)

View File

@ -3,6 +3,8 @@ package ocelot.desktop.inventory.item
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem} import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.InternetCard import totoro.ocelot.brain.entity.InternetCard
import totoro.ocelot.brain.entity.traits.{Entity, Environment} import totoro.ocelot.brain.entity.traits.{Entity, Environment}
import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier
@ -20,7 +22,7 @@ object InternetCardItem {
override def itemClass: Class[InternetCardItem] = classOf override def itemClass: Class[InternetCardItem] = classOf
override def name: String = "Internet Card" override def name: Message = m"component.internetCard"
override def tier: Option[Tier] = Some(Tier.Two) override def tier: Option[Tier] = Some(Tier.Two)

View File

@ -6,6 +6,8 @@ import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.TunnelDialog import ocelot.desktop.ui.widget.TunnelDialog
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.LinkedCard import totoro.ocelot.brain.entity.LinkedCard
import totoro.ocelot.brain.entity.traits.{Entity, Environment} import totoro.ocelot.brain.entity.traits.{Entity, Environment}
import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier
@ -17,12 +19,12 @@ class LinkedCardItem(val linkedCard: LinkedCard) extends Item with ComponentItem
override def fillTooltip(tooltip: ItemTooltip): Unit = { override def fillTooltip(tooltip: ItemTooltip): Unit = {
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
tooltip.addLine(s"Channel: ${linkedCard.tunnel}") tooltip.addLine(s"${m"tooltip.tunnel.channel"}: ${linkedCard.tunnel}")
} }
override def fillRmbMenu(menu: ContextMenu): Unit = { override def fillRmbMenu(menu: ContextMenu): Unit = {
menu.addEntry( menu.addEntry(
ContextMenuEntry("Set channel", IconSource.Antenna) { ContextMenuEntry(m"label.menu.setChannel", IconSource.Antenna) {
new TunnelDialog( new TunnelDialog(
tunnel => linkedCard.tunnel = tunnel, tunnel => linkedCard.tunnel = tunnel,
linkedCard.tunnel, linkedCard.tunnel,
@ -41,7 +43,7 @@ object LinkedCardItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = "Linked Card" override def name: Message = m"component.tunnel"
override def tier: Option[Tier] = Some(Tier.Three) override def tier: Option[Tier] = Some(Tier.Three)

View File

@ -3,7 +3,8 @@ package ocelot.desktop.inventory.item
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.{ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{ItemFactory, ItemRecoverer}
import ocelot.desktop.util.TierColor import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, TierColor}
import totoro.ocelot.brain.entity.MagicalMemory import totoro.ocelot.brain.entity.MagicalMemory
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
import totoro.ocelot.brain.util.{ExtendedTier, Tier} import totoro.ocelot.brain.util.{ExtendedTier, Tier}
@ -20,7 +21,7 @@ object MagicalMemoryItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = "Magical Memory (Creative)" override def name: Message = m"component.ram.magical"
override def tier: Option[Tier] = Some(Tier.One) override def tier: Option[Tier] = Some(Tier.One)

View File

@ -4,6 +4,8 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{ComponentItem, PersistableItem} import ocelot.desktop.inventory.traits.{ComponentItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.Memory import totoro.ocelot.brain.entity.Memory
import totoro.ocelot.brain.entity.traits.{Entity, Environment} import totoro.ocelot.brain.entity.traits.{Entity, Environment}
import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier import totoro.ocelot.brain.util.ExtendedTier.ExtendedTier
@ -17,8 +19,8 @@ class MemoryItem(val memory: Memory) extends Item with ComponentItem with Persis
override def fillTooltip(tooltip: ItemTooltip): Unit = { override def fillTooltip(tooltip: ItemTooltip): Unit = {
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
tooltip.addLine( tooltip.addLine(
if (memory.amount == Double.PositiveInfinity) "Capacity: infinite" if (memory.amount == Double.PositiveInfinity) m"tooltip.ram.capacity.infinite"
else s"Capacity: ${memory.amount.toInt} kB" else s"${m"tooltip.ram.capacity"}: ${memory.amount.toInt} kB"
) )
} }
} }
@ -29,7 +31,7 @@ object MemoryItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = s"Memory (${memoryTier.label})" override def name: Message = s"${m"component.ram"} (${m"${memoryTier.label}"})"
override def tier: Option[Tier] = Some(memoryTier.toTier) override def tier: Option[Tier] = Some(memoryTier.toTier)

View File

@ -4,6 +4,8 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem} import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.NetworkCard import totoro.ocelot.brain.entity.NetworkCard
import totoro.ocelot.brain.entity.traits.Entity import totoro.ocelot.brain.entity.traits.Entity
import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier
@ -18,10 +20,10 @@ class NetworkCardItem(val card: NetworkCard) extends Item with ComponentItem wit
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
if (card != null) { if (card != null) {
tooltip.addLine( tooltip.addLine(
if (card.openPorts.isEmpty) s"Open ports: none" if (card.openPorts.isEmpty) m"tooltip.modem.openPortsNone"
else s"Open ports: ${card.openPorts.mkString(", ")}" else s"${m"tooltip.modem.openPorts"}: ${card.openPorts.mkString(", ")}"
) )
tooltip.addLine(s"Max open ports: ${card.maxOpenPorts}") tooltip.addLine(s"${m"tooltip.modem.maxOpenPorts"}: ${card.maxOpenPorts}")
} }
} }
} }
@ -32,7 +34,7 @@ object NetworkCardItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = "Network Card" override def name: Message = m"component.modem"
override def tier: Option[Tier] = Some(Tier.One) override def tier: Option[Tier] = Some(Tier.One)
override def icon: IconSource = IconSource.Items.NetworkCard override def icon: IconSource = IconSource.Items.NetworkCard

View File

@ -9,7 +9,8 @@ import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.{Logging, OcelotInterfaceLogStorage} import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Logging, Message, OcelotInterfaceLogStorage}
import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
@ -23,7 +24,7 @@ class OcelotCardItem(val ocelotCard: OcelotCard)
override def tooltipNameColor: Color = ColorScheme("OcelotCardTooltip") override def tooltipNameColor: Color = ColorScheme("OcelotCardTooltip")
override def fillRmbMenu(menu: ContextMenu): Unit = { override def fillRmbMenu(menu: ContextMenu): Unit = {
menu.addEntry(ContextMenuEntry("Open console", IconSource.Window) { menu.addEntry(ContextMenuEntry(m"label.menu.openConsole", IconSource.Window) {
window.open() window.open()
}) })
@ -48,7 +49,7 @@ object OcelotCardItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = "Ocelot Card" override def name: Message = m"component.ocelot.card"
override def tier: Option[Tier] = Some(Tier.One) override def tier: Option[Tier] = Some(Tier.One)

View File

@ -7,6 +7,8 @@ import ocelot.desktop.ui.widget.card.{Redstone1Window, Redstone2Window}
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.ui.widget.window.Windowed import ocelot.desktop.ui.widget.window.Windowed
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.Redstone import totoro.ocelot.brain.entity.Redstone
import totoro.ocelot.brain.entity.traits.{Entity, Environment} import totoro.ocelot.brain.entity.traits.{Entity, Environment}
import totoro.ocelot.brain.nbt.NBTTagCompound import totoro.ocelot.brain.nbt.NBTTagCompound
@ -17,7 +19,7 @@ abstract class RedstoneCardItem extends Item with ComponentItem with Persistable
object RedstoneCardItem { object RedstoneCardItem {
abstract class Factory extends ItemFactory { abstract class Factory extends ItemFactory {
override def name: String = s"Redstone Card (${tier.get.label})" override def name: Message = s"${m"component.redstoneCard"} (${m"${tier.get.label}"})"
override def icon: IconSource = IconSource.Items.RedstoneCard(tier.get) override def icon: IconSource = IconSource.Items.RedstoneCard(tier.get)
} }
@ -31,7 +33,7 @@ object RedstoneCardItem {
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
if (redstoneCard.wakeThreshold > 0) if (redstoneCard.wakeThreshold > 0)
tooltip.addLine(s"Wake threshold: ${redstoneCard.wakeThreshold}") tooltip.addLine(s"${m"tooltip.redstone.wakeThreshold"}: ${redstoneCard.wakeThreshold}")
} }
// ----------------------------- Window ----------------------------- // ----------------------------- Window -----------------------------
@ -43,7 +45,7 @@ object RedstoneCardItem {
} }
override def fillRmbMenu(menu: ContextMenu): Unit = { override def fillRmbMenu(menu: ContextMenu): Unit = {
menu.addEntry(ContextMenuEntry("Redstone I/O", IconSource.ArrowRight) { menu.addEntry(ContextMenuEntry(m"label.menu.redstoneIO", IconSource.ArrowRight) {
windowed.window.open() windowed.window.open()
}) })
@ -93,7 +95,7 @@ object RedstoneCardItem {
} }
override def fillRmbMenu(menu: ContextMenu): Unit = { override def fillRmbMenu(menu: ContextMenu): Unit = {
menu.addEntry(ContextMenuEntry("Bundled I/O", IconSource.LinesHorizontal) { menu.addEntry(ContextMenuEntry(m"label.menu.bundledIO", IconSource.LinesHorizontal) {
windowed.window.open() windowed.window.open()
}) })

View File

@ -4,6 +4,8 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem} import ocelot.desktop.inventory.traits.{CardItem, ComponentItem, PersistableItem}
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.SelfDestructingCard import totoro.ocelot.brain.entity.SelfDestructingCard
import totoro.ocelot.brain.entity.traits.{Entity, Environment} import totoro.ocelot.brain.entity.traits.{Entity, Environment}
import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier
@ -20,8 +22,8 @@ class SelfDestructingCardItem(val card: SelfDestructingCard)
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
if (card != null) { if (card != null) {
tooltip.addLine( tooltip.addLine(
if (card.remainingTime < 0) "Fuse has not been set" if (card.remainingTime < 0) m"tooltip.selfDestruct.fuseNotSet"
else if (card.remainingTime == 0) "BOOM!" else if (card.remainingTime == 0) m"tooltip.selfDestruct.boom"
else card.remainingTime.toString else card.remainingTime.toString
) )
} }
@ -34,7 +36,7 @@ object SelfDestructingCardItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = "Self-Destructing Card" override def name: Message = m"component.selfDestructingCard"
override def tier: Option[Tier] = Some(Tier.Two) override def tier: Option[Tier] = Some(Tier.Two)

View File

@ -5,7 +5,8 @@ import ocelot.desktop.inventory.traits.RackMountableItem
import ocelot.desktop.inventory.{ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.slot._ import ocelot.desktop.ui.widget.slot._
import ocelot.desktop.util.ComputerType.ComputerType import ocelot.desktop.util.ComputerType.ComputerType
import ocelot.desktop.util.{AudibleComputerAware, ComputerType} import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{AudibleComputerAware, ComputerType, Message}
import totoro.ocelot.brain.entity.Server import totoro.ocelot.brain.entity.Server
import totoro.ocelot.brain.entity.traits.Inventory import totoro.ocelot.brain.entity.traits.Inventory
import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier
@ -103,7 +104,7 @@ object ServerItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = s"Server (${_tier.label})" override def name: Message = s"${m"component.server"} (${m"${_tier.label}"})"
override def tier: Option[Tier] = Some(_tier) override def tier: Option[Tier] = Some(_tier)

View File

@ -6,6 +6,8 @@ import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.card.SoundCardWindow import ocelot.desktop.ui.widget.card.SoundCardWindow
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.window.Windowed import ocelot.desktop.ui.widget.window.Windowed
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.sound_card.SoundCard import totoro.ocelot.brain.entity.sound_card.SoundCard
import totoro.ocelot.brain.entity.traits.{Entity, Environment} import totoro.ocelot.brain.entity.traits.{Entity, Environment}
import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier
@ -19,7 +21,7 @@ class SoundCardItem(val soundCard: SoundCard)
override def entity: Entity with Environment = soundCard override def entity: Entity with Environment = soundCard
override def fillRmbMenu(menu: ContextMenu): Unit = { override def fillRmbMenu(menu: ContextMenu): Unit = {
menu.addEntry(ContextMenuEntry("Open card interface", IconSource.Window) { menu.addEntry(ContextMenuEntry(m"label.menu.openCardInterface", IconSource.Window) {
window.open() window.open()
}) })
@ -37,7 +39,7 @@ object SoundCardItem {
override def itemClass: Class[I] = classOf override def itemClass: Class[I] = classOf
override def name: String = "Sound Card" override def name: Message = m"component.soundCard"
override def tier: Option[Tier] = Some(Tier.Two) override def tier: Option[Tier] = Some(Tier.Two)

View File

@ -5,6 +5,8 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.EntityItem import ocelot.desktop.inventory.traits.EntityItem
import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{Item, ItemFactory, ItemRecoverer}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.SizeFormatting.formatSize import ocelot.desktop.util.SizeFormatting.formatSize
import totoro.ocelot.brain.entity.tape.Tape import totoro.ocelot.brain.entity.tape.Tape
import totoro.ocelot.brain.nbt.NBTTagCompound import totoro.ocelot.brain.nbt.NBTTagCompound
@ -19,15 +21,15 @@ class TapeItem(var tape: Tape) extends Item with EntityItem {
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
if (tape.label.nonEmpty) { if (tape.label.nonEmpty) {
tooltip.addLine(s"Label: ${tape.label}") tooltip.addLine(s"${m"tooltip.tape.label"}: ${tape.label}")
} }
for (storageId <- tape.storageId) { for (storageId <- tape.storageId) {
tooltip.addLine(s"ID: $storageId") tooltip.addLine(s"${m"tooltip.tape.ID"}: $storageId")
} }
tooltip.addLine(s"Size: ${formatSize(tape.size)}") tooltip.addLine(s"${m"tooltip.tape.size"}: ${formatSize(tape.size)}")
tooltip.addLine(f"Length: ${tape.lengthMinutes}%.0f minutes") tooltip.addLine(f"${m"tooltip.tape.length"}: ${tape.lengthMinutes}%.0f minutes")
} }
override def load(nbt: NBTTagCompound): Unit = { override def load(nbt: NBTTagCompound): Unit = {
@ -49,7 +51,7 @@ object TapeItem {
override def itemClass: Class[TapeItem] = classOf override def itemClass: Class[TapeItem] = classOf
override def name: String = "Tape" override def name: Message = m"component.tape"
override def tier: Option[Tier] = None override def tier: Option[Tier] = None

View File

@ -2,6 +2,8 @@ package ocelot.desktop.inventory.item
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.{ItemFactory, ItemRecoverer} import ocelot.desktop.inventory.{ItemFactory, ItemRecoverer}
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.WirelessNetworkCard import totoro.ocelot.brain.entity.WirelessNetworkCard
import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
@ -10,7 +12,7 @@ abstract class WirelessNetworkCardItem(override val card: WirelessNetworkCard) e
object WirelessNetworkCardItem { object WirelessNetworkCardItem {
abstract class Factory extends ItemFactory { abstract class Factory extends ItemFactory {
override def name: String = s"Wireless Net. Card (${tier.get.label})" override def name: Message = s"${m"component.modem.wireless"} (${m"${tier.get.label}"})"
override def icon: IconSource = IconSource.Items.WirelessNetworkCard(tier.get) override def icon: IconSource = IconSource.Items.WirelessNetworkCard(tier.get)
} }

View File

@ -5,6 +5,7 @@ import ocelot.desktop.inventory.Item
import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.traits.{Entity, Environment} import totoro.ocelot.brain.entity.traits.{Entity, Environment}
/** Implemented by [[Item]]s that wrap a component. */ /** Implemented by [[Item]]s that wrap a component. */
@ -18,11 +19,11 @@ trait ComponentItem extends EntityItem {
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
if (showAddress && entity.node.address != null) { if (showAddress && entity.node.address != null) {
tooltip.addLine(s"Address: ${entity.node.address}") tooltip.addLine(s"${m"tooltip.address"}: ${entity.node.address}")
} }
} }
private val copyAddressEntry = ContextMenuEntry("Copy address", IconSource.Copy) { private val copyAddressEntry = ContextMenuEntry(m"label.menu.copyAddress", IconSource.Copy) {
UiHandler.clipboard = entity.node.address UiHandler.clipboard = entity.node.address
} }

View File

@ -5,6 +5,7 @@ import ocelot.desktop.inventory.Item
import ocelot.desktop.inventory.traits.CpuLikeItem.CpuArchitectureChangedNotification import ocelot.desktop.inventory.traits.CpuLikeItem.CpuArchitectureChangedNotification
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuIcon, ContextMenuSubmenu} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuIcon, ContextMenuSubmenu}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.machine.MachineAPI import totoro.ocelot.brain.entity.machine.MachineAPI
import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU} import totoro.ocelot.brain.entity.traits.{Entity, GenericCPU}
@ -13,10 +14,10 @@ trait CpuLikeItem extends ComponentItem {
override def entity: Entity with GenericCPU override def entity: Entity with GenericCPU
override def fillRmbMenu(menu: ContextMenu): Unit = { override def fillRmbMenu(menu: ContextMenu): Unit = {
menu.addEntry(new ContextMenuSubmenu("Set architecture", Some(ContextMenuIcon(IconSource.Microchip))) { menu.addEntry(new ContextMenuSubmenu(m"label.menu.setArchitecture", Some(ContextMenuIcon(IconSource.Microchip))) {
for (arch <- entity.allArchitectures) { for (arch <- entity.allArchitectures) {
val name = MachineAPI.getArchitectureName(arch) + val name = MachineAPI.getArchitectureName(arch) +
(if (arch == entity.architecture) " (current)" else "") (if (arch == entity.architecture) s" (${m"label.menu.currentArchitecture"})" else "")
val entry = ContextMenuEntry(name) { val entry = ContextMenuEntry(name) {
entity.setArchitecture(arch) entity.setArchitecture(arch)
notifySlot(CpuArchitectureChangedNotification) notifySlot(CpuArchitectureChangedNotification)
@ -33,7 +34,7 @@ trait CpuLikeItem extends ComponentItem {
override def fillTooltip(tooltip: ItemTooltip): Unit = { override def fillTooltip(tooltip: ItemTooltip): Unit = {
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
if (entity != null) { if (entity != null) {
tooltip.addLine(s"Components: ${entity.supportedComponents}") tooltip.addLine(s"${m"tooltip.components"}: ${entity.supportedComponents}")
} }
} }
} }

View File

@ -7,6 +7,8 @@ import ocelot.desktop.ui.widget.DiskEditWindow
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.ui.widget.window.{Window, Windowed} import ocelot.desktop.ui.widget.window.{Window, Windowed}
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.traits.{Disk, DiskManaged, DiskRealPathAware, DiskUnmanaged, Entity} import totoro.ocelot.brain.entity.traits.{Disk, DiskManaged, DiskRealPathAware, DiskUnmanaged, Entity}
import totoro.ocelot.brain.util.DyeColor import totoro.ocelot.brain.util.DyeColor
@ -17,7 +19,7 @@ import scala.util.Try
trait DiskItem extends ComponentItem with Windowed[DiskEditWindow] { trait DiskItem extends ComponentItem with Windowed[DiskEditWindow] {
override def entity: Entity with Disk override def entity: Entity with Disk
def diskKind: String def diskKind: Message
def color: Option[DyeColor] = None def color: Option[DyeColor] = None
@ -68,26 +70,26 @@ trait DiskItem extends ComponentItem with Windowed[DiskEditWindow] {
} }
protected def addDiskLabelTooltip(tooltip: ItemTooltip, label: String): Unit = { protected def addDiskLabelTooltip(tooltip: ItemTooltip, label: String): Unit = {
tooltip.addLine(s"Label: $label") tooltip.addLine(s"${m"tooltip.disk.label"}: $label")
} }
protected def addSourcePathTooltip(tooltip: ItemTooltip, disk: DiskManaged): Unit = { protected def addSourcePathTooltip(tooltip: ItemTooltip, disk: DiskManaged): Unit = {
for (customRealPath <- disk.customRealPath) { for (customRealPath <- disk.customRealPath) {
tooltip.addLine(s"Source path: $customRealPath") tooltip.addLine(s"${m"tooltip.disk.sourcePath"}: $customRealPath")
} }
} }
protected def addManagedTooltip(tooltip: ItemTooltip, disk: Disk): Unit = { protected def addManagedTooltip(tooltip: ItemTooltip, disk: Disk): Unit = {
tooltip.addLine(disk match { tooltip.addLine(disk match {
case _: DiskManaged => "Mode: managed" case _: DiskManaged => m"tooltip.disk.managedMode"
case _: DiskUnmanaged => "Mode: unmanaged" case _: DiskUnmanaged => m"tooltip.disk.unmanagedMode"
}) })
} }
override def fillTooltip(tooltip: ItemTooltip): Unit = { override def fillTooltip(tooltip: ItemTooltip): Unit = {
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
if (entity != null) { if (entity != null) {
tooltip.addLine(s"Capacity: ${entity.capacity / 1024} kB") tooltip.addLine(s"${m"tooltip.disk.capacity"}: ${entity.capacity / 1024} kB")
} }
} }
} }
@ -96,7 +98,7 @@ object DiskItem {
def addRealPathContextMenuEntries(menu: ContextMenu, diskRealPathAware: DiskRealPathAware, def addRealPathContextMenuEntries(menu: ContextMenu, diskRealPathAware: DiskRealPathAware,
realPathSetter: (() => Unit) => Unit): Unit = { realPathSetter: (() => Unit) => Unit): Unit = {
menu.addEntry(ContextMenuEntry( menu.addEntry(ContextMenuEntry(
if (diskRealPathAware.customRealPath.isDefined) "Change directory" else "Set directory", if (diskRealPathAware.customRealPath.isDefined) m"label.menu.changeDirectory" else m"label.menu.setDirectory",
IconSource.Folder, IconSource.Folder,
) { ) {
OcelotDesktop.showFileChooserDialog(JFileChooser.OPEN_DIALOG, JFileChooser.DIRECTORIES_ONLY) { dir => OcelotDesktop.showFileChooserDialog(JFileChooser.OPEN_DIALOG, JFileChooser.DIRECTORIES_ONLY) { dir =>
@ -112,7 +114,7 @@ object DiskItem {
}) })
if (diskRealPathAware.customRealPath.isDefined) { if (diskRealPathAware.customRealPath.isDefined) {
menu.addEntry(ContextMenuEntry("Reset directory", IconSource.FolderSlash) { menu.addEntry(ContextMenuEntry(m"label.menu.resetDirectory", IconSource.FolderSlash) {
realPathSetter(() => { realPathSetter(() => {
// trigger component_removed / component_added signals // trigger component_removed / component_added signals
diskRealPathAware.customRealPath = None diskRealPathAware.customRealPath = None
@ -122,7 +124,7 @@ object DiskItem {
} }
def addEditDiskContextMenuEntries[T <: Window](menu: ContextMenu, windowed: Windowed[T]): Unit = { def addEditDiskContextMenuEntries[T <: Window](menu: ContextMenu, windowed: Windowed[T]): Unit = {
menu.addEntry(ContextMenuEntry("Edit disk", IconSource.Edit) { menu.addEntry(ContextMenuEntry(m"label.menu.editDisk", IconSource.Edit) {
windowed.window.open() windowed.window.open()
}) })
} }

View File

@ -1,6 +1,7 @@
package ocelot.desktop.inventory.traits package ocelot.desktop.inventory.traits
import ocelot.desktop.ui.widget.tooltip.ItemTooltip import ocelot.desktop.ui.widget.tooltip.ItemTooltip
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.Settings import totoro.ocelot.brain.Settings
import totoro.ocelot.brain.entity.traits.{Entity, GenericGPU} import totoro.ocelot.brain.entity.traits.{Entity, GenericGPU}
import totoro.ocelot.brain.util.ColorDepth import totoro.ocelot.brain.util.ColorDepth
@ -12,14 +13,14 @@ trait GpuLikeItem extends ComponentItem {
super.fillTooltip(tooltip) super.fillTooltip(tooltip)
if (entity != null) { if (entity != null) {
val resolution = Settings.screenResolutionsByTier(entity.tier.id) val resolution = Settings.screenResolutionsByTier(entity.tier.id)
tooltip.addLine(s"Max resolution: ${resolution._1}×${resolution._2}") tooltip.addLine(s"${m"tooltip.gpu.maxResolution"}: ${resolution._1}×${resolution._2}")
val depth = Settings.screenDepthsByTier(entity.tier.id) match { val depth = Settings.screenDepthsByTier(entity.tier.id) match {
case ColorDepth.OneBit => "1 bit" case ColorDepth.OneBit => "1"
case ColorDepth.FourBit => "4 bit" case ColorDepth.FourBit => "4"
case ColorDepth.EightBit => "8 bit" case ColorDepth.EightBit => "8"
} }
tooltip.addLine(s"Max color depth: $depth") tooltip.addLine(s"${m"tooltip.gpu.maxColorDepth"}: $depth ${m"tooltip.bit"}")
tooltip.addLine(s"VRAM: ${entity.totalVRAM.toInt}") tooltip.addLine(s"${m"tooltip.gpu.vram"}: ${entity.totalVRAM.toInt}")
} }
} }
} }

View File

@ -5,6 +5,7 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.ClickEvent import ocelot.desktop.ui.event.ClickEvent
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.traits.{Entity, Environment, SidedEnvironment} import totoro.ocelot.brain.entity.traits.{Entity, Environment, SidedEnvironment}
import totoro.ocelot.brain.nbt.NBTTagCompound import totoro.ocelot.brain.nbt.NBTTagCompound
import totoro.ocelot.brain.network import totoro.ocelot.brain.network
@ -35,7 +36,7 @@ abstract class EntityNode(val entity: Entity with Environment) extends Node {
override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = { override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = {
if (exposeAddress && entity.node != null && entity.node.address != null) { if (exposeAddress && entity.node != null && entity.node.address != null) {
menu.addEntry( menu.addEntry(
ContextMenuEntry("Copy address", IconSource.Copy) { ContextMenuEntry(m"label.menu.copyAddress", IconSource.Copy) {
UiHandler.clipboard = entity.node.address UiHandler.clipboard = entity.node.address
} }
) )

View File

@ -6,6 +6,7 @@ import ocelot.desktop.ui.event.ClickEvent
import ocelot.desktop.ui.widget.InputDialog import ocelot.desktop.ui.widget.InputDialog
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.util.DrawUtils import ocelot.desktop.util.DrawUtils
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.nbt.NBTTagCompound import totoro.ocelot.brain.nbt.NBTTagCompound
trait LabeledNode extends Node { trait LabeledNode extends Node {
@ -26,9 +27,9 @@ trait LabeledNode extends Node {
} }
override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = { override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = {
menu.addEntry(ContextMenuEntry("Set label", IconSource.Label) { menu.addEntry(ContextMenuEntry(m"label.menu.setLabel", IconSource.Label) {
new InputDialog( new InputDialog(
"Set label", m"label.menu.setLabel",
text => { text => {
_label = Option.unless(text.isEmpty)(text) _label = Option.unless(text.isEmpty)(text)
}, },

View File

@ -10,6 +10,7 @@ import ocelot.desktop.ui.event.sources.KeyEvents
import ocelot.desktop.ui.event.{ClickEvent, DragEvent, HoverEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, DragEvent, HoverEvent, MouseEvent}
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.{Widget, WorkspaceView} import ocelot.desktop.ui.widget.{Widget, WorkspaceView}
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.Persistable import ocelot.desktop.util.Persistable
import ocelot.desktop.util.animation.ColorAnimation import ocelot.desktop.util.animation.ColorAnimation
import totoro.ocelot.brain.nbt.NBTTagCompound import totoro.ocelot.brain.nbt.NBTTagCompound
@ -89,12 +90,12 @@ abstract class Node extends Widget with MouseHandler with HoverHandler with Pers
def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = { def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = {
if (ports.nonEmpty) { if (ports.nonEmpty) {
menu.addEntry(ContextMenuEntry("Disconnect", IconSource.LinkSlash, SoundSource.InterfaceClickLow) { menu.addEntry(ContextMenuEntry(m"label.menu.disconnect", IconSource.LinkSlash, SoundSource.InterfaceClickLow) {
disconnectFromAll() disconnectFromAll()
}) })
} }
menu.addEntry(ContextMenuEntry("Remove", IconSource.Delete, SoundSource.InterfaceClickLow) { menu.addEntry(ContextMenuEntry(m"label.menu.remove", IconSource.Delete, SoundSource.InterfaceClickLow) {
destroy() destroy()
}) })
} }
@ -103,11 +104,11 @@ abstract class Node extends Widget with MouseHandler with HoverHandler with Pers
super.update() super.update()
if (isHovered || isMoving) { if (isHovered || isMoving) {
root.get.statusBar.addMouseEntry("icons/RMB", "Menu") root.get.statusBar.addMouseEntry("icons/RMB", m"label.bar.menu")
root.get.statusBar.addMouseEntry("icons/DragLMB", "Move node") root.get.statusBar.addMouseEntry("icons/DragLMB", m"label.bar.moveNode")
if (ports.nonEmpty) { if (ports.nonEmpty) {
root.get.statusBar.addMouseEntry("icons/DragRMB", "Connect/Disconnect") root.get.statusBar.addMouseEntry("icons/DragRMB", m"label.bar.connectDisconnect")
} }
} }
} }

View File

@ -3,10 +3,9 @@ package ocelot.desktop.node
import ocelot.desktop.entity.{Camera, OcelotBlock, OpenFMRadio} import ocelot.desktop.entity.{Camera, OcelotBlock, OpenFMRadio}
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.node.nodes._ import ocelot.desktop.node.nodes._
import totoro.ocelot.brain.entity.{ import ocelot.desktop.util.Message
Cable, Case, ColorfulLamp, FloppyDiskDrive, HologramProjector, IronNoteBlock, Microcontroller, NoteBlock, Rack, Raid, import ocelot.desktop.util.Message.LocalizedMessage
Relay, Screen, TapeDrive, import totoro.ocelot.brain.entity.{Cable, Case, ColorfulLamp, FloppyDiskDrive, HologramProjector, IronNoteBlock, Microcontroller, NoteBlock, Rack, Raid, Relay, Screen, TapeDrive}
}
import totoro.ocelot.brain.util.Tier import totoro.ocelot.brain.util.Tier
import scala.collection.mutable import scala.collection.mutable
@ -16,7 +15,7 @@ object NodeRegistry {
private var group: NodeTypeGroup = _ private var group: NodeTypeGroup = _
private def nextGroup(name: String): Unit = { private def nextGroup(name: Message): Unit = {
group = new NodeTypeGroup(name) group = new NodeTypeGroup(name)
groups += group groups += group
} }
@ -27,89 +26,89 @@ object NodeRegistry {
// ------------------------------ Original nodes ------------------------------ // ------------------------------ Original nodes ------------------------------
nextGroup("Original") nextGroup(m"selector.group.original")
for (tier <- Tier.One to Tier.Creative) { for (tier <- Tier.One to Tier.Creative) {
addType(NodeType(s"Computer Case (${tier.label})", IconSource.Nodes.Computer.Default, tier) { addType(NodeType(m"component.computer", IconSource.Nodes.Computer.Default, tier) {
new ComputerNode(new Case(tier)) new ComputerNode(new Case(tier))
}) })
} }
addType(NodeType("Rack", IconSource.Nodes.Rack.Default, None) { addType(NodeType(m"component.rack", IconSource.Nodes.Rack.Default, None) {
new RackNode(new Rack) new RackNode(new Rack)
}) })
for (tier <- Tier.One to Tier.Three) { for (tier <- Tier.One to Tier.Three) {
addType(NodeType(s"Screen (${tier.label})", IconSource.Nodes.Screen.Standalone, tier) { addType(NodeType(m"component.screen", IconSource.Nodes.Screen.Standalone, tier) {
val node = new ScreenNode(new Screen(tier)) val node = new ScreenNode(new Screen(tier))
node.attachKeyboard() node.attachKeyboard()
node node
}) })
} }
addType(NodeType("Disk Drive", IconSource.Nodes.DiskDrive.Default, None) { addType(NodeType(m"component.diskDrive", IconSource.Nodes.DiskDrive.Default, None) {
new DiskDriveNode(new FloppyDiskDrive()) new DiskDriveNode(new FloppyDiskDrive())
}) })
addType(NodeType("Raid", IconSource.Nodes.Raid.Default, None) { addType(NodeType(m"component.raid", IconSource.Nodes.Raid.Default, None) {
new RaidNode(new Raid) new RaidNode(new Raid)
}) })
for (tier <- Tier.One to Tier.Two) { for (tier <- Tier.One to Tier.Two) {
addType(NodeType(s"Hologram Projector (${tier.label})", IconSource.Nodes.HologramProjector(tier), None) { addType(NodeType(m"component.hologramProjector", IconSource.Nodes.HologramProjector(tier), tier) {
new HologramProjectorNode(new HologramProjector(tier)) new HologramProjectorNode(new HologramProjector(tier))
}) })
} }
addType(NodeType("Note Block", IconSource.Nodes.NoteBlock, None) { addType(NodeType(m"component.noteBlock", IconSource.Nodes.NoteBlock, None) {
new NoteBlockNode(new NoteBlock) new NoteBlockNode(new NoteBlock)
}) })
addType(NodeType("Microcontroller", IconSource.Nodes.Microcontroller.Default, None) { addType(NodeType(m"component.microcontroller", IconSource.Nodes.Microcontroller.Default, None) {
new MicrocontrollerNode(new Microcontroller(Tier.Two)) new MicrocontrollerNode(new Microcontroller(Tier.Two))
}) })
addType(NodeType("Relay", IconSource.Nodes.Relay, None) { addType(NodeType(m"component.relay", IconSource.Nodes.Relay, None) {
new RelayNode(new Relay) new RelayNode(new Relay)
}) })
addType(NodeType("Chest", IconSource.Nodes.Chest, None) { addType(NodeType(m"component.chest", IconSource.Nodes.Chest, None) {
new ChestNode new ChestNode
}) })
addType(NodeType("Cable", IconSource.Nodes.Cable, None) { addType(NodeType(m"component.cable", IconSource.Nodes.Cable, None) {
new CableNode(new Cable) new CableNode(new Cable)
}) })
// ------------------------------ Addon nodes ------------------------------ // ------------------------------ Addon nodes ------------------------------
nextGroup("Addons") nextGroup(m"selector.group.addons")
addType(NodeType("Iron Note Block", IconSource.Nodes.IronNoteBlock, None) { addType(NodeType(m"component.ironNoteBlock", IconSource.Nodes.IronNoteBlock, None) {
new IronNoteBlockNode(new IronNoteBlock) new IronNoteBlockNode(new IronNoteBlock)
}) })
addType(NodeType("Camera", IconSource.Nodes.Camera, None) { addType(NodeType(m"component.camera", IconSource.Nodes.Camera, None) {
new CameraNode(new Camera) new CameraNode(new Camera)
}) })
addType(NodeType("Colorful Lamp", IconSource.Nodes.Lamp, None) { addType(NodeType(m"component.colorfulLamp", IconSource.Nodes.Lamp, None) {
new ColorfulLampNode(new ColorfulLamp) new ColorfulLampNode(new ColorfulLamp)
}) })
addType(NodeType("OpenFM Radio", IconSource.Nodes.OpenFMRadio, None) { addType(NodeType(m"component.openFmRadio", IconSource.Nodes.OpenFMRadio, None) {
new OpenFMRadioNode(new OpenFMRadio) new OpenFMRadioNode(new OpenFMRadio)
}) })
addType(NodeType("Tape Drive", IconSource.Nodes.TapeDrive, None) { addType(NodeType(m"component.tapeDrive", IconSource.Nodes.TapeDrive, None) {
new TapeDriveNode(new TapeDrive) new TapeDriveNode(new TapeDrive)
}) })
// ------------------------------ Custom nodes ------------------------------ // ------------------------------ Custom nodes ------------------------------
nextGroup("Custom") nextGroup(m"selector.group.custom")
addType(NodeType("Ocelot Block", IconSource.Nodes.OcelotBlock.Default, None) { addType(NodeType(m"component.ocelot.block", IconSource.Nodes.OcelotBlock.Default, None) {
new OcelotBlockNode(new OcelotBlock) new OcelotBlockNode(new OcelotBlock)
}) })
} }

View File

@ -1,19 +1,24 @@
package ocelot.desktop.node package ocelot.desktop.node
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.util.Message
import totoro.ocelot.brain.util.Tier.Tier import totoro.ocelot.brain.util.Tier.Tier
class NodeType(val name: String, val icon: IconSource, val tier: Option[Tier], factory: => Node) class NodeType(val name: Message, val icon: IconSource, val tier: Option[Tier], factory: => Node)
extends Ordered[NodeType] { extends Ordered[NodeType] {
def make(): Node = factory def make(): Node = factory
override def compare(that: NodeType): Int = this.name.compare(that.name) override def compare(that: NodeType): Int = {
val compareNames = this.name.value.compare(that.name.value)
if (compareNames == 0) this.tier.map(_.num).getOrElse(0).compare(that.tier.map(_.num).getOrElse(0))
else compareNames
}
} }
object NodeType { object NodeType {
def apply(name: String, icon: IconSource, tier: Tier)(factory: => Node): NodeType = def apply(name: Message, icon: IconSource, tier: Tier)(factory: => Node): NodeType =
new NodeType(name, icon, Some(tier), factory) new NodeType(name, icon, Some(tier), factory)
def apply(name: String, icon: IconSource, tier: Option[Tier])(factory: => Node): NodeType = def apply(name: Message, icon: IconSource, tier: Option[Tier])(factory: => Node): NodeType =
new NodeType(name, icon, tier, factory) new NodeType(name, icon, tier, factory)
} }

View File

@ -1,7 +1,9 @@
package ocelot.desktop.node package ocelot.desktop.node
import ocelot.desktop.util.Message
import scala.collection.mutable import scala.collection.mutable
class NodeTypeGroup(val name: String) { class NodeTypeGroup(val name: Message) {
val types: mutable.ArrayBuffer[NodeType] = mutable.ArrayBuffer[NodeType]() val types: mutable.ArrayBuffer[NodeType] = mutable.ArrayBuffer[NodeType]()
} }

View File

@ -8,6 +8,7 @@ import ocelot.desktop.ui.event.handlers.{HoverHandler, MouseHandler}
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.tooltip.LabelTooltip import ocelot.desktop.ui.widget.tooltip.LabelTooltip
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Spritesheet, TierColor} import ocelot.desktop.util.{Spritesheet, TierColor}
class NodeTypeWidget(val nodeType: NodeType) extends Widget with MouseHandler with HoverHandler { class NodeTypeWidget(val nodeType: NodeType) extends Widget with MouseHandler with HoverHandler {
@ -27,7 +28,7 @@ class NodeTypeWidget(val nodeType: NodeType) extends Widget with MouseHandler wi
else onHoverLeave() else onHoverLeave()
} }
private val labelTooltip = new LabelTooltip(nodeType.name) private val labelTooltip = new LabelTooltip(nodeType.name + nodeType.tier.map(tier => s" (${m"${tier.label}"})").getOrElse(""))
def onHoverEnter(): Unit = def onHoverEnter(): Unit =
root.get.tooltipPool.addTooltip(labelTooltip) root.get.tooltipPool.addTooltip(labelTooltip)
@ -44,7 +45,7 @@ class NodeTypeWidget(val nodeType: NodeType) extends Widget with MouseHandler wi
position.y + Size / 2 - size.height / 2, position.y + Size / 2 - size.height / 2,
size.width, size.width,
size.height, size.height,
nodeType.tier.map(TierColor.get).getOrElse(Color.White), if (nodeType.icon.tierTint) nodeType.tier.map(TierColor.get).getOrElse(Color.White) else Color.White,
nodeType.icon.animation, nodeType.icon.animation,
) )
} }
@ -52,7 +53,7 @@ class NodeTypeWidget(val nodeType: NodeType) extends Widget with MouseHandler wi
override def update(): Unit = { override def update(): Unit = {
super.update() super.update()
if (isHovered) { if (isHovered) {
root.get.statusBar.addMouseEntry("icons/LMB", "Add node") root.get.statusBar.addMouseEntry("icons/LMB", m"label.bar.addNode")
} }
} }
} }

View File

@ -2,10 +2,11 @@ package ocelot.desktop.node
import ocelot.desktop.ui.event.sources.KeyEvents import ocelot.desktop.ui.event.sources.KeyEvents
import ocelot.desktop.ui.event.{ClickEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, MouseEvent}
import ocelot.desktop.util.Message
trait ShiftClickNode extends Node { trait ShiftClickNode extends Node {
protected def onShiftClick(event: ClickEvent): Unit protected def onShiftClick(event: ClickEvent): Unit
protected def hoveredShiftStatusBarText: String protected def hoveredShiftStatusBarText: Message
override def onClick(event: ClickEvent): Unit = { override def onClick(event: ClickEvent): Unit = {
event match { event match {

View File

@ -3,7 +3,7 @@ package ocelot.desktop.node
import ocelot.desktop.ui.event.sources.KeyEvents import ocelot.desktop.ui.event.sources.KeyEvents
import ocelot.desktop.ui.event.{ClickEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, MouseEvent}
import ocelot.desktop.ui.widget.window.{Window, Windowed} import ocelot.desktop.ui.widget.window.{Window, Windowed}
import org.lwjgl.input.Keyboard import ocelot.desktop.util.Message.LocalizedMessage
trait WindowedNode[T <: Window] extends Node with Windowed[T] { trait WindowedNode[T <: Window] extends Node with Windowed[T] {
override def dispose(): Unit = { override def dispose(): Unit = {
@ -14,7 +14,7 @@ trait WindowedNode[T <: Window] extends Node with Windowed[T] {
override def update(): Unit = { override def update(): Unit = {
if (isHovered || isMoving) if (isHovered || isMoving)
root.get.statusBar.addMouseEntry("icons/LMB", if (windowCreated && window.isOpen) "Close" else "Open") root.get.statusBar.addMouseEntry("icons/LMB", if (windowCreated && window.isOpen) m"label.bar.close" else m"label.bar.open")
super.update() super.update()
} }

View File

@ -8,7 +8,8 @@ import ocelot.desktop.ui.event.ClickEvent
import ocelot.desktop.ui.widget.contextmenu.ContextMenu import ocelot.desktop.ui.widget.contextmenu.ContextMenu
import ocelot.desktop.ui.widget.slot._ import ocelot.desktop.ui.widget.slot._
import ocelot.desktop.util.ComputerType.ComputerType import ocelot.desktop.util.ComputerType.ComputerType
import ocelot.desktop.util.{AudibleComputerAware, ComputerType, DrawUtils, TierColor} import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{AudibleComputerAware, ComputerType, DrawUtils, Message, TierColor}
import ocelot.desktop.windows.ComputerWindow import ocelot.desktop.windows.ComputerWindow
import totoro.ocelot.brain.entity.Case import totoro.ocelot.brain.entity.Case
import totoro.ocelot.brain.entity.traits.Inventory import totoro.ocelot.brain.entity.traits.Inventory
@ -113,5 +114,5 @@ class ComputerNode(val computerCase: Case)
override protected def onShiftClick(event: ClickEvent): Unit = toggleIsTurnedOn() override protected def onShiftClick(event: ClickEvent): Unit = toggleIsTurnedOn()
override protected def hoveredShiftStatusBarText: String = if (computer.machine.isRunning) "Turn off" else "Turn on" override protected def hoveredShiftStatusBarText: Message = if (computer.machine.isRunning) m"label.menu.turnOff" else m"label.menu.turnOn"
} }

View File

@ -8,7 +8,8 @@ import ocelot.desktop.node.{EntityNode, LabeledEntityNode, ShiftClickNode, Windo
import ocelot.desktop.ui.event.ClickEvent import ocelot.desktop.ui.event.ClickEvent
import ocelot.desktop.ui.event.handlers.DiskActivityHandler import ocelot.desktop.ui.event.handlers.DiskActivityHandler
import ocelot.desktop.ui.widget.contextmenu.ContextMenu import ocelot.desktop.ui.widget.contextmenu.ContextMenu
import ocelot.desktop.util.DiskDriveAware import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{DiskDriveAware, Message}
import ocelot.desktop.windows.DiskDriveWindow import ocelot.desktop.windows.DiskDriveWindow
import totoro.ocelot.brain.entity.FloppyDiskDrive import totoro.ocelot.brain.entity.FloppyDiskDrive
@ -63,5 +64,5 @@ class DiskDriveNode(entity: FloppyDiskDrive)
eject() eject()
} }
override protected def hoveredShiftStatusBarText: String = "Eject floppy" override protected def hoveredShiftStatusBarText: Message = m"label.menu.ejectFloppy"
} }

View File

@ -3,6 +3,8 @@ package ocelot.desktop.node.nodes
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.node.nodes.IronNoteBlockNode.{Instruments, NumberOfPitches} import ocelot.desktop.node.nodes.IronNoteBlockNode.{Instruments, NumberOfPitches}
import ocelot.desktop.ui.event.{ClickEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, MouseEvent}
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.IronNoteBlock import totoro.ocelot.brain.entity.IronNoteBlock
import totoro.ocelot.brain.event.{EventBus, NoteBlockTriggerEvent} import totoro.ocelot.brain.event.{EventBus, NoteBlockTriggerEvent}
@ -30,17 +32,17 @@ class IronNoteBlockNode(val ironNoteBlock: IronNoteBlock) extends NoteBlockNodeB
object IronNoteBlockNode { object IronNoteBlockNode {
val NumberOfPitches: Int = 24 val NumberOfPitches: Int = 24
val Instruments: List[(String, String)] = List( val Instruments: List[(String, Message)] = List(
("harp", "Harp"), ("harp", m"component.noteBlock.harp"),
("basedrum", "Bass Drum (Stone)"), ("basedrum", m"component.noteBlock.basedrum"),
("snare", "Snare Drum (Sand)"), ("snare", m"component.noteBlock.snare"),
("hat", "Hi-hat (Glass)"), ("hat", m"component.noteBlock.hat"),
("bass", "Bass (Wood)"), ("bass", m"component.noteBlock.bass"),
("flute", "Flute (Clay)"), ("flute", m"component.noteBlock.flute"),
("bell", "Glockenspiel (Gold)"), ("bell", m"component.noteBlock.bell"),
("guitar", "Guitar (Wool)"), ("guitar", m"component.noteBlock.guitar"),
("chime", "Chimes (Packed Ice)"), ("chime", m"component.noteBlock.chime"),
("xylophone", "Xylophone (Bone)"), ("xylophone", m"component.noteBlock.xylophone"),
("pling", "Electric Piano (Glowstone)"), ("pling", m"component.noteBlock.pling"),
) )
} }

View File

@ -8,7 +8,8 @@ import ocelot.desktop.ui.event.ClickEvent
import ocelot.desktop.ui.widget.contextmenu.ContextMenu import ocelot.desktop.ui.widget.contextmenu.ContextMenu
import ocelot.desktop.ui.widget.slot._ import ocelot.desktop.ui.widget.slot._
import ocelot.desktop.util.ComputerType.ComputerType import ocelot.desktop.util.ComputerType.ComputerType
import ocelot.desktop.util.{ComputerAware, ComputerType, DefaultSlotItemsFillable, DrawUtils} import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{ComputerAware, ComputerType, DefaultSlotItemsFillable, DrawUtils, Message}
import ocelot.desktop.windows.ComputerWindow import ocelot.desktop.windows.ComputerWindow
import totoro.ocelot.brain.entity.Microcontroller import totoro.ocelot.brain.entity.Microcontroller
import totoro.ocelot.brain.entity.traits.Inventory import totoro.ocelot.brain.entity.traits.Inventory
@ -145,5 +146,5 @@ class MicrocontrollerNode(val microcontroller: Microcontroller)
override protected def onShiftClick(event: ClickEvent): Unit = toggleIsTurnedOn() override protected def onShiftClick(event: ClickEvent): Unit = toggleIsTurnedOn()
override protected def hoveredShiftStatusBarText: String = if (computer.machine.isRunning) "Turn off" else "Turn on" override protected def hoveredShiftStatusBarText: Message = if (computer.machine.isRunning) m"label.menu.turnOff" else m"label.menu.turnOn"
} }

View File

@ -3,6 +3,7 @@ package ocelot.desktop.node.nodes
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.ui.event.{ClickEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, MouseEvent}
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuIcon, ContextMenuSubmenu} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry, ContextMenuIcon, ContextMenuSubmenu}
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.NoteBlock import totoro.ocelot.brain.entity.NoteBlock
import totoro.ocelot.brain.event.{EventBus, NoteBlockTriggerEvent} import totoro.ocelot.brain.event.{EventBus, NoteBlockTriggerEvent}
@ -10,14 +11,14 @@ class NoteBlockNode(val noteBlock: NoteBlock) extends NoteBlockNodeBase(noteBloc
override def iconSource: IconSource = IconSource.Nodes.NoteBlock override def iconSource: IconSource = IconSource.Nodes.NoteBlock
override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = { override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = {
menu.addEntry(new ContextMenuSubmenu("Instrument", Some(ContextMenuIcon(IconSource.Guitar))) { menu.addEntry(new ContextMenuSubmenu(m"label.menu.instrument", Some(ContextMenuIcon(IconSource.Guitar))) {
{ {
val maxLen = NoteBlockNode.Instruments.map(_._2.length).max val maxLen = NoteBlockNode.Instruments.map(_._2.toString.length).max
for ((instrument, name) <- NoteBlockNode.Instruments) { for ((instrument, name) <- NoteBlockNode.Instruments) {
val dot = if (noteBlock.instrument == instrument) '•' else ' ' val dot = if (noteBlock.instrument == instrument) '•' else ' '
addEntry(ContextMenuEntry(name.padTo(maxLen, ' ') + dot) { addEntry(ContextMenuEntry(name.toString.padTo(maxLen, ' ') + dot) {
noteBlock.instrument = instrument noteBlock.instrument = instrument
}) })
} }
@ -43,21 +44,21 @@ class NoteBlockNode(val noteBlock: NoteBlock) extends NoteBlockNodeBase(noteBloc
object NoteBlockNode { object NoteBlockNode {
private val Instruments = List( private val Instruments = List(
("bass", "Bass (Wood)"), ("bass", m"component.noteBlock.bass"),
("snare", "Snare Drum (Sand)"), ("snare", m"component.noteBlock.snare"),
("hat", "Hi-hat (Glass)"), ("hat", m"component.noteBlock.hat"),
("basedrum", "Bass Drum (Stone)"), ("basedrum", m"component.noteBlock.basedrum"),
("bell", "Glockenspiel (Gold)"), ("bell", m"component.noteBlock.bell"),
("flute", "Flute (Clay)"), ("flute", m"component.noteBlock.flute"),
("chime", "Chimes (Packed Ice)"), ("chime", m"component.noteBlock.chime"),
("guitar", "Guitar (Wool)"), ("guitar", m"component.noteBlock.guitar"),
("xylophone", "Xylophone (Bone)"), ("xylophone", m"component.noteBlock.xylophone"),
("iron_xylophone", "Vibraphone (Iron)"), ("iron_xylophone", m"component.noteBlock.ironXylophone"),
("cow_bell", "Cow Bell (Soul Sand)"), ("cow_bell", m"component.noteBlock.cowBell"),
("didgeridoo", "Didgeridoo (Pumpkin)"), ("didgeridoo", m"component.noteBlock.didgeridoo"),
("bit", "Square Wave (Emerald)"), ("bit", m"component.noteBlock.bit"),
("banjo", "Banjo (Hay Bale)"), ("banjo", m"component.noteBlock.banjo"),
("pling", "Electric Piano (Glowstone)"), ("pling", m"component.noteBlock.pling"),
("harp", "Harp"), ("harp", m"component.noteBlock.harp"),
) )
} }

View File

@ -7,6 +7,7 @@ import ocelot.desktop.graphics.Graphics
import ocelot.desktop.node.{EntityNode, LabeledEntityNode} import ocelot.desktop.node.{EntityNode, LabeledEntityNode}
import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.BrainEvent import ocelot.desktop.ui.event.BrainEvent
import ocelot.desktop.util.Message.LocalizedMessage
import totoro.ocelot.brain.entity.traits.{Entity, Environment} import totoro.ocelot.brain.entity.traits.{Entity, Environment}
import totoro.ocelot.brain.event.NoteBlockTriggerEvent import totoro.ocelot.brain.event.NoteBlockTriggerEvent
@ -47,6 +48,6 @@ abstract class NoteBlockNodeBase(entity: Entity with Environment) extends Entity
super.update() super.update()
if (isHovered || isMoving) if (isHovered || isMoving)
root.get.statusBar.addMouseEntry("icons/LMB", "Play sample") root.get.statusBar.addMouseEntry("icons/LMB", m"label.bar.playSample")
} }
} }

View File

@ -10,7 +10,8 @@ import ocelot.desktop.node.nodes.OcelotBlockNode.ActivityFadeOutMs
import ocelot.desktop.node.{EntityNode, LabeledEntityNode, OcelotLogParticleNode, WindowedNode} import ocelot.desktop.node.{EntityNode, LabeledEntityNode, OcelotLogParticleNode, WindowedNode}
import ocelot.desktop.ui.widget.LogWidget import ocelot.desktop.ui.widget.LogWidget
import ocelot.desktop.ui.widget.LogWidget.LogEntry import ocelot.desktop.ui.widget.LogWidget.LogEntry
import ocelot.desktop.util.OcelotInterfaceLogStorage import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, OcelotInterfaceLogStorage}
import ocelot.desktop.windows.OcelotInterfaceWindow import ocelot.desktop.windows.OcelotInterfaceWindow
class OcelotBlockNode(val ocelot: OcelotBlock) class OcelotBlockNode(val ocelot: OcelotBlock)
@ -20,7 +21,7 @@ class OcelotBlockNode(val ocelot: OcelotBlock)
with OcelotInterfaceLogStorage with OcelotInterfaceLogStorage
with WindowedNode[OcelotInterfaceWindow] { with WindowedNode[OcelotInterfaceWindow] {
override def name: String = "Ocelot Block" override def name: Message = m"component.ocelot.block"
override def iconSource: IconSource = IconSource.Nodes.OcelotBlock.Default override def iconSource: IconSource = IconSource.Nodes.OcelotBlock.Default

View File

@ -9,7 +9,8 @@ import ocelot.desktop.node.Node.{HighlightThickness, NoHighlightSize, Size, Texe
import ocelot.desktop.node.{ComputerAwareNode, NodePort, WindowedNode} import ocelot.desktop.node.{ComputerAwareNode, NodePort, WindowedNode}
import ocelot.desktop.ui.event.{BrainEvent, ClickEvent} import ocelot.desktop.ui.event.{BrainEvent, ClickEvent}
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.util.DrawUtils import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{DrawUtils, Message}
import ocelot.desktop.windows.RackWindow import ocelot.desktop.windows.RackWindow
import totoro.ocelot.brain.entity.traits.{ComponentInventory, Environment, Inventory, RackMountable} import totoro.ocelot.brain.entity.traits.{ComponentInventory, Environment, Inventory, RackMountable}
import totoro.ocelot.brain.entity.{Rack, Server} import totoro.ocelot.brain.entity.{Rack, Server}
@ -162,7 +163,7 @@ class RackNode(val rack: Rack) extends ComputerAwareNode(rack) with WindowedNode
} }
} }
override protected def hoveredShiftStatusBarText: String = "Turn server on/off" override protected def hoveredShiftStatusBarText: Message = m"label.bar.turnServerOnOff"
// ---------------------------- Event handlers ---------------------------- // ---------------------------- Event handlers ----------------------------
@ -183,7 +184,7 @@ object RackNode {
def addContextMenuEntriesOfMountable(menu: ContextMenu, item: Option[RackMountableItem]): Unit = { def addContextMenuEntriesOfMountable(menu: ContextMenu, item: Option[RackMountableItem]): Unit = {
item match { item match {
case Some(serverItem: ServerItem) => case Some(serverItem: ServerItem) =>
menu.addEntry(ContextMenuEntry("Set up", IconSource.Window) { menu.addEntry(ContextMenuEntry(m"label.menu.setup", IconSource.Window) {
serverItem.window.open() serverItem.window.open()
}) })
@ -203,9 +204,9 @@ object RackNode {
menu.addEntry(ContextMenuEntry( menu.addEntry(ContextMenuEntry(
if (diskDriveMountableItem.isFloppyItemPresent) if (diskDriveMountableItem.isFloppyItemPresent)
"Change floppy" m"label.menu.changeFloppy"
else else
"Set floppy", m"label.menu.setFloppy",
IconSource.Save, IconSource.Save,
) { ) {
diskDriveMountableItem.window.open() diskDriveMountableItem.window.open()

View File

@ -11,6 +11,7 @@ import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.ClickEvent import ocelot.desktop.ui.event.ClickEvent
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.{ScreenAspectRatioDialog, TickUpdatable} import ocelot.desktop.ui.widget.{ScreenAspectRatioDialog, TickUpdatable}
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.TierColor import ocelot.desktop.util.TierColor
import ocelot.desktop.windows.ScreenWindow import ocelot.desktop.windows.ScreenWindow
import ocelot.desktop.{OcelotDesktop, Settings} import ocelot.desktop.{OcelotDesktop, Settings}
@ -98,25 +99,25 @@ class ScreenNode(val screen: Screen)
override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = { override def setupContextMenu(menu: ContextMenu, event: ClickEvent): Unit = {
// no synchronization here: the methods to turn the screen on/off are indirect. // no synchronization here: the methods to turn the screen on/off are indirect.
if (screen.getPowerState) { if (screen.getPowerState) {
menu.addEntry(ContextMenuEntry("Turn off", IconSource.Power) { menu.addEntry(ContextMenuEntry(m"label.menu.turnOff", IconSource.Power) {
screen.setPowerState(false) screen.setPowerState(false)
}) })
} else { } else {
menu.addEntry(ContextMenuEntry("Turn on", IconSource.Power) { menu.addEntry(ContextMenuEntry(m"label.menu.turnOn", IconSource.Power) {
screen.setPowerState(true) screen.setPowerState(true)
}) })
} }
menu.addEntry(ContextMenuEntry("Set aspect ratio", IconSource.AspectRatio) { menu.addEntry(ContextMenuEntry(m"label.menu.setAspectRatio", IconSource.AspectRatio) {
new ScreenAspectRatioDialog(this).show() new ScreenAspectRatioDialog(this).show()
}) })
if (keyboard.isDefined) { if (keyboard.isDefined) {
menu.addEntry(ContextMenuEntry("Remove keyboard", IconSource.KeyboardOff) { menu.addEntry(ContextMenuEntry(m"label.menu.removeKeyboard", IconSource.KeyboardOff) {
detachKeyboard() detachKeyboard()
}) })
} else { } else {
menu.addEntry(ContextMenuEntry("Add keyboard", IconSource.Keyboard) { menu.addEntry(ContextMenuEntry(m"label.menu.addKeyboard", IconSource.Keyboard) {
attachKeyboard() attachKeyboard()
}) })
} }

View File

@ -1,6 +1,7 @@
package ocelot.desktop.ui.swing package ocelot.desktop.ui.swing
import buildinfo.BuildInfo import buildinfo.BuildInfo
import ocelot.desktop.util.Message
import java.awt.Window.Type import java.awt.Window.Type
import java.awt.{Color, Dimension, Font, Insets, Rectangle} import java.awt.{Color, Dimension, Font, Insets, Rectangle}
@ -92,8 +93,8 @@ class SplashScreen extends JDialog {
progressBar.setBounds(0, 440, (imageWidth * percent).toInt, 3) progressBar.setBounds(0, 440, (imageWidth * percent).toInt, 3)
} }
def setStatus(text: String, percent: Float): Unit = { def setStatus(text: Message, percent: Float): Unit = {
status.setText(text) status.setText(text.toString)
setProgress(percent) setProgress(percent)
} }
} }

View File

@ -9,7 +9,7 @@ import ocelot.desktop.ui.event.handlers.{HoverHandler, MouseHandler}
import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent}
import ocelot.desktop.ui.widget.tooltip.Tooltip import ocelot.desktop.ui.widget.tooltip.Tooltip
import ocelot.desktop.ui.widget.traits.HoverAnimation import ocelot.desktop.ui.widget.traits.HoverAnimation
import ocelot.desktop.util.DrawUtils import ocelot.desktop.util.{DrawUtils, Message}
class Button(tooltip: Option[Tooltip] = None) extends Widget with MouseHandler with HoverHandler with HoverAnimation { class Button(tooltip: Option[Tooltip] = None) extends Widget with MouseHandler with HoverHandler with HoverAnimation {
@ -19,7 +19,7 @@ class Button(tooltip: Option[Tooltip] = None) extends Widget with MouseHandler w
override protected val hoverAnimationColorDefault: Color = colorScheme("ButtonBackground") override protected val hoverAnimationColorDefault: Color = colorScheme("ButtonBackground")
override protected val hoverAnimationColorActive: Color = colorScheme("ButtonBackgroundActive") override protected val hoverAnimationColorActive: Color = colorScheme("ButtonBackgroundActive")
def text: String = "" def text: Message = ""
def onClick(): Unit = {} def onClick(): Unit = {}
@ -41,7 +41,7 @@ class Button(tooltip: Option[Tooltip] = None) extends Widget with MouseHandler w
} }
} }
override def minimumSize: Size2D = Size2D(24 + text.length * 8, 24) override def minimumSize: Size2D = Size2D(24 + text.toString.length * 8, 24)
override def maximumSize: Size2D = minimumSize override def maximumSize: Size2D = minimumSize
@ -62,8 +62,8 @@ class Button(tooltip: Option[Tooltip] = None) extends Widget with MouseHandler w
g.background = Color.Transparent g.background = Color.Transparent
g.foreground = foreground g.foreground = foreground
val textWidth = text.iterator.map(g.font.charWidth(_)).sum val textWidth = text.toString.iterator.map(g.font.charWidth(_)).sum
g.text(position.x + ((width - textWidth) / 2).round, position.y + 4, text) g.text(position.x + ((width - textWidth) / 2).round, position.y + 4, text.toString)
} }
protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClick protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClick

View File

@ -6,7 +6,8 @@ import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.ChangeSimulationSpeedDialog.validateIntervalUs import ocelot.desktop.ui.widget.ChangeSimulationSpeedDialog.validateIntervalUs
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.util.Orientation import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, Orientation}
import scala.concurrent.duration.{Duration, DurationLong} import scala.concurrent.duration.{Duration, DurationLong}
@ -25,7 +26,7 @@ class ChangeSimulationSpeedDialog extends ModalDialog {
new Widget { new Widget {
override val layout = new LinearLayout(this, orientation = Orientation.Vertical) override val layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= new PaddingBox(new Label("Change simulation speed"), Padding2D(bottom = 16)) children :+= new PaddingBox(new Label(m"label.menu.changeSimulationSpeed"), Padding2D(bottom = 16))
private var inputTPS: TextInput = _ private var inputTPS: TextInput = _
private var inputMSPT: TextInput = _ private var inputMSPT: TextInput = _
@ -76,9 +77,9 @@ class ChangeSimulationSpeedDialog extends ModalDialog {
override def onConfirm(): Unit = confirm() override def onConfirm(): Unit = confirm()
} }
children :+= new Label("Milliseconds per tick:") children :+= new Label(m"label.dialog.speed.msPerTick")
children :+= new PaddingBox(inputMSPT, Padding2D(bottom = 8)) children :+= new PaddingBox(inputMSPT, Padding2D(bottom = 8))
children :+= new Label("Ticks per second:") children :+= new Label(m"label.dialog.speed.ticksPerSecond")
children :+= new PaddingBox(inputTPS, Padding2D(bottom = 8)) children :+= new PaddingBox(inputTPS, Padding2D(bottom = 8))
children :+= new Widget { children :+= new Widget {
@ -86,7 +87,7 @@ class ChangeSimulationSpeedDialog extends ModalDialog {
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Cancel" override def text: Message = m"button.cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow
override def onClick(): Unit = close() override def onClick(): Unit = close()
}, },
@ -94,7 +95,7 @@ class ChangeSimulationSpeedDialog extends ModalDialog {
) )
children :+= new Button { children :+= new Button {
override def text: String = "Apply" override def text: Message = m"button.apply"
override def onClick(): Unit = confirm() override def onClick(): Unit = confirm()
override def enabled: Boolean = tickInterval.nonEmpty override def enabled: Boolean = tickInterval.nonEmpty
} }

View File

@ -7,9 +7,9 @@ import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.event.handlers.MouseHandler import ocelot.desktop.ui.event.handlers.MouseHandler
import ocelot.desktop.ui.event.{ClickEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, MouseEvent}
import ocelot.desktop.ui.widget.traits.HoverAnimation import ocelot.desktop.ui.widget.traits.HoverAnimation
import ocelot.desktop.util.DrawUtils import ocelot.desktop.util.{DrawUtils, Message}
class Checkbox(val label: String, val initialValue: Boolean = false, val isSmall: Boolean = false) class Checkbox(val label: Message, val initialValue: Boolean = false, val isSmall: Boolean = false)
extends Widget with MouseHandler with HoverAnimation { extends Widget with MouseHandler with HoverAnimation {
override protected val hoverAnimationColorDefault: Color = ColorScheme("CheckboxBackground") override protected val hoverAnimationColorDefault: Color = ColorScheme("CheckboxBackground")
@ -42,7 +42,7 @@ class Checkbox(val label: String, val initialValue: Boolean = false, val isSmall
private var corrected: Boolean = false private var corrected: Boolean = false
private var textWidth = label.length * 8 private var textWidth = label.length * 8
private def wideWidth(g: Graphics): Int = label.map(g.font.charWidth(_)).sum private def wideWidth(g: Graphics): Int = label.toString.map(g.font.charWidth(_)).sum
override def minimumSize: Size2D = Size2D(textWidth, if (isSmall) 8 else 16) override def minimumSize: Size2D = Size2D(textWidth, if (isSmall) 8 else 16)
override def maximumSize: Size2D = minimumSize.copy(width = Float.PositiveInfinity) override def maximumSize: Size2D = minimumSize.copy(width = Float.PositiveInfinity)
@ -68,7 +68,7 @@ class Checkbox(val label: String, val initialValue: Boolean = false, val isSmall
} }
g.foreground = ColorScheme("CheckboxLabel") g.foreground = ColorScheme("CheckboxLabel")
g.text(position.x + boxSize + 8, position.y, label) g.text(position.x + boxSize + 8, position.y, label.toString)
g.setNormalFont() g.setNormalFont()
} }

View File

@ -4,10 +4,11 @@ import ocelot.desktop.audio.{ClickSoundSource, SoundSource}
import ocelot.desktop.geometry.Padding2D import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.util.Orientation import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, Orientation}
class CloseConfirmationDialog extends ModalDialog { class CloseConfirmationDialog extends ModalDialog {
protected def prompt: String = "Save workspace before exiting?" protected def prompt: Message = m"notification.saveBeforeExit"
children :+= new PaddingBox( children :+= new PaddingBox(
new Widget { new Widget {
@ -15,7 +16,7 @@ class CloseConfirmationDialog extends ModalDialog {
children :+= new PaddingBox( children :+= new PaddingBox(
new Label { new Label {
override def text: String = prompt override def text: Message = prompt
}, },
Padding2D(bottom = 16), Padding2D(bottom = 16),
) )
@ -23,7 +24,7 @@ class CloseConfirmationDialog extends ModalDialog {
children :+= new Widget { children :+= new Widget {
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Cancel" override def text: Message = m"button.cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow
override def onClick(): Unit = close() override def onClick(): Unit = close()
}, },
@ -34,7 +35,7 @@ class CloseConfirmationDialog extends ModalDialog {
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "No" override def text: Message = m"button.no"
override def onClick(): Unit = onNoSaveSelected() override def onClick(): Unit = onNoSaveSelected()
}, },
Padding2D(right = 8), Padding2D(right = 8),
@ -42,7 +43,7 @@ class CloseConfirmationDialog extends ModalDialog {
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Yes" override def text: Message = m"button.yes"
override def onClick(): Unit = onSaveSelected() override def onClick(): Unit = onSaveSelected()
}, },
Padding2D(right = 8), Padding2D(right = 8),

View File

@ -3,11 +3,12 @@ package ocelot.desktop.ui.widget
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
import ocelot.desktop.util.Message.LocalizedMessage
class ComponentUsageBar extends Widget with TickUpdatable { class ComponentUsageBar extends Widget with TickUpdatable {
var maxValue = 0 var maxValue = 0
var currentValue = 0 var currentValue = 0
var title = "Component usage" var title = m"label.window.computer.componentUsage"
private def drawText(g: Graphics, x: Float, y: Float, text: String): Unit = { private def drawText(g: Graphics, x: Float, y: Float, text: String): Unit = {
g.setSmallFont() g.setSmallFont()
@ -32,7 +33,7 @@ class ComponentUsageBar extends Widget with TickUpdatable {
// Text // Text
drawText(g, x - marginLeft / 2 - 4, position.y + 3, currentValue.toString) drawText(g, x - marginLeft / 2 - 4, position.y + 3, currentValue.toString)
drawText(g, x - marginLeft / 2 - 4, position.y + 18, s"($maxValue)") drawText(g, x - marginLeft / 2 - 4, position.y + 18, s"($maxValue)")
drawText(g, x + gridWidth / 2, position.y + 18, title) drawText(g, x + gridWidth / 2, position.y + 18, title.toString)
// Horizontal lines // Horizontal lines
g.rect(x, position.y, gridWidth, cellThickness, ColorScheme("HistogramGrid")) g.rect(x, position.y, gridWidth, cellThickness, ColorScheme("HistogramGrid"))

View File

@ -4,8 +4,9 @@ import ocelot.desktop.ColorScheme
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Vector2D import ocelot.desktop.geometry.Vector2D
import ocelot.desktop.node.Node import ocelot.desktop.node.Node
import ocelot.desktop.util.Message
class ComputerErrorMessageLabel(node: Node, override val text: String) extends Label { class ComputerErrorMessageLabel(node: Node, override val text: Message) extends Label {
override def isSmall: Boolean = true override def isSmall: Boolean = true
var alpha: Float = 1f var alpha: Float = 1f

View File

@ -7,9 +7,10 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.inventory.traits.DiskItem import ocelot.desktop.inventory.traits.DiskItem
import ocelot.desktop.ui.layout.{AlignItems, LinearLayout} import ocelot.desktop.ui.layout.{AlignItems, LinearLayout}
import ocelot.desktop.ui.widget.window.PanelWindow import ocelot.desktop.ui.widget.window.PanelWindow
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.SizeFormatting.formatSize import ocelot.desktop.util.SizeFormatting.formatSize
import ocelot.desktop.util.animation.ColorAnimation import ocelot.desktop.util.animation.ColorAnimation
import ocelot.desktop.util.{DiskDriveAware, Orientation} import ocelot.desktop.util.{DiskDriveAware, Message, Orientation}
import totoro.ocelot.brain.entity.traits.{DiskManaged, DiskUnmanaged} import totoro.ocelot.brain.entity.traits.{DiskManaged, DiskUnmanaged}
import totoro.ocelot.brain.util.DyeColor import totoro.ocelot.brain.util.DyeColor
@ -32,7 +33,7 @@ class DiskEditWindow(item: DiskItem) extends PanelWindow {
private def address: Option[String] = Option(item.entity.node).flatMap(node => Option(node.address)) private def address: Option[String] = Option(item.entity.node).flatMap(node => Option(node.address))
override protected def title: String = s"${item.diskKind} " + address.getOrElse("") override protected def title: Message = s"${item.diskKind} " + address.getOrElse("")
override protected def titleMaxLength: Int = 32 override protected def titleMaxLength: Int = 32
@ -41,9 +42,9 @@ class DiskEditWindow(item: DiskItem) extends PanelWindow {
children :+= new PaddingBox( children :+= new PaddingBox(
new Label { new Label {
override def text: String = diskSize match { override def text: Message = diskSize match {
case Some(used) => s"Used: ${formatSize(used)} / ${formatSize(diskCapacity)}" case Some(used) => s"${m"label.window.disk.used"}: ${formatSize(used)} / ${formatSize(diskCapacity)}"
case None => s"Capacity: ${formatSize(diskCapacity)}" case None => s"${m"label.window.disk.capacity"}: ${formatSize(diskCapacity)}"
} }
}, },
Padding2D(bottom = 12), Padding2D(bottom = 12),
@ -54,7 +55,7 @@ class DiskEditWindow(item: DiskItem) extends PanelWindow {
override val layout = new LinearLayout(this, override val layout = new LinearLayout(this,
orientation = Orientation.Horizontal, alignItems = AlignItems.Center) orientation = Orientation.Horizontal, alignItems = AlignItems.Center)
children :+= new Label("Label") children :+= new Label(m"label.window.disk.label")
children :+= new TextInput(item.label.getOrElse("")) { children :+= new TextInput(item.label.getOrElse("")) {
override def onConfirm(): Unit = { override def onConfirm(): Unit = {
@ -127,7 +128,7 @@ class DiskEditWindow(item: DiskItem) extends PanelWindow {
override val layout = new LinearLayout(this, orientation = Orientation.Horizontal, gap = 8) override val layout = new LinearLayout(this, orientation = Orientation.Horizontal, gap = 8)
children :+= new Button { children :+= new Button {
override def text: String = "Make read-only" override def text: Message = m"label.window.disk.makeReadOnly"
override def onClick(): Unit = item.lock() override def onClick(): Unit = item.lock()
@ -135,7 +136,7 @@ class DiskEditWindow(item: DiskItem) extends PanelWindow {
} }
children :+= new Button { children :+= new Button {
override def text: String = s"Make ${if (isManaged) "unmanaged" else "managed"}" override def text: Message = m"label.window.disk.make.${if (isManaged) "unmanaged" else "managed"}"
override def onClick(): Unit = item.setManaged(!isManaged) override def onClick(): Unit = item.setManaged(!isManaged)

View File

@ -0,0 +1,19 @@
package ocelot.desktop.ui.widget
import ocelot.desktop.geometry.Vector2D
import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
class Dropdown(options: List[String]) extends Button {
def onSelect(option: String): Unit = {}
private var opened = false
override def onClick(): Unit = {
opened = true
val menu = new ContextMenu()
options.foreach(option => menu.addEntry(ContextMenuEntry(option) { onSelect(option) }))
UiHandler.root.contextMenus.open(menu, position + Vector2D(0, height))
}
}

View File

@ -3,12 +3,13 @@ package ocelot.desktop.ui.widget
import ocelot.desktop.ColorScheme import ocelot.desktop.ColorScheme
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
import ocelot.desktop.util.Message
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer
class Histogram extends Widget { class Histogram extends Widget {
var value = "N/A" var value = "N/A"
var title = "Hello world" var title: Message = "Hello world"
var history: ArrayBuffer[Float] = ArrayBuffer(50) var history: ArrayBuffer[Float] = ArrayBuffer(50)
private def drawBars(g: Graphics): Unit = { private def drawBars(g: Graphics): Unit = {
@ -52,7 +53,7 @@ class Histogram extends Widget {
val gridHeight = horizontalLineCount * cellSize val gridHeight = horizontalLineCount * cellSize
// Text // Text
drawText(g, x + gridWidth / 2, title) drawText(g, x + gridWidth / 2, title.toString)
// Horizontal lines // Horizontal lines
for (i <- 0 until horizontalLineCount + 1) for (i <- 0 until horizontalLineCount + 1)

View File

@ -11,7 +11,7 @@ import ocelot.desktop.ui.widget.IconButton.{AnimationSpeed, Mode}
import ocelot.desktop.ui.widget.tooltip.LabelTooltip import ocelot.desktop.ui.widget.tooltip.LabelTooltip
import ocelot.desktop.ui.widget.traits.HoverAnimation import ocelot.desktop.ui.widget.traits.HoverAnimation
import ocelot.desktop.util.animation.{ColorAnimation, ValueAnimation} import ocelot.desktop.util.animation.{ColorAnimation, ValueAnimation}
import ocelot.desktop.util.{DrawUtils, Spritesheet} import ocelot.desktop.util.{DrawUtils, Message, Spritesheet}
class IconButton( class IconButton(
releasedIcon: String, releasedIcon: String,
@ -22,7 +22,7 @@ class IconButton(
mode: Mode = Mode.Regular, mode: Mode = Mode.Regular,
drawBackground: Boolean = false, drawBackground: Boolean = false,
padding: Float = 0, padding: Float = 0,
tooltip: Option[String] = None, tooltip: Option[Message] = None,
darkenActiveColorFactor: Float = 0f, darkenActiveColorFactor: Float = 0f,
val model: IconButton.Model = IconButton.DefaultModel(false), val model: IconButton.Model = IconButton.DefaultModel(false),
) extends Widget with MouseHandler with HoverHandler with HoverAnimation { ) extends Widget with MouseHandler with HoverHandler with HoverAnimation {

View File

@ -4,10 +4,11 @@ import ocelot.desktop.audio.{ClickSoundSource, SoundSource}
import ocelot.desktop.geometry.Padding2D import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.util.Orientation import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, Orientation}
class InputDialog( class InputDialog(
title: String, title: Message,
onConfirmed: String => Unit, onConfirmed: String => Unit,
initialText: String = "", initialText: String = "",
inputValidator: String => Boolean = _ => true, inputValidator: String => Boolean = _ => true,
@ -32,7 +33,7 @@ class InputDialog(
children :+= new PaddingBox( children :+= new PaddingBox(
new Label { new Label {
override def text: String = title override def text: Message = title
}, },
Padding2D(bottom = 8), Padding2D(bottom = 8),
) )
@ -42,13 +43,13 @@ class InputDialog(
children :+= new Widget { children :+= new Widget {
children :+= new Filler children :+= new Filler
children :+= new Button { children :+= new Button {
override def text: String = "Cancel" override def text: Message = m"button.cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow
override def onClick(): Unit = close() override def onClick(): Unit = close()
} }
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Ok" override def text: Message = m"button.ok"
override def onClick(): Unit = { override def onClick(): Unit = {
if (input.isInputValid) if (input.isInputValid)
confirm() confirm()

View File

@ -4,14 +4,15 @@ import ocelot.desktop.ColorScheme
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Size2D import ocelot.desktop.geometry.Size2D
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
import ocelot.desktop.util.Message
class Label(private val value: String = "", private val small: Boolean = false) extends Widget { class Label(private val value: Message = "", private val foreground: Color = ColorScheme("Label"), private val small: Boolean = false) extends Widget {
def text: String = value def text: Message = value
def isSmall: Boolean = small def isSmall: Boolean = small
def color: Color = ColorScheme("Label") def color: Color = foreground
private var textWidth = text.length * 8 private var textWidth = text.toString.length * 8
private def wideWidth(g: Graphics): Int = text.map(g.font.charWidth(_)).sum private def wideWidth(g: Graphics): Int = text.toString.map(g.font.charWidth(_)).sum
override def minimumSize: Size2D = Size2D(textWidth, if (isSmall) 8 else 16) override def minimumSize: Size2D = Size2D(textWidth, if (isSmall) 8 else 16)
override def maximumSize: Size2D = minimumSize.copy(width = Float.PositiveInfinity) override def maximumSize: Size2D = minimumSize.copy(width = Float.PositiveInfinity)
@ -23,7 +24,7 @@ class Label(private val value: String = "", private val small: Boolean = false)
g.background = Color.Transparent g.background = Color.Transparent
g.foreground = color g.foreground = color
g.text(position.x, position.y, text) g.text(position.x, position.y, text.toString)
g.setNormalFont() g.setNormalFont()
} }

View File

@ -7,6 +7,7 @@ import ocelot.desktop.ui.event.KeyEvent
import ocelot.desktop.ui.widget.contextmenu.{ContextMenuEntry, ContextMenuSubmenu} import ocelot.desktop.ui.widget.contextmenu.{ContextMenuEntry, ContextMenuSubmenu}
import ocelot.desktop.ui.widget.help.{AboutDialog, UpdateCheckerDialog} import ocelot.desktop.ui.widget.help.{AboutDialog, UpdateCheckerDialog}
import ocelot.desktop.ui.widget.settings.SettingsDialog import ocelot.desktop.ui.widget.settings.SettingsDialog
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.{ColorScheme, OcelotDesktop} import ocelot.desktop.{ColorScheme, OcelotDesktop}
import org.lwjgl.input.Keyboard import org.lwjgl.input.Keyboard
@ -20,30 +21,30 @@ class MenuBar extends Widget {
private def addEntry(w: Widget): Unit = entries.children :+= w private def addEntry(w: Widget): Unit = entries.children :+= w
addEntry(new MenuBarSubmenu( addEntry(new MenuBarSubmenu(
"File", m"label.menu.file",
menu => { menu => {
menu.addEntry(ContextMenuEntry("New", IconSource.Plus) { OcelotDesktop.newWorkspace() }) menu.addEntry(ContextMenuEntry(m"label.menu.file.new", IconSource.Plus) { OcelotDesktop.newWorkspace() })
menu.addEntry(ContextMenuEntry("Open", IconSource.Folder) { OcelotDesktop.showOpenDialog() }) menu.addEntry(ContextMenuEntry(m"label.menu.file.open", IconSource.Folder) { OcelotDesktop.showOpenDialog() })
menu.addEntry(ContextMenuEntry("Save", IconSource.Save) { OcelotDesktop.save() }) menu.addEntry(ContextMenuEntry(m"label.menu.file.save", IconSource.Save) { OcelotDesktop.save() })
menu.addEntry(ContextMenuEntry("Save as", IconSource.SaveAs) { OcelotDesktop.saveAs() }) menu.addEntry(ContextMenuEntry(m"label.menu.file.saveAs", IconSource.SaveAs) { OcelotDesktop.saveAs() })
menu.addSeparator() menu.addSeparator()
menu.addEntry(ContextMenuEntry("Exit", IconSource.Cross, SoundSource.InterfaceClickLow) { OcelotDesktop.exit() }) menu.addEntry(ContextMenuEntry(m"label.menu.file.exit", IconSource.Cross, SoundSource.InterfaceClickLow) { OcelotDesktop.exit() })
}, },
)) ))
addEntry(new MenuBarSubmenu( addEntry(new MenuBarSubmenu(
"Player", m"label.menu.player",
menu => { menu => {
menu.addEntry(ContextMenuEntry("Create new", IconSource.Plus) { OcelotDesktop.showAddPlayerDialog() }) menu.addEntry(ContextMenuEntry(m"label.menu.player.new", IconSource.Plus) { OcelotDesktop.showAddPlayerDialog() })
menu.addSeparator() menu.addSeparator()
OcelotDesktop.players.foreach(player => { OcelotDesktop.players.foreach(player => {
menu.addEntry(new ContextMenuSubmenu( menu.addEntry(new ContextMenuSubmenu(
s"${if (player == OcelotDesktop.players.head) "● " else " "}${player.nickname}", s"${if (player == OcelotDesktop.players.head) "● " else " "}${player.nickname}",
onClick = () => OcelotDesktop.selectPlayer(player.nickname), onClick = () => OcelotDesktop.selectPlayer(player.nickname),
) { ) {
addEntry(ContextMenuEntry("Remove", IconSource.Delete, SoundSource.InterfaceClickLow) { addEntry(ContextMenuEntry(m"label.menu.player.remove", IconSource.Delete, SoundSource.InterfaceClickLow) {
OcelotDesktop.removePlayer(player.nickname) OcelotDesktop.removePlayer(player.nickname)
}) })
}) })
@ -51,17 +52,17 @@ class MenuBar extends Widget {
}, },
)) ))
addEntry(new MenuBarButton("Settings", () => new SettingsDialog().show())) addEntry(new MenuBarButton(m"label.menu.settings", () => new SettingsDialog().show()))
addEntry(new MenuBarSubmenu( addEntry(new MenuBarSubmenu(
"Help", m"label.menu.help",
menu => { menu => {
menu.addEntry(ContextMenuEntry("Check for Updates", IconSource.Help) { menu.addEntry(ContextMenuEntry(m"label.menu.help.updates", IconSource.Help) {
new UpdateCheckerDialog().show() new UpdateCheckerDialog().show()
}) })
menu.addSeparator() menu.addSeparator()
menu.addEntry(ContextMenuEntry("Manual", IconSource.Book) {}.setEnabled(false)) menu.addEntry(ContextMenuEntry(m"label.menu.help.manual", IconSource.Book) {}.setEnabled(false))
menu.addEntry(ContextMenuEntry("About", IconSource.Ocelot) { new AboutDialog().show() }) menu.addEntry(ContextMenuEntry(m"label.menu.help.about", IconSource.Ocelot) { new AboutDialog().show() })
}, },
)) ))

View File

@ -7,15 +7,16 @@ import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.event.handlers.{HoverHandler, MouseHandler} import ocelot.desktop.ui.event.handlers.{HoverHandler, MouseHandler}
import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent}
import ocelot.desktop.util.Message
import ocelot.desktop.util.animation.ColorAnimation import ocelot.desktop.util.animation.ColorAnimation
class MenuBarButton(label: String, handler: () => Unit = () => {}) extends Widget with MouseHandler with HoverHandler { class MenuBarButton(label: Message, handler: () => Unit = () => {}) extends Widget with MouseHandler with HoverHandler {
val colorAnimation: ColorAnimation = new ColorAnimation(ColorScheme("TitleBarBackground"), 0.6f) val colorAnimation: ColorAnimation = new ColorAnimation(ColorScheme("TitleBarBackground"), 0.6f)
children :+= new PaddingBox( children :+= new PaddingBox(
new Label { new Label {
override def text: String = label override def text: Message = label
override def color: Color = ColorScheme("TitleBarButtonForeground") override def color: Color = ColorScheme("TitleBarButtonForeground")
override def maximumSize: Size2D = minimumSize override def maximumSize: Size2D = minimumSize
}, },

View File

@ -3,8 +3,9 @@ package ocelot.desktop.ui.widget
import ocelot.desktop.geometry.Vector2D import ocelot.desktop.geometry.Vector2D
import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.widget.contextmenu.ContextMenu import ocelot.desktop.ui.widget.contextmenu.ContextMenu
import ocelot.desktop.util.Message
class MenuBarSubmenu(label: String, setup: ContextMenu => Unit) extends MenuBarButton(label) { class MenuBarSubmenu(label: Message, setup: ContextMenu => Unit) extends MenuBarButton(label) {
private var menuOpened = false private var menuOpened = false
override def onMouseLeave(): Unit = { override def onMouseLeave(): Unit = {

View File

@ -5,14 +5,15 @@ import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.node.nodes.ScreenNode import ocelot.desktop.node.nodes.ScreenNode
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.util.Orientation import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, Orientation}
class ScreenAspectRatioDialog(screenNode: ScreenNode) extends ModalDialog { class ScreenAspectRatioDialog(screenNode: ScreenNode) extends ModalDialog {
children :+= new PaddingBox( children :+= new PaddingBox(
new Widget { new Widget {
override val layout = new LinearLayout(this, orientation = Orientation.Vertical) override val layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= new PaddingBox(new Label("Set aspect ratio"), Padding2D(bottom = 16)) children :+= new PaddingBox(new Label(m"label.menu.setAspectRatio"), Padding2D(bottom = 16))
private var typedWidth: Option[Int] = Some(screenNode.screen.aspectRatio._1.toInt) private var typedWidth: Option[Int] = Some(screenNode.screen.aspectRatio._1.toInt)
private var typedHeight: Option[Int] = Some(screenNode.screen.aspectRatio._2.toInt) private var typedHeight: Option[Int] = Some(screenNode.screen.aspectRatio._2.toInt)
@ -55,7 +56,7 @@ class ScreenAspectRatioDialog(screenNode: ScreenNode) extends ModalDialog {
) )
} }
children :+= new Label("Width:") children :+= new Label(m"label.dialog.aspect.width")
addInput( addInput(
8, 8,
@ -63,7 +64,7 @@ class ScreenAspectRatioDialog(screenNode: ScreenNode) extends ModalDialog {
value => typedWidth = value, value => typedWidth = value,
) )
children :+= new Label("Height:") children :+= new Label(m"label.dialog.aspect.height")
addInput( addInput(
6, 6,
@ -76,7 +77,7 @@ class ScreenAspectRatioDialog(screenNode: ScreenNode) extends ModalDialog {
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Cancel" override def text: Message = m"button.cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow
override def onClick(): Unit = close() override def onClick(): Unit = close()
}, },
@ -84,7 +85,7 @@ class ScreenAspectRatioDialog(screenNode: ScreenNode) extends ModalDialog {
) )
val confirmButton: Button = new Button { val confirmButton: Button = new Button {
override def text: String = "Apply" override def text: Message = m"button.apply"
override def onClick(): Unit = confirm() override def onClick(): Unit = confirm()
override def enabled: Boolean = canConfirm override def enabled: Boolean = canConfirm
} }

View File

@ -9,9 +9,9 @@ import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.event.handlers.MouseHandler import ocelot.desktop.ui.event.handlers.MouseHandler
import ocelot.desktop.ui.event.{ClickEvent, DragEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, DragEvent, MouseEvent}
import ocelot.desktop.ui.widget.traits.HoverAnimation import ocelot.desktop.ui.widget.traits.HoverAnimation
import ocelot.desktop.util.DrawUtils import ocelot.desktop.util.{DrawUtils, Message}
class Slider(var value: Float, val text: String, val snapPoints: Int = 0) class Slider(var value: Float, val text: Message, val snapPoints: Int = 0)
extends Widget with MouseHandler with HoverAnimation { extends Widget with MouseHandler with HoverAnimation {
override protected val hoverAnimationColorDefault: Color = ColorScheme("SliderBackground") override protected val hoverAnimationColorDefault: Color = ColorScheme("SliderBackground")

View File

@ -9,7 +9,7 @@ import ocelot.desktop.ui.event.handlers.MouseHandler
import ocelot.desktop.ui.event.sources.KeyEvents import ocelot.desktop.ui.event.sources.KeyEvents
import ocelot.desktop.ui.event.{ClickEvent, KeyEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, KeyEvent, MouseEvent}
import ocelot.desktop.ui.widget.traits.HoverAnimation import ocelot.desktop.ui.widget.traits.HoverAnimation
import ocelot.desktop.util.DrawUtils import ocelot.desktop.util.{DrawUtils, Message}
import ocelot.desktop.util.animation.ColorAnimation import ocelot.desktop.util.animation.ColorAnimation
import org.lwjgl.input.Keyboard import org.lwjgl.input.Keyboard
@ -34,7 +34,7 @@ class TextInput(val initialText: String = "") extends Widget with MouseHandler w
def text_=(value: String): Unit = chars = value.toCharArray def text_=(value: String): Unit = chars = value.toCharArray
protected var placeholder: Array[Char] = "".toCharArray protected var placeholder: Array[Char] = "".toCharArray
def placeholder_=(value: String): Unit = placeholder = value.toCharArray def placeholder_=(value: Message): Unit = placeholder = value.toString.toCharArray
private var cursorPos = 0 private var cursorPos = 0
private var cursorOffset = 0f private var cursorOffset = 0f

View File

@ -6,7 +6,8 @@ import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.util.Orientation import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, Orientation}
import java.util.UUID import java.util.UUID
@ -31,7 +32,7 @@ class TunnelDialog(
new Widget { new Widget {
override val layout = new LinearLayout(this, orientation = Orientation.Vertical, gap = 8) override val layout = new LinearLayout(this, orientation = Orientation.Vertical, gap = 8)
children :+= new PaddingBox(new Label("Set channel name/code"), Padding2D(bottom = 8)) children :+= new PaddingBox(new Label(m"label.dialog.tunnel"), Padding2D(bottom = 8))
children :+= new Widget { children :+= new Widget {
children :+= input children :+= input
@ -42,7 +43,7 @@ class TunnelDialog(
drawBackground = true, drawBackground = true,
releasedColor = ColorScheme("ButtonForeground"), releasedColor = ColorScheme("ButtonForeground"),
padding = 3.5f, padding = 3.5f,
tooltip = Some("Generate random channel name"), tooltip = Some(m"label.dialog.tunnel.random"),
) { ) {
override def onPressed(): Unit = input.text = UUID.randomUUID().toString override def onPressed(): Unit = input.text = UUID.randomUUID().toString
}, },
@ -55,7 +56,7 @@ class TunnelDialog(
releasedColor = ColorScheme("ButtonForeground"), releasedColor = ColorScheme("ButtonForeground"),
pressedColor = ColorScheme("ButtonConfirm"), pressedColor = ColorScheme("ButtonConfirm"),
padding = 3.5f, padding = 3.5f,
tooltip = Some("Copy channel name to the clipboard"), tooltip = Some(m"label.dialog.tunnel.copy"),
) { ) {
override def onPressed(): Unit = UiHandler.clipboard = input.text override def onPressed(): Unit = UiHandler.clipboard = input.text
} }
@ -64,13 +65,13 @@ class TunnelDialog(
children :+= new Widget { children :+= new Widget {
children :+= new Filler children :+= new Filler
children :+= new Button { children :+= new Button {
override def text: String = "Cancel" override def text: Message = m"button.cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow
override def onClick(): Unit = close() override def onClick(): Unit = close()
} }
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Ok" override def text: Message = m"button.ok"
override def onClick(): Unit = { override def onClick(): Unit = {
if (input.isInputValid) if (input.isInputValid)
confirm() confirm()

View File

@ -10,6 +10,7 @@ import ocelot.desktop.ui.event.handlers.{HoverHandler, MouseHandler}
import ocelot.desktop.ui.event.sources.KeyEvents import ocelot.desktop.ui.event.sources.KeyEvents
import ocelot.desktop.ui.event.{DragEvent, MouseEvent, ScrollEvent} import ocelot.desktop.ui.event.{DragEvent, MouseEvent, ScrollEvent}
import ocelot.desktop.ui.layout.{CopyLayout, Layout, LinearLayout} import ocelot.desktop.ui.layout.{CopyLayout, Layout, LinearLayout}
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{DrawUtils, Orientation} import ocelot.desktop.util.{DrawUtils, Orientation}
abstract class Viewport3DWidget extends Widget with MouseHandler with HoverHandler { abstract class Viewport3DWidget extends Widget with MouseHandler with HoverHandler {
@ -150,8 +151,8 @@ abstract class Viewport3DWidget extends Widget with MouseHandler with HoverHandl
scene = createScene() scene = createScene()
if (isHovered) { if (isHovered) {
root.get.statusBar.addMouseEntry("icons/LMB", "Rotate view") root.get.statusBar.addMouseEntry("icons/LMB", m"label.bar.rotateView")
root.get.statusBar.addKeyMouseEntry("icons/LMB", "Shift", "Pan view") root.get.statusBar.addKeyMouseEntry("icons/LMB", "Shift", m"label.bar.panView")
} }
} }

View File

@ -12,6 +12,7 @@ import ocelot.desktop.ui.event.sources.KeyEvents
import ocelot.desktop.ui.layout.{CopyLayout, Layout} import ocelot.desktop.ui.layout.{CopyLayout, Layout}
import ocelot.desktop.ui.widget.WorkspaceView.NodeLoadException import ocelot.desktop.ui.widget.WorkspaceView.NodeLoadException
import ocelot.desktop.ui.widget.window.{NodeSelector, ProfilerWindow, WindowPool} import ocelot.desktop.ui.widget.window.{NodeSelector, ProfilerWindow, WindowPool}
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.ReflectionUtils.findUnaryConstructor import ocelot.desktop.util.ReflectionUtils.findUnaryConstructor
import ocelot.desktop.util.animation.ValueAnimation import ocelot.desktop.util.animation.ValueAnimation
import ocelot.desktop.util.{DrawUtils, Logging, Persistable} import ocelot.desktop.util.{DrawUtils, Logging, Persistable}
@ -608,19 +609,19 @@ class WorkspaceView extends Widget with Persistable with MouseHandler with Hover
nodes.foreach(_.update()) nodes.foreach(_.update())
if (isHovered) { if (isHovered) {
root.get.statusBar.addKeyEntry("HOME", "Reset camera") root.get.statusBar.addKeyEntry("HOME", m"label.bar.resetCamera")
} }
if (isHovered || nodes.exists(_.isHovered)) { if (isHovered || nodes.exists(_.isHovered)) {
root.get.statusBar.addKeyEntry("CTRL", "Show grid") root.get.statusBar.addKeyEntry("CTRL", m"label.bar.showGrid")
} }
if (isHovered && newConnection.isEmpty) { if (isHovered && newConnection.isEmpty) {
if (nodeSelector.isClosed) if (nodeSelector.isClosed)
root.get.statusBar.addMouseEntry("icons/LMB", "Add node") root.get.statusBar.addMouseEntry("icons/LMB", m"label.bar.addNode")
else else
root.get.statusBar.addMouseEntry("icons/LMB", "Close selector") root.get.statusBar.addMouseEntry("icons/LMB", m"label.bar.closeSelector")
root.get.statusBar.addMouseEntry("icons/DragLMB", "Move camera") root.get.statusBar.addMouseEntry("icons/DragLMB", m"label.bar.moveCamera")
} }
} }
} }

View File

@ -4,7 +4,8 @@ import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.ui.layout.{AlignItems, Layout, LinearLayout} import ocelot.desktop.ui.layout.{AlignItems, Layout, LinearLayout}
import ocelot.desktop.ui.widget.window.PanelWindow import ocelot.desktop.ui.widget.window.PanelWindow
import ocelot.desktop.ui.widget.{Knob, Label, PaddingBox, Widget} import ocelot.desktop.ui.widget.{Knob, Label, PaddingBox, Widget}
import ocelot.desktop.util.Orientation import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, Orientation}
import totoro.ocelot.brain.entity.Redstone import totoro.ocelot.brain.entity.Redstone
import totoro.ocelot.brain.util.{Direction, DyeColor} import totoro.ocelot.brain.util.{Direction, DyeColor}
@ -21,18 +22,18 @@ class Redstone1Window(card: Redstone.Tier1) extends PanelWindow {
override def output: Int = card.redstoneOutput(side.id) min 15 max 0 override def output: Int = card.redstoneOutput(side.id) min 15 max 0
} }
override protected def title: String = s"Redstone I/O ${card.node.address}" override protected def title: Message = s"${m"component.redstoneIO"} ${card.node.address}"
override protected def titleMaxLength: Int = 26 override protected def titleMaxLength: Int = 26
private def redstoneBlock(side: Direction.Value, name: String) = new PaddingBox( private def redstoneBlock(side: Direction.Value, name: Message) = new PaddingBox(
new Widget { new Widget {
override protected val layout: Layout = override protected val layout: Layout =
new LinearLayout(this, Orientation.Horizontal, alignItems = AlignItems.Center) new LinearLayout(this, Orientation.Horizontal, alignItems = AlignItems.Center)
children :+= new PaddingBox( children :+= new PaddingBox(
new Label { new Label {
override def text: String = name override def text: Message = name
override def maximumSize: Size2D = minimumSize override def maximumSize: Size2D = minimumSize
}, },
@ -47,18 +48,18 @@ class Redstone1Window(card: Redstone.Tier1) extends PanelWindow {
setInner(new Widget { setInner(new Widget {
children :+= new Widget { children :+= new Widget {
override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical) override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= redstoneBlock(Direction.Down, "Bottom") children :+= redstoneBlock(Direction.Down, m"direction.bottom")
children :+= redstoneBlock(Direction.Up, " Top") children :+= redstoneBlock(Direction.Up, m"direction.top")
} }
children :+= new Widget { children :+= new Widget {
override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical) override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= redstoneBlock(Direction.Back, " Back") children :+= redstoneBlock(Direction.Back, m"direction.back")
children :+= redstoneBlock(Direction.Front, "Front") children :+= redstoneBlock(Direction.Front, m"direction.front")
} }
children :+= new Widget { children :+= new Widget {
override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical) override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= redstoneBlock(Direction.Right, "Right") children :+= redstoneBlock(Direction.Right, m"direction.right")
children :+= redstoneBlock(Direction.Left, " Left") children :+= redstoneBlock(Direction.Left, m"direction.left")
} }
}) })
} }

View File

@ -4,7 +4,8 @@ import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.ui.layout.{AlignItems, Layout, LinearLayout} import ocelot.desktop.ui.layout.{AlignItems, Layout, LinearLayout}
import ocelot.desktop.ui.widget.window.PanelWindow import ocelot.desktop.ui.widget.window.PanelWindow
import ocelot.desktop.ui.widget.{Knob, Label, PaddingBox, Widget} import ocelot.desktop.ui.widget.{Knob, Label, PaddingBox, Widget}
import ocelot.desktop.util.Orientation import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, Orientation}
import totoro.ocelot.brain.entity.Redstone import totoro.ocelot.brain.entity.Redstone
import totoro.ocelot.brain.util.{Direction, DyeColor} import totoro.ocelot.brain.util.{Direction, DyeColor}
@ -21,17 +22,17 @@ class Redstone2Window(card: Redstone.Tier2) extends PanelWindow {
override def output: Int = card.bundledRedstoneOutput(side.id)(col) min 15 max 0 override def output: Int = card.bundledRedstoneOutput(side.id)(col) min 15 max 0
} }
override protected def title: String = s"Bundled I/O ${card.node.address}" override protected def title: Message = s"${m"component.bundledIO"} ${card.node.address}"
override protected def titleMaxLength: Int = 36 override protected def titleMaxLength: Int = 36
private def bundledBlock(side: Direction.Value, name: String) = new PaddingBox( private def bundledBlock(side: Direction.Value, name: Message) = new PaddingBox(
new Widget { new Widget {
override protected val layout: Layout = new LinearLayout(this, override protected val layout: Layout = new LinearLayout(this,
orientation = Orientation.Vertical, alignItems = AlignItems.Center) orientation = Orientation.Vertical, alignItems = AlignItems.Center)
children :+= new Label { children :+= new Label {
override def text: String = name override def text: Message = name
override def maximumSize: Size2D = minimumSize override def maximumSize: Size2D = minimumSize
} }
@ -66,18 +67,18 @@ class Redstone2Window(card: Redstone.Tier2) extends PanelWindow {
setInner(new Widget { setInner(new Widget {
children :+= new Widget { children :+= new Widget {
override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical) override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= bundledBlock(Direction.Down, "Bottom") children :+= bundledBlock(Direction.Down, m"direction.bottom")
children :+= bundledBlock(Direction.Up, "Top") children :+= bundledBlock(Direction.Up, m"direction.top")
} }
children :+= new Widget { children :+= new Widget {
override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical) override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= bundledBlock(Direction.Back, "Back") children :+= bundledBlock(Direction.Back, m"direction.back")
children :+= bundledBlock(Direction.Front, "Front") children :+= bundledBlock(Direction.Front, m"direction.front")
} }
children :+= new Widget { children :+= new Widget {
override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical) override protected val layout: Layout = new LinearLayout(this, orientation = Orientation.Vertical)
children :+= bundledBlock(Direction.Right, "Right") children :+= bundledBlock(Direction.Right, m"direction.right")
children :+= bundledBlock(Direction.Left, "Left") children :+= bundledBlock(Direction.Left, m"direction.left")
} }
}) })
} }

View File

@ -8,7 +8,8 @@ import ocelot.desktop.ui.layout.{Layout, LinearLayout}
import ocelot.desktop.ui.widget.card.SoundCardWindow._ import ocelot.desktop.ui.widget.card.SoundCardWindow._
import ocelot.desktop.ui.widget.window.{PanelWindow, Window} import ocelot.desktop.ui.widget.window.{PanelWindow, Window}
import ocelot.desktop.ui.widget.{Oscilloscope, PaddingBox, Widget} import ocelot.desktop.ui.widget.{Oscilloscope, PaddingBox, Widget}
import ocelot.desktop.util.{DrawUtils, Orientation} import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{DrawUtils, Message, Orientation}
import totoro.ocelot.brain.Settings import totoro.ocelot.brain.Settings
import totoro.ocelot.brain.entity.sound_card._ import totoro.ocelot.brain.entity.sound_card._
import totoro.ocelot.brain.event.{EventBus, SoundCardAudioEvent} import totoro.ocelot.brain.event.{EventBus, SoundCardAudioEvent}
@ -40,7 +41,7 @@ class SoundCardWindow(card: SoundCard) extends PanelWindow {
private var eventSub: Option[EventBus.Subscription] = None private var eventSub: Option[EventBus.Subscription] = None
override protected def title: String = s"Sound Card ${card.node.address}" override protected def title: Message = s"${m"component.soundCard"} ${card.node.address}"
override protected def titleMaxLength: Int = 80 override protected def titleMaxLength: Int = 80

View File

@ -9,11 +9,12 @@ import ocelot.desktop.ui.event.handlers.{HoverHandler, MouseHandler}
import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent}
import ocelot.desktop.ui.layout.{AlignItems, Layout, LinearLayout} import ocelot.desktop.ui.layout.{AlignItems, Layout, LinearLayout}
import ocelot.desktop.ui.widget._ import ocelot.desktop.ui.widget._
import ocelot.desktop.util.Message
import ocelot.desktop.util.animation.ValueAnimation import ocelot.desktop.util.animation.ValueAnimation
import ocelot.desktop.util.animation.easing.{EaseInQuad, EaseOutQuad} import ocelot.desktop.util.animation.easing.{EaseInQuad, EaseOutQuad}
class ContextMenuEntry( class ContextMenuEntry(
label: String, label: Message,
icon: Option[ContextMenuIcon] = None, icon: Option[ContextMenuIcon] = None,
onClick: () => Unit = () => {}, onClick: () => Unit = () => {},
sound: ClickSoundSource = SoundSource.InterfaceClick, sound: ClickSoundSource = SoundSource.InterfaceClick,
@ -55,7 +56,7 @@ class ContextMenuEntry(
children :+= new PaddingBox( children :+= new PaddingBox(
new Label { new Label {
override def text: String = label override def text: Message = label
override def color: Color = ColorScheme("ContextMenuText") override def color: Color = ColorScheme("ContextMenuText")
}, },
Padding2D(top = 5f, bottom = 5f), Padding2D(top = 5f, bottom = 5f),
@ -135,7 +136,7 @@ class ContextMenuEntry(
object ContextMenuEntry { object ContextMenuEntry {
def apply( def apply(
label: String, label: Message,
icon: Option[ContextMenuIcon] = None, icon: Option[ContextMenuIcon] = None,
)(onClick: => Unit): ContextMenuEntry = { )(onClick: => Unit): ContextMenuEntry = {
new ContextMenuEntry( new ContextMenuEntry(
@ -146,7 +147,7 @@ object ContextMenuEntry {
} }
def apply( def apply(
label: String label: Message
)(onClick: => Unit): ContextMenuEntry = { )(onClick: => Unit): ContextMenuEntry = {
new ContextMenuEntry( new ContextMenuEntry(
label, label,
@ -156,7 +157,7 @@ object ContextMenuEntry {
} }
def apply( def apply(
label: String, label: Message,
icon: IconSource, icon: IconSource,
)(onClick: => Unit): ContextMenuEntry = { )(onClick: => Unit): ContextMenuEntry = {
new ContextMenuEntry( new ContextMenuEntry(
@ -167,7 +168,7 @@ object ContextMenuEntry {
} }
def apply( def apply(
label: String, label: Message,
icon: IconSource, icon: IconSource,
sound: ClickSoundSource, sound: ClickSoundSource,
)(onClick: => Unit): ContextMenuEntry = { )(onClick: => Unit): ContextMenuEntry = {

View File

@ -6,9 +6,10 @@ import ocelot.desktop.geometry.Vector2D
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.event.HoverEvent import ocelot.desktop.ui.event.HoverEvent
import ocelot.desktop.util.Message
class ContextMenuSubmenu( class ContextMenuSubmenu(
label: String, label: Message,
icon: Option[ContextMenuIcon] = None, icon: Option[ContextMenuIcon] = None,
onClick: () => Unit = () => {}, onClick: () => Unit = () => {},
) extends ContextMenuEntry( ) extends ContextMenuEntry(

View File

@ -9,7 +9,8 @@ import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.{Button, Filler, Label, PaddingBox, Widget} import ocelot.desktop.ui.widget.{Button, Filler, Label, PaddingBox, Widget}
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.ui.widget.tooltip.LabelTooltip import ocelot.desktop.ui.widget.tooltip.LabelTooltip
import ocelot.desktop.util.{DrawUtils, Orientation, Spritesheet} import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{DrawUtils, Message, Orientation, Spritesheet}
import java.awt.Desktop import java.awt.Desktop
import java.net.URI import java.net.URI
@ -37,8 +38,8 @@ class AboutDialog extends ModalDialog {
children :++= Seq( children :++= Seq(
new PaddingBox(AboutLabel("OCELOT DESKTOP"), Padding2D(top = 32)), new PaddingBox(AboutLabel("OCELOT DESKTOP"), Padding2D(top = 32)),
new PaddingBox(AboutLabel(" OpenComputers Emulator", isSmall = true), Padding2D(bottom = 16)), new PaddingBox(AboutLabel(m"label.dialog.about.subtitle", isSmall = true), Padding2D(bottom = 16, left = 16)),
AboutLabel(s"Version: ${BuildInfo.version}"), AboutLabel(s"${m"label.dialog.about.version"}: ${BuildInfo.version}"),
new PaddingBox(AboutLabel(s" (${BuildInfo.commit.take(7)})", isSmall = true), Padding2D(bottom = 16)), new PaddingBox(AboutLabel(s" (${BuildInfo.commit.take(7)})", isSmall = true), Padding2D(bottom = 16)),
AboutLabel(s"MIT License (c) ${Year.now.getValue} Ocelot Dev Team"), AboutLabel(s"MIT License (c) ${Year.now.getValue} Ocelot Dev Team"),
AboutLabel(" OpenComputers (C) 2013-2015, MIT, Florian \"Sangar\" Nücke", isSmall = true), AboutLabel(" OpenComputers (C) 2013-2015, MIT, Florian \"Sangar\" Nücke", isSmall = true),
@ -61,13 +62,13 @@ class AboutDialog extends ModalDialog {
} }
if (Desktop.isDesktopSupported) { if (Desktop.isDesktopSupported) {
children :+= new PaddingBox(new AboutButton("Website", WebsiteURL), Padding2D(right = 8)) children :+= new PaddingBox(new AboutButton(m"label.dialog.about.website", WebsiteURL), Padding2D(right = 8))
children :+= new PaddingBox(new AboutButton("IRC", IrcURL), Padding2D(right = 8)) children :+= new PaddingBox(new AboutButton("IRC", IrcURL), Padding2D(right = 8))
children :+= new PaddingBox(new AboutButton("Discord", DiscordURL), Padding2D(right = 20)) children :+= new PaddingBox(new AboutButton("Discord", DiscordURL), Padding2D(right = 20))
} }
children :+= new Button { children :+= new Button {
override def text: String = "Ok" override def text: Message = m"button.ok"
override def onClick(): Unit = close() override def onClick(): Unit = close()
override protected def colorScheme: ColorScheme = customButtonColorScheme override protected def colorScheme: ColorScheme = customButtonColorScheme
} }
@ -102,19 +103,19 @@ class AboutDialog extends ModalDialog {
scheme scheme
} }
private class AboutButton(val label: String, val url: String) extends Button(new LabelTooltip(url)) { private class AboutButton(val label: Message, val url: String) extends Button(new LabelTooltip(url)) {
override def text: String = label override def text: Message = label
override def onClick(): Unit = Desktop.getDesktop.browse(new URI(url)) override def onClick(): Unit = Desktop.getDesktop.browse(new URI(url))
override protected def colorScheme: ColorScheme = customButtonColorScheme override protected def colorScheme: ColorScheme = customButtonColorScheme
} }
private class AboutLabel(private val _text: String, private val _isSmall: Boolean = false) extends Label { private class AboutLabel(private val _text: Message, private val _isSmall: Boolean = false) extends Label {
override def text: String = _text override def text: Message = _text
override def isSmall: Boolean = _isSmall override def isSmall: Boolean = _isSmall
override def color: Color = if (isSmall) ColorScheme("AboutForegroundSubtle") else ColorScheme("AboutForeground") override def color: Color = if (isSmall) ColorScheme("AboutForegroundSubtle") else ColorScheme("AboutForeground")
} }
private object AboutLabel { private object AboutLabel {
def apply(text: String, isSmall: Boolean = false): AboutLabel = new AboutLabel(text, isSmall) def apply(text: Message, isSmall: Boolean = false): AboutLabel = new AboutLabel(text, isSmall)
} }
} }

View File

@ -7,8 +7,9 @@ import ocelot.desktop.graphics.IconSource
import ocelot.desktop.ui.layout.{Layout, LinearLayout} import ocelot.desktop.ui.layout.{Layout, LinearLayout}
import ocelot.desktop.ui.widget.{Button, Filler, Icon, Label, PaddingBox, Widget} import ocelot.desktop.ui.widget.{Button, Filler, Icon, Label, PaddingBox, Widget}
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.Orientation.Vertical import ocelot.desktop.util.Orientation.Vertical
import ocelot.desktop.util.{Logging, OcelotOnlineAPI} import ocelot.desktop.util.{Logging, Message, OcelotOnlineAPI}
import java.awt.Desktop import java.awt.Desktop
import java.net.URI import java.net.URI
@ -35,7 +36,7 @@ class UpdateCheckerDialog extends ModalDialog with Logging {
override def maximumSize: Size2D = Size2D(Float.PositiveInfinity, 1) override def maximumSize: Size2D = Size2D(Float.PositiveInfinity, 1)
} }
children :+= new Button { children :+= new Button {
override def text: String = "Ok" override def text: Message = m"button.ok"
override def onClick(): Unit = close() override def onClick(): Unit = close()
} }
} }
@ -44,7 +45,7 @@ class UpdateCheckerDialog extends ModalDialog with Logging {
) )
// loading screen // loading screen
container.children :+= new Label("Checking development news...") container.children :+= new Label(m"label.dialog.updates.checking")
container.children :+= new PaddingBox(new Icon(IconSource.Loading, color = ColorScheme("Label")), container.children :+= new PaddingBox(new Icon(IconSource.Loading, color = ColorScheme("Label")),
Padding2D(16, 0, 0, 90)) Padding2D(16, 0, 0, 90))
@ -55,16 +56,16 @@ class UpdateCheckerDialog extends ModalDialog with Logging {
setContainerChildren(ArraySeq.empty) setContainerChildren(ArraySeq.empty)
if (version.releaseVersion.isDefined) { if (version.releaseVersion.isDefined) {
val newReleaseVersion = version.releaseVersion.get.drop(1) val newReleaseVersion = version.releaseVersion.get.drop(1)
container.children :+= new Label(s"Release: ${BuildInfo.version} ${newReleaseVersion}") container.children :+= new Label(s"${m"label.dialog.updates.release"}: ${BuildInfo.version} $newReleaseVersion")
if (newReleaseVersion == BuildInfo.version) { if (newReleaseVersion == BuildInfo.version) {
container.children :+= new PaddingBox(new Label("Up to date!", small = true), Padding2D(6)) container.children :+= new PaddingBox(new Label(m"label.dialog.updates.upToDate", small = true), Padding2D(6))
} else { } else {
container.children :+= new PaddingBox(new Label("New release version is available:", small = true), container.children :+= new PaddingBox(new Label(m"label.dialog.updates.releaseUpdateAvailable", foreground = ColorScheme("LabelUpdateAvailable"), small = true),
Padding2D(6)) Padding2D(6))
if (Desktop.isDesktopSupported) { if (Desktop.isDesktopSupported) {
container.children :+= new PaddingBox( container.children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Download" override def text: Message = m"button.download"
override def onClick(): Unit = Desktop.getDesktop.browse(new URI("https://ocelot.fomalhaut.me/desktop")) override def onClick(): Unit = Desktop.getDesktop.browse(new URI("https://ocelot.fomalhaut.me/desktop"))
}, },
@ -76,7 +77,7 @@ class UpdateCheckerDialog extends ModalDialog with Logging {
} }
} }
} else { } else {
container.children :+= new Label("Release: N\\A") container.children :+= new Label(s"${m"label.dialog.updates.release"}: N\\A")
} }
container.children :+= new Filler { container.children :+= new Filler {
@ -85,21 +86,21 @@ class UpdateCheckerDialog extends ModalDialog with Logging {
if (version.devId.isDefined && version.devDate.isDefined) { if (version.devId.isDefined && version.devDate.isDefined) {
val newDevVersion = version.devId.get.take(7) val newDevVersion = version.devId.get.take(7)
container.children :+= new Label(s"Dev build: ${BuildInfo.commit.take(7)} ${newDevVersion}") container.children :+= new Label(s"${m"label.dialog.updates.devBuild"}: ${BuildInfo.commit.take(7)} $newDevVersion")
if (BuildInfo.commit.take(7) == newDevVersion) { if (BuildInfo.commit.take(7) == newDevVersion) {
container.children :+= new PaddingBox(new Label("Up to date!", small = true), Padding2D(6)) container.children :+= new PaddingBox(new Label(m"label.dialog.updates.upToDate", small = true), Padding2D(6))
} else { } else {
container.children :+= new PaddingBox( container.children :+= new PaddingBox(
new Label( new Label(
s"New dev build from ${version.devDate.get.withZoneSameInstant(ZoneId.systemDefault()).format(dateFormat)}:", s"${m"label.dialog.updates.devUpdateAvailable"} ${version.devDate.get.withZoneSameInstant(ZoneId.systemDefault()).format(dateFormat)}!",
small = true, foreground = ColorScheme("LabelUpdateAvailable"), small = true,
), ),
Padding2D(4), Padding2D(4),
) )
if (Desktop.isDesktopSupported) { if (Desktop.isDesktopSupported) {
container.children :+= new PaddingBox( container.children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Download" override def text: Message = m"button.download"
override def onClick(): Unit = Desktop.getDesktop.browse(new URI("https://ocelot.fomalhaut.me/desktop")) override def onClick(): Unit = Desktop.getDesktop.browse(new URI("https://ocelot.fomalhaut.me/desktop"))
}, },
@ -111,17 +112,19 @@ class UpdateCheckerDialog extends ModalDialog with Logging {
} }
} }
} else { } else {
container.children :+= new Label("Dev build: N\\A") container.children :+= new Label(s"${m"label.dialog.updates.devBuild"}: N\\A")
} }
case Failure(exception) => case Failure(exception) =>
logger.error("Cannot download information about new Ocelot version!", exception) logger.error("Cannot download information about new Ocelot version!", exception)
val message = "Ocelot website is unavailable...\n" + val messages: Array[Message] = Array(
s"($exception)\n" + m"label.dialog.updates.unavailable",
"Check the log file for a full stacktrace." s"(${exception.getMessage.split('\n').head})",
setContainerChildren(ArraySeq.unsafeWrapArray(message.split('\n').map(line => { m"label.dialog.updates.checkLogs"
)
setContainerChildren(ArraySeq.unsafeWrapArray(messages.map(message => {
new Label { new Label {
override def text: String = line override def text: Message = message
} }
}))) })))
} }

View File

@ -8,9 +8,10 @@ import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget._ import ocelot.desktop.ui.widget._
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.ui.widget.modal.notification.NotificationType.NotificationType import ocelot.desktop.ui.widget.modal.notification.NotificationType.NotificationType
import ocelot.desktop.util.{DrawUtils, Orientation} import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{DrawUtils, Message, Orientation}
class NotificationDialog(message: String, notificationType: NotificationType = NotificationType.Warning) class NotificationDialog(message: Message, notificationType: NotificationType = NotificationType.Warning)
extends ModalDialog { extends ModalDialog {
private val buttonsLayout: Widget = new Widget { private val buttonsLayout: Widget = new Widget {
override val layout: LinearLayout = new LinearLayout(this, gap = 15) override val layout: LinearLayout = new LinearLayout(this, gap = 15)
@ -49,10 +50,9 @@ class NotificationDialog(message: String, notificationType: NotificationType = N
override val layout: LinearLayout = new LinearLayout(this, override val layout: LinearLayout = new LinearLayout(this,
orientation = Orientation.Vertical, gap = 5) orientation = Orientation.Vertical, gap = 5)
children :++= message.split('\n').map(line => { children :++= message.toStringMultiline.map(line => {
new Label { new Label {
override def text: String = line override def text: Message = line
override def color: Color = ColorScheme("ContextMenuText") override def color: Color = ColorScheme("ContextMenuText")
} }
}) })
@ -76,11 +76,11 @@ class NotificationDialog(message: String, notificationType: NotificationType = N
drawChildren(g) drawChildren(g)
} }
def addButton(buttonText: String)(onClick: => Unit): NotificationDialog = { def addButton(buttonText: Message)(onClick: => Unit): NotificationDialog = {
val callback = onClick _ val callback = onClick _
buttonsLayout.children :+= new Button { buttonsLayout.children :+= new Button {
override def text: String = buttonText override def text: Message = buttonText
override def onClick(): Unit = callback() override def onClick(): Unit = callback()
} }
@ -88,7 +88,7 @@ class NotificationDialog(message: String, notificationType: NotificationType = N
this this
} }
def addCloseButton(buttonText: String = "Ok"): NotificationDialog = addButton(buttonText) { def addCloseButton(buttonText: Message = m"button.ok"): NotificationDialog = addButton(buttonText) {
close() close()
} }

View File

@ -8,7 +8,8 @@ import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.modal.ModalDialog import ocelot.desktop.ui.widget.modal.ModalDialog
import ocelot.desktop.ui.widget.verticalmenu.{VerticalMenu, VerticalMenuButton} import ocelot.desktop.ui.widget.verticalmenu.{VerticalMenu, VerticalMenuButton}
import ocelot.desktop.ui.widget.{Button, PaddingBox, Widget} import ocelot.desktop.ui.widget.{Button, PaddingBox, Widget}
import ocelot.desktop.util.{Orientation, SettingsData} import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, Orientation, SettingsData}
class SettingsDialog extends ModalDialog { class SettingsDialog extends ModalDialog {
private val settingsBackup = new SettingsData(Settings.get) private val settingsBackup = new SettingsData(Settings.get)
@ -37,7 +38,7 @@ class SettingsDialog extends ModalDialog {
} }
children :+= new Button { children :+= new Button {
override def text: String = "Cancel" override def text: Message = m"button.cancel"
override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow override protected def clickSoundSource: ClickSoundSource = SoundSource.InterfaceClickLow
override def onClick(): Unit = { override def onClick(): Unit = {
resetSettings() resetSettings()
@ -47,7 +48,7 @@ class SettingsDialog extends ModalDialog {
children :+= new PaddingBox( children :+= new PaddingBox(
new Button { new Button {
override def text: String = "Ok" override def text: Message = m"button.ok"
override def onClick(): Unit = close() override def onClick(): Unit = close()
}, },

View File

@ -3,13 +3,13 @@ package ocelot.desktop.ui.widget.settings
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.Widget import ocelot.desktop.ui.widget.Widget
import ocelot.desktop.util.Orientation import ocelot.desktop.util.{Message, Orientation}
trait SettingsTab extends Widget { trait SettingsTab extends Widget {
override protected val layout = new LinearLayout(this, orientation = Orientation.Vertical) override protected val layout = new LinearLayout(this, orientation = Orientation.Vertical)
val icon: IconSource val icon: IconSource
val label: String val label: Message
/** Callback that will be called by the parent Settings dialog when settings were changed /** Callback that will be called by the parent Settings dialog when settings were changed
* from outside the tab (for example user pressed "Cancel" and they were reset). * from outside the tab (for example user pressed "Cancel" and they were reset).

View File

@ -5,15 +5,16 @@ import ocelot.desktop.geometry.Size2D
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.{Checkbox, Slider} import ocelot.desktop.ui.widget.{Checkbox, Slider}
import ocelot.desktop.util.Orientation import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Message, Orientation}
class SoundSettingsTab extends SettingsTab { class SoundSettingsTab extends SettingsTab {
override val layout = new LinearLayout(this, orientation = Orientation.Vertical, gap = 8) override val layout = new LinearLayout(this, orientation = Orientation.Vertical, gap = 8)
override val icon: IconSource = IconSource.SettingsSound override val icon: IconSource = IconSource.SettingsSound
override val label: String = "Sound" override val label: Message = m"label.settings.sound"
private def addSlider(name: String, value: Float, valueSetter: Float => Unit): Unit = { private def addSlider(name: Message, value: Float, valueSetter: Float => Unit): Unit = {
children :+= new Slider(value, name) { children :+= new Slider(value, name) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
@ -25,36 +26,36 @@ class SoundSettingsTab extends SettingsTab {
} }
addSlider( addSlider(
"Master volume", m"label.settings.sound.master",
Settings.get.volumeMaster, Settings.get.volumeMaster,
Settings.get.volumeMaster = _, Settings.get.volumeMaster = _,
) )
addSlider( addSlider(
"Music blocks volume", m"label.settings.sound.music",
Settings.get.volumeRecords, Settings.get.volumeRecords,
Settings.get.volumeRecords = _, Settings.get.volumeRecords = _,
) )
addSlider( addSlider(
"Environment volume", m"label.settings.sound.environment",
Settings.get.volumeEnvironment, Settings.get.volumeEnvironment,
Settings.get.volumeEnvironment = _, Settings.get.volumeEnvironment = _,
) )
addSlider( addSlider(
"Beep volume", m"label.settings.sound.beep",
Settings.get.volumeBeep, Settings.get.volumeBeep,
Settings.get.volumeBeep = _, Settings.get.volumeBeep = _,
) )
addSlider( addSlider(
"Interface volume", m"label.settings.sound.ui",
Settings.get.volumeInterface, Settings.get.volumeInterface,
Settings.get.volumeInterface = _, Settings.get.volumeInterface = _,
) )
children :+= new Checkbox("Use positional sound", Settings.get.soundPositional) { children :+= new Checkbox(m"label.settings.sound.positional", Settings.get.soundPositional) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
override def onValueChanged(value: Boolean): Unit = { override def onValueChanged(value: Boolean): Unit = {

View File

@ -7,7 +7,8 @@ import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget.modal.notification.{NotificationDialog, NotificationType} import ocelot.desktop.ui.widget.modal.notification.{NotificationDialog, NotificationType}
import ocelot.desktop.ui.widget._ import ocelot.desktop.ui.widget._
import ocelot.desktop.ui.widget.tooltip.LabelTooltip import ocelot.desktop.ui.widget.tooltip.LabelTooltip
import ocelot.desktop.util.{FileUtils, Logging, OcelotPaths, Orientation} import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{FileUtils, Logging, Message, OcelotPaths, Orientation}
import ocelot.desktop.{ColorScheme, OcelotDesktop, Settings} import ocelot.desktop.{ColorScheme, OcelotDesktop, Settings}
import java.io.File import java.io.File
@ -18,7 +19,7 @@ class SystemSettingsTab extends SettingsTab with Logging {
private val OpenComputersConfigResource = "/application.conf" private val OpenComputersConfigResource = "/application.conf"
override val icon: IconSource = IconSource.SettingsSystem override val icon: IconSource = IconSource.SettingsSystem
override val label: String = "System" override val label: Message = m"label.settings.system"
override def applySettings(): Unit = { override def applySettings(): Unit = {
if (Settings.get.autosave) { if (Settings.get.autosave) {
@ -26,10 +27,10 @@ class SystemSettingsTab extends SettingsTab with Logging {
} }
} }
children :+= new PaddingBox(new Label("Set OpenComputers configuration file path:"), Padding2D(bottom = 8)) children :+= new PaddingBox(new Label(m"label.settings.system.confPath"), Padding2D(bottom = 8))
private val textInput: TextInput = new TextInput(Settings.get.brainCustomConfigPath.getOrElse("")) { private val textInput: TextInput = new TextInput(Settings.get.brainCustomConfigPath.getOrElse("")) {
if (Settings.get.brainCustomConfigPath.isEmpty) placeholder = "not set / using default OpenComputers configuration" if (Settings.get.brainCustomConfigPath.isEmpty) placeholder = m"label.settings.system.confPathPlaceholder"
override def onInput(text: String): Unit = { override def onInput(text: String): Unit = {
Settings.get.brainCustomConfigPath = Some(text) Settings.get.brainCustomConfigPath = Some(text)
restartWarning.isVisible = true restartWarning.isVisible = true
@ -49,7 +50,7 @@ class SystemSettingsTab extends SettingsTab with Logging {
pressedColor = ColorScheme("ButtonForegroundPressed"), pressedColor = ColorScheme("ButtonForegroundPressed"),
drawBackground = true, drawBackground = true,
padding = 3.5f, padding = 3.5f,
tooltip = Some("Search for OpenComputers configuration file"), tooltip = Some(m"label.settings.system.confSearch"),
) { ) {
override def onPressed(): Unit = { override def onPressed(): Unit = {
OcelotDesktop.showFileChooserDialog(JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY) { OcelotDesktop.showFileChooserDialog(JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY) {
@ -64,19 +65,19 @@ class SystemSettingsTab extends SettingsTab with Logging {
Padding2D(bottom = 4), Padding2D(bottom = 4),
) )
children :+= new PaddingBox(new Label("Generate new OpenComputers configuration file in:"), children :+= new PaddingBox(new Label(m"label.settings.system.confGenerate"),
Padding2D(top = 8, bottom = 8)) Padding2D(top = 8, bottom = 8))
children :+= new Widget { children :+= new Widget {
children :+= new Button(new LabelTooltip(new File(OcelotPaths.openComputersConfigName).getCanonicalPath)) { children :+= new Button(new LabelTooltip(new File(OcelotPaths.openComputersConfigName).getCanonicalPath)) {
override def text: String = "Current Directory" override def text = m"label.settings.system.currentDir"
override def onClick(): Unit = { override def onClick(): Unit = {
unpackConfig(new File(OcelotPaths.openComputersConfigName)) unpackConfig(new File(OcelotPaths.openComputersConfigName))
} }
} }
children :+= new PaddingBox( children :+= new PaddingBox(
new Button(new LabelTooltip(OcelotPaths.openComputersConfig.toString)) { new Button(new LabelTooltip(OcelotPaths.openComputersConfig.toString)) {
override def text: String = "Config Directory" override def text = m"label.settings.system.configDir"
override def onClick(): Unit = { override def onClick(): Unit = {
unpackConfig(OcelotPaths.openComputersConfig.toFile) unpackConfig(OcelotPaths.openComputersConfig.toFile)
} }
@ -85,7 +86,7 @@ class SystemSettingsTab extends SettingsTab with Logging {
) )
children :+= new PaddingBox( children :+= new PaddingBox(
new Button(new LabelTooltip("...")) { new Button(new LabelTooltip("...")) {
override def text: String = "Custom Path" override def text = m"label.settings.system.customDir"
override def onClick(): Unit = { override def onClick(): Unit = {
OcelotDesktop.showFileChooserDialog(JFileChooser.SAVE_DIALOG, JFileChooser.FILES_ONLY) { OcelotDesktop.showFileChooserDialog(JFileChooser.SAVE_DIALOG, JFileChooser.FILES_ONLY) {
case Some(file) => case Some(file) =>
@ -100,7 +101,7 @@ class SystemSettingsTab extends SettingsTab with Logging {
} }
children :+= new PaddingBox( children :+= new PaddingBox(
new Checkbox("Workspace autosave", Settings.get.autosave) { new Checkbox(m"label.settings.system.autosave", Settings.get.autosave) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
override def onValueChanged(value: Boolean): Unit = { override def onValueChanged(value: Boolean): Unit = {
@ -113,7 +114,7 @@ class SystemSettingsTab extends SettingsTab with Logging {
children :+= new PaddingBox( children :+= new PaddingBox(
new Widget { new Widget {
children :+= new PaddingBox(new Label("Workspace autosave period (seconds):"), Padding2D(top = 4, right = 8)) children :+= new PaddingBox(new Label(m"label.settings.system.autosavePeriod"), Padding2D(top = 4, right = 8))
children :+= new TextInput(Settings.get.autosavePeriod.toString) { children :+= new TextInput(Settings.get.autosavePeriod.toString) {
override def onInput(text: String): Unit = { override def onInput(text: String): Unit = {
@ -131,12 +132,12 @@ class SystemSettingsTab extends SettingsTab with Logging {
private def unpackConfig(file: File): Unit = { private def unpackConfig(file: File): Unit = {
if (file.exists()) { if (file.exists()) {
new NotificationDialog(s"You are overriding an existing file!", NotificationType.Warning) { new NotificationDialog(m"error.ocelot.overriding", NotificationType.Warning) {
addButton("Proceed") { addButton(m"button.proceed") {
unpackAndOverrideConfig(file) unpackAndOverrideConfig(file)
close() close()
} }
}.addCloseButton("Cancel").show() }.addCloseButton(m"button.cancel").show()
} else { } else {
unpackAndOverrideConfig(file) unpackAndOverrideConfig(file)
} }
@ -150,7 +151,7 @@ class SystemSettingsTab extends SettingsTab with Logging {
setConfigPath(dir.getCanonicalPath) setConfigPath(dir.getCanonicalPath)
case Failure(exception) => case Failure(exception) =>
new NotificationDialog( new NotificationDialog(
s"Something went wrong!\n($exception)\nCheck the log file for a full stacktrace.", s"${m"error.ocelot.somethingWentWrong"}\n($exception)\n${m"error.ocelot.checkTheLogs"}",
NotificationType.Error, NotificationType.Error,
).addCloseButton().show() ).addCloseButton().show()
} }
@ -167,7 +168,7 @@ class SystemSettingsTab extends SettingsTab with Logging {
override def color: Color = ColorScheme("ErrorMessage") override def color: Color = ColorScheme("ErrorMessage")
override def text = "Restart Ocelot to apply new configuration" override def text: Message = m"label.settings.system.restart"
} }
children :+= new PaddingBox(restartWarning, Padding2D(top = 4, bottom = 8)) children :+= new PaddingBox(restartWarning, Padding2D(top = 4, bottom = 8))

View File

@ -4,13 +4,15 @@ import ocelot.desktop.Settings
import ocelot.desktop.geometry.{Padding2D, Size2D} import ocelot.desktop.geometry.{Padding2D, Size2D}
import ocelot.desktop.graphics.IconSource import ocelot.desktop.graphics.IconSource
import ocelot.desktop.ui.UiHandler import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.{AlignItems, LinearLayout}
import ocelot.desktop.ui.widget.{Checkbox, Label, PaddingBox, Slider, Widget} import ocelot.desktop.ui.widget.{Checkbox, Dropdown, Label, PaddingBox, Slider, Widget}
import ocelot.desktop.util.MathUtils.roundAt import ocelot.desktop.util.MathUtils.roundAt
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.util.{Language, Message, Messages}
class UISettingsTab extends SettingsTab { class UISettingsTab extends SettingsTab {
override val icon: IconSource = IconSource.SettingsUI override val icon: IconSource = IconSource.SettingsUI
override val label: String = "UI" override val label: Message = m"label.settings.ui"
override def applySettings(): Unit = { override def applySettings(): Unit = {
if (UiHandler.fullScreen != Settings.get.windowFullscreen) { if (UiHandler.fullScreen != Settings.get.windowFullscreen) {
@ -20,10 +22,35 @@ class UISettingsTab extends SettingsTab {
if (UiHandler.scalingFactor != Settings.get.scaleFactor) { if (UiHandler.scalingFactor != Settings.get.scaleFactor) {
UiHandler.scalingFactor = Settings.get.scaleFactor UiHandler.scalingFactor = Settings.get.scaleFactor
} }
if (Messages.getCurrentLanguageCode != Settings.get.language) {
Messages.load(Settings.get.language)
}
} }
private val languages = Messages.loadLanguagesManifest()
private var selectedLanguage = languages.find(lang => lang.code == Settings.get.language).map(lang => lang.name).getOrElse("")
children :+= new PaddingBox(new Widget {
override val layout = new LinearLayout(this, alignItems = AlignItems.Start)
children :+= new PaddingBox(new Label(m"label.settings.ui.language") {
override def maximumSize: Size2D = minimumSize
}, Padding2D(top = 4, right = 8))
children :+= new Dropdown(languages.map(lang => lang.name)) {
override def text: Message = selectedLanguage
override def onSelect(option: String): Unit = {
selectedLanguage = option
Settings.get.language = languages.find(lang => lang.name == option).map(lang => lang.code).getOrElse(Language.DefaultCode)
applySettings()
}
}
}, Padding2D(bottom = 8))
children :+= new PaddingBox( children :+= new PaddingBox(
new Checkbox("Pin newly opened windows", new Checkbox(m"label.settings.ui.pinWindows",
initialValue = Settings.get.pinNewWindows) { initialValue = Settings.get.pinNewWindows) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
@ -35,7 +62,7 @@ class UISettingsTab extends SettingsTab {
) )
children :+= new PaddingBox( children :+= new PaddingBox(
new Checkbox("Fullscreen mode", new Checkbox(m"label.settings.ui.fullscreen",
initialValue = Settings.get.windowFullscreen) { initialValue = Settings.get.windowFullscreen) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
@ -48,7 +75,7 @@ class UISettingsTab extends SettingsTab {
) )
children :+= new PaddingBox( children :+= new PaddingBox(
new Checkbox("Save workspace on exit", new Checkbox(m"label.settings.ui.saveOnExit",
initialValue = Settings.get.saveOnExit) { initialValue = Settings.get.saveOnExit) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
@ -60,7 +87,7 @@ class UISettingsTab extends SettingsTab {
) )
children :+= new PaddingBox( children :+= new PaddingBox(
new Checkbox("Re-open last workspace on startup", new Checkbox(m"label.settings.ui.openLastWorkspace",
initialValue = Settings.get.openLastWorkspace) { initialValue = Settings.get.openLastWorkspace) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
@ -72,7 +99,7 @@ class UISettingsTab extends SettingsTab {
) )
children :+= new PaddingBox( children :+= new PaddingBox(
new Checkbox("Show previews on screen blocks", new Checkbox(m"label.settings.ui.screenPreview",
initialValue = Settings.get.renderScreenDataOnNodes) { initialValue = Settings.get.renderScreenDataOnNodes) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
@ -84,7 +111,7 @@ class UISettingsTab extends SettingsTab {
) )
children :+= new PaddingBox( children :+= new PaddingBox(
new Checkbox("Enable mipmaps for screen windows", new Checkbox(m"label.settings.ui.mipmaps",
initialValue = Settings.get.screenWindowMipmap) { initialValue = Settings.get.screenWindowMipmap) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
@ -96,7 +123,7 @@ class UISettingsTab extends SettingsTab {
) )
children :+= new PaddingBox( children :+= new PaddingBox(
new Checkbox("Enable festive decorations", new Checkbox(m"label.settings.ui.festiveDecorations",
initialValue = Settings.get.enableFestiveDecorations) { initialValue = Settings.get.enableFestiveDecorations) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
@ -108,7 +135,7 @@ class UISettingsTab extends SettingsTab {
) )
children :+= new PaddingBox( children :+= new PaddingBox(
new Slider((Settings.get.scaleFactor - 1) / 2, "Interface scale", 5) { new Slider((Settings.get.scaleFactor - 1) / 2, m"label.settings.ui.scale", 5) {
override def minimumSize: Size2D = Size2D(512, 24) override def minimumSize: Size2D = Size2D(512, 24)
// Interpolates [0; 1] as [1; 3] rounded to nearest 0.5 // Interpolates [0; 1] as [1; 3] rounded to nearest 0.5
@ -124,13 +151,13 @@ class UISettingsTab extends SettingsTab {
Padding2D(bottom = 8), Padding2D(bottom = 8),
) )
children :+= new PaddingBox(new Label("Tooltip delays:"), Padding2D(bottom = 8)) children :+= new PaddingBox(new Label(m"label.settings.ui.tooltipDelay"), Padding2D(bottom = 8))
children :+= new PaddingBox( children :+= new PaddingBox(
new Widget { new Widget {
override val layout = new LinearLayout(this) override val layout = new LinearLayout(this)
children :+= new Slider(Settings.get.tooltipDelayItem / 2.0f, "Items") { children :+= new Slider(Settings.get.tooltipDelayItem / 2.0f, m"label.settings.ui.tooltip.items") {
override def minimumSize: Size2D = Size2D(247, 24) override def minimumSize: Size2D = Size2D(247, 24)
private def convert(value: Float): Float = roundAt(2)(value * 2.0f).toFloat private def convert(value: Float): Float = roundAt(2)(value * 2.0f).toFloat
@ -146,7 +173,7 @@ class UISettingsTab extends SettingsTab {
override def maximumSize: Size2D = Size2D(16, 8) override def maximumSize: Size2D = Size2D(16, 8)
} }
children :+= new Slider(Settings.get.tooltipDelayUI / 2.0f, "UI Elements") { children :+= new Slider(Settings.get.tooltipDelayUI / 2.0f, m"label.settings.ui.tooltip.ui") {
override def minimumSize: Size2D = Size2D(247, 24) override def minimumSize: Size2D = Size2D(247, 24)
private def convert(value: Float): Float = roundAt(2)(value * 2.0f).toFloat private def convert(value: Float): Float = roundAt(2)(value * 2.0f).toFloat

View File

@ -5,10 +5,10 @@ import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Size2D import ocelot.desktop.geometry.Size2D
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.widget.Widget import ocelot.desktop.ui.widget.Widget
import ocelot.desktop.util.DrawUtils import ocelot.desktop.util.{DrawUtils, Message}
class KeyEntry(val key: String, val text: String) extends Widget { class KeyEntry(val key: String, val text: Message) extends Widget {
override def minimumSize: Size2D = Size2D(key.length * 8 + 24 + text.length * 8, 16) override def minimumSize: Size2D = Size2D(key.length * 8 + 24 + text.toString.length * 8, 16)
override def maximumSize: Size2D = minimumSize override def maximumSize: Size2D = minimumSize
override def draw(g: Graphics): Unit = { override def draw(g: Graphics): Unit = {
@ -19,6 +19,6 @@ class KeyEntry(val key: String, val text: String) extends Widget {
g.foreground = ColorScheme("StatusBarForeground") g.foreground = ColorScheme("StatusBarForeground")
g.setNormalFont() g.setNormalFont()
g.text(position.x + key.length * 8 + 16, position.y, text) g.text(position.x + key.length * 8 + 16, position.y, text.toString)
} }
} }

View File

@ -5,12 +5,12 @@ import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Size2D import ocelot.desktop.geometry.Size2D
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.widget.Widget import ocelot.desktop.ui.widget.Widget
import ocelot.desktop.util.{DrawUtils, Spritesheet} import ocelot.desktop.util.{DrawUtils, Message, Spritesheet}
class KeyMouseEntry(val icon: String, val key: String, val text: String) extends Widget { class KeyMouseEntry(val icon: String, val key: String, val text: Message) extends Widget {
private val iconSize = Spritesheet.spriteSize(icon) private val iconSize = Spritesheet.spriteSize(icon)
override def minimumSize: Size2D = Size2D(iconSize.width + key.length * 8 + 40 + text.length * 8, 16) override def minimumSize: Size2D = Size2D(iconSize.width + key.length * 8 + 40 + text.toString.length * 8, 16)
override def maximumSize: Size2D = minimumSize override def maximumSize: Size2D = minimumSize
override def draw(g: Graphics): Unit = { override def draw(g: Graphics): Unit = {
@ -23,6 +23,6 @@ class KeyMouseEntry(val icon: String, val key: String, val text: String) extends
g.foreground = ColorScheme("StatusBarForeground") g.foreground = ColorScheme("StatusBarForeground")
g.setNormalFont() g.setNormalFont()
g.text(position.x + iconSize.width + key.length * 8 + 24, position.y, text) g.text(position.x + iconSize.width + key.length * 8 + 24, position.y, text.toString)
} }
} }

View File

@ -5,18 +5,18 @@ import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Size2D import ocelot.desktop.geometry.Size2D
import ocelot.desktop.graphics.Graphics import ocelot.desktop.graphics.Graphics
import ocelot.desktop.ui.widget.Widget import ocelot.desktop.ui.widget.Widget
import ocelot.desktop.util.Spritesheet import ocelot.desktop.util.{Message, Spritesheet}
class MouseEntry(val icon: String, val text: String) extends Widget { class MouseEntry(val icon: String, val text: Message) extends Widget {
private val iconSize = Spritesheet.spriteSize(icon) private val iconSize = Spritesheet.spriteSize(icon)
override def minimumSize: Size2D = Size2D(iconSize.width + 24 + text.length * 8, 16) override def minimumSize: Size2D = Size2D(iconSize.width + 24 + text.toString.length * 8, 16)
override def maximumSize: Size2D = minimumSize override def maximumSize: Size2D = minimumSize
override def draw(g: Graphics): Unit = { override def draw(g: Graphics): Unit = {
g.sprite(icon, position + Size2D(8, height / 2 - iconSize.height / 2), ColorScheme("StatusBarIcon")) g.sprite(icon, position + Size2D(8, height / 2 - iconSize.height / 2), ColorScheme("StatusBarIcon"))
g.background = Color.Transparent g.background = Color.Transparent
g.foreground = ColorScheme("StatusBarForeground") g.foreground = ColorScheme("StatusBarForeground")
g.text(position.x + iconSize.width + 16, position.y, text) g.text(position.x + iconSize.width + 16, position.y, text.toString)
} }
} }

View File

@ -10,6 +10,8 @@ import ocelot.desktop.ui.layout.{AlignItems, LinearLayout}
import ocelot.desktop.ui.widget._ import ocelot.desktop.ui.widget._
import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry} import ocelot.desktop.ui.widget.contextmenu.{ContextMenu, ContextMenuEntry}
import ocelot.desktop.ui.widget.traits.HoverAnimation import ocelot.desktop.ui.widget.traits.HoverAnimation
import ocelot.desktop.util.Message
import ocelot.desktop.util.Message.LocalizedMessage
import ocelot.desktop.{ColorScheme, OcelotDesktop} import ocelot.desktop.{ColorScheme, OcelotDesktop}
import org.lwjgl.input.Keyboard import org.lwjgl.input.Keyboard
@ -35,7 +37,7 @@ class StatusBar extends Widget {
new Label { new Label {
override def maximumSize: Size2D = minimumSize override def maximumSize: Size2D = minimumSize
override def color: Color = ColorScheme("StatusBarFPS") override def color: Color = ColorScheme("StatusBarFPS")
override def text: String = f"FPS: ${UiHandler.fps}%02.1f" override def text = f"FPS: ${UiHandler.fps}%02.1f"
}, },
Padding2D(left = 8, right = 8), Padding2D(left = 8, right = 8),
) )
@ -65,13 +67,13 @@ class StatusBar extends Widget {
case ClickEvent(MouseEvent.Button.Right, pos) => case ClickEvent(MouseEvent.Button.Right, pos) =>
val menu = new ContextMenu val menu = new ContextMenu
menu.addEntry( menu.addEntry(
ContextMenuEntry("Change simulation speed", IconSource.Edit) { ContextMenuEntry(m"label.menu.changeSimulationSpeed", IconSource.Edit) {
new ChangeSimulationSpeedDialog().show() new ChangeSimulationSpeedDialog().show()
} }
) )
menu.addEntry( menu.addEntry(
ContextMenuEntry("Reset simulation speed", IconSource.Restart) { ContextMenuEntry(m"label.menu.resetSimulationSpeed", IconSource.Restart) {
OcelotDesktop.ticker.tickInterval = 50.millis OcelotDesktop.ticker.tickInterval = 50.millis
} }
) )
@ -100,7 +102,7 @@ class StatusBar extends Widget {
super.update() super.update()
if (isHovered) { if (isHovered) {
root.get.statusBar.addMouseEntry("icons/RMB", "Change simulation speed") root.get.statusBar.addMouseEntry("icons/RMB", m"label.menu.changeSimulationSpeed")
} }
} }
@ -108,7 +110,7 @@ class StatusBar extends Widget {
override def color: Color = ColorScheme("StatusBarTPS") override def color: Color = ColorScheme("StatusBarTPS")
override def text: String = f"TPS: ${OcelotDesktop.tpsCounter.fps}%02.1f" override def text = f"TPS: ${OcelotDesktop.tpsCounter.fps}%02.1f"
} }
object HoverBox extends PaddingBox(TpsLabel, Padding2D(left = 8, right = 8)) with HoverAnimation { object HoverBox extends PaddingBox(TpsLabel, Padding2D(left = 8, right = 8)) with HoverAnimation {
@ -133,7 +135,7 @@ class StatusBar extends Widget {
Padding2D(left = 8), Padding2D(left = 8),
) )
def addMouseEntry(icon: String, text: String): Unit = { def addMouseEntry(icon: String, text: Message): Unit = {
if ( if (
!keyMouseEntries.children.filter(_.isInstanceOf[MouseEntry]).map(_.asInstanceOf[MouseEntry]).exists( !keyMouseEntries.children.filter(_.isInstanceOf[MouseEntry]).map(_.asInstanceOf[MouseEntry]).exists(
_.icon == icon _.icon == icon
@ -142,7 +144,7 @@ class StatusBar extends Widget {
keyMouseEntries.children :+= new MouseEntry(icon, text) keyMouseEntries.children :+= new MouseEntry(icon, text)
} }
def addKeyMouseEntry(icon: String, key: String, text: String): Unit = { def addKeyMouseEntry(icon: String, key: String, text: Message): Unit = {
if ( if (
!keyMouseEntries.children.filter(_.isInstanceOf[KeyMouseEntry]).map(_.asInstanceOf[KeyMouseEntry]).exists(v => !keyMouseEntries.children.filter(_.isInstanceOf[KeyMouseEntry]).map(_.asInstanceOf[KeyMouseEntry]).exists(v =>
v.icon == icon && v.key == key v.icon == icon && v.key == key
@ -151,7 +153,7 @@ class StatusBar extends Widget {
keyMouseEntries.children :+= new KeyMouseEntry(icon, key, text) keyMouseEntries.children :+= new KeyMouseEntry(icon, key, text)
} }
def addKeyEntry(key: String, text: String): Unit = { def addKeyEntry(key: String, text: Message): Unit = {
if (!keyEntries.children.map(_.asInstanceOf[KeyEntry]).exists(_.key == key)) if (!keyEntries.children.map(_.asInstanceOf[KeyEntry]).exists(_.key == key))
keyEntries.children :+= new KeyEntry(key, text) keyEntries.children :+= new KeyEntry(key, text)
} }

View File

@ -4,15 +4,16 @@ import ocelot.desktop.Settings
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Padding2D import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.ui.widget.Label import ocelot.desktop.ui.widget.Label
import ocelot.desktop.util.Message
class ItemTooltip extends Tooltip { class ItemTooltip extends Tooltip {
override val DelayTime: Float = Settings.get.tooltipDelayItem override val DelayTime: Float = Settings.get.tooltipDelayItem
override def bodyPadding: Padding2D = Padding2D.equal(5) override def bodyPadding: Padding2D = Padding2D.equal(5)
def addLine(_text: String, _color: Color = Color.Grey): Unit = { def addLine(_text: Message, _color: Color = Color.Grey): Unit = {
body.children :+= new Label { body.children :+= new Label {
override def text: String = _text override def text: Message = _text
override def color: Color = _color override def color: Color = _color
} }
} }

View File

@ -4,13 +4,16 @@ import ocelot.desktop.Settings
import ocelot.desktop.color.Color import ocelot.desktop.color.Color
import ocelot.desktop.geometry.Padding2D import ocelot.desktop.geometry.Padding2D
import ocelot.desktop.ui.widget.Label import ocelot.desktop.ui.widget.Label
import ocelot.desktop.util.Message
class LabelTooltip(text: String) extends Tooltip { class LabelTooltip(text: String) extends Tooltip {
override val DelayTime: Float = Settings.get.tooltipDelayUI override val DelayTime: Float = Settings.get.tooltipDelayUI
def this(text: Message) = this(text.toString)
for (line <- text.split("\n")) { for (line <- text.split("\n")) {
body.children :+= new Label { body.children :+= new Label {
override def text: String = line override def text: Message = line
override def color: Color = Color.White override def color: Color = Color.White
} }
} }

View File

@ -9,10 +9,10 @@ import ocelot.desktop.ui.event.handlers.{HoverHandler, MouseHandler}
import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent} import ocelot.desktop.ui.event.{ClickEvent, HoverEvent, MouseEvent}
import ocelot.desktop.ui.layout.LinearLayout import ocelot.desktop.ui.layout.LinearLayout
import ocelot.desktop.ui.widget._ import ocelot.desktop.ui.widget._
import ocelot.desktop.util.Orientation import ocelot.desktop.util.{Message, Orientation}
import ocelot.desktop.util.animation.ColorAnimation import ocelot.desktop.util.animation.ColorAnimation
class VerticalMenuButton(icon: IconSource, label: String, handler: VerticalMenuButton => Unit = _ => {}) class VerticalMenuButton(icon: IconSource, label: Message, handler: VerticalMenuButton => Unit = _ => {})
extends Widget with MouseHandler with HoverHandler { extends Widget with MouseHandler with HoverHandler {
val colorAnimation: ColorAnimation = new ColorAnimation(ColorScheme("VerticalMenuBackground"), 0.6f) val colorAnimation: ColorAnimation = new ColorAnimation(ColorScheme("VerticalMenuBackground"), 0.6f)
@ -29,7 +29,7 @@ class VerticalMenuButton(icon: IconSource, label: String, handler: VerticalMenuB
) )
children :+= new Label { children :+= new Label {
override def text: String = label override def text: Message = label
override def color: Color = ColorScheme("VerticalMenuEntryForeground") override def color: Color = ColorScheme("VerticalMenuEntryForeground")
override def maximumSize: Size2D = Size2D(Float.PositiveInfinity, 16) override def maximumSize: Size2D = Size2D(Float.PositiveInfinity, 16)
} }

View File

@ -10,7 +10,7 @@ import ocelot.desktop.ui.UiHandler
import ocelot.desktop.ui.layout.{AlignItems, JustifyContent, LinearLayout} import ocelot.desktop.ui.layout.{AlignItems, JustifyContent, LinearLayout}
import ocelot.desktop.ui.widget._ import ocelot.desktop.ui.widget._
import ocelot.desktop.util.animation.{ColorAnimation, UnitAnimation} import ocelot.desktop.util.animation.{ColorAnimation, UnitAnimation}
import ocelot.desktop.util.{DefaultSlotItemsFillable, DrawUtils, Logging, Orientation} import ocelot.desktop.util.{DefaultSlotItemsFillable, DrawUtils, Logging, Message, Orientation}
import scala.collection.immutable.ArraySeq import scala.collection.immutable.ArraySeq
@ -68,7 +68,7 @@ class NodeSelector extends Window with Logging {
new LinearLayout(this, Orientation.Vertical, JustifyContent.Center, AlignItems.Center) new LinearLayout(this, Orientation.Vertical, JustifyContent.Center, AlignItems.Center)
children :+= new Label { children :+= new Label {
override def text: String = group.name override def text: Message = group.name
override def color: Color = ColorScheme("NodeSelectorRing") override def color: Color = ColorScheme("NodeSelectorRing")
} }

Some files were not shown because too many files have changed in this diff Show More