summaryrefslogtreecommitdiff
path: root/src/ui/android
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/android')
-rw-r--r--src/ui/android/.classpath7
-rw-r--r--src/ui/android/.project33
-rw-r--r--src/ui/android/AndroidManifest.xml18
-rw-r--r--src/ui/android/default.properties13
-rw-r--r--src/ui/android/res/drawable/brushed_metal.pngbin0 -> 36233 bytes
-rw-r--r--src/ui/android/res/drawable/icon.pngbin0 -> 2574 bytes
-rw-r--r--src/ui/android/res/layout/main.xml25
-rw-r--r--src/ui/android/res/values/strings.xml5
-rw-r--r--src/ui/android/src/org/grammaticalframework/fridge/FridgeMagnets.java151
-rw-r--r--src/ui/android/src/se/fnord/android/layout/PredicateLayout.java134
10 files changed, 386 insertions, 0 deletions
diff --git a/src/ui/android/.classpath b/src/ui/android/.classpath
new file mode 100644
index 000000000..6e9239ff0
--- /dev/null
+++ b/src/ui/android/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/src/ui/android/.project b/src/ui/android/.project
new file mode 100644
index 000000000..c24012a32
--- /dev/null
+++ b/src/ui/android/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>GF-Android</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/src/ui/android/AndroidManifest.xml b/src/ui/android/AndroidManifest.xml
new file mode 100644
index 000000000..be36eaf2d
--- /dev/null
+++ b/src/ui/android/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.grammaticalframework.fridge"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application android:icon="@drawable/icon" android:label="@string/app_name">
+ <activity android:name=".FridgeMagnets"
+ 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>
+ <uses-sdk android:minSdkVersion="2" />
+
+</manifest> \ No newline at end of file
diff --git a/src/ui/android/default.properties b/src/ui/android/default.properties
new file mode 100644
index 000000000..19c96655d
--- /dev/null
+++ b/src/ui/android/default.properties
@@ -0,0 +1,13 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Indicates whether an apk should be generated for each density.
+split.density=false
+# Project target.
+target=android-4
diff --git a/src/ui/android/res/drawable/brushed_metal.png b/src/ui/android/res/drawable/brushed_metal.png
new file mode 100644
index 000000000..c2f03fe7d
--- /dev/null
+++ b/src/ui/android/res/drawable/brushed_metal.png
Binary files differ
diff --git a/src/ui/android/res/drawable/icon.png b/src/ui/android/res/drawable/icon.png
new file mode 100644
index 000000000..a07c69fa5
--- /dev/null
+++ b/src/ui/android/res/drawable/icon.png
Binary files differ
diff --git a/src/ui/android/res/layout/main.xml b/src/ui/android/res/layout/main.xml
new file mode 100644
index 000000000..67ce499fb
--- /dev/null
+++ b/src/ui/android/res/layout/main.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/main_view"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="@drawable/brushed_metal"
+ >
+ <se.fnord.android.layout.PredicateLayout
+ android:id="@+id/magnets_sentence"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="5dip"/>
+
+ <View
+ android:layout_height="8dip"
+ android:layout_width="fill_parent"
+ android:background="#FF909090"/>
+
+ <se.fnord.android.layout.PredicateLayout
+ android:id="@+id/magnets_bag"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="5dip"/>
+</LinearLayout>
diff --git a/src/ui/android/res/values/strings.xml b/src/ui/android/res/values/strings.xml
new file mode 100644
index 000000000..662c708c1
--- /dev/null
+++ b/src/ui/android/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello">Hello World, FridgeMagnets!</string>
+ <string name="app_name">Fridge Magnets</string>
+</resources>
diff --git a/src/ui/android/src/org/grammaticalframework/fridge/FridgeMagnets.java b/src/ui/android/src/org/grammaticalframework/fridge/FridgeMagnets.java
new file mode 100644
index 000000000..32c71ba0d
--- /dev/null
+++ b/src/ui/android/src/org/grammaticalframework/fridge/FridgeMagnets.java
@@ -0,0 +1,151 @@
+package org.grammaticalframework.fridge;
+
+import java.util.Arrays;
+
+import android.os.*;
+import android.app.*;
+import android.content.*;
+import android.text.*;
+import android.view.*;
+import android.view.inputmethod.*;
+import android.widget.*;
+import android.graphics.*;
+import se.fnord.android.layout.*;
+
+public class FridgeMagnets extends Activity {
+ /** Called when the activity is first created. */
+ String[] words = {"hello","buy","I","you","have","please","where",
+ "how","go","Gothenburg","London","rakia","wine",
+ "whisky","man","woman","boy","girl","to"};
+
+ private Controller controller = new Controller();
+ private EditText searchBox = null;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ Arrays.sort(words);
+
+ refreshBagOfWords(null);
+
+ View main = findViewById(R.id.main_view);
+ main.setFocusableInTouchMode(true);
+ main.setOnKeyListener(controller);
+ }
+
+ private void applyMagnetStyles(TextView view) {
+ view.setTextColor(Color.BLACK);
+ view.setBackgroundColor(Color.WHITE);
+ view.setSingleLine(true);
+ view.setPadding(2, 2, 2, 2);
+ view.setClickable(true);
+ }
+
+ private void refreshBagOfWords(String prefix) {
+ PredicateLayout l = (PredicateLayout) findViewById(R.id.magnets_bag);
+
+ l.removeAllViews();
+
+ for (int i = 0; i < words.length; i++) {
+ if (prefix != null && !words[i].startsWith(prefix))
+ continue;
+
+ TextView t = new TextView(this);
+ t.setText(words[i]);
+ t.setOnTouchListener(controller);
+ applyMagnetStyles(t);
+ l.addView(t, new PredicateLayout.LayoutParams(3, 3));
+ }
+ }
+
+ private void addWord(String word) {
+ PredicateLayout l = (PredicateLayout) findViewById(R.id.magnets_sentence);
+
+ TextView t = new TextView(this);
+ t.setText(word);
+ applyMagnetStyles(t);
+ l.addView(t, new PredicateLayout.LayoutParams(3, 3));
+ }
+
+ private void showSearchBox() {
+ if (searchBox != null)
+ return;
+
+ PredicateLayout l = (PredicateLayout) findViewById(R.id.magnets_sentence);
+
+ EditText edit = new EditText(this);
+ edit.setInputType(InputType.TYPE_CLASS_TEXT |
+ InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
+ edit.addTextChangedListener(controller);
+ edit.setOnKeyListener(controller);
+ applyMagnetStyles(edit);
+
+ l.addView(edit, new PredicateLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ 3, 3));
+ edit.requestFocus();
+ InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(edit, 0);
+
+ searchBox = edit;
+ }
+
+ private void hideSearchBox() {
+ if (searchBox == null)
+ return;
+
+ InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(searchBox.getWindowToken(), 0);
+
+ PredicateLayout l = (PredicateLayout) findViewById(R.id.magnets_sentence);
+ l.removeView(searchBox);
+
+ refreshBagOfWords(null);
+
+ searchBox = null;
+ }
+
+ private class Controller implements View.OnKeyListener, View.OnTouchListener, TextWatcher {
+
+ @Override
+ public boolean onKey(View view, int keyCode, KeyEvent event) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ if (searchBox == null && keyCode == KeyEvent.KEYCODE_SEARCH) {
+ showSearchBox();
+ return true;
+ } else if (searchBox != null && keyCode == KeyEvent.KEYCODE_SEARCH) {
+ hideSearchBox();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onTouch(View view, MotionEvent event) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ hideSearchBox();
+ addWord(((TextView) view).getText().toString());
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public void afterTextChanged(Editable arg0) {
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence text, int arg1, int arg2, int arg3) {
+ refreshBagOfWords(text.toString());
+ }
+ }
+} \ No newline at end of file
diff --git a/src/ui/android/src/se/fnord/android/layout/PredicateLayout.java b/src/ui/android/src/se/fnord/android/layout/PredicateLayout.java
new file mode 100644
index 000000000..4734d4618
--- /dev/null
+++ b/src/ui/android/src/se/fnord/android/layout/PredicateLayout.java
@@ -0,0 +1,134 @@
+package se.fnord.android.layout;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * ViewGroup that arranges child views in a similar way to text, with them laid
+ * out one line at a time and "wrapping" to the next line as needed.
+ *
+ * Code licensed under CC-by-SA
+ *
+ * @author Henrik Gustafsson
+ * @see http://stackoverflow.com/questions/549451/line-breaking-widget-layout-for-android
+ * @license http://creativecommons.org/licenses/by-sa/2.5/
+ *
+ */
+public class PredicateLayout extends ViewGroup {
+
+ private int line_height;
+
+ public static class LayoutParams extends ViewGroup.LayoutParams {
+ public final int horizontal_spacing;
+ public final int vertical_spacing;
+
+ /**
+ * @param horizontal_spacing Pixels between items, horizontally
+ * @param vertical_spacing Pixels between items, vertically
+ */
+ public LayoutParams(int horizontal_spacing, int vertical_spacing) {
+ this(0, 0, horizontal_spacing, vertical_spacing);
+ }
+
+ /**
+ * @param width
+ * @param height
+ * @param horizontal_spacing Pixels between items, horizontally
+ * @param vertical_spacing Pixels between items, vertically
+ */
+ public LayoutParams(int width, int height, int horizontal_spacing, int vertical_spacing) {
+ super(width, height);
+ this.horizontal_spacing = horizontal_spacing;
+ this.vertical_spacing = vertical_spacing;
+ }
+ }
+
+ public PredicateLayout(Context context) {
+ super(context);
+ }
+
+ public PredicateLayout(Context context, AttributeSet attrs){
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ assert(MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED);
+
+ final int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
+ int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
+ final int count = getChildCount();
+ int line_height = 0;
+
+ int xpos = getPaddingLeft();
+ int ypos = getPaddingTop();
+
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ child.measure(
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
+
+ final int childw = child.getMeasuredWidth();
+ line_height = Math.max(line_height, child.getMeasuredHeight() + lp.vertical_spacing);
+
+ if (xpos + childw > width) {
+ xpos = getPaddingLeft();
+ ypos += line_height;
+ }
+
+ xpos += childw + lp.horizontal_spacing;
+ }
+ }
+ this.line_height = line_height;
+
+ if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED){
+ height = ypos + line_height;
+
+ } else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST){
+ if (ypos + line_height < height){
+ height = ypos + line_height;
+ }
+ }
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
+ return new LayoutParams(1, 1); // default of 1px spacing
+ }
+
+ @Override
+ protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
+ if (p instanceof LayoutParams)
+ return true;
+ return false;
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ final int count = getChildCount();
+ final int width = r - l;
+ int xpos = getPaddingLeft();
+ int ypos = getPaddingTop();
+
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ final int childw = child.getMeasuredWidth();
+ final int childh = child.getMeasuredHeight();
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ if (xpos + childw > width) {
+ xpos = getPaddingLeft();
+ ypos += line_height;
+ }
+ child.layout(xpos, ypos, xpos + childw, ypos + childh);
+ xpos += childw + lp.horizontal_spacing;
+ }
+ }
+ }
+} \ No newline at end of file