mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 10:34:06 +09:00
new import screen
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing.",
|
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "This is a world currently playing.",
|
||||||
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_1": "Copy the Avatar Code into the clipboard, then hit the Paste button below.",
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_1": "1. Place the Avatar file into the following directory:",
|
||||||
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_2": ""
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_2": "",
|
||||||
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_3": "2. Enter the name of the file below, then press Import"
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다.",
|
"CONTEXT_THIS_IS_A_WORLD_CURRENTLY_PLAYING": "현재 플레이 중인 월드입니다.",
|
||||||
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_1": "아바타 코드를 클립보드에 복사한 다음, 아래의 붙여넣기 버튼을 눌러주세요.",
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_1": "1. 아바타 파일을 다음 폴더에 넣어주세요",
|
||||||
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_2": ""
|
"CONTEXT_IMPORT_AVATAR_INSTRUCTION_3": "2. 아바타 파일 이름을 아래에 입력하고 가져오기를 눌러주세요"
|
||||||
}
|
}
|
||||||
@@ -1185,6 +1185,8 @@ public class App implements ApplicationListener {
|
|||||||
public static String configDir;
|
public static String configDir;
|
||||||
/** defaultDir + "/LoadOrder.txt" */
|
/** defaultDir + "/LoadOrder.txt" */
|
||||||
public static String loadOrderDir;
|
public static String loadOrderDir;
|
||||||
|
/** defaultDir + "/Imported" */
|
||||||
|
public static String importDir;
|
||||||
|
|
||||||
public static RunningEnvironment environment;
|
public static RunningEnvironment environment;
|
||||||
|
|
||||||
@@ -1224,6 +1226,7 @@ public class App implements ApplicationListener {
|
|||||||
loadOrderDir = defaultDir + "/LoadOrder.txt";
|
loadOrderDir = defaultDir + "/LoadOrder.txt";
|
||||||
recycledPlayersDir = defaultDir + "/Recycled/Players";
|
recycledPlayersDir = defaultDir + "/Recycled/Players";
|
||||||
recycledWorldsDir = defaultDir + "/Recycled/Worlds";
|
recycledWorldsDir = defaultDir + "/Recycled/Worlds";
|
||||||
|
importDir = defaultDir + "/Imports";
|
||||||
|
|
||||||
System.out.println(String.format("os.name = %s (with identifier %s)", OSName, operationSystem));
|
System.out.println(String.format("os.name = %s (with identifier %s)", OSName, operationSystem));
|
||||||
System.out.println(String.format("os.version = %s", OSVersion));
|
System.out.println(String.format("os.version = %s", OSVersion));
|
||||||
@@ -1239,6 +1242,7 @@ public class App implements ApplicationListener {
|
|||||||
new File(worldsDir),
|
new File(worldsDir),
|
||||||
new File(recycledPlayersDir),
|
new File(recycledPlayersDir),
|
||||||
new File(recycledWorldsDir),
|
new File(recycledWorldsDir),
|
||||||
|
new File(importDir)
|
||||||
};
|
};
|
||||||
|
|
||||||
for (File it : dirs) {
|
for (File it : dirs) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
|||||||
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
import com.badlogic.gdx.graphics.glutils.FrameBuffer
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.ui.Toolkit
|
||||||
|
import net.torvald.terrarum.utils.OpenFile
|
||||||
import java.awt.Desktop
|
import java.awt.Desktop
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ class NoModuleDefaultTitlescreen(batch: FlippingSpriteBatch) : IngameInstance(ba
|
|||||||
App.scr.hf - Gdx.input.y in pathButtonY - 12..pathButtonY + pathButtonH + 12)
|
App.scr.hf - Gdx.input.y in pathButtonY - 12..pathButtonY + pathButtonH + 12)
|
||||||
|
|
||||||
if (mouseOnLink && Gdx.input.isButtonJustPressed(Input.Buttons.LEFT)) {
|
if (mouseOnLink && Gdx.input.isButtonJustPressed(Input.Buttons.LEFT)) {
|
||||||
Desktop.getDesktop().open(pathFile)
|
OpenFile(pathFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
fbatch.inUse {
|
fbatch.inUse {
|
||||||
|
|||||||
@@ -6,15 +6,22 @@ import com.badlogic.gdx.graphics.Camera
|
|||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.terrarum.App
|
import net.torvald.terrarum.App
|
||||||
|
import net.torvald.terrarum.App.printdbg
|
||||||
|
import net.torvald.terrarum.AppUpdateListOfSavegames
|
||||||
import net.torvald.terrarum.Second
|
import net.torvald.terrarum.Second
|
||||||
import net.torvald.terrarum.ceilToInt
|
import net.torvald.terrarum.ceilToInt
|
||||||
import net.torvald.terrarum.gamecontroller.*
|
import net.torvald.terrarum.gamecontroller.*
|
||||||
import net.torvald.terrarum.langpack.Lang
|
import net.torvald.terrarum.langpack.Lang
|
||||||
import net.torvald.terrarum.serialise.Ascii85Codec
|
import net.torvald.terrarum.savegame.*
|
||||||
import net.torvald.terrarum.ui.Toolkit
|
import net.torvald.terrarum.savegame.VDFileID.ROOT
|
||||||
import net.torvald.terrarum.ui.UIItem
|
import net.torvald.terrarum.savegame.VDFileID.SAVEGAMEINFO
|
||||||
import net.torvald.terrarum.ui.UIItemTextButton
|
import net.torvald.terrarum.serialise.Common
|
||||||
|
import net.torvald.terrarum.ui.*
|
||||||
import net.torvald.terrarum.utils.Clipboard
|
import net.torvald.terrarum.utils.Clipboard
|
||||||
|
import net.torvald.terrarum.utils.JsonFetcher
|
||||||
|
import net.torvald.terrarum.utils.OpenFile
|
||||||
|
import java.awt.Desktop
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2023-08-24.
|
* Created by minjaesong on 2023-08-24.
|
||||||
@@ -31,14 +38,23 @@ class UIImportAvatar(val remoCon: UIRemoCon) : Advanceable() {
|
|||||||
private val rows = 30
|
private val rows = 30
|
||||||
private val goButtonWidth = 180
|
private val goButtonWidth = 180
|
||||||
|
|
||||||
|
private val descStartY = 24 * 4
|
||||||
|
private val lh = App.fontGame.lineHeight.toInt()
|
||||||
|
|
||||||
private val codeBox = UIItemCodeBox(this, (Toolkit.drawWidth - App.fontSmallNumbers.W * cols) / 2, drawY, cols, rows)
|
// private val codeBox = UIItemCodeBox(this, (Toolkit.drawWidth - App.fontSmallNumbers.W * cols) / 2, drawY, cols, rows)
|
||||||
|
|
||||||
|
private val inputWidth = 340
|
||||||
|
private val filenameInput = UIItemTextLineInput(this,
|
||||||
|
(Toolkit.drawWidth - inputWidth) / 2, (App.scr.height - height) / 2 + descStartY + (5) * lh, inputWidth,
|
||||||
|
maxLen = InputLenCap(256, InputLenCap.CharLenUnit.UTF8_BYTES)
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
private val clearButton = UIItemTextButton(this,
|
private val clearButton = UIItemTextButton(this,
|
||||||
{ Lang["MENU_IO_CLEAR"] }, drawX + (width/2 - goButtonWidth) / 2, drawY + height - 24 - 34, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
{ Lang["MENU_IO_CLEAR"] }, drawX + (width/2 - goButtonWidth) / 2, drawY + height - 24 - 34, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
private val pasteButton = UIItemTextButton(this,
|
private val pasteButton = UIItemTextButton(this,
|
||||||
{ Lang["MENU_LABEL_PASTE"] }, drawX + width/2 + (width/2 - goButtonWidth) / 2, drawY + height - 24 - 34, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
{ Lang["MENU_LABEL_PASTE"] }, drawX + width/2 + (width/2 - goButtonWidth) / 2, drawY + height - 24 - 34, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
*/
|
||||||
|
|
||||||
private val backButton = UIItemTextButton(this,
|
private val backButton = UIItemTextButton(this,
|
||||||
{ Lang["MENU_LABEL_BACK"] }, drawX + (width/2 - goButtonWidth) / 2, drawY + height - 24, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
{ Lang["MENU_LABEL_BACK"] }, drawX + (width/2 - goButtonWidth) / 2, drawY + height - 24, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
@@ -46,32 +62,63 @@ class UIImportAvatar(val remoCon: UIRemoCon) : Advanceable() {
|
|||||||
{ Lang["MENU_IO_IMPORT"] }, drawX + width/2 + (width/2 - goButtonWidth) / 2, drawY + height - 24, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
{ Lang["MENU_IO_IMPORT"] }, drawX + width/2 + (width/2 - goButtonWidth) / 2, drawY + height - 24, goButtonWidth, alignment = UIItemTextButton.Companion.Alignment.CENTRE, hasBorder = true)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
addUIitem(codeBox)
|
// addUIitem(codeBox)
|
||||||
addUIitem(clearButton)
|
// addUIitem(clearButton)
|
||||||
addUIitem(pasteButton)
|
// addUIitem(pasteButton)
|
||||||
|
addUIitem(filenameInput)
|
||||||
addUIitem(backButton)
|
addUIitem(backButton)
|
||||||
addUIitem(goButton)
|
addUIitem(goButton)
|
||||||
|
|
||||||
clearButton.clickOnceListener = { _,_ ->
|
/*clearButton.clickOnceListener = { _,_ ->
|
||||||
codeBox.clearTextBuffer()
|
codeBox.clearTextBuffer()
|
||||||
}
|
}
|
||||||
pasteButton.clickOnceListener = { _,_ ->
|
pasteButton.clickOnceListener = { _,_ ->
|
||||||
codeBox.pasteFromClipboard()
|
codeBox.pasteFromClipboard()
|
||||||
}
|
}*/
|
||||||
backButton.clickOnceListener = { _,_ ->
|
backButton.clickOnceListener = { _,_ ->
|
||||||
remoCon.openUI(UILoadSavegame(remoCon))
|
remoCon.openUI(UILoadSavegame(remoCon))
|
||||||
}
|
}
|
||||||
goButton.clickOnceListener = { _,_ ->
|
goButton.clickOnceListener = { _,_ ->
|
||||||
doImport()
|
val returnCode = doImport()
|
||||||
|
if (returnCode == 0) remoCon.openUI(UILoadSavegame(remoCon))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// private var textX = 0
|
||||||
|
private var textY = 0
|
||||||
|
private var mouseOnLink = false
|
||||||
|
private var pathW = 0
|
||||||
|
|
||||||
override fun updateUI(delta: Float) {
|
override fun updateUI(delta: Float) {
|
||||||
uiItems.forEach { it.update(delta) }
|
uiItems.forEach { it.update(delta) }
|
||||||
|
|
||||||
|
|
||||||
|
pathW = App.fontGame.getWidth(App.importDir)
|
||||||
|
val textX = (Toolkit.drawWidth - pathW) / 2
|
||||||
|
textY = (App.scr.height - height) / 2 + descStartY + (1) * lh
|
||||||
|
mouseOnLink = (Gdx.input.x in textX - 48..textX + 48 + pathW &&
|
||||||
|
Gdx.input.y in textY - 12..textY + lh + 12)
|
||||||
|
|
||||||
|
if (mouseOnLink && Gdx.input.isButtonJustPressed(Input.Buttons.LEFT)) {
|
||||||
|
OpenFile(File(App.importDir))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val textboxIndices = (1..3)
|
||||||
|
|
||||||
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
override fun renderUI(batch: SpriteBatch, camera: Camera) {
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
val textboxWidth = textboxIndices.maxOf { App.fontGame.getWidth(Lang["CONTEXT_IMPORT_AVATAR_INSTRUCTION_$it"]) }
|
||||||
|
val textX = (Toolkit.drawWidth - textboxWidth) / 2
|
||||||
|
// draw texts
|
||||||
|
for (i in textboxIndices) {
|
||||||
|
App.fontGame.draw(batch, Lang["CONTEXT_IMPORT_AVATAR_INSTRUCTION_$i"], textX, (App.scr.height - height) / 2 + descStartY + (i - 1) * lh)
|
||||||
|
}
|
||||||
|
// draw path
|
||||||
|
batch.color = if (mouseOnLink) Toolkit.Theme.COL_SELECTED else Toolkit.Theme.COL_MOUSE_UP
|
||||||
|
App.fontGame.draw(batch, App.importDir, (Toolkit.drawWidth - pathW) / 2, textY)
|
||||||
|
|
||||||
|
|
||||||
uiItems.forEach { it.render(batch, camera) }
|
uiItems.forEach { it.render(batch, camera) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,13 +128,68 @@ class UIImportAvatar(val remoCon: UIRemoCon) : Advanceable() {
|
|||||||
override fun advanceMode(button: UIItem) {
|
override fun advanceMode(button: UIItem) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doImport() {
|
private fun doImport(): Int {
|
||||||
val rawStr = codeBox.textBuffer.toString()
|
val file = File("${App.importDir}/${filenameInput.getText()}")
|
||||||
// sanity check
|
|
||||||
|
// check file's existence
|
||||||
|
if (!file.exists()) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to mount the TEVd
|
||||||
|
try {
|
||||||
|
val dom = VDUtil.readDiskArchive(file)
|
||||||
|
val timeNow = App.getTIME_T()
|
||||||
|
|
||||||
|
// get the uuid
|
||||||
|
val oldPlayerInfoFile = dom.getEntry(SAVEGAMEINFO)!!
|
||||||
|
val playerInfo = JsonFetcher.readFromJsonString(ByteArray64Reader(VDUtil.getAsNormalFile(dom, SAVEGAMEINFO).bytes, Common.CHARSET))
|
||||||
|
val uuid = playerInfo.getString("uuid")
|
||||||
|
val newFile = File("${App.playersDir}/$uuid")
|
||||||
|
|
||||||
|
printdbg(this, "Avatar uuid: $uuid")
|
||||||
|
|
||||||
|
if (newFile.exists()) return 2
|
||||||
|
|
||||||
|
// update playerinfo so that:
|
||||||
|
// totalPlayTime to zero
|
||||||
|
// lastPlayedTime to now
|
||||||
|
// playerinfofile's lastModifiedTime to now
|
||||||
|
// root's lastModifiedTime to now
|
||||||
|
printdbg(this, "avatar old lastPlayTime: ${playerInfo.getLong("lastPlayTime")}")
|
||||||
|
printdbg(this, "avatar old totalPlayTime: ${playerInfo.getLong("totalPlayTime")}")
|
||||||
|
playerInfo.get("lastPlayTime").set(timeNow, null)
|
||||||
|
playerInfo.get("totalPlayTime").set(0, null)
|
||||||
|
printdbg(this, "avatar new lastPlayTime: ${playerInfo.getLong("lastPlayTime")}")
|
||||||
|
printdbg(this, "avatar new totalPlayTime: ${playerInfo.getLong("totalPlayTime")}")
|
||||||
|
|
||||||
|
val newJsonBytes = ByteArray64Writer(Common.CHARSET).let {
|
||||||
|
// println(playerInfo.toString())
|
||||||
|
it.write(playerInfo.toString())
|
||||||
|
it.close()
|
||||||
|
it.toByteArray64()
|
||||||
|
}
|
||||||
|
val newPlayerInfo = DiskEntry(SAVEGAMEINFO, ROOT, oldPlayerInfoFile.creationDate, timeNow, EntryFile(newJsonBytes))
|
||||||
|
VDUtil.addFile(dom, newPlayerInfo)
|
||||||
|
|
||||||
|
dom.getEntry(ROOT)!!.modificationDate = timeNow
|
||||||
|
|
||||||
|
// mark the file as Imported
|
||||||
|
dom.saveOrigin = VDSaveOrigin.IMPORTED
|
||||||
|
|
||||||
|
// write modified file to the Players dir
|
||||||
|
VDUtil.dumpToRealMachine(dom, newFile)
|
||||||
|
|
||||||
|
|
||||||
val ascii85codec = Ascii85Codec((33..117).map { it.toChar() }.joinToString(""))
|
AppUpdateListOfSavegames()
|
||||||
val ascii85str = rawStr.substring(2 until rawStr.length - 2).replace("z", "!!!!!")
|
}
|
||||||
|
catch (e: Throwable) {
|
||||||
|
// format error
|
||||||
|
e.printStackTrace()
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -447,6 +447,13 @@ removefile:
|
|||||||
fa.close()
|
fa.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setSaveOrigin(bits: Int) {
|
||||||
|
val fa = RandomAccessFile(diskFile, "rwd")
|
||||||
|
fa.seek(51L)
|
||||||
|
fa.writeByte(bits)
|
||||||
|
fa.close()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Save type (0b 0000 00ab)
|
* @return Save type (0b 0000 00ab)
|
||||||
* b: unset - full save; set - quicksave (only applicable to worlds -- quicksave just means the disk is in dirty state)
|
* b: unset - full save; set - quicksave (only applicable to worlds -- quicksave just means the disk is in dirty state)
|
||||||
@@ -467,6 +474,15 @@ removefile:
|
|||||||
return fa.read().also { fa.close() }
|
return fa.read().also { fa.close() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return 16 if the savegame was imported, 0 if the savegame was generated in-game
|
||||||
|
*/
|
||||||
|
fun getSaveOrigin(): Int {
|
||||||
|
val fa = RandomAccessFile(diskFile, "rwd")
|
||||||
|
fa.seek(51L)
|
||||||
|
return fa.read().also { fa.close() }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun getDiskName(charset: Charset): String {
|
override fun getDiskName(charset: Charset): String {
|
||||||
|
|||||||
@@ -76,8 +76,11 @@ Version 254 is a customised version of TEVD tailored to be used as a savegame fo
|
|||||||
0: Undefined (or very old version of the game)
|
0: Undefined (or very old version of the game)
|
||||||
1: Player Data
|
1: Player Data
|
||||||
2: World Data
|
2: World Data
|
||||||
Int8[13] Extra info bytes reserved for future usage
|
Int8 Savefile Origin Flags
|
||||||
/* END extraInfoBytes */
|
0: Created in-game
|
||||||
|
16: Imported
|
||||||
|
Int8[12] Extra info bytes reserved for future usage
|
||||||
|
-- END extraInfoBytes --
|
||||||
UInt8[236] Rest of the long disk name (268 bytes total)
|
UInt8[236] Rest of the long disk name (268 bytes total)
|
||||||
|
|
||||||
(Header size: 300 bytes)
|
(Header size: 300 bytes)
|
||||||
@@ -150,6 +153,9 @@ class VirtualDisk(
|
|||||||
var saveKind: Int
|
var saveKind: Int
|
||||||
set(value) { extraInfoBytes[2] = value.toByte() }
|
set(value) { extraInfoBytes[2] = value.toByte() }
|
||||||
get() = extraInfoBytes[2].toUint()
|
get() = extraInfoBytes[2].toUint()
|
||||||
|
var saveOrigin: Int
|
||||||
|
set(value) { extraInfoBytes[3] = value.toByte() }
|
||||||
|
get() = extraInfoBytes[3].toUint()
|
||||||
override fun getDiskName(charset: Charset) = diskName.toCanonicalString(charset)
|
override fun getDiskName(charset: Charset) = diskName.toCanonicalString(charset)
|
||||||
val root: DiskEntry
|
val root: DiskEntry
|
||||||
get() = entries[0]!!
|
get() = entries[0]!!
|
||||||
@@ -249,6 +255,11 @@ object VDSaveKind {
|
|||||||
const val WORLD_DATA = 2
|
const val WORLD_DATA = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object VDSaveOrigin {
|
||||||
|
const val INGAME = 0
|
||||||
|
const val IMPORTED = 16
|
||||||
|
}
|
||||||
|
|
||||||
object VDFileID {
|
object VDFileID {
|
||||||
const val ROOT = 0L
|
const val ROOT = 0L
|
||||||
const val SAVEGAMEINFO = -1L
|
const val SAVEGAMEINFO = -1L
|
||||||
|
|||||||
@@ -1,24 +1,43 @@
|
|||||||
package net.torvald.terrarum.utils
|
package net.torvald.terrarum.utils
|
||||||
|
|
||||||
|
import net.torvald.terrarum.App
|
||||||
|
import java.awt.Desktop
|
||||||
import java.awt.Toolkit
|
import java.awt.Toolkit
|
||||||
import java.awt.datatransfer.DataFlavor
|
import java.awt.datatransfer.DataFlavor
|
||||||
import java.awt.datatransfer.StringSelection
|
import java.awt.datatransfer.StringSelection
|
||||||
import java.awt.datatransfer.UnsupportedFlavorException
|
import java.awt.datatransfer.UnsupportedFlavorException
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2016-07-31.
|
* Created by minjaesong on 2016-07-31.
|
||||||
*/
|
*/
|
||||||
object Clipboard {
|
object Clipboard {
|
||||||
fun fetch(): String = try {
|
private val IS_MACOS = App.operationSystem == "OSX"
|
||||||
Toolkit.getDefaultToolkit().systemClipboard.getData(DataFlavor.stringFlavor) as String
|
|
||||||
}
|
fun fetch(): String =
|
||||||
catch (e: UnsupportedFlavorException) {
|
if (IS_MACOS) "Clipboard is disabled on macOS" else
|
||||||
""
|
try {
|
||||||
}
|
Toolkit.getDefaultToolkit().systemClipboard.getData(DataFlavor.stringFlavor) as String
|
||||||
|
}
|
||||||
|
catch (e: UnsupportedFlavorException) {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
|
||||||
fun copy(s: String) {
|
fun copy(s: String) {
|
||||||
|
if (IS_MACOS) return
|
||||||
val selection = StringSelection(s)
|
val selection = StringSelection(s)
|
||||||
val clipboard = Toolkit.getDefaultToolkit().systemClipboard
|
val clipboard = Toolkit.getDefaultToolkit().systemClipboard
|
||||||
clipboard.setContents(selection, selection)
|
clipboard.setContents(selection, selection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-25.
|
||||||
|
*/
|
||||||
|
object OpenFile {
|
||||||
|
private val IS_MACOS = App.operationSystem == "OSX"
|
||||||
|
operator fun invoke(file: File) {
|
||||||
|
if (IS_MACOS) return // at this point macOS might as well be a bane of existence for "some" devs Apple fanboys think they are not worthy of existence
|
||||||
|
Desktop.getDesktop().open(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user