mirror of
https://github.com/TermoraDev/termora.git
synced 2026-01-15 18:02:58 +08:00
feat: editor support maximization
This commit is contained in:
@@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
|
||||
|
||||
project.version = "0.0.6"
|
||||
project.version = "0.0.7"
|
||||
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
package app.termora.plugins.editor
|
||||
|
||||
import app.termora.DialogWrapper
|
||||
import app.termora.Disposable
|
||||
import app.termora.Disposer
|
||||
import app.termora.OptionPane
|
||||
import java.awt.Dimension
|
||||
import java.awt.Window
|
||||
import java.awt.event.WindowAdapter
|
||||
import java.awt.event.WindowEvent
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JOptionPane
|
||||
import javax.swing.UIManager
|
||||
import kotlin.io.path.absolutePathString
|
||||
import kotlin.io.path.name
|
||||
|
||||
|
||||
class EditorDialog(file: Path, owner: Window, private val myDisposable: Disposable) : DialogWrapper(null) {
|
||||
|
||||
private val filename = file.name
|
||||
private val filepath = File(file.absolutePathString())
|
||||
private val editorPanel = EditorPanel(this, filepath)
|
||||
private val disposed = AtomicBoolean()
|
||||
|
||||
init {
|
||||
size = Dimension(UIManager.getInt("Dialog.width"), UIManager.getInt("Dialog.height"))
|
||||
isModal = false
|
||||
controlsVisible = true
|
||||
isResizable = true
|
||||
title = filename
|
||||
iconImages = owner.iconImages
|
||||
escapeDispose = false
|
||||
defaultCloseOperation = DO_NOTHING_ON_CLOSE
|
||||
|
||||
initEvents()
|
||||
|
||||
setLocationRelativeTo(owner)
|
||||
|
||||
init()
|
||||
}
|
||||
|
||||
|
||||
private fun initEvents() {
|
||||
|
||||
addWindowListener(object : WindowAdapter() {
|
||||
override fun windowClosing(e: WindowEvent?) {
|
||||
if (disposed.compareAndSet(false, true)) {
|
||||
doCancelAction()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Disposer.register(myDisposable, object : Disposable {
|
||||
override fun dispose() {
|
||||
if (disposed.compareAndSet(false, true)) {
|
||||
doCancelAction()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Disposer.register(disposable, object : Disposable {
|
||||
override fun dispose() {
|
||||
if (disposed.compareAndSet(false, true)) {
|
||||
Disposer.dispose(myDisposable)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun doCancelAction() {
|
||||
if (editorPanel.changes()) {
|
||||
if (OptionPane.showConfirmDialog(
|
||||
this,
|
||||
"文件尚未保存,你确定要退出吗?",
|
||||
optionType = JOptionPane.OK_CANCEL_OPTION,
|
||||
) != JOptionPane.OK_OPTION
|
||||
) {
|
||||
return
|
||||
}
|
||||
}
|
||||
super.doCancelAction()
|
||||
}
|
||||
|
||||
override fun createCenterPanel(): JComponent {
|
||||
return editorPanel
|
||||
}
|
||||
|
||||
override fun createSouthPanel(): JComponent? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package app.termora.plugins.editor
|
||||
|
||||
import app.termora.Disposable
|
||||
import app.termora.Disposer
|
||||
import app.termora.EnableManager
|
||||
import app.termora.OptionPane
|
||||
import java.awt.BorderLayout
|
||||
import java.awt.Dimension
|
||||
import java.awt.Window
|
||||
import java.awt.event.WindowAdapter
|
||||
import java.awt.event.WindowEvent
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import javax.swing.JFrame
|
||||
import javax.swing.JOptionPane
|
||||
import javax.swing.UIManager
|
||||
import kotlin.io.path.absolutePathString
|
||||
import kotlin.io.path.name
|
||||
import kotlin.math.max
|
||||
|
||||
class EditorFrame(private val file: Path, private val owner: Window, private val disposable: Disposable) : JFrame() {
|
||||
private val enableManager get() = EnableManager.getInstance()
|
||||
private val disposed = AtomicBoolean()
|
||||
private val filepath = File(file.absolutePathString())
|
||||
private val frame get() = this
|
||||
private val editorPanel = EditorPanel(this, filepath)
|
||||
|
||||
init {
|
||||
initView()
|
||||
initEvent()
|
||||
}
|
||||
|
||||
private fun initEvent() {
|
||||
|
||||
Disposer.register(disposable, object : Disposable {
|
||||
override fun dispose() {
|
||||
if (disposed.compareAndSet(false, true)) frame.dispose()
|
||||
}
|
||||
})
|
||||
|
||||
addWindowListener(object : WindowAdapter() {
|
||||
override fun windowClosed(e: WindowEvent) {
|
||||
if (disposed.compareAndSet(false, true)) Disposer.dispose(disposable)
|
||||
enableManager.setFlag("Plugins.editor.dialog.width", width)
|
||||
enableManager.setFlag("Plugins.editor.dialog.height", height)
|
||||
enableManager.setFlag("Plugins.editor.dialog.extendedState", extendedState)
|
||||
}
|
||||
|
||||
override fun windowClosing(e: WindowEvent?) {
|
||||
if (editorPanel.changes()) {
|
||||
if (OptionPane.showConfirmDialog(
|
||||
frame,
|
||||
EditorI18n.getString("termora.plugins.editor.not-save"),
|
||||
optionType = JOptionPane.OK_CANCEL_OPTION,
|
||||
) == JOptionPane.OK_OPTION
|
||||
) {
|
||||
frame.dispose()
|
||||
}
|
||||
} else {
|
||||
frame.dispose()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
size = Dimension(UIManager.getInt("Dialog.width"), UIManager.getInt("Dialog.height"))
|
||||
val state = enableManager.getFlag("Plugins.editor.dialog.extendedState", 0)
|
||||
|
||||
if ((state and MAXIMIZED_BOTH) == MAXIMIZED_BOTH) {
|
||||
frame.setLocationRelativeTo(null)
|
||||
frame.extendedState = state
|
||||
} else {
|
||||
val mySize = size
|
||||
mySize.width = max(enableManager.getFlag("Plugins.editor.dialog.width", mySize.width), mySize.width)
|
||||
mySize.height = max(enableManager.getFlag("Plugins.editor.dialog.height", mySize.height), mySize.height)
|
||||
size = mySize
|
||||
setLocationRelativeTo(owner)
|
||||
}
|
||||
|
||||
title = file.name
|
||||
iconImages = owner.iconImages
|
||||
defaultCloseOperation = DO_NOTHING_ON_CLOSE
|
||||
|
||||
rootPane.contentPane.layout = BorderLayout()
|
||||
rootPane.contentPane.add(editorPanel, BorderLayout.CENTER)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package app.termora.plugins.editor
|
||||
|
||||
import app.termora.NamedI18n
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
object EditorI18n : NamedI18n("i18n/messages") {
|
||||
private val log = LoggerFactory.getLogger(EditorI18n::class.java)
|
||||
|
||||
override fun getLogger(): Logger {
|
||||
return log
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ import javax.swing.event.DocumentEvent
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class EditorPanel(private val window: JDialog, private val file: File) : JPanel(BorderLayout()) {
|
||||
class EditorPanel(private val window: JFrame, private val file: File) : JPanel(BorderLayout()) {
|
||||
|
||||
companion object {
|
||||
private val log = LoggerFactory.getLogger(EditorPanel::class.java)
|
||||
|
||||
@@ -14,7 +14,7 @@ class MyTransportEditFileExtension private constructor() : TransportEditFileExte
|
||||
|
||||
override fun edit(owner: Window, path: Path): Disposable {
|
||||
val disposable = Disposer.newDisposable()
|
||||
SwingUtilities.invokeLater { EditorDialog(path, owner, disposable).isVisible = true }
|
||||
SwingUtilities.invokeLater { EditorFrame(path, owner, disposable).isVisible = true }
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
termora.plugins.editor.not-save=The file has not been saved. Are you sure you want to exit?
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
termora.plugins.editor.not-save=Файл не сохранён. Вы уверены, что хотите выйти?
|
||||
@@ -0,0 +1 @@
|
||||
termora.plugins.editor.not-save=文件尚未保存,你确定要退出吗?
|
||||
@@ -0,0 +1 @@
|
||||
termora.plugins.editor.not-save=檔案尚未儲存,你確定要退出嗎?
|
||||
@@ -1,8 +1,11 @@
|
||||
package app.termora.plugin.internal.updater
|
||||
|
||||
import app.termora.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.swing.Swing
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.semver4j.Semver
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.awt.KeyboardFocusManager
|
||||
@@ -20,7 +23,7 @@ internal class MyApplicationRunnerExtension private constructor() : ApplicationR
|
||||
|
||||
|
||||
override fun ready() {
|
||||
swingCoroutineScope.launch {
|
||||
swingCoroutineScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
delay(3.seconds)
|
||||
scheduleUpdate()
|
||||
@@ -31,7 +34,7 @@ internal class MyApplicationRunnerExtension private constructor() : ApplicationR
|
||||
}
|
||||
|
||||
|
||||
private fun scheduleUpdate() {
|
||||
private suspend fun scheduleUpdate() {
|
||||
if (disabledUpdater) return
|
||||
|
||||
val latestVersion = updaterManager.fetchLatestVersion()
|
||||
@@ -45,13 +48,15 @@ internal class MyApplicationRunnerExtension private constructor() : ApplicationR
|
||||
return
|
||||
}
|
||||
|
||||
val owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().focusedWindow
|
||||
?: TermoraFrameManager.getInstance().getWindows().firstOrNull()
|
||||
if (owner == null) return
|
||||
|
||||
val dialog = UpdaterDialog(owner, latestVersion)
|
||||
dialog.isModal = true
|
||||
dialog.isVisible = true
|
||||
withContext(Dispatchers.Swing) {
|
||||
val owner = KeyboardFocusManager.getCurrentKeyboardFocusManager().focusedWindow
|
||||
?: TermoraFrameManager.getInstance().getWindows().firstOrNull()
|
||||
if (owner != null) {
|
||||
val dialog = UpdaterDialog(owner, latestVersion)
|
||||
dialog.isModal = true
|
||||
dialog.isVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user