| Author | DaveJarvis <email> |
|---|---|
| Date | 2020-07-16 19:54:26 GMT-0700 |
| Commit | 13d830302cb15bb23066307e47e41de43cee7ee5 |
| Parent | 16a6742 |
| <component name="ChangeListManager"> | ||
| <list default="true" id="be1819c5-28d3-4984-9634-0b266734e13c" name="Default Changelist" comment=""> | ||
| - <change afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/AppImage.java" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/.idea/gradle.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/gradle.xml" afterDir="false" /> | ||
| + <change afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/listeners/Modifier.java" afterDir="false" /> | ||
| + <change afterPath="$PROJECT_DIR$/src/main/resources/images/mouse/1-3.svg" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/build.gradle" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/key/dn/alphanum.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/key/dn/short.svg" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/key/dn/modifier.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/key/dn/medium.svg" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/key/dn/shift.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/key/dn/long.svg" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/key/up/alphanum.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/key/up/short.svg" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/key/up/modifier.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/key/up/medium.svg" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/key/up/shift.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/key/up/long.svg" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/mouse/all.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/mouse/all.svg" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/mouse/chord.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/mouse/2.svg" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/mouse/left.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/mouse/1.svg" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/mouse/rest.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/mouse/0.svg" afterDir="false" /> | ||
| - <change beforePath="$PROJECT_DIR$/images/mouse/right.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/mouse/3.svg" afterDir="false" /> | ||
| + <change beforePath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/AppImage.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/AppImage.java" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/EventFrame.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/EventFrame.java" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/KmCaster.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/KmCaster.java" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/listeners/KeyboardListener.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/listeners/KeyboardListener.java" afterDir="false" /> | ||
| <change beforePath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/listeners/MouseListener.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/listeners/MouseListener.java" afterDir="false" /> | ||
| + <change beforePath="$PROJECT_DIR$/src/main/resources/images/mouse/0.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/mouse/0.svg" afterDir="false" /> | ||
| + <change beforePath="$PROJECT_DIR$/src/main/resources/images/mouse/1.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/mouse/1.svg" afterDir="false" /> | ||
| + <change beforePath="$PROJECT_DIR$/src/main/resources/images/mouse/2.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/mouse/2.svg" afterDir="false" /> | ||
| + <change beforePath="$PROJECT_DIR$/src/main/resources/images/mouse/3.svg" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/images/mouse/3.svg" afterDir="false" /> | ||
| + <change beforePath="$PROJECT_DIR$/src/main/resources/images/mouse/all.svg" beforeDir="false" /> | ||
| </list> | ||
| <option name="SHOW_DIALOG" value="false" /> | ||
| <system id="GRADLE"> | ||
| <state> | ||
| + <task path="$PROJECT_DIR$"> | ||
| + <activation /> | ||
| + </task> | ||
| <projects_view> | ||
| <tree_state> | ||
| <expand> | ||
| + <path> | ||
| + <item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" /> | ||
| + <item name="kmcaster" type="f1a62948:ProjectNode" /> | ||
| + </path> | ||
| <path> | ||
| <item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" /> | ||
| <item name="kmcaster" type="f1a62948:ProjectNode" /> | ||
| + <item name="Tasks" type="e4a08cd1:TasksNode" /> | ||
| </path> | ||
| </expand> | ||
| <option name="RECENT_TEMPLATES"> | ||
| <list> | ||
| - <option value="Class" /> | ||
| <option value="Enum" /> | ||
| + <option value="Class" /> | ||
| </list> | ||
| </option> | ||
| <component name="RecentsManager"> | ||
| <key name="MoveInnerDialog.RECENTS_KEY"> | ||
| - <recent name="com.whitemagicsoftware.kmcaster" /> | ||
| <recent name="com.whitemagicsoftware.kmcaster.listeners" /> | ||
| + <recent name="com.whitemagicsoftware.kmcaster" /> | ||
| </key> | ||
| <key name="CreateClassDialog.RecentsKey"> | ||
| </state> | ||
| <state x="813" y="683" width="218" height="250" key="#Notifications/0.28.2560.1529@0.28.2560.1529" timestamp="1594856235998" /> | ||
| - <state x="734" y="519" width="376" height="578" key="#com.intellij.ide.util.MemberChooser" timestamp="1594881096559"> | ||
| + <state x="314" y="436" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1594912481218"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state x="734" y="519" width="376" height="578" key="#com.intellij.ide.util.MemberChooser/0.28.2560.1529@0.28.2560.1529" timestamp="1594881096559" /> | ||
| - <state x="745" y="737" key="#com.intellij.refactoring.move.MoveHandler.SelectRefactoringDialog" timestamp="1594860488340"> | ||
| + <state x="314" y="436" key="#com.intellij.execution.impl.EditConfigurationsDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594912481218" /> | ||
| + <state x="734" y="519" width="376" height="578" key="#com.intellij.ide.util.MemberChooser" timestamp="1594883540197"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state x="745" y="737" key="#com.intellij.refactoring.move.MoveHandler.SelectRefactoringDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594860488340" /> | ||
| - <state x="707" y="657" width="431" height="302" key="#com.intellij.refactoring.move.moveInner.MoveInnerDialog" timestamp="1594860490819"> | ||
| + <state x="734" y="519" width="376" height="578" key="#com.intellij.ide.util.MemberChooser/0.28.2560.1529@0.28.2560.1529" timestamp="1594883540197" /> | ||
| + <state x="745" y="737" key="#com.intellij.refactoring.move.MoveHandler.SelectRefactoringDialog" timestamp="1594953388252"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state x="707" y="657" width="431" height="302" key="#com.intellij.refactoring.move.moveInner.MoveInnerDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594860490819" /> | ||
| + <state x="745" y="737" key="#com.intellij.refactoring.move.MoveHandler.SelectRefactoringDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594953388252" /> | ||
| + <state x="707" y="657" width="431" height="302" key="#com.intellij.refactoring.move.moveInner.MoveInnerDialog" timestamp="1594953392347"> | ||
| + <screen x="0" y="28" width="2560" height="1529" /> | ||
| + </state> | ||
| + <state x="707" y="657" width="431" height="302" key="#com.intellij.refactoring.move.moveInner.MoveInnerDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594953392347" /> | ||
| <state x="567" y="28" width="711" height="1526" key="#com.intellij.refactoring.rename.AutomaticRenamingDialog" timestamp="1594858565314"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| <state x="710" y="704" width="425" height="207" key="DetectedRootsChooserDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594872764235" /> | ||
| - <state width="1479" height="406" key="GridCell.Tab.0.bottom" timestamp="1594881867827"> | ||
| + <state width="1479" height="330" key="GridCell.Tab.0.bottom" timestamp="1594954347951"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state width="1479" height="406" key="GridCell.Tab.0.bottom/0.28.2560.1529@0.28.2560.1529" timestamp="1594881867827" /> | ||
| - <state width="1479" height="406" key="GridCell.Tab.0.center" timestamp="1594881867826"> | ||
| + <state width="1479" height="330" key="GridCell.Tab.0.bottom/0.28.2560.1529@0.28.2560.1529" timestamp="1594954347951" /> | ||
| + <state width="1479" height="330" key="GridCell.Tab.0.center" timestamp="1594954347950"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state width="1479" height="406" key="GridCell.Tab.0.center/0.28.2560.1529@0.28.2560.1529" timestamp="1594881867826" /> | ||
| - <state width="1479" height="406" key="GridCell.Tab.0.left" timestamp="1594881867826"> | ||
| + <state width="1479" height="330" key="GridCell.Tab.0.center/0.28.2560.1529@0.28.2560.1529" timestamp="1594954347950" /> | ||
| + <state width="1479" height="330" key="GridCell.Tab.0.left" timestamp="1594954347950"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state width="1479" height="406" key="GridCell.Tab.0.left/0.28.2560.1529@0.28.2560.1529" timestamp="1594881867826" /> | ||
| - <state width="1479" height="406" key="GridCell.Tab.0.right" timestamp="1594881867827"> | ||
| + <state width="1479" height="330" key="GridCell.Tab.0.left/0.28.2560.1529@0.28.2560.1529" timestamp="1594954347950" /> | ||
| + <state width="1479" height="330" key="GridCell.Tab.0.right" timestamp="1594954347951"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state width="1479" height="406" key="GridCell.Tab.0.right/0.28.2560.1529@0.28.2560.1529" timestamp="1594881867827" /> | ||
| - <state width="1479" height="406" key="GridCell.Tab.1.bottom" timestamp="1594881867827"> | ||
| + <state width="1479" height="330" key="GridCell.Tab.0.right/0.28.2560.1529@0.28.2560.1529" timestamp="1594954347951" /> | ||
| + <state width="1479" height="406" key="GridCell.Tab.1.bottom" timestamp="1594948352434"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state width="1479" height="406" key="GridCell.Tab.1.bottom/0.28.2560.1529@0.28.2560.1529" timestamp="1594881867827" /> | ||
| - <state width="1479" height="406" key="GridCell.Tab.1.center" timestamp="1594881867827"> | ||
| + <state width="1479" height="406" key="GridCell.Tab.1.bottom/0.28.2560.1529@0.28.2560.1529" timestamp="1594948352434" /> | ||
| + <state width="1479" height="406" key="GridCell.Tab.1.center" timestamp="1594948352433"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state width="1479" height="406" key="GridCell.Tab.1.center/0.28.2560.1529@0.28.2560.1529" timestamp="1594881867827" /> | ||
| - <state width="1479" height="406" key="GridCell.Tab.1.left" timestamp="1594881867827"> | ||
| + <state width="1479" height="406" key="GridCell.Tab.1.center/0.28.2560.1529@0.28.2560.1529" timestamp="1594948352433" /> | ||
| + <state width="1479" height="406" key="GridCell.Tab.1.left" timestamp="1594948352432"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state width="1479" height="406" key="GridCell.Tab.1.left/0.28.2560.1529@0.28.2560.1529" timestamp="1594881867827" /> | ||
| - <state width="1479" height="406" key="GridCell.Tab.1.right" timestamp="1594881867827"> | ||
| + <state width="1479" height="406" key="GridCell.Tab.1.left/0.28.2560.1529@0.28.2560.1529" timestamp="1594948352432" /> | ||
| + <state width="1479" height="406" key="GridCell.Tab.1.right" timestamp="1594948352433"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| - <state width="1479" height="406" key="GridCell.Tab.1.right/0.28.2560.1529@0.28.2560.1529" timestamp="1594881867827" /> | ||
| + <state width="1479" height="406" key="GridCell.Tab.1.right/0.28.2560.1529@0.28.2560.1529" timestamp="1594948352433" /> | ||
| <state x="423" y="444" width="1026" height="842" key="SettingsEditor" timestamp="1594876039235"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| <state x="423" y="444" width="1026" height="842" key="SettingsEditor/0.28.2560.1529@0.28.2560.1529" timestamp="1594876039235" /> | ||
| + <state width="761" height="601" key="XDebugger.FullValuePopup" timestamp="1594940367498"> | ||
| + <screen x="0" y="28" width="2560" height="1529" /> | ||
| + </state> | ||
| + <state width="761" height="601" key="XDebugger.FullValuePopup/0.28.2560.1529@0.28.2560.1529" timestamp="1594940367498" /> | ||
| <state x="265" y="308" width="1323" height="1003" key="com.intellij.history.integration.ui.views.FileHistoryDialog" timestamp="1594881438574"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| <state x="265" y="308" width="1323" height="1003" key="com.intellij.history.integration.ui.views.FileHistoryDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594881438573" /> | ||
| + <state x="840" y="410" width="564" height="770" key="com.intellij.openapi.editor.actions.MultiplePasteAction$ClipboardContentChooser" timestamp="1594946566725"> | ||
| + <screen x="0" y="28" width="2560" height="1529" /> | ||
| + </state> | ||
| + <state x="840" y="410" width="564" height="770" key="com.intellij.openapi.editor.actions.MultiplePasteAction$ClipboardContentChooser/0.28.2560.1529@0.28.2560.1529" timestamp="1594946566725" /> | ||
| + <state x="833" y="545" width="586" height="502" key="find.popup" timestamp="1594949350582"> | ||
| + <screen x="0" y="28" width="2560" height="1529" /> | ||
| + </state> | ||
| + <state x="833" y="545" width="586" height="502" key="find.popup/0.28.2560.1529@0.28.2560.1529" timestamp="1594949350582" /> | ||
| <state x="589" y="382" key="run.anything.popup" timestamp="1594881668952"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| <state x="589" y="382" key="run.anything.popup/0.28.2560.1529@0.28.2560.1529" timestamp="1594881668952" /> | ||
| <state x="589" y="477" width="672" height="678" key="search.everywhere.popup" timestamp="1594880500645"> | ||
| <screen x="0" y="28" width="2560" height="1529" /> | ||
| </state> | ||
| <state x="589" y="477" width="672" height="678" key="search.everywhere.popup/0.28.2560.1529@0.28.2560.1529" timestamp="1594880500645" /> | ||
| - </component> | ||
| - <component name="XDebuggerManager"> | ||
| - <watches-manager> | ||
| - <configuration name="Remote"> | ||
| - <watch expression="mClassLoader.getResource("/images/key/dn/shift.svg")" language="JAVA" /> | ||
| - </configuration> | ||
| - </watches-manager> | ||
| </component> | ||
| </project> | ||
| +/* | ||
| + * Copyright 2020 White Magic Software, Ltd. | ||
| + * | ||
| + * All rights reserved. | ||
| + * | ||
| + * Redistribution and use in source and binary forms, with or without | ||
| + * modification, are permitted provided that the following conditions are met: | ||
| + * | ||
| + * o Redistributions of source code must retain the above copyright | ||
| + * notice, this list of conditions and the following disclaimer. | ||
| + * | ||
| + * o Redistributions in binary form must reproduce the above copyright | ||
| + * notice, this list of conditions and the following disclaimer in the | ||
| + * documentation and/or other materials provided with the distribution. | ||
| + * | ||
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| + */ | ||
| package com.whitemagicsoftware.kmcaster; | ||
| import com.kitfox.svg.SVGDiagram; | ||
| +import com.kitfox.svg.SVGException; | ||
| import com.kitfox.svg.SVGUniverse; | ||
| +import javax.swing.*; | ||
| +import java.awt.*; | ||
| +import java.awt.geom.AffineTransform; | ||
| +import java.awt.image.BufferedImage; | ||
| import java.net.URL; | ||
| +import java.util.Map; | ||
| +import static com.whitemagicsoftware.kmcaster.KmCaster.rethrow; | ||
| +import static java.awt.RenderingHints.*; | ||
| +import static java.awt.image.BufferedImage.TYPE_INT_ARGB; | ||
| import static java.lang.String.format; | ||
| /** | ||
| * Responsible for loading vector graphics representations of application | ||
| * images. The images provide an on-screen interface that indicate to the user | ||
| * what key or mouse events are being triggered. | ||
| */ | ||
| public class AppImage { | ||
| + public final static Map<Object, Object> RENDERING_HINTS = Map.of( | ||
| + KEY_ANTIALIASING, | ||
| + VALUE_ANTIALIAS_ON, | ||
| + KEY_ALPHA_INTERPOLATION, | ||
| + VALUE_ALPHA_INTERPOLATION_QUALITY, | ||
| + KEY_COLOR_RENDERING, | ||
| + VALUE_COLOR_RENDER_QUALITY, | ||
| + KEY_DITHERING, | ||
| + VALUE_DITHER_DISABLE, | ||
| + KEY_FRACTIONALMETRICS, | ||
| + VALUE_FRACTIONALMETRICS_ON, | ||
| + KEY_INTERPOLATION, | ||
| + VALUE_INTERPOLATION_BICUBIC, | ||
| + KEY_RENDERING, | ||
| + VALUE_RENDER_QUALITY, | ||
| + KEY_STROKE_CONTROL, | ||
| + VALUE_STROKE_PURE, | ||
| + KEY_TEXT_ANTIALIASING, | ||
| + VALUE_TEXT_ANTIALIAS_ON | ||
| + ); | ||
| + | ||
| private final static String IMAGES = "/images"; | ||
| private final static String IMAGES_KEY = IMAGES + "/key"; | ||
| private final static String IMAGES_MOUSE = IMAGES + "/mouse"; | ||
| - public static final AppImage MOUSE_LEFT = mouseImage( "0" ); | ||
| - public static final AppImage MOUSE_RIGHT = mouseImage( "1" ); | ||
| + public static final AppImage MOUSE_REST = mouseImage( "0" ); | ||
| + public static final AppImage MOUSE_LEFT = mouseImage( "1" ); | ||
| public static final AppImage MOUSE_CHORD = mouseImage( "2" ); | ||
| - public static final AppImage MOUSE_WHEEL = mouseImage( "3" ); | ||
| - public static final AppImage MOUSE_ALL = mouseImage( "all" ); | ||
| + public static final AppImage MOUSE_RIGHT = mouseImage( "3" ); | ||
| + public static final AppImage MOUSE_LR = mouseImage( "1-3" ); | ||
| public static final AppImage KEY_UP_SHIFT = keyUpImage( "long" ); | ||
| public static final AppImage KEY_UP_ALT = keyUpImage( "medium" ); | ||
| } | ||
| - public SVGDiagram getImage() { | ||
| + public JComponent toComponent( final Dimension dimension ) { | ||
| + final var image = toImage( dimension ); | ||
| + | ||
| + return new JComponent() { | ||
| + @Override | ||
| + public Dimension getPreferredSize() { | ||
| + return new Dimension( | ||
| + image.getWidth( null ), image.getHeight( null ) | ||
| + ); | ||
| + } | ||
| + | ||
| + @Override | ||
| + protected void paintComponent( final Graphics graphics ) { | ||
| + super.paintComponent( graphics ); | ||
| + | ||
| + final var g = (Graphics2D) graphics.create(); | ||
| + g.drawImage( image, 0, 0, this ); | ||
| + } | ||
| + }; | ||
| + } | ||
| + | ||
| + public Image toImage( final Dimension dstDim ) { | ||
| + final var diagram = loadDiagram(); | ||
| + final var diaWidth = diagram.getWidth(); | ||
| + final var diaHeight = diagram.getHeight(); | ||
| + final var srcDim = new Dimension( (int) diaWidth, (int) diaHeight ); | ||
| + | ||
| + final var scaledDim = scale( srcDim, dstDim ); | ||
| + final var w = (int) scaledDim.getWidth(); | ||
| + final var h = (int) scaledDim.getHeight(); | ||
| + | ||
| + final var image = new BufferedImage( w, h, TYPE_INT_ARGB ); | ||
| + | ||
| + try { | ||
| + final Graphics2D g = image.createGraphics(); | ||
| + g.setRenderingHints( RENDERING_HINTS ); | ||
| + | ||
| + final AffineTransform transform = g.getTransform(); | ||
| + transform.setToScale( w / diaWidth, h / diaHeight ); | ||
| + | ||
| + g.setTransform( transform ); | ||
| + diagram.render( g ); | ||
| + g.dispose(); | ||
| + } catch( final SVGException e ) { | ||
| + rethrow( e ); | ||
| + } | ||
| + | ||
| + return image; | ||
| + } | ||
| + | ||
| + private SVGDiagram loadDiagram() { | ||
| final var url = getResourceUrl(); | ||
| - return mRenderer.getDiagram( mRenderer.loadSVG( url ) ); | ||
| + return applySettings( mRenderer.getDiagram( mRenderer.loadSVG( url ) ) ); | ||
| + } | ||
| + | ||
| + private SVGDiagram applySettings( final SVGDiagram diagram ) { | ||
| + diagram.setIgnoringClipHeuristic( true ); | ||
| + return diagram; | ||
| } | ||
| private URL getResourceUrl() { | ||
| return AppImage.class.getResource( getPath() ); | ||
| } | ||
| private String getPath() { | ||
| return mPath; | ||
| + } | ||
| + | ||
| + private Dimension scale( final Dimension src, final Dimension dst ) { | ||
| + final var srcWidth = src.getWidth(); | ||
| + final var srcHeight = src.getHeight(); | ||
| + final var dstHeight = dst.getHeight(); | ||
| + | ||
| + var newWidth = srcWidth; | ||
| + var newHeight = srcHeight; | ||
| + | ||
| + if( newHeight < dstHeight ) { | ||
| + newHeight = dstHeight; | ||
| + newWidth = (newHeight * srcWidth) / srcHeight; | ||
| + } | ||
| + | ||
| + return new Dimension( (int) newWidth, (int) newHeight ); | ||
| } | ||
| } | ||
| +/* | ||
| + * Copyright 2020 White Magic Software, Ltd. | ||
| + * | ||
| + * All rights reserved. | ||
| + * | ||
| + * Redistribution and use in source and binary forms, with or without | ||
| + * modification, are permitted provided that the following conditions are met: | ||
| + * | ||
| + * o Redistributions of source code must retain the above copyright | ||
| + * notice, this list of conditions and the following disclaimer. | ||
| + * | ||
| + * o Redistributions in binary form must reproduce the above copyright | ||
| + * notice, this list of conditions and the following disclaimer in the | ||
| + * documentation and/or other materials provided with the distribution. | ||
| + * | ||
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| + */ | ||
| package com.whitemagicsoftware.kmcaster; | ||
| import com.whitemagicsoftware.kmcaster.listeners.FrameDragListener; | ||
| import javax.swing.*; | ||
| import java.awt.*; | ||
| import java.awt.geom.RoundRectangle2D; | ||
| + | ||
| +import static com.whitemagicsoftware.kmcaster.AppImage.*; | ||
| class EventFrame extends JFrame { | ||
| private static final float ARC = 8; | ||
| - private static final int FRAME_WIDTH = 380; | ||
| - private static final int FRAME_HEIGHT = 60; | ||
| + private static final Dimension FRAME_DIMENSIONS = new Dimension( 484, 70 ); | ||
| + private static final Color TRANSLUCENT = new Color( .2f, .2f, .2f, 0.5f ); | ||
| + private static final Color TRANSPARENT = new Color( 0, 0, 0, 0 ); | ||
| public EventFrame() { | ||
| + setLocationRelativeTo( null ); | ||
| setUndecorated( true ); | ||
| setAlwaysOnTop( true ); | ||
| - setBackground( new Color( .2f, .2f, .2f, 0.5f ) ); | ||
| - | ||
| - setLocationRelativeTo( null ); | ||
| - setSize( FRAME_WIDTH, FRAME_HEIGHT ); | ||
| - setShape( new RoundRectangle2D.Double( | ||
| - 0, 0, getWidth(), getHeight(), ARC, ARC ) ); | ||
| + setBackground( TRANSPARENT ); | ||
| + setSize( FRAME_DIMENSIONS ); | ||
| + setShape( createShape() ); | ||
| final var frameDragListener = new FrameDragListener( this ); | ||
| addMouseListener( frameDragListener ); | ||
| addMouseMotionListener( frameDragListener ); | ||
| + | ||
| + final var dimensions = new Dimension( getWidth(), getHeight() - 10 ); | ||
| + final var mouseView = MOUSE_LR.toComponent( dimensions ); | ||
| + final var shiftView = KEY_UP_SHIFT.toComponent( dimensions ); | ||
| + final var ctrlView = KEY_UP_CTRL.toComponent( dimensions ); | ||
| + final var altView = KEY_UP_ALT.toComponent( dimensions ); | ||
| + final var regularView = KEY_UP_REGULAR.toComponent( dimensions ); | ||
| + | ||
| + final var panel = new JPanel(); | ||
| + panel.setAlignmentX( Component.CENTER_ALIGNMENT ); | ||
| + panel.setBackground( TRANSLUCENT ); | ||
| + panel.add( mouseView ); | ||
| + panel.add( shiftView ); | ||
| + panel.add( ctrlView ); | ||
| + panel.add( altView ); | ||
| + panel.add( regularView ); | ||
| + | ||
| + final var content = getContentPane(); | ||
| + final var layout = new BoxLayout( content, BoxLayout.Y_AXIS ); | ||
| + | ||
| + content.setLayout( layout ); | ||
| + content.add( panel ); | ||
| + } | ||
| + | ||
| + private Shape createShape() { | ||
| + return new RoundRectangle2D.Double( | ||
| + 0, 0, getWidth(), getHeight(), ARC, ARC | ||
| + ); | ||
| } | ||
| } |
| import static java.util.logging.Logger.getLogger; | ||
| +import static javax.swing.SwingUtilities.invokeLater; | ||
| import static org.jnativehook.GlobalScreen.*; | ||
| initNativeHook(); | ||
| - final var kc = new KmCaster(); | ||
| - SwingUtilities.invokeLater( () -> kc.setVisible( true ) ); | ||
| + invokeLater( () -> { | ||
| + final var kc = new KmCaster(); | ||
| + kc.setVisible( true ); | ||
| + } ); | ||
| } | ||
| +/* | ||
| + * Copyright 2020 White Magic Software, Ltd. | ||
| + * | ||
| + * All rights reserved. | ||
| + * | ||
| + * Redistribution and use in source and binary forms, with or without | ||
| + * modification, are permitted provided that the following conditions are met: | ||
| + * | ||
| + * o Redistributions of source code must retain the above copyright | ||
| + * notice, this list of conditions and the following disclaimer. | ||
| + * | ||
| + * o Redistributions in binary form must reproduce the above copyright | ||
| + * notice, this list of conditions and the following disclaimer in the | ||
| + * documentation and/or other materials provided with the distribution. | ||
| + * | ||
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| + */ | ||
| package com.whitemagicsoftware.kmcaster.listeners; | ||
| import org.jnativehook.keyboard.NativeKeyEvent; | ||
| import org.jnativehook.keyboard.NativeKeyListener; | ||
| import java.beans.PropertyChangeListener; | ||
| import java.beans.PropertyChangeSupport; | ||
| +import java.util.List; | ||
| import java.util.Map; | ||
| -import java.util.Set; | ||
| import static java.util.Map.entry; | ||
| import static org.jnativehook.NativeInputEvent.*; | ||
| import static org.jnativehook.keyboard.NativeKeyEvent.getKeyText; | ||
| public class KeyboardListener implements NativeKeyListener { | ||
| - public final static String KEY_NAME_ALT = "ALT"; | ||
| - public final static String KEY_NAME_CTRL = "CTRL"; | ||
| - public final static String KEY_NAME_SHIFT = "SHIFT"; | ||
| - public final static String KEY_NAME_REGULAR = "REGULAR"; | ||
| + public final static String KEY_NAME_REGULAR = "regular"; | ||
| - /** | ||
| - * The library has default names for these modifiers, which will be | ||
| - * converted to lower case for comparison with this set. | ||
| - */ | ||
| - private final static Set<String> modifiers = Set.of( | ||
| - "alt", "ctrl", "shift" | ||
| + private final List<Modifier> mModifiers = List.of( | ||
| + new Modifier( "alt", ALT_MASK ), | ||
| + new Modifier( "ctrl", CTRL_MASK ), | ||
| + new Modifier( "shift", SHIFT_MASK ) | ||
| ); | ||
| ); | ||
| - private boolean mAltHeld; | ||
| - private boolean mCtrlHeld; | ||
| - private boolean mShiftHeld; | ||
| private String mRegularHeld = ""; | ||
| } | ||
| + @SuppressWarnings("unused") | ||
| public void removePropertyChangeListener( | ||
| final PropertyChangeListener listener ) { | ||
| mDispatcher.removePropertyChangeListener( listener ); | ||
| } | ||
| @Override | ||
| public void nativeKeyPressed( final NativeKeyEvent e ) { | ||
| final String regularHeld = getDisplayText( e ); | ||
| - // If it's not a modifier key, broadcast the regular value. | ||
| - if( !modifiers.contains( regularHeld.toLowerCase() ) ) { | ||
| - tryFire( KEY_NAME_REGULAR, mRegularHeld, regularHeld ); | ||
| - mRegularHeld = regularHeld; | ||
| + for( final var modifier : mModifiers ) { | ||
| + // If it's not a modifier key, broadcast the regular value. | ||
| + if( modifier.isName( regularHeld.toLowerCase() ) ) { | ||
| + tryFire( KEY_NAME_REGULAR, mRegularHeld, regularHeld ); | ||
| + mRegularHeld = regularHeld; | ||
| + } | ||
| } | ||
| - // If the modifier has changed, it'll be caught here. | ||
| updateModifiers( e ); | ||
| } | ||
| } | ||
| + /** | ||
| + * Notifies of any modifier state changes. | ||
| + * | ||
| + * @param e The keyboard event that was most recently triggered. | ||
| + */ | ||
| private void updateModifiers( final NativeKeyEvent e ) { | ||
| - final boolean alt = isAltDown( e ); | ||
| - final boolean ctrl = isControlDown( e ); | ||
| - final boolean shift = isShiftDown( e ); | ||
| - | ||
| - tryFire( KEY_NAME_ALT, mAltHeld, alt ); | ||
| - tryFire( KEY_NAME_CTRL, mCtrlHeld, ctrl ); | ||
| - tryFire( KEY_NAME_SHIFT, mShiftHeld, shift ); | ||
| - | ||
| - mAltHeld = alt; | ||
| - mCtrlHeld = ctrl; | ||
| - mShiftHeld = shift; | ||
| + for( final var modifier : mModifiers ) { | ||
| + final boolean down = modifier.matches( e ); | ||
| + tryFire( modifier.toString(), modifier.isHeld(), down ); | ||
| + modifier.setHeld( down ); | ||
| + } | ||
| } | ||
| /** | ||
| * Called to fire the property change with the two given values differ. | ||
| * | ||
| * @param name The name of the property that has changed. | ||
| * @param o Old property value. | ||
| * @param n New property value. | ||
| */ | ||
| - @SuppressWarnings("SameParameterValue") | ||
| private void tryFire( final String name, final String o, final String n ) { | ||
| if( !o.equals( n ) ) { | ||
| mDispatcher.firePropertyChange( name, o, n ); | ||
| } | ||
| } | ||
| /** | ||
| - * Called to fire the property change with the two given values differ. | ||
| + * Delegates to {@link #tryFire(String, String, String)} with {@link Boolean} | ||
| + * values as strings. | ||
| * | ||
| * @param name The name of the property that has changed. | ||
| * @param o Old property value. | ||
| * @param n New property value. | ||
| */ | ||
| private void tryFire( final String name, final boolean o, final boolean n ) { | ||
| - if( o != n ) { | ||
| - mDispatcher.firePropertyChange( name, o, n ); | ||
| - } | ||
| + tryFire( name, Boolean.toString( o ), Boolean.toString( n ) ); | ||
| } | ||
| e.getRawCode(), getKeyText( e.getKeyCode() ) | ||
| ); | ||
| - } | ||
| - | ||
| - private boolean isModifierDown( final NativeKeyEvent e, final int mask ) { | ||
| - return (e.getModifiers() & mask) != 0; | ||
| - } | ||
| - | ||
| - private boolean isAltDown( final NativeKeyEvent e ) { | ||
| - return isModifierDown( e, ALT_MASK ); | ||
| - } | ||
| - | ||
| - private boolean isControlDown( final NativeKeyEvent e ) { | ||
| - return isModifierDown( e, CTRL_MASK ); | ||
| - } | ||
| - | ||
| - private boolean isShiftDown( final NativeKeyEvent e ) { | ||
| - return isModifierDown( e, SHIFT_MASK ); | ||
| } | ||
| } | ||
| +/* | ||
| + * Copyright 2020 White Magic Software, Ltd. | ||
| + * | ||
| + * All rights reserved. | ||
| + * | ||
| + * Redistribution and use in source and binary forms, with or without | ||
| + * modification, are permitted provided that the following conditions are met: | ||
| + * | ||
| + * o Redistributions of source code must retain the above copyright | ||
| + * notice, this list of conditions and the following disclaimer. | ||
| + * | ||
| + * o Redistributions in binary form must reproduce the above copyright | ||
| + * notice, this list of conditions and the following disclaimer in the | ||
| + * documentation and/or other materials provided with the distribution. | ||
| + * | ||
| + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| + */ | ||
| +package com.whitemagicsoftware.kmcaster.listeners; | ||
| + | ||
| +import org.jnativehook.keyboard.NativeKeyEvent; | ||
| + | ||
| +import javax.swing.event.ChangeListener; | ||
| + | ||
| +/** | ||
| + * Responsible for tracking the state of modifier keys. | ||
| + */ | ||
| +class Modifier { | ||
| + private boolean mHeld; | ||
| + private final int mMask; | ||
| + private final String mName; | ||
| + | ||
| + Modifier( final String name, final int mask ) { | ||
| + assert name != null; | ||
| + | ||
| + mName = name.toLowerCase(); | ||
| + mMask = mask; | ||
| + } | ||
| + | ||
| + public boolean isName( final String name ) { | ||
| + return mName.equals( name ); | ||
| + } | ||
| + | ||
| + public boolean isHeld() { | ||
| + return mHeld; | ||
| + } | ||
| + | ||
| + public void setHeld( final boolean held ) { | ||
| + mHeld = held; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Answers whether the given {@link NativeKeyEvent} modifiers are set to | ||
| + * include the modifiers defined by this instance. | ||
| + * | ||
| + * @param e The event that has modifiers to check. | ||
| + * @return {@code true} This modifier matches the given event's modifiers. | ||
| + */ | ||
| + public boolean matches( final NativeKeyEvent e ) { | ||
| + return (e.getModifiers() & mMask) != 0; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Returns a unique identifier for this modifier that can be used by | ||
| + * a {@link ChangeListener}. | ||
| + * | ||
| + * @return The modifier key name, in lowercase. | ||
| + */ | ||
| + @Override | ||
| + public String toString() { | ||
| + return mName; | ||
| + } | ||
| +} | ||
| public void nativeMouseDragged( NativeMouseEvent e ) { | ||
| - System.out.println( "Mouse Dragged: " + e.getX() + ", " + e.getY() ); | ||
| +// System.out.println( "Mouse Dragged: " + e.getX() + ", " + e.getY() ); | ||
| } | ||
| -<svg height="9.563195mm" viewBox="0 0 6.2268581 9.5631952" width="6.226858mm" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="675.16781095345" x2="726.91040621336" y1="193.5974546131" y2="193.5974546131"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="694.62630016049" x2="706.30293766591" y1="170.04024231137" y2="170.04024231137"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><g transform="matrix(.11019174 0 0 .11019174 -74.07199 -16.55124)"><path d="m728.71927 191.15556c0 25.31414-12.65005 45.83532-28.25465 45.83532s-28.25465-20.52118-28.25465-45.83532 12.87203-40.95154 28.47664-40.95154c15.6046 0 28.03266 15.6374 28.03266 40.95154z" fill="url(#a)"/><g stroke="#333"><path d="m700.46462 150.76421v38.00227" fill="none" stroke-linecap="round"/><path d="m727.85189 184.1953c-16.7914 6.29576-36.32862 6.68664-54.76049 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#b)" fill-rule="evenodd" height="25.528791" rx="5.216753" width="10.433506" x="695.24786" y="157.27585"/></g></g></svg> | ||
| +<svg height="60" viewBox="0 0 40 60" width="40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="2.45" x2="3.66" xlink:href="#c" y1="1.7" y2="1.7"/><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="9.5" x2="14.098" xlink:href="#c" y1="6.46" y2="6.46"/><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="2.45" x2="3.66" y1="1.7" y2="1.7"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="d" gradientUnits="userSpaceOnUse" x1=".95001" x2="22.686" y1="16.492" y2="16.492"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><g transform="scale(1.6949 1.6438)"><g stroke="#333" stroke-width=".11" transform="matrix(3.8 0 0 3.8 .00001 -.000006)"><path d="m3.1.062v4.2" fill="none" stroke-linecap="round"/><path d="m6.1 3.7c-1.9.69-4 .74-6 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#a)" fill-rule="evenodd" height="2.8" rx=".57" width="1.1" x="2.5" y=".78"/></g><g stroke-width=".418"><path d="m23.6 17.1c0 10.6-5.32 19.4-11.8 19.4s-11.8-8.74-11.8-19.4 5.32-17.1 11.8-17.1 11.8 6.46 11.8 17.1z" fill="url(#d)"/><g stroke="#333"><path d="m11.8.236v16" fill="none" stroke-linecap="round"/><path d="m23.2 14.2c-7.22 2.62-15.2 2.81-22.8 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#b)" fill-rule="evenodd" height="10.6" rx="2.17" width="4.18" x="9.69" y="2.96"/></g></g></g></svg> |
| - | ||
| +<svg height="60" viewBox="0 0 40 60" width="40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="2.45" x2="3.66" xlink:href="#c" y1="1.7" y2="1.7"/><linearGradient id="b" gradientTransform="scale(1.6949 1.6438)" gradientUnits="userSpaceOnUse" x1="9.5" x2="14.098" xlink:href="#c" y1="6.46" y2="6.46"/><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="2.45" x2="3.66" y1="1.7" y2="1.7"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="d" gradientTransform="scale(1.6949 1.6438)" gradientUnits="userSpaceOnUse" x1=".95001" x2="22.686" y1="16.492" y2="16.492"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><g stroke="#333" stroke-width=".11" transform="matrix(6.4406 0 0 6.2464 .000017 -.00001)"><path d="m3.1.062v4.2" fill="none" stroke-linecap="round"/><path d="m6.1 3.7c-1.9.69-4 .74-6 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#a)" fill-rule="evenodd" height="2.8" rx=".57" width="1.1" x="2.5" y=".78"/></g><path d="m40 28.109c0 17.424-9.0169 31.89-20 31.89s-20-14.367-20-31.89 9.0169-28.109 20-28.109 20 10.619 20 28.109z" fill="url(#d)" stroke-width=".69771"/><path d="m20.002 0c6.4635 0 11.4 3.5947 14.536 8.0789 3.2687 4.6251 4.7135 10.298 5.2149 15.107-6.9009 2.2617-12.492 3.5032-19.751 3.4974z" fill="#40ff00" fill-opacity=".25" fill-rule="evenodd" stroke-width="1.7077"/><path d="m19.947 0c-6.2319 0-11.204 3.4235-14.462 8.0337-3.2687 4.6251-4.7622 10.391-5.2389 15.204 6.9009 2.2617 12.442 3.4521 19.701 3.4463z" fill="#0096ff" fill-opacity=".25" fill-rule="evenodd" stroke-width="1.7077"/><g stroke="#333" stroke-width=".69771"><path d="m20 .38794v26.301" fill="none" stroke-linecap="round"/><path d="m39.322 23.342c-12.237 4.3068-25.762 4.6191-38.644 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#b)" fill-rule="evenodd" height="17.424" rx="3.6779" width="7.0847" x="16.424" y="4.8656"/></g></svg> |
| -<svg height="9.563195mm" viewBox="0 0 6.2268581 9.5631952" width="6.226858mm" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="-218.23392109934" x2="-212.53231434848" y1="188.98810309963" y2="188.98810309963"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="-216.08975626054" x2="-214.80308722328" y1="186.3922928196" y2="186.3922928196"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><g transform="translate(218.55985 -184.2065)"><path d="m-212.333 188.71902c0 2.78941-1.39393 5.05068-3.11342 5.05068-1.7195 0-3.11343-2.26127-3.11343-5.05068s1.41839-4.51252 3.13789-4.51252c1.71949 0 3.08896 1.72311 3.08896 4.51252z" fill="url(#a)"/><path d="m-215.44807 184.20884c-.95261 0-1.73653.55323-2.24371 1.28803-.50884.73718-.75361 1.66727-.82783 2.43428 1.07427.36049 1.94146.53162 3.07154.53069z" fill="#0096ff" fill-opacity=".25" fill-rule="evenodd" stroke-width=".268987"/><g stroke="#333" stroke-width=".110192"><path d="m-215.44642 184.26823v4.18754" fill="none" stroke-linecap="round"/><path d="m-212.42857 187.95206c-1.85028.69374-4.00312.73681-6.03416 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#b)" fill-rule="evenodd" height="2.813062" rx=".574843" width="1.149686" x="-216.02127" y="184.98576"/></g></g></svg> | ||
| +<svg height="60" viewBox="0 0 40 60" width="40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="2.45" x2="3.66" xlink:href="#c" y1="1.7" y2="1.7"/><linearGradient id="b" gradientTransform="scale(1.6949 1.6438)" gradientUnits="userSpaceOnUse" x1="9.5" x2="14.098" xlink:href="#c" y1="6.46" y2="6.46"/><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="2.45" x2="3.66" y1="1.7" y2="1.7"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="d" gradientTransform="scale(1.6949 1.6438)" gradientUnits="userSpaceOnUse" x1=".95001" x2="22.686" y1="16.492" y2="16.492"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><g stroke="#333" stroke-width=".11" transform="matrix(6.4406 0 0 6.2464 .000017 -.00001)"><path d="m3.1.062v4.2" fill="none" stroke-linecap="round"/><path d="m6.1 3.7c-1.9.69-4 .74-6 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#a)" fill-rule="evenodd" height="2.8" rx=".57" width="1.1" x="2.5" y=".78"/></g><path d="m40 28.109c0 17.424-9.0169 31.89-20 31.89s-20-14.367-20-31.89 9.0169-28.109 20-28.109 20 10.619 20 28.109z" fill="url(#d)" stroke-width=".69771"/><path d="m19.947 0c-6.2319 0-11.204 3.4235-14.462 8.0337-3.2687 4.6251-4.7622 10.391-5.2389 15.204 6.9009 2.2617 12.442 3.4521 19.701 3.4463z" fill="#0096ff" fill-opacity=".25" fill-rule="evenodd" stroke-width="1.7077"/><g stroke="#333" stroke-width=".69771"><path d="m20 .38794v26.301" fill="none" stroke-linecap="round"/><path d="m39.322 23.342c-12.237 4.3068-25.762 4.6191-38.644 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#b)" fill-rule="evenodd" height="17.424" rx="3.6779" width="7.0847" x="16.424" y="4.8656"/></g></svg> |
| -<svg height="9.563195mm" viewBox="0 0 6.2268581 9.5631952" width="6.226858mm" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="-218.23392109934" x2="-212.53231434848" y1="188.98810309963" y2="188.98810309963"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="-216.08975626054" x2="-214.80308722328" y1="186.3922928196" y2="186.3922928196"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><g transform="translate(218.55985 -184.2065)"><path d="m-212.333 188.71902c0 2.78941-1.39393 5.05068-3.11342 5.05068-1.7195 0-3.11343-2.26127-3.11343-5.05068s1.41839-4.51252 3.13789-4.51252c1.71949 0 3.08896 1.72311 3.08896 4.51252z" fill="url(#a)"/><g stroke="#333" stroke-width=".110192"><path d="m-215.44642 184.26823v4.18754" fill="none" stroke-linecap="round"/><path d="m-212.42857 187.95206c-1.85028.69374-4.00312.73681-6.03416 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#b)" fill-rule="evenodd" height="2.813062" rx=".574843" width="1.149686" x="-216.02127" y="184.98576"/></g><rect fill="#ff1500" fill-opacity=".25" fill-rule="evenodd" height="2.700655" rx=".537201" ry=".551873" width="1.074401" x="-215.98364" y="185.04196"/></g></svg> | ||
| +<svg height="60" viewBox="0 0 40 60" width="40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(6.4406 0 0 6.2464 .000017 -.00001)" gradientUnits="userSpaceOnUse" x1="2.45" x2="3.66" xlink:href="#c" y1="1.7" y2="1.7"/><linearGradient id="b" gradientTransform="scale(1.6949 1.6438)" gradientUnits="userSpaceOnUse" x1="9.5" x2="14.098" xlink:href="#c" y1="6.46" y2="6.46"/><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="2.45" x2="3.66" y1="1.7" y2="1.7"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="d" gradientTransform="scale(1.6949 1.6438)" gradientUnits="userSpaceOnUse" x1=".95001" x2="22.686" y1="16.492" y2="16.492"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><g stroke-width=".69771"><g stroke="#333"><path d="m19.966.38727v26.235" fill="none" stroke-linecap="round"/><path d="m39.288 23.112c-12.237 4.31-25.762 4.6224-38.644 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#a)" fill-rule="evenodd" height="17.49" rx="3.6712" width="7.0847" x="16.102" y="4.8722"/></g><path d="m40 28.109c0 17.424-9.0169 31.89-20 31.89s-20-14.367-20-31.89 9.0169-28.109 20-28.109 20 10.619 20 28.109z" fill="url(#d)"/><g stroke="#333"><path d="m20 .38794v26.301" fill="none" stroke-linecap="round"/><path d="m39.322 23.342c-12.237 4.3068-25.762 4.6191-38.644 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#b)" fill-rule="evenodd" height="17.424" rx="3.6779" width="7.0847" x="16.424" y="4.8656"/></g></g><rect fill="#ff1500" fill-opacity=".25" fill-rule="evenodd" height="16.944" rx="3.2245" ry="3.4625" stroke-width="6.1367" width="6.4489" x="16.741" y="5.1058"/></svg> |
| -<svg height="9.563195mm" viewBox="0 0 6.2268581 9.5631952" width="6.226858mm" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="-218.23392109934" x2="-212.53231434848" y1="188.98810309963" y2="188.98810309963"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="-216.08975626054" x2="-214.80308722328" y1="186.3922928196" y2="186.3922928196"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><g transform="translate(218.55985 -184.2065)"><path d="m-212.333 188.71902c0 2.78941-1.39393 5.05068-3.11342 5.05068-1.7195 0-3.11343-2.26127-3.11343-5.05068s1.41839-4.51252 3.13789-4.51252c1.71949 0 3.08896 1.72311 3.08896 4.51252z" fill="url(#a)"/><path d="m-215.44627 184.21104c1.05121 0 1.75568.55287 2.26286 1.28767.50884.73718.73446 1.66763.80868 2.43464-1.07427.36049-1.94146.53162-3.07154.53069z" fill="#40ff00" fill-opacity=".25" fill-rule="evenodd" stroke-width=".268987"/><g stroke="#333" stroke-width=".110192"><path d="m-215.44642 184.26823v4.18754" fill="none" stroke-linecap="round"/><path d="m-212.42857 187.95206c-1.85028.69374-4.00312.73681-6.03416 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#b)" fill-rule="evenodd" height="2.813062" rx=".574843" width="1.149686" x="-216.02127" y="184.98576"/></g></g></svg> | ||
| +<svg height="60" viewBox="0 0 40 60" width="40" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(6.4406 0 0 6.2464 .000017 -.00001)" gradientUnits="userSpaceOnUse" x1="2.45" x2="3.66" xlink:href="#c" y1="1.7" y2="1.7"/><linearGradient id="b" gradientTransform="scale(1.6949 1.6438)" gradientUnits="userSpaceOnUse" x1="9.5" x2="14.098" xlink:href="#c" y1="6.46" y2="6.46"/><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="2.45" x2="3.66" y1="1.7" y2="1.7"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="d" gradientTransform="scale(1.6949 1.6438)" gradientUnits="userSpaceOnUse" x1=".95001" x2="22.686" y1="16.492" y2="16.492"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><g stroke="#333" stroke-width=".69771"><path d="m19.966.38727v26.235" fill="none" stroke-linecap="round"/><path d="m39.288 23.112c-12.237 4.31-25.762 4.6224-38.644 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#a)" fill-rule="evenodd" height="17.49" rx="3.6712" width="7.0847" x="16.102" y="4.8722"/></g><path d="m40 28.109c0 17.424-9.0169 31.89-20 31.89s-20-14.367-20-31.89 9.0169-28.109 20-28.109 20 10.619 20 28.109z" fill="url(#d)" stroke-width=".69771"/><path d="m20 .0051998c6.4635 0 11.4 3.5947 14.536 8.0789 3.2687 4.6251 4.7135 10.298 5.2149 15.107-6.9009 2.2617-12.492 3.5032-19.751 3.4974z" fill="#40ff00" fill-opacity=".25" fill-rule="evenodd" stroke-width="1.7077"/><g stroke="#333" stroke-width=".69771"><path d="m20 .38794v26.301" fill="none" stroke-linecap="round"/><path d="m39.322 23.342c-12.237 4.3068-25.762 4.6191-38.644 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#b)" fill-rule="evenodd" height="17.424" rx="3.6779" width="7.0847" x="16.424" y="4.8656"/></g></svg> |
| -<svg height="9.563195mm" viewBox="0 0 6.2268581 9.5631952" width="6.226858mm" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="-218.23392109934" x2="-212.53231434848" y1="188.98810309963" y2="188.98810309963"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><linearGradient id="b" gradientUnits="userSpaceOnUse" x1="-216.08975626054" x2="-214.80308722328" y1="186.3922928196" y2="186.3922928196"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><g transform="translate(218.55985 -184.2065)"><path d="m-212.333 188.71902c0 2.78941-1.39393 5.05068-3.11342 5.05068-1.7195 0-3.11343-2.26127-3.11343-5.05068s1.41839-4.51252 3.13789-4.51252c1.71949 0 3.08896 1.72311 3.08896 4.51252z" fill="url(#a)"/><path d="m-215.44627 184.21104c1.05121 0 1.75568.55287 2.26286 1.28767.50884.73718.73446 1.66763.80868 2.43464-1.07427.36049-1.94146.53162-3.07154.53069z" fill="#40ff00" fill-opacity=".25" fill-rule="evenodd" stroke-width=".268987"/><path d="m-215.44807 184.20884c-.95261 0-1.73653.55323-2.24371 1.28803-.50884.73718-.75361 1.66727-.82783 2.43428 1.07427.36049 1.94146.53162 3.07154.53069z" fill="#0096ff" fill-opacity=".25" fill-rule="evenodd" stroke-width=".268987"/><g stroke="#333" stroke-width=".110192"><path d="m-215.44642 184.26823v4.18754" fill="none" stroke-linecap="round"/><path d="m-212.42857 187.95206c-1.85028.69374-4.00312.73681-6.03416 0" fill="none" stroke-linecap="round" stroke-linejoin="bevel"/><rect fill="url(#b)" fill-rule="evenodd" height="2.813062" rx=".574843" width="1.149686" x="-216.02127" y="184.98576"/></g><rect fill="#ff1500" fill-opacity=".25" fill-rule="evenodd" height="2.700655" rx=".537201" ry=".551873" width="1.074401" x="-215.98364" y="185.04196"/></g></svg> | ||
| + |
| Delta | 401 lines added, 119 lines removed, 282-line increase |
|---|