Sunday, May 27, 2012

Clojure macro for LibGDX input polling

A very simple macro:
(defmacro when-pressed
  ([key form]
  `(when (.isKeyPressed Gdx/input (. com.badlogic.gdx.Input$Keys ~key))
     ~form))
  ([key form & rest]
     `(do
        (when-pressed ~key ~form)
        (when-pressed ~@rest))))
example usage:
 (when-pressed LEFT  (do-something)
               RIGHT (do-something-different)
               SPACE ( ... )
               ...)
expands to:
user=> (pprint (macroexpand-1 '(when-pressed LEFT (do-something))))
(clojure.core/when
 (.isKeyPressed Gdx/input (. com.badlogic.gdx.Input$Keys LEFT))
 (do-something))
nil
or
user=> (pprint (macroexpand-1 '(when-pressed LEFT (do-something)
                                             RIGHT (do-something-else))))
(do
 (when-pressed LEFT (do-something))
 (when-pressed RIGHT (do-something-else)))
nil

Saturday, May 12, 2012

Android: A two column ListView with an ImageView

Struggling with ListViews and SimpleAdapters on Android, I came up with the following simple example of a ListView with two columns: an image and some text. In res/layout, create a xml list_item.xml for the listview items:
<?xml version="1.0" encoding="utf-8"?>
<!-- list_item.xml -->
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:paddingTop="4dip"
    android:paddingBottom="6dip"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#ffffff"
    android:orientation="horizontal">
    <ImageView android:layout_width="100px"
       android:layout_height="50px"
       android:layout_gravity="left"
       android:id="@+id/LOGO_CELL"
       />
    <TextView android:id="@+id/TEXT_CELL"
       android:layout_height="wrap_content"
       android:layout_width="wrap_content"
       android:textColor="#000000"
       android:layout_gravity="center"
       android:layout_weight="1"/>

</LinearLayout>

Add a ListView to main.xml main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
  <TextView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="Some Text"
      />
  <ListView  android:id="@+id/LISTVIEW"
      android:orientation="horizontal"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
   >
  </ListView>
</LinearLayout>

Finally, the code:
(ns com.example.android.ListExample 
  (:gen-class
   :extends android.app.Activity
   :exposes-methods {onCreate superOnCreate}
  (:import (android.app Activity)
           (android.os Bundle))))

(defn -onCreate  [this bundle]
    (.superOnCreate this bundle )
    (.setContentView this com.example.android.R$layout/main)
    (let [ids (int-array [com.example.android.R$id/LOGO_CELL
                          com.example.android.R$id/TEXT_CELL])
          names (into-array ["logo" "text"])
          thelist (java.util.ArrayList.
                   [{"logo" com.example.android.R$drawable/logo1 "text" "Text 1"}
                    {"logo" com.example.android.R$drawable/logo2 "text" "Text 2"}]
                   aa (android.widget.SimpleAdapter. this thelist
                                                     com.example.android.R$layout/list_item names ids)]
      (.setAdapter (.findViewById this com.example.android.R$id/LISTVIEW) aa)))
          
This will find the two pngs "logo1.png" and "logo2.png" in the res/drawable folders.