Skip to content

Commit

Permalink
Merge pull request #128 from Azn9/feat/different-theme-for-applicatio…
Browse files Browse the repository at this point in the history
…n-and-language-icons

feat: allow to choose two different themes for the application and language icons
  • Loading branch information
Azn9 authored Jun 14, 2024
2 parents cbe20ed + a9511d4 commit df79530
Show file tree
Hide file tree
Showing 16 changed files with 89 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ interface Theme {
override val name: String
get() = "Default"
override val description: String
get() = "The default theme"
get() = "Use the theme set on the global settings"
override val onlyApplicationIcons: Boolean
get() = false
override val onlyLanguageIcons: Boolean
get() = false

override fun getIconSet(applicationName: String): IconSet? {
return null
Expand All @@ -35,6 +39,8 @@ interface Theme {
val id: String
val name: String
val description: String
val onlyApplicationIcons: Boolean
val onlyLanguageIcons: Boolean

fun getIconSet(applicationName: String): IconSet?
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import com.fasterxml.jackson.databind.JsonNode

interface ThemeSourceMap : Map<String, ThemeSource> {
fun createThemeMap(themes: Map<String, Theme>, default: Theme): ThemeMap
fun createTheme(id: String, name: String, description: String): Theme
fun createTheme(id: String, name: String, description: String, onlyApplicationIcons: Boolean, onlyLanguageIcons: Boolean): Theme

fun toThemeMap(): ThemeMap {
val themes = stream()
Expand All @@ -39,7 +39,9 @@ interface ThemeSourceMap : Map<String, ThemeSource> {
fun ThemeSource.asTheme(): Theme {
val name: String = node["name"]?.textValue()!!
val description: String = node["description"]?.textValue()!!
val onlyApplicationIcons = node["onlyApplicationIcons"]?.booleanValue() ?: false
val onlyLanguageIcons = node["onlyLanguageIcons"]?.booleanValue() ?: false

return createTheme(id, name, description)
return createTheme(id, name, description, onlyApplicationIcons, onlyLanguageIcons)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ abstract class AbstractTheme(
override val id: String,
override val name: String,
override val description: String,
override val onlyApplicationIcons: Boolean,
override val onlyLanguageIcons: Boolean
) : Theme {
override fun toString(): String {
return "AbstractTheme(id='$id', name='$name', description='$description')"
return "AbstractTheme(id='$id', name='$name', description='$description', onlyApplicationIcons=$onlyApplicationIcons, onlyLanguageIcons=$onlyLanguageIcons)"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import org.apache.commons.io.FilenameUtils
import java.util.concurrent.ConcurrentHashMap
import kotlin.collections.set

class ClasspathTheme(private val source: ClasspathSource, id: String, name: String, description: String) :
AbstractTheme(id, name, description) {
class ClasspathTheme(private val source: ClasspathSource, id: String, name: String, description: String, onlyApplicationIcons: Boolean, onlyLanguageIcons: Boolean) :
AbstractTheme(id, name, description, onlyApplicationIcons, onlyLanguageIcons) {
private val sets = ConcurrentHashMap<String, ClasspathIconSet>()

override fun getIconSet(applicationName: String): IconSet {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ import dev.azn9.plugins.discord.icons.source.abstract.AbstractThemeSourceMap

class ClasspathThemeSourceMap(private val source: ClasspathSource, map: Map<String, ThemeSource>) : AbstractThemeSourceMap(map) {
override fun createThemeMap(themes: Map<String, Theme>, default: Theme) = ClasspathThemeMap(themes, default)
override fun createTheme(id: String, name: String, description: String) =
ClasspathTheme(source, id, name, description)
override fun createTheme(id: String, name: String, description: String, onlyApplicationIcons: Boolean, onlyLanguageIcons: Boolean) =
ClasspathTheme(source, id, name, description, onlyApplicationIcons, onlyLanguageIcons)
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class IdleRenderer(context: RenderContext) : Renderer(context) {
)
}

this@presence.largeImage = icons?.let { icons -> RichPresence.Image(icons.getAsset("application"), "Idling") }
this@presence.largeImage = applicationIcons?.let { icons -> RichPresence.Image(icons.getAsset("application"), "Idling") }

this.partyId = Plugin.version?.toString()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,22 @@ import dev.azn9.plugins.discord.settings.options.types.SimpleValue
import dev.azn9.plugins.discord.settings.settings

class RenderContext(val source: Source, val data: Data, val mode: Renderer.Mode) {
val icons: IconSet? by lazy {
var themeValue = projectData?.projectSettings?.theme ?: settings.theme

val applicationIcons: IconSet? by lazy {
var themeValue = projectData?.projectSettings?.applicationTheme ?: settings.applicationTheme
if (themeValue.getValue() == "default") {
themeValue = settings.applicationTheme
}

source.getThemesOrNull()
?.get(themeValue.getValue())
?.getIconSet(settings.applicationType.getValue().applicationName)
}

val languageIcons: IconSet? by lazy {
var themeValue = projectData?.projectSettings?.iconsTheme ?: settings.iconsTheme
if (themeValue.getValue() == "default") {
themeValue = settings.theme
themeValue = settings.iconsTheme
}

source.getThemesOrNull()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,11 @@ abstract class Renderer(protected val context: RenderContext) {
DiscordPlugin.LOG.debug("Rendering presence, data=${context.data}, mode=${context.mode}")
DiscordPlugin.LOG.debug("Themes: ${context.source.getThemesOrNull()}")
DiscordPlugin.LOG.debug("languages: ${context.source.getLanguagesOrNull()}")
DiscordPlugin.LOG.debug("Icons: ${context.icons}")
DiscordPlugin.LOG.debug("Application Icons: ${context.applicationIcons}")
DiscordPlugin.LOG.debug("Language Icons: ${context.languageIcons}")
DiscordPlugin.LOG.debug("Data: ${context.data}")
DiscordPlugin.LOG.debug("Mode: ${context.mode}")

if (context.icons == null) {
DiscordPlugin.LOG.debug("RenderContext.icons=null")
}

return RichPresence(context.applicationData?.applicationId) presence@{
val customTemplateContext by lazy { context.asCustomTemplateContext() }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ interface ApplicationSettings : PersistentStateComponent<Element>, OptionHolder
val fileTime: TimeValue

val applicationType: ApplicationTypeValue
val theme: ThemeValue

val applicationTheme: ThemeValue
val iconsTheme: ThemeValue

val applicationLastUpdateNotification: StringValue
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ interface ProjectSettings : PersistentStateComponent<Element>, OptionHolder {

val description: StringValue

val theme: ThemeValue?
val applicationTheme: ThemeValue?
val iconsTheme: ThemeValue?

val button1Title: StringValue
val button1Url: StringValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
package dev.azn9.plugins.discord.settings.gui.themes

import dev.azn9.plugins.discord.icons.source.Theme
import dev.azn9.plugins.discord.icons.source.ThemeMap
import com.intellij.openapi.ui.DialogWrapper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand All @@ -32,7 +31,7 @@ import javax.swing.JPanel
import javax.swing.plaf.basic.BasicComboBoxRenderer
import kotlin.coroutines.CoroutineContext

class ThemeDialog(private val themes: ThemeMap, private val initialValue: String?, private val showDefault: Boolean = false) : DialogWrapper(null, true, IdeModalityType.IDE), CoroutineScope {
class ThemeDialog(private val themes: Map<String, Theme>, private val initialValue: String?, private val showDefault: Boolean = false) : DialogWrapper(null, true, IdeModalityType.IDE), CoroutineScope {
private val parentJob: Job = SupervisorJob()

override val coroutineContext: CoroutineContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@ class ApplicationSettingsImpl : ApplicationSettings, PersistentStateOptionHolder
/* ========== General Settings ========== */

override val applicationType by selection("Application name", ApplicationType.IDE_EDITION)
override val theme by themeChooser("Theme")

override val applicationTheme by themeChooser("Theme for the application icon", null, false, ThemeType.APPLICATION_ONLY)
override val iconsTheme by themeChooser("Theme for the language icons", null, false, ThemeType.LANGUAGE_ONLY)

/* ---------- Hidden Settings ---------- */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import dev.azn9.plugins.discord.settings.values.ThemeType

@State(name = "DiscordProjectSettings", storages = [Storage("discord.xml")])
class ProjectSettingsImpl(override val project: Project) : ProjectSettings, PersistentStateOptionHolderImpl() {
Expand All @@ -40,7 +41,8 @@ class ProjectSettingsImpl(override val project: Project) : ProjectSettings, Pers

override val description by text("Project description", "")

override val theme by themeChooser("Project theme", "The theme to use for this project", true)
override val applicationTheme by themeChooser("Theme for the application icon", null, true, ThemeType.APPLICATION_ONLY)
override val iconsTheme by themeChooser("Theme for the language icons", null, true, ThemeType.LANGUAGE_ONLY)

override val button1Title by text("Button 1 title", "")
override val button1Url by text("Button 1 url", "")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import dev.azn9.plugins.discord.utils.label
import dev.azn9.plugins.discord.utils.throwing
import com.intellij.openapi.util.JDOMExternalizerUtil
import dev.azn9.plugins.discord.icons.source.Theme
import kotlinx.coroutines.future.asCompletableFuture
import dev.azn9.plugins.discord.settings.values.ThemeType
import org.jdom.Element
import java.awt.GridBagConstraints
import java.awt.GridBagLayout
Expand All @@ -38,10 +38,10 @@ import javax.swing.JComponent
import javax.swing.JPanel
import kotlin.reflect.KProperty

fun OptionCreator<in ThemeValue>.themeChooser(text: String, description: String? = null, showDefault: Boolean = false) =
OptionProviderImpl(this, ThemeOption(text, description, showDefault))
fun OptionCreator<in ThemeValue>.themeChooser(text: String, description: String? = null, showDefault: Boolean = false, themeType: ThemeType) =
OptionProviderImpl(this, ThemeOption(text, description, showDefault, themeType))

class ThemeOption(text: String, val description: String?, val showDefault: Boolean) : Option<ThemeValue>(text), ThemeValue.Provider {
class ThemeOption(text: String, val description: String?, val showDefault: Boolean, themeType: ThemeType) : Option<ThemeValue>(text), ThemeValue.Provider {
private val source: Source = sourceService.source

private val listeners = mutableListOf<(ThemeValue) -> Unit>()
Expand All @@ -63,9 +63,17 @@ class ThemeOption(text: String, val description: String?, val showDefault: Boole

addActionListener {
val themes = this@ThemeOption.source.getThemesOrNull()
var themeMap = themes as Map<String, Theme>?

if (themes != null) {
val dialog = ThemeDialog(themes, componentValue, showDefault)
if (themeType == ThemeType.APPLICATION_ONLY) {
themeMap = themeMap?.filter { !it.value.onlyLanguageIcons }
}
if (themeType == ThemeType.LANGUAGE_ONLY) {
themeMap = themes?.filter { !it.value.onlyApplicationIcons }
}

if (themeMap != null) {
val dialog = ThemeDialog(themeMap, componentValue, showDefault)
val result = dialog.showAndGet()

if (result) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ typealias IconValue = SimpleValue<PresenceIcon>

enum class PresenceIcon(override val text: String, override val description: String? = null) : RenderedValue<PresenceIcon.Result>, UiValueType {
APPLICATION("Application") {
override fun RenderContext.getResult() = icons?.getAsset("application").toResult()
override fun RenderContext.getResult() = applicationIcons?.getAsset("application").toResult()
},
FILE("File") {
override fun RenderContext.getResult(): Result {
return icons?.let { icons -> language?.findIcon(icons) }?.asset.toResult()
return languageIcons?.let { icons -> language?.findIcon(icons) }?.asset.toResult()
}
},
NONE("None") {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2017-2020 Aljoscha Grebe
* Copyright 2023-2024 Axel JOLY (Azn9) <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package dev.azn9.plugins.discord.settings.values

enum class ThemeType {

APPLICATION_ONLY,
LANGUAGE_ONLY;

}

0 comments on commit df79530

Please sign in to comment.