All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scalismo.ui.view.util.ScalableUI.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2016  University of Basel, Graphics and Vision Research Group
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */

package scalismo.ui.view.util

import java.awt.{Dimension, Font, GraphicsEnvironment, Transparency}

import javax.swing.plaf.FontUIResource
import javax.swing.{Icon, ImageIcon, UIDefaults, UIManager}
import scalismo.ui.resources.icons.ScalableIcon
import scalismo.ui.settings.GlobalSettings

import scala.collection.mutable

object ScalableUI {

  class ScalableInt(val self: Int) extends AnyVal {
    def scaled: Int = scale(self)
  }

  object implicits {

    import scala.language.implicitConversions

    implicit def scalableInt(int: Int): ScalableInt = new ScalableInt(int)
  }

  private var _factor: Float = GlobalSettings.get[Float](GlobalSettings.Keys.HighDpiScale).getOrElse(1)

  def scaleFactor: Float = _factor

  def scaleFactor_=(newValue: Float): Unit = {
    GlobalSettings.set[Float](GlobalSettings.Keys.HighDpiScale, newValue)
    _factor = newValue
  }

  /**
   * Scale (multiply) a given number by a factor.
   *
   * The first argument is usually a pixel count.
   * The second argument is a multiplier, and is usually left unspecified, so that
   * the default value ([[ScalableUI.scaleFactor]] is used.
   *
   * @param loDpiPixels unscaled number (usually in pixels)
   * @param factor      scale factor. If not specified, [[ScalableUI.scaleFactor]] is used.
   * @return the argument multiplied by the given factor, rounded to the next integer.
   */
  def scale(loDpiPixels: Int, factor: Float = scaleFactor): Int = Math.round(loDpiPixels * factor)

  def scaleDimension(loDpiDimension: Dimension, factor: Float = scaleFactor): Dimension = {
    new Dimension(scale(loDpiDimension.width, factor), scale(loDpiDimension.height, factor))
  }

  /**
   * Scales an icon by the given factor.
   * The resulting icon's size will be the size of the icon, multiplied by the given factor.
   *
   * @param sourceIcon the icon to scale
   * @param factor     the factor to change the icon's size. If unspecified, the currently set default scale factor is applied
   * @return the scaled icon
   */
  def scaleIcon(sourceIcon: Icon, factor: Float = scaleFactor): Icon = {
    resizeIcon(sourceIcon, scale(sourceIcon.getIconWidth), scale(sourceIcon.getIconHeight))
  }

  def standardSizedIcon(icon: Icon): Icon = {
    icon match {
      case scalable: ScalableIcon => scalable.standardSized()
      case i =>
        val standardSize = ScalableUI.scale(Constants.StandardUnscaledIconSize)
        resizeIcon(i, standardSize, standardSize)
    }
  }

  def resizeIcon(sourceIcon: Icon, width: Int, height: Int): Icon = {
    if (sourceIcon.getIconWidth == width && sourceIcon.getIconHeight == height) {
      sourceIcon
    } else {
      sourceIcon match {
        case icon: ScalableIcon => icon.resize(width, height)
        case icon: ImageIcon =>
          new ImageIcon(icon.getImage.getScaledInstance(width, height, java.awt.Image.SCALE_SMOOTH))
        case icon: Icon =>
          val (w, h) = (icon.getIconWidth, icon.getIconHeight)
          val ge = GraphicsEnvironment.getLocalGraphicsEnvironment
          val gd = ge.getDefaultScreenDevice
          val gc = gd.getDefaultConfiguration
          val image = gc.createCompatibleImage(w, h, Transparency.TRANSLUCENT)
          val g = image.createGraphics()
          icon.paintIcon(null, g, 0, 0)
          g.dispose()
          new ImageIcon(image.getScaledInstance(width, height, java.awt.Image.SCALE_SMOOTH))
      }
    }
  }

  def updateLookAndFeelDefaults(): Unit = {
    updateDefaults(UIManager.getDefaults)
    updateDefaults(UIManager.getLookAndFeelDefaults)
  }

  private def updateDefaults(defaults: UIDefaults): Unit = {
    val keys = defaults.keys()
    val replacements = new mutable.LinkedHashMap[String, AnyRef]

    while (keys.hasMoreElements) {
      val key = keys.nextElement()
      key match {
        case stringKey: String if stringKey.toLowerCase.endsWith("font") =>
          val value = defaults.get(key)
          value match {
            case fr: FontUIResource =>
              val size = scale(fr.getSize)
              replacements(stringKey) = new FontUIResource(fr.getName, fr.getStyle, size)
            case f: Font =>
              val size = scale(f.getSize)
              replacements(stringKey) = new Font(f.getName, f.getStyle, size)
            case _ => // do nothing
          }
        case _ => // nothing
      }
    }

    replacements.foreach {
      case (key, value) =>
        defaults.put(key, value)
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy