<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>frameworker</title>
	<atom:link href="http://frameworker.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://frameworker.wordpress.com</link>
	<description>Using object frameworks to build software</description>
	<lastBuildDate>Thu, 10 Nov 2011 05:43:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='frameworker.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>frameworker</title>
		<link>http://frameworker.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://frameworker.wordpress.com/osd.xml" title="frameworker" />
	<atom:link rel='hub' href='http://frameworker.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Thank you, Steve</title>
		<link>http://frameworker.wordpress.com/2011/10/14/thank-you-steve/</link>
		<comments>http://frameworker.wordpress.com/2011/10/14/thank-you-steve/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 18:30:32 +0000</pubDate>
		<dc:creator>frameworker</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://frameworker.wordpress.com/?p=315</guid>
		<description><![CDATA[Steve changed my life completely in a good way. First, in the 1980&#8242;s, Macintosh became a vehicle that infused my – languishing – career with new purpose. And then again, when I lost my bearing in the last decade, OS X was a nurturing place to come home to. I fervently hope that Steve felt [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=315&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Steve changed my life completely in a good way. First, in the 1980&#8242;s, Macintosh became a vehicle that infused my – languishing – career with new purpose. And then again, when I lost my bearing in the last decade, OS X was a nurturing place to come home to. I fervently hope that Steve felt the deep gratitude of the developer community for having begotten this fertile ground for our achievement. Namasté, Steve.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/frameworker.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/frameworker.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/frameworker.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/frameworker.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/frameworker.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/frameworker.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/frameworker.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/frameworker.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/frameworker.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/frameworker.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/frameworker.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/frameworker.wordpress.com/315/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/frameworker.wordpress.com/315/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/frameworker.wordpress.com/315/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=315&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://frameworker.wordpress.com/2011/10/14/thank-you-steve/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6d6ddc877489e0012793019337be11e0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joely</media:title>
		</media:content>
	</item>
		<item>
		<title>Cocoa to Cappuccino &#8211; Spatially Formatting Text Fields</title>
		<link>http://frameworker.wordpress.com/2010/04/20/cocoa-to-cappuccino-%e2%80%93-spatially-formatting-text-fields/</link>
		<comments>http://frameworker.wordpress.com/2010/04/20/cocoa-to-cappuccino-%e2%80%93-spatially-formatting-text-fields/#comments</comments>
		<pubDate>Tue, 20 Apr 2010 06:18:39 +0000</pubDate>
		<dc:creator>frameworker</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://frameworker.wordpress.com/?p=294</guid>
		<description><![CDATA[OVERVIEW I&#8217;m using pdf images as the background of electronic forms. The purpose of doing this is to make the electronic form feel just like the familiar paper one. It&#8217;s user friendly. Also the electronic forms can perform calculations automatically and accurately. WHY A WIDE STRING? One of the cases that inevitably has to be [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=294&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>OVERVIEW</strong></p>
<p>I&#8217;m using pdf images as the background of electronic forms. The purpose of doing this is to make the electronic form feel just like the familiar paper one. It&#8217;s user friendly. Also the electronic forms can perform calculations automatically and accurately.</p>
<p><strong>WHY A WIDE STRING?</strong></p>
<p>One of the cases that inevitably has to be handled is when a string has to be entered, with its characters equally spaced in a sequence of contiguous boxes, like this:</p>
<p><a href="http://frameworker.files.wordpress.com/2010/04/account-number1.png"><img class="alignnone size-full wp-image-307" title="Account Number" src="http://frameworker.files.wordpress.com/2010/04/account-number1.png?w=488&#038;h=20" alt="" width="488" height="20" /></a></p>
<p><strong>THE COCOA WAY</strong></p>
<p>Cocoa has this nifty <em>NSString</em> method, <em>drawAtPoint</em>, that lets you do this when the field is not active. (But when it is active you can enter the string – unformatted – in the text field, which exactly covers the boxes in the background, so it all feels quite natural.)</p>
<p><pre class="brush: cpp;">
- (void)drawRect:(NSRect)rect
{
    if ((![self focus]) &amp;&amp; ([self format] == kWideFormat))
    {
        // drawWideString calculates the bounds for each character
        // and calls a routine to draw it using drawAtPoint.
        [self drawWideString: [self stringValue]];
    }
    else
    {
        [super drawRect:rect];
    }
}
</pre></p>
<p><strong>THE CAPPUCCINO WAY</strong></p>
<p>Unfortunately, there is no <em>-[CPString drawAtPoint]</em> method in Cappuccino, so this approach can&#8217;t be used.</p>
<p>I must confess that this &#8220;deficiency&#8221; left me with some confusion about how to procceed to implement the WIDE string behavior in Cappuccino.</p>
<p>I wondered if there was a way to do it using Canvas or CSS, or if Cappuccino text support for this kind of thing might be “just around the corner.”</p>
<p>And the sledgehammer approach of creating a sequence of single character text fields to display the inactive text, to be swapped-out with a regular text field while editing, seemed inelegant.</p>
<p>But a recent conversation with @saikatc at #shdh37 convinced me that the “buffered” approach was, in fact, a reasonable way to do this. And as it is with so many things in life, once the approach was determined, it started happening.</p>
<p><strong>KEY MECHANISM</strong></p>
<p>The one <em>CPTextField</em> subclass I use throughout the forms project overrides <em>becomeFirstResponder</em> / <em>resignFirstResponder</em> to bracket the active field with <em>controlTextDidBeginEditing</em> / <em>controlTextDidEndEditing</em> calls, something that neither Cocoa nor Cappuccino does, but which is critical to knowing when to swap the static text array in and out with the regular text field. Having this mechanism obviates the need for a special <em>CPTextField</em> subclass for these WIDE fields!</p>
<p>The <em>Begin</em>/<em>End Editing</em> messages are passed to the Text Field’s delegate, a widget subclass, which sends <em>setFocusedDisplayFormat</em>/<em>setUnfocusedDisplayFormat</em> messages to the object being <em>activated</em>/<em>inactivated</em>.</p>
<p>It&#8217;s important to note that the approach used here takes advantage of fact that the text field covers the char-array. If this were not the case, it would be necessary to buffer the char-array&#8217;s stringValues, so they wouldn&#8217;t be displayed, while the text field was active. That would be confusing.</p>
<p>So to avail ourselves of this pattern, we create a WIDE Widget subclass which switches the display of the static array on and off.</p>
<p>Here&#8217;s the code for that class.</p>
<p><em>PDQWideWidget</em> descends from the concrete <em>PDQTextWidget</em> class and adds an array for the equally spaced characters.</p>
<p><pre class="brush: cpp;">
// PDQWideWidget.j

@import &quot;PDQTextWidget.j&quot;

@implementation PDQWideWidget : PDQTextWidget

{
	CPMutableArray chars @accessors; // The array of equally spaced characters
}
</pre></p>
<p>Init calls super, then creates the array.</p>
<p><pre class="brush: cpp;">
- (id) init
{
	self = [super init];

	if (self)
	{
		// Do any initialization here!
		chars = [];
	}

    return self;
}
</pre></p>
<p><em>makeView</em> is overridden to create the array of one-char text fields. The order in which the constituent fields are created is crucial. The real <em>CPTextField</em> is created last, so it will be on top and receive mouse events. And the widget is put into &#8220;unfocused&#8221; mode.</p>
<p><pre class="brush: cpp;">
- (void)makeView:(CPView)itsSuperview
{
	[self buildChars:itsSuperview];

	[super makeView:itsSuperview];

	[self setUnfocusedDisplayFormat];
}
</pre></p>
<p><em>buildChars</em> builds the array of one-char text fields using the <em>maxLen</em> parameter to determine how many to create that will cover the <em>widgetRect</em>.</p>
<p><pre class="brush: cpp;">
- (void)buildChars:(CPView)itsSuperview
{
	var frameRect = [self widgetRect];

	var width   = frameRect.size.width;
	var height  = frameRect.size.height;
	var x	    = frameRect.origin.x;
	var y	    = frameRect.origin.y;

	var cellWidth = width/[self maxLen];

	for (var index = 0; index &lt; [self maxLen]; index++)
	{
		var left = x + cellWidth * index;
		var charFrame = CGRectMake(left, y, cellWidth, height); // x,y,w,h

		var newCharField = [[CPTextField alloc] initWithFrame:charFrame];

		[self initCharField: newCharField];
		[newCharField setStringValue: @&quot;&quot;];
		[newCharField setDelegate:self];
		[itsSuperview addSubview:newCharField];
		[chars addObject: newCharField];
	}
}
</pre></p>
<p>Each <em>charField</em> must be initialized to (among other things) not accept events nor become a responder.</p>
<p><pre class="brush: cpp;">
- (void) initCharField:(CPTextField)aCharField
{
	[aCharField setBordered:NO];
	[aCharField setBezeled:NO];
	[aCharField setEditable:NO];
	[aCharField setEnabled:NO];
	[aCharField setSelectable:NO];
	[aCharField setAlignment: CPCenterTextAlignment];
	[aCharField setBackgroundColor:[CPColor clearColor]];
	[aCharField setDrawsBackground:YES];
	[aCharField setVerticalAlignment:CPCenterVerticalTextAlignment];
	[aCharField setFont:[PDQAbstractWidget getFont]];
}
</pre></p>
<p>When the text field is focused, compose and set its <em>stringValue</em> from the char-array. The TextField will be displayed over the char-array, masking it.</p>
<p><pre class="brush: cpp;">
- (void)setFocusedDisplayFormat
{
	// Build the stringValue from the char-array

	var itsStringValue = @&quot;&quot;;

	for (var index = 0; index &lt; [chars count]; index++)
	{
		var aCharField = [chars objectAtIndex: index];
		var aChar = [aCharField stringValue];
		itsStringValue += aChar;
	}

	[[self attachedControl] setStringValue:itsStringValue];
}
</pre></p>
<p>When the text field loses focus, or is first created, unpack <em>stringValue</em> into the char-array, then clear <em>stringValue</em>. The equally spaced chars will be displayed, but the empty TextField covering it, will not.</p>
<p><pre class="brush: cpp;">
- (void)setUnfocusedDisplayFormat
{
	// Set the chars from stringValue and then clear it.
	var itsStringValue = [[self attachedControl] stringValue];
	var count = [itsStringValue length];

	for (var index = 0; index &lt; count; index++)
	{
		var aCharField = [chars objectAtIndex: index];
		[aCharField setStringValue: [itsStringValue characterAtIndex:index]];
	}

	[[self attachedControl] setStringValue:@&quot;&quot;];
}
</pre></p>
<p>&nbsp;</p>
<p><pre class="brush: cpp;">
@end
</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/frameworker.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/frameworker.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/frameworker.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/frameworker.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/frameworker.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/frameworker.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/frameworker.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/frameworker.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/frameworker.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/frameworker.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/frameworker.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/frameworker.wordpress.com/294/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/frameworker.wordpress.com/294/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/frameworker.wordpress.com/294/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=294&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://frameworker.wordpress.com/2010/04/20/cocoa-to-cappuccino-%e2%80%93-spatially-formatting-text-fields/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6d6ddc877489e0012793019337be11e0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joely</media:title>
		</media:content>

		<media:content url="http://frameworker.files.wordpress.com/2010/04/account-number1.png" medium="image">
			<media:title type="html">Account Number</media:title>
		</media:content>
	</item>
		<item>
		<title>OPTIMIZING PDQFORMS</title>
		<link>http://frameworker.wordpress.com/2010/03/20/pdqforms-optimizations/</link>
		<comments>http://frameworker.wordpress.com/2010/03/20/pdqforms-optimizations/#comments</comments>
		<pubDate>Sat, 20 Mar 2010 19:52:12 +0000</pubDate>
		<dc:creator>frameworker</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://frameworker.wordpress.com/?p=271</guid>
		<description><![CDATA[I&#8217;d been testing PDQForms and hadn&#8217;t seen any performance problems, but then I saw a noticable recalculation delay when certain fields were changed in a particular form. After a moment of doubt whether my approach was simply wrong, I sucked it up and asked myself &#8220;What would Mike Ash do?&#8221; So I jumped into the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=271&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;d been testing PDQForms and hadn&#8217;t seen any performance problems, but then I saw a noticable recalculation delay when certain fields were changed in a particular form.  </p>
<p>After a moment of doubt whether my approach was simply wrong, I sucked it up and asked myself <em>&#8220;What would <a href="http://www.mikeash.com/pyblog/">Mike Ash</a> do?&#8221;</em></p>
<p>So I jumped into the debugger, and after tracing the flow of execution &#8211; aided by liberal logging of intermediate results &#8211; I realized that I was seeing a cascading dependency problem.</p>
<p>I was adding a notifier for each cell reference in a formula, so when it had more than one reference to the same cell, I was creating duplicate notifiers.  And if that cell was referenced more than once in another cell&#8217;s formula, there would be duplicated recalculations.  This is what I was seeing*.  And the problem could become arbitrarily worse than this, since there could be an indefinite coupling of such formulae.  Ouch!</p>
<p>* Formula A, of cell a, has n references to cell b, who&#8217;s formula B contains m references to cell c.  So when cell c changes, formula B would be recalculated m times and formula A would be recalculated m * n times.  </p>
<p>The solution to this cascading dependency problem was to allow only one notifier for any cell reference in a formula, even if the cell was referenced more than once in that formula.</p>
<p><strong>THE PATTERN</strong></p>
<p>When a PDQ document is opened, its form widgets are &#8220;internalized.&#8221;  One step in this process is, for widgets that have a formula, to add observers to cells referenced by that formula.  This stack-trace depicts the widget internalization pattern.</p>
<p><strong>-[PDQDocument windowControllerDidLoadNib:]</strong><br />
Code added here is executed when the windowController has loaded the document&#8217;s window.</p>
<p>&nbsp; <strong>-[PDQDocument internalizeWidgets]</strong><br />
&nbsp; This contains the widgets&#8217; internalization logic.</p>
<p>&nbsp; &nbsp; <strong>-[PDQDocument observeReferencedCells]</strong><br />
&nbsp; &nbsp; This document method calls observeReferencedCells for each widget.</p>
<p>&nbsp; &nbsp; &nbsp; <strong> -[PDQAbstractWidget observeReferencedCells]</strong><br />
&nbsp; &nbsp; &nbsp; Adds notifications to observe each cell referenced by this widget.</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <strong>-[NSString coalesceObservers]</strong><br />
&nbsp; &nbsp; &nbsp; &nbsp; Constructs the observer list and removes duplicates, before adding notifications.</p>
<p><strong>THE CODE</strong></p>
<p>Here is the add/coalesceObservers code associated with the widget internalization pattern.</p>
<p><strong>observeReferencedCells</strong> creates an array of the referenced cell IDs.  Then it finds the object referenced by each ID and adds an observer to it.</p>
<p><pre class="brush: cpp;">

- (void) observeReferencedCells
{
    if ([self hasExpression])
    {
        NSMutableArray * observers = [[self expression] coalesceObservers];

        int index;
		
        for (index = 0; index &lt; [observers count]; index++) // Work OK for empty array?
        {
            NSString * theToken =  [observers objectAtIndex:index];
            
            // iterate the document's widgets (a global variable)

            PDQAbstractWidget *referencedCell = [self findWidgetWithID:theToken];
            [self addObserverToReferencedCell:(PDQAbstractWidget *)referencedCell];
        }
    }
}

</pre></p>
<p><strong>coalesceObservers</strong> constructs the observer list, avoiding duplicates, by copying one instance of each cellRef token into coalescedObservers before adding notifications</p>
<p><pre class="brush: cpp;">

- (NSMutableArray *) coalesceObservers
{
    NSMutableArray * theTokens = [self createTokensForExpression];
    NSMutableArray * coalescedObservers = [NSMutableArray array];

    int index = 0;
    while (index &lt; [theTokens count])
    {
        NSString * theToken = [theTokens objectAtIndex:index];

        if ([theToken tokenType] == eCellRefToken)
        {
            [coalescedObservers addObject:theToken];
			
            // Remove all occurrences of theToken from theTokens.
            [theTokens removeObject:theToken];
        }
        else
        {
            index++;
        }
    }

    return coalescedObservers;
}

</pre></p>
<p>When theReferencedCell changes value <strong>addObserverToReferencedCell</strong> tells the dependent cell to handleVariableChanged by sending the NSNotificationCenter a changed message.</p>
<p>The NSNotificationCenter then sends the observer a PDQReferencedCellChanged message with an object reference to the cell that changed.</p>
<p><pre class="brush: cpp;">

- (void) addObserverToReferencedCell:(PDQAbstractWidget *)theReferencedCell
{
    NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];

    [nc addObserver:self
           selector:@selector(handleReferencedCellChanged:)
           name    :@&quot;PDQReferencedCellChanged&quot;
           object  :theReferencedCell];
}

</pre><br />
</br> </br><br />
<strong>handleReferencedCellChanged</strong> is the &#8220;action procedure&#8221; being set by <strong>addObserverToReferencedCell</strong>.</p>
<p><pre class="brush: cpp;">

// Update the cell's value since a cell it depends on has changed.
- (void) handleReferencedCellChanged:(NSNotification *)notification
{
    [self recalculate];
	
    // Now say &quot;changed&quot; to tell the cells that depend on me to update also. 
    NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
    [nc postNotificationName:@&quot;PDQReferencedCellChanged&quot; object:self];
}

</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/frameworker.wordpress.com/271/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/frameworker.wordpress.com/271/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/frameworker.wordpress.com/271/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/frameworker.wordpress.com/271/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/frameworker.wordpress.com/271/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/frameworker.wordpress.com/271/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/frameworker.wordpress.com/271/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/frameworker.wordpress.com/271/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/frameworker.wordpress.com/271/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/frameworker.wordpress.com/271/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/frameworker.wordpress.com/271/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/frameworker.wordpress.com/271/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/frameworker.wordpress.com/271/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/frameworker.wordpress.com/271/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=271&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://frameworker.wordpress.com/2010/03/20/pdqforms-optimizations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6d6ddc877489e0012793019337be11e0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joely</media:title>
		</media:content>
	</item>
		<item>
		<title>Cocoa to Cappuccino – Thinking About Strings</title>
		<link>http://frameworker.wordpress.com/2010/02/08/thinking-about-strings/</link>
		<comments>http://frameworker.wordpress.com/2010/02/08/thinking-about-strings/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 23:52:40 +0000</pubDate>
		<dc:creator>frameworker</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://frameworker.wordpress.com/?p=252</guid>
		<description><![CDATA[#cocoa-to-cappuccino I found working with strings in Cappuccino to be more logical than in Cocoa, but I experienced some uncertainty about what methods and functions were available in JavaScript. So I thought this example and writeup might be useful to others, who are coming to Cappuccino from Cocoa, as many of us are. One of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=252&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>#cocoa-to-cappuccino</p>
<p>I found working with strings in Cappuccino to be more logical than in Cocoa, but I experienced some uncertainty about what methods and functions were available in JavaScript.  So I thought this example and writeup might be useful to others, who are coming to Cappuccino from Cocoa, as many of us are.</p>
<p>One of the main differences between Cocoa and Cappuccino when working with strings, is that Cappuccino lacks a scanner class.  So Cappuccino applications must handle scanning by themselves.  I thought it would be useful and illustrative to implement a Category that performs scanning, similar to Cocoa&#8217;s NSScanner.  And since JavaScript strings are toll-free bridged to Cappuccino&#8217;s CPString class that was not too difficult.  </p>
<p>I&#8217;ve constructed my API as a Category, rather than as a Subclass, so it can be used with all CPStrings.  It corresponds roughly to NSScanner, but doesn&#8217;t mirror it.</p>
<p>I&#8217;ve maintained a Cocoa-like style. This may change as time goes by, but for now it feels more readable, especially since I&#8217;m going back and forth between Cappuccino and Cocoa.</p>
<p>And I haven&#8217;t addressed performance issues in writing this. The code is adequate for my purposes.  But it would be interesting to profile and optimize it somewhere down the line.</p>
<p><strong>IMPLEMENTATION NOTE:</strong>  I&#8217;m not currently supporting &#8220;skip characters.&#8221;  That&#8217;s because the next scan position is determined by the length of the previously scanned string.  If you skip characters there isn&#8217;t a simple way (that I could think of) to communicate this to the next use of the the scanner.  Also all scans are case sensitive.  An extended scanning category could add methods to support these.  But for now, I&#8217;m avoiding that to keep things simple.</p>
<p>If you&#8217;re not familiar with NSScanner, it&#8217;s useful to note that the term &#8220;scan&#8221; means scanning from a particular starting point.  That is, if you&#8217;re scanning for a particular string and it isn&#8217;t at the starting location of the string being scanned, then an empty string will be returned.</p>
<p>I&#8217;ll summarize the API here, but it will be much more instructive to view the source, which I&#8217;ve wrapped in a test program called <a href="http://dl.dropbox.com/u/2248/cappscanner.zip">cappscanner</a>.</p>
<p><strong>SCANNING METHODS</strong></p>
<p>scanString &#8211; scans SELF, returning theString if a match is found.</p>
<p><pre class="brush: cpp;">
    -(CPString)scanString:(CPString)theString startingAt:(int)startIndex
</pre></p>
<p>scanUpToString &#8211; scans SELF until a given string is encountered, accumulating characters into a string that’s returned.  Scans to the end of SELF if stopString is not found.</p>
<p><pre class="brush: cpp;">
- (CPString) scanUpToString:(CPString)stopString startingAt:(int)startIndex
</pre></p>
<p>scanUpToCharactersFromSet &#8211; scans SELF until a stopChar is encountered, accumulating characters into a string that’s returned.  Scans to the end of SELF if no stopChars are found.</p>
<p><pre class="brush: cpp;">
-(CPString)scanUpToCharactersFromSet:(CPString)stopChars startIndex:(int)index
</pre></p>
<p>scanCharactersFromSet &#8211; scans SELF as long as charsToScan are encountered, accumulating characters into a string that’s returned. Returns an empty string if no charsToScan are found.</p>
<p><pre class="brush: cpp;">
-(CPString)scanCharactersFromSet:(CPString)charsToScan startIndex:(int)index
</pre></p>
<p><strong>UTILITY METHODS</strong></p>
<p>stringByReplacingString  &#8211; replaces &#8220;target&#8221; with &#8220;replacement&#8221;, where &#8220;target&#8221; is a substring of SELF.</p>
<p><pre class="brush: cpp;">
- (CPString)stringByReplacingString:(CPString)target withString:(CPString)replacement
</pre></p>
<p>setCharacterAtIndex  &#8211; replaces the character at &#8220;index&#8221; in SELF.</p>
<p><pre class="brush: cpp;">
-(CPString)setCharacterAtIndex:(unsigned)index theChar:(unichar)character
</pre></p>
<p>filterString &#8211; returns a copy of SELF filtering out the specified characters.</p>
<p><pre class="brush: cpp;">
-(CPString)filterString:(CPString)charactersToRemove
</pre></p>
<p>stripPrefix &#8211; returns a copy of SELF without thePrefix.  Does nothing if SELF doesn&#8217;t have thePrefix</p>
<p><pre class="brush: cpp;">
-(CPString)stripPrefix:(CPString)thePrefix
</pre></p>
<p>stripSuffix &#8211; returns a copy of SELF without theSuffix.  Does nothing if SELF doesn&#8217;t have theSuffix.</p>
<p><pre class="brush: cpp;">
-(CPString)stripSuffix:(CPString)theSuffix
</pre></p>
<p>dropCharacters &#8211; drops numCharsToDrop from the end of SELF.  Does nothing if charsToDrop &gt; [string length].  Returns an empty string if numCharsToDrop == [string length]</p>
<p><pre class="brush: cpp;">
-(CPString)dropCharacters:(int)numCharsToDrop
</pre></p>
<p><strong> TEST RELATED METHODS </strong></p>
<p>decimalTail &#8211; returns the tail of a decimal string.</p>
<p><pre class="brush: cpp;">
-(CPString)decimalTail
</pre></p>
<p>formatNodecString  &#8211; replaces the period in a formatted decimal string with a single space character.</p>
<p><pre class="brush: cpp;">
-(CPString)formatNodecString
</pre></p>
<p>formatNosepString &#8211; removes commas and the period from a formatted decimal string.</p>
<p><pre class="brush: cpp;">
-(CPString)formatNosepString
</pre></p>
<p>removeSurroundingParentheses &#8211; strips any leading or trailing spaces too.  N.B. Won’t remove an odd parenthesis on one end!</p>
<p><pre class="brush: cpp;">
-(CPString)removeSurroundingParentheses
</pre></p>
<p>parseScript &#8211; parses the if, then and else components of a script string.  Notice how the scanner walks down the script using the cumulative offset of previously scanned components. This is illustrative of a repetitive scanning pattern.</p>
<p><pre class="brush: cpp;">
-(void)parseScript
</pre></p>
<p>rectFromAnnot &#8211; converts the RECT string from a pdf annotation (e.g. RECT [432.97 580.92 441.86 589.95]) into a CGRect.</p>
<p><pre class="brush: cpp;">
-(CGRect)rectFromAnnot
</pre></p>
<p>scanRect &#8211; scans the RECT string found in pdf annotations.  Returns an array of strings for the left, bottom, right and top coordinates.  Note that scanRect also employs a repetitive scanning pattern.</p>
<p><pre class="brush: cpp;">
-(CPArray)scanRect
</pre></p>
<p>tokensSeparatedByCharactersFromSet &#8211; breaks the input string into an array of substrings.<br />
<pre class="brush: cpp;">
-(CPArray)tokensSeparatedByCharactersFromSet:(CPString)separatorSet
</pre></p>
<p><strong>SCANNING TESTS</strong></p>
<p>When you double-click the index.html file and then click the &#8220;Perform Scan Tests&#8221; button in the Scan Tests window, a Cappuccino Run Log Window will appear that contains these statements:</p>
<p>&nbsp; Performing scan tests.</p>
<p>&nbsp; Testing Scanning Methods.</p>
<p>&nbsp; Scan if-then-else script.</p>
<p>&nbsp; script is =IF(L222&lt;12000;3500*L106e;0)<br />
&nbsp; scriptIf = L222&lt;12000<br />
&nbsp; scriptThen = 3500*L106e<br />
&nbsp; scriptElse = 0</p>
<p>&nbsp; Scan pdf style Rect.</p>
<p>&nbsp; Build CGRect.</p>
<p>&nbsp; left   = 432.97<br />
&nbsp; bottom = 580.92<br />
&nbsp; right  = 441.86<br />
&nbsp; top    = 589.95</p>
<p>&nbsp; Testing Utility Methods.</p>
<p>&nbsp; Test stringByReplacingString</p>
<p>&nbsp; string A plus string B<br />
&nbsp; string A + string B</p>
<p>&nbsp; Test setCharacterAtIndex</p>
<p>&nbsp; 1234567<br />
&nbsp; A2C4E6G</p>
<p>&nbsp; Test stripPrefix</p>
<p>&nbsp; Mr. Coffee<br />
&nbsp; Coffee</p>
<p>&nbsp; Test stripSuffix</p>
<p>&nbsp; String Jr.<br />
&nbsp; String</p>
<p>&nbsp; Test dropCharacters</p>
<p>&nbsp; 123.45<br />
&nbsp; 123</p>
<p>&nbsp; Testing Test Related Methods.</p>
<p>&nbsp; Test decimalTail</p>
<p>&nbsp; 1,099.87<br />
&nbsp; 87</p>
<p>&nbsp; Test formatNodecString</p>
<p>&nbsp; 1,099.87<br />
&nbsp; 1,099 87</p>
<p>&nbsp; Test formatNosepString</p>
<p>&nbsp; 1,099.87<br />
&nbsp; 109987</p>
<p>&nbsp; Scan tests complete.</p>
<p>&#8220;It works&#8221; <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>My thanks to the Cappuccino Community, and especially to the Core Team.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/frameworker.wordpress.com/252/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/frameworker.wordpress.com/252/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/frameworker.wordpress.com/252/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/frameworker.wordpress.com/252/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/frameworker.wordpress.com/252/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/frameworker.wordpress.com/252/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/frameworker.wordpress.com/252/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/frameworker.wordpress.com/252/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/frameworker.wordpress.com/252/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/frameworker.wordpress.com/252/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/frameworker.wordpress.com/252/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/frameworker.wordpress.com/252/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/frameworker.wordpress.com/252/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/frameworker.wordpress.com/252/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=252&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://frameworker.wordpress.com/2010/02/08/thinking-about-strings/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6d6ddc877489e0012793019337be11e0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joely</media:title>
		</media:content>
	</item>
		<item>
		<title>How to constrain window size in Cappuccino?</title>
		<link>http://frameworker.wordpress.com/2009/09/11/how-to-constrain-window-size-in-cappuccino/</link>
		<comments>http://frameworker.wordpress.com/2009/09/11/how-to-constrain-window-size-in-cappuccino/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 20:13:36 +0000</pubDate>
		<dc:creator>frameworker</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://frameworker.wordpress.com/?p=231</guid>
		<description><![CDATA[I&#8217;m displaying an image in a CPWindow and wanted to keep the window from getting bigger than the image it&#8217;s displaying. I tried setting the window&#8217;s maximum size in applicationDidFinishLaunching. But that didn&#8217;t accomplish what I wanted; I&#8217;m still able to make the window arbitrarily large. However, there is a change in behavior when setMaxSize [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=231&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m displaying an image in a CPWindow and wanted to keep the window from getting bigger than the image it&#8217;s displaying.  I tried setting the window&#8217;s maximum size in applicationDidFinishLaunching. But that didn&#8217;t accomplish what I wanted; I&#8217;m still able to make the window arbitrarily large.</p>
<p>However, there is a change in behavior when setMaxSize is called.  The scroll bars persist at the maxSize position until both x and y are greater than maxSize.</p>
<p>With maxSize set, as you grow the window vertically, the horizontal scroll bar is fixed at the maxSize position and there is white space between the scroll bar and the bottom of the window.  Also, the vertical scroll bar is depicted as an empty, shaded, rect.</p>
<p style="text-align:left;padding-left:30px;"><img class="size-full wp-image-250    alignnone" title="CPWindow" src="http://frameworker.files.wordpress.com/2009/09/cpwindow.jpg?w=199&#038;h=320" alt="CPWindow" width="199" height="320" /></p>
<p style="text-align:left;padding-left:30px;">
<p>Once you make the window bigger than both maxWidth and maxHeight both scroll bars disappear and the window looks just like it would in the case where maxSize isn&#8217;t set.</p>
<p>In the case when maxSize isn&#8217;t set, as you grow the window vertically, the horizontal scroll bar is displayed at the window&#8217;s bottom edge with white space separating the bottom of the image and the scroll bar.  And if you make the window wider than the image&#8217;s width, the horizontal scroll bar disappears.</p>
<div id="_mcePaste" style="position:absolute;left:-10000px;top:0;width:1px;height:1px;">However, there is a change in behavior when setMaxSize is called.  The scroll bars persist at the maxSize position until both x and y are greater than maxSize.</div>
<div id="_mcePaste" style="position:absolute;left:-10000px;top:0;width:1px;height:1px;">With maxSize set, as you grow the window vertically, the horizontal scroll bar is fixed at the maxSize position and there is white space between the scroll bar and the bottom of the window.  Also, the vertical scroll bar is depicted as an empty, shaded, rect.  Once you make the window bigger than both maxWidth and maxHeight both scroll bars disappear and the window looks just like it would in the case where maxSize isn&#8217;t set.</div>
<div id="_mcePaste" style="position:absolute;left:-10000px;top:0;width:1px;height:1px;">In the case when maxSize isn&#8217;t set, as you grow the window vertically, the horizontal scroll bar is displayed at the window&#8217;s bottom edge with white space separating the bottom of the image and the scroll bar.  And if you make the window wider than the image&#8217;s width, the horizontal scroll bar disappears</div>
<p>How do you constrain the window&#8217;s size? Do I need to do something in addition to setMaxSize? Is a different approach required to do this?</p>
<p>Here&#8217;s my AppController.j source code.</p>
<pre style="font:normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;">
<pre style="font:normal normal normal 12px/18px Consolas, Monaco, 'Courier New', Courier, monospace;"><pre class="brush: cpp;">
@import &lt;Foundation/CPObject.j&gt;
@import &lt;Foundation/CPString.j&gt;

@implementation AppController : CPObject
{

}

- (void)applicationDidFinishLaunching:(CPNotification)aNotification
{
    var kImageWidth  = 612.0,
        kImageHeight = 792.0,
            kMargin  = 16.0;

    // Create a window to take up the full screen

    var theWindow = [[CPWindow alloc] initWithContentRect:CGRectMakeZero() styleMask:CPBorderlessBridgeWindowMask],

        contentView = [theWindow contentView],

        bounds = [contentView bounds];

    // Create a scrollView to contain the pdf image

    var scrollView = [[CPScrollView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(bounds), CGRectGetHeight(bounds))];

    [scrollView setAutoresizingMask: CPViewHeightSizable | CPViewWidthSizable];

    [scrollView setAutohidesScrollers:YES];

    // Create the image and imageView.

    var theImage = [[CPImage alloc] initWithContentsOfFile:[[CPBundle mainBundle] pathForResource:@&quot;testImage.pdf&quot;]];

    // Create the image view.

    var imageView = [[CPImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, kImageWidth, kImageHeight)];

    // Put the image in the imageView.

    [imageView setImage: theImage];

    // We don't want the image to resize.

    // (Could have [imageView setAutoresizingMask:CPViewNotSizable | CPViewNotSizable] instead.)

    [imageView setImageScaling: CPScaleNone];

    // Put the imageView in the scroller.

    [scrollView setDocumentView:imageView];

    // Put the scroller in the window's view hierarchy.
    [contentView addSubview:scrollView];

    var maxWidth   = kImageWidth  + kMargin,

        maxHeight  = kImageHeight + kMargin,

        theMaxSize = CPMakeSize(maxWidth, maxHeight);

    [theWindow setMaxSize: theMaxSize];

    // Bring the window forward to display it.

    [theWindow orderFront:self];
}

@end
</pre></pre>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/frameworker.wordpress.com/231/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/frameworker.wordpress.com/231/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/frameworker.wordpress.com/231/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/frameworker.wordpress.com/231/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/frameworker.wordpress.com/231/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/frameworker.wordpress.com/231/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/frameworker.wordpress.com/231/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/frameworker.wordpress.com/231/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/frameworker.wordpress.com/231/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/frameworker.wordpress.com/231/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/frameworker.wordpress.com/231/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/frameworker.wordpress.com/231/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/frameworker.wordpress.com/231/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/frameworker.wordpress.com/231/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=231&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://frameworker.wordpress.com/2009/09/11/how-to-constrain-window-size-in-cappuccino/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6d6ddc877489e0012793019337be11e0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joely</media:title>
		</media:content>

		<media:content url="http://frameworker.files.wordpress.com/2009/09/cpwindow.jpg" medium="image">
			<media:title type="html">CPWindow</media:title>
		</media:content>
	</item>
		<item>
		<title>Inside PDQForms</title>
		<link>http://frameworker.wordpress.com/2009/06/29/inside-pdqforms/</link>
		<comments>http://frameworker.wordpress.com/2009/06/29/inside-pdqforms/#comments</comments>
		<pubDate>Mon, 29 Jun 2009 21:31:26 +0000</pubDate>
		<dc:creator>frameworker</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://frameworker.wordpress.com/?p=216</guid>
		<description><![CDATA[Overview PDQForms is tax preparation software for State and Federal forms. It integrates spreadsheet logic into pdf forms using PDFKit to combine form field information with labels and expressions. The result is a spreadsheet-like application layer over the form. Creating a PDQ Form The idea was to automate everything that could be. The first step [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=216&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>Overview</strong></p>
<p>PDQForms is tax preparation software for State and Federal forms.  It integrates spreadsheet logic into pdf forms using PDFKit to combine form field information with labels and expressions.  The result is a spreadsheet-like application layer over the form.</p>
<p><strong>Creating a PDQ Form</strong></p>
<p><em>The idea was to automate</em><br />
<em>everything that could be.</em></p>
<p>The first step is to extract information for all the form&#8217;s fields, or &#8220;Annotations&#8221; in PDF lingo.</p>
<p>We need the type of Annotation: TEXT or CHECKBOX, and its PAGE, RECT and MAXLEN values.</p>
<p>This is accomplished with a PDFKit based program called PDQ Annotation Editor, which outputs a text file.</p>
<p>Next we must define expressions that contain the logic for each of the form&#8217;s fields.  This is just like programming a spreadsheet.</p>
<p>Adding this information to the Annotation meta-data completes our task.</p>
<p>We now have a text file containing the information PDQForms will need to automate the form.</p>
<p>We then &#8220;bake&#8221; this back into the original PDF file.</p>
<p>And the form can now be opened with PDQForms!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/frameworker.wordpress.com/216/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/frameworker.wordpress.com/216/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/frameworker.wordpress.com/216/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/frameworker.wordpress.com/216/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/frameworker.wordpress.com/216/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/frameworker.wordpress.com/216/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/frameworker.wordpress.com/216/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/frameworker.wordpress.com/216/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/frameworker.wordpress.com/216/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/frameworker.wordpress.com/216/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/frameworker.wordpress.com/216/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/frameworker.wordpress.com/216/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/frameworker.wordpress.com/216/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/frameworker.wordpress.com/216/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=216&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://frameworker.wordpress.com/2009/06/29/inside-pdqforms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6d6ddc877489e0012793019337be11e0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joely</media:title>
		</media:content>
	</item>
		<item>
		<title>TABLE LOOKUPS IN PDQFORMS</title>
		<link>http://frameworker.wordpress.com/2009/06/23/table-lookups-in-pdqforms/</link>
		<comments>http://frameworker.wordpress.com/2009/06/23/table-lookups-in-pdqforms/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 05:26:27 +0000</pubDate>
		<dc:creator>frameworker</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://frameworker.wordpress.com/?p=188</guid>
		<description><![CDATA[Since some tax forms use tables as well as formulae, I had to implement a tax table lookup algorithm. Things were complicated by the fact that these tables were not always available in sorted format. I first tried using the unsorted tax tables. This required doing a comparison of each table entry until the proper [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=188&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Since some tax forms use tables as well as formulae, I had to implement a tax table lookup algorithm.  Things were complicated by the fact that these tables were not always available in sorted format.</p>
<p>I first tried using the unsorted tax tables.  This required doing a comparison of each table entry until the proper tax bracket was found.  But tax lookup tends to occur whenever you change any numeric field on the form, since this usually affects taxable income.  So, doing a comparison for each entry, while easy, was way too slow!  Suddenly I was seeing a totally unacceptable delay.</p>
<p>The solution was to pre-sort the tables, shifting the performance burden completely out of the user&#8217;s work flow, and then to use an efficient, recursive binary search, algorithm to do the table lookup in PDQForms.</p>
<p><strong>PREPARING A TABLE</strong></p>
<p>Copy the table from the tax handbook into a text file and clean-out any patches of non-table data.  Fortunately, the topology of non-table data is amenable to doing this, and also, the table data consists of an integral number of tuples on each line.</p>
<p>Finally, filter-out commas, and prepend TUPLESIZE to the table.</p>
<p>The table we&#8217;re creating will have the same name as the form it applies to, but with a suffix that&#8217;s specified in the call to createTupleTable.  Here it&#8217;s &#8220;tax&#8221;.</p>
<p><pre class="brush: cpp;">

    NSString * theTableContents = [self createTupleTable: theTableData named: @&quot;tax&quot;];

</pre></p>
<p><strong>PRE-SORTING THE TABLES</strong></p>
<p><strong>1</strong>. Put the elements (NSStrings) of each tuple into an array (NSArray)</p>
<p><strong>2.</strong> Put these tuples into an array so they can be sorted.</p>
<p><strong>3.</strong> Sort the array of tuples, from smallest to largest, using &#8220;sortedArrayUsingFunction&#8221;<br />
   and passing it the comparison function &#8220;sortByValue&#8221;:</p>
<p><pre class="brush: cpp;">

    NSArray *sortedTuples = [tuples sortedArrayUsingFunction: sortByValue context: 0];

    NSInteger sortByValue(id tuple1, id tuple2, void *context)
    {
        double value1 = [[tuple1 objectAtIndex: 0] doubleValue];
        double value2 = [[tuple2 objectAtIndex: 0] doubleValue];
	
        if      (value1 &gt; value2) return NSOrderedDescending;
        else if (value1 &lt; value2) return NSOrderedAscending;
        else                      return NSOrderedSame;
    }

</pre></p>
<p><strong>4.</strong> Convert the sorted tuples back into a single NSString.</p>
<p><strong>5.</strong> Finally, &#8220;bake&#8221; the table data into the pdq file using PDFKit (10.5).</p>
<p><strong>DOING TABLE LOOKUPS IN PDQFORMS</strong></p>
<p>This stack-trace depicts the tax calculation mechanism:</p>
<p><strong>[PDQAbstractWidget evaluateExpression: theTableLookup]</strong><br />
Table lookups are processed as a special case by evaluateExpression.<br />
e.g. =TAXTABLE(&#8220;TAXTABLE&#8221;,&#8221;6&#8243;,INCOME,FILING_STATUS)<br />
evaluateExpression calls doTableLookup. </p>
<p>&nbsp;    <strong>[PDQAbstractWidget doTableLookup: theTableLookup]</strong><br />
&nbsp;    doTableLookup is analagous to evaluateFunction, but for tableLookups.<br />
&nbsp;    doTableLookup packages the call&#8217;s parameters and calls &#8220;execute.&#8221;<br />
&nbsp;    Note that quoted parameters are passed in as literal strings.</p>
<p>&nbsp; &nbsp;        <strong>[NSString+PDQFunctionAdditions execute: parameterArray]</strong><br />
&nbsp; &nbsp;        execute dispatches the call to taxTableLookup.</p>
<p>&nbsp; &nbsp;                <strong>[NSString+PDQFunctionAdditions taxtablelookup: parameterArray]</strong><br />
&nbsp; &nbsp;                taxTableLookup unpacks the parameters, finds the taxBracket<br />
&nbsp; &nbsp;                and uses it to determine the tax.</p>
<p>&nbsp; &nbsp; &nbsp;                    <strong>[NSArray+PDQTableAdditions taxBracket]</strong><br />
&nbsp; &nbsp; &nbsp;                    taxBracket is the recursive binary search algorithm,<br />
&nbsp; &nbsp; &nbsp;                    initially called from taxTableLookup,<br />
&nbsp; &nbsp; &nbsp;                    that does the &#8220;heavy lifting.&#8221;<br />
&nbsp; &nbsp; &nbsp;                    taxBracket calls the helper routine taxInTuple</p>
<p>&nbsp; &nbsp; &nbsp;                <strong>[NSArray+PDQTableAdditions taxInTuple]</strong><br />
&nbsp; &nbsp; &nbsp;                taxInTuple tests to see if taxable income falls<br />
&nbsp; &nbsp; &nbsp;                within a bracket, to its left, or to its right.<br />
&nbsp; &nbsp; &nbsp;                If income isn&#8217;t in the current tax bracket<br />
&nbsp; &nbsp; &nbsp;                taxInTuple&#8217;s return value is then used<br />
&nbsp; &nbsp; &nbsp;                to seed recursive calls to taxBracket.</p>
<p>taxBracket and taxInTuple are shown below.</p>
<p><pre class="brush: cpp;">

- (int) taxBracket: (double) income 
        tupleWidth: (int) tupleSize 
      startingWith: (int) firstTuple 
     andEndingWith: (int) lastTuple
{
    int tupleIndex = -1;

    int comparison;

    int middleTuple = firstTuple+(lastTuple-firstTuple)/2;

    comparison = [self taxInTuple: income 
                          atIndex: middleTuple 
                       tupleWidth: tupleSize];
	
    if (comparison == 0)
    {
        tupleIndex = middleTuple;
    }
    else 
    if (comparison == 1)
    {
        tupleIndex = [self taxBracket: income 
                           tupleWidth: tupleSize 
                         startingWith: middleTuple+1 
                        andEndingWith: lastTuple];
    }
    else 
    if (comparison == -1)
    {
        tupleIndex = [self taxBracket: income 
                           tupleWidth: tupleSize 
                         startingWith: firstTuple 
                        andEndingWith: middleTuple-1];
    }

    return tupleIndex;
}

</pre></p>
<p><pre class="brush: cpp;">

// Tuples are laid out end to end as one long array.
// The first two items of a tuple are its income bracket.
// the trailing items are the tax for each filing status 
// in that tuple's income bracket.
- (int) taxInTuple: (double) income 
           atIndex: (int) tupleIndex 
        tupleWidth: (int) tupleSize
{
	int leftIndex  = tupleIndex*tupleSize;
	int rightIndex = leftIndex + 1;
	
	NSString * leftItem  = [self objectAtIndex:  leftIndex];
	NSString * rightItem = [self objectAtIndex: rightIndex];
	
	double leftValue  = [leftItem  doubleValue];
	double rightValue = [rightItem doubleValue];

	// Test if intervals overlap:
	// 
	// IF YES use &lt;= for right value
	// IF NO  use &lt;  for right value.

	// CA brackets don't overlap
	// they're [x,y] [y+1,z].
	// So when income is exactly &quot;y&quot;
	// we want to match the ONLY bracket containing &quot;y&quot;,
	// not the higher of two brackets!
	
	// One even, one odd means the intervals shouldn't &quot;overlap.&quot;
	if ((int)leftValue%2 != (int)rightValue%2)
	{
		if ((income &gt;= leftValue) &amp;&amp; (income &lt;= rightValue))
		{
			return 0;
		}
	}
	else
	// IRS brackets are [x,y] [y,z] so when income is exactly &quot;y&quot;
	// we want to match the higher of the two brackets!
	{
		if ((income &gt;= leftValue) &amp;&amp; (income &lt; rightValue))
		{
			return 0;
		}
	}

	if (income &lt; leftValue)
	{
		return -1;
	}
	else
	{
		return 1;
	}
}

</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/frameworker.wordpress.com/188/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/frameworker.wordpress.com/188/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/frameworker.wordpress.com/188/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/frameworker.wordpress.com/188/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/frameworker.wordpress.com/188/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/frameworker.wordpress.com/188/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/frameworker.wordpress.com/188/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/frameworker.wordpress.com/188/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/frameworker.wordpress.com/188/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/frameworker.wordpress.com/188/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/frameworker.wordpress.com/188/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/frameworker.wordpress.com/188/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/frameworker.wordpress.com/188/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/frameworker.wordpress.com/188/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=188&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://frameworker.wordpress.com/2009/06/23/table-lookups-in-pdqforms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6d6ddc877489e0012793019337be11e0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joely</media:title>
		</media:content>
	</item>
		<item>
		<title>HOW I TEST FORMS</title>
		<link>http://frameworker.wordpress.com/2009/06/23/how-i-test-forms/</link>
		<comments>http://frameworker.wordpress.com/2009/06/23/how-i-test-forms/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 04:58:31 +0000</pubDate>
		<dc:creator>frameworker</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://frameworker.wordpress.com/?p=184</guid>
		<description><![CDATA[OVERVIEW The PDQForms Debug target contains a Debug menu with commands that are enabled if a PDQDocument is open. &#160; Read test file&#8230; &#160; Save test file&#8230; The &#8220;Save test file&#8230;&#8221; command journals edited forms into test files. The &#8220;Read test file&#8230;&#8221; command causes the test file to be read back into the current form, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=184&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><strong>OVERVIEW</strong></p>
<p>The PDQForms Debug target contains a Debug menu with commands that are enabled if a PDQDocument is open.</p>
<p>&nbsp; Read test file&#8230;<br />
&nbsp; Save test file&#8230;</p>
<p>The &#8220;Save test file&#8230;&#8221; command journals edited forms into test files.  The &#8220;Read test file&#8230;&#8221; command causes the test file to be read back into the current form, and verifies that values of the calculated fields are correct.  This allows for rapid regression testing of forms after making changes to the code base.</p>
<p><strong>I TEST FILE</strong></p>
<p>Test files have the same names as the forms they &#8220;exercise,&#8221; but with the suffix &#8220;test&#8221;.  </p>
<p>Test files are kept in the same folder as their corresponding &#8220;pdq&#8221; file.</p>
<p>The test file consists of FIELD_NAME, STRING_VALUE pairs, one pair per line.</p>
<p><strong>II TEST COMMAND</strong></p>
<p>Saving the test file writes out the form&#8217;s FIELD_NAME, STRING_VALUE data.</p>
<p>Reading the file back into the current form, populates each FIELD_NAME with its STRING_VALUE and causes that field&#8217;s dependents to update.</p>
<p>But if a STRING_VALUE read from the test file begins with an &#8220;=&#8221;, then it is an expected result and it will be compared to the calculated value of the form&#8217;s field, not stuffed into the form.</p>
<p><strong>III TEST RESULTS</strong></p>
<p>The test command logs descrepencies in calculated values:</p>
<p>&#8220;Unexpected value for calculated widget: &#8216;WidgetID&#8217;  shown: &#8216;itsValue&#8217;  expected: &#8216;itsExpectedValue&#8217;&#8221;</p>
<p>If there are no descrepencies, the test command logs the message:</p>
<p>&#8220;All calculated widgets have expected values <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> &#8220;</p>
<p><strong>IV SUMMARY</strong></p>
<p>Since the accuracy of calculations in forms is paramount, this simple but powerful approach solves an important problem.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/frameworker.wordpress.com/184/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/frameworker.wordpress.com/184/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/frameworker.wordpress.com/184/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/frameworker.wordpress.com/184/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/frameworker.wordpress.com/184/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/frameworker.wordpress.com/184/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/frameworker.wordpress.com/184/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/frameworker.wordpress.com/184/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/frameworker.wordpress.com/184/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/frameworker.wordpress.com/184/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/frameworker.wordpress.com/184/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/frameworker.wordpress.com/184/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/frameworker.wordpress.com/184/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/frameworker.wordpress.com/184/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=184&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://frameworker.wordpress.com/2009/06/23/how-i-test-forms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6d6ddc877489e0012793019337be11e0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joely</media:title>
		</media:content>
	</item>
		<item>
		<title>EXPRESSIONS IN PDQFORMS</title>
		<link>http://frameworker.wordpress.com/2009/06/23/expressions-in-pdqforms/</link>
		<comments>http://frameworker.wordpress.com/2009/06/23/expressions-in-pdqforms/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 04:50:30 +0000</pubDate>
		<dc:creator>frameworker</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://frameworker.wordpress.com/?p=178</guid>
		<description><![CDATA[I realize this document is pretty dry, but I needed to document this implementation to facilitate discussion with othere in the quest to improve it. Without going into why I took the approach I did, I will say that I did become very proficient in using strings with Objective C I OVERVIEW OF EXPRESSION SYNTAX [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=178&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I realize this document is pretty dry, but I needed to document this implementation to facilitate discussion with othere in the quest to improve it.  Without going into why I took the approach I did, I will say that I did become very proficient in using strings with Objective C <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><strong>I OVERVIEW OF EXPRESSION SYNTAX</strong></p>
<p>Expressions may be FORMULAE (including BOOLEAN FORMULAE), FUNCTIONS, TABLE LOOKUPS or CONDITIONAL EXPRESSIONS.</p>
<p>Expressions are written in infix notation, just as you&#8217;d expect.  They consist of OPERATORS, OPERANDS, SEPARATORS and FUNCTION NAMES.</p>
<p><strong>A.</strong> OPERATORS include BOOLEAN OPERATORS</p>
<p>==    &lt;= or == or =&gt;  != or   &amp;&amp;  ||  !</p>
<p>and ARITHMETIC OPERATORS</p>
<p>+  &#8211;  *  % (modulus)  ^ (exponentiation)</p>
<p><strong>B.</strong> OPERANDS may be cell references or numbers.  Numbers are evaluated as double-precision floating point.</p>
<p><strong>C.</strong> SEPARATORS include  (  )  ,  ;</p>
<p>The &#8220;=&#8221; character is prepended to all expressions, just like in VisiCalc.</p>
<p><strong>D.</strong> All other tokens, those which are not OPERATORS, OPERANDS or SEPARATORS, are FUNCTION NAMES.</p>
<p>FUNCTION NAMES that end with &#8220;TABLE&#8221; are a special case.  They perform Table Lookups for forms that use Tax Tables.</p>
<p><strong>II FORMULAE</strong></p>
<p>Operands, within formulae, may be cell references or numbers.  Numbers are evaluated as double-precision floating point.</p>
<p><strong>III BOOLEAN FORMULAE</strong></p>
<p>Boolean Formulae, expressions that resolve to YES (1) or NO (0), are used in the scriptIf component of Conditional Expressions.  They aren&#8217;t used elsewhere at this time, but they could be.  Any positive number could be interpreted as YES, but we currently require &#8220;1&#8243;.</p>
<p><strong>IV FUNCTIONS</strong></p>
<p>Functions are snippets of code that get dispatched interpretively.</p>
<p>Function arguments may be formulae or can, themselves, be functions.</p>
<p>Quotes are used to transmit function (and table lookup) arguments as literals.</p>
<p>*Describe how a function gets added to PDQForms and the function dispatch mechanism.*<br />
*Show the recursive function parsing routine.*</p>
<p><strong>V TABLE LOOKUPS</strong></p>
<p>Table Lookups are used to find income tax, for example, for Federal filers whose taxable income is less than $100,000.</p>
<p>See the blog post on TABLE LOOKUPS IN PDQFORMS for a more detailed description of how they&#8217;re implemented.</p>
<p><strong>VI CONDITIONAL EXPRESSIONS</strong></p>
<p>Conditional Expressions are of the form =IF(scriptIf;scriptThen;scriptElse)</p>
<p>(&#8220;IF&#8221; is a reserved word)</p>
<p>ScriptIf, a Boolean Formula, resolves to a value of zero or one.  If scriptIf resolves to 0, scriptThen is executed, otherwise scriptElse is executed.  ScriptThen and scriptElse can be Table Lookups, Functions or Formulae.</p>
<p>Conditional Expressions may not be &#8220;nested.&#8221;</p>
<p><strong>VII LIMITATIONS</strong></p>
<p>Expressions may not contain functions.  For now, if an expression needs an embedded function, an invisible widget, that calls the function, can be referenced from the expression.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/frameworker.wordpress.com/178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/frameworker.wordpress.com/178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/frameworker.wordpress.com/178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/frameworker.wordpress.com/178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/frameworker.wordpress.com/178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/frameworker.wordpress.com/178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/frameworker.wordpress.com/178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/frameworker.wordpress.com/178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/frameworker.wordpress.com/178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/frameworker.wordpress.com/178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/frameworker.wordpress.com/178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/frameworker.wordpress.com/178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/frameworker.wordpress.com/178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/frameworker.wordpress.com/178/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=178&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://frameworker.wordpress.com/2009/06/23/expressions-in-pdqforms/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6d6ddc877489e0012793019337be11e0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joely</media:title>
		</media:content>
	</item>
		<item>
		<title>[RECOMMEND] Jordan Langille, Iconographer</title>
		<link>http://frameworker.wordpress.com/2009/04/30/recommending-jordan-langille-iconographer/</link>
		<comments>http://frameworker.wordpress.com/2009/04/30/recommending-jordan-langille-iconographer/#comments</comments>
		<pubDate>Thu, 30 Apr 2009 19:53:36 +0000</pubDate>
		<dc:creator>frameworker</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://frameworker.wordpress.com/?p=160</guid>
		<description><![CDATA[Jordan is an Artist and Iconographer at OneToad Design He designed the icons for PDQForms I found Jordan through CIMGF; thanks guys! Jordan responded to my initial query, worked with me and delivered my icons in a very reasonable amount of time! He communicates well, is easy to work with, and does EXCELLENT WORK! And [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=160&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Jordan is an Artist and Iconographer at <a href="http://onetoad.com/">OneToad Design</a></p>
<p>He designed the icons for <a href="http://pdqforms.biz">PDQForms</a> <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>I found Jordan through <a href="http://www.cimgf.com/">CIMGF</a>; thanks guys!</p>
<p>Jordan responded to my initial query, worked with me and delivered my icons in a very reasonable amount of time!  </p>
<p>He communicates well, is easy to work with, and does EXCELLENT WORK!</p>
<p>And he&#8217;s very concerned with his customers&#8217; satisfaction!</p>
<p>Thank you, Jordan!!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/frameworker.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/frameworker.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/frameworker.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/frameworker.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/frameworker.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/frameworker.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/frameworker.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/frameworker.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/frameworker.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/frameworker.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/frameworker.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/frameworker.wordpress.com/160/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/frameworker.wordpress.com/160/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/frameworker.wordpress.com/160/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=frameworker.wordpress.com&amp;blog=425141&amp;post=160&amp;subd=frameworker&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://frameworker.wordpress.com/2009/04/30/recommending-jordan-langille-iconographer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/6d6ddc877489e0012793019337be11e0?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">joely</media:title>
		</media:content>
	</item>
	</channel>
</rss>
