Initial commit
9
.gitignore
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
22
.idea/compiler.xml
generated
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.form" />
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.groovy" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
<entry name="!?*.aj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
3
.idea/copyright/profiles_settings.xml
generated
Normal file
@ -0,0 +1,3 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings default="" />
|
||||
</component>
|
6
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
20
.idea/gradle.xml
generated
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/libtlang" />
|
||||
<option value="$PROJECT_DIR$/mobile" />
|
||||
<option value="$PROJECT_DIR$/wear" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
22
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,22 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="AndroidLintGradleCompatible" enabled="false" level="ERROR" enabled_by_default="false" />
|
||||
<inspection_tool class="EmptyCatchBlock" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<option name="m_includeComments" value="true" />
|
||||
<option name="m_ignoreTestCases" value="true" />
|
||||
<option name="m_ignoreIgnoreParameter" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="EmptyFinallyBlock" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="EmptyTryBlock" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
|
||||
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="WeakerAccess" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="true" />
|
||||
<option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="true" />
|
||||
<option name="SUGGEST_PRIVATE_FOR_INNERS" value="false" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
7
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="PROJECT_PROFILE" value="Project Default" />
|
||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
33
.idea/misc.xml
generated
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
11
.idea/modules.xml
generated
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/ColoursByControl.iml" filepath="$PROJECT_DIR$/ColoursByControl.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/libtlang/libtlang.iml" filepath="$PROJECT_DIR$/libtlang/libtlang.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/mobile/mobile.iml" filepath="$PROJECT_DIR$/mobile/mobile.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/wear/wear.iml" filepath="$PROJECT_DIR$/wear/wear.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
12
.idea/runConfigurations.xml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
25
build.gradle
Normal file
@ -0,0 +1,25 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.1.3-2'
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.0-alpha5'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
17
gradle.properties
Normal file
@ -0,0 +1,17 @@
|
||||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx4G
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
#Sat Jul 01 20:00:00 CEST 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-milestone-1-all.zip
|
160
gradlew
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
90
gradlew.bat
vendored
Normal file
@ -0,0 +1,90 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
1
libtlang/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
8
libtlang/build.gradle
Normal file
@ -0,0 +1,8 @@
|
||||
apply plugin: 'java-library'
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
}
|
||||
|
||||
sourceCompatibility = "1.8"
|
||||
targetCompatibility = "1.8"
|
52
libtlang/src/main/java/net/tofvesson/libtlang/Compiler.java
Normal file
@ -0,0 +1,52 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public interface Compiler {
|
||||
byte[] compile(Routine<?> r);
|
||||
Instruction<?> load(byte[] b);
|
||||
|
||||
class DefaultCompiler implements Compiler{
|
||||
|
||||
protected static final byte[] LID = "tfvsnlng".getBytes();
|
||||
protected long CID = 0b00100100;
|
||||
|
||||
@Override
|
||||
public byte[] compile(Routine<?> r) {
|
||||
List<Byte> build = new ArrayList<>();
|
||||
for(byte b : LID) build.add(b);
|
||||
for(byte b : split(CID)) build.add(b);
|
||||
|
||||
|
||||
|
||||
byte[] b = new byte[build.size()];
|
||||
for(int i = 0; i<b.length; ++i) b[i] = build.get(i);
|
||||
return b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instruction<?> load(byte[] b) {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected byte[] split(long l){
|
||||
return new byte[]{
|
||||
(byte)(l&0xFF),
|
||||
(byte)((l>>8)&0xFF),
|
||||
(byte)((l>>16)&0xFF),
|
||||
(byte)((l>>24)&0xFF),
|
||||
(byte)((l>>32)&0xFF),
|
||||
(byte)((l>>40)&0xFF),
|
||||
(byte)((l>>48)&0xFF),
|
||||
(byte)(l>>56)
|
||||
};
|
||||
}
|
||||
protected long combine(byte[] b){
|
||||
int size = Math.min(b.length, 8);
|
||||
long out = 0;
|
||||
for(int i = 0; i<size; ++i) out += b[i] << i*8;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
public enum ConditionOp implements Instruction {
|
||||
EQU{
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Object.class, Object.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
return (params[0]==null && params[1]==null) || (params[0]!=null && params[0].equals(params[1])) || (params[1]!=null && params[1].equals(params[0]));
|
||||
}
|
||||
}, NOT{
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Boolean.class };
|
||||
}
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
return !((Boolean)params[0]);
|
||||
}
|
||||
}, OR{
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Boolean.class, Boolean.class };
|
||||
}
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
return ((Boolean)params[0]) || ((Boolean)params[1]);
|
||||
}
|
||||
}, AND{
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Boolean.class, Boolean.class };
|
||||
}
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
return ((Boolean)params[0]) && ((Boolean)params[1]);
|
||||
}
|
||||
}, XOR{
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Boolean.class, Boolean.class };
|
||||
}
|
||||
@Override
|
||||
public Boolean eval(Routine s, Object... params) {
|
||||
return ((Boolean)params[0]) ^ ((Boolean)params[1]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@Override public final Class getReturnType() { return Boolean.class; }
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
public class DeclareVariable<T> implements Instruction {
|
||||
|
||||
protected final Variable<T> var;
|
||||
protected final String name;
|
||||
protected final T initialValue;
|
||||
|
||||
public DeclareVariable(String name, Class<T> type, T initialValue){
|
||||
var = new Variable<>(initialValue, type);
|
||||
this.name = name;
|
||||
this.initialValue = initialValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
if(s.vars.containsKey(name)) throw new ExecutionException(s.stackPointer, "Attempted to declare variable that already exists: "+name);
|
||||
var.handleSet(initialValue);
|
||||
s.vars.put(name, var);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public Class<?>[] getParamTypes() { return new Class<?>[0]; }
|
||||
@Override public Class getReturnType() { return Void.class; }
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
public class ExecutionException extends RuntimeException {
|
||||
public final int stackPointer;
|
||||
public ExecutionException(int stackPointer) { this.stackPointer = stackPointer; }
|
||||
public ExecutionException(int stackPointer, String message) { super(message); this.stackPointer = stackPointer; }
|
||||
public ExecutionException(int stackPointer, String message, Throwable cause) { super(message, cause); this.stackPointer = stackPointer;}
|
||||
public ExecutionException(int stackPointer, Throwable cause) { super(cause); this.stackPointer = stackPointer; }
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
public interface Instruction<T> { T eval(Routine<?> s, Object... params); Class<?>[] getParamTypes(); Class<T> getReturnType(); }
|
10
libtlang/src/main/java/net/tofvesson/libtlang/Label.java
Normal file
@ -0,0 +1,10 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
public class Label implements Instruction {
|
||||
protected String name;
|
||||
public Label(String name){ this.name = name; }
|
||||
@Override public Object eval(Routine s, Object... params) { return null; }
|
||||
@Override public Class<?>[] getParamTypes() { return new Class<?>[0]; }
|
||||
@Override public Class getReturnType() { return Void.class; }
|
||||
public String getName(){ return name; }
|
||||
}
|
53
libtlang/src/main/java/net/tofvesson/libtlang/MathOp.java
Normal file
@ -0,0 +1,53 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
public enum MathOp implements Instruction<Double> {
|
||||
ADD {
|
||||
@Override
|
||||
public Double evaluate(Double n1, Double n2) {
|
||||
return n1 + n2;
|
||||
}
|
||||
}, SUB {
|
||||
@Override
|
||||
public Double evaluate(Double n1, Double n2) {
|
||||
return n1 - n2;
|
||||
}
|
||||
}, MUL {
|
||||
@Override
|
||||
public Double evaluate(Double n1, Double n2) {
|
||||
return n1 * n2;
|
||||
}
|
||||
}, DIV {
|
||||
@Override
|
||||
public Double evaluate(Double n1, Double n2) {
|
||||
return n1 / n2;
|
||||
}
|
||||
}, POW {
|
||||
@Override
|
||||
public Double evaluate(Double n1, Double n2) {
|
||||
return Math.pow(n1, n2);
|
||||
}
|
||||
}, MOD {
|
||||
@Override
|
||||
public Double evaluate(Double n1, Double n2) {
|
||||
return n1 % n2;
|
||||
}
|
||||
};
|
||||
|
||||
public abstract Double evaluate(Double n1, Double n2);
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{Number.class, Number.class};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Double> getReturnType() {
|
||||
return Double.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double eval(Routine<?> s, Object... params) {
|
||||
//noinspection unchecked
|
||||
return evaluate(((Number) params[0]).doubleValue(), ((Number) params[1]).doubleValue());
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
public class RetroGenGoto implements Instruction {
|
||||
|
||||
final Label link;
|
||||
|
||||
public RetroGenGoto(){ this.link = new Label(""); }
|
||||
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
for(int i = 0 ; i<s.set.size(); ++i) if(s.set.get(i)==link){ s.stackPointer = i; break; }
|
||||
if(((Boolean) params[0])) s.operands.clear();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Boolean.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getReturnType() {
|
||||
return Void.class;
|
||||
}
|
||||
|
||||
public void retrogen(Routine<?> r){
|
||||
Stack<Character> s = new Stack<>();
|
||||
s.push((char)0);
|
||||
String genName;
|
||||
OUTER:
|
||||
do{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(Character c : s) sb.append(c);
|
||||
genName = sb.toString();
|
||||
for(int i = 0; i < r.set.size(); ++i)
|
||||
if(r.set.get(i)==link) break;
|
||||
else if(r.set.get(i) instanceof Label && ((Label)r.set.get(i)).name.equals(genName)){
|
||||
boolean next = true;
|
||||
for(int j = 0; j < s.size(); ++j)
|
||||
if(next){
|
||||
char c = s.get(j);
|
||||
if(++c != 0) next = false;
|
||||
s.set(j, c);
|
||||
}else break;
|
||||
if(next) s.push((char)0);
|
||||
continue OUTER;
|
||||
}
|
||||
link.name = genName;
|
||||
break;
|
||||
}while(true);
|
||||
}
|
||||
}
|
201
libtlang/src/main/java/net/tofvesson/libtlang/Routine.java
Normal file
@ -0,0 +1,201 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
public class Routine<T> implements Instruction<T> {
|
||||
|
||||
protected final Class<T> returnType;
|
||||
protected final Class<?>[] paramTypes;
|
||||
|
||||
protected boolean retroNames = false;
|
||||
|
||||
protected int stackPointer = 0;
|
||||
protected List<Instruction<?>> set = new ArrayList<>();
|
||||
protected HashMap<String, Variable<?>> vars = new HashMap<>();
|
||||
protected Stack<Object> operands = new Stack<>();
|
||||
protected boolean strictOperands = true;
|
||||
|
||||
public Routine(Class<T> returnType, Class<?>... paramTypes){ this.returnType = returnType; this.paramTypes = paramTypes; }
|
||||
|
||||
@Override
|
||||
public T eval(Routine<?> s, Object... params) {
|
||||
for(int i = 0; i<params.length; ++i) set.add(0, new DeclareVariable<>("$"+i, Object.class, params[i]));
|
||||
operands.clear();
|
||||
if(!retroNames){
|
||||
for(int i = 0; i<set.size(); ++i) if(set.get(i) instanceof RetroGenGoto) ((RetroGenGoto)set.get(i)).retrogen(this);
|
||||
retroNames = true;
|
||||
}
|
||||
Instruction<?> i;
|
||||
for(stackPointer = 0; stackPointer < set.size(); ++stackPointer){
|
||||
Object o = (i=set.get(stackPointer)).eval(this, popOpStack(i.getParamTypes()));
|
||||
if(i.getReturnType()!=Void.class) pushOpStack(o);
|
||||
}
|
||||
vars.clear();
|
||||
if(strictOperands && ((returnType==Void.class && operands.size()!=0)||
|
||||
(returnType!=Void.class && operands.size()>1)||
|
||||
(returnType!=Void.class && operands.peek()!=null && !returnType.isAssignableFrom(operands.peek().getClass()))))
|
||||
throw new RuntimeException("Unclean operand stack at end of routine: "+ Arrays.toString(operands.toArray()));
|
||||
List<DeclareVariable<?>> idx = new ArrayList<>();
|
||||
for(int j = 0; j<params.length; ++j)
|
||||
for(int k = 0; k<set.size(); ++k)
|
||||
if(set.get(k) instanceof DeclareVariable && ((DeclareVariable<?>)set.get(k)).name.equals("$"+j))
|
||||
idx.add((DeclareVariable<?>) set.get(k));
|
||||
set.removeAll(idx);
|
||||
//noinspection unchecked
|
||||
return returnType==Void.class ? null : operands.size() == 0 ? null : (T) operands.pop();
|
||||
}
|
||||
|
||||
public T eval(){ return eval(null); }
|
||||
|
||||
protected Object[] popOpStack(Class<?>[] operandTypes){
|
||||
if(operandTypes.length>operands.size()) throw new ExecutionException(stackPointer, "Operand stack underflow (Operator stack pointer value: "+stackPointer+")");
|
||||
Object o;
|
||||
for(int i = 0; i < operandTypes.length; ++i)
|
||||
if(((o=operands.get(operands.size()-i-1))==null && operandTypes[i]==Number.class)
|
||||
|| (o!=null && !operandTypes[i].isAssignableFrom(o.getClass()) && !Number.class.isAssignableFrom(operandTypes[i]) && !String.class.isAssignableFrom(operandTypes[i])))
|
||||
throw new ExecutionException(stackPointer, "Parameter mismatch for routine eval: "+Arrays.toString(operands.toArray()));
|
||||
Object[] o1 = new Object[operandTypes.length];
|
||||
for(int i = 0; i < operandTypes.length; ++i)
|
||||
o1[i] = String.class==operandTypes[i] ? String.valueOf(operands.pop()) :
|
||||
Number.class.isAssignableFrom(operandTypes[i]) ? Double.parseDouble(String.valueOf(operands.pop())) : operands.pop();
|
||||
return o1;
|
||||
}
|
||||
|
||||
protected void pushOpStack(Object v){ operands.push(v); }
|
||||
|
||||
public void pushMath(MathOp op, String var1, String var2){
|
||||
loadVar(var1);
|
||||
loadVar(var2);
|
||||
set.add(op);
|
||||
}
|
||||
|
||||
public void pushMath(MathOp op, Number var1, String var2){
|
||||
set.add(new StackPush(var1));
|
||||
loadVar(var2);
|
||||
set.add(op);
|
||||
}
|
||||
|
||||
public void pushMath(MathOp op, String var1, Number var2){
|
||||
loadVar(var1);
|
||||
set.add(new StackPush(var2));
|
||||
set.add(op);
|
||||
}
|
||||
|
||||
public void pushMath(MathOp op, Number var1, Number var2){
|
||||
set.add(new StackPush(var1));
|
||||
set.add(new StackPush(var2));
|
||||
set.add(op);
|
||||
}
|
||||
|
||||
public void pushMath(MathOp op, Routine<? extends Number> var1, String var2){
|
||||
set.add(var1);
|
||||
loadVar(var2);
|
||||
set.add(op);
|
||||
}
|
||||
|
||||
public void pushMath(MathOp op, String var1, Routine<? extends Number> var2){
|
||||
loadVar(var1);
|
||||
set.add(var2);
|
||||
set.add(op);
|
||||
}
|
||||
|
||||
public void pushMath(MathOp op, Routine<? extends Number> var1, Routine<? extends Number> var2){
|
||||
set.add(var1);
|
||||
set.add(new StackPush(var2));
|
||||
set.add(op);
|
||||
}
|
||||
|
||||
public void pushMath(MathOp op, Routine<? extends Number> var1, Number var2){
|
||||
set.add(var1);
|
||||
set.add(new StackPush(var2));
|
||||
set.add(op);
|
||||
}
|
||||
|
||||
public void pushMath(MathOp op, Number var1, Routine<? extends Number> var2){
|
||||
set.add(new StackPush(var1));
|
||||
set.add(var2);
|
||||
set.add(op);
|
||||
}
|
||||
|
||||
public void pushPop(int maxPopCount){
|
||||
set.add(new StackPush(maxPopCount));
|
||||
set.add(StandardOps.StackPop);
|
||||
}
|
||||
|
||||
public void pushPop(String maxPopCount){
|
||||
loadVar(maxPopCount);
|
||||
set.add(StandardOps.StackPop);
|
||||
}
|
||||
|
||||
public void pushPop(){ pushPop(1); }
|
||||
|
||||
public void loadVar(String var){
|
||||
set.add(new StackPush(var));
|
||||
set.add(StandardOps.LoadVar);
|
||||
set.add(StandardOps.ReadVar);
|
||||
}
|
||||
|
||||
public void storeVal(String var, Object val){
|
||||
set.add(new StackPush(var));
|
||||
set.add(StandardOps.LoadVar);
|
||||
set.add(new StackPush(val));
|
||||
set.add(StandardOps.StoreVar);
|
||||
}
|
||||
|
||||
public void gotoLabel(String name, boolean clearOperands){
|
||||
set.add(new StackPush(clearOperands));
|
||||
set.add(new StackPush(name));
|
||||
set.add(StandardOps.GOTO);
|
||||
}
|
||||
|
||||
public <V> void condition(V _true, V _false){
|
||||
set.add(StandardOps.Condition);
|
||||
RetroGenGoto t = new RetroGenGoto();
|
||||
set.add(new StackPush(_true));
|
||||
set.add(new StackPush(false));
|
||||
set.add(t);
|
||||
set.add(new StackPush(_false));
|
||||
set.add(t.link);
|
||||
}
|
||||
|
||||
public void gotoLabel(String name){ gotoLabel(name, true); }
|
||||
|
||||
public void add(Instruction<?> i){ set.add(i); }
|
||||
|
||||
public void print(int output){
|
||||
set.add(new StackPush(0));
|
||||
set.add(StandardOps.Debug);
|
||||
}
|
||||
|
||||
public void print(String s, int output){
|
||||
set.add(new StackPush(s));
|
||||
set.add(new StackPush(output));
|
||||
set.add(StandardOps.Debug);
|
||||
}
|
||||
|
||||
public void inline(Routine<?> r){
|
||||
r.strictOperands = false;
|
||||
r.operands = operands; // Simulate inline actions (as if it were run in the same routine)
|
||||
set.add(r);
|
||||
}
|
||||
|
||||
public void swapStack(int idx1, int idx2){
|
||||
set.add(new StackPush(idx1));
|
||||
set.add(new StackPush(idx2));
|
||||
set.add(StandardOps.StackSwap);
|
||||
}
|
||||
|
||||
List<Instruction<?>> getSet(){ return set; }
|
||||
HashMap<String, Variable<?>> getVars(){ return vars; }
|
||||
Stack<Object> getOperands(){ return operands; }
|
||||
public int getStackPointer(){ return stackPointer; }
|
||||
int setStackPointer(int newVal){ return stackPointer = newVal; }
|
||||
|
||||
@Override public Class<?>[] getParamTypes() { return paramTypes; }
|
||||
|
||||
@Override public Class<T> getReturnType() { return returnType; }
|
||||
}
|
25
libtlang/src/main/java/net/tofvesson/libtlang/StackPush.java
Normal file
@ -0,0 +1,25 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
public class StackPush implements Instruction {
|
||||
|
||||
protected final Object item;
|
||||
|
||||
public StackPush(Object o){ item = o; }
|
||||
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
//noinspection unchecked
|
||||
s.operands.push(item);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getReturnType() {
|
||||
return Void.class;
|
||||
}
|
||||
}
|
142
libtlang/src/main/java/net/tofvesson/libtlang/StandardOps.java
Normal file
@ -0,0 +1,142 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public enum StandardOps implements Instruction {
|
||||
Condition{
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
if(!((Boolean) params[0])) s.stackPointer+=3;
|
||||
return null;
|
||||
}
|
||||
@Override public Class<?>[] getParamTypes() { return new Class<?>[]{ Boolean.class }; }
|
||||
@Override public Class getReturnType() { return Void.class; }
|
||||
},
|
||||
Debug{
|
||||
@Override
|
||||
public Void eval(Routine s, Object... params) {
|
||||
(((Number) params[0]).intValue()%2 == 0 ? System.out : System.err).println(String.valueOf(params[1]));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Number.class, Object.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Void> getReturnType() {
|
||||
return Void.class;
|
||||
}
|
||||
},
|
||||
GOTO{
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
Instruction t;
|
||||
for(int i =0 ; i<s.set.size(); ++i) if((t=(Instruction) s.set.get(i)) instanceof Label && ((Label)t).getName().equals(params[0])){ s.stackPointer = i; break; }
|
||||
if(((Boolean) params[1])) s.operands.clear();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ String.class, Boolean.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getReturnType() {
|
||||
return Void.class;
|
||||
}
|
||||
},
|
||||
LoadVar{
|
||||
@Override
|
||||
public Variable<?> eval(Routine s, Object... params) {
|
||||
for(String n : (Set<String>) s.vars.keySet()) if(n == params[0] || (n != null && n.equals(params[0]))) return (Variable<?>) s.vars.get(n);
|
||||
throw new ExecutionException(s.stackPointer, "Couldn't find any variable called "+params[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ String.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getReturnType() {
|
||||
return Variable.class;
|
||||
}
|
||||
},
|
||||
StoreVar{
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
((Variable<?>)params[1]).handleSet(params[0]);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Object.class, Variable.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getReturnType() {
|
||||
return Void.class;
|
||||
}
|
||||
},
|
||||
ReadVar{
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
return ((Variable<?>) params[0]).getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Variable.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getReturnType() {
|
||||
return Object.class;
|
||||
}
|
||||
},
|
||||
StackPop{
|
||||
@Override
|
||||
public Object eval(Routine s, Object... params) {
|
||||
for(int i = Math.min(((Number)params[0]).intValue(), s.operands.size()); i>0; --i) s.operands.pop();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Number.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getReturnType() {
|
||||
return Void.class;
|
||||
}
|
||||
},
|
||||
NOP{
|
||||
@Override public Class<?>[] getParamTypes() { return new Class<?>[0]; }
|
||||
@Override public Class getReturnType() { return Void.class; }
|
||||
@Override public Object eval(Routine s, Object... params) { return null; }
|
||||
},
|
||||
DUP{
|
||||
@Override public Class<?>[] getParamTypes() { return new Class<?>[0]; }
|
||||
@Override public Class getReturnType() { return Object.class; }
|
||||
@Override public Object eval(Routine s, Object... params) { return s.operands.peek(); }
|
||||
},
|
||||
StackSwap{
|
||||
@Override public Class<?>[] getParamTypes() { return new Class<?>[]{ Number.class, Number.class }; }
|
||||
@Override public Class getReturnType() { return Void.class; }
|
||||
@Override public Object eval(Routine s, Object... params) {
|
||||
int i1 = s.operands.size()-1-((Number)params[0]).intValue(), i2 = s.operands.size()-1-((Number)params[1]).intValue();
|
||||
Object o = s.operands.get(i1);
|
||||
//noinspection unchecked
|
||||
s.operands.set(i1, s.operands.get(i2));
|
||||
//noinspection unchecked
|
||||
s.operands.set(i2, o);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
public class StringAppend implements Instruction<String> {
|
||||
|
||||
protected final boolean paramOrder;
|
||||
|
||||
public StringAppend(boolean paramOrder){ this.paramOrder = paramOrder; }
|
||||
public StringAppend(){ this(true); }
|
||||
|
||||
@Override
|
||||
public String eval(Routine s, Object... params) {
|
||||
return String.valueOf(params[paramOrder?1:0]) + params[paramOrder?0:1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getParamTypes() {
|
||||
return new Class<?>[]{ Object.class, Object.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<String> getReturnType() {
|
||||
return String.class;
|
||||
}
|
||||
}
|
20
libtlang/src/main/java/net/tofvesson/libtlang/Variable.java
Normal file
@ -0,0 +1,20 @@
|
||||
package net.tofvesson.libtlang;
|
||||
|
||||
public class Variable<T>{
|
||||
|
||||
protected T value;
|
||||
protected final Class<T> type;
|
||||
|
||||
public Variable(T t, Class<T> type){
|
||||
this.type = type;
|
||||
handleSet(t);
|
||||
}
|
||||
public Variable( Class<T> type){ this(null, type); }
|
||||
|
||||
public void handleSet(Object value){
|
||||
if(value!=null && !type.isAssignableFrom(value.getClass())) throw new RuntimeException("Variable assignment type mismatch: "+value);
|
||||
this.value = (T) (Number.class.isAssignableFrom(type) && value==null ? 0 : (value instanceof Number && Number.class.isAssignableFrom(type)) ? ((Number) value).doubleValue() : value);
|
||||
}
|
||||
|
||||
public T getValue(){ return value; }
|
||||
}
|
1
mobile/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
46
mobile/CMakeLists.txt
Normal file
@ -0,0 +1,46 @@
|
||||
# For more information about using CMake with Android Studio, read the
|
||||
# documentation: https://d.android.com/studio/projects/add-native-code.html
|
||||
|
||||
# Sets the minimum version of CMake required to build the native library.
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
|
||||
# Creates and names a library, sets it as either STATIC
|
||||
# or SHARED, and provides the relative paths to its source code.
|
||||
# You can define multiple libraries, and CMake builds them for you.
|
||||
# Gradle automatically packages shared libraries with your APK.
|
||||
|
||||
add_library(lib-tlang SHARED src/main/cpp/lib-tlang.cpp)
|
||||
add_library(lib-tlang-cbc SHARED src/main/cpp/lib-tlang-cbc.cpp)
|
||||
|
||||
#add_library( # Sets the name of the library.
|
||||
# native-lib
|
||||
#
|
||||
# # Sets the library as a shared library.
|
||||
# SHARED
|
||||
#
|
||||
# # Provides a relative path to your source file(s).
|
||||
# src/main/cpp/native-lib.cpp )
|
||||
## Searches for a specified prebuilt library and stores the path as a
|
||||
## variable. Because CMake includes system libraries in the search path by
|
||||
## default, you only need to specify the name of the public NDK library
|
||||
## you want to add. CMake verifies that the library exists before
|
||||
## completing its build.
|
||||
#
|
||||
#find_library( # Sets the name of the path variable.
|
||||
# log-lib
|
||||
#
|
||||
# # Specifies the name of the NDK library that
|
||||
# # you want CMake to locate.
|
||||
# log )
|
||||
#
|
||||
## Specifies libraries CMake should link to your target library. You
|
||||
## can link multiple libraries, such as libraries you define in this
|
||||
## build script, prebuilt third-party libraries, or system libraries.
|
||||
#
|
||||
#target_link_libraries( # Specifies the target library.
|
||||
# native-lib
|
||||
#
|
||||
# # Links the target library to the log library
|
||||
# # included in the NDK.
|
||||
# ${log-lib} )
|
55
mobile/build.gradle
Normal file
@ -0,0 +1,55 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion '26.0.0'
|
||||
defaultConfig {
|
||||
applicationId "net.tofvesson.coloursbycontrol"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 26
|
||||
versionCode 4
|
||||
versionName "1.3"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
cppFlags "-std=c++11 -fexceptions"
|
||||
}
|
||||
}
|
||||
vectorDrawables.useSupportLibrary true
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
path "CMakeLists.txt"
|
||||
}
|
||||
}
|
||||
//dexOptions.preDexLibraries false
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(include: ['*.jar'], dir: 'libs')
|
||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
})
|
||||
//wearApp project(':wear')
|
||||
compile project(":libtlang")
|
||||
compile 'com.google.android.gms:play-services-wearable:11.0.2'
|
||||
compile 'com.android.support:appcompat-v7:25.3.1'
|
||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
compile 'com.android.support:design:25.3.1'
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
BIN
mobile/mobile-release.apk
Normal file
25
mobile/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in E:\Users\Gabriel\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
@ -0,0 +1,26 @@
|
||||
package net.tofvesson.coloursbycontrol;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumentation test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("net.tofvesson.coloursbycontrol", appContext.getPackageName());
|
||||
}
|
||||
}
|
29
mobile/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="net.tofvesson.coloursbycontrol">
|
||||
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppThemeLight">
|
||||
<activity
|
||||
android:name=".activity.MainActivity"
|
||||
android:theme="@style/WelcomeLight">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.ScrollingActivity"
|
||||
android:label="Project"
|
||||
android:theme="@style/AppThemeLight"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
1
mobile/src/main/cpp/lib-tlang-cbc.cpp
Normal file
@ -0,0 +1 @@
|
||||
// Add bindings to app/activity here
|
0
mobile/src/main/cpp/lib-tlang.cpp
Normal file
9
mobile/src/main/cpp/lib-tlang.h
Normal file
@ -0,0 +1,9 @@
|
||||
#include <math.h>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
#ifndef COLOURSBYCONTROL_LIB_TLANG_H
|
||||
#define COLOURSBYCONTROL_LIB_TLANG_H
|
||||
#endif //COLOURSBYCONTROL_LIB_TLANG_H
|
0
mobile/src/main/cpp/native-lib.cpp
Normal file
285
mobile/src/main/java/net/tofvesson/coloursbycontrol/CodeCtx.kt
Normal file
@ -0,0 +1,285 @@
|
||||
package net.tofvesson.coloursbycontrol
|
||||
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.experimental.and
|
||||
|
||||
class CodeCtx(ctxName: String, const: Array<String>, code: ByteArray): Operation{
|
||||
val name = ctxName
|
||||
val vars = HashMap<String, Any?>()
|
||||
val pairedCalls = ArrayList<Pair<Int, Byte>>()
|
||||
val operands = Stack<Any?>()
|
||||
val operators = ArrayList<Operations>()
|
||||
val hasReturn = !(code.isEmpty() || ((code[0] and -128).toInt() ushr 7) == 0)
|
||||
val paramCount = if(code.isEmpty()) 0 else code[0] and 0b01111111
|
||||
val constants = const
|
||||
var stackPointer = -1
|
||||
var popFlag = false
|
||||
var isRunning = false
|
||||
|
||||
private constructor(ctxName: String, const: Array<String>, op: ArrayList<Operations>, pC: ArrayList<Pair<Int, Byte>>) : this(ctxName, const, kotlin.ByteArray(0)) {
|
||||
operators.addAll(op)
|
||||
for((i, b) in pC) pairedCalls.add(Pair(i, b))
|
||||
}
|
||||
|
||||
init{
|
||||
var first = true
|
||||
var paired = 0
|
||||
for(b in code){
|
||||
if(!first){
|
||||
if(paired>0){
|
||||
pairedCalls.add(Pair(operators.size-1, b))
|
||||
--paired
|
||||
}else{
|
||||
val o = Operations.values()[b.toInt()]
|
||||
paired = o.getPairCount()
|
||||
operators.add(o)
|
||||
}
|
||||
}
|
||||
first = false
|
||||
}
|
||||
var v = paramCount+1
|
||||
while(--v!=0) vars.put(v.toString(), null)
|
||||
}
|
||||
|
||||
override fun hasReturnValue(): Boolean = hasReturn
|
||||
override fun getParamCount(): Int = paramCount.toInt()
|
||||
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? {
|
||||
if(isRunning) return loadContext(stack, name).eval(stack, params) // Prevent errors with multi-threading or self-referencing code
|
||||
isRunning = true
|
||||
stack.push(this)
|
||||
if(params.size > paramCount) throw exception(stack, "Context given too many parameters!")
|
||||
params.forEachIndexed { index, it -> vars[index.toString()] = it }
|
||||
while (stackPointer<operators.size-1){
|
||||
val o = operators[++stackPointer]
|
||||
val a = o.eval(stack, loadOperands(stack, o))
|
||||
if(o.hasReturnValue()) operands.push(a)
|
||||
if(popFlag) operands.pop()
|
||||
popFlag = false
|
||||
}
|
||||
stack.pop()
|
||||
val v = if(hasReturn) operands.pop() else null
|
||||
operands.clear()
|
||||
stackPointer = -1
|
||||
isRunning = false
|
||||
return v
|
||||
}
|
||||
|
||||
private fun loadOperands(stack: Stack<CodeCtx>, op: Operations): Array<Any?> {
|
||||
if(op.getParamCount()>operands.size) throw exception(stack, "Operand stack underflow!")
|
||||
return Array(op.getParamCount() + op.getPairCount(), {
|
||||
if(it<op.getParamCount()) operands.pop() else loadPairedVal(stack, it-op.getParamCount(), stackPointer)
|
||||
})
|
||||
}
|
||||
|
||||
private fun loadPairedVal(stack: Stack<CodeCtx>, which: Int, atStack: Int): Byte{
|
||||
var count = 0
|
||||
for((first, second) in pairedCalls)
|
||||
if(first == atStack){
|
||||
if(count==which) return second
|
||||
else ++count
|
||||
}
|
||||
throw exception(stack, "Can't load paired call value $which from $atStack!")
|
||||
}
|
||||
|
||||
fun loadContext(stack: Stack<CodeCtx>, ctxName: String): CodeCtx {
|
||||
// TODO: Make better 'n load from files 'n other stuff
|
||||
if(ctxName == name) return CodeCtx(name, constants, operators, pairedCalls)
|
||||
else throw exception(stack, "Could not find any context called \"$ctxName\"!") // TODO: Do search for other contexts
|
||||
}
|
||||
override fun toString(): String = "Context{name=$name, pointer=$stackPointer ("+operators[stackPointer].name+")}"
|
||||
}
|
||||
|
||||
interface Operation{
|
||||
fun hasReturnValue(): Boolean
|
||||
fun getParamCount(): Int
|
||||
fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any?
|
||||
}
|
||||
|
||||
infix fun <K, V> HashMap<K, V>.containsKeyI(key: K) = contains(key)
|
||||
fun Any?.asBoolean(): Boolean =
|
||||
if(this==null) false else this as? Boolean ?: if((this.toString() == "true") or (this.toString() == "false")) this.toString().toBoolean() else !((this.toString()=="0") or (this.toString()=="0.0"))
|
||||
fun Any?.asDouble(): Double = if(this==null) 0.0 else (this as? Number ?: try{ this.toString().toDouble() }catch(e: NumberFormatException){ 0.0 }).toDouble()
|
||||
|
||||
fun exception(stack: Stack<CodeCtx>, reason: String?): RuntimeException =
|
||||
RuntimeException((reason ?: "")+" Trace: "+Arrays.toString(stack.toArray())+
|
||||
(if(stack.size>0) " at "+stack[stack.size-1].operators[stack[stack.size-1].stackPointer].ordinal+" ("+stack[stack.size-1].operators[stack[stack.size-1].stackPointer].name+")" else ""))
|
||||
|
||||
enum class Operations: Operation{
|
||||
LDV{ // Load variable
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 1
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? {
|
||||
var i = stack.size-1
|
||||
while(i!=-1){
|
||||
if(stack[i].vars containsKeyI params[0].toString()){
|
||||
return stack[i].vars[params[0].toString()]
|
||||
}
|
||||
--i
|
||||
}
|
||||
throw exception(stack, "Variable \""+params[0]+"\" cannot be found!")
|
||||
}
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
STV{ // Store variable
|
||||
override fun hasReturnValue(): Boolean = false
|
||||
override fun getParamCount(): Int = 2
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): String? {
|
||||
var i = stack.size
|
||||
while(i!=-1){
|
||||
if(stack[i].vars containsKeyI params[0].toString()){
|
||||
stack[i].vars.put(params[0].toString(), params[1].toString())
|
||||
return null
|
||||
}
|
||||
--i
|
||||
}
|
||||
throw exception(stack, "Variable \""+params[0]+"\" cannot be found!")
|
||||
}
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
LDC{ // Load constant
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 0
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): String? = stack[stack.size-1].constants[params[0].asDouble().toInt()]
|
||||
override fun getPairCount(): Int = 1
|
||||
},
|
||||
EXT{ // Call external
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 2
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? {
|
||||
val m = Class.forName(params[0].toString()).getDeclaredMethod(params[1].toString(), Object::class.java)
|
||||
m.isAccessible = true
|
||||
stack[stack.size-1].popFlag = m.returnType==Void::class.java
|
||||
val static = (m.modifiers and 0x8) == 0
|
||||
val paramCount = m.parameterTypes.size + if(static) 0 else 1
|
||||
val caller = stack[stack.size-1]
|
||||
if(paramCount > caller.operands.size) throw exception(stack, "Operand stack underflow! Required parameter count: "+paramCount)
|
||||
val callee = if(static) null else caller.operands.pop()
|
||||
val v = Array(paramCount, { caller.operands.pop() })
|
||||
caller.popFlag = m.returnType == Void.TYPE
|
||||
return m.invoke(callee, v)
|
||||
}
|
||||
override fun getPairCount(): Int = 1
|
||||
},
|
||||
POP{ // Pop one operand
|
||||
override fun hasReturnValue(): Boolean = false
|
||||
override fun getParamCount(): Int = 1
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): String? = null
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
DCV{ // Declare variable
|
||||
override fun hasReturnValue(): Boolean = false
|
||||
override fun getParamCount(): Int = 2
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? {
|
||||
if(stack[stack.size-1].vars containsKeyI params[0].toString()) return null
|
||||
stack[stack.size-1].vars.put(params[0].toString(), params[1])
|
||||
return null
|
||||
}
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
CMP{ // Compare
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 2
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? = (params[0].toString() == params[1].toString()) or (if(params[0]==null) params[1]==null else params[0]?.equals(params[1]) as Boolean)
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
LNT{ // Logical NOT
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 1
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? = !params[0].asBoolean()
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
LOR{ // Logical OR
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 2
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? = params[0].asBoolean() or params[1].asBoolean()
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
CND{ // Conditional Jump (false = jump 2, true = no jump)
|
||||
override fun hasReturnValue(): Boolean = false
|
||||
override fun getParamCount(): Int = 1
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? = if(!params[0].asBoolean()) stack[stack.size-1].stackPointer+=2 else 0
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
JMP{ // Unconditional jump (1 operand)
|
||||
override fun hasReturnValue(): Boolean = false
|
||||
override fun getParamCount(): Int = 2
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any?{
|
||||
stack[stack.size-1].stackPointer = (if(params[0].asBoolean()) stack[stack.size-1].stackPointer else 0) + params[1].asDouble().toInt()
|
||||
return null
|
||||
}
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
CALL{ // Call context
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 1
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? {
|
||||
val caller = stack[stack.size-1]
|
||||
val ctx = caller.loadContext(stack, params[0].toString())
|
||||
if(ctx.getParamCount() > caller.operands.size) throw exception(stack, "Operand stack underflow! Required parameter count: "+ctx.getParamCount())
|
||||
caller.popFlag = !ctx.hasReturn
|
||||
return ctx.eval(stack, Array(ctx.getParamCount(), { caller.operands.pop() }))
|
||||
}
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
LDN{ // Load constant number
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 0
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? = params[0]
|
||||
override fun getPairCount(): Int = 1
|
||||
},
|
||||
CJP{ // Constant jump (unconditional, no operands)
|
||||
override fun hasReturnValue(): Boolean = false
|
||||
override fun getParamCount(): Int = 0
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? {
|
||||
stack[stack.size-1].stackPointer += params[0].asDouble().toInt()
|
||||
return null
|
||||
}
|
||||
override fun getPairCount(): Int = 1
|
||||
},
|
||||
VLD{ // Constant load from variable (load constant based on value of variable)
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 1
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? = stack[stack.size-1].constants[params[0].asDouble().toInt()]
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
NOP{ // No operation
|
||||
override fun hasReturnValue(): Boolean = false
|
||||
override fun getParamCount(): Int = 0
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? = null
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
INC{ // Increment variable
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 1
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? = params[0].asDouble() + 1
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
DEC { // Decrement variable
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 1
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? = params[0].asDouble() - 1
|
||||
override fun getPairCount(): Int = 0
|
||||
},
|
||||
LOP{ // Logical operation
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 2
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? =
|
||||
if(params[2]==0) params[0].asDouble() + params[1].asDouble()
|
||||
else if(params[2]==1) params[0].asDouble() - params[1].asDouble()
|
||||
else if(params[2]==2) params[0].asDouble() * params[1].asDouble()
|
||||
else if(params[2]==3) params[0].asDouble() / params[1].asDouble()
|
||||
else if(params[2]==4) params[0].asDouble() % params[1].asDouble()
|
||||
else throw exception(stack, "Invalid operation "+params[2])
|
||||
override fun getPairCount(): Int = 1
|
||||
},
|
||||
DUP{ // Duplicate top operand
|
||||
override fun hasReturnValue(): Boolean = true
|
||||
override fun getParamCount(): Int = 1
|
||||
override fun eval(stack: Stack<CodeCtx>, params: Array<Any?>): Any? = stack[stack.size-1].operands.push(params[0])
|
||||
override fun getPairCount(): Int = 0
|
||||
};
|
||||
abstract fun getPairCount(): Int
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package net.tofvesson.coloursbycontrol.activity;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.View;
|
||||
|
||||
import net.tofvesson.coloursbycontrol.R;
|
||||
import net.tofvesson.coloursbycontrol.view.WelcomeView;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
//if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
|
||||
setContentView(R.layout.activity_main);
|
||||
((WelcomeView) findViewById(R.id.welcome)).setOnFinishedListener(new WelcomeView.OnWelcomeFinishedListener() {
|
||||
@Override
|
||||
public void onTriggerFinished(WelcomeView view) {
|
||||
view.triggerDraw();
|
||||
}
|
||||
}).triggerDraw();
|
||||
findViewById(R.id.newProj).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
startActivity(new Intent(getApplicationContext(), ScrollingActivity.class));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package net.tofvesson.coloursbycontrol.activity;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
import net.tofvesson.coloursbycontrol.CodeCtx;
|
||||
import net.tofvesson.coloursbycontrol.R;
|
||||
import net.tofvesson.coloursbycontrol.view.StackPushCard;
|
||||
import java.util.Stack;
|
||||
import static net.tofvesson.coloursbycontrol.Operations.*;
|
||||
|
||||
public class ScrollingActivity extends AppCompatActivity {
|
||||
|
||||
static{
|
||||
System.loadLibrary("lib-tlang");
|
||||
System.loadLibrary("lib-tlang-cbc");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_scrolling);
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
|
||||
System.out.println(void.class);
|
||||
|
||||
final CodeCtx ctx = new CodeCtx("RunMe",
|
||||
new String[]{ "Hello World", "makeText", Toast.class.getName(), "show" }, // Constant pool
|
||||
new byte[] // Instructions
|
||||
{
|
||||
-127 , // 10000001 (Return: true, Params: 1)
|
||||
12, 0,
|
||||
2, 0,
|
||||
12, 0,
|
||||
0,
|
||||
2, 1,
|
||||
2, 2,
|
||||
3, 3,
|
||||
2, 3,
|
||||
3, 0
|
||||
}
|
||||
);
|
||||
System.out.println(ctx.eval(new Stack<>(), new Object[]{ this }));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
final StackPushCard cnst = (StackPushCard) findViewById(R.id.stackPush);
|
||||
cnst.push = "Hello World";
|
||||
cnst.setOnClickListener(v -> {
|
||||
final Dialog d = new Dialog(new android.view.ContextThemeWrapper(ScrollingActivity.this, R.style.AppThemeLight));
|
||||
d.setContentView(R.layout.dialog_constant);
|
||||
d.setTitle("Constant value");
|
||||
if(cnst.push!=null) ((EditText) d.findViewById(R.id.newConst)).setText(String.valueOf(cnst.push));
|
||||
d.findViewById(R.id.cancel_action).setOnClickListener(v12 -> d.dismiss());
|
||||
d.findViewById(R.id.confirm_action).setOnClickListener(v1 -> {
|
||||
cnst.push = ((EditText) d.findViewById(R.id.newConst)).getText();
|
||||
d.dismiss();
|
||||
});
|
||||
d.show();
|
||||
});
|
||||
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
|
||||
fab.setOnClickListener(view -> {
|
||||
|
||||
});
|
||||
findViewById(R.id.fab1).setOnClickListener(v -> Toast.makeText(getApplicationContext(), "I'm going to analyze the defined stack to check whether or not there will be and error on execution", Toast.LENGTH_LONG).show());
|
||||
}
|
||||
|
||||
private static void toast(Object o){ ExternalData d = (ExternalData) o; Toast.makeText(d.ctx, d.message, Toast.LENGTH_SHORT).show(); }
|
||||
private static void snackbar(Object o){ ExternalData d = (ExternalData) o; Snackbar.make(d.ctx.findViewById(android.R.id.content), d.message, Snackbar.LENGTH_LONG).show(); }
|
||||
|
||||
static class ExternalData{ public String message; public Activity ctx; }
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.RectF;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class ActionCard extends ActionView {
|
||||
protected static final float rX = 16, rY = 9, cornerSharpness = 30; // Ratio
|
||||
protected float sRel;
|
||||
private Bitmap cardSurface;
|
||||
private Canvas cardDraw;
|
||||
private final RectF ovCard = new RectF();
|
||||
public ActionCard(Context c) { super(c); }
|
||||
public ActionCard(Context c, @Nullable AttributeSet a) { super(c, a); }
|
||||
public ActionCard(Context c, @Nullable AttributeSet a, int d) { super(c, a, d); }
|
||||
@android.support.annotation.RequiresApi(api = android.os.Build.VERSION_CODES.LOLLIPOP) public ActionCard(Context c, @Nullable AttributeSet a, int s, int r) { super(c, a, s, r); }
|
||||
|
||||
@SuppressLint("DrawAllocation")
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
int desiredWidth = (int) rX*10;
|
||||
int desiredHeight = (int) rY*10;
|
||||
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
boolean wDef = widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST, hDef = heightMode == MeasureSpec.EXACTLY || heightMode == MeasureSpec.AT_MOST;
|
||||
|
||||
if(wDef && !hDef) {
|
||||
width = widthSize;
|
||||
height = (int)(width * rY / rX);
|
||||
}else if(hDef && !wDef) {
|
||||
height = heightSize;
|
||||
width = (int)(height * rX / rY);
|
||||
}else if(hDef){
|
||||
width = widthSize;
|
||||
height = heightSize;
|
||||
}else{
|
||||
height = desiredHeight;
|
||||
width = desiredWidth;
|
||||
}
|
||||
|
||||
setMeasuredDimension(width, height);
|
||||
|
||||
if(cardSurface == null || cardSurface.getWidth() != getMeasuredWidth() || cardSurface.getHeight() != getMeasuredHeight()) {
|
||||
boolean verticalPad;
|
||||
float
|
||||
ratio = ((float)getMeasuredHeight()) / ((float)getMeasuredWidth()),
|
||||
ratioI = ((float)getMeasuredWidth()) / ((float)getMeasuredHeight()),
|
||||
iRY = rY * ratioI,
|
||||
padding = (verticalPad=iRY>rX)?getMeasuredWidth() - (rX*getMeasuredHeight()/rY) : getMeasuredHeight() - (rY*getMeasuredWidth()/rX);
|
||||
int x = (int) (((float)getMeasuredWidth())-(verticalPad?padding:0.0F)), y = (int) (((float)getMeasuredHeight()) - (verticalPad?0.0F:padding));
|
||||
cardSurface = Bitmap.createBitmap(x<=0?1:x, y<=0?1:y, Bitmap.Config.ARGB_8888);
|
||||
cardDraw = new Canvas(cardSurface);
|
||||
}
|
||||
}
|
||||
|
||||
private int autoDef(int size, int cT, int cN){
|
||||
return size * cN / cT;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SuspiciousNameCombination") // They don't know
|
||||
@Override
|
||||
public final void onDraw(Canvas canvas) {
|
||||
//if(cardDraw.getWidth()==1 || cardDraw.getHeight()==1) return; // View is impossibly small (probably off-screen or something) so just skip rendering
|
||||
|
||||
// Call pre-draw function in case something may need to be partially occluded
|
||||
preDraw(cardDraw);
|
||||
|
||||
// Clear everything
|
||||
cardDraw.drawColor(0);
|
||||
|
||||
// Draw actual card
|
||||
ovCard.left = 0;
|
||||
ovCard.top = 0;
|
||||
ovCard.right = cardDraw.getWidth()/cornerSharpness;
|
||||
ovCard.bottom = ovCard.right;
|
||||
|
||||
cardDraw.drawArc(ovCard, 180, 90, true, color);
|
||||
|
||||
ovCard.right = cardDraw.getWidth();
|
||||
ovCard.left = cardDraw.getWidth() - cardDraw.getWidth()/cornerSharpness;
|
||||
ovCard.top = 0;
|
||||
ovCard.bottom = cardDraw.getWidth()/cornerSharpness;
|
||||
|
||||
cardDraw.drawArc(ovCard, 270, 90, true, color);
|
||||
|
||||
ovCard.top = (ovCard.bottom = cardDraw.getHeight()) - cardDraw.getWidth()/cornerSharpness;
|
||||
|
||||
cardDraw.drawArc(ovCard, 0, 90, true, color);
|
||||
|
||||
ovCard.left = 0;
|
||||
ovCard.right = cardDraw.getWidth()/cornerSharpness;
|
||||
|
||||
cardDraw.drawArc(ovCard, 90, 90, true, color);
|
||||
|
||||
ovCard.top = ovCard.right/2F;
|
||||
|
||||
ovCard.bottom = cardDraw.getHeight() - ovCard.top;
|
||||
|
||||
cardDraw.drawRect(0, cardDraw.getWidth()/(2*cornerSharpness), cardDraw.getWidth()/cornerSharpness, cardDraw.getHeight()-cardDraw.getWidth()/(2*cornerSharpness), color);
|
||||
cardDraw.drawRect(cardDraw.getWidth()-cardDraw.getWidth()/(2*cornerSharpness), cardDraw.getWidth()/(2*cornerSharpness), cardDraw.getWidth(), cardDraw.getHeight()-cardDraw.getWidth()/(2*cornerSharpness), color);
|
||||
cardDraw.drawRect(cardDraw.getWidth()/(2*cornerSharpness), 0, cardDraw.getWidth()-cardDraw.getWidth()/(2*cornerSharpness), cardDraw.getHeight(), color);
|
||||
|
||||
// Let sub-classes draw class-specific items on top of card
|
||||
drawItems(cardDraw);
|
||||
|
||||
// Draw to actual canvas
|
||||
canvas.drawBitmap(cardSurface,(canvas.getWidth()-cardDraw.getWidth())/2, (canvas.getHeight()-cardDraw.getHeight())/2, null); // Draw bitmap with calculated padding
|
||||
|
||||
// Process whether or not view should be invalidated
|
||||
if(shouldUpdate()) invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw action-specific card items on top of card.
|
||||
* @param canvas Canvas to draw to
|
||||
*/
|
||||
protected abstract void drawItems (Canvas canvas);
|
||||
protected void preDraw (Canvas canvas){ }
|
||||
protected boolean shouldUpdate() { return false; }
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Paint;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import net.tofvesson.coloursbycontrol.R;
|
||||
import net.tofvesson.libtlang.Routine;
|
||||
|
||||
public abstract class ActionView extends View {
|
||||
protected final Paint color = new Paint(), backgroundColor = new Paint(), accentColor = new Paint(), textColor = new Paint(), errorColor = new Paint();
|
||||
public ActionView(Context c) { super(c); init(c, null, 0, 0); }
|
||||
public ActionView(Context c, @Nullable AttributeSet a) { super(c, a); init(c, a, 0, 0); }
|
||||
public ActionView(Context c, @Nullable AttributeSet a, int d) { super(c, a, d); init(c, a, d, 0); }
|
||||
@android.support.annotation.RequiresApi(api = android.os.Build.VERSION_CODES.LOLLIPOP) public ActionView(Context c, @Nullable AttributeSet a, int s, int r) { super(c, a, s, r); init(c, a, s, r); }
|
||||
private void init(Context ctx, AttributeSet set, int da, int dr){
|
||||
if(set==null){
|
||||
color.setColor(0xffffffff);
|
||||
backgroundColor.setColor(0xffffffff);
|
||||
accentColor.setColor(0xffffffff);
|
||||
textColor.setColor(0xffffffff);
|
||||
errorColor.setColor(0xffffffff);
|
||||
}
|
||||
else{
|
||||
TypedArray a = ctx.getTheme().obtainStyledAttributes(set, R.styleable.CustomVal, da, dr);
|
||||
try {
|
||||
color.setColor(a.getColor(R.styleable.CustomVal_color, 0xffffffff));
|
||||
backgroundColor.setColor(a.getColor(R.styleable.CustomVal_backgroundColor, 0xffffffff));
|
||||
accentColor.setColor(a.getColor(R.styleable.CustomVal_accentColor, 0xffffffff));
|
||||
textColor.setColor(a.getColor(R.styleable.CustomVal_textColor, 0xffffffff));
|
||||
errorColor.setColor(a.getColor(R.styleable.CustomVal_errorColor, 0xffffffff));
|
||||
} finally { a.recycle(); }
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void processInstructions(Routine<?> r);
|
||||
public abstract void onDraw(android.graphics.Canvas canvas);
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import net.tofvesson.coloursbycontrol.R;
|
||||
|
||||
public class CircleHideView extends View {
|
||||
protected static final float FRAME_TOTAL = 60;
|
||||
protected final RectF circleSize = new RectF();
|
||||
protected Bitmap drawOn = null;
|
||||
protected Canvas c;
|
||||
protected boolean trigger = false;
|
||||
protected long frame = 0;
|
||||
protected Paint drawColor = new Paint();
|
||||
public boolean reverse = false;
|
||||
protected OnHideFinishListener listener;
|
||||
|
||||
public CircleHideView(Context c) { super(c); init(c, null, 0, 0); }
|
||||
public CircleHideView(Context c, @Nullable AttributeSet a) { super(c, a); init(c, a, 0, 0); }
|
||||
public CircleHideView(Context c, @Nullable AttributeSet a, int d) { super(c, a, d); init(c, a, d, 0); }
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public CircleHideView(Context c, @Nullable AttributeSet a, int d, int r) { super(c, a, d, r); init(c, a, d, r); }
|
||||
|
||||
private void init(Context ctx, AttributeSet set, int da, int dr){
|
||||
if(set==null) drawColor.setColor(0xffffffff);
|
||||
else{
|
||||
TypedArray a = ctx.getTheme().obtainStyledAttributes(set, R.styleable.CustomVal, da, dr);
|
||||
try { drawColor.setColor(a.getColor(R.styleable.CustomVal_color, 0xffffffff)); } finally { a.recycle(); }
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
if(drawOn == null) drawOn = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(), Bitmap.Config.ARGB_8888); // Allocate once
|
||||
if(c == null) c = new Canvas(drawOn);
|
||||
}
|
||||
|
||||
public void triggerDraw(){ if(!trigger){ trigger = true; invalidate(); } }
|
||||
public CircleHideView setOnFinishedListner(OnHideFinishListener listener){ this.listener = listener; return this; }
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if(!trigger) canvas.drawPaint(drawColor);
|
||||
else if(frame<=FRAME_TOTAL){
|
||||
float vCenter = canvas.getHeight() / 2.0F, hCenter = canvas.getWidth() / 2.0F, time = frame / FRAME_TOTAL;
|
||||
circleSize.top = reverse ? (1-time) * vCenter : time * vCenter;
|
||||
circleSize.bottom = reverse ? (1+time)*vCenter : (2-time) * vCenter;
|
||||
circleSize.left = reverse ? (1-time) * hCenter : time * hCenter;
|
||||
circleSize.right = reverse ? (1+time)*hCenter : (2-time) * hCenter;
|
||||
c.drawColor(Color.TRANSPARENT);
|
||||
c.drawCircle(hCenter, vCenter, (float) Math.sqrt((vCenter*vCenter)+(hCenter*hCenter))*time, drawColor);
|
||||
canvas.drawBitmap(drawOn, 0, 0, null);
|
||||
++frame;
|
||||
invalidate();
|
||||
}else{
|
||||
trigger = false;
|
||||
frame = 0;
|
||||
if(listener!=null) listener.onHideFinished(this);
|
||||
}
|
||||
}
|
||||
|
||||
public interface OnHideFinishListener{ void onHideFinished(CircleHideView view); }
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Rect;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import net.tofvesson.libtlang.Routine;
|
||||
|
||||
import net.tofvesson.coloursbycontrol.R;
|
||||
|
||||
public class FunctionCard extends ActionCard {
|
||||
private static final String func = "Function", inputs = "Inputs: ", out = "Output: ", n = "Name: ";
|
||||
protected String name;
|
||||
public Routine<?> instruction;
|
||||
public boolean inline = false;
|
||||
private final Rect tMeasure = new Rect();
|
||||
|
||||
public FunctionCard(Context c) { super(c); init(c, null); }
|
||||
public FunctionCard(Context c, @Nullable AttributeSet a) { super(c, a); init(c, a); }
|
||||
public FunctionCard(Context c, @Nullable AttributeSet a, int d) { super(c, a, d); init(c, a); }
|
||||
@android.support.annotation.RequiresApi(api = android.os.Build.VERSION_CODES.LOLLIPOP) public FunctionCard(Context c, @Nullable AttributeSet a, int s, int r) { super(c, a, s, r); init(c, a); }
|
||||
|
||||
private void init(Context c, AttributeSet a){
|
||||
if(a!=null) {
|
||||
TypedArray a1 = c.getTheme().obtainStyledAttributes(a, R.styleable.CustomVal, 0, 0);
|
||||
try { setName(a1.getString(R.styleable.CustomVal_name)); } finally { a1.recycle(); }
|
||||
}
|
||||
if (name == null) name = "NAMELESS";
|
||||
}
|
||||
|
||||
public void setName(String name){ if(name==null || name.length()==0) return; this.name = name; }
|
||||
public String getName(){ return name; }
|
||||
|
||||
@Override public void processInstructions(Routine<?> r) {
|
||||
if(instruction == null) return;
|
||||
if(inline) r.inline(instruction);
|
||||
else r.add(instruction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawItems(android.graphics.Canvas canvas) {
|
||||
String s;
|
||||
textColor.setTextSize((float) Math.sqrt(canvas.getWidth()*canvas.getHeight())/7.5F);
|
||||
textColor.getTextBounds(func, 0, func.length(), tMeasure);
|
||||
canvas.drawText(func, canvas.getWidth()/2 - tMeasure.exactCenterX(), -tMeasure.exactCenterY() * 4, textColor);
|
||||
textColor.setTextSize((float) Math.sqrt(canvas.getWidth()*canvas.getHeight())/12F);
|
||||
textColor.getTextBounds(s=inputs + (instruction==null?"0":instruction.getParamTypes().length), 0, s.length(), tMeasure);
|
||||
canvas.drawText(s, canvas.getWidth()/2 - tMeasure.exactCenterX(), canvas.getHeight()*2F/3F - tMeasure.exactCenterY() * 3, textColor);
|
||||
textColor.getTextBounds(s=out+(instruction==null || instruction.getReturnType()==Void.class?"No":"Yes"), 0, s.length(), tMeasure);
|
||||
canvas.drawText(s, canvas.getWidth()/2 - tMeasure.exactCenterX(), canvas.getHeight()+tMeasure.exactCenterY() * 4, textColor);
|
||||
textColor.setTextSize((float) Math.sqrt(canvas.getWidth()*canvas.getHeight())/14F);
|
||||
if (name.length()>20) s = n+name.substring(0, 20)+"...";
|
||||
else s = n+name;
|
||||
textColor.getTextBounds(s, 0, s.length(), tMeasure);
|
||||
canvas.drawText(s, canvas.getWidth()/2 - tMeasure.exactCenterX(), canvas.getHeight()/2.5F, textColor);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import net.tofvesson.libtlang.Routine;
|
||||
|
||||
public class GOTOCard extends ActionCard {
|
||||
public GOTOCard(Context c) { super(c); }
|
||||
public GOTOCard(Context c, @Nullable AttributeSet a) { super(c, a); }
|
||||
public GOTOCard(Context c, @Nullable AttributeSet a, int d) { super(c, a, d); }
|
||||
@android.support.annotation.RequiresApi(api = android.os.Build.VERSION_CODES.LOLLIPOP) public GOTOCard(Context c, @Nullable AttributeSet a, int s, int r) { super(c, a, s, r); }
|
||||
|
||||
@Override public void processInstructions(Routine<?> r) { }
|
||||
|
||||
@Override
|
||||
public void drawItems(android.graphics.Canvas canvas) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
public class LinearActionLayout extends LinearLayout {
|
||||
public LinearActionLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LinearActionLayout(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public LinearActionLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public LinearActionLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void addView(View child, int index, ViewGroup.LayoutParams params) {
|
||||
if(!(child instanceof ActionView)) throw new RuntimeException("Attempted to add a non-ActionView view to Action layout!");
|
||||
super.addView(child, index, params);
|
||||
}
|
||||
|
||||
@Override public ActionView getChildAt(int index) { return (ActionView) super.getChildAt(index); }
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import net.tofvesson.libtlang.Routine;
|
||||
|
||||
|
||||
public class OperationCard extends ActionCard {
|
||||
public OperationCard(Context c) { super(c); }
|
||||
public OperationCard(Context c, @Nullable AttributeSet a) { super(c, a); }
|
||||
public OperationCard(Context c, @Nullable AttributeSet a, int d) { super(c, a, d); }
|
||||
@android.support.annotation.RequiresApi(api = android.os.Build.VERSION_CODES.LOLLIPOP) public OperationCard(Context c, @Nullable AttributeSet a, int s, int r) { super(c, a, s, r); }
|
||||
|
||||
@Override public void processInstructions(Routine<?> r) { }
|
||||
|
||||
@Override
|
||||
public void drawItems(android.graphics.Canvas canvas) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import net.tofvesson.libtlang.Routine;
|
||||
import net.tofvesson.libtlang.StackPush;
|
||||
|
||||
public class StackPushCard extends ActionCard {
|
||||
protected static final String name = "Constant", help = "Click to edit...";
|
||||
public Object push;
|
||||
private final Rect tMeasure = new Rect();
|
||||
|
||||
public StackPushCard(Context c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
public StackPushCard(Context c, @Nullable AttributeSet a) {
|
||||
super(c, a);
|
||||
}
|
||||
|
||||
public StackPushCard(Context c, @Nullable AttributeSet a, int d) {
|
||||
super(c, a, d);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public StackPushCard(Context c, @Nullable AttributeSet a, int s, int r) {
|
||||
super(c, a, s, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processInstructions(Routine<?> r) { r.add(new StackPush(push)); }
|
||||
|
||||
@Override
|
||||
protected void drawItems(Canvas canvas) {
|
||||
String s = String.valueOf(push);
|
||||
if (s.length()>15) s = s.substring(0, 15)+"...";
|
||||
s = '\"' + s + '\"';
|
||||
textColor.setTextSize((float) Math.sqrt(canvas.getWidth()*canvas.getHeight())/7.5F);
|
||||
textColor.getTextBounds(name, 0, name.length(), tMeasure);
|
||||
canvas.drawText(name, canvas.getWidth()/2 - tMeasure.exactCenterX(), -tMeasure.exactCenterY() * 4, textColor);
|
||||
textColor.setTextSize((float) Math.sqrt(canvas.getWidth()*canvas.getHeight())/10F);
|
||||
textColor.getTextBounds(s, 0, s.length(), tMeasure);
|
||||
canvas.drawText(s, canvas.getWidth()/2 - tMeasure.exactCenterX(), canvas.getHeight()/1.5F, textColor);
|
||||
textColor.setTextSize((float) Math.sqrt(canvas.getWidth()*canvas.getHeight())/16F);
|
||||
textColor.getTextBounds(help, 0, help.length(), tMeasure);
|
||||
canvas.drawText(help, canvas.getWidth()/2 - tMeasure.exactCenterX(), canvas.getHeight()/1.125F, textColor);
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import net.tofvesson.libtlang.Routine;
|
||||
|
||||
public class StartIcon extends ActionView {
|
||||
protected final Rect bounds = new Rect();
|
||||
public StartIcon(Context c) { super(c); }
|
||||
public StartIcon(Context c, @Nullable AttributeSet a) { super(c, a); }
|
||||
public StartIcon(Context c, @Nullable AttributeSet a, int d) { super(c, a, d); }
|
||||
@android.support.annotation.RequiresApi(api = android.os.Build.VERSION_CODES.LOLLIPOP) public StartIcon(Context c, @Nullable AttributeSet a, int s, int r) { super(c, a, s, r); }
|
||||
|
||||
@Override public void processInstructions(Routine<?> r) { }
|
||||
|
||||
@Override
|
||||
public void onDraw(android.graphics.Canvas canvas) {
|
||||
float f;
|
||||
accentColor.setTextSize((float) Math.sqrt(canvas.getWidth()*canvas.getHeight())/1.25F);
|
||||
accentColor.getTextBounds("S", 0, 1, bounds);
|
||||
canvas.drawCircle(canvas.getWidth()/2F, canvas.getHeight()/2F, f=Math.min(canvas.getWidth(), canvas.getHeight())/2F, color);
|
||||
canvas.drawText("S", f - bounds.exactCenterX(), f - bounds.exactCenterY(), accentColor);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import net.tofvesson.libtlang.Routine;
|
||||
|
||||
public class VarDeclareCard extends ActionCard {
|
||||
public VarDeclareCard(Context c) { super(c); }
|
||||
public VarDeclareCard(Context c, @Nullable AttributeSet a) { super(c, a); }
|
||||
public VarDeclareCard(Context c, @Nullable AttributeSet a, int d) { super(c, a, d); }
|
||||
@android.support.annotation.RequiresApi(api = android.os.Build.VERSION_CODES.LOLLIPOP) public VarDeclareCard(Context c, @Nullable AttributeSet a, int s, int r) { super(c, a, s, r); }
|
||||
|
||||
@Override public void processInstructions(Routine<?> r) { }
|
||||
|
||||
@Override
|
||||
public void drawItems(android.graphics.Canvas canvas) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
package net.tofvesson.coloursbycontrol.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import net.tofvesson.coloursbycontrol.R;
|
||||
|
||||
public class WelcomeView extends View {
|
||||
//static{ System.loadLibrary("native-lib"); } // Load native (rendering) code for this class
|
||||
|
||||
protected static final float precision = 30, delimiter = 30, milestone = delimiter+precision;
|
||||
protected static final Interpolator i = new AccelerateDecelerateInterpolator();
|
||||
protected long frame;
|
||||
private int maxHeight;
|
||||
private int maxWidth;
|
||||
protected final RectF s1_oval = new RectF(), s1_innerOval = new RectF(), s2_topCir = new RectF(), s2_botCir = new RectF(), s2_topInnerCir = new RectF(), s2_botInnerCir = new RectF();
|
||||
protected final Paint drawColor = new Paint(Paint.ANTI_ALIAS_FLAG), clearColor = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
protected boolean trigger = false;
|
||||
protected OnWelcomeFinishedListener listener;
|
||||
|
||||
public WelcomeView(Context c) { super(c); init(c, null, 0, 0); }
|
||||
public WelcomeView(Context c, @Nullable AttributeSet a) { super(c, a); init(c, a, 0, 0); }
|
||||
public WelcomeView(Context c, @Nullable AttributeSet a, int d) { super(c, a, d); init(c, a, d, 0); }
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public WelcomeView(Context c, @Nullable AttributeSet a, int d, int r) { super(c, a, d, r); init(c, a, d, r); }
|
||||
|
||||
private void init(Context ctx, AttributeSet set, int da, int dr){
|
||||
if(set==null){
|
||||
clearColor.setColor(0xffffffff);
|
||||
drawColor.setColor(0xffffffff);
|
||||
}
|
||||
else{
|
||||
TypedArray a = ctx.getTheme().obtainStyledAttributes(set, R.styleable.CustomVal, da, dr);
|
||||
try {
|
||||
drawColor.setColor(a.getColor(R.styleable.CustomVal_color, 0xffffffff));
|
||||
clearColor.setColor(a.getColor(R.styleable.CustomVal_backgroundColor, 0xffffffff));
|
||||
} finally { a.recycle(); }
|
||||
}
|
||||
s1_oval.left = 1;
|
||||
s1_oval.top = 1;
|
||||
}
|
||||
public void setDrawColor(Paint drawColor) { this.drawColor.setColor(drawColor.getColor()); }
|
||||
public void setClearColor(Paint clearColor) { this.clearColor.setColor(clearColor.getColor()); }
|
||||
public void triggerDraw(){ if(!trigger){ trigger = true; invalidate(); } }
|
||||
public WelcomeView setOnFinishedListener(OnWelcomeFinishedListener listener){ this.listener = listener; return this; }
|
||||
|
||||
@Override
|
||||
protected final void onDraw(Canvas canvas){
|
||||
if(!trigger){
|
||||
canvas.drawPaint(drawColor);
|
||||
return;
|
||||
}
|
||||
if(frame<delimiter) invalidate();
|
||||
else if(frame<milestone || frame<milestone +delimiter || frame <milestone*2 || frame <milestone*2+delimiter) drawC1(canvas);
|
||||
else if(frame<milestone*3 || frame<milestone*3+delimiter) drawB(canvas);
|
||||
else if(frame<milestone*4 || frame<milestone*4+delimiter) clearB(canvas);
|
||||
else if(frame<milestone*5 || frame<milestone*5+delimiter || frame <milestone*6 || frame <milestone*6+delimiter) drawC2(canvas);
|
||||
else { trigger = false; frame = 0; if(listener!=null) listener.onTriggerFinished(this); }
|
||||
if(trigger) ++frame;
|
||||
}
|
||||
|
||||
protected void drawC1(Canvas canvas){
|
||||
boolean b = frame<milestone || frame<milestone+delimiter;
|
||||
float
|
||||
f = frame<milestone ? i.getInterpolation((frame-delimiter)/precision) : b ? 1 :
|
||||
frame<milestone*2 ? i.getInterpolation((frame-milestone-delimiter)/precision) : 1, // Render factor
|
||||
f1 = 45 + 135 * (b ? (1-f) : f), // Bottom half render size
|
||||
f2 = 270 * (b ? f : (1-f)); // Top half render size
|
||||
|
||||
s1_oval.right = maxWidth = canvas.getWidth() - 1;
|
||||
s1_oval.bottom = maxHeight = canvas.getHeight() - 1;
|
||||
|
||||
s1_innerOval.left = canvas.getWidth() * 0.15F;
|
||||
s1_innerOval.top = canvas.getHeight() * 0.15F;
|
||||
s1_innerOval.right = maxWidth - s1_innerOval.left + 1;
|
||||
s1_innerOval.bottom = maxHeight - s1_innerOval.top + 1;
|
||||
|
||||
canvas.drawArc(s1_oval, f1, f2, true, drawColor); // Draw arc
|
||||
canvas.drawArc(s1_innerOval, f1 - 1, f2 + 2, true, clearColor); // Remove inner part (with 1 degree's overlap)
|
||||
invalidate(); // Make sure method is called again
|
||||
}
|
||||
|
||||
protected void drawB(Canvas canvas){
|
||||
float
|
||||
hf = canvas.getHeight() / 2.0F, width = canvas.getWidth(), hq = width / 4.0F,
|
||||
f = frame <milestone * 3 ? (frame -milestone*2-delimiter)/precision : 1,
|
||||
f1 = 0;
|
||||
canvas.drawRect(canvas.getWidth() / 8.0F, f <= 0.3F ? hf * (1-(f1=(f/0.3F))) : 0, hq, f <= 0.3F ? hf * (1 + f1) : 2 * hf, drawColor);
|
||||
if(f>=0.3){
|
||||
s2_topCir.left = -hq*0.5F;
|
||||
s2_topCir.right = width - hq*1.5F;
|
||||
s2_topCir.bottom = canvas.getHeight() / 2.5F;
|
||||
|
||||
float tWFact = (s2_topCir.right - s2_topCir.left) * 0.15F, tHFact = s2_topCir.bottom * 0.15F;
|
||||
|
||||
s2_topInnerCir.left = s2_topCir.left + tWFact;
|
||||
s2_topInnerCir.right = s2_topCir.right - tWFact;
|
||||
s2_topInnerCir.top = s2_topCir.top + tHFact;
|
||||
s2_topInnerCir.bottom = s2_topCir.bottom - tHFact;
|
||||
|
||||
canvas.drawArc(s2_topCir, 270, f<=0.6F ? 180 * (f1=(f-0.3F)/0.3F): 180, true, drawColor);
|
||||
canvas.drawArc(s2_topInnerCir, 270, f<=0.6F ? 180 * f1: 180, true, clearColor);
|
||||
}
|
||||
if(f>=0.6){
|
||||
s2_botCir.left = -hq;
|
||||
s2_botCir.top = canvas.getHeight() / 2.5F;
|
||||
s2_botCir.right = width - hq;
|
||||
s2_botCir.bottom = canvas.getHeight();
|
||||
|
||||
float bWFact = (s2_botCir.right - s2_botCir.left) * 0.15F, bHFact = (s2_botCir.bottom - s2_botCir.top) * 0.15F;
|
||||
|
||||
s2_botInnerCir.left = s2_botCir.left + bWFact;
|
||||
s2_botInnerCir.right = s2_botCir.right - bWFact;
|
||||
s2_botInnerCir.top = s2_botCir.top + bHFact;
|
||||
s2_botInnerCir.bottom = s2_botCir.bottom - bHFact;
|
||||
|
||||
canvas.drawArc(s2_botCir, 270, f<=1 ? 180 * (f1=(f-0.6F)/0.4F) : 180, true, drawColor);
|
||||
canvas.drawArc(s2_botInnerCir, 270, f<=1 ? 180 * f1 : 180, true, clearColor);
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
protected void clearB(Canvas canvas){
|
||||
float
|
||||
hf = canvas.getHeight() / 2.0F,
|
||||
f = frame <milestone * 4 ? (frame -milestone*3-delimiter)/precision : 1;
|
||||
canvas.drawRect(canvas.getWidth() / 8.0F, f >= 0.5F ? hf * (f-0.5F)/0.5F : 0, canvas.getWidth() / 4.0F, f >= 0.5F ? hf * (2-(f-0.5F)/0.5F) : 2 * hf, drawColor);
|
||||
|
||||
canvas.drawArc(s2_topCir, 270, f<=0.5F ? 180 * (1-(f/0.5F)) : 0, true, drawColor);
|
||||
canvas.drawArc(s2_topInnerCir, 270, f<=0.5F ? 180 * (1-(f/0.5F)) : 0, true, clearColor);
|
||||
|
||||
canvas.drawArc(s2_botCir, 270 + (f<=0.5F ? 180 * (f/0.5F) : 180), f<=0.5F ? 180 * (1-(f/0.5F)) : 0, true, drawColor);
|
||||
canvas.drawArc(s2_botInnerCir, 270 + (f<=0.5F ? 180 * (f/0.5F) : 180), f<=0.5F ? 180 * (1-(f/0.5F)) : 0, true, clearColor);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
protected void drawC2(Canvas canvas){
|
||||
boolean b = frame <milestone*5 || frame <milestone*5+delimiter;
|
||||
float f= frame <milestone*5?i.getInterpolation((frame -milestone*4-delimiter)/precision): frame <milestone*5+delimiter?1: frame <milestone*6?i.getInterpolation((frame -milestone*5-delimiter)/precision):1,
|
||||
f2 = b ? 0 : 270 * f,
|
||||
f1 = b ? 270 * f: 270 - f2;
|
||||
canvas.drawArc(s1_oval, 45 + f2, f1, true, drawColor);
|
||||
canvas.drawArc(s1_innerOval, 45 + f2, f1, true, clearColor);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
//protected native void _onDraw(Canvas canvas);
|
||||
|
||||
public interface OnWelcomeFinishedListener{ void onTriggerFinished(WelcomeView view); }
|
||||
}
|
13
mobile/src/main/res/drawable/ic_auto.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M21.7 25.3h4.6L24 18l-2.3 7.3zM40 17.37V8h-9.37L24 1.37 17.37 8H8v9.37L1.37 24 8
|
||||
30.63V40h9.37L24 46.63 30.63 40H40v-9.37L46.63 24 40 17.37zM28.6
|
||||
32l-1.4-4h-6.4l-1.4 4h-3.8L22 14h4l6.4 18h-3.8z" />
|
||||
</vector>
|
13
mobile/src/main/res/drawable/ic_bright.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M40 30.63L46.63 24 40 17.37V8h-9.37L24 1.37 17.37 8H8v9.37L1.37 24 8
|
||||
30.63V40h9.37L24 46.63 30.63 40H40v-9.37zM24 36c-6.63 0-12-5.37-12-12s5.37-12
|
||||
12-12 12 5.37 12 12-5.37 12-12 12z" />
|
||||
</vector>
|
12
mobile/src/main/res/drawable/ic_dark.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M18 4c-2.09 0-4.11 .32 -6 .92C20.11 7.47 26 15.05 26 24c0 8.95-5.89 16.53-14
|
||||
19.08 1.89 .59 3.91 .92 6 .92 11.05 0 20-8.95 20-20S29.05 4 18 4z" />
|
||||
</vector>
|
15
mobile/src/main/res/drawable/ic_day.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M13.51 9.69L9.93 6.1 7.1 8.93l3.59 3.59 2.82-2.83zM8 21H2v4h6v-4zM26
|
||||
1.1h-4V7h4V1.1zm14.9 7.83L38.07 6.1l-3.59 3.59 2.83 2.83 3.59-3.59zm-6.41
|
||||
27.38l3.59 3.59 2.83-2.83-3.59-3.59-2.83 2.83zM40 21v4h6v-4h-6zM24 11c-6.63 0-12
|
||||
5.37-12 12s5.37 12 12 12 12-5.37 12-12-5.37-12-12-12zm-2 33.9h4V39h-4v5.9zM7.1
|
||||
37.07l2.83 2.83 3.59-3.59-2.83-2.83-3.59 3.59z" />
|
||||
</vector>
|
11
mobile/src/main/res/drawable/ic_run.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M16,10 L16,38 L38,24 Z" />
|
||||
</vector>
|
12
mobile/src/main/res/drawable/ic_stack.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="48"
|
||||
android:viewportHeight="48">
|
||||
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M8,30 L42,30 L42,26 L8,26 L8,30 Z M8,38 L42,38 L42,34 L8,34 L8,38 Z M8,22 L42,22
|
||||
L42,18 L8,18 L8,22 Z M8,10 L8,14 L42,14 L42,10 L8,10 Z" />
|
||||
</vector>
|
37
mobile/src/main/res/layout/activity_main.xml
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="net.tofvesson.coloursbycontrol.activity.MainActivity"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?colorPrimaryDark">
|
||||
|
||||
<net.tofvesson.coloursbycontrol.view.WelcomeView
|
||||
android:id="@+id/welcome"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:layout_centerInParent="true"
|
||||
app:color="?colorAccent"
|
||||
app:backgroundColor="?colorPrimaryDark"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/newProj"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/openProj"
|
||||
android:background="?colorAccent"
|
||||
android:padding="16sp"
|
||||
android:text="New project"
|
||||
android:textSize="16sp"/>
|
||||
<Button
|
||||
android:id="@id/openProj"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="?colorAccent"
|
||||
android:padding="16dp"
|
||||
android:text="Open project"
|
||||
android:textSize="16sp"/>
|
||||
</RelativeLayout>
|
56
mobile/src/main/res/layout/activity_scrolling.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context="net.tofvesson.coloursbycontrol.activity.ScrollingActivity">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:id="@+id/app_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/app_bar_height"
|
||||
android:fitsSystemWindows="true"
|
||||
android:theme="@style/AppThemeLight.AppBarOverlay">
|
||||
|
||||
<android.support.design.widget.CollapsingToolbarLayout
|
||||
android:id="@+id/toolbar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
app:contentScrim="?attr/colorPrimaryDark"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed"
|
||||
app:expandedTitleGravity="bottom|center_horizontal">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
app:layout_collapseMode="pin"
|
||||
app:popupTheme="@style/AppThemeLight.PopupOverlay" />
|
||||
|
||||
</android.support.design.widget.CollapsingToolbarLayout>
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_scrolling" />
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
app:layout_anchor="@id/app_bar"
|
||||
app:layout_anchorGravity="bottom|end"
|
||||
app:srcCompat="@drawable/ic_run" />
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
app:layout_anchor="@id/app_bar"
|
||||
app:layout_anchorGravity="bottom|start"
|
||||
app:srcCompat="@drawable/ic_stack" />
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
46
mobile/src/main/res/layout/content_scrolling.xml
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:context="net.tofvesson.coloursbycontrol.activity.ScrollingActivity"
|
||||
tools:showIn="@layout/activity_scrolling">
|
||||
<net.tofvesson.coloursbycontrol.view.LinearActionLayout
|
||||
android:id="@+id/instructions"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="120dp"
|
||||
android:paddingLeft="120dp"
|
||||
android:paddingEnd="120dp"
|
||||
android:paddingRight="120dp"
|
||||
android:paddingBottom="40dp"
|
||||
android:paddingTop="40dp"
|
||||
android:gravity="center_horizontal">
|
||||
<net.tofvesson.coloursbycontrol.view.StartIcon
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="60dp"
|
||||
app:color="?colorPrimary"
|
||||
app:backgroundColor="?colorPrimaryDark"
|
||||
app:textColor="?colorAccent"/>
|
||||
<net.tofvesson.coloursbycontrol.view.StackPushCard
|
||||
android:id="@+id/stackPush"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/start_margin"
|
||||
app:color="?colorPrimary"
|
||||
app:accentColor="?colorAccent" />
|
||||
<net.tofvesson.coloursbycontrol.view.FunctionCard
|
||||
android:id="@+id/test"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/start_margin"
|
||||
app:color="?colorPrimary"
|
||||
app:accentColor="?colorAccent"
|
||||
app:name="Show Snackbar"/>
|
||||
</net.tofvesson.coloursbycontrol.view.LinearActionLayout>
|
||||
|
||||
</android.support.v4.widget.NestedScrollView>
|
33
mobile/src/main/res/layout/dialog_constant.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp">
|
||||
<EditText
|
||||
android:id="@+id/newConst"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
android:hint="Define new constant value"/>
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
<Button
|
||||
android:id="@+id/cancel_action"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:text="Cancel"/>
|
||||
<Button
|
||||
android:id="@+id/confirm_action"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:text="OK"/>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
10
mobile/src/main/res/menu/menu_scrolling.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="net.tofvesson.coloursbycontrol.activity.ScrollingActivity">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
BIN
mobile/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
mobile/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
mobile/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
mobile/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
mobile/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
mobile/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
mobile/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
mobile/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
mobile/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
mobile/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
After Width: | Height: | Size: 14 KiB |
30
mobile/src/main/res/values-v21/styles.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="WelcomeLight" parent="Theme.AppCompat.NoActionBar">
|
||||
<item name="colorPrimary">@color/light_primary</item>
|
||||
<item name="colorPrimaryDark">@color/light_primary_dark</item>
|
||||
<item name="colorAccent">@color/light_accent</item>
|
||||
<item name="android:navigationBarColor">@color/light_accent_dark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="colorPrimary">@color/light_primary</item>
|
||||
<item name="colorPrimaryDark">@color/light_primary_dark</item>
|
||||
<item name="colorAccent">@color/light_accent</item>
|
||||
<item name="android:navigationBarColor">@color/light_primary_dark</item>
|
||||
</style>
|
||||
|
||||
<style name="WelcomeDark" parent="Theme.AppCompat.NoActionBar">
|
||||
<item name="colorPrimary">@color/dark_primary</item>
|
||||
<item name="colorPrimaryDark">@color/dark_primary_dark</item>
|
||||
<item name="colorAccent">@color/dark_accent</item>
|
||||
<item name="android:navigationBarColor">@color/dark_accent_dark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDark" parent="Theme.AppCompat.NoActionBar">
|
||||
<item name="colorPrimary">@color/dark_primary</item>
|
||||
<item name="colorPrimaryDark">@color/dark_primary_dark</item>
|
||||
<item name="colorAccent">@color/dark_accent</item>
|
||||
<item name="android:navigationBarColor">@color/dark_primary_dark</item>
|
||||
</style>
|
||||
</resources>
|
11
mobile/src/main/res/values/attrs.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<declare-styleable name="CustomVal">
|
||||
<attr name="color" format="color" />
|
||||
<attr name="backgroundColor" format="color" />
|
||||
<attr name="accentColor" format="color" />
|
||||
<attr name="textColor" format="color" />
|
||||
<attr name="errorColor" format="color" />
|
||||
<attr name="name" format="string" />
|
||||
</declare-styleable>
|
||||
</resources>
|
24
mobile/src/main/res/values/colors.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Dark theme -->
|
||||
<color name="dark_primary">#3F51B5</color>
|
||||
<color name="dark_primary_dark">#303F9F</color>
|
||||
<color name="dark_primary_light">#C5CAE9</color>
|
||||
<color name="dark_accent">#FF4081</color>
|
||||
<color name="dark_accent_dark">#FF2061</color>
|
||||
<color name="dark_primary_text">#212121</color>
|
||||
<color name="dark_secondary_text">#757575</color>
|
||||
<color name="dark_icons">#FFFFFF</color>
|
||||
<color name="dark_divider">#BDBDBD</color>
|
||||
|
||||
<!-- Light theme -->
|
||||
<color name="light_primary">#03A9F4</color>
|
||||
<color name="light_primary_dark">#0288D1</color>
|
||||
<color name="light_primary_light">#B3E5FC</color>
|
||||
<color name="light_accent">#FFC107</color>
|
||||
<color name="light_accent_dark">#FFA127</color>
|
||||
<color name="light_primary_text">#212121</color>
|
||||
<color name="light_secondary_text">#757575</color>
|
||||
<color name="light_icons">#FFFFFF</color>
|
||||
<color name="light_divider">#BDBDBD</color>
|
||||
</resources>
|
7
mobile/src/main/res/values/dimens.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<resources>
|
||||
<dimen name="app_bar_height">180dp</dimen>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
<dimen name="text_margin">16dp</dimen>
|
||||
<dimen name="card_margin">20dp</dimen>
|
||||
<dimen name="start_margin">20dp</dimen>
|
||||
</resources>
|
94
mobile/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,94 @@
|
||||
<resources>
|
||||
<string name="app_name">Colours By Control</string>
|
||||
<string name="title_activity_scrolling">ScrollingActivity</string>
|
||||
<string name="large_text">
|
||||
"Material is the metaphor.\n\n"
|
||||
|
||||
"A material metaphor is the unifying theory of a rationalized space and a system of motion."
|
||||
"The material is grounded in tactile reality, inspired by the study of paper and ink, yet "
|
||||
"technologically advanced and open to imagination and magic.\n"
|
||||
"Surfaces and edges of the material provide visual cues that are grounded in reality. The "
|
||||
"use of familiar tactile attributes helps users quickly understand affordances. Yet the "
|
||||
"flexibility of the material creates new affordances that supercede those in the physical "
|
||||
"world, without breaking the rules of physics.\n"
|
||||
"The fundamentals of light, surface, and movement are key to conveying how objects move, "
|
||||
"interact, and exist in space and in relation to each other. Realistic lighting shows "
|
||||
"seams, divides space, and indicates moving parts.\n\n"
|
||||
|
||||
"Bold, graphic, intentional.\n\n"
|
||||
|
||||
"The foundational elements of print based design typography, grids, space, scale, color, "
|
||||
"and use of imagery guide visual treatments. These elements do far more than please the "
|
||||
"eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge "
|
||||
"imagery, large scale typography, and intentional white space create a bold and graphic "
|
||||
"interface that immerse the user in the experience.\n"
|
||||
"An emphasis on user actions makes core functionality immediately apparent and provides "
|
||||
"waypoints for the user.\n\n"
|
||||
|
||||
"Motion provides meaning.\n\n"
|
||||
|
||||
"Motion respects and reinforces the user as the prime mover. Primary user actions are "
|
||||
"inflection points that initiate motion, transforming the whole design.\n"
|
||||
"All action takes place in a single environment. Objects are presented to the user without "
|
||||
"breaking the continuity of experience even as they transform and reorganize.\n"
|
||||
"Motion is meaningful and appropriate, serving to focus attention and maintain continuity. "
|
||||
"Feedback is subtle yet clear. Transitions are efficient yet coherent.\n\n"
|
||||
|
||||
"3D world.\n\n"
|
||||
|
||||
"The material environment is a 3D space, which means all objects have x, y, and z "
|
||||
"dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the "
|
||||
"positive z-axis extending towards the viewer. Every sheet of material occupies a single "
|
||||
"position along the z-axis and has a standard 1dp thickness.\n"
|
||||
"On the web, the z-axis is used for layering and not for perspective. The 3D world is "
|
||||
"emulated by manipulating the y-axis.\n\n"
|
||||
|
||||
"Light and shadow.\n\n"
|
||||
|
||||
"Within the material environment, virtual lights illuminate the scene. Key lights create "
|
||||
"directional shadows, while ambient light creates soft shadows from all angles.\n"
|
||||
"Shadows in the material environment are cast by these two light sources. In Android "
|
||||
"development, shadows occur when light sources are blocked by sheets of material at "
|
||||
"various positions along the z-axis. On the web, shadows are depicted by manipulating the "
|
||||
"y-axis only. The following example shows the card with a height of 6dp.\n\n"
|
||||
|
||||
"Resting elevation.\n\n"
|
||||
|
||||
"All material objects, regardless of size, have a resting elevation, or default elevation "
|
||||
"that does not change. If an object changes elevation, it should return to its resting "
|
||||
"elevation as soon as possible.\n\n"
|
||||
|
||||
"Component elevations.\n\n"
|
||||
|
||||
"The resting elevation for a component type is consistent across apps (e.g., FAB elevation "
|
||||
"does not vary from 6dp in one app to 16dp in another app).\n"
|
||||
"Components may have different resting elevations across platforms, depending on the depth "
|
||||
"of the environment (e.g., TV has a greater depth than mobile or desktop).\n\n"
|
||||
|
||||
"Responsive elevation and dynamic elevation offsets.\n\n"
|
||||
|
||||
"Some component types have responsive elevation, meaning they change elevation in response "
|
||||
"to user input (e.g., normal, focused, and pressed) or system events. These elevation "
|
||||
"changes are consistently implemented using dynamic elevation offsets.\n"
|
||||
"Dynamic elevation offsets are the goal elevation that a component moves towards, relative "
|
||||
"to the component’s resting state. They ensure that elevation changes are consistent "
|
||||
"across actions and component types. For example, all components that lift on press have "
|
||||
"the same elevation change relative to their resting elevation.\n"
|
||||
"Once the input event is completed or cancelled, the component will return to its resting "
|
||||
"elevation.\n\n"
|
||||
|
||||
"Avoiding elevation interference.\n\n"
|
||||
|
||||
"Components with responsive elevations may encounter other components as they move between "
|
||||
"their resting elevations and dynamic elevation offsets. Because material cannot pass "
|
||||
"through other material, components avoid interfering with one another any number of ways, "
|
||||
"whether on a per component basis or using the entire app layout.\n"
|
||||
"On a component level, components can move or be removed before they cause interference. "
|
||||
"For example, a floating action button (FAB) can disappear or move off screen before a "
|
||||
"user picks up a card, or it can move if a snackbar appears.\n"
|
||||
"On the layout level, design your app layout to minimize opportunities for interference. "
|
||||
"For example, position the FAB to one side of stream of a cards so the FAB won’t interfere "
|
||||
"when a user tries to pick up one of cards.\n\n"
|
||||
</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
</resources>
|
34
mobile/src/main/res/values/styles.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<resources>
|
||||
|
||||
<style name="WelcomeLight" parent="Theme.AppCompat.NoActionBar">
|
||||
<item name="colorPrimary">@color/light_primary</item>
|
||||
<item name="colorPrimaryDark">@color/light_primary_dark</item>
|
||||
<item name="colorAccent">@color/light_accent</item>
|
||||
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="colorPrimary">@color/light_primary</item>
|
||||
<item name="colorPrimaryDark">@color/light_primary_dark</item>
|
||||
<item name="colorAccent">@color/light_accent</item>
|
||||
|
||||
</style>
|
||||
|
||||
<style name="WelcomeDark" parent="Theme.AppCompat.NoActionBar">
|
||||
<item name="colorPrimary">@color/dark_primary</item>
|
||||
<item name="colorPrimaryDark">@color/dark_primary_dark</item>
|
||||
<item name="colorAccent">@color/dark_accent</item>
|
||||
|
||||
</style>
|
||||
|
||||
<style name="AppThemeDark" parent="Theme.AppCompat.NoActionBar">
|
||||
<item name="colorPrimary">@color/dark_primary</item>
|
||||
<item name="colorPrimaryDark">@color/dark_primary_dark</item>
|
||||
<item name="colorAccent">@color/dark_accent</item>
|
||||
|
||||
</style>
|
||||
|
||||
<style name="AppThemeLight.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
|
||||
|
||||
<style name="AppThemeLight.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
|
||||
</resources>
|
@ -0,0 +1,17 @@
|
||||
package net.tofvesson.coloursbycontrol;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
BIN
mobile/wear-release.apk
Normal file
1
settings.gradle
Normal file
@ -0,0 +1 @@
|
||||
include ':mobile', ':wear', ':libtlang'
|
1
wear/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/build
|
35
wear/build.gradle
Normal file
@ -0,0 +1,35 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion 26
|
||||
buildToolsVersion "26.0.0"
|
||||
defaultConfig {
|
||||
applicationId "net.tofvesson.coloursbycontrol"
|
||||
minSdkVersion 20
|
||||
targetSdkVersion 26
|
||||
versionCode 2
|
||||
versionName "1.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
dexOptions.preDexLibraries = false
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.google.android.support:wearable:2.0.3'
|
||||
compile 'com.google.android.gms:play-services-wearable:11.0.2'
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
25
wear/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in E:\Users\Gabriel\AppData\Local\Android\sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
24
wear/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="net.tofvesson.coloursbycontrol">
|
||||
|
||||
<uses-feature android:name="android.hardware.type.watch" />
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@android:style/Theme.DeviceDefault">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,24 @@
|
||||
package net.tofvesson.coloursbycontrol;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.support.wearable.view.WatchViewStub;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class MainActivity extends Activity {
|
||||
|
||||
private TextView mTextView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
final WatchViewStub stub = (WatchViewStub) findViewById(R.id.watch_view_stub);
|
||||
stub.setOnLayoutInflatedListener(new WatchViewStub.OnLayoutInflatedListener() {
|
||||
@Override
|
||||
public void onLayoutInflated(WatchViewStub stub) {
|
||||
mTextView = (TextView) stub.findViewById(R.id.text);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
11
wear/src/main/res/layout/activity_main.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.wearable.view.WatchViewStub xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/watch_view_stub"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:rectLayout="@layout/rect_activity_main"
|
||||
app:roundLayout="@layout/round_activity_main"
|
||||
tools:context="net.tofvesson.coloursbycontrol.activity.MainActivity"
|
||||
tools:deviceIds="wear"></android.support.wearable.view.WatchViewStub>
|
15
wear/src/main/res/layout/rect_activity_main.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context="net.tofvesson.coloursbycontrol.activity.MainActivity"
|
||||
tools:deviceIds="wear_square">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/hello_square" />
|
||||
</LinearLayout>
|
16
wear/src/main/res/layout/round_activity_main.xml
Normal file
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="net.tofvesson.coloursbycontrol.activity.MainActivity"
|
||||
tools:deviceIds="wear_round">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:text="@string/hello_round" />
|
||||
</RelativeLayout>
|
BIN
wear/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
wear/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
wear/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
wear/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
5
wear/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<resources>
|
||||
<string name="app_name">Colours By Control</string>
|
||||
<string name="hello_round">Hello Round World!</string>
|
||||
<string name="hello_square">Hello Square World!</string>
|
||||
</resources>
|