UI DSL and LaF tests — run on Retina monitor
@@ -0,0 +1,5 @@
|
||||
<root>
|
||||
<item name='javax.swing.JComponent void paint(java.awt.Graphics) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
@@ -1,18 +1,4 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.openapi.ui.impl;
|
||||
|
||||
import com.intellij.util.IconUtil;
|
||||
@@ -101,7 +87,7 @@ public class ShadowPainter extends ScaleContextSupport<ScaleContext> {
|
||||
}
|
||||
|
||||
public void paintShadow(Component c, Graphics2D g, int x, int y, int width, int height) {
|
||||
ScaleContext ctx = ScaleContext.create(c);
|
||||
ScaleContext ctx = ScaleContext.create(c, g);
|
||||
if (updateScaleContext(ctx)) {
|
||||
updateIcons(ctx);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 357" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
@@ -109,12 +110,12 @@
|
||||
<rect x="2" width="458" height="24" y="2" clip-path="url(#clipPath3)" stroke="none"/>
|
||||
</g>
|
||||
<g fill="rgb(187,187,187)" font-size="13px" font-family="'.SF NS Text'" transform="translate(8,52)" stroke="rgb(187,187,187)">
|
||||
<text x="9" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text x="20" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text x="31" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text x="42" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text x="53" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text x="64" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text x="9" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
<text x="15" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
<text x="21" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
<text x="27" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
<text x="33" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
<text x="39" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
</g>
|
||||
<g fill="rgb(100,100,100)" text-rendering="optimizeLegibility" font-size="13px" font-family="'.SF NS Text'" transform="translate(9,53)" stroke="rgb(100,100,100)">
|
||||
<path d="M2 2 L460 2 L460 26 L2 26 L2 2 ZM3 3 L459 3 L459 25 L3 25 L3 3 Z" fill-rule="evenodd" clip-path="url(#clipPath3)" stroke="none"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -1,3 +1,4 @@
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 343" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
@@ -86,12 +87,12 @@
|
||||
<g fill="rgb(236,236,236)" font-size="13px" font-family="'.SF NS Text'" transform="translate(8,46)" stroke="rgb(236,236,236)">
|
||||
<rect x="0" width="464" height="30" y="0" clip-path="url(#clipPath6)" stroke="none"/>
|
||||
<rect x="3" y="3" clip-path="url(#clipPath6)" fill="white" width="458" height="24" stroke="none"/>
|
||||
<text fill="rgb(29,29,29)" x="8" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text fill="rgb(29,29,29)" x="19" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text fill="rgb(29,29,29)" x="30" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text fill="rgb(29,29,29)" x="41" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text fill="rgb(29,29,29)" x="52" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text fill="rgb(29,29,29)" x="63" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">●</text>
|
||||
<text fill="rgb(29,29,29)" x="8" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
<text fill="rgb(29,29,29)" x="14" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
<text fill="rgb(29,29,29)" x="20" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
<text fill="rgb(29,29,29)" x="26" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
<text fill="rgb(29,29,29)" x="32" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
<text fill="rgb(29,29,29)" x="38" xml:space="preserve" y="20" clip-path="url(#clipPath7)" stroke="none">•</text>
|
||||
</g>
|
||||
<g fill="rgb(188,188,188)" text-rendering="optimizeLegibility" font-size="13px" font-family="'.SF NS Text'" transform="translate(9,47)" stroke="rgb(188,188,188)">
|
||||
<path d="M3 3 L459 3 L459 25 L3 25 L3 3 ZM4 4 L458 4 L458 24 L4 24 L4 4 Z" fill-rule="evenodd" clip-path="url(#clipPath8)" stroke="none"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.9 KiB |
@@ -1,3 +1,4 @@
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 320" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.6 KiB |
@@ -1,3 +1,4 @@
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 320" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 4.0 KiB |
@@ -1,6 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square"
|
||||
stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 320"
|
||||
font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 320" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
<g>
|
||||
|
||||
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.3 KiB |
@@ -1,3 +1,4 @@
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 320" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.5 KiB |
@@ -1,3 +1,4 @@
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 646 371" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
@@ -1,3 +1,4 @@
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 320" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
@@ -1,3 +1,4 @@
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 320" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
@@ -1,6 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square"
|
||||
stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 320"
|
||||
font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 320" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
<g>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.1 KiB |
@@ -1,3 +1,4 @@
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 480 320" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
@@ -1,3 +1,4 @@
|
||||
<!--suppress XmlUnusedNamespaceDeclaration -->
|
||||
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" fill-opacity="1" color-rendering="auto" color-interpolation="auto" text-rendering="auto" stroke="black" stroke-linecap="square" stroke-miterlimit="10" shape-rendering="auto" stroke-opacity="1" fill="black" stroke-dasharray="none" font-weight="normal" stroke-width="1" viewBox="0 0 649 341" font-family="'Dialog'" font-style="normal" stroke-linejoin="miter" font-size="12px" stroke-dashoffset="0" image-rendering="auto">
|
||||
<!--Generated by the Batik Graphics2D SVG Generator-->
|
||||
<defs id="genericDefs"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
@@ -3,8 +3,10 @@ package com.intellij.ui
|
||||
|
||||
import com.intellij.openapi.application.ex.PathManagerEx
|
||||
import com.intellij.openapi.util.IconLoader
|
||||
import com.intellij.openapi.util.SystemInfoRt
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.util.ui.IconCache
|
||||
import org.apache.batik.anim.dom.SVGDOMImplementation
|
||||
import org.apache.batik.dom.GenericDOMImplementation
|
||||
import org.apache.batik.svggen.ImageHandlerBase64Encoder
|
||||
import org.apache.batik.svggen.SVGGeneratorContext
|
||||
@@ -13,7 +15,9 @@ import org.apache.batik.svggen.SVGSyntax
|
||||
import org.apache.xmlgraphics.java2d.GraphicsConfigurationWithTransparency
|
||||
import org.w3c.dom.Element
|
||||
import java.awt.Component
|
||||
import java.awt.GraphicsConfiguration
|
||||
import java.awt.Image
|
||||
import java.awt.Rectangle
|
||||
import java.io.StringWriter
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
@@ -23,13 +27,15 @@ import javax.xml.transform.dom.DOMSource
|
||||
import javax.xml.transform.stream.StreamResult
|
||||
|
||||
// jFreeSvg produces not so compact and readable SVG as batik
|
||||
internal class SvgRenderer(private val svgFileDir: Path) {
|
||||
internal class SvgRenderer(val svgFileDir: Path) {
|
||||
private val xmlTransformer = TransformerFactory.newInstance().newTransformer()
|
||||
|
||||
// todo check on Retina - does it works or not (is Retina disabled or not)
|
||||
private val deviceConfiguration = GraphicsConfigurationWithTransparency()
|
||||
val deviceConfiguration = object : GraphicsConfigurationWithTransparency() {
|
||||
override fun getBounds() = Rectangle(0, 0, 1000, 1000)
|
||||
}
|
||||
|
||||
private val xmlFactory = GenericDOMImplementation.getDOMImplementation().createDocument("http://www.w3.org/2000/svg", "svg", null)
|
||||
private val xmlFactory = GenericDOMImplementation.getDOMImplementation().createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg", null)
|
||||
private val context = SVGGeneratorContext.createDefault(xmlFactory)
|
||||
|
||||
init {
|
||||
@@ -91,27 +97,41 @@ internal class SvgRenderer(private val svgFileDir: Path) {
|
||||
val writer = StringWriter()
|
||||
writer.use {
|
||||
val root = svgGenerator.root
|
||||
|
||||
root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns", SVGSyntax.SVG_NAMESPACE_URI)
|
||||
root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink")
|
||||
|
||||
val bounds = component.bounds
|
||||
root.setAttributeNS(null, "viewBox", "${bounds.x} ${bounds.y} ${bounds.width} ${bounds.height}")
|
||||
root.setAttributeNS(null, "viewBox", "0 0 ${component.width} ${component.height}")
|
||||
|
||||
xmlTransformer.transform(DOMSource(root), StreamResult(writer))
|
||||
}
|
||||
return writer
|
||||
// xlink is not used in some files and optimize imports on commit can modify file, so, as simple solution, disable inspection
|
||||
val result = "<!--suppress XmlUnusedNamespaceDeclaration -->\n" + writer
|
||||
.toString()
|
||||
// Remember
|
||||
// no idea why transformer/batik doesn't escape it correctly
|
||||
.replace(">", ">&")
|
||||
return if (SystemInfoRt.isWindows) FileUtilRt.toSystemIndependentName(result) else result
|
||||
}
|
||||
|
||||
fun render(component: Component): String {
|
||||
val svgGenerator = object : SVGGraphics2D(context, false) {
|
||||
override fun getDeviceConfiguration() = this@SvgRenderer.deviceConfiguration
|
||||
}
|
||||
val svgGenerator = SvgGraphics2dWithDeviceConfiguration(context, deviceConfiguration)
|
||||
component.paint(svgGenerator)
|
||||
return svgGraphicsToString(svgGenerator, component)
|
||||
}
|
||||
}
|
||||
|
||||
private class SvgGraphics2dWithDeviceConfiguration : SVGGraphics2D {
|
||||
private val _deviceConfiguration: GraphicsConfiguration
|
||||
|
||||
constructor(context: SVGGeneratorContext, _deviceConfiguration: GraphicsConfiguration) : super(context, false) {
|
||||
this._deviceConfiguration = _deviceConfiguration
|
||||
}
|
||||
|
||||
private constructor(g: SvgGraphics2dWithDeviceConfiguration): super(g) {
|
||||
this._deviceConfiguration = g._deviceConfiguration
|
||||
}
|
||||
|
||||
override fun getDeviceConfiguration() = _deviceConfiguration
|
||||
|
||||
override fun create() = SvgGraphics2dWithDeviceConfiguration(this)
|
||||
}
|
||||
@@ -6,15 +6,13 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import com.intellij.ui.JBIntSpinner
|
||||
import com.intellij.ui.changeLafIfNeed
|
||||
import com.intellij.ui.*
|
||||
import com.intellij.ui.components.CheckBox
|
||||
import com.intellij.ui.components.textFieldWithHistoryWithBrowseButton
|
||||
import com.intellij.ui.layout.*
|
||||
import com.intellij.ui.snapshotFileName
|
||||
import com.intellij.ui.validatePanel
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.junit.Before
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TestName
|
||||
@@ -33,6 +31,10 @@ class LafTest {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun lafNames() = listOf("Darcula", "IntelliJ")
|
||||
|
||||
@JvmField
|
||||
@ClassRule
|
||||
val requireHeadlessMode = RequireHeadlessMode()
|
||||
}
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
@@ -5,15 +5,13 @@ import com.intellij.openapi.application.invokeAndWaitIfNeed
|
||||
import com.intellij.openapi.util.SystemInfoRt
|
||||
import com.intellij.testFramework.PlatformTestUtil
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import com.intellij.ui.RequireHeadlessMode
|
||||
import com.intellij.ui.changeLafIfNeed
|
||||
import com.intellij.ui.snapshotFileName
|
||||
import com.intellij.ui.validatePanel
|
||||
import net.miginfocom.layout.LayoutUtil
|
||||
import org.junit.After
|
||||
import org.junit.*
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TestName
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
@@ -29,6 +27,10 @@ class UiDslTest {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun lafNames() = listOf("Darcula", "IntelliJ")
|
||||
|
||||
@JvmField
|
||||
@ClassRule
|
||||
val requireHeadlessMode = RequireHeadlessMode()
|
||||
}
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
@@ -6,20 +6,25 @@ import com.intellij.ide.ui.laf.darcula.DarculaLaf
|
||||
import com.intellij.openapi.application.invokeAndWaitIfNeed
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import com.intellij.testFramework.assertions.Assertions.assertThat
|
||||
import com.intellij.ui.layout.*
|
||||
import com.intellij.util.io.exists
|
||||
import com.intellij.util.io.sanitizeFileName
|
||||
import com.intellij.util.io.write
|
||||
import com.intellij.util.ui.JBUI
|
||||
import com.intellij.util.ui.TestScaleHelper
|
||||
import com.intellij.util.ui.UIUtil
|
||||
import io.netty.util.internal.SystemPropertyUtil
|
||||
import net.miginfocom.swing.MigLayout
|
||||
import org.junit.Assume
|
||||
import org.junit.rules.ExternalResource
|
||||
import org.junit.rules.TestName
|
||||
import org.yaml.snakeyaml.DumperOptions
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import java.awt.Component
|
||||
import java.awt.Container
|
||||
import java.awt.GraphicsEnvironment
|
||||
import java.io.File
|
||||
import java.nio.file.Path
|
||||
import javax.swing.AbstractButton
|
||||
@@ -30,21 +35,32 @@ import javax.swing.plaf.metal.MetalLookAndFeel
|
||||
|
||||
private val isUpdateSnapshotsGlobal by lazy { SystemPropertyUtil.getBoolean("test.update.snapshots", false) }
|
||||
|
||||
//class RestoreLafRule : ExternalResource() {
|
||||
// var oldLafName: String? = null
|
||||
//
|
||||
// override fun before() {
|
||||
// oldLafName = UIManager.getLookAndFeel().name
|
||||
// }
|
||||
//
|
||||
// override fun after() {
|
||||
// val oldLafName = oldLafName
|
||||
// if (oldLafName != null && oldLafName != UIManager.getLookAndFeel().name) {
|
||||
// assertThat(oldLafName).isEqualTo("IntelliJ")
|
||||
// UIManager.setLookAndFeel(IntelliJLaf())
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
class NoScaleRule : ExternalResource() {
|
||||
private var scaleHelper = TestScaleHelper()
|
||||
|
||||
override fun before() {
|
||||
scaleHelper.setState()
|
||||
}
|
||||
|
||||
override fun after() {
|
||||
scaleHelper.restoreState()
|
||||
}
|
||||
}
|
||||
|
||||
class RequireHeadlessMode : ExternalResource() {
|
||||
override fun before() {
|
||||
// there is some difference if run as not headless (on retina monitor, at least), not yet clear why, so, just require to run in headless mode
|
||||
if (UsefulTestCase.IS_UNDER_TEAMCITY) {
|
||||
Assume.assumeTrue(GraphicsEnvironment.isHeadless())
|
||||
}
|
||||
else {
|
||||
System.setProperty("java.awt.headless", "true")
|
||||
if (!GraphicsEnvironment.isHeadless()) {
|
||||
throw RuntimeException("must be headless")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun changeLafIfNeed(lafName: String) {
|
||||
if (UIManager.getLookAndFeel().name == lafName) {
|
||||
@@ -119,8 +135,8 @@ private fun compareSnapshot(snapshotFile: Path, newData: String, isUpdateSnapsho
|
||||
}
|
||||
}
|
||||
|
||||
fun validateUsingImage(component: Component, snapshotDir: Path, snapshotName: String, isUpdateSnapshots: Boolean = isUpdateSnapshotsGlobal) {
|
||||
compareSnapshot(snapshotDir.resolve("$snapshotName.svg"), SvgRenderer(snapshotDir).render(component), isUpdateSnapshots)
|
||||
internal fun validateUsingImage(component: Component, svgRenderer: SvgRenderer, snapshotName: String, isUpdateSnapshots: Boolean = isUpdateSnapshotsGlobal) {
|
||||
compareSnapshot(svgRenderer.svgFileDir.resolve("$snapshotName.svg"), svgRenderer.render(component), isUpdateSnapshots)
|
||||
}
|
||||
|
||||
val TestName.snapshotFileName: String
|
||||
@@ -152,11 +168,28 @@ internal fun getComponentKey(c: Component, index: Int): String {
|
||||
}
|
||||
}
|
||||
|
||||
fun validatePanel(panel: JPanel, testDataRoot: Path, snapshotName: String, lafName: String) {
|
||||
val preferredSize = panel.preferredSize
|
||||
panel.setBounds(0, 0, Math.max(preferredSize.width, JBUI.scale(480)), Math.max(preferredSize.height, 320))
|
||||
panel.doLayout()
|
||||
fun validatePanel(userPanel: JPanel, testDataRoot: Path, snapshotName: String, lafName: String) {
|
||||
val svgRenderer = SvgRenderer(testDataRoot.resolve(getSnapshotRelativePath(lafName, isForImage = true)))
|
||||
|
||||
validateUsingImage(panel, testDataRoot.resolve(getSnapshotRelativePath(lafName, isForImage = true)), snapshotName)
|
||||
validateBounds(panel, testDataRoot.resolve(getSnapshotRelativePath(lafName, isForImage = false)), snapshotName)
|
||||
// to run tests on retina monitor (@2x images must be not used and so on)
|
||||
// Graphics2D.getDeviceConfiguration is not enough because our IconLoader.paintIcon uses component.getGraphicsConfiguration() instead of g.getDeviceConfiguration()
|
||||
// val panel = object : JComponent() {
|
||||
// override fun getGraphicsConfiguration() = svgRenderer.deviceConfiguration
|
||||
//
|
||||
// override fun paint(g: Graphics) {
|
||||
// // paint userPanel directly to ensure that SVG doesn't contain this wrapper
|
||||
// userPanel.paint(g)
|
||||
// }
|
||||
// }
|
||||
|
||||
// panel.add(userPanel)
|
||||
|
||||
// panel.addNotify()
|
||||
val preferredSize = userPanel.preferredSize
|
||||
// panel.setBounds(0, 0, Math.max(preferredSize.width, JBUI.scale(480)), Math.max(preferredSize.height, 320))
|
||||
userPanel.setBounds(0, 0, Math.max(preferredSize.width, JBUI.scale(480)), Math.max(preferredSize.height, 320))
|
||||
userPanel.doLayout()
|
||||
|
||||
validateUsingImage(userPanel, svgRenderer, snapshotName)
|
||||
validateBounds(userPanel, testDataRoot.resolve(getSnapshotRelativePath(lafName, isForImage = false)), snapshotName)
|
||||
}
|
||||
@@ -515,10 +515,7 @@ public final class IconLoader {
|
||||
|
||||
@Override
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
// Component is preferable to Graphics as a scale provider, as it lets the context stick
|
||||
// to the comp's actual scale via the update method.
|
||||
ScaleContext ctx = c != null ? ScaleContext.create(c) : ScaleContext.create((Graphics2D)g);
|
||||
getRealIcon(ctx).paintIcon(c, g, x, y);
|
||||
getRealIcon(ScaleContext.create(c, g)).paintIcon(c, g, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -628,7 +628,7 @@ public class JBUI {
|
||||
return SystemInfo.isMac ? smallFont() : label();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static final JBEmptyBorder SHARED_EMPTY_INSTANCE = new JBEmptyBorder(0);
|
||||
|
||||
@SuppressWarnings("UseDPIAwareBorders")
|
||||
@@ -964,10 +964,24 @@ public class JBUI {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a context based on the component's (or graphics's) scale and sticks to it via the {@link #update()} method.
|
||||
*/
|
||||
public static ScaleContext create(@Nullable Component component, @Nullable Graphics graphics) {
|
||||
// Component is preferable to Graphics as a scale provider, as it lets the context stick
|
||||
// to the comp's actual scale via the update method.
|
||||
if (component == null || component.getGraphicsConfiguration() == null) {
|
||||
return create((Graphics2D)graphics);
|
||||
}
|
||||
else {
|
||||
return create(component);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a context based on the gc's system scale
|
||||
*/
|
||||
public static ScaleContext create(GraphicsConfiguration gc) {
|
||||
public static ScaleContext create(@Nullable GraphicsConfiguration gc) {
|
||||
return new ScaleContext(SYS_SCALE.of(sysScale(gc)));
|
||||
}
|
||||
|
||||
|
||||