David Janes' Code Weblog

November 11, 2011

Beautiful Code

android,code fragments,java · admin · 8:40 am ·

This is what I’m aiming for — powerful declarations, minimal logic. UIButtonGroup, UIWebView and UIBundleHelper carry a lot of the weight here and I hope to explain (and share) all of these soon.

public class TTActivityInfo
  extends TTAbstractActivity
{
  public Button uiLeftButton;
  public Button uiRightButton;
  public UIButtonGroup buttonGroup;

  public WebView uiWebView;

  static String lActivityTitle = "Welcome!";
  static String lLeftButtonTitle = "Welcome";
  static String lRightButtonTitle = "About the app";

  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);

    this.setContentView(R.layout.tt_activity_info);

    UIHelper.bindViews(this);
    UIHelper.hookupButtons(this);

    _configureWebView();
    _configureNavigationBar();
    _configureButtons();

    UIBundleHelper.restoreActivityStateFromBundle(this, savedInstanceState);

    if (savedInstanceState == null) {
      _forceWebViewToCurrentState();
    }
  }

  @Override
  protected void onSaveInstanceState(Bundle _bundle)
  {
    UIBundleHelper.saveActivityStateToBundle(this, _bundle);
  }

  protected void _configureNavigationBar()
  {
    TTUI.configureNavigationBarTitle(this, lActivityTitle);
  }

  protected void _configureButtons()
  {
    TTUI.configureBlueButton(this, uiLeftButton, lLeftButtonTitle);
    TTUI.configureBlueButton(this, uiRightButton, lRightButtonTitle);

    buttonGroup = new UIButtonGroup(uiLeftButton, uiRightButton);
    buttonGroup.select(uiLeftButton);
  }

  protected void _configureWebView()
  {
    if (uiWebView == null) {
      return;
    }

    uiWebView.getSettings().setJavaScriptEnabled(true);
    uiWebView.setWebViewClient(new UIWebViewClient(this, "uiWebView"));
  }

  protected void _forceWebViewToCurrentState()
  {
    if (uiWebView == null) {
      return;
    }

    if (buttonGroup.getSelectedButton() == uiRightButton) {
      uiWebView.loadUrl("http://www.google.com");
    } else {
      uiWebView.loadUrl("http://www.davidjanes.com");
    }
  }

  public void _handleButtonSelected(Button _button)
  {
    buttonGroup.select(_button);

    _forceWebViewToCurrentState();
  }

  public void uiLeftButton_onClick(Button _button)
  {
    _handleButtonSelected(_button);
  }

  public void uiRightButton_onClick(Button _button)
  {
    _handleButtonSelected(_button);
  }
}

October 24, 2011

Automatically Binding Resources to Methods in Android Applications

android,code fragments,java · admin · 4:33 pm ·

AKA I’m as mad as hell at Java and not taking it any more Part II.

When developing Android applications, binding resources to end method calls is even more annoying than binding resources to variables.

One approach is to create an anonymous inner classes implementing various listener interface.

