Skip to content

Commit

Permalink
feat: Key-combinations to improve usability. CTRL + W closes the curr…
Browse files Browse the repository at this point in the history
…ent tab, CTRL + T opens a new tab, CTRL + S saves the current tab, CTRL + LSHIFT + S saves all tabs, CTRL + L opens the file selection for loading, CTRL + G generates the current tab.
  • Loading branch information
Griefed committed Jul 30, 2023
1 parent 3c571c8 commit 992cc9f
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 71 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/* Copyright (C) 2023 Griefed
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* The full license can be found at https:github.com/Griefed/ServerPackCreator/blob/main/LICENSE
*/
package de.griefed.serverpackcreator.gui.window

import de.griefed.serverpackcreator.api.ApiWrapper
import de.griefed.serverpackcreator.gui.GuiProps
import de.griefed.serverpackcreator.gui.window.menu.MainMenuBar
import de.griefed.serverpackcreator.updater.MigrationManager
import de.griefed.serverpackcreator.updater.UpdateChecker
import java.awt.AWTEvent
import java.awt.Toolkit
import java.awt.event.KeyEvent
import javax.swing.JFrame

/**
* Common key-combinations usable across ServerPackCreator, like loading and saving configs, generating
* a server pack, opening a new tab, closing a tab, etc. etc.
*
* * CTRL + W closes the current tab
* * CTRL + T opens a new tab
* * CTRL + S saves the current tab
* * CTRL + LSHIFT + S saves all tabs
* * CTRL + L opens the file selection for loading
* * CTRL + G generates the current tab
*
* @author Griefed
*/
class KeyComboManager(
private val guiProps: GuiProps,

Check warning on line 46 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/KeyComboManager.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Property "guiProps" is never used
private val apiWrapper: ApiWrapper,

Check warning on line 47 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/KeyComboManager.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Property "apiWrapper" is never used
private val updateChecker: UpdateChecker,

Check warning on line 48 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/KeyComboManager.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Property "updateChecker" is never used
private val updateDialogs: UpdateDialogs,

Check warning on line 49 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/KeyComboManager.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Property "updateDialogs" is never used
private val migrationManager: MigrationManager,

Check warning on line 50 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/KeyComboManager.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Property "migrationManager" is never used
private val frame: JFrame,

Check warning on line 51 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/KeyComboManager.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Property "frame" is never used
private val mainPanel: MainPanel,

Check warning on line 52 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/KeyComboManager.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Constructor parameter is never used as a property

Constructor parameter is never used as a property
private val menu: MainMenuBar

Check warning on line 53 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/KeyComboManager.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Unused symbol

Property "menu" is never used
) {

private val configs = mainPanel.tabbedConfigsTab
private val control = mainPanel.controlPanel

init {
addCloseTabCombo()
addNewTabCombo()
addSaveCurrentTabCombo()
addSaveAllTabsCombo()
addLoadConfigsCombo()
addStartGenerationCombo()
}

private fun addCloseTabCombo() {
Toolkit.getDefaultToolkit().addAWTEventListener({ e: AWTEvent ->
val event = e as KeyEvent
if (event.id == KeyEvent.KEY_RELEASED) {
when {
event.keyCode == KeyEvent.VK_W && event.isControlDown -> {
configs.selectedEditor!!.editorTitle.close()
}
}
}
}, AWTEvent.KEY_EVENT_MASK)
}

private fun addNewTabCombo() {
Toolkit.getDefaultToolkit().addAWTEventListener({ e: AWTEvent ->
val event = e as KeyEvent
if (event.id == KeyEvent.KEY_RELEASED) {
when {
event.keyCode == KeyEvent.VK_T && event.isControlDown -> {
configs.addTab()
}
}
}
}, AWTEvent.KEY_EVENT_MASK)
}

private fun addSaveCurrentTabCombo() {
Toolkit.getDefaultToolkit().addAWTEventListener({ e: AWTEvent ->
val event = e as KeyEvent
if (event.id == KeyEvent.KEY_RELEASED) {
when {
event.keyCode == KeyEvent.VK_S && event.isControlDown && !event.isShiftDown -> {
configs.selectedEditor!!.saveCurrentConfiguration()
}
}
}
}, AWTEvent.KEY_EVENT_MASK)
}

private fun addSaveAllTabsCombo() {
Toolkit.getDefaultToolkit().addAWTEventListener({ e: AWTEvent ->
val event = e as KeyEvent
if (event.id == KeyEvent.KEY_RELEASED) {
when {
event.keyCode == KeyEvent.VK_S && event.isControlDown && event.isShiftDown -> {
configs.saveAll()
}
}
}
}, AWTEvent.KEY_EVENT_MASK)
}

private fun addLoadConfigsCombo() {
Toolkit.getDefaultToolkit().addAWTEventListener({ e: AWTEvent ->
val event = e as KeyEvent
if (event.id == KeyEvent.KEY_RELEASED) {
when {
event.keyCode == KeyEvent.VK_L && event.isControlDown -> {
configs.loadConfigFile()
}
}
}
}, AWTEvent.KEY_EVENT_MASK)
}

private fun addStartGenerationCombo() {
Toolkit.getDefaultToolkit().addAWTEventListener({ e: AWTEvent ->
val event = e as KeyEvent
if (event.id == KeyEvent.KEY_RELEASED) {
when {
event.keyCode == KeyEvent.VK_G && event.isControlDown -> {
control.generate()
}
}
}
}, AWTEvent.KEY_EVENT_MASK)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,16 @@
package de.griefed.serverpackcreator.gui.window

import Gui
import com.formdev.flatlaf.FlatLaf
import de.griefed.serverpackcreator.api.ApiWrapper
import de.griefed.serverpackcreator.gui.GuiProps
import de.griefed.serverpackcreator.gui.window.menu.MainMenuBar
import de.griefed.serverpackcreator.updater.MigrationManager
import de.griefed.serverpackcreator.updater.UpdateChecker
import java.awt.AWTEvent
import java.awt.Dimension
import java.awt.Font
import java.awt.Toolkit
import java.awt.event.KeyEvent
import java.awt.event.WindowAdapter
import java.awt.event.WindowEvent
import javax.swing.JFrame
import javax.swing.UIManager
import javax.swing.WindowConstants
import javax.swing.plaf.FontUIResource

/**
* Main Frame of ServerPackCreator, housing [MainPanel], [MainMenuBar].
Expand All @@ -50,7 +43,7 @@ class MainFrame(
migrationManager: MigrationManager
) {
val frame: JFrame = JFrame(Gui.createserverpack_gui_createandshowgui.toString())
val mainPanel = MainPanel(guiProps, apiWrapper, guiProps.larsonScanner)
val mainPanel = MainPanel(guiProps, apiWrapper, guiProps.larsonScanner,this)

init {
val closeAndExit = object : WindowAdapter() {
Expand Down Expand Up @@ -78,6 +71,7 @@ class MainFrame(
frame.isVisible = true
guiProps.larsonScanner.loadConfig(guiProps.idleConfig)
guiProps.larsonScanner.play()
KeyComboManager(guiProps,apiWrapper,updateChecker,updateDialogs,migrationManager,frame,mainPanel,menu)
/*Toolkit.getDefaultToolkit().addAWTEventListener({ e: AWTEvent ->
val event = e as KeyEvent
if (event.id == KeyEvent.KEY_RELEASED) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ import kotlin.system.exitProcess
class MainPanel(
private val guiProps: GuiProps,
private val apiWrapper: ApiWrapper,
larsonScanner: LarsonScanner
larsonScanner: LarsonScanner,
mainFrame: MainFrame
) : TabPanel(
MigLayout(
"",
Expand All @@ -52,10 +53,10 @@ class MainPanel(
),
"growx,growy,north"
) {
val tabbedConfigsTab = TabbedConfigsTab(guiProps, apiWrapper)
private val tabbedLogsTab = TabbedLogsTab(apiWrapper.apiProperties)
private val settingsEditorTab = SettingsEditorTab(guiProps, apiWrapper.apiProperties)
private val controlPanel = ControlPanel(guiProps, tabbedConfigsTab, larsonScanner, apiWrapper)
val tabbedConfigsTab = TabbedConfigsTab(guiProps, apiWrapper, mainFrame)
val tabbedLogsTab = TabbedLogsTab(apiWrapper.apiProperties)

Check notice on line 57 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/MainPanel.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Class member can have 'private' visibility

Property 'tabbedLogsTab' could be private
val settingsEditorTab = SettingsEditorTab(guiProps, apiWrapper.apiProperties)

Check notice on line 58 in serverpackcreator-gui/src/main/kotlin/de/griefed/serverpackcreator/gui/window/MainPanel.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Class member can have 'private' visibility

Property 'settingsEditorTab' could be private
val controlPanel = ControlPanel(guiProps, tabbedConfigsTab, larsonScanner, apiWrapper)

init {
tabs.addTab("Configs", tabbedConfigsTab.panel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ package de.griefed.serverpackcreator.gui.window.configs
import Gui
import de.griefed.serverpackcreator.api.ApiWrapper
import de.griefed.serverpackcreator.api.PackConfig
import de.griefed.serverpackcreator.api.utilities.common.InvalidFileTypeException
import de.griefed.serverpackcreator.gui.GuiProps
import de.griefed.serverpackcreator.gui.components.TabPanel
import de.griefed.serverpackcreator.gui.utilities.DialogUtilities
import de.griefed.serverpackcreator.gui.window.MainFrame
import de.griefed.serverpackcreator.gui.window.configs.components.ComponentResizer
import de.griefed.serverpackcreator.gui.window.menu.file.ConfigChooser
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
Expand All @@ -35,6 +39,8 @@ import org.apache.logging.log4j.kotlin.cachedLoggerOf
import java.io.File
import java.util.concurrent.Executors
import javax.swing.DefaultComboBoxModel
import javax.swing.JFileChooser
import javax.swing.JOptionPane

/**
* Tabbed pane housing every server pack config tab.
Expand All @@ -44,7 +50,8 @@ import javax.swing.DefaultComboBoxModel
@OptIn(DelicateCoroutinesApi::class)
class TabbedConfigsTab(
private val guiProps: GuiProps,
private val apiWrapper: ApiWrapper
private val apiWrapper: ApiWrapper,
private val mainFrame: MainFrame
) : TabPanel() {
private val log = cachedLoggerOf(this.javaClass)
private val choose = arrayOf(Gui.createserverpack_gui_quickselect_choose.toString())
Expand Down Expand Up @@ -113,6 +120,12 @@ class TabbedConfigsTab(
return editor
}

fun saveAll() {
for (tab in allTabs) {
(tab as ConfigEditor).saveCurrentConfiguration()
}
}

/**
* When the GUI has finished loading, try and load the existing serverpackcreator.conf-file into
* ServerPackCreator.
Expand All @@ -125,6 +138,42 @@ class TabbedConfigsTab(
tab.loadConfiguration(PackConfig(apiWrapper.utilities!!, configFile), configFile)
}

/**
* @author Griefed
*/
fun loadConfigFile() {
val configChooser = ConfigChooser(apiWrapper.apiProperties, Gui.createserverpack_gui_buttonloadconfig_title.toString())
configChooser.isMultiSelectionEnabled = true
if (configChooser.showOpenDialog(mainFrame.frame) == JFileChooser.APPROVE_OPTION) {
val files = configChooser.selectedFiles.map { file ->
try {
File(apiWrapper.fileUtilities.resolveLink(file)).absoluteFile
} catch (ex: InvalidFileTypeException) {
log.error("Could not resolve link/symlink. Using entry from user input for checks.", ex)
file.absoluteFile
}
}
for (file in files) {
if (tabs.tabCount > 0 &&
DialogUtilities.createShowGet(
Gui.menubar_gui_config_load_message(file.absolutePath),
Gui.menubar_gui_config_load_title.toString(),
mainFrame.frame,
JOptionPane.QUESTION_MESSAGE,
JOptionPane.YES_NO_OPTION,
guiProps.warningIcon,
false,
arrayOf(Gui.menubar_gui_config_load_current, Gui.menubar_gui_config_load_new)
) == 0
) {
loadConfig(file, selectedEditor!!)
} else {
loadConfig(file)
}
}
}
}

/**
* @author Griefed
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,11 @@ class ConfigEditorTitle(
}

/**
* Close this tab. If this config has unsaved changes, ask whether this config should be saved first.
*
* @author Griefed
*/
private fun close() {
fun close() {
if (hasUnsavedChanges) {
tabbedConfigsTab.tabs.selectedComponent = configEditor
if (DialogUtilities.createShowGet(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,7 @@ class ControlPanel(
private val log = cachedLoggerOf(this.javaClass)
private val statusPanel = StatusPanel(guiProps)

@OptIn(DelicateCoroutinesApi::class)
private val runGeneration = GenerationButton(guiProps) {
GlobalScope.launch(guiProps.generationDispatcher) {
launchGeneration()
readyForGeneration()
}
}
private val runGeneration = GenerationButton(guiProps) { generate() }
private val serverPacks = ServerPacksButton(guiProps) {
apiWrapper.utilities!!.fileUtilities.openFolder(apiWrapper.apiProperties.serverPacksDirectory)
}
Expand All @@ -78,8 +72,16 @@ class ControlPanel(
panel.add(statusPanel.panel, "cell 1 0 1 2,grow,push, h 160!")
}

@OptIn(DelicateCoroutinesApi::class)
fun generate() {
GlobalScope.launch(guiProps.generationDispatcher) {
launchGeneration()
readyForGeneration()
}
}

/**
* Upon button-press, check the entered configuration and if successfull, generate a server pack.
* Upon button-press, check the entered configuration and if successful, generate a server pack.
*
* @author Griefed
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class FileMenu(
) : JMenu(Gui.menubar_gui_menu_file.toString()) {
init {
add(NewConfigItem(tabbedConfigsTab))
add(LoadConfigItem(apiProperties, mainFrame.frame, utilities.fileUtilities, guiProps, tabbedConfigsTab))
add(LoadConfigItem(tabbedConfigsTab))
add(JSeparator())
add(SaveConfigItem(tabbedConfigsTab))
add(SaveConfigAsItem(apiProperties, mainFrame.frame, tabbedConfigsTab))
Expand Down
Loading

0 comments on commit 992cc9f

Please sign in to comment.