Skip to content

Commit

Permalink
Add capability to copy the image
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonScholz committed Nov 25, 2023
1 parent 66f72ea commit 1ec9832
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,18 @@ class ConfigService(
fun saveConfig() {
val config = Mapper.fromViewModel(qrCodeConfigViewModel)
val configJson = objectMapper.writeValueAsString(config)
preferences.put("config", configJson)
preferences.put(QR_CODE_CONFIG_PREFERENCE_KEY, configJson)
}

fun loadConfig() {
preferences.get(QR_CODE_CONFIG_PREFERENCE_KEY, null)?.let {
val config = objectMapper.readValue(it, QrCodeConfig::class.java)
Mapper.applyViewModel(config, qrCodeConfigViewModel)
}
}

fun resetConfig() {
preferences.remove(QR_CODE_CONFIG_PREFERENCE_KEY)
}

fun saveConfigFile(filePath: String) {
Expand All @@ -28,17 +39,14 @@ class ConfigService(
configJsonFile.writeText(configJson)
}

fun loadConfig() {
preferences.get("config", null)?.let {
val config = objectMapper.readValue(it, QrCodeConfig::class.java)
Mapper.applyViewModel(config, qrCodeConfigViewModel)
}
}

fun loadConfigFile(filePath: String) {
val configJsonFile = File(filePath)
val configJson = configJsonFile.readText()
val config = objectMapper.readValue(configJson, QrCodeConfig::class.java)
Mapper.applyViewModel(config, qrCodeConfigViewModel)
}

companion object {
private const val QR_CODE_CONFIG_PREFERENCE_KEY = "qrcode.config"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,21 @@ import io.github.simonscholz.qrcode.QrCodeConfig
import io.github.simonscholz.qrcode.QrCodeFactory
import io.github.simonscholz.qrcode.QrPositionalSquaresConfig
import io.github.simonscholz.ui.ImageUI
import org.jdesktop.swingx.graphics.GraphicsUtilities
import java.awt.Color
import java.awt.Image
import java.awt.datatransfer.DataFlavor
import java.awt.datatransfer.Transferable
import java.awt.datatransfer.UnsupportedFlavorException
import java.awt.image.BufferedImage
import java.io.File
import java.io.IOException
import java.util.ArrayList
import javax.imageio.ImageIO
import javax.swing.JOptionPane

class ImageService(private val qrCodeConfigViewModel: QrCodeConfigViewModel) {

fun renderImage(): BufferedImage {
val builder = QrCodeConfig.Builder(qrCodeConfigViewModel.qrCodeContent.value)
.qrCodeSize(qrCodeConfigViewModel.size.value)
Expand Down
59 changes: 57 additions & 2 deletions qr-code-app/src/main/kotlin/io/github/simonscholz/ui/FileUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package io.github.simonscholz.ui
import io.github.simonscholz.service.CodeGeneratorService
import io.github.simonscholz.service.ConfigService
import io.github.simonscholz.service.ImageService
import org.jdesktop.swingx.graphics.GraphicsUtilities
import java.awt.Image
import java.awt.Toolkit
import java.awt.datatransfer.Clipboard
import java.awt.datatransfer.StringSelection
import java.awt.datatransfer.*
import java.io.File
import java.io.IOException
import javax.imageio.ImageIO
import javax.swing.JFileChooser
import javax.swing.JOptionPane
Expand All @@ -19,6 +21,17 @@ class FileUI(
private val alreadyAppliedOnceDelegate: () -> Boolean,
) {

fun copyImageToClipboard() {
val qrCodeImage = if (alreadyAppliedOnceDelegate()) {
imageService.renderImage()
} else {
imageService.renderInitialImage()
}
val transferableImage = ImageTransferable(qrCodeImage)
val clipboard = Toolkit.getDefaultToolkit().systemClipboard
clipboard.setContents(transferableImage, null)
}

fun copyJavaCodeToClipboard() {
val generateKotlinCode = codeGeneratorService.generateJavaCode()
val clipboard: Clipboard = Toolkit.getDefaultToolkit().systemClipboard
Expand Down Expand Up @@ -97,4 +110,46 @@ class FileUI(
}
}
}

private class ImageTransferable(
private val img: Image,
private val exportName: String = "qr-code",
private val exportFormat: String = "png",
) : Transferable {
private var files: MutableList<File>? = null
override fun getTransferDataFlavors(): Array<DataFlavor> {
return arrayOf(
DataFlavor.imageFlavor,
DataFlavor.javaFileListFlavor,
)
}

override fun isDataFlavorSupported(flavor: DataFlavor): Boolean {
return if (flavor === DataFlavor.imageFlavor) {
true
} else flavor === DataFlavor.javaFileListFlavor
}

@Throws(UnsupportedFlavorException::class, IOException::class)
override fun getTransferData(flavor: DataFlavor): Any {
//log.fine("doing get trans data: " + flavor);
if (flavor === DataFlavor.imageFlavor) {
return img
}
if (flavor === DataFlavor.javaFileListFlavor) {
if (files == null) {
val file = File.createTempFile(exportName, ".$exportFormat")
//log.fine("writing to: " + file);
ImageIO.write(
GraphicsUtilities.convertToBufferedImage(img),
exportFormat, file,
)
files = listOf(file).toMutableList()
}
//log.fine("returning: " + files);
return files as MutableList<File>
}
return emptyList<File>()
}
}
}
11 changes: 11 additions & 0 deletions qr-code-app/src/main/kotlin/io/github/simonscholz/ui/ImageUI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ object ImageUI {
val contextMenu = JPopupMenu()

contextMenu.add(saveQrCodeImageMenuItem(fileUI))
contextMenu.add(copyQrCodeImageMenuItem(fileUI))
contextMenu.add(saveKotlinCodeMenuItem(fileUI))
contextMenu.add(saveJavaCodeMenuItem(fileUI))

Expand Down Expand Up @@ -73,6 +74,16 @@ object ImageUI {
return saveImageMenuItem
}

private fun copyQrCodeImageMenuItem(fileUI: FileUI): JMenuItem {
val copyImageMenuItem = JMenuItem("Copy Qr Code Image to clipboard")
// Add the keybinding for Save (Ctrl + C)
copyImageMenuItem.accelerator = KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK)
copyImageMenuItem.addActionListener {
fileUI.copyImageToClipboard()
}
return copyImageMenuItem
}

private fun saveKotlinCodeMenuItem(fileUI: FileUI): JMenuItem {
val saveImageMenuItem = JMenuItem("Copy Kotlin code to clipboard")
// Add the keybinding for Save (Ctrl + K)
Expand Down
32 changes: 30 additions & 2 deletions qr-code-app/src/main/kotlin/io/github/simonscholz/ui/MainMenu.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ object MainMenu {

createGenerateCodeMenu(menuBar, frame, fileUI)

createHelpMenu(menuBar, frame)
createHelpMenu(menuBar, frame, configService)
}

private fun createGenerateCodeMenu(menuBar: JMenuBar, frame: JFrame, fileUI: FileUI) {
Expand Down Expand Up @@ -88,6 +88,18 @@ object MainMenu {
},
)

val copyMenuItem = JMenuItem("Copy Qr Code Image")
// Add the keybinding for Save (Ctrl + C)
copyMenuItem.accelerator = KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK)
frame.rootPane.actionMap.put(
"CopyAction",
object : AbstractAction() {
override fun actionPerformed(e: ActionEvent) {
fileUI.copyImageToClipboard()
}
},
)

val importConfigMenuItem = JMenuItem("Import Config")
// Add the keybinding for Save (Ctrl + I)
importConfigMenuItem.accelerator = KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.CTRL_DOWN_MASK)
Expand Down Expand Up @@ -124,11 +136,13 @@ object MainMenu {
)

saveMenuItem.addActionListener { fileUI.saveQrCodeImageFile() }
copyMenuItem.addActionListener { fileUI.copyImageToClipboard() }
importConfigMenuItem.addActionListener { fileUI.loadConfig() }
exportConfigMenuItem.addActionListener { fileUI.saveConfig() }
exitMenuItem.addActionListener { exitApplication(configService) }

fileMenu.add(saveMenuItem)
fileMenu.add(copyMenuItem)
fileMenu.add(importConfigMenuItem)
fileMenu.add(exportConfigMenuItem)
fileMenu.add(exitMenuItem)
Expand Down Expand Up @@ -254,22 +268,36 @@ object MainMenu {
specialContentMenu.add(urlMenuItem)
}

private fun createHelpMenu(menuBar: JMenuBar, frame: JFrame) {
private fun createHelpMenu(menuBar: JMenuBar, frame: JFrame, configService: ConfigService) {
// Create the Help menu
val helpMenu = JMenu("Help")
menuBar.add(helpMenu)

val gitHubRepoMenuItem = JMenuItem("GitHub Repository")
val readmeMenuItem = JMenuItem("README")
val issueMenuItem = JMenuItem("Open Issue")
val resetPreferences = JMenuItem("Reset Preferences")

gitHubRepoMenuItem.addActionListener { openURL(frame, "https://github.com/SimonScholz/qr-code-with-logo") }
readmeMenuItem.addActionListener { openURL(frame, "https://github.com/SimonScholz/qr-code-with-logo/blob/main/README.adoc") }
issueMenuItem.addActionListener { openURL(frame, "https://github.com/SimonScholz/qr-code-with-logo/issues") }
resetPreferences.addActionListener {
val result = JOptionPane.showConfirmDialog(
frame,
"Do you really want to reset all preferences?",
"Reset Preferences",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
)
if (result == JOptionPane.YES_OPTION) {
configService.resetConfig()
}
}

helpMenu.add(gitHubRepoMenuItem)
helpMenu.add(readmeMenuItem)
helpMenu.add(issueMenuItem)
helpMenu.add(resetPreferences)
}

private fun openURL(frame: JFrame, url: String) {
Expand Down

0 comments on commit 1ec9832

Please sign in to comment.