<?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"
	>

<channel>
	<title>GUI.NET &#187; Coder()</title>
	<atom:link href="http://www.gui.net/blog/category/coder/feed/" rel="self" type="application/rss+xml" />
	<link>http://gui.net/blog</link>
	<description>Advanced Software Perspectives</description>
	<pubDate>Sun, 29 Aug 2010 19:52:09 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5</generator>
	<language>en</language>
			<item>
		<title>Our blog has a new look-and-feel!</title>
		<link>http://gui.net/blog/2008/03/31/we-have-a-new-theme/</link>
		<comments>http://gui.net/blog/2008/03/31/we-have-a-new-theme/#comments</comments>
		<pubDate>Mon, 31 Mar 2008 17:04:49 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Coder()]]></category>

		<category><![CDATA[Featured]]></category>

		<guid isPermaLink="false">http://gui.net/blog/?p=26</guid>
		<description><![CDATA[Along with merging GUI.NET with Software Federation, it was time for a new theme that wasn&#8217;t so, how shall we put it, well, it was more of an anti-theme than anything. It&#8217;s sole goal was to use as much of the screen real-estate for content as possible.
This new theme was chosen to both match Software [...]]]></description>
			<content:encoded><![CDATA[<p>Along with merging GUI.NET with Software Federation, it was time for a new theme that wasn&#8217;t so, how shall we put it, well, it was more of an anti-theme than anything. It&#8217;s sole goal was to use as much of the screen real-estate for content as possible.</p>
<p>This new theme was chosen to both match Software Federation&#8217;s new Web 2.0-ish look and feel, as well as for me to have the opportunity to play around with magazine-ish look-and-feels in anticipation of an upcoming product we have been planning to build for some time now.</p>
<p>The theme we chose is the <a href="http://themasterplan.in/themes/the-morning-after/">Morning After</a> theme. A review of this theme can also be found <a href="http://themecritic.com/wordpress/the-morning-after-magazine-style.html#more-40">here</a>.</p>
<p>This theme has a lot of cool features, like featured posts and asides, and lots of functionality which we have not yet begone to explore (we just updated Wordpress and installed the theme late yesterday). So far, we have been mostly replacing floats with divs and tables so that when we use font sizes large enough for people who are on the high side of 40, the layout is preserved.</p>
<p>Otherwise, the PHP seems very well designed and my overall impression at this point is very favorable. We hope that your impression is likewise - but if not, please let us know!</p>
]]></content:encoded>
			<wfw:commentRss>http://gui.net/blog/2008/03/31/we-have-a-new-theme/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Getting rid of control-M ^M in files checked into Subversion from Windows and checked out on Linux, Solaris, Unix, Ubuntu, Whateverrrr</title>
		<link>http://gui.net/blog/2008/01/02/getting-rid-of-control-m-m-in-files-checked-in-from-windows-and-checked-out-on-linux-solaris-unix-ubuntu-whateverrrr/</link>
		<comments>http://gui.net/blog/2008/01/02/getting-rid-of-control-m-m-in-files-checked-in-from-windows-and-checked-out-on-linux-solaris-unix-ubuntu-whateverrrr/#comments</comments>
		<pubDate>Thu, 03 Jan 2008 02:40:31 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Coder()]]></category>

		<guid isPermaLink="false">http://gui.net/blog/?p=25</guid>
		<description><![CDATA[Ruby doesn&#8217;t like files with ^M at the end of each line. Go figure.
Here is what I did. Hopefully it&#8217;ll work for you too.
In my  Subversion installation directory, ON MY WINDOWS BOX (don&#8217;t you go wasting several hours on this, too, I wasted enough for the whole kit-and-kaboodle of us on this one) I [...]]]></description>
			<content:encoded><![CDATA[<p>Ruby doesn&#8217;t like files with ^M at the end of each line. Go figure.</p>
<p>Here is what I did. Hopefully it&#8217;ll work for you too.</p>
<p>In my  Subversion installation directory, ON MY WINDOWS BOX (don&#8217;t you go wasting several hours on this, too, I wasted enough for the whole kit-and-kaboodle of us on this one) I added a conf subdirectory.</p>
<p>in there I added a file called config. The contents of this file is at the end of this blog post. You can see examples of this file all over the net.</p>
<p>Then, in my batch files I created to do the import and checkin and add I add, in my case:</p>
<p>&#8211;config-dir C:\runtime\svn-win32-1.4.6\conf</p>
<p>Of course, in your case, you would replace &#8216;C:runtime\ svn-win32-1.4.6&#8242; with the path to YOUR subversion installation.</p>
<p>For example my checkin.bat looks like:</p>
<p>svn commit -m &#8220;Checking In&#8221;     &#8211;config-dir C:\runtime\svn-win32-1.4.6\conf     &#8211;username me   &#8211;password my_password</p>
<p>(actually, I have another line in this file that calls a script to automatically add all new files that have been created since the last checkin. Subversion can&#8217;t do this itself, for some reason. They don&#8217;t call it source code management SCuM without a good reason).</p>
<p>OK, here is the file. What this says is to set end-of-line properties to linefeed for files with extensions that are likely to be text files.</p>
<p>The key lines are to enable the property feature.<br />
enable-auto-props = yes</p>
<p>and the lines at the end of the file that specify what to do about files with various extensions. Specifically, in our case:</p>
<p>*.rb = svn:eol-style=LF</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>###<br />
### The commented-out examples below are intended to demonstrate<br />
### how to use this file.</p>
<p>### Section for authentication and authorization customizations.<br />
[auth]<br />
### Set store-passwords to &#8216;no&#8217; to avoid storing passwords in the<br />
### auth/ area of your config directory.  It defaults to &#8216;yes&#8217;.<br />
### Note that this option only prevents saving of *new* passwords;<br />
### it doesn&#8217;t invalidate existing passwords.  (To do that, remove<br />
### the cache files by hand as described in the Subversion book.)<br />
# store-passwords = no<br />
### Set store-auth-creds to &#8216;no&#8217; to avoid storing any subversion<br />
### credentials in the auth/ area of your config directory.<br />
### It defaults to &#8216;yes&#8217;.  Note that this option only prevents<br />
### saving of *new* credentials;  it doesn&#8217;t invalidate existing<br />
### caches.  (To do that, remove the cache files by hand.)<br />
# store-auth-creds = no</p>
<p>### Section for configuring external helper applications.<br />
[helpers]<br />
### Set editor to the command used to invoke your text editor.<br />
###   This will override the environment variables that Subversion<br />
###   examines by default to find this information ($EDITOR,<br />
###   et al).<br />
# editor-cmd = editor (vi, emacs, notepad, etc.)<br />
### Set diff-cmd to the absolute path of your &#8216;diff&#8217; program.<br />
###   This will override the compile-time default, which is to use<br />
###   Subversion&#8217;s internal diff implementation.<br />
# diff-cmd = diff_program (diff, gdiff, etc.)<br />
### Set diff3-cmd to the absolute path of your &#8216;diff3&#8242; program.<br />
###   This will override the compile-time default, which is to use<br />
###   Subversion&#8217;s internal diff3 implementation.<br />
# diff3-cmd = diff3_program (diff3, gdiff3, etc.)<br />
### Set diff3-has-program-arg to &#8216;true&#8217; or &#8216;yes&#8217; if your &#8216;diff3&#8242;<br />
###   program accepts the &#8216;&#8211;diff-program&#8217; option.<br />
# diff3-has-program-arg = [true | false]</p>
<p>### Section for configuring tunnel agents.<br />
[tunnels]<br />
### Configure svn protocol tunnel schemes here.  By default, only<br />
### the &#8217;ssh&#8217; scheme is defined.  You can define other schemes to<br />
### be used with &#8217;svn+scheme://hostname/path&#8217; URLs.  A scheme<br />
### definition is simply a command, optionally prefixed by an<br />
### environment variable name which can override the command if it<br />
### is defined.  The command (or environment variable) may contain<br />
### arguments, using standard shell quoting for arguments with<br />
### spaces.  The command will be invoked as:<br />
###     svnserve -t<br />
### (If the URL includes a username, then the hostname will be<br />
### passed to the tunnel agent as @.)  If the<br />
### built-in ssh scheme were not predefined, it could be defined<br />
### as:<br />
# ssh = $SVN_SSH ssh<br />
### If you wanted to define a new &#8216;rsh&#8217; scheme, to be used with<br />
### &#8217;svn+rsh:&#8217; URLs, you could do so as follows:<br />
# rsh = rsh<br />
### Or, if you wanted to specify a full path and arguments:<br />
# rsh = /path/to/rsh -l myusername<br />
### On Windows, if you are specifying a full path to a command,<br />
### use a forward slash (/) or a paired backslash (\\) as the<br />
### path separator.  A single backslash will be treated as an<br />
### escape for the following character.</p>
<p>### Section for configuring miscelleneous Subversion options.<br />
[miscellany]<br />
### Set global-ignores to a set of whitespace-delimited globs<br />
### which Subversion will ignore in its &#8217;status&#8217; output, and<br />
### while importing or adding files and directories.<br />
# global-ignores = *.o *.lo *.la #*# .*.rej *.rej .*~ *~ .#* .DS_Store<br />
### Set log-encoding to the default encoding for log messages<br />
# log-encoding = latin1<br />
### Set use-commit-times to make checkout/update/switch/revert<br />
### put last-committed timestamps on every file touched.<br />
# use-commit-times = yes<br />
### Set no-unlock to prevent &#8217;svn commit&#8217; from automatically<br />
### releasing locks on files.<br />
# no-unlock = yes<br />
### Set enable-auto-props to &#8216;yes&#8217; to enable automatic properties<br />
### for &#8217;svn add&#8217; and &#8217;svn import&#8217;, it defaults to &#8216;no&#8217;.<br />
### Automatic properties are defined in the section &#8216;auto-props&#8217;.<br />
enable-auto-props = yes</p>
<p>### Section for configuring automatic properties.<br />
[auto-props]<br />
### The format of the entries is:<br />
###   file-name-pattern = propname[=value][;propname[=value]&#8230;]<br />
### The file-name-pattern can contain wildcards (such as &#8216;*&#8217; and<br />
### &#8216;?&#8217;).  All entries which match will be applied to the file.<br />
### Note that auto-props functionality must be enabled, which<br />
### is typically done by setting the &#8216;enable-auto-props&#8217; option.<br />
*.c = svn:eol-style=LF<br />
*.cpp = svn:eol-style=LF<br />
*.h = svn:eol-style=LF<br />
*.dsp = svn:eol-style=CRLF<br />
*.dsw = svn:eol-style=CRLF<br />
*.sh = svn:eol-style=LF;svn:executable<br />
*.txt = svn:eol-style=LF<br />
*.png = svn:mime-type=image/png<br />
*.jpg = svn:mime-type=image/jpeg<br />
*.gif = svn:mime-type=image/gif<br />
Makefile = svn:eol-style=LF<br />
*.rhtml = svn:eol-style=LF<br />
*.fcgi = svn:eol-style=LF<br />
*.cgi = svn:eol-style=LF<br />
*.rb = svn:eol-style=LF<br />
*.txt = svn:eol-style=LF<br />
*.yml = svn:eol-style=LF<br />
*.html = svn:eol-style=LF</p>
]]></content:encoded>
			<wfw:commentRss>http://gui.net/blog/2008/01/02/getting-rid-of-control-m-m-in-files-checked-in-from-windows-and-checked-out-on-linux-solaris-unix-ubuntu-whateverrrr/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Gotchyas along the road to Ruby application deployment success on Joyent</title>
		<link>http://gui.net/blog/2008/01/02/gotchyas-along-the-road-to-ruby-application-installation-success-on-joyent/</link>
		<comments>http://gui.net/blog/2008/01/02/gotchyas-along-the-road-to-ruby-application-installation-success-on-joyent/#comments</comments>
		<pubDate>Thu, 03 Jan 2008 02:20:11 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Coder()]]></category>

		<category><![CDATA[Joyent]]></category>

		<category><![CDATA[Rails]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://gui.net/blog/?p=24</guid>
		<description><![CDATA[Hopefully this will be most of the difficult issues we run into, as we have several &#8216;S&#8217; and &#8216;M&#8217; accounts over at Joyent, and we are supposed to learn from our experiences and mistakes, right? I mean, most other mammals can do this, right, so why not coders, I ask you.
First off, the Joyent wiki [...]]]></description>
			<content:encoded><![CDATA[<p>Hopefully this will be most of the difficult issues we run into, as we have several &#8216;S&#8217; and &#8216;M&#8217; accounts over at Joyent, and we are supposed to learn from our experiences and mistakes, right? I mean, most other mammals can do this, right, so why not coders, I ask you.</p>
<p>First off, the Joyent wiki documentation is kind of confusing. You got textdrive the product and textdrive the server, shared hosting, shared accelerators, connectors, plain accelerators&#8230; product names, service names and domain names are all overloaded. And, coming in from Google, there are no markings on the pages to tell in which section they are part of, and their forums are like this too.</p>
<p>So all this is to say, please excuse me and do not laugh to hard when you read that, at my registrar (GoDaddy), to set up my DNS:<br />
I first tried</p>
<p>dns1.textdrive.com<br />
dns2.textdrive.com<br />
dns3.textdrive.com<br />
dns4.textdrive.com</p>
<p>I then tried</p>
<p>dns1.joyentdns.com<br />
dns2.joyentdns.com<br />
dns3.joyentdns.com<br />
dns4.joyentdns.com</p>
<p>Finally, I figured out that this was for one of their other services, so, at GoDaddy the trick was to:</p>
<p>First configure your domain so that it says it is to be hosted at GoDaddy  It isn&#8217;t really going to be, Well, the name server is, but not the pages. Anyway, another overloading of terms here.</p>
<p>Then use Total DNS Control Panel to point (in the Default DNS zone) the host at your IP address over at Joyent. Started working in about an hour or so.</p>
<p>Anyway, followed the directions in http://wiki.joyent.com/accelerators:absolute_beginners_guide  and http://wiki.joyent.com/accelerators:deploying_rails_apps</p>
<p>Set up Subversion, SVN client on Windows box, SVN server on the Joyent server. The SVN server is already in place, but when adding user to access SVN, well, there are config files in ~/etc/subversion and in ~/.svn/subversion? Anyway there are two, and well, here is the thing. The Subversion user must be able to have access to subversion, SSH to be able to log in automatically from the client, and to add things to your deployment directory.<br />
One of the mistakes I made was to create a special SVNUser, which I then backed out this and had to modify all the config files blah blah blah pain pain pain.</p>
<p>Then, a &#8216;feature&#8217; of su on Solaris is apparently that when you su Another_User ~ (i.e. tilde) still points to the home directory of the user you logged in over SSH as. so all those config files I set up? They were for admin, not the SVN user. Doh!</p>
<p>And then, the documentation says that the URL for the SVN repository is http://my_domain_name.com/svn/repos. Well it took me forever to figure out that repos was supposed to be the name of the repository, which was something like svnreposository in my case.</p>
<p>Yeah, Yeah, we all laugh about it NOW. But these things took hours to figure out.  OK, you can stop laughing now.</p>
<p>Then, related to the above &#8217;su&#8217; anomaly,  make sure when you checkout of SVN, to &#8216;prime&#8217; it for the initial import process, that you do it as the user who will be doing the import in. And you can&#8217;t su to them you have to <span style="font-weight: bold">log in</span> as them.<br />
svn export http://my_domain_name/svn/my_repostiroy_name/trunk /home/somewhere_temporary/tmp</p>
<p>Next, how to get rid of those nasty ^M &#8217;s all over the freakin place.</p>
<p>And, to get different blog software, as this version of Wordpress has a NASTY text editor that is slow and weird and jumps around and is more or less useless.</p>
]]></content:encoded>
			<wfw:commentRss>http://gui.net/blog/2008/01/02/gotchyas-along-the-road-to-ruby-application-installation-success-on-joyent/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Ruby on Rails - ARMailer - and View Templates</title>
		<link>http://gui.net/blog/2007/12/29/ruby-on-rails-armailer-and-templates/</link>
		<comments>http://gui.net/blog/2007/12/29/ruby-on-rails-armailer-and-templates/#comments</comments>
		<pubDate>Sun, 30 Dec 2007 04:22:51 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Coder()]]></category>

		<category><![CDATA[Rails]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://gui.net/blog/?p=23</guid>
		<description><![CDATA[While working on Zategories.com it was &#8216;discovered&#8217; that&#8230;
&#8230;the default ARmailer template feature doesn&#8217;t work the way it is documented.
At least if you want to use the features where you just have to put the email templates in a directory and the mailer generates and sends a multi-part email for ya.
Why?
Because this:
ActionMailer::Base.template_root = &#8220;mailer/templates&#8221;
does not work. [...]]]></description>
			<content:encoded><![CDATA[<p>While working on <a href="http://www.zategories.com">Zategories.com</a> it was &#8216;discovered&#8217; that&#8230;</p>
<p>&#8230;the default ARmailer template feature doesn&#8217;t work the way it is documented.</p>
<p>At least if you want to use the features where you just have to put the email templates in a directory and the mailer generates and sends a multi-part email for ya.</p>
<p>Why?</p>
<p>Because this:</p>
<p>ActionMailer::Base.template_root = &#8220;mailer/templates&#8221;</p>
<p>does not work. Why, you might ask?</p>
<p>Because, in ActionMailer::Base, template_root is defined as:</p>
<p>class_inheritable_accessor :template_root</p>
<p>So assigning it a value like it was a class variable, doesn&#8217;t work because it is an instance variable.</p>
<p>What I did was to copy <a href="http://agilewebdevelopment.com/plugins/exception_notifier">exception_notifier</a>&#8217;s approach and override the accessor method in our notifier.rb model class:</p>
<p>def template_root<br />
&#8216;app/views&#8217;<br />
end</p>
<p>Now, our notifier model class [subclassing ActionMailer::ARMailer, used to be ActionMailer::Base]<br />
can use templates, like:</p>
<p>new_photo_notification.text.plain.rhtml<br />
new_photo_notification.text.html.rhtml</p>
<p>which we put in a directory under apps/views/notifier</p>
]]></content:encoded>
			<wfw:commentRss>http://gui.net/blog/2007/12/29/ruby-on-rails-armailer-and-templates/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Interfacing to Google Checkout - Java 1.4, Linux (CentOS) - using the XML, Level 2, Alternative Method (programmatic) API - Part 1</title>
		<link>http://gui.net/blog/2007/01/06/interfacing-to-google-checkout-java-14-linux-centos-using-the-xml-level-2-alternative-method-programmatic-api-part-1/</link>
		<comments>http://gui.net/blog/2007/01/06/interfacing-to-google-checkout-java-14-linux-centos-using-the-xml-level-2-alternative-method-programmatic-api-part-1/#comments</comments>
		<pubDate>Sat, 06 Jan 2007 12:42:17 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Coder()]]></category>

		<guid isPermaLink="false">http://gui.net/blog/?p=20</guid>
		<description><![CDATA[I am posting this thread because I found it difficult to find some of this informationÂ and so thought it might eventually be useful to someone else in the Google CheckoutÂ trenches.Â 
Â The main link for information is: http://code.google.com/apis/checkout/
at that link the main page is: http://code.google.com/apis/checkout/developer/index.html
SETTING UP SANDBOX ACCOUNTSÂ 
One of the first things [...]]]></description>
			<content:encoded><![CDATA[<p>I am posting this thread because I found it difficult to find some of this informationÂ and so thought it might eventually be useful to someone else in the Google CheckoutÂ trenches.Â </p>
<p>Â The main link for information is: <a href="http://code.google.com/apis/checkout/">http://code.google.com/apis/checkout/</a></p>
<p>at that link the main page is: <a href="http://code.google.com/apis/checkout/developer/index.html">http://code.google.com/apis/checkout/developer/index.html</a></p>
<p>SETTING UP SANDBOX ACCOUNTSÂ </p>
<p>One of the first things ya gotta do is setup three google accounts - one real and one sandbox seller (merchant account) and one sandbox buyer.Â In orderÂ to differentiate the sand box accounts from each other and from your real one you need to use different email addresses when you set them up. Yeah, so that means three email addresses are required, since that is whatÂ you use to log in to these accounts. I used real email addresses - and don&#8217;t know if fake ones will work just as well.Â Your page for your real accountÂ will have a link on it to your sandbox account(s) login.</p>
<p>Â The pertinent paragraph in the docs is:Â </p>
<p>&#8220;You need to create two test accounts in the Sandbox. One of these accounts will function as a <a href="http://sandbox.google.com/checkout"><font color="#0000cc">customer account</font></a> and the other will function as your <a href="http://sandbox.google.com/checkout/sell/"><font color="#0000cc">merchant account</font></a>. Please note that Google Checkout does not allow a single account to function as both the customer and the merchant for the same transaction. In addition, the links in the previous sentence point to different signup URLs, and you will be asked for different information to create these two accounts.&#8221;</p>
<p>This link to create the sandbox customer account did not work for me, perhaps because I created the sandbox merchant account first [long story, suffice it to say that I incorrectly used my &#8216;real&#8217; email address to create my first sandbox account]. A link that DID work for me is: <a href="http://sandbox.google.com/checkout/buy">http://sandbox.google.com/checkout/buy</a></p>
<p>SETTING UP A CART and HANDING THE USER OVER TO THEIR GOOGLE ACCOUNT SO THAT THEY CAN MAKE PAYMENT</p>
<p>Â Here is the code as it stands now. Seems to me that taking their sample code and modifying it, [i.e. the MerchantConstants file and the event handlers] which is what a lot of people do, is not the best idea. What if google changes things later? Ya want to keep rewriting this stuff? Who wants to spend the time to setup and incorporate the building of this code into their app? Anyway, the following code uses what they call their example code in a minimal fashion, and will probably not use it at all next revision.</p>
<p>I chose to use the Java 1.4 version, since I use Jikes [a very fast compiler]Â and that is stuck at 1.4 [looks like we will have to abandon Jikes unless someone steps in and updates it real soon now]. But the example code, all that I&#8217;ve been able to find, is in the jsp fiels in the top level directory of the jdk 1.5 version WAR file that google has on their downloads page: <a href="http://code.google.com/apis/checkout/samplecode.html">http://code.google.com/apis/checkout/samplecode.html</a></p>
<p>The other part of this code, the asynchronous callback handler that lets goggle send us messages to let us know how the checkout process went, will be posted at a future date (aka after it works).</p>
<p>We are using resin-pro 3.x and had a little bit of a hard time getting it to see all of the classes this code references in the jaxb libraries that the google checkout sample code uses.Â One thing that I did to make sure Resin found some of the classes at runtime was to rename xsdlib.jar to axsdlib.jar, so that it would be loaded before libs that reference it. Shades of LD_LIBRARY_PATH&#8230;</p>
<p>Part II will be forthcoming after CES sometime&#8230; as will more comments here&#8230; Strings is our class here that manages lists of class String. EVerything else is a google checkout class provided by their example libraries. So, anyway, here is an example of how to create a cart and send it, and the user,Â off to Goggle after polling it for an address to sendÂ them to.</p>
<pre>Â  Â
import javax.xml.bind.JAXBException;
import com.sun.msv.datatype.xsd.DoubleType;

import com.google.checkout.sample.util.StringUtil;
import com.google.checkout.sample.protocol.CheckoutCartBuilder;

import com.google.checkout.schema._2.impl.AnyTypeImpl;
import com.google.checkout.schema._2.USStateArea;
import com.google.checkout.schema._2.Item;
import com.google.checkout.schema._2.ShoppingCart;
import com.google.checkout.schema._2.ShippingRestrictions;
import com.google.checkout.schema._2.DefaultTaxTable;
import com.google.checkout.schema._2.DefaultTaxRule;
import com.google.checkout.schema._2.MerchantCheckoutFlowSupport;
import com.google.checkout.schema._2.CheckoutRedirect;
import com.google.checkout.sample.crypto.CryptUtil;
//import com.google.checkout.sample.MerchantConstants;

import org.w3c.dom.Document;

import org.xml.sax.InputSource;
import javax.net.ssl.HttpsURLConnection;

/**----------------------------------------------------------------------------------------------
 * This class
 *
 * @author      Michael L. Davis
 *----------------------------------------------------------------------------------------------*/
public class NzGoogleCheckoutOperations implements NziBillingMethodWorkflow
	{
	private static	final String	sandboxMerchantId	= "xxxxxxxxxxxxxxxx";
	private static	final String	sandboxMerchantKey	= "xxxxxxxxxxxxxxxxxxxxxxx";
	private static	final String	sandboxRequestUrl	= "https://sandbox.google.com/cws/v2/Merchant/" + sandboxMerchantId + "/request";
	private static 	final String	sandboxCheckoutButtonUrl= "http://sandbox.google.com/buttons/checkout.gif?merchant_id=" + sandboxMerchantId;		 // "http://sandbox.google.com/checkout/" after 1/3/07
	private static	final String	merchantId		= "xxxxxxxxxxxxxxxxxxxxx";
	private static	final String	merchantKey		= "xxxxxxxxxxxxxxxxxxxxxxxx";
	private static	final String	requestUrl		= "https://checkout.google.com/cws/v2/Merchant/" + merchantId + "/request";
	private static 	final String	checkoutButtonUrl	= "http://checkout.google.com/buttons/checkout.gif?merchant_id=" + merchantId;

	public				NzGoogleCheckoutOperations()
		{
		}

	public static	String		getMerchantID()
		{
		if (Utility.toBoolean(NzConfigurationResources.get(NziConstants.NZ_GOOGLE_CHECKOUT_USING_SANDBOX)))
			{
			return(sandboxMerchantId);
			}
		return(merchantId);
		}
	private static	String		getMerchantKey()
		{
		if (Utility.toBoolean(NzConfigurationResources.get(NziConstants.NZ_GOOGLE_CHECKOUT_USING_SANDBOX)))
			{
			return(sandboxMerchantKey);
			}
		return(merchantKey);
		}
	private static	String		getRequestUrl()
		{
		if (Utility.toBoolean(NzConfigurationResources.get(NziConstants.NZ_GOOGLE_CHECKOUT_USING_SANDBOX)))
			{
			return(sandboxRequestUrl);
			}
		return(requestUrl);
		}
	public static	String		getCheckoutButtonUrl()
		{
		if (Utility.toBoolean(NzConfigurationResources.get(NziConstants.NZ_GOOGLE_CHECKOUT_USING_SANDBOX)))
			{
			return(sandboxCheckoutButtonUrl);
			}
		return(checkoutButtonUrl);
		}
	public static 	String 		getHttpAuth()
		{
		if (Utility.toBoolean(NzConfigurationResources.get(NziConstants.NZ_GOOGLE_CHECKOUT_USING_SANDBOX)))
			{
			String combinedKey = sandboxMerchantId + ":" + sandboxMerchantKey;
			return(CryptUtil.base64Encode(combinedKey));
			}
		String combinedKey = merchantId + ":" + merchantKey;
		return(CryptUtil.base64Encode(combinedKey));
		}

	public 		boolean		billCustomer(
						String accountId,
						String pendindOrderId,
						Strings orderItemIds,
						String cost,
						String taxAmount,
						String discount,
						String totalAmount,
						Strings itemizedCosts,
						Strings itemizedCostsDescriptions,
						Strings itemizedDiscountIds,
						Strings itemizedDiscounts,
						Strings itemizedDiscountsDescriptions,
						String customerReference,
						String generalDescription,
						Strings errors,
						HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
		{

		// Google
		String[] signature = new String[1];
		String cart = null;

		try	{
			cart = buildEncodedCart(
						accountId,
						pendindOrderId,
						orderItemIds,
						cost,
						taxAmount + "",
						discount,
						totalAmount,
						itemizedCosts,
						itemizedCostsDescriptions,
						itemizedDiscountIds,
						itemizedDiscounts,
						itemizedDiscountsDescriptions,
						customerReference);
			}
		catch (Throwable t)
			{
			NzLog.logException("Unable to build google cart for account: " + accountId, t);
			}

		try	{
			URL url = new URL(getRequestUrl()); 

			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); 

			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Authorization","Basic " + getHttpAuth());
			conn.setRequestProperty("Content-Type","application/xml");
                	conn.setRequestProperty("Accept","application/xml");
			conn.setRequestProperty("Host", conn.getURL().getHost());
			conn.setUseCaches (false);
			conn.setInstanceFollowRedirects(true);
			conn.connect(); 

			OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
			wr.write(cart);
			wr.flush();
			//wr.close(); 

			CheckoutRedirect redirect = null;
			try	{
				String responseCode = "" + conn.getResponseCode();
				String responseMessage = "" + conn.getResponseMessage();

				//Get the response
				InputSource source = new InputSource(conn.getInputStream());
				redirect = (CheckoutRedirect)CheckoutCartBuilder.getInstance().parseToJAXB(source); 

				response.setStatus(302);
				response.sendRedirect(redirect.getRedirectUrl()); 

				return(true);
				}
			catch (Throwable t)
				{
				t.printStackTrace();
				NzLog.logException("Unable to redirect to google cart for account: " + accountId + ", to address: " + (redirect != null ? redirect.getRedirectUrl() : "null"), t);
				}
			}
		catch (Throwable t)
			{
			NzLog.logException("Unable to send request for google cart address message for account: " + accountId, t);
			}
		return(false);
		}

	/**
	 * Does this billing handler handle checkout synchronously, or must we wait for
	 * some kind of asynchronous message indicating the success of failure of the
	 &#038; checkout proocess?
	 **/
	public		boolean		isSynchronous()
		{
		return(false);
		}

	/**
	 * There is a little example code for building carts, but for
	 * alternative 1, in the jsp files found  in the top
	 * diretory of the example War file for java 1.5 on
	 * google's site
	 **/
	private		String		buildEncodedCart(
						String accountId,
						String pendingOrderId,
						Strings orderItemIds,
						String cost,
						String taxAmount,
						String discount,
						String totalAmount,
						Strings itemizedCosts,
						Strings itemizedCostsDescriptions,
						Strings itemizedDiscountIds,
						Strings itemizedDiscounts,
						Strings itemizedDiscountsDescriptions,
						String customerReference) throws JAXBException, Exception
		{
		String mKey = getMerchantKey();
  		String mId = getMerchantID();

		CheckoutCartBuilder pBuilder = null;
		pBuilder = CheckoutCartBuilder.getInstance();

		List itemList = new ArrayList();
		for (int i = 0; i < itemizedCosts.size(); ++i)
			{
			Item item = pBuilder.createShoppingItem(itemizedCostsDescriptions.get(i), NzOrderItemOperations.getOrderItemDescription(orderItemIds.get(i)), 1, Utility.toFloat(itemizedCosts.get(i)), null, null, null);
			itemList.add(item);
			}
		for (int i = 0; i < itemizedDiscounts.size(); ++i)
			{
			Item item = pBuilder.createShoppingItem(itemizedDiscountIds.get(i), itemizedDiscountsDescriptions.get(i), 1, -Utility.toFloat(itemizedDiscounts.get(i)), null, null, null);
			itemList.add(item);
			}

		ShoppingCart cart = pBuilder.createShoppingCart(itemList, null, null);

		// Unfortunately there is no programmatic way to create an empty MerchantCheckoutFlowSupport
		// taxTable = null;
		USStateArea stateArea = pBuilder.createStateArea("CO");
		DefaultTaxRule taxRule = pBuilder.createDefaultTaxRule(stateArea, 0.0F, false);
		List ruleList = new ArrayList();
		ruleList.add(taxRule);
		DefaultTaxTable taxTable = pBuilder.createDefaultTaxTable(ruleList);

		MerchantCheckoutFlowSupport flowSupport = pBuilder.createMerchantSupport(null, taxTable, null, null, null, null);

		flowSupport.setContinueShoppingUrl("http://" + NzConfigurationResources.get(NziConstants.NZ_APPLICATION_DOMAIN_NAME) + "/nav?action=portfolio-statements");

		AnyTypeImpl pendingOrderIdHolder = new AnyTypeImpl();
		pendingOrderIdHolder.setAny(pendingOrderId);
		cart.setMerchantPrivateData(pendingOrderIdHolder);

		Document cartDom = pBuilder.createCheckoutCart(cart, flowSupport);
		String clearXml = pBuilder.unmarshal(cartDom);

		return(clearXml);
		}

	}</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://gui.net/blog/2007/01/06/interfacing-to-google-checkout-java-14-linux-centos-using-the-xml-level-2-alternative-method-programmatic-api-part-1/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Why RPM sucks</title>
		<link>http://gui.net/blog/2007/01/05/why-rpm-sucks/</link>
		<comments>http://gui.net/blog/2007/01/05/why-rpm-sucks/#comments</comments>
		<pubDate>Sat, 06 Jan 2007 02:55:18 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Coder()]]></category>

		<guid isPermaLink="false">http://gui.net/blog/?p=19</guid>
		<description><![CDATA[This is obvious.
Anyone who uses it has run into the X.rpm has 226 dependencies, of which your system will have 10 unresolved, of various unknown degrees of criticality. Attempting to resolve those 10 involves serveral more rpm files, that have their own 826 dependcies, of which yet more are unresolved, of course.
Not to be pointing [...]]]></description>
			<content:encoded><![CDATA[<p>This is obvious.</p>
<p>Anyone who uses it has run into the X.rpm has 226 dependencies, of which your system will have 10 unresolved, of various unknown degrees of criticality. Attempting to resolve those 10 involves serveral more rpm files, that have their own 826 dependcies, of which yet more are unresolved, of course.</p>
<p>Not to be pointing fingers, but if people were A. actually to want to get work done, or to B. have a life outside of masturbating their operating systems, then this situation would not have gone on like this for as long as it has. I am in the A category. Masturbating OSes is a whole lotta fun, but it interferes with A.</p>
<p>One solution, which seems simple and straight forward, something the *nix&#8217;s have usually been pretty good at, is to have several global repositories on the net. Actually they can be distributed anyway people see fit, the repositories just have to be registered and secure.</p>
<p>From these repositories, the RPM install process, say for App-X, has a list of App-X files, its dependent files, and access to <em>their</em> dependencies, recursively, and just downloads and installs all the software required to run the darn thing.</p>
<p>For example, anÂ &#8216;install program&#8217; would just be a listÂ of pseudo URIs of the files and libs it needs, the URIs encoding the OS species, version number, and whatever else is needed to uniquely identify a file of some sort.</p>
<p>This could be expanded so that these &#8216;neo rpm&#8217; scripts could download and run programs locally, being a kind of service that runs on your box, whether the component programs of the service is stored / cachedÂ locally or not - a kind of mirror image of SOA - but that is for another day.</p>
<p>Â</p>
]]></content:encoded>
			<wfw:commentRss>http://gui.net/blog/2007/01/05/why-rpm-sucks/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Why CSS Sucks</title>
		<link>http://gui.net/blog/2006/12/15/why-css-sucks/</link>
		<comments>http://gui.net/blog/2006/12/15/why-css-sucks/#comments</comments>
		<pubDate>Sat, 16 Dec 2006 03:38:10 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Coder()]]></category>

		<guid isPermaLink="false">http://gui.net/blog/?p=18</guid>
		<description><![CDATA[1. CSS has no concept of what a real layout specification is. Geometric offsets are often unnecessarily hardcoded.
When people hype CSS over the html Table, I think they do not understand the functionality that the Table brings to the table. I think they do not understand the history of hard-coded coordinates versus automatic layouts. It [...]]]></description>
			<content:encoded><![CDATA[<p>1. CSS has no concept of what a real layout specification is. Geometric offsets are often unnecessarily hardcoded.</p>
<p>When people hype CSS over the html Table, I think they do not understand the functionality that the Table brings to the table. I think they do not understand the history of hard-coded coordinates versus automatic layouts. It is called &#8216;dynamic resizability&#8217;. You can set the minimum and maximum distance in a table and have the table resize based on the size of its container.</p>
<p>Not so CSS, which hearkens back to the bad old days under MSFT Windows.</p>
<p>So often, when the viewer of a page of CSS resizes their font, so that they can read the text, it overlaps itself and nearby text and images. How quaint.</p>
<p>2. CSS mixes layout and appearance, and soon in CSS 3, behavior.</p>
<p>Right now, common practice is to put everything into one CSS file, so if you want to add a new skin appearance, the new skin has to duplicate layout, and soon, behavior information along with colors and font sizes. Or what if some skins are behavior-specific, for example with and without javascript support.</p>
<p>You can see where this is leading&#8230; we will need an object-oriented CSS, that supports packages so that the CSS &#8216;programmer&#8217; will be able to manage the complexities.</p>
<p>So what we will end up with is html elements that have several pointers (or &#8216;tags&#8217; if you wish) that each refer to either their appearance, layout or behavior aspects. And to make it a little more sensical, the CSS behavior should just be a binding to javascript or PHP [update: or Ruby!] or something. And while we are at it, might as well add a tag for the content to permit dynamic content.</p>
<p>So what we will have at the end of the road, after we get through this adolescent infatuation with toys that mimic the good old days of Windows 95 et. al, is:</p>
<p>HTML Element</p>
<ul>
<li>Appearance id</li>
<li>Layout id (we are talking springs, struts, tables, and dumb margins only if needed)</li>
<li>Behavior binding id (i.e. onclick boundto store_data)</li>
<li>Implementation id (the javascript file location with a store_data method)</li>
<li>Content id</li>
<li>Importance quotient id</li>
<li>Semantic meaning id</li>
<li>Help id</li>
</ul>
<p>3. It is more difficult for search engines to determine what is being done to the content which they must know in order to see what is of importance on the page.</p>
<p>No, the emphasis tags really do not take the place of this analysis, because &#8216;really&#8217; is <em>really </em>not what this post is all about.</p>
<p>4. CSS is overly powerful</p>
<p>For example: font-size is multiplicative (if another element and its child both have font size 8em, then the child will be 64em).</p>
<p>The law of against designing a language that has numerous unintended consequences has yet again been violated, very much in the spirit of C++. You cannot just look at a piece of code and know what it does without CLOSELY examining the N^N-1 possible consequences of all other assignments in this and any included files.</p>
<p>Similarly for the overly broad assignment such as:</p>
<p>.class a</p>
<p>which assigns &#8216;a&#8217; some style which has every chance of having been assigned at least one other style somewhere else in the CSS hierarchy. Maybe. Which came first? in which file? And how did that precedence of CSS assignments go again?</p>
<p>So in conclusion,</p>
<p>CSS has the mishappen non-structure of assembly language [although I like the limited instruction set of asm languages, so this is an insult to them], the syntactically over-powering &#8216;why use a hammer when an atom bomb will do&#8217; approach of C++, with the spaghetti-inducing compression of responsibilities and nostalgic lack of runtime layout tools of pre-Java MSFT Windows.</p>
<p>&#8230;aka CSS sucks.</p>
<p>[Oh, and it would be nice to see a syntax/completeness checker tool. But I bet that would just add another layer of incompatible implementation to deal with on top of all the others] [Update: FireBug does help some, tracing all the inheritance trees for you. Does no one else see how wacko this is? Yet another specification that tries to be too many things].</p>
]]></content:encoded>
			<wfw:commentRss>http://gui.net/blog/2006/12/15/why-css-sucks/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Javascript</title>
		<link>http://gui.net/blog/2006/09/04/javascript/</link>
		<comments>http://gui.net/blog/2006/09/04/javascript/#comments</comments>
		<pubDate>Tue, 05 Sep 2006 03:32:20 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Coder()]]></category>

		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://gui.net/blog/?p=17</guid>
		<description><![CDATA[So, the last topic begs the question&#8230;.
So is everyone writing their own DIY javascript debuggers? And, with DOM/HTML, absolute positioning layout engines? And widget toolkits. And Flash-like animation tools? And syntax checkers? And println and logging tools?
 Sometimes I think our industry is making leaps and bounds every month - new things better things all [...]]]></description>
			<content:encoded><![CDATA[<p>So, the last topic begs the question&#8230;.</p>
<p>So is everyone writing their own DIY javascript debuggers? And, with DOM/HTML, absolute positioning layout engines? And widget toolkits. And Flash-like animation tools? And syntax checkers? And println and logging tools?</p>
<p> Sometimes I think our industry is making leaps and bounds every month - new things better things all the time.</p>
<p>And then there&#8217;s now.</p>
<p>Is it just that everyone is on the server bandwagon hopping from J2EE to Struts, to Spring to Ruby on Rails to&#8230;.and this is keeping them all busy?</p>
<p>Arguably it should be the browser manufacturers that write the javascript debuggers for their browser - seems like attracting developers is a good thing if one wants to dominate such a market&#8230;</p>
<p>Anyone research MSFT&#8217;s JavaScript debugger lately?</p>
<p>BWTFDIK.</p>
]]></content:encoded>
			<wfw:commentRss>http://gui.net/blog/2006/09/04/javascript/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Rolling your own</title>
		<link>http://gui.net/blog/2006/08/24/rolling-your-own/</link>
		<comments>http://gui.net/blog/2006/08/24/rolling-your-own/#comments</comments>
		<pubDate>Thu, 24 Aug 2006 12:56:13 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Coder()]]></category>

		<guid isPermaLink="false">http://gui.net/blog/?p=16</guid>
		<description><![CDATA[Work on theÂ Obsidian Framework is taking a back seat lately as I write a JSP (MySQL, JavaScript, Resin, CSS, etc.) web application. I am hoping that is going to be a nine-week baby&#8230;. but we&#8217;ll see.
More on the unpleasant state of some of these haphazard technologies later (I am refering[sic] to Javascript and CSS) [...]]]></description>
			<content:encoded><![CDATA[<p>Work on theÂ Obsidian Framework is taking a back seat lately as I write a JSP (MySQL, JavaScript, Resin, CSS, etc.) web application. I am hoping that is going to be a nine-week baby&#8230;. but we&#8217;ll see.</p>
<p>More on the unpleasant state of some of these haphazard technologies later (I am refering[sic] to Javascript and CSS) - but as I write the code I came face to face a number of times with the option to either download and use somebody else&#8217;s code or write my own.</p>
<p>Â Given that Not Invented Here (NIH) is a perjorative it is obviously unpopular to advocate writing ones ownÂ routines when reusing someone elses will &#8216;work&#8217;.</p>
<p>Â But there are good reasons to write ones own:</p>
<p>1. When it is faster to write the code that it is to understand how to useÂ the often overly generalized and overly documented alternative (why does a logger, or a dispatch routine,Â take a whole book to document?).</p>
<p>2. When there is anticipation that the functionality that you require does not quite fit into the set of featrures offered by the exisintg alternatives. A collary to #1, really. It is that the time spent trying to learn someone elses code well-enough to A. use it and B. tweak it often is much greater than the time it takes to write it themselves, which comes with aÂ deep understanding that allows one to customizeÂ the solutionÂ in the future.</p>
<p>3. The alternatives are so general that they hog way more resources than what is desired, or necessary</p>
<p>This is all extemporaneously written and it is very late at nightÂ - and there are more reasons than listed above - but the whole thing should be able to be expressed by an equation:</p>
<p>S - set of features required<br />
TS - time to implement those features<br />
SP - giant set of features offered by the &#8216;popular&#8217; and more general solutions<br />
TPÂ - The time it will take to understand and customize the features to solve the problem we are trying to solve</p>
<p>I am saying that TS is often less, way less, than TP because S isÂ way less, and <em>somewhat</em> <em>different</em>, than SPÂ - and that over time the indepth understanding of the code that is hand-rolled allows one to customize their solution over time to gain market advantage over the competition.</p>
<p>I am not talking about writing one&#8217;s own web browser here (wish I was) or database, typically, but about things like log4j, Junit, Struts, etc.</p>
<p>It is my suspicion that the popularity of this &#8216;rather download it than write it&#8217; attitiude is because</p>
<p>1. The current industry hype says we should</p>
<p>2. Many programmers do not know how to write code - but stitching together someone else&#8217;s code is manageable and delays are more justifyable to management if they can point their finger at a tool insetad of their own code.</p>
<p>3. Many programmers who choose what tool to use do not care if they understand the tool or not - they will be on to something else soon enough.</p>
<p>4. Management wants interchangeable coder-botsÂ and everything that will make coder-bots skill-sets more indentical, likeÂ understanding the toolkits that their programmers are downloading-Â makes them that more interchangeable (i.e. easier to hire andÂ fire).</p>
<p>5.Â HandÂ rolled codeÂ does not get a cool name that can be putÂ on a resume.</p>
<p>So, here&#8217;s an idea,Â let&#8217;s start naming our custom software. Let&#8217;s see, I just wrote Dispatchertron 1.0., LoggerSharp and TestBot3000 [this works great - it is able to make a browser navigate the site at random - filling in forms as it encounters them with randomly valid data - can&#8217;t wait to see if it can be made to handle stuff like uploads&#8230;].</p>
<p>Don&#8217;t ya think they&#8217;llÂ look great on a resume? :-)</p>
<p>Â </p>
<p>The advantages of DIY are numerous:</p>
<p>1. Ability to fix bugs yourselves</p>
<p>2. Abiltiy to control the release schedule</p>
<p>3. Ability to control the feature set</p>
<p>4. Abiltiy to control the dependencies</p>
<p>5. Competitive advantage</p>
<p>Â Using someone elses code does not let a corp focus on core competancies if it takes them more staff hours to understand and use the externally determined feature set and find and fix their bugs thanÂ it does to writeÂ a little bit of code that does what you need now - written in such a fashionÂ that it is expandable (Agile is good to a point - butÂ until computers program computers - it is often quicker in the long run to think ahead a little)Â in the direction the corp wants to go.</p>
<p>Â</p>
]]></content:encoded>
			<wfw:commentRss>http://gui.net/blog/2006/08/24/rolling-your-own/feed/</wfw:commentRss>
		</item>
		<item>
		<title>More on the Next-Gen User Interface</title>
		<link>http://gui.net/blog/2006/05/10/more-on-the-next-gen-user-interface/</link>
		<comments>http://gui.net/blog/2006/05/10/more-on-the-next-gen-user-interface/#comments</comments>
		<pubDate>Wed, 10 May 2006 12:17:44 +0000</pubDate>
		<dc:creator>Michael</dc:creator>
		
		<category><![CDATA[Coder()]]></category>

		<category><![CDATA[The GUI]]></category>

		<guid isPermaLink="false">http://gui.net/blog/?p=14</guid>
		<description><![CDATA[Well, the last post may have been opaque - and was in some sense vacuously true.
What Obsidian is, and what I think the GUI should evolve to be, is&#8230;a meta GUI.
Meta-GUI: Where the user sits down and can choose some data and choose operations to perform on that data, AND choose how they want to [...]]]></description>
			<content:encoded><![CDATA[<p>Well, the last post may have been opaque - and was in some sense vacuously true.</p>
<p>What Obsidian is, and what I think the GUI should evolve to be, is&#8230;a meta GUI.</p>
<blockquote><p>Meta-GUI: Where the user sits down and can choose some data and choose operations to perform on that data, AND choose how <em>they </em>want to see and work with the set of available data and see and work with that particular data of interest and see and work with the set of operations and see and work with the operation itself in action and see and work with the results.</p></blockquote>
<p>All this so easy that a CEO can do it. Actually, Obsidian is more targeted towards ordinary people - but deep down, way deep, CEOs - who typically are targetted because of their software-purchasing budget powers - are ordinary people too [OK, sorry for the post market bubble bursting CEO humor].</p>
<p>Anyway, as you can see, this meta GUI is a very general flexible description of how humans interact with computers. It is just that, currently, most of these things in most applications are FROZEN by the programmer - so that the user has NO flexibility - they are in a multi-dimensional straight-jacket (and don&#8217;t talk to me about &#8217;skins&#8217; - The ability to change the application&#8217;s colors&#8230;? whoo hoo!]</p>
<p>This degree of flexibility takes the GUI beyond the physical metaphors we have been tied to since Xerox PARC - or rather builds upon them to make the user some kind of super-being in the virtual reality of the computer.</p>
<p>The challenges the Obsidian Framework has are - well there is really only one:</p>
<p>How to make using the GUI with so much flexibility as easy to use as, say, using a TV? or driving a car?</p>
<p>Well, there I go asking a question and answering it in the same sentence&#8230; :-)</p>
<p>The solution Obsidan itself takes, and it is the easy-way-out so to speak, but if you think about it there is no other answer for a generic framework supporting this kind of GUI, is</p>
<p>To Punt.</p>
<p>To make the Meta-GUI itself a plug in.</p>
<p>The key here is to realize that the Meta-GUI is somewhat recursive. No, that&#8217;s not right. It is like those Russian dolls where inside one doll is another, and inside that is another, etc. Except that any of the dolls can contain any of the other dolls - and/or itself. [and, unfortunatately, this is not the typical &#8216;container isa part&#8217; relationship, though visually that is often what it looks like].</p>
<p>I.E. a Meta GUI defines interactions between other plug-in GUIs, that may and often do define iteractions with (for example a list, or a search field) other GUIs and on and on. And of course there is a GUI to displays the choices of possibleMeta GUIs, and a GUI to choose the GUI that lists Meta GUIs. All plugins of course.</p>
<p>It is the flexibility of this &#8216;Universe of Choices&#8217;, where the atoms are more or less well-defined but what you can build with them is not - and how do you &#8216;boot&#8217; such a universe? -  that makes writing Obsidian somewhat of a challange.</p>
<p>Oh, yeah, and there is how to make all these plugins - functional plugins, GUI plugins, and data source plugins, plugin-customizer plugins, plugin-network-builder plugins all work together. </p>
<p>The last post talked about how it is these types of frameworks, no matter how crippled thye have been in the past - that have spawned large numbers of very specialized, one-of-a-kind &#8217;software screw&#8217; factories&#8217; (ex: Photoshop). The point being that the specification of how to make a plug-in just has to be understandable and to actually work - it does not have to be created by some consortium populated by big companies with their fiduciary desire and need to <em>over complexify </em>everything.</p>
<p>So that is one key to how Obsidian is being designed&#8230; Keep it small, simple and stupid. Otherwise my poor brain is just too lazy these days to Grok it. There is enough inherent challenges for the brain with respect to Meta GUIs - no reason to add more.</p>
<p>But sometimes small, simple and stupid creates its own complexitites - especially with regards to debugging.</p>
<p>For example, there is only one kind of Data in the whole framework - in order that every plugin, and every <em>type </em>of plugin, knows what to expect - and it can be interesting to debug a piece of data as it winds itself through the system.</p>
<p>[Which creates a need for a god-like set of choosable nested GUIs that looks at the Meta GUI from the programmers perspective&#8230;]</p>
<p>Next&#8230; more on the architectural choices taken to make this all work and make it implementable in finite time&#8230; oh, and maintainable by someone with not a lot of free time.</p>
]]></content:encoded>
			<wfw:commentRss>http://gui.net/blog/2006/05/10/more-on-the-next-gen-user-interface/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
<!-- analytics977 --> 