UIButton postButton = (Button) findViewById(R.id.share_post);
postButton.setOnClickListener(new View.OnClickListener() {
  public void onClick(View v) {
    // do stuff ...
  }
}

The other is to just implement the listener interface with whatever activity you’re using and figure out what button is being pressed.

I’d just as soon have the data wired up automatically to functions if it’s there. Here’s how I’m doing it now.

In MyActivity:

// class fields
public ImageButton uiButtonDining;

// in onCreate
UIHelper.bindImageButtons(this);

This will automatically wire to the following function

public void uiButtonDining_onClick(ImageButton _imageButton)
{
  // ... do stuff ...
}

I’ve only done this for ImageButton so far but I’m hoping this approach will scale for various other widgets.

The Code

Here’s The Magic for UIHelper.java:

static public void bindImageButtons(final Activity _activity) {
  Field[] instance_fields = _activity.getClass().getDeclaredFields();
  for (final Field instance_field : instance_fields) {
    if (!ImageButton.class.isAssignableFrom(instance_field.getType())) {
      continue;
    }

    LogHelper.debug(true, _activity, "field=" + instance_field.getName());

    try {
      final ImageButton button = (ImageButton) instance_field.get(_activity);
      if (button == null) {
        LogHelper.debug(true, _activity,
        "Button is stil NULL", "field=" + instance_field.getName());
        continue;
      }

      String callback_onClick_name = instance_field.getName() + "_onClick";
      try {
        final Method callback_onClick = _activity.getClass().getMethod(
         callback_onClick_name, ImageButton.class);

        button.setOnClickListener(new View.OnClickListener() {
          public void onClick(View v) {
            LogHelper.debug(false, _activity, "clicked", "field=" + instance_field.getName());

            try {
              callback_onClick.invoke(_activity, button);
            } catch (IllegalAccessException x) {
              LogHelper.debug(true, _activity,
              "Couldn't invoke callback", "callback=", callback_onClick, x);
            } catch (InvocationTargetException x) {
              LogHelper.debug(true, _activity,
              "Couldn't invoke callback", "callback=", callback_onClick, x);
            }
          }
        });
      } catch (NoSuchMethodException x) {
        LogHelper.debug(true, _activity,
        "no callback", "method=", callback_onClick_name);
      }
    } catch (IllegalAccessException x) {
      LogHelper.debug(true, _activity,
      "Can't set R.id", "name=", instance_field.getName(), x);
    }
  }
}

October 23, 2011

Dynamically resize and stack many UIViews

code fragments,iphone · admin · 5:58 pm ·

The iOS’s UILabel is kind of an annoying beast – out-of-the-box it takes coding to get the correct height or to “top justify” it. If there’s too much text inside a UILabel, sometimes it shrinks the text which visually doesn’t make it look that great – the ideal solution would be to split the text over multiple lines and adjust everything else downward dynamically. Also if you have to have multiple labels with different styles a typical solution would be to use a UIWebView controller. However, this isn’t really suitable inside a UITableView where you have to have many views and you need to know the exact space to allocate.

Here’s a helper function that will take an Array of UIViews and stack them up, returning the height. If any of the UIViews are UILabels, it’ll resize them to the appropriate height.

/*
 *  Stack views on top of each other starting at a point.
 *  If they are labels, we resize. Return the height used.
 */
+ (CGFloat) uiStack:(NSArray*)_views startingAt:(CGPoint)_point
{
  if (!_views || !_views.count) {
    return  0;
  }

  for (UIView* view in _views) {
    if ([view isKindOfClass:[UILabel class]]) {
      UILabel* label = (UILabel*) view;
      CGSize labelSize = [label.text
                sizeWithFont:label.font
                constrainedToSize:CGSizeMake(label.frame.size.width, 1000.0)
                lineBreakMode:label.lineBreakMode];

      label.frame = CGRectMake(_point.x, _point.y, view.frame.size.width, labelSize.height);
      _point.y += labelSize.height;
    } else {
      view.frame = CGRectMake(_point.x, _point.y, view.frame.size.width, view.frame.size.height);
      _point.y += view.frame.size.height;
    }
  }

  return _point.y;
}

Enjoy!

Automatically Binding Resources to Fields in Android Applications

android,code fragments,java · admin · 4:53 pm ·

AKA I’m as mad as hell at Java and not taking it any more.

Here’s how I’ve been getting access to various UI resources in my Android applications. Almost certainly, you’re doing the same thing too.

layout/file.xml:

<TextView android:id="@+id/title" ... />

File.java:

TextView title = (TextView) parent.findViewById(R.id.title);

Over and over for as many UI elements as I need to access. To hell with that.

Here’s my new method of doing this

First, give the ID and the Fields the same name:

layout/file.xml:

<TextView android:id="@+id/uiTitleTextView" ... />

File.java:

public TextView uiTitleTextView;

Note that that’s a class field — it’s not in the method, and it must be public Then in onCreate I just do this:

UIHelper.bindViews(this);

And that’s it: every field just gets wired up.

The Code

Here’s The Magic for UIHelper.java:

static public void bindViews(Activity _activity)
{
  Field[] instance_fields = _activity.getClass().getDeclaredFields();
  for (Field instance_field : instance_fields) {
    if (!View.class.isAssignableFrom(instance_field.getType())) {
      continue;
    }

    try {
      Field id_field = R.id.class.getField(instance_field.getName());
      int r = id_field.getInt(R.id.class);

      View view = _activity.findViewById(r);
      if (view == null) {
        LogHelper.debug(true, _activity,
          "Field expected in Layout but not found", "name=",
          instance_field.getName());
        continue;
      }

      instance_field.set(_activity, view);
    } catch (NoSuchFieldException x) {
      LogHelper.debug(true, _activity,
        "Field expected in R.id but not found", "name=",
        instance_field.getName());
    } catch (IllegalAccessException x) {
      LogHelper.debug(true, _activity,
        "Can't set R.id", "name=",
        instance_field.getName(), x);
    }
  }
}

How to use custom fonts in Android applications

android,code fragments,java · admin · 3:07 pm ·

Here’s how to use custom fonts in your Android application.

  1. Select your font – for example, Ubuntu. Make sure you use a royalty-free font (such as that one) or you pay the appropriate licensing fee (because you could get in a world of legal pain and because don’t be a dick)
  2. In the root folder of your Android project, make sure there’s a folder called assets/fonts. The fonts subdirectory is entirely optional but to my taste.
  3. You cannot specify the font (really the typeface) in your resources, so you have to do in code as follows
Typeface font = Typeface.createFromAsset(_activity.getAssets(), "fonts/Ubuntu-Bold.ttf");
textView.setTypeface(font);

And that’s it.

September 18, 2011

Adding alpha levels to images with PIL

code fragments,pil,python,tips · admin · 4:54 am ·

I recently was tasked by a client with replacing a number of images — PNGs with alpha levels, such that parts of the image were transparent — with new pictures. The issue was how to get the exact same alpha level holes in the new images.

Here’s how I did it. I renamed one of the original images “template.png” and assumed that all the source images will the exactly the same size as the template. I then wrote this Python script using the Python Imaging Library.

import sys
import os
import re
import Image

#
#   Get the template
#
itemplate = Image.open("template.png")
itemplate.getpixel(( 0, 0 ))
r, g, b, alpha = itemplate.split()

#
#   Get the JPGs - they must be exactly the same size
#
for in_file in os.listdir("."):
    if not in_file.endswith(".jpg"):
        continue

    isrc = Image.open(in_file)
    if isrc.size != itemplate.size:
        continue

    idst = isrc.convert("RGBA")
    idst.putalpha(alpha)

    idst.save(in_file[:-4] + ".png")

February 28, 2011

Foursquare, Python & OAuth2

authentication,code fragments,python · admin · 11:21 am ·

Foursquare has revved their API, but there’s no Python Library to support it. Here’s how to use it from Python

  1. Get OAuth info from foursquare — the callback URL does not matter _but_ you must record here. https://foursquare.com/oauth/register. Fill in the results into CLIENT_ID, CLIENT_SECRET and CALLBACK_URL
  2. Run this, enter the URL in browser, get code as FS_ACCESS_CODE, add back here
  3. Run this, fill in FS_ACCESS_TOKEN
  4. Run this, you’re authorized: enjoy!

Notes

  1. Python OAuth2 from here:  https://github.com/rodbegbie/python-oauth2
  2. This is entirely standing on the shoulder’s of Rod Begbie’s work.

Code:

import oauth2
import json
import pprint

OAUTH_BASE = "https://foursquare.com/oauth2/authenticate"

CLIENT_ID = ""
CLIENT_SECRET = ""
CALLBACK_URL = ""

FS_ACCESS_CODE = ""
FS_ACCESS_TOKEN = ""

client = oauth2.Client2(CLIENT_ID, CLIENT_SECRET, OAUTH_BASE)

if not CLIENT_ID:
  print "=== Register your Foursquare data here"
  print "=== Copy back CLIENT_ID, CLIENT_SECRET and CALLBACK_URL here"
  print "https://foursquare.com/oauth/"
elif FS_ACCESS_TOKEN:
  headers, content = client.request("https://api.foursquare.com/v2/users/self",
   access_token = FS_ACCESS_TOKEN)

  pprint.pprint({
    "headers" : headers,
    "content" : json.loads(content),
  })
elif not FS_ACCESS_CODE:
  print "=== Enter this URL in your browser."
  print "=== Copy the CODE in the URL that results into FS_ACCESS_CODE"
  print client.authorization_url(redirect_uri = CALLBACK_URL, 
    endpoint='authenticate')
else:
  print "=== Here is your Access Token"
  print "=== Copy into FS_ACCESS_TOKEN as start using Foursquare"
  print client.access_token(FS_ACCESS_CODE, redirect_uri= CALLBACK_URL,
    grant_type='authorization_code')["access_token"]

December 28, 2010

Display only one jPicker at a time

code fragments,javascript,jquery · David Janes · 9:26 am ·

I’ve been playing with jQuery (in general) and jPicker (in particular) over the last few days. I’m using jPicker because it’s not only a color picker but it also supports alpha-levels.

One – major – issue I’ve had is that jPicker doesn’t make it very easy to display only one control at a time, making the screen a bit of a visual mess when multiple color fields are being used.

Here’s how I fixed this.

$(document).ready(function() {
    $('body').click(function(evt) {
        if ($('div.jPicker.Container:visible').length > 0) {
            if ($(evt.target).parents('span.jPicker').length > 0) {
                $('div.jPicker.Container').each(function() {
                    if ($(this).css('z-index') == '10') {
                        $(this).hide('fast');
                    }
                });
            } else if ($(evt.target).parents('div.jPicker.Container').length == 0) {
                $('div.jPicker.Container').hide('fast');
            }
        }
    });
});

Notes:

  • this will dismiss the current jPicker if you click outside of one
  • the first if makes sure there’s something to do first
  • the second and third ifs take care of the case where the user clicks on the control to popup a jPicker. This takes advantage of the fact that the current jPicker is shown at z-index = 20 (which makes me wonder if we could do a lot of this with just a CSS selector for z-index = 10)
  • the final if takes care of the case where we’ve clicked outside of all jPicker controls

December 24, 2010

Python recipe – sorting strings with numbers in them

code fragments,python · David Janes · 9:16 am ·

Here’s a quick Christmas Eve recipe for sorting lists of strings that have numbers in them at some place.

import re
import string

numeric_rex = re.compile('(\d+)')

def numeric_sorter(a, b):
    av = filter(None, numeric_rex.split(a))
    bv = filter(None, numeric_rex.split(b))

    while av and bv:
        af = av.pop(0)
        bf = bv.pop(0)

        if af[0] in string.digits and bf[0] in string.digits:
            r = cmp(int(af), int(bf))
        else:
            r = cmp(af, bf)

        if r != 0:
            return  r

    if av:
        return  1
    elif bv:
        return  -1
    else:
        return  0

Here’s an example of it being used:

>>> items = [ "Item1", "Item10", "Item", "Item9", "Item100", "ItemLogo", ]
>>> items.sort()
>>> pprint.pprint(items)
['Item', 'Item1', 'Item10', 'Item100', 'Item9', 'ItemLogo']
>>> items.sort(numeric_sorter)
>>> pprint.pprint(items)
['Item', 'Item1', 'Item9', 'Item10', 'Item100', 'ItemLogo']

April 9, 2010

Djolt-obj: Django-like templates for Objective-C

code fragments,djolt,iphone · David Janes · 7:51 am ·

My company, Discover Anywhere Mobile, has open sourced a software component that many iPhone developers may be interested in: Djolt (Django-like Templates) for Objective C. The objective of this project is to be able to take NSObjects – particularly NSDictionary, NSArray, NSString and NSNumber – and be able to feed them to a text template, Django style, and get text output. This will be fantastic for working with APIs that deliver data via JSON or XML.

It’s dependent on RegexKit library for now, though if the iPhone OS 4 NSRegularExpression is powerful enough we may transition to that.

The code is being tested against the Django template test cases, with the goal of having as complete as possible (given different language idioms) compatibility. We only cover a small subset of Django yet – the stuff we need – but if you’re interested in working on the project, please by all means join in.

Code

NSDictionary* d = [[NSData dataWithContentsOfFile:@"test.json"] yajl_JSON];

DjoltTemplate* t = [[DjoltTemplate alloc] initWithTemplateFile:@"test.djolt"];
NSString* r = [t render:d];

test.json

{
 "title" : "Test 1",
 "items" : [
  {
   "href" : "http://www.example.com/1",
   "title" : "Example 1"
  },
  {
   "href" : "http://www.example.com/2",
   "title" : "Example 2 & Example \"2.5\""
  },
  {
   "href" : "http://www.example.com/3",
   "title" : "Example 3"
  }
 ]
}

test.djolt

<html>
<head>{{ title }}</head>
<body>
{% if fred or items or bleck %}
<ul>
{% for itemd in items %}
<li><a href='{{ itemd.href }}'>{{ itemd.title|safe }}</a> ({{ forloop.counter }})</li>
{% endfor %}
</ul>
{% endif %}
<p>
{{ nothing|default:"something" }}
</p>
</body>
</html>

Output

<html>
<head>Test 1</head>
<body>

<ul>

<li><a href='http://www.example.com/1'>Example 1</a> (1)</li>

<li><a href='http://www.example.com/2'>Example 2 & Example "2.5"</a> (2)</li>

<li><a href='http://www.example.com/3'>Example 3</a> (3)</li>

</ul>

<p>
something
</p>
</body>
</html>
Older Posts »

Powered by WordPress

Switch to our mobile site