Initial commit

This commit is contained in:
Gabriel Tofvesson 2017-07-04 22:28:16 +02:00
commit 8241033eba
99 changed files with 2993 additions and 0 deletions

9
.gitignore vendored Normal file
View 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
View 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
View File

@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

6
.idea/encodings.xml generated Normal file
View 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
View 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>

View 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>

View 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
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

View 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
View 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
View 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
View File

@ -0,0 +1 @@
/build

8
libtlang/build.gradle Normal file
View File

@ -0,0 +1,8 @@
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8"

View 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;
}
}
}

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -0,0 +1,3 @@
package net.tofvesson.libtlang;
public interface Instruction<T> { T eval(Routine<?> s, Object... params); Class<?>[] getParamTypes(); Class<T> getReturnType(); }

View 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; }
}

View 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());
}
}

View File

@ -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);
}
}

View 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; }
}

View 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;
}
}

View 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;
}
}
}

View File

@ -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;
}
}

View 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
View File

@ -0,0 +1 @@
/build

46
mobile/CMakeLists.txt Normal file
View 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
View 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

Binary file not shown.

25
mobile/proguard-rules.pro vendored Normal file
View 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

View File

@ -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());
}
}

View 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>

View File

@ -0,0 +1 @@
// Add bindings to app/activity here

View File

View 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

View File

View 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
}

View File

@ -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));
}
});
}
}

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -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);
}

View File

@ -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); }
}

View File

@ -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);
}
}

View File

@ -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) {
}
}

View File

@ -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); }
}

View File

@ -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) {
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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) {
}
}

View File

@ -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); }
}

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View 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>

View 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>

View 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>

View 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>

View 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 components 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 wont interfere "
"when a user tries to pick up one of cards.\n\n"
</string>
<string name="action_settings">Settings</string>
</resources>

View 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>

View File

@ -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

Binary file not shown.

1
settings.gradle Normal file
View File

@ -0,0 +1 @@
include ':mobile', ':wear', ':libtlang'

1
wear/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

35
wear/build.gradle Normal file
View 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
View 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

View 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>

View File

@ -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);
}
});
}
}

View 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>

View 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>

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View 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>