Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/kmcaster.git
.idea/.gitignore
+workspace.xml
.idea/workspace.xml
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
- <component name="ChangeListManager">
- <list default="true" id="be1819c5-28d3-4984-9634-0b266734e13c" name="Default Changelist" comment="">
- <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" 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/HardwareState.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/HardwareState.java" afterDir="false" />
- <change beforePath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/HardwareSwitches.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/HardwareSwitches.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/SwitchName.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/listeners/SwitchName.java" afterDir="false" />
- <change beforePath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/listeners/FrameDragListener.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/listeners/FrameDragListener.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/KeyboardModifier.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/com/whitemagicsoftware/kmcaster/listeners/KeyboardModifier.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" />
- </list>
- <option name="SHOW_DIALOG" value="false" />
- <option name="HIGHLIGHT_CONFLICTS" value="true" />
- <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
- <option name="LAST_RESOLUTION" value="IGNORE" />
- </component>
- <component name="ExternalProjectsData">
- <projectState path="$PROJECT_DIR$">
- <ProjectState />
- </projectState>
- </component>
- <component name="ExternalProjectsManager">
- <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>
- </expand>
- <select />
- </tree_state>
- </projects_view>
- </state>
- </system>
- </component>
- <component name="FileTemplateManagerImpl">
- <option name="RECENT_TEMPLATES">
- <list>
- <option value="Enum" />
- <option value="Class" />
- </list>
- </option>
- </component>
- <component name="Git.Settings">
- <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
- </component>
- <component name="ProjectId" id="1ekBeNU4c094edVfyTkiboUOdYP" />
- <component name="ProjectLevelVcsManager">
- <ConfirmationsSetting value="2" id="Add" />
- </component>
- <component name="ProjectViewState">
- <option name="hideEmptyMiddlePackages" value="true" />
- <option name="showLibraryContents" value="true" />
- </component>
- <component name="PropertiesComponent">
- <property name="ASKED_ADD_EXTERNAL_FILES" value="true" />
- <property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
- <property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
- <property name="last_opened_file_path" value="$PROJECT_DIR$" />
- <property name="project.structure.last.edited" value="Modules" />
- <property name="project.structure.proportion" value="0.15" />
- <property name="project.structure.side.proportion" value="0.21724138" />
- <property name="settings.editor.selected.configurable" value="File.Encoding" />
- <property name="show.unlinked.gradle.project.popup" value="true" />
- </component>
- <component name="RecentsManager">
- <key name="MoveInnerDialog.RECENTS_KEY">
- <recent name="com.whitemagicsoftware.kmcaster" />
- <recent name="com.whitemagicsoftware.kmcaster.listeners" />
- </key>
- <key name="CreateClassDialog.RecentsKey">
- <recent name="com.whitemagicsoftware.kmcaster" />
- <recent name="com.whitemagicsoftware.kmcaster.listeners" />
- </key>
- </component>
- <component name="RunManager">
- <configuration name="KmCaster" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
- <option name="MAIN_CLASS_NAME" value="com.whitemagicsoftware.kmcaster.KmCaster" />
- <module name="kmcaster.main" />
- <extension name="coverage">
- <pattern>
- <option name="PATTERN" value="com.whitemagicsoftware.kmcaster.listeners.*" />
- <option name="ENABLED" value="true" />
- </pattern>
- </extension>
- <method v="2">
- <option name="Make" enabled="true" />
- </method>
- </configuration>
- <recent_temporary>
- <list>
- <item itemvalue="Application.KmCaster" />
- </list>
- </recent_temporary>
- </component>
- <component name="SvnConfiguration">
- <configuration />
- </component>
- <component name="TaskManager">
- <task active="true" id="Default" summary="Default task">
- <changelist id="be1819c5-28d3-4984-9634-0b266734e13c" name="Default Changelist" comment="" />
- <created>1594855804356</created>
- <option name="number" value="Default" />
- <option name="presentableId" value="Default" />
- <updated>1594855804356</updated>
- </task>
- <servers />
- </component>
- <component name="VcsManagerConfiguration">
- <option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
- </component>
- <component name="WindowStateProjectService">
- <state x="813" y="683" width="218" height="250" key="#Notifications" timestamp="1594856235998">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state x="813" y="683" width="218" height="250" key="#Notifications/0.28.2560.1529@0.28.2560.1529" timestamp="1594856235998" />
- <state x="314" y="436" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1594970464272">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state x="314" y="436" key="#com.intellij.execution.impl.EditConfigurationsDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594970464272" />
- <state x="734" y="519" width="477" height="578" key="#com.intellij.ide.util.MemberChooser" timestamp="1594969516839">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state x="734" y="519" width="477" height="578" key="#com.intellij.ide.util.MemberChooser/0.28.2560.1529@0.28.2560.1529" timestamp="1594969516839" />
- <state x="745" y="737" key="#com.intellij.refactoring.move.MoveHandler.SelectRefactoringDialog" timestamp="1594958988910">
- <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="1594958988910" />
- <state x="707" y="657" width="431" height="302" key="#com.intellij.refactoring.move.moveInner.MoveInnerDialog" timestamp="1594958994663">
- <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="1594958994663" />
- <state x="567" y="28" width="711" height="1526" key="#com.intellij.refactoring.rename.AutomaticRenamingDialog" timestamp="1594967090738">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state x="567" y="28" width="711" height="1526" key="#com.intellij.refactoring.rename.AutomaticRenamingDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594967090738" />
- <state x="659" y="559" width="526" height="497" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog" timestamp="1594880960290">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state x="659" y="559" width="526" height="497" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594880960290" />
- <state x="710" y="704" width="425" height="207" key="DetectedRootsChooserDialog" timestamp="1594872764235">
- <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="330" key="GridCell.Tab.0.bottom" timestamp="1594972026417">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state width="1479" height="330" key="GridCell.Tab.0.bottom/0.28.2560.1529@0.28.2560.1529" timestamp="1594972026417" />
- <state width="1479" height="330" key="GridCell.Tab.0.center" timestamp="1594972026417">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state width="1479" height="330" key="GridCell.Tab.0.center/0.28.2560.1529@0.28.2560.1529" timestamp="1594972026417" />
- <state width="1479" height="330" key="GridCell.Tab.0.left" timestamp="1594972026416">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state width="1479" height="330" key="GridCell.Tab.0.left/0.28.2560.1529@0.28.2560.1529" timestamp="1594972026416" />
- <state width="1479" height="330" key="GridCell.Tab.0.right" timestamp="1594972026417">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state width="1479" height="330" key="GridCell.Tab.0.right/0.28.2560.1529@0.28.2560.1529" timestamp="1594972026417" />
- <state width="1479" height="406" key="GridCell.Tab.1.bottom" timestamp="1594959771008">
- <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="1594959771008" />
- <state width="1479" height="406" key="GridCell.Tab.1.center" timestamp="1594959771007">
- <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="1594959771007" />
- <state width="1479" height="406" key="GridCell.Tab.1.left" timestamp="1594959771006">
- <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="1594959771006" />
- <state width="1479" height="406" key="GridCell.Tab.1.right" timestamp="1594959771007">
- <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="1594959771007" />
- <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="1594959421070">
- <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="1594959421070" />
- <state x="1068" y="347" width="1323" height="1003" key="com.intellij.history.integration.ui.views.FileHistoryDialog" timestamp="1594955523088">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state x="1068" y="347" width="1323" height="1003" key="com.intellij.history.integration.ui.views.FileHistoryDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594955523088" />
- <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="1594972340355">
- <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="1594972340355" />
- <state x="915" y="547" width="415" height="496" key="refactoring.ChangeSignatureDialog" timestamp="1594967617639">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state x="915" y="547" width="415" height="496" key="refactoring.ChangeSignatureDialog/0.28.2560.1529@0.28.2560.1529" timestamp="1594967617639" />
- <state x="589" y="382" width="672" height="677" key="run.anything.popup" timestamp="1594967368555">
- <screen x="0" y="28" width="2560" height="1529" />
- </state>
- <state x="589" y="382" width="672" height="677" key="run.anything.popup/0.28.2560.1529@0.28.2560.1529" timestamp="1594967368555" />
- <state x="589" y="477" width="672" height="678" key="search.everywhere.popup" timestamp="1594965859325">
- <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="1594965859325" />
- </component>
-</project>
+
build.gradle
dependencies {
- implementation 'com.kitfox.svg:svg-salamander:1.0'
+ // SVG
+ implementation fileTree(include: ['**/*.jar'], dir: 'libs')
implementation 'com.1stleg:jnativehook:2.1.0'
libs/svgSalamander-1.1.2.jar
Binary files differ
src/main/com/whitemagicsoftware/kmcaster/EventFrame.java
import com.whitemagicsoftware.kmcaster.listeners.FrameDragListener;
-import com.whitemagicsoftware.kmcaster.listeners.SwitchName;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.util.HashMap;
import java.util.Map;
-import static com.whitemagicsoftware.kmcaster.HardwareSwitches.state;
-import static com.whitemagicsoftware.kmcaster.listeners.SwitchName.*;
+import static com.whitemagicsoftware.kmcaster.HardwareImages.state;
+import static com.whitemagicsoftware.kmcaster.HardwareSwitch.*;
public class EventFrame extends JFrame {
private static final float ARC = 8;
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 );
- private final HardwareSwitches mSwitches;
- private final Map<SwitchName, ImageComponent> mSwitchViews = new HashMap<>();
+ private final HardwareImages mSwitches;
+ private final Map<HardwareSwitch, ImageComponent> mSwitchViews = new HashMap<>();
public EventFrame() {
addMouseMotionListener( frameDragListener );
- final var dimensions = new Dimension( getWidth(), getHeight() - 10 );
- mSwitches = new HardwareSwitches( dimensions );
+ final var dimensions = new Dimension( getWidth(), getHeight()- 10 );
+ mSwitches = new HardwareImages( dimensions );
final var mouseImage = mSwitches.get( state( MOUSE_LEFT, false ) );
protected void updateSwitchLabel(
- final SwitchName name, final String label ) {
+ final HardwareSwitch name, final String label ) {
+ System.out.println( "Switch Label: " + label );
}
src/main/com/whitemagicsoftware/kmcaster/HardwareImages.java
+/*
+ * 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 java.awt.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.whitemagicsoftware.kmcaster.HardwareState.ANY_KEY;
+import static com.whitemagicsoftware.kmcaster.HardwareSwitch.*;
+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 HardwareImages {
+
+ private final static String DIR_IMAGES = "/images";
+ private final static String DIR_IMAGES_KEYBOARD = DIR_IMAGES + "/key";
+ private final static String DIR_IMAGES_MOUSE = DIR_IMAGES + "/mouse";
+
+ private final static SvgRasterizer sRasterizer = new SvgRasterizer();
+
+ private final Map<HardwareState, Image> mImages = new HashMap<>();
+ private final Dimension mDimension;
+
+ /**
+ * Constructs an enumerated type that represents the different types of
+ * images shown when keyboard and mouse events are triggered.
+ *
+ * @param dimension The image will be scaled to the given dimensions, aspect
+ * ratio is maintained.
+ */
+ public HardwareImages( final Dimension dimension ) {
+ assert dimension != null;
+
+ mDimension = dimension;
+
+ final var mouseReleased = mouseImage( "0" );
+
+ for( int i = 1; i <= 3; i++ ) {
+ final var s = Integer.toString( i );
+ final var switchName = HardwareSwitch.valueFrom( "button " + s );
+ mImages.put( state( switchName, true ), mouseImage( s ) );
+ mImages.put( state( switchName, false ), mouseReleased );
+ }
+
+ mImages.put( state( MOUSE_LR, true ), mouseImage( "1-3" ) );
+ mImages.put( state( MOUSE_LR, false ), mouseReleased );
+
+ mImages.put( state( KEY_ALT, true ), keyDnImage( "medium" ) );
+ mImages.put( state( KEY_ALT, false ), keyUpImage( "medium" ) );
+ mImages.put( state( KEY_CTRL, true ), keyDnImage( "medium" ) );
+ mImages.put( state( KEY_CTRL, false ), keyUpImage( "medium" ) );
+ mImages.put( state( KEY_SHIFT, true ), keyDnImage( "long" ) );
+ mImages.put( state( KEY_SHIFT, false ), keyUpImage( "long" ) );
+ mImages.put( state( KEY_REGULAR, ANY_KEY ), keyDnImage( "short" ) );
+ mImages.put( state( KEY_REGULAR, false ), keyUpImage( "short" ) );
+ }
+
+ public Image get( final HardwareState state ) {
+ return mImages.get( state );
+ }
+
+ public static HardwareState state(
+ final HardwareSwitch name, final boolean state ) {
+ return state( name, Boolean.toString( state ) );
+ }
+
+ public static HardwareState state(
+ final HardwareSwitch name, final String state ) {
+ return new HardwareState( name, state );
+ }
+
+ private Image mouseImage( final String prefix ) {
+ return createImage( format( "%s/%s", DIR_IMAGES_MOUSE, prefix ) );
+ }
+
+ private Image keyImage(
+ final String state, final String prefix ) {
+ return createImage(
+ format( "%s/%s/%s", DIR_IMAGES_KEYBOARD, state, prefix )
+ );
+ }
+
+ private Image keyUpImage( final String prefix ) {
+ return keyImage( "up", prefix );
+ }
+
+ private Image keyDnImage( final String prefix ) {
+ return keyImage( "dn", prefix );
+ }
+
+ private Image createImage( final String path ) {
+ assert mDimension != null;
+
+ final var resource = format( "%s.svg", path );
+
+ try {
+ return sRasterizer.rasterize( resource, mDimension );
+ } catch( final Exception ex ) {
+ rethrow( ex );
+ }
+
+ final var msg = format( "Missing resource %s", resource );
+ throw new RuntimeException( msg );
+ }
+
+ /**
+ * Cast a checked exception as a {@link RuntimeException}.
+ *
+ * @param <T> What type of {@link Throwable} to throw.
+ * @param t The problem to cast.
+ * @throws T The throwable is casted to this type.
+ */
+ @SuppressWarnings("unchecked")
+ private static <T extends Throwable> void rethrow( final Throwable t )
+ throws T {
+ throw (T) t;
+ }
+}
src/main/com/whitemagicsoftware/kmcaster/HardwareState.java
package com.whitemagicsoftware.kmcaster;
-import com.whitemagicsoftware.kmcaster.listeners.SwitchName;
-
/**
* Responsible for defining hardware switch states.
*/
public class HardwareState {
public final static String ANY_KEY = "*";
- private final SwitchName mName;
+ private final HardwareSwitch mName;
private final String mState;
/**
* Constructs a new instance that represents whether a key or mouse button
* was pressed.
*
- * @param name The {@link SwitchName} representing the type of switch
+ * @param name The {@link HardwareSwitch} representing the type of switch
* state to represent.
* @param state A value of "*' means a regular key was pressed; otherwise,
* "true" or "false" indicate pressed or released, respectively.
*/
- public HardwareState( final SwitchName name, final String state ) {
+ public HardwareState( final HardwareSwitch name, final String state ) {
assert name != null;
assert valid( state );
mName = name;
mState = state;
}
- public SwitchName getKey() {
+ public HardwareSwitch getKey() {
return mName;
}
src/main/com/whitemagicsoftware/kmcaster/HardwareSwitch.java
+/*
+ * 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 static org.jnativehook.NativeInputEvent.*;
+
+/**
+ * Used for compile-time binding between change listeners input events.
+ */
+public enum HardwareSwitch {
+ KEY_ALT( "alt", ALT_MASK ),
+ KEY_CTRL( "ctrl", CTRL_MASK ),
+ KEY_SHIFT( "shift", SHIFT_MASK ),
+ KEY_REGULAR( "regular" ),
+ MOUSE_LEFT( "button 1" ),
+ MOUSE_WHEEL( "button 2" ),
+ MOUSE_RIGHT( "button 3" ),
+ MOUSE_LR( "button 1-3" );
+
+ /**
+ * Indicates the switch is not a modifier.
+ */
+ private final static int NO_MASK = -1;
+
+ private final String mName;
+ private final int mMask;
+
+ /**
+ * Constructs a new switch with no mask value.
+ *
+ * @param name The switch name.
+ */
+ HardwareSwitch( final String name ) {
+ this( name, NO_MASK );
+ }
+
+ /**
+ * Constructs a new switch associated with a mask value that can be used
+ * to determine whether a modifier key is pressed.
+ *
+ * @param name The switch name.
+ * @param mask Modifier key bitmask.
+ */
+ HardwareSwitch( final String name, final int mask ) {
+ mName = name;
+ mMask = mask;
+ }
+
+ /**
+ * Answers whether this enumerated item represents a keyboard modifier.
+ *
+ * @return {@code true} when the switch is a modifier key.
+ */
+ public boolean isModifier() {
+ return this == KEY_ALT || this == KEY_CTRL || this == KEY_SHIFT;
+ }
+
+ /**
+ * Answers whether the given name and the switch's name are the same,
+ * ignoring case.
+ *
+ * @param name The switch name to compare against this name.
+ * @return {@code true} when the names match, regardless of case.
+ */
+ public boolean isName( final String name ) {
+ return mName.equalsIgnoreCase( name );
+ }
+
+ /**
+ * Answers whether this hardware switch is pressed, but only applies to
+ * keyboard modifier keys, not mouse buttons.
+ *
+ * @param modifiers A set of bits that indicate what modifier keys are
+ * pressed.
+ * @return {@code true} if this switch's modifier bit is set in the
+ * given {@code modifiers} value.
+ */
+ public boolean isPressed( final int modifiers ) {
+ assert isModifier();
+
+ return (modifiers & mMask) != 0;
+ }
+
+ /**
+ * Looks up the key that matches the given name, case-insensitively.
+ *
+ * @param name The name of the key to find in this enum.
+ * @return The {@link HardwareSwitch} object that matches the name.
+ */
+ public static HardwareSwitch valueFrom( final String name ) {
+ for( final var b : HardwareSwitch.values() ) {
+ if( b.isName( name ) ) {
+ return b;
+ }
+ }
+
+ return KEY_REGULAR;
+ }
+
+ /**
+ * Returns the switch name.
+ *
+ * @return The switch name, nothing more.
+ */
+ @Override
+ public String toString() {
+ return mName;
+ }
+
+}
src/main/com/whitemagicsoftware/kmcaster/HardwareSwitches.java
-/*
- * 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.SwitchName;
-
-import java.awt.*;
-import java.util.HashMap;
-import java.util.Map;
-
-import static com.whitemagicsoftware.kmcaster.HardwareState.ANY_KEY;
-import static com.whitemagicsoftware.kmcaster.listeners.SwitchName.*;
-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 HardwareSwitches {
-
- private final static String DIR_IMAGES = "/images";
- private final static String DIR_IMAGES_KEYBOARD = DIR_IMAGES + "/key";
- private final static String DIR_IMAGES_MOUSE = DIR_IMAGES + "/mouse";
-
- private final static SvgRasterizer sRasterizer = new SvgRasterizer();
-
- private final Map<HardwareState, Image> mImages = new HashMap<>();
- private final Dimension mDimension;
-
- /**
- * Constructs an enumerated type that represents the different types of
- * images shown when keyboard and mouse events are triggered.
- *
- * @param dimension The image will be scaled to the given height, aspect
- * ratio is maintained.
- */
- public HardwareSwitches( final Dimension dimension ) {
- assert dimension != null;
-
- mDimension = dimension;
-
- final var mouseReleased = mouseImage( "0" );
-
- for( int i = 1; i <= 3; i++ ) {
- final var s = Integer.toString( i );
- final var switchName = SwitchName.valueFrom( "button " + s );
- mImages.put( state( switchName, true ), mouseImage( s ) );
- mImages.put( state( switchName, false ), mouseReleased );
- }
-
- mImages.put( state( MOUSE_LR, true ), mouseImage( "1-3" ) );
- mImages.put( state( MOUSE_LR, false ), mouseReleased );
-
- mImages.put( state( KEY_ALT, true ), keyDnImage( "medium" ) );
- mImages.put( state( KEY_ALT, false ), keyUpImage( "medium" ) );
- mImages.put( state( KEY_CTRL, true ), keyDnImage( "medium" ) );
- mImages.put( state( KEY_CTRL, false ), keyUpImage( "medium" ) );
- mImages.put( state( KEY_SHIFT, true ), keyDnImage( "long" ) );
- mImages.put( state( KEY_SHIFT, false ), keyUpImage( "long" ) );
- mImages.put( state( KEY_REGULAR, ANY_KEY ), keyDnImage( "short" ) );
- mImages.put( state( KEY_REGULAR, false ), keyUpImage( "short" ) );
- }
-
- public Image get( final HardwareState state ) {
- return mImages.get( state );
- }
-
- public static HardwareState state(
- final SwitchName name, final boolean state ) {
- return state( name, Boolean.toString( state ) );
- }
-
- public static HardwareState state(
- final SwitchName name, final String state ) {
- return new HardwareState( name, state );
- }
-
- private Image mouseImage( final String prefix ) {
- return createImage( format( "%s/%s", DIR_IMAGES_MOUSE, prefix ) );
- }
-
- private Image keyImage(
- final String state, final String prefix ) {
- return createImage(
- format( "%s/%s/%s", DIR_IMAGES_KEYBOARD, state, prefix )
- );
- }
-
- private Image keyUpImage( final String prefix ) {
- return keyImage( "up", prefix );
- }
-
- private Image keyDnImage( final String prefix ) {
- return keyImage( "dn", prefix );
- }
-
- private Image createImage( final String path ) {
- assert mDimension != null;
-
- return sRasterizer.rasterize( format( "%s.svg", path ), mDimension );
- }
-}
src/main/com/whitemagicsoftware/kmcaster/KmCaster.java
import com.whitemagicsoftware.kmcaster.listeners.KeyboardListener;
import com.whitemagicsoftware.kmcaster.listeners.MouseListener;
-import com.whitemagicsoftware.kmcaster.listeners.SwitchName;
import org.jnativehook.GlobalScreen;
+import org.jnativehook.NativeHookException;
import java.beans.PropertyChangeEvent;
}
+ /**
+ * Called when a hardware switch has changed state.
+ *
+ * @param e Contains the identifier for the switch, its previous value,
+ * and its new value.
+ */
@Override
public void propertyChange( final PropertyChangeEvent e ) {
- var switchValue = e.getNewValue().toString();
+ final var switchName = e.getPropertyName();
+ final var switchValue = e.getNewValue().toString();
// True or false indicates a non-regular key was pressed.
- if( !"false".equals( switchValue ) && !"true".equals( switchValue ) ) {
- switchValue = ANY_KEY;
- }
+ final var context =
+ (!"false".equals( switchValue ) && !"true".equals( switchValue ))
+ ? ANY_KEY
+ : switchValue;
- final var switchState = createState( e.getPropertyName(), switchValue );
+ final var switchState = createState( e.getPropertyName(), context );
updateSwitchState( switchState );
updateSwitchLabel( switchState.getKey(), switchValue );
}
private HardwareState createState(
final String name, final String state ) {
assert name != null;
assert state != null;
- final var key = SwitchName.valueFrom( name );
+ final var key = HardwareSwitch.valueFrom( name );
return new HardwareState( key, state );
}
/**
* Initialize the key and mouse event listener native interface.
*/
- private static void initNativeHook() {
- try {
- registerNativeHook();
+ private static void initNativeHook() throws NativeHookException {
+ registerNativeHook();
- final var logger = getLogger( GlobalScreen.class.getPackage().getName() );
- logger.setLevel( Level.OFF );
- logger.setUseParentHandlers( false );
- } catch( final Exception ex ) {
- rethrow( ex );
- }
+ final var logger = getLogger( GlobalScreen.class.getPackage().getName() );
+ logger.setLevel( Level.OFF );
+ logger.setUseParentHandlers( false );
}
/**
* Main entry point.
*
* @param args Unused.
*/
- public static void main( final String[] args ) {
+ public static void main( final String[] args ) throws NativeHookException {
initNativeHook();
invokeLater( () -> {
final var kc = new KmCaster();
kc.setVisible( true );
} );
- }
-
- /**
- * Cast a checked exception as a {@link RuntimeException}.
- *
- * @param <T> What type of {@link Throwable} to throw.
- * @param throwable The problem to cast.
- * @throws T The throwable is casted to this type.
- */
- @SuppressWarnings("unchecked")
- public static <T extends Throwable> void rethrow( final Throwable throwable )
- throws T {
- throw (T) throwable;
}
}
src/main/com/whitemagicsoftware/kmcaster/SvgRasterizer.java
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.RenderingHints.VALUE_TEXT_ANTIALIAS_ON;
import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
* @param dstDim The output image dimensions.
* @return The rasterized {@link Image}.
+ * @throws SVGException Could not open, read, parse, or render SVG data.
*/
- public Image rasterize( final String path, final Dimension dstDim ) {
+ public Image rasterize( final String path, final Dimension dstDim )
+ throws SVGException {
final var diagram = loadDiagram( path );
- final var diaWidth = diagram.getWidth();
- final var diaHeight = diagram.getHeight();
- final var srcDim = new Dimension( (int) diaWidth, (int) diaHeight );
+ final var wDiagram = diagram.getWidth();
+ final var hDiagram = diagram.getHeight();
+ final var srcDim = new Dimension( (int) wDiagram, (int) hDiagram );
- final var scaledDim = scale( srcDim, dstDim );
- final var w = (int) scaledDim.getWidth();
- final var h = (int) scaledDim.getHeight();
+ final var scaled = fit( srcDim, dstDim );
+ final var wScaled = (int) scaled.getWidth();
+ final var hScaled = (int) scaled.getHeight();
- final var image = new BufferedImage( w, h, TYPE_INT_ARGB );
+ final var image = new BufferedImage( wScaled, hScaled, TYPE_INT_ARGB );
- try {
- final Graphics2D g = image.createGraphics();
- g.setRenderingHints( RENDERING_HINTS );
+ final var g = image.createGraphics();
+ g.setRenderingHints( RENDERING_HINTS );
- final AffineTransform transform = g.getTransform();
- transform.setToScale( w / diaWidth, h / diaHeight );
+ final var transform = g.getTransform();
+ transform.setToScale( wScaled / wDiagram, hScaled / hDiagram );
- g.setTransform( transform );
- diagram.render( g );
- g.dispose();
- } catch( final SVGException e ) {
- rethrow( e );
- }
+ g.setTransform( transform );
+ diagram.render( g );
+ g.dispose();
return image;
}
+ /**
+ * Gets an instance of {@link URL} that references a file in the
+ * application's resources.
+ *
+ * @param path The full path (starting at the root), relative to the
+ * application or JAR file's resources directory.
+ * @return A {@link URL} to the file or {@code null} if the path does not
+ * point to a resource.
+ */
private URL getResourceUrl( final String path ) {
- return HardwareSwitches.class.getResource( path );
+ return SvgRasterizer.class.getResource( path );
}
+ /**
+ * Loads the resource specified by the given path into an instance of
+ * {@link SVGDiagram} that can be rasterized into a bitmap format. The
+ * {@link SVGUniverse} class will
+ *
+ * @param path The full path (starting at the root), relative to the
+ * application or JAR file's resources directory.
+ * @return An {@link SVGDiagram} that can be rasterized onto a
+ * {@link BufferedImage}.
+ */
private SVGDiagram loadDiagram( final String path ) {
final var url = getResourceUrl( path );
- return applySettings( sRenderer.getDiagram( sRenderer.loadSVG( url ) ) );
+ final var uri = sRenderer.loadSVG( url );
+ final var diagram = sRenderer.getDiagram( uri );
+ return applySettings( diagram );
}
+ /**
+ * Instructs the SVG renderer to rasterize the image even if it would be
+ * clipped.
+ *
+ * @param diagram The {@link SVGDiagram} to render.
+ * @return The same instance with ignore clip heuristics set to {@code true}.
+ */
private SVGDiagram applySettings( final SVGDiagram diagram ) {
diagram.setIgnoringClipHeuristic( true );
return diagram;
}
- private Dimension scale( final Dimension src, final Dimension dst ) {
+ /**
+ * Scales the given source {@link Dimension} to the destination
+ * {@link Dimension}, maintaining the aspect ratio with respect to
+ * the best fit.
+ *
+ * @param src The original vector graphic dimensions to change.
+ * @param dst The desired image dimensions to scale.
+ * @return The given source dimensions scaled to the destination dimensions,
+ * maintaining the aspect ratio.
+ */
+ private Dimension fit( 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;
- }
+ // Determine the ratio that will have the best fit.
+ final var ratio = Math.min(
+ dst.getWidth() / srcWidth, dst.getHeight() / srcHeight
+ );
- return new Dimension( (int) newWidth, (int) newHeight );
+ // Scale both dimensions with respect to the best fit ratio.
+ return new Dimension( (int) (srcWidth * ratio), (int) (srcHeight * ratio) );
}
}
src/main/com/whitemagicsoftware/kmcaster/listeners/FrameDragListener.java
import java.awt.event.MouseEvent;
+/**
+ * Responsible for moving the window when the user drags it around the screen.
+ */
public class FrameDragListener extends MouseAdapter {
private final JFrame mFrame;
src/main/com/whitemagicsoftware/kmcaster/listeners/KeyboardListener.java
package com.whitemagicsoftware.kmcaster.listeners;
+import com.whitemagicsoftware.kmcaster.HardwareSwitch;
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.HashMap;
import java.util.Map;
-import static com.whitemagicsoftware.kmcaster.listeners.SwitchName.*;
+import static com.whitemagicsoftware.kmcaster.HardwareSwitch.*;
import static java.util.Map.entry;
-import static org.jnativehook.NativeInputEvent.*;
import static org.jnativehook.keyboard.NativeKeyEvent.getKeyText;
+/**
+ * Responsible for sending property change events when the keyboard state
+ * changes.
+ */
public class KeyboardListener implements NativeKeyListener {
- private final List<KeyboardModifier> mModifiers = List.of(
- new KeyboardModifier( KEY_ALT, ALT_MASK ),
- new KeyboardModifier( KEY_CTRL, CTRL_MASK ),
- new KeyboardModifier( KEY_SHIFT, SHIFT_MASK )
- );
-
@SuppressWarnings("RedundantTypeArguments")
private final static Map<Integer, String> KEY_CODES =
);
- private String mRegularHeld = "";
+ private final Map<HardwareSwitch, Boolean> mModifiers = new HashMap<>();
private final PropertyChangeSupport mDispatcher =
new PropertyChangeSupport( this );
+
+ private String mRegularHeld = "";
public KeyboardListener() {
+ mModifiers.put( KEY_ALT, false );
+ mModifiers.put( KEY_CTRL, false );
+ mModifiers.put( KEY_SHIFT, false );
}
// The key is regular iff its name does not match any modifier name.
- for( final var modifier : mModifiers ) {
- isModifier |= (modifier.isKeyName( n ) || modifier.isKeyName( o ));
+ for( final var key : mModifiers.keySet() ) {
+ isModifier |= (key.isName( n ) || key.isName( o ));
}
*/
private void updateModifiers( final NativeKeyEvent e ) {
- for( final var modifier : mModifiers ) {
- final boolean down = modifier.matches( e );
- tryFire( modifier.getKey(), modifier.isHeld(), down );
- modifier.setHeld( down );
+ for( final var key : mModifiers.keySet() ) {
+ final boolean down = key.isPressed( e.getModifiers() );
+ tryFire( key, mModifiers.get( key ), down );
+ mModifiers.put( key, down );
}
}
* @param n New property value.
*/
- private void tryFire( final SwitchName key, final String o, final String n ) {
+ private void tryFire( final HardwareSwitch key, final String o,
+ final String n ) {
if( !o.equals( n ) ) {
mDispatcher.firePropertyChange( key.toString(), o, n );
}
}
/**
- * Delegates to {@link #tryFire(SwitchName, String, String)} with {@link Boolean}
+ * Delegates to {@link #tryFire(HardwareSwitch, String, String)} with
+ * {@link Boolean}
* values as strings.
*
* @param key The name of the property that has changed.
* @param o Old property value.
* @param n New property value.
*/
- private void tryFire( final SwitchName key, final boolean o, final boolean n ) {
+ private void tryFire( final HardwareSwitch key, final boolean o,
+ final boolean n ) {
tryFire( key, Boolean.toString( o ), Boolean.toString( n ) );
}
src/main/com/whitemagicsoftware/kmcaster/listeners/KeyboardModifier.java
-/*
- * 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;
-
-/**
- * Responsible for tracking the state of modifier keys.
- */
-public class KeyboardModifier {
- private boolean mHeld;
- private final int mMask;
- private final SwitchName mKey;
-
- KeyboardModifier( final SwitchName key, final int mask ) {
- assert key != null;
-
- mKey = key;
- mMask = mask;
- }
-
- public boolean isKeyName( final String key ) {
- return getKey().isName( key );
- }
-
- public boolean isHeld() {
- return mHeld;
- }
-
- public void setHeld( final boolean held ) {
- mHeld = held;
- }
-
- public SwitchName getKey() {
- return mKey;
- }
-
- /**
- * 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;
- }
-
- public String toString() {
- return getKey().toString();
- }
-}
src/main/com/whitemagicsoftware/kmcaster/listeners/SwitchName.java
-/*
- * 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;
-
-/**
- * Used for compile-time binding between change listeners input events.
- */
-public enum SwitchName {
- KEY_ALT( "alt" ),
- KEY_CTRL( "ctrl" ),
- KEY_SHIFT( "shift" ),
- KEY_REGULAR( "regular" ),
- MOUSE_LEFT( "button 1" ),
- MOUSE_WHEEL( "button 2" ),
- MOUSE_RIGHT( "button 3" ),
- MOUSE_LR( "button 1-3" );
-
- private final String mName;
-
- SwitchName( final String name ) {
- mName = name;
- }
-
- public boolean isName( final String name ) {
- return mName.equalsIgnoreCase( name );
- }
-
- /**
- * Looks up the key that matches the given name, case-insensitively.
- *
- * @param name The name of the key to find in this enum.
- * @return The {@link SwitchName} object that matches the name.
- */
- public static SwitchName valueFrom( final String name ) {
- for( final var b : SwitchName.values() ) {
- if( b.isName( name ) ) {
- return b;
- }
- }
-
- return KEY_REGULAR;
- }
-
- @Override
- public String toString() {
- return mName;
- }
-}

Update SVG renderer, generalize resizing, add comments

Author DaveJarvis <email>
Date 2020-07-17 15:42:09 GMT-0700
Commit cc2f14b8dc109344f53960e6302f96160624e07b
Parent 27637a3
Delta 412 lines added, 596 lines removed, 184-line decrease