Skip to content

Commit

Permalink
Refactored AlphaImage into PictureButton
Browse files Browse the repository at this point in the history
  • Loading branch information
McAJBen committed Jun 24, 2020
1 parent 58da65a commit 2190cfd
Show file tree
Hide file tree
Showing 6 changed files with 210 additions and 180 deletions.
32 changes: 16 additions & 16 deletions src/main/kotlin/control/ControlPictures.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@ class ControlPictures(
/**
* the scroll menu of images inside the folder
*/
private val picturePanel = object : PicturePanel(thumbnailFolder) {
override fun select(name: String) {
if (!allowList) {
display.removeAllImages()
components.forEach { it.background = Colors.DISABLE_COLOR }
private val picturePanel = object : PicturePanel(mode) {
override fun onChange(button: PictureButton, isEnabled: Boolean) {
if (isEnabled) {
if (!allowList) {
display.removeAllImages()
buttons.forEach { it.setEnabled(false) }
}
display.addImage(button)
} else {
display.removeImage(button)
}
display.addImage(name)
}

override fun deselect(name: String) {
display.removeImage(name)
}
}

Expand Down Expand Up @@ -89,7 +89,7 @@ class ControlPictures(
BorderLayout.CENTER
)
load()
picturePanel.forgetThumbnails()
picturePanel.unloadButtons()
isVisible = true
}

Expand All @@ -103,9 +103,9 @@ class ControlPictures(

override fun setMainControl(b: Boolean) {
if (b) {
picturePanel.rememberThumbnails()
picturePanel.loadButtons()
} else {
picturePanel.forgetThumbnails()
picturePanel.unloadButtons()
}
}

Expand All @@ -119,13 +119,13 @@ class ControlPictures(
it.delete()
}

picturePanel.clearButtons()
picturePanel.unloadButtons()

runBlocking {
folder.listFilesInOrder().filter {
it.hasImageExtension()
}.map {
async { picturePanel.add(picturePanel.createPPButton(it)) }
async { picturePanel.addPicture(it) }
}.forEach {
it.await()
}
Expand All @@ -134,7 +134,7 @@ class ControlPictures(
repaint()
revalidate()
display.removeAllImages()
picturePanel.rememberThumbnails()
picturePanel.loadButtons()
}
}

Expand Down
153 changes: 153 additions & 0 deletions src/main/kotlin/control/PictureButton.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package control

import util.*
import java.awt.Color
import java.awt.Dimension
import java.awt.Insets
import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO
import javax.swing.ImageIcon
import javax.swing.JButton
import javax.swing.SwingConstants

/**
* a container for an image source. To be used in `PicturePanel`
* @param source the source for the image. This must be in one of the Dungeon Board folders
* @author [email protected]
* @since 3.0.1
*/
class PictureButton(
private val source: File,
private val listener: Listener
) {
interface Listener {

/**
* called when an image is selected or deselected
* @param button the button that was clicked
* @param isEnabled the new state of the button
*/
fun onChange(button: PictureButton, isEnabled: Boolean)
}

companion object {

/**
* The size of the `ImageIcon` in each of the buttons
*/
private val IMAGE_ICON_SIZE = Dimension(100, 60)
}

/**
* the file used to load the image
*/
private val mode = Settings.getFileMode(source) ?: throw IllegalArgumentException("invalid source")

/**
* the thumbnail file for this image
*/
private val thumbnailSource = File(Settings.getDataFolder(mode), source.name)

/**
* whether the button is currently enabled or disabled
*/
private var isEnabled = false

/**
* button that controls whether the image should be displayed
*/
val button = JButton(source.nameWithoutExtension).also { button ->
button.margin = Insets(0, 0, 0, 0)
button.isFocusPainted = false
button.verticalTextPosition = SwingConstants.TOP
button.horizontalTextPosition = SwingConstants.CENTER
button.background = Colors.DISABLE_COLOR

button.addActionListener {
val isEnabled = !isEnabled
listener.onChange(this, isEnabled)
setEnabled(isEnabled)
}
}

init {
if (!thumbnailSource.exists() || source.lastModified() > thumbnailSource.lastModified()) {
try {
val bufferedImage = BufferedImage(
IMAGE_ICON_SIZE.width,
IMAGE_ICON_SIZE.height,
BufferedImage.TYPE_INT_RGB
)
bufferedImage.graphics.drawImage(
ImageIO.read(source).getScaledInstance(
IMAGE_ICON_SIZE.width,
IMAGE_ICON_SIZE.height,
BufferedImage.SCALE_SMOOTH
),
0,
0,
null
)
ImageIO.write(bufferedImage, "GIF", thumbnailSource)
} catch (e: Exception) {
Log.error(Labels.CANNOT_CREATE_THUMBNAIL, e)
}
}
}

/**
* changes the button's visual appearance
* @param isEnabled whether the button should be enabled
*/
fun setEnabled(isEnabled: Boolean) {
this.isEnabled = isEnabled

button.background = when(this.isEnabled) {
true -> Colors.ENABLE_COLOR
false -> Colors.DISABLE_COLOR
}
}

/**
* loads the thumbnail from file
*/
fun load() {
try {
button.icon = ImageIcon(ImageIO.read(thumbnailSource))
} catch (e: Exception) {
Log.error(Labels.CANNOT_LOAD_THUMBNAIL, e)
}
}

/**
* removes the thumbnail from local memory
*/
fun unload() {
button.icon = null
}

/**
* the `BufferedImage` from the file
*/
fun readImage(): BufferedImage {
return try {
ImageIO.read(source)
} catch (e: Exception) {
Log.error(String.format(Labels.CANNOT_LOAD_IMAGE, source), e)
Resources.BLANK_CURSOR
}
}

/**
* the background color of the image by using the top left corner pixel
*/
fun getBackgroundColor(): Color {
return try {
Color(ImageIO.read(thumbnailSource).getRGB(0, 0))
} catch (e: Exception) {
Log.error(String.format(Labels.CANNOT_LOAD_IMAGE_RGB, thumbnailSource), e)
Color.BLACK
}
}
}
121 changes: 23 additions & 98 deletions src/main/kotlin/control/PicturePanel.kt
Original file line number Diff line number Diff line change
@@ -1,25 +1,20 @@
package control

import util.Colors
import util.Labels
import util.Log
import java.awt.Dimension
import main.Mode
import java.awt.GridLayout
import java.awt.Insets
import java.awt.image.BufferedImage
import java.io.File
import javax.imageio.ImageIO
import javax.swing.*
import javax.swing.BorderFactory
import javax.swing.JPanel

/**
* a scroll menu to display images on as buttons
* @param thumbnailFolder directory to hold thumbnail caches
* @param mode directory to hold thumbnail caches
* @author [email protected]
* @since 1.0
*/
abstract class PicturePanel(
private val thumbnailFolder: File
) : JPanel() {
private val mode: Mode
) : JPanel(), PictureButton.Listener {

companion object {

Expand All @@ -29,114 +24,44 @@ abstract class PicturePanel(
* The number of picture per row of a picture panel
*/
private const val GRID_WIDTH = 4

/**
* The size of the `ImageIcon` in each of the buttons
*/
private val IMAGE_ICON_SIZE = Dimension(100, 60)
}

protected val buttons = mutableListOf<PictureButton>()

init {
layout = GridLayout(0, GRID_WIDTH)
border = BorderFactory.createEmptyBorder()
}

/**
* creates a button for a `PicturePanel` by loading an image from file
* @param file the file of an image to add
* @return a button with the proper settings for a `PicturePanel`
* creates a button for the `PicturePanel` by loading an image from file
* @param source the file of an image to add
*/
fun createPPButton(file: File): JButton {
createThumbnail(file)

return JButton(file.name).apply {
margin = Insets(0, 0, 0, 0)
isFocusPainted = false
verticalTextPosition = SwingConstants.TOP
horizontalTextPosition = SwingConstants.CENTER
background = Colors.DISABLE_COLOR
addActionListener {
val button = it.source as JButton
val name = button.text
if (button.background === Colors.DISABLE_COLOR) {
select(name)
button.background = Colors.ENABLE_COLOR
} else {
deselect(name)
button.background = Colors.DISABLE_COLOR
}
}
}
}

/**
* re-sizes an image and saves a lower quality version as a thumbnail
* @param file the file input of the full size image
*/
private fun createThumbnail(file: File) {
val tFile = File(thumbnailFolder, file.name)
if (!tFile.exists() || file.lastModified() > tFile.lastModified()) {
try {
val bufferedImage = BufferedImage(
IMAGE_ICON_SIZE.width,
IMAGE_ICON_SIZE.height,
BufferedImage.TYPE_INT_RGB
)
bufferedImage.graphics.drawImage(
ImageIO.read(file).getScaledInstance(
IMAGE_ICON_SIZE.width,
IMAGE_ICON_SIZE.height,
BufferedImage.SCALE_SMOOTH
),
0, 0, null
)
ImageIO.write(bufferedImage, "GIF", tFile)
} catch (e: Exception) {
Log.error(Labels.CANNOT_CREATE_THUMBNAIL, e)
}
}
}
fun addPicture(source: File) {
val pictureButton = PictureButton(source, this)

/**
* removes all images
*/
fun clearButtons() {
components.filterIsInstance<JButton>().forEach {
remove(it)
}
buttons.add(pictureButton)
}

/**
* called when an image is selected
* @param name the name of the image
*/
protected abstract fun select(name: String)

/**
* called when an image is deselected
* @param name the name of the image
*/
protected abstract fun deselect(name: String)

/**
* loads the thumbnails from file
*/
fun rememberThumbnails() {
components.filterIsInstance<JButton>().forEach {
try {
it.icon = ImageIcon(ImageIO.read(File(thumbnailFolder, it.text)))
} catch (e: Exception) {
Log.error(Labels.CANNOT_LOAD_THUMBNAIL, e)
}
fun loadButtons() {
buttons.forEach {
it.load()
add(it.button)
}
}

/**
* removes the thumbnails from local memory
*/
fun forgetThumbnails() {
components.filterIsInstance<JButton>().forEach {
it.icon = null
fun unloadButtons() {
buttons.forEach {
it.unload()
remove(it.button)
}
}

abstract override fun onChange(button: PictureButton, isEnabled: Boolean)
}
Loading

0 comments on commit 2190cfd

Please sign in to comment.