<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" 
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
    xmlns:admin="http://webns.net/mvcb/"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
	<channel>
<title>Benedict &#x26; his Soapbox</title><link>http://benedictcohen.co.uk/index.php</link><description>Benedict &#x26; his Soapbox</description><dc:language>en</dc:language><dc:creator>ben@benedictcohen.co.uk</dc:creator><dc:rights>Copyright 2009 Benedict Cohen</dc:rights><dc:date>2010-09-02T16:44:33+01:00</dc:date><admin:generatorAgent rdf:resource="http://www.realmacsoftware.com/" />
<admin:errorReportsTo rdf:resource="mailto:ben@benedictcohen.co.uk" /><sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<sy:updateBase>2000-01-01T12:00+00:00</sy:updateBase>
<lastBuildDate>Thu, 02 Sep 2010 21:46:53 +0100</lastBuildDate><item><title>Apple&#x27;s Hardware and GUI Design Symmetry</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>None</category><dc:date>2010-09-02T16:44:33+01:00</dc:date><link>http://benedictcohen.co.uk/files/f91804c3d53152c85ffe76d103088c47-16.php#unique-entry-id-16</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/f91804c3d53152c85ffe76d103088c47-16.php#unique-entry-id-16</guid><content:encoded><![CDATA[<br />Yesterday Apple released iTunes 10 along with updates to the iPod line. The iTunes interface has had a few tweaks; 'album list', grey icons, repositioning of the 'traffic lights' to match the mini player and a restyled volume slider. The volume slider mimics the appearance of the shuffle switch of the iPod Shuffle: <br /><br /><img class="imageStyle" alt="slider" src="http://benedictcohen.co.uk/files/slider.png" width="334" height="110"/><br /><br /><img src="http://upload.wikimedia.org/wikipedia/commons/0/0c/IPod_Shuffle_Second_Generation_Green_Clip_Opened_by_hand.jpg" style="max-width:800px;" /><br /><br />The symmetry between Apple GUIs and hardware has existed for a while. In 1998 Apple had released the iMac. The iMac was an all in one PC with a trend setting corrugated plastic case. OS X, released in 2001, included a redesigned interface called Aqua. Aqua mimic the corrugated plastic of the iMac:<br /><br /><img src="http://upload.wikimedia.org/wikipedia/commons/5/56/Indigo_iMac_G3_slot_loading.jpg" style="max-width:800px;max-height:800px;" /><br /><br /><img src="http://upload.wikimedia.org/wikipedia/en/d/d8/MacOSX10-0screenshot.png"  style="max-width:800px;max-height:800px;" /><br /><br />In 2003 the Power Mac G5 and PowerBook G4 were released. These Macs had a brushed aluminium case. OS X Panther was also released in 2003 and included a new brushed aluminium style for Finder:<br /><br /><img src="http://upload.wikimedia.org/wikipedia/commons/c/c6/Power_Mac_G5_hero_left.jpg"  style="max-width:800px;max-height:800px;" /><br /><br /><img src="http://upload.wikimedia.org/wikipedia/en/5/54/AM_MacOSX_Panther.png"  style="max-width:800px;max-height:800px;" /><br /><br /><br />By the release of Tiger in 2005 Apples hardware line up included the snow white iMac G5 and iBook. Tiger replaced the corrugated GUI appearance with a smooth polished appearance that matched the snow white hardware:<br /><br /><img src="http://upload.wikimedia.org/wikipedia/commons/b/b3/IMac_G5_Rev._A_front.jpg"  style="max-width:800px;max-height:800px;" /><br /><br /><img src="http://upload.wikimedia.org/wikipedia/commons/6/62/IBook_G4.jpg"  style="max-width:800px;max-height:800px;" /><br /><br /><img src="http://upload.wikimedia.org/wikipedia/en/f/fe/TigerDesk.png"  style="max-width:800px;max-height:800px;" /><br /><br /><br />By the release of Leopard in 2007 the iMac, Mac Mini, MacBook Pro and Apple TV all had a brushed aluminium case, and once again the interface had evolved:<br /><br /><img src="http://upload.wikimedia.org/wikipedia/commons/2/24/MacBook_Pro_situated_on_a_wooden_table.jpg"  style="max-width:800px;max-height:800px;" /><br /><br /><img src="http://upload.wikimedia.org/wikipedia/commons/0/02/Mac-mini-1st-gen.jpg"  style="max-width:800px;max-height:800px;" /><br /><br /><img src="http://upload.wikimedia.org/wikipedia/en/c/c0/Leopard_Desktop.png"  style="max-width:800px;max-height:800px;" /><br /><br /><br />Another interface tweak in iTunes 10 are the 'flat' buttons:<br /><br /><img class="imageStyle" alt="buttons" src="http://benedictcohen.co.uk/files/buttons.png" width="189" height="26"/><br /><br />These remind me of a <a href="http://arstechnica.com/apple/news/2010/05/apple-combines-touch-laser-etching-for-disappearing-input.ars">patent for etched buttons</a>. Could these flat buttons be a hint to the design of new Apple hardware?]]></content:encoded></item><item><title>HTML parsing/screen scraping in iOS</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>None</category><dc:date>2010-08-25T11:24:11+01:00</dc:date><link>http://benedictcohen.co.uk/files/d08b885904b19b01692ad49aaca6e994-15.php#unique-entry-id-15</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/d08b885904b19b01692ad49aaca6e994-15.php#unique-entry-id-15</guid><content:encoded><![CDATA[I asked a question on Stack Overflow about how to do screen scarping in iOS. The outcome was that using running some javascript with UIWebView stringByEvaluatingJavaScriptFromString: to extract and serialise the data is the best approach. However, there are a few gotchas.<br />Firstly, it's worth noting what stringByEvaluatingJavaScriptFromString actually 'returns'. It's a little strange but some examples make it clear. The comment at the end of the lines is the output of NSLog:<br /><br /><pre><br />NSLog(@"%@", [webView stringByEvaluatingJavaScriptFromString:@"'hello';"]);   // hello<br />NSLog(@"%@", [webView stringByEvaluatingJavaScriptFromString:@"'hello';'goodbye';"]);   // goodbye<br />NSLog(@"%@", [webView stringByEvaluatingJavaScriptFromString:@"return 'hello';"]);   //<br />NSLog(@"%@", [webView stringByEvaluatingJavaScriptFromString:@"var greeting = function(){return 'hello';}; greeting();"]);   //hello<br /></pre><br />However, we can use stringByEvaluatingJavaScriptFromString: to inject javascript into the DOM and make additional stringByEvaluatingJavaScriptFromString calls to fetch the result:<br /><br /><pre><br />NSLog(@"%@", [webView stringByEvaluatingJavaScriptFromString:@"document.wordOfTheDay = 'discorporate';"]);   //<br />NSLog(@"%@", [webView stringByEvaluatingJavaScriptFromString:@"document.wordOfTheDay;"]);   //discorporate<br /></pre><br /><br />It&rsquo;s worth noting that there are other ways to <a href="http://drnicwilliams.com/2008/11/10/to-webkit-or-not-to-webkit-within-your-iphone-app/" rel="self">communicate with the javascript in a UIWebView</a>.<br /><br />OK, on to the scraping.<br />The biggest problem is being certain that the DOM has loaded before the script is run. The UIWebViewDelegate protocol includes webViewDidFinishLoad: which at first glance seems perfect. If only life was that simple. I've encountered quite a few pages that trigger webViewDidFinishLoad: multiple times before the DOM is actually ready (presumable this is due to iframes or javascript). <br />The solution is to combine webViewDidFinishLoad: with the standard javascript approach of detecting when the DOM is ready. On the first invocation of webViewDidFinishLoad: we inject code to check the DOM for readyness (injecting this in webViewDidStartLoad: has unpredictable results):<br /><br /><pre><br />if (/loaded|complete/.test(document.readyState))<br />{<br />    document.UIWebViewDocumentIsReady = true;<br />} else<br />{<br />    document.addEventListener('DOMContentLoaded', function(){document.UIWebViewDocumentIsReady = true;}, false);<br />}<br /></pre><br />We then poll the UIWebView to determine when the DOM is ready:<br /><br /><pre><br />-(void)pollDocumentReadyState<br />{<br />    if ([@"true" caseInsensitiveCompare:[webview stringByEvaluatingJavaScriptFromString:@"document.UIWebViewDocumentIsReady;"]] == NSOrderedSame)<br />    {<br />        NSString *json = [webView stringByEvaluatingJavaScriptFromString:myFancyParsingAndSerializationScript];<br />	//Do something with json<br />    } else <br />    {<br />        [self performSelector:@selector(pollDocumentReadyState) withObject:nil afterDelay:1];<br />    }<br />}<br /></pre><br /><br />That's it!<br /><br />I've created a class, <a href="http://benedictcohen.co.uk/assets/EMKJavascriptEvaluation.zip" rel="self">EMKJavascriptEvaluation</a> (zip archive), to handle all of this. Here&rsquo;s a usage example:<br /><br /><pre><br />-(void)beginScrape<br />{<br />    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(jsEvaluationCompleted:) name:EMKJavascriptEvaluationComplete object:nil];<br /><br />    NSString *scriptPath = [[NSBundle mainBundle] pathForResource:@"myFancyParsingAndSerializationScript" ofType:@"js"];<br />    NSString *script = [NSString stringWithContentsOfFile:scriptPath encoding:NSUTF8StringEncoding error:NULL];<br />    NSURL* url = [NSURL URLWithString: @"http://example.com"];<br /><br />    EMKJavascriptEvaluation *evaluation = [EMKJavascriptEvaluation evaluateScript:script withHtmlAtURL:url];<br /><br />    [evaluation injectLibraryAtPath:[[NSBundle mainBundle] pathForResource:@"jquery" ofType:@"js"]];<br />    [evaluation injectLibraryAtPath:[[NSBundle mainBundle] pathForResource:@"json2" ofType:@"js"]];<br /><br />    [evaluation evaluate];<br />}<br /><br /><br />-(void)jsEvaluationCompleted:(NSNotification*)notification<br />{<br />    NSLog(@"result: %@", [[notification object] result]);<br />}<br /></pre><br /><br />Take a look at the .h for details. <br /><br />The code is completely free and comes with no warranty what so ever (MIT style license). I haven&rsquo;t used this code in a finished app yet so there&rsquo;s probably a bug or two. Please <a href="mailto:ben@benedictcohen.co.uk" rel="self">send me an email</a> if you have any comments.]]></content:encoded></item><item><title>Data access layer with PHP Streams</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>None</category><dc:date>2010-03-27T16:06:37+00:00</dc:date><link>http://benedictcohen.co.uk/files/4f8ab77b836ee6ec9ed4d70b384abf97-14.php#unique-entry-id-14</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/4f8ab77b836ee6ec9ed4d70b384abf97-14.php#unique-entry-id-14</guid><content:encoded><![CDATA[I had an idea: "Why not use the PHP Streams layer as an abstraction mechanism for a data access layer?". After reading the <a href="http://php.net/manual/en/book.stream.php" rel="self">PHP streams manual</a> I can see no reason why this wouldn't work. By using streams the  boiler plater functionality of a request can then be distilled into standard file operations. Authentication and authorization can be handled by defining a uri scheme that follows the standard form of <code>scheme://username:password@....</code> and calling <code>getperems()</code> on the uri. If <code>username:password</code> is invalid then <code>getperms()</code> would return <code>false</code>, else it would return standard unix permissions. It's a very RESTful solution.]]></content:encoded></item><item><title>@property&#x2c; dot syntax and a sprinkling of code</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>None</category><dc:date>2010-03-22T18:54:35+00:00</dc:date><link>http://benedictcohen.co.uk/files/05973d12387b53e0c7488a508aac62eb-13.php#unique-entry-id-13</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/05973d12387b53e0c7488a508aac62eb-13.php#unique-entry-id-13</guid><content:encoded><![CDATA[Until recently I've avoided dot syntax. I reluctantly adopted dot syntax due to the fact that Apple uses it extensively in iPhone Xcode templates. I had no desire to re-write the templates but I also wanted my code to be consistent. Therefore I bit the bullet and started using dot syntax.<br /><br />I'm glad I made the change. With dot syntax I find it easier to see the difference between when the state of an object is being changed and when the object is being asked to perform an action.<br /><br />(See <a href="http://cocoawithlove.com/2008/08/in-defense-of-objective-c-20-properties.html" rel="self">In defense of Objective-C 2.0 Properties</a> for a round up of the criticism and a defense of dot syntax).<br /><br />Although I've only recently been using dot syntax I have always used the @property directive. Some times when setting (and occasionally getting) a property the object being called needs to do a little extra work, for example updating an internal cache. When using standard message syntax for setters this was easy to implement:<br /><br /><code>@interface ImageGallery : NSView{    ...    NSArray* images;}@property(readwrite, retain, setter:setImagesSynth:) NSArray* images;-(void)setImages:(NSArray*)newImages;...@end@implementation ImageGallery...@synthesize images;-(void)setImages:(NSArray*)newImages{    [self setImagesSynth: newImages];    //do additional work here    [self resizeCanvas];}@end</code><br />(See <a href="http://www.algorithm.com.au/blog/files/objective-c-2-accessors-memory-management.php" rel="self">Objective-C 2.0 Accessors & Memory Management</a> at Stay Hungry, Stay Foolish for a full description of this solution).<br /><br />Unfortunately this solution doesn't work with dot syntax. With dot syntax...<br /><br /><code>gallery.images = photos;</code><br /><br />is compiled into...<br /><br /><code>[gallery setImagesSynth: photos];</code><br /><br />My solution is to use 2 property declarations. A private one that does the basic getting and setting and a public one which the extra code can be added to:<br /><br /><code>@interface ImageGallery : NSView{    ...    NSArray* imagesProperty;}@property(readwrite, retain) NSArray* imagesProperty;@property(readwrite, retain) NSArray* images;...@end@implementation ImageGallery...@synthesize imagesProperty;@dynamic images;-(NSArray*)images{    return self.imagesProperty;}-(void)setImages:(NSArray*)newImages{    self.setImagesProperty = newImages;    //do additional work here    [self resizeCanvas];}@end</code><br /><br />Admittedly this is a lot of boiler plate code which does slightly undermining the convenience of @property. However this approach allows a class to present a uniform interface for all of its properties.]]></content:encoded></item><item><title>Don&#x27;t forget the data model&#x21;</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>None</category><dc:date>2010-02-14T13:24:55+00:00</dc:date><link>http://benedictcohen.co.uk/files/2e7f37757a7597415a7a1fda0e41ab20-12.php#unique-entry-id-12</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/2e7f37757a7597415a7a1fda0e41ab20-12.php#unique-entry-id-12</guid><content:encoded><![CDATA[Regardless of the complexity of an application a <a href="http://en.wikipedia.org/wiki/Data_model" rel="self">data model</a> can help gleam a deeper understanding of the problem that the application is addressing. A data model is an abstract description of the data, it is not tied to any technology. A data model illustrates the core of an application. A data model will help find flaws in your application and provides rationale for further development.<br /><br />Reading the Wikipedia <a href="http://en.wikipedia.org/wiki/Data_modeling" rel="self">Data Modelling</a> article may leave you scratching your head. Theres a huge number of long, cryptic terms and it's not clear how or where to start the modelling. I'm not a data modelling expert, but my approach, outlined below, has served me well.<br /><br />I use two types of diagrams. I start by sketching an <a href="http://en.wikipedia.org/wiki/Entity-relationship_model" rel="self">Entity Relationship model</a> (ERM). I do this on paper and iterate quickly. The ERM gives me a broad understanding of the problem. Once I'm happy with the ERM I move onto an<a href="http://en.wikipedia.org/wiki/Entity-attribute-value_model" rel="self"> Entity-attribute-value model</a> (EAV). The EAV lets me flesh out the details and describe inheritance relationships within the data (EAV is the approach used by Core Data).]]></content:encoded></item><item><title>Zend Framework Quickstart internal server error</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>None</category><dc:date>2009-11-19T18:50:37+00:00</dc:date><link>http://benedictcohen.co.uk/files/1f07a6ae7f587ae156ec4d43c34b5cd0-11.php#unique-entry-id-11</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/1f07a6ae7f587ae156ec4d43c34b5cd0-11.php#unique-entry-id-11</guid><content:encoded><![CDATA[I&rsquo;m learning the Zend Framework with the help of the quick start tutorial. I received a &lsquo;500 internal server error&rsquo;  when trying to access <code>/guestbook</code>. A look in the Apache log file (<code>/private/var/log/apache2/error_log</code> or via Console.app) reveals that mod_rewrite is exceeding 10 redirects. The solution is to edit <code>/quickStartRoot/public/.htaccess</code> file so that the rewrite is an absolute path, ie the last line should be: <code>RewriteRule ^.*$ /index.php [NC,L]</code><br />]]></content:encoded></item><item><title>Setting up a web development environment in OS X</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>None</category><dc:date>2009-11-19T18:47:49+00:00</dc:date><link>http://benedictcohen.co.uk/files/248bc189a6ff9f108be966b97caa2259-10.php#unique-entry-id-10</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/248bc189a6ff9f108be966b97caa2259-10.php#unique-entry-id-10</guid><content:encoded><![CDATA[<ol class="arabic-numbers"><li>Follow <a href="http://alen.mobi/blog/2009/09/16/snow-leopard-web-developer/" rel="self">Snow Leopard for web developer</a></li><li>Use <a href="http://panic.com/coda" rel="self">Coda</a> by Panic</li></ol>]]></content:encoded></item><item><title>Tweaking HTTP</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>None</category><dc:date>2009-10-16T12:37:12+01:00</dc:date><link>http://benedictcohen.co.uk/files/1a8c51a62efae4ef1317004b1e3ef704-9.php#unique-entry-id-9</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/1a8c51a62efae4ef1317004b1e3ef704-9.php#unique-entry-id-9</guid><content:encoded><![CDATA[<span style="color:#333333;">I recently watched Alan Kay's OOPSLA 1997 lecture "</span><span style="color:#333333;"><a href="http://video.google.com/videoplay?docid=-2950949730059754521#" rel="self">the Computer Revolution hasn't Happened Yet</a></span><span style="color:#333333;">". Watching it was mildly frustrating as Kay would make tantalising abstract points and not elaborate upon them. <br /><br />Kay makes some points about the web which I initially found jarring. But after thinking about the web in the context of the message passing environments that Kay helped pioneer I began to see the flaws that Kay may have had in mind. <br /><br />So, what's wrong with the web and how can it be fixed? In my view there are two main problems, both of which can be solved by without compromising the simplicity of the web. These problems are the assumption of prior knowledge and the richness of communication.<br /><br /></span><h2>Background</h2><span style="color:#333333;"><br /></span><span style="color:#333333;">When the web was created it consisted of one data format, HyperText Markup Language documents (HTML), and a protocol for transporting them, HyperText Transport Protocol (HTTP). The only web clients were web browsers and the only action they could perform was to GET documents. Browser only had to know how to handle HTML data as that was the only type of data on the web. This was the web as codified in the 0.9 spec.<br /></span><span style="color:#333333;"><br />The short comings of the 0.9 spec were quickly addressed by the 1.0 spec (and further expanded in the 1.1 spec) which extended HTTP in two ways. Firstly it allowed arbitrary data, not just HTML, to be transported. Secondly, it augmented the GET request method with the POST method, thus providing a mechanism for the client to send data to the server. It is the implementation of these two features which I think Alan Kay may have had in mind when he criticised the web.<br /><br /></span><h2>Arbitrary data and the assumption of prior knowledge</h2><span style="color:#333333;"><br />In the 0.9 spec HTTP was coupled to HTML - any data sent over HTTP was assumed to be HTML. The web was initially a system for sharing interlinked documents which were to be displayed on a screen for a human to read. This coupling allowed the system to remain simple but at a cost - if the data could not be represented in an HTML document then it could not be made available on the web.<br /><br />The coupling of HTTP and HTML was addressed by the introduction of the content-type header. The content-type header allowed the server to send metadata that described the format of the data that the client had requested. The content-type header effectively de-coupled HTTP from HTML resulting in a more flexible system. This opened up HTTP to any situation that required data to be transmitted from point A to point B. The data no longer had to be HTML and there was no requirement for it to be consumable by humans. A client could be any software that consumed data, not just a browser.<br /><br />This increase in scope created a conflict with the primary intent of the web as a system for sharing documents. In the 0.9 spec the browser only had to render HTML documents to be able to display all of the documents available on the web. The implication of the content-type header is that if a browser is to render everything on the web then it has to be able to render any data that the world can throw at it - which is a seemingly impossible task. This problem is currently address by the following measures:<br /><br /></span><ol class="arabic-numbers"><li><span style="color:#333333;">Standards based data formats are developed and promoted</span></li><li><span style="color:#333333;">Browsers directly render common data types (i.e. the most common data formats, which are not necessarily the standards based formats)</span></li><li><span style="color:#333333;">Browsers provide a plugin mechanism for other data types (the HTML spec provides a mechanism for embedding these plugins in the form of the <object> element)</span></li><li><span style="color:#333333;">Browsers save unknown data types to disk and hand them off to the OS</span></li></ol><span style="color:#333333;"><br />I believe this approach is defeatist. The system doesn't empower the browser, instead it defaults to the lowest common denominator. <br /><br />A better solution would be for the server to provided rendering instructions in addition to the data. This would effectively separate the communication of the data from the rendering of the data. Therefore the browser would only have to fetch the data and provide a screen space for the data renderer. A HTTP headers listing a URI would be an adequate mechanism for locating a renderer - for example </span><code>pargma: content-render http://example.com/renders/mathml</code><span style="color:#333333;">. This approach could resolve or help to resolve all sorts of problems:<br /></span><ul class="disc"><li><span style="color:#333333;">'browser' compatibility problems (rendering engine compatibility problems is technically more accurate) e.g. </span><code>pargma: content-render http://microsoft.com/guano/trident</code></li><li><span style="color:#333333;">codec support e.g. </span><code>pargma: content-render http://xiph.org/codec/ogg</code></li></ul><span style="color:#333333;"><br />I think this is what Alan Kay was getting at when he said the following:<br /><br /></span><blockquote><p>"HTML on the Internet has gone back to the dark ages because it presupposes that there should be a browser that should understand its formats. This has to be one of the worst ideas since MS-DOS."</p></blockquote><span style="color:#333333;"><br /></span><h2>Richness of communication</h2><span style="color:#333333;"><br />In the 0.9 spec there was one request method that a client could use to communicate with the server; GET. Later this was augmented to include other methods, most noticeable POST, PUT and DELETE. The HTTP spec outlines the intent of this verbs, but due to technical limitations, ambiguity in the spec (and poor programming practice) request methods do not adequately describing the intent of the request. Some examples:<br /><br /></span><ol class="arabic-numbers"><li><span style="color:#333333;">The GET method can only use the query part of the URI to transmit data to the server. The URI has a practical maximum length, therefore there is a limit to the amount of data a client can send to the server. To overcome this problem clients often send query data via the POST method. The POST (and PUT) methods both imply the creation of a resource, which is not think of happening when we querying a resource.</span></li><li><span style="color:#333333;"><a href="http://www.w3.org/Provider/Style/URI" rel="self">Cool URI's Don't Change</a></span><span style="color:#333333;"> states that </span><blockquote><p>Pretty much the only good reason for a document to disappear from the Web is that the company which owned the domain name went out of business or can no longer afford to keep the server running. </p></blockquote><span style="color:#333333;">In which case why is DELETE one of the HTTP verbs?</span></li></ol><span style="color:#333333;"><br />These problems could be addressed by using semantically relevant methods. Such methods are permissible within the </span><span style="color:#333333;"><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9" rel="self">1.1 spec</a></span><span style="color:#333333;">:<br /><br /></span><blockquote><p>The set of common methods for HTTP/1.1 is defined below. Although this set can be expanded, additional methods cannot be assumed to share the same semantics for separately extended clients and servers.</p></blockquote><span style="color:#333333;"><br /><br />Accompanied by the "405 Method Not Allowed" status code HTTP provides a very clean mechanism for semantically correct communication. The two problems outlined above could then be easily addressed:<br /><br /></span><ol class="arabic-numbers"><li><span style="color:#333333;">A QUERY method which makes use of the message body. This would over come the limitations of using GET and the semantic error of using POST (this ignores the failing of HTML forms which can only use the GET and POST methods. HTML 5 will allow PUT and DELETE but not arbitrary methods) </span></li><li><span style="color:#333333;">Using an EXPIRE or INVALIDATE method would be better than DELETE.</span></li></ol><span style="color:#333333;"><br /></span><h2>Conclusion</h2><span style="color:#333333;"><br />The first of these suggestions is certainly grander than the second and would require significant changes to client software to implement in full. The second of these suggestions would only require a guiding hand as there are no (theoretical) infrastructure changes required. The creation of a registry for extended HTTP request methods is all that would be required. The HTTP 1.1 spec is currently being revised and it seems that such a </span><span style="color:#333333;"><a href="http://www.w3.org/Protocols/HTTP/1.1/rfc2616bis/issues/#i72" rel="self">registry has been suggested</a></span><span style="color:#333333;">.</span>]]></content:encoded></item><item><title>10/GUI</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>Design</category><dc:date>2009-10-13T21:13:59+01:00</dc:date><link>http://benedictcohen.co.uk/files/e72fc657cbf88ed0ec254eb41c422289-8.php#unique-entry-id-8</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/e72fc657cbf88ed0ec254eb41c422289-8.php#unique-entry-id-8</guid><content:encoded><![CDATA[<span style="color:#333333;">I've just watched the video at </span><span style="color:#333333;"><a href="http://10gui.com/" rel="self">10gui.com</a></span><span style="color:#333333;">:<br /><br /><object width="400" height="220"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=6712657&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=6712657&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="220"></embed></object><p><a href="http://vimeo.com/6712657">10/GUI</a> from <a href="http://vimeo.com/user1415432">C. Miller</a> on <a href="http://vimeo.com">Vimeo</a>.</p><br /><br />I'm impressed. Most re-inventions of the desktop leave me with little more than a renewed contempt for technology. 3D desktops, for example, are a teribble idea. Superfically they look pretty, but they are inherintly flawed as they try to reduce 3 dimensions worth of information into 2 dimensions. I'm a huge fan of Jeff Raskins The Humane Interface, but I believe the zooming metaphor fails as it effiectively locks data into a single hierarchally structure and also requires information to be presented in a document orientated manner.<br /><br />10GUI strikes me as an attempt to keep the best bits of the current windowing metaphor (eg document or task based interface design) and the zooming metaphor (eg increasing the usefulness of spatial information).</span>]]></content:encoded></item><item><title>Slugs and Airports</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>Web development</category><category>geek</category><category>linux</category><category>Hardware</category><dc:date>2009-09-15T10:31:26+01:00</dc:date><link>http://benedictcohen.co.uk/files/801850ad75555548a6eb16f646fb7886-6.php#unique-entry-id-6</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/801850ad75555548a6eb16f646fb7886-6.php#unique-entry-id-6</guid><content:encoded><![CDATA[<span style="color:#333333;">I've setup an NSLU2 to serve video to my iPod Touch. Here's what I did.<br /><br /></span><h2>The problem </h2><span style="color:#333333;"><br /></span><span style="color:#333333;">I have a conflicted position with regard to technology. On one hand I think technology should just work. I have no time for cryptic interfaces and poorly written instruction manuals. This is why I like Apple. I have a Macbook, and Airport Extreme (with printer and hard drives attached) and an iPod Touch. These three devices constitute my home network and I'm pleased to say that it works perfectly. <br /><br />However, I'm also a geek. When I see the flash of a green LED I can't help but ask myself 'I wonder if...'. Over time my geekish tendencies to fiddle have been tempered by my desire to have elegant solutions, so much so that I know refuse to let a geekish endeavour compromise the integrity a working solution. It turns out that this restriction has, possibly unsurprisingly, caused my geekish side to raise its' game.<br /><br />A few years ago I bit the bullet and ripped all of my CDs. It took a while, but it was a worthwhile investment. Ever since then I've had my sights set on my DVD collection. Ripping all my DVDs is a harder problem to crack. The sticking point was not the ripping, it was the watching. I have no problem having my music only being accessible from my laptop (or my transferring to my iPod), but that won't do for movies - I don't want to mess with my laptop just to watch a movie. I want a solution that just works; <br /><br />I want to be able to watch a movies by expending less effort than if I were to put a disc in a dvd player. So how do I do it? First of all lets take a look at the elements that constitute the current solution. Firstly there are the shelves full of DVD discs, secondly there's the DVD player to play them on.<br /><br />Replacing the DVD player is relatively straight forward. I have a TV-out cable for my iPod Touch which I'm very pleased with. This is the simplest replacement for the DVD player. <br /><br />Replacing the shelves of DVDs is less straight forward. The first problem is deciding where to store the video. They could be stored on the laptop, but there are problems with this. The laptop only has a 500GB hard drive video files take up a lot of space. Even if the hard drive had nothing except movies on it, it wouldn't take too long before the hard drive was full. Also, if the movies were stored on the laptop then the laptop would have to be turned for the movies to be accessible. My anal-retentive non-geeky side deems this unacceptable as it would require turning the laptop on whenever I wanted to watch a movie. The alternative to storing them on the laptop is to store them on a network drive. With this in mind I bought a 2TB WD RAID drive and attached it to the Airport Extreme. I set up the drive to act in mirror mode to provide a backup if one of the drive fails (it's not possible to backup network drives with Time Machine).<br /><br />The second problem is how to get the movies from the Airport to the iPod. The movies can be transferred via iTunes or they can be access wirelessly via HTTP or a different protocol, such as uPnP ("there's an app for that"). Obviously transferring movies via iTunes is not an option for the same reasons that storing the movies on the laptop are not an option. That leaves the wireless network option &mdash; which raises the question of a server. <br /><br />The Airport Extreme has only 2 network protocols AFP and SAMBA, neither of which can be accessed via the iPod touch. Game over? No. The solution is to add another network device which can access the Airport Extremes network drives and then make that data available via a protocol that the iPod Touch can work with. The obvious device is another computer. Another computer could easily be setup to act as a server. But there in lies the problem, another computer could easily do a lot more than sever video. Another computer is massive overkill. The wasted energy and computing power of having a computer set up just to act as a web server for one or two clients makes me shudder.<br /><br />So what else could do the job? The Linksys NSLU2, affectionately known as a slug. The NSLU2 has one LAN port and 2 USB ports. The idea is that you attach USB hard drive to the NSLU2, hook it up to your network and the hard drive become accessible via the network. At least that's how Linksys expected the device to be used, some geeks had different ideas. </span><span style="color:#333333;"><a href="http://www.nslu2-linux.org/" rel="self">NSLU2-Linux</a></span><span style="color:#333333;"> is the home of the alternate firmware for NSLU2. By installing alternative firmware the NSLU2 becomes capable of much more. There are a few different firmwares to choice from. After a bit of playing with them I decided to go for the Debian Lenny. This provides a full Linux system with a huge selection of software to install.<br /><br /></span><h2>The solution - How to set up an NSLU2 to server movies</h2><span style="color:#333333;"><br /></span><h3>1. Install Debian (Lenny)</h3><span style="color:#333333;"><br /></span><a href="http://www.cyrius.com/" rel="self">Martin Michlmayr</a><span style="color:#333333;"> has </span><span style="color:#333333;"><a href="http://www.cyrius.com/debian/nslu2/install.html" rel="self">detailed instruction for installing Debian on the NSLU2</a></span><span style="color:#333333;">. I used the unofficial image from </span><span style="color:#333333;"><a href="http://www.slug-firmware.net/" rel="self">Slug-Firmware.net</a></span><span style="color:#333333;"> and upslug2 for flashing the NSLU2. There isn't a pre-compiled version of upslug2 for OS X. I used a Ubuntu 9.04 virtual machine. There is an upslug2 package in the pre-configure Ubuntu repository. To install it type the following use the following command:<br /></span><span style="color:#333333;"><br /><code>apt-get install upslug2</code><br /></span><span style="color:#333333;"><br /></span><h4>Macfusion</h4><span style="color:#333333;"><br />Once Lenny is installed you will need access to edit files. This can be done via SSH and edited in the terminal with vi or nano, but Macfusion offers an alternative. </span><span style="color:#333333;"><a href="http://www.macfusionapp.org/" rel="self">Macfusion</a></span><span style="color:#333333;"> makes it possible for arbitrary resources to mounted as part of the local file system, (Macfusion is based on </span><span style="color:#333333;"><a href="http://en.wikipedia.org/wiki/FUSE_(Linux)" rel="self">FUSE</a></span><span style="color:#333333;">). FTPFS is such a resource.  FTPFS clients can connect to an out of the box Lenny installation. If you install Macfusion you will be able to browse the NSLU2 filesystem with Finder and edit files with the app of your choice.<br /><br /></span><h3>2. Install SAMBA</h3><span style="color:#333333;"><br />Once Lenny has installed, login to the NSLU2 via SSH, and install the SAMBA package (we only need the client package):<br /><code>NSLU1:/# apt-get install smbfs</code><br /><br />Create a directory to mount to:<br /><code>NSLU1:/#  mkdir /media/Movies</code><br /><br />Mount the shared drive:<br /><code>NSLU1:/# mount -t smbfs //AIRPORT-IP-ADDRESS/AIRPORT-VOLUME-NAME /media/Movies -o password=AIRPORT-PASSWORD</code><br /><br />Check that it worked:<br /><code>NSLU1:/# ls /media/Movies</code><br /><br />The contents of the root directory of you shared drive should be listed.<br /><br /></span><h3>3. Mount SAMBA drive on boot</h3><span style="color:#333333;"><br /><code>fstab</code> is used to determine where to mount devices. By adding an entry for the shared drive the NSLU2 will mount the drive at boot. Open <code>/etc/fstab</code> and add the following line:<br /><br /><code>//AIRPORT-IP-ADDRESS/AIRPORT-VOLUME-NAME /media/Movies smbfs password=AIRPORT-PASSWORD 0 0</code><br /><br />Make sure there is a blank line at the end of fstab.<br /><br />Check that the amendment has worked by rebooting:<br /><br /><code>NSLU1:/# reboot</code><br /><br />After the reboot the contents of the network drive should be available in <code>/media/Movies</code>.<br /><br /></span><h3>4. Install a web server (Nginx)</h3><span style="color:#333333;"><br />Nginx is a very capable alternative to resource-hungry Apache. Nginx is resource-light thus making it well suited to the NSLU2.<br /><br />Install nginx:<br /><br /><code>NSLU1:/# apt-get install nginx</code><br /><br />Check that nginx has installed by entering accessing your NSLU2 via a browser.<br /><br /><br /></span><h3>5. Configure Nginx</h3><span style="color:#333333;"><br />Organise the web server directory to make it easier to add extra features later:<br /><code>NSLU1:/# mkdir /var/www/public_html</code><br /><br />Create a symlink to the mount point of the shared network drive:<br /><code>NSLU1:/# ln -s /media/Movies /var/www/public_html/Movies</code><br /><br />Next, add the mime types for mpeg 4 movies to the Nginx mime type config file. The file is found at <code>/etc/nginx/mime.types</code> , open it and add the following lines above the closing curly bracket.<br /><br /><code>video/x-m4v                           m4v;<br />video/mp4                             mp4; </code><br /><br />The last step is to configure the Nginx site so that it serves the files from the correct directory and is capable of sending large files. Open the default site config file located at <code>/etc/nginx/sites-enabled/default</code> (this file is actually a symlink to a file in sites-available).<br />Change the value of <code>root</code> from <code>/var/www;</code> to <code>/var/www/public_html;</code>. Add the following line into the server section: <code>sendfile off;</code>.<br /><br />Finally, restart nginx:<br /><code>NSLU1:/# /etc/init.d/nginx restart</code><br /><br />Access your slug via the browser and you will be able to files shared by the Airport. Movies will be accessible from an iPod Touch or iPhone. If everything went as planned the NSLU2 will mount the network drive and start Nginx when it is turned on.<br /><br /></span><h2>Optional extras</h2><span style="color:#333333;"><br /></span><h3>Install a scripting language (eg PHP)</h3><span style="color:#333333;"><br />Installing a server-side scripting language gives you greater control over the pages you server. Scripting languages have to run as a fastCGI server for them to be accessible from nginx. I </span><span style="color:#333333;"><a href="http://www.howtoforge.com/installing-nginx-with-php5-and-mysql-support-on-debian-lenny" rel="self">installed PHP</a></span><span style="color:#333333;">. Here's some screen shots of the site my NSLU2 servers up:<br /><br /></span><img class="imageStyle" alt="screenshot1" src="http://benedictcohen.co.uk/files/screenshot1.png" width="386" height="742"/><img class="imageStyle" alt="screenshot2" src="http://benedictcohen.co.uk/files/screenshot2.png" width="386" height="742"/><span style="color:#333333;"><br /></span><span style="color:#333333;"><br />I did this by setting the autoindex to a script that is located in the root of public_html.  The source code is a bit messy so I won't release it just yet. However, if you'd like the messy version just send me an email.<br /><br /></span><h3>FireFly</h3><span style="color:#333333;"><br />FireFly is an DAAP server. DAAP is the protocol used by iTunes and AppleTV to access remote media. Unfortunately the version of FireFly in the Lenny repository doesn't serve video correctly. There are other DAAP servers, but I haven't investigated them.<br /><br /></span><h3>Access your NSLU2 from anywhere</h3><span style="color:#333333;"><br />Setting up a dynamic DNS would allow you to access your NSLU2 from anywhere on the internet.</span>]]></content:encoded></item><item><title>&#x26;lt;select multiple&#x26;gt; sucks</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>Web development</category><category>Design</category><dc:date>2009-06-13T14:00:00+01:00</dc:date><link>http://benedictcohen.co.uk/files/63a9c518f5854f60199e91ac6be5db46-5.php#unique-entry-id-5</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/63a9c518f5854f60199e91ac6be5db46-5.php#unique-entry-id-5</guid><content:encoded><![CDATA[<span style="color:#333333;">The select element is used to create list of options. In &lsquo;normal&rsquo; mode it presents a popup box. In &lsquo;multiple&rsquo; mode it presents a list which requires the user to hold a key to select additional items. The native list control in Windows and OS X works exactly the same.<br />I really don&rsquo;t like this control. There are no visual clues that the user can select multiple items, which means that most users don&rsquo;t know that multiple selections are possible. To address this problem websites often add a label to explain how multiple selections is made:<br /></span><img class="imageStyle" alt="selection" src="http://benedictcohen.co.uk/files/selection.jpg" width="480" height="72"/><span style="color:#333333;"><br /></span><span style="color:#333333;">When notes and labels are added to things it&rsquo;s a huge clue that the thing in question suffers from poor design. Also, the label in the screenshot is inaccurate. It is true in Windows, but not in OS X (and possibly not in true in GTK, QT etc).<br />The control requires the user to user press a key so that they can make multiple multiple selections - this means that the control is quasi-modal. Modes confuse the user and should be avoid. For such a simple task these failings are inexcusable.<br /><br />Here&rsquo;s a better approach:<br /></span><span style="font:16px Times-Roman; "><div style="overflow-y:scroll;height:6em;width:20em;border:1px solid black;"> <input type="checkbox">Jimmy</input><br /> <input type="checkbox">Jimi</input><br /> <input type="checkbox">Frank</input><br /> <input type="checkbox">Dweezil</input><br /> <input type="checkbox">Jeff</input><br /> <input type="checkbox">Keef</input><br /> <input type="checkbox">John</input><br /> </div></span><span style="font:10px Monaco; "><br /><br /><br />&lt;div style=&quot;overflow-y:scroll;height:6em;width:20em;border:1px solid black;&quot;&gt;<br />&lt;input type=&quot;checkbox&quot;&gt;Jimmy&lt;/input&gt;&lt;br /&gt;<br />&lt;input type=&quot;checkbox&quot;&gt;Jimi&lt;/input&gt;&lt;br /&gt;<br />&lt;input type=&quot;checkbox&quot;&gt;Frank&lt;/input&gt;&lt;br /&gt;<br />&lt;input type=&quot;checkbox&quot;&gt;Dweezil&lt;/input&gt;&lt;br /&gt;<br />&lt;input type=&quot;checkbox&quot;&gt;Jeff&lt;/input&gt;&lt;br /&gt;<br />&lt;input type=&quot;checkbox&quot;&gt;Keef&lt;/input&gt;&lt;br /&gt;<br />&lt;input type=&quot;checkbox&quot;&gt;John&lt;/input&gt;&lt;br /&gt;<br />&lt;/div&gt;<br /><br /><br /></span><span style="color:#333333;">The above creates a scrolling checkbox list by setting the size and overflow style attributes of the parent block element (in this case a &lt;div&gt;, but it could be applied to the &lt;form&gt; directly). Checkboxes lists are common in OS&rsquo;s so the user will understand how to use the control.<br /></span>]]></content:encoded></item><item><title>The correct way to display time</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>Design</category><dc:date>2009-02-28T08:36:00+00:00</dc:date><link>http://benedictcohen.co.uk/files/8ace6b0a72ecf1ee6b17d9f1585466cc-4.php#unique-entry-id-4</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/8ace6b0a72ecf1ee6b17d9f1585466cc-4.php#unique-entry-id-4</guid><content:encoded><![CDATA[<span style="color:#333333;">I&rsquo;ve just upgraded the hard drive of my MacBook. To do this I used the excellent </span><span style="color:#3465F2;"><a href="http://www.prosofteng.com/products/drive_genius.php">Drive Genius 2</a></span><span style="color:#333333;"> which was included in the MacUpdate Holiday Bundle. Drive Genius 2 is a great piece of software. It&rsquo;s really easy to use compared to GParted and all the other fiddle Linux tools. The interface to Drive Genius contains lots of (superfluous) animation but on the whole is very clear. However, when I was duplicating the drive I noticed something that got my goat:<br /></span><img class="imageStyle" alt="drivegenius-300x30" src="http://benedictcohen.co.uk/files/drivegenius-300x30.jpg" width="300" height="30"/><span style="color:#333333;"><br /></span><span style="color:#333333;">Why is time state as a decimal? This is confusing. For example, does &lsquo;4.33 hours&rsquo; mean 4 hour 33 minutes or 4 hour 20 minutes?&nbsp;<br />Time should be displayed in its natural units; hours minutes and seconds. The work involved in converting &lsquo;1.5 hours&rsquo; into &lsquo;1 &nbsp;hour 30 minutes&rsquo; is trivial and the result is a better user experience.<br />&nbsp;<br />Bonus rant: I much prefer analogue clocks that have a second hand which moves at a constant rate rather than one that ticks. I prefer them for two reasons. Firstly time is continuous, the &nbsp;discreet unit of a second is for our convenience, therefore continuous movement better represents this. Secondly, I hate the constant &lsquo;tick. tick. tick.&rsquo; it drives me crazy!</span>]]></content:encoded></item><item><title>NSCollectionView Tips</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>Cocoa</category><dc:date>2008-11-04T11:55:00+00:00</dc:date><link>http://benedictcohen.co.uk/files/5b81e3c40cee2daf88ceffe6eb556a63-3.php#unique-entry-id-3</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/5b81e3c40cee2daf88ceffe6eb556a63-3.php#unique-entry-id-3</guid><content:encoded><![CDATA[<span style="color:#333333;">Recently I&rsquo;ve been teaching myself Cocoa. I&rsquo;ve been following the excellent </span><span style="color:#3465F2;"><a href="http://www.amazon.co.uk/exec/obidos/ASIN/0321503619/bignerdranch-20">Cocoa Programming For Mac OS X</a></span><span style="color:#333333;"> by Aaron Hillegass. Quality reference material like this book and Apple&rsquo;s documentation makes learning much easier. Apple&rsquo;s material is consitent, consisce and in the most part complete. However, there is one class where Apple&rsquo;s reference is quite poor; </span><span style="color:#3465F2;"><a href="http://developer.apple.com/documentation/Cocoa/Reference/NSCollectionView_Class/Introduction/Introduction.html">NSCollectionView</a></span><span style="color:#333333;">.<br />NSCollectionView is similar to NSTableView; they both display data with the help of a prototype which is copied for each piece of data to be displayed. NSTableView uses the NSCell for the prototype. The NSCell draws its self directly onto the NSTableView. NSCollectionView uses NSCollectionViewItem for the prototype. NSCollectionViewItem is a simple controller (it inherits directly from NSObject), it has no visual element. NSCollectionViewItem has two properties, representedObject and view. representedObject holds the object that the view will display and is set by the NSCollectionView. &nbsp;It is the responsibility of the NSCollectionViewItem to provide the view object.&nbsp;<br />When an NSCollectionView is created in Interface Builder two additional objects are created:<br /></span><ul class="disc"><li><span style="color:#333333;">An NSCollectionViewItem which is connected to the prototype outlet of the NSCollectionView</span></li><li><span style="color:#333333;">An NSView which is connected to the view outlet of the NSCollectionViewItem</span></li></ul><span style="color:#333333;">The suggested method for constructing the view is to bind the controls to the representedObject of the NSCollectionViewItem.&nbsp;The bindings are copied for each new instance of NSView. Because of these bindings the view and the model are connected with no controller code. Great!<br />Well, it&rsquo;s great for a short while. Problems arises when you want more than simple bindings between the view and the representedObject. There are two parts to this problem:<br /></span><ul class="(null)"><li><span style="color:#333333;">where do we put our controller code?</span></li><li><span style="color:#333333;">how do we access the IBOutlets specified in our controller code?</span></li></ul><span style="color:#333333;">The NSCollectionViewItem is the controller that mediates between the item data and the item view thus making it the correct place to put this code. This is achived by subclassing NSCollectionViewItem. Once NSCollectionViewItem has been subclassed we need to tell Interface Builder to use the subclass, this is done by changing the Class Identity in Interface Builder from NSCollectionViewItem to&nbsp;the NSCollectionViewItem subclass.<br />The next problem is that unlike the bindings the in the NSView, the IBOutlet&rsquo;s specifed in our NSCollectionViewItem subclass are not connected when the prototype is copied. So&nbsp;how do we connect the IBOutlet&rsquo;s&nbsp;specified&nbsp;in our NSCollectionViewItem subclass to the controls in the view? &nbsp;This problem is trivial once you&nbsp;realise&nbsp;that Interface Builder is not being very clever.<br />Interface Builder puts the custom NSView in the same nib as the NSCollectionView and NSCollectionViewItem. This is dumb. The solution is to move the NSView to its own nib and get the controller to load the view programmatically:<br /></span><ul class="(null)"><li><span style="color:#333333;">Move the NSView into its own nib (thus breaking the connection between the NSCollectionViewItem and NSView).&nbsp;</span></li><li><span style="color:#333333;">In I.B., change the Class Identity of File Owner to the NSCollectionViewItem subclass.</span></li><li><span style="color:#333333;">Connect the controls to the File Owner outlets.</span></li><li><span style="color:#333333;">Finally get the NSCollectionViewItem subclass to load the nib:</span></li></ul><span style="font:12px Courier, mono; color:#333333;">//NSCollectionViewItem Subclass
-(id)copyWithZone:(NSZone *)zone
{
&nbsp;id result = [super copyWithZone:zone];</span><span style="color:#333333;"><br /></span><span style="font:12px Courier, mono; color:#333333;">[NSBundle LoadFromNib:@"viewItem" owner: result];</span><span style="color:#333333;"><br /></span><span style="font:12px Courier, mono; color:#333333;">//we can configure other aspects of result too
&nbsp;[result setPopupMenuDelegate: [self popupMenuDelegate];</span><span style="color:#333333;"><br /></span><span style="font:12px Courier, mono; color:#333333;">return result;
}
/*This might not be the best place for LoadFromNib:. If it was place in setRepresentObject: we could load different views depending on the class of the representedObject.*/</span><span style="color:#333333;"><br />
Problem solved. We now have much more control of NSCollectionView. (Remember you can still bind to representObject).</span>]]></content:encoded></item><item><title>Ramblings on Keyboard Shortcuts</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>Design</category><dc:date>2008-07-27T11:11:00+01:00</dc:date><link>http://benedictcohen.co.uk/files/e808827e4edd39f3b7f27ccde1b288bd-2.php#unique-entry-id-2</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/e808827e4edd39f3b7f27ccde1b288bd-2.php#unique-entry-id-2</guid><content:encoded><![CDATA[<span style="color:#333333;">On the surface keyboard shortcuts seems like a rather small topic: ctrl + s to saves and alt + f4 to closes, what else is there to know? But as with most things there&rsquo;s always more than what meets the eye.<br />First of all lets state what a keyboard shortcut is and what it does:<br />A </span><span style="color:#333333;font-weight:bold; ">keyboard shortcut</span><span style="color:#333333;"> (or </span><span style="color:#333333;font-weight:bold; ">accelerator key</span><span style="color:#333333;">, </span><span style="color:#333333;font-weight:bold; ">shortcut key</span><span style="color:#333333;">, </span><span style="color:#333333;font-weight:bold; ">hot key</span><span style="color:#333333;">, </span><span style="color:#333333;font-weight:bold; ">key binding</span><span style="color:#333333;">, </span><span style="color:#333333;font-weight:bold; ">keybinding</span><span style="color:#333333;">, </span><span style="color:#333333;font-weight:bold; ">key combo</span><span style="color:#333333;">, etc.) is a </span><span style="color:#3465F2;"><a href="http://en.wikipedia.org/wiki/Computer_keyboard">key</a></span><span style="color:#333333;"> or </span><span style="color:#3465F2;"><a href="http://en.wikipedia.org/wiki/Set">set</a></span><span style="color:#333333;"> of keys that performs a predefined function. These functions can often be done via some other, more indirect mechanism, such as using a </span><span style="color:#3465F2;"><a href="http://en.wikipedia.org/wiki/Menu_%28computing%29">menu</a></span><span style="color:#333333;">, typing a longer </span><span style="color:#3465F2;"><a href="http://en.wikipedia.org/wiki/Command_line_interface">command</a></span><span style="color:#333333;">, and/or using a </span><span style="color:#3465F2;"><a href="http://en.wikipedia.org/wiki/Pointing_device">pointing device</a></span><span style="color:#333333;">. By reducing such sequences to a few keystrokes, this can often save the user time, hence &ldquo;shortcut&rdquo;.<br /></span><span style="color:#3465F2;"><a href="http://en.wikipedia.org/wiki/Keyboard_shortcut">Wikipedia - Keyboard shortcut</a></span><span style="color:#333333;"><br />&nbsp;<br />For a system to be sucessful it needs to be&nbsp;sympathetic&nbsp;to its user. We therefore need to look at limitations of the user and how to accomodate them.<br />&nbsp;<br /></span><span style="font-size:14px; color:#333333;font-weight:bold; ">Physiology (ergonomics)<br /></span><span style="color:#333333;">Anyone that paid attention in biology class will have heard the term&nbsp; </span><span style="color:#3465F2;"><em><a href="http://en.wikipedia.org/wiki/Thumb#Importance_of_the_opposable_thumb">opposable&nbsp;thumbs</a></em></span><span style="color:#333333;">. The &ldquo;thumbs&rdquo; of other animals evolved into wings, hooves or flippers, but ours have shift around a bit to be </span><span style="color:#333333;"><em>opposite</em></span><span style="color:#333333;"> our fingers. This change in position allows us to&nbsp; grab things, it has also resulted in our thumbs becoming the strongest and one of the more dextrous fingers. Our fingers decease in strength as they move away from the thumb. It therefore follows that any good design should utilise this fact by making good use of our superior digits; the&nbsp; thumb, index and middle (ring) fingers.<br /></span><span style="font-size:14px; color:#333333;font-weight:bold; ">The brain (cognetics)<br /></span><span style="color:#333333;">Designing an object so it is sympathetic to our bodies is only half of the story. A well designed &lsquo;thing&rsquo; must be sympathetic to the constraints of our minds too.<br /></span><span style="color:#333333;font-weight:bold; ">Modes</span><span style="color:#333333;"> are a major design consideration for good shortcuts.&nbsp;<br />In </span><span style="color:#3465F2;"><a href="http://en.wikipedia.org/wiki/User_interface">user interface</a></span><span style="color:#333333;"> design, a </span><span style="color:#333333;font-weight:bold; ">mode</span><span style="color:#333333;"> is a distinct setting within a computer program or any physical machine interface, in which the same user input will produce perceived different results than it would in other settings.&nbsp;<br /></span><span style="color:#3465F2;"><a href="http://en.wikipedia.org/wiki/Mode_%28computer_interface%29">Wikipedia - Mode (computer interface)</a></span><span style="color:#333333;"><br />&nbsp;<br />Some examples:<br /></span><ul class="disc"><li><span style="color:#333333;">The caps lock key is modal (ie it creates a mode). When the &lsquo;k&rsquo; key is press a &lsquo;k&rsquo; is displayed, but when caps lock is engaged pressing &lsquo;k&rsquo; will display &lsquo;K&rsquo;.</span></li><li><span style="color:#333333;">In TextEdit pressing cmd + t displays the font pallette, but in Safari pressing cmd + t opens a new tab. The same key presses have different results. (Conflicts such a this are common due to the current computing paradigm of independent applications which is inherently modal).</span></li></ul><span style="color:#333333;">Modes confuse the user and should be avoided. There is an alternative to modes, quasi-modes. Quasi-modes are like modes but with one important difference. Quasi-modes require a constant action to occur for the quasi-mode to become active. The standard shift key is quasi-modal; if the key is not held down it has no effect. Quasi-modes rely on the fact that the process of performing the action require to be in the quasi-modes (eg the holding of the shift key) causes the user to be aware of the fact that they are in a different mode. Quasi-modes reduce the confusion of modes.<br />&nbsp;The second consideration is </span><span style="color:#333333;font-weight:bold; ">human memory</span><span style="color:#333333;">. Our short term memory is quiet limited. We can store around 7 items of data in our short term memory. This has an impact on the way we use shortcuts. When a user is performing a task they will concentrating on their data than the tools for manipulating the data.<br />There are a few ways to reduce the burden of remember how to use a system. The first is to remove the burden of remembering - this is done by clear labelling. The second is by creating meaning relationships between the desired result and required action. Meaningful relationships allow users to understand the system as a whole rather than having to learn a collection of&nbsp;unrelated&nbsp;and arbitrary actions.<br /></span><span style="font-size:14px; color:#333333;font-weight:bold; ">Current systems shortcuts<br /></span><span style="color:#333333;">Lets see how Windows XP and OS X Leopard far with the above&nbsp;criteria.<br /></span><span style="color:#333333;font-weight:bold; ">Ergonomics:<br /></span><span style="color:#333333;">The physical design of Mac and standard PC keyboards are almost identical. The most&nbsp;noticeable&nbsp;differences are the modifier keys. A standard PC keyboard has ctrl, alt and windows keys, a Mac keyboard has ctrl, alt and cmd keys.<br /></span><img class="imageStyle" alt="keyboard20080429-300x237" src="http://benedictcohen.co.uk/files/keyboard20080429-300x237.jpg" width="300" height="237"/><span style="color:#333333;">
Left side of a mac keyboard
&nbsp;<br /></span><img class="imageStyle" alt="winkbedit" src="http://benedictcohen.co.uk/files/winkbedit.jpg" width="167" height="197"/><span style="color:#333333;">
Left side of a Windows keyboard
&nbsp;<br /></span><span style="color:#333333;">In Windows the most common modifier key used with shortcuts is the ctrl key. The crtl keys are located on the bottom row at the far left and far right of a standard keyboard.<br />It is the little finger (pinkie finger) that people most often use to press the ctrl key.</span><span style="color:#333333;"><em>&nbsp;</em></span><span style="color:#333333;">The little finger is a feeble thing and tires quickly. Also the degree of stretch required to move the hands from the standard typing position is quite pronounced which makes it prone to a RSI (see&nbsp;</span><span style="color:#3465F2;"><a href="http://xahlee.org/emacs/emacs_pinky.html">How To Avoid The Emacs Pinky Problem</a></span><span style="color:#333333;">).<br />OS X fairs better. The modifier key used is always the cmd key&nbsp; which are located directly to left and right of the space bar (additional modifier keys may also be used).&nbsp;The positioning allows the modifier keys to be pressed with the thumb - ideal.<br /></span><span style="color:#333333;font-weight:bold; ">Modal design:</span><span style="color:#333333;"><br />Windows has many mode based issues. To issue a in shortcut we have to press either ctrl, alt or the &lsquo;Windows key&rsquo; which is often followed by pressing another key. The ctrl key is the most common modifer key to be used in a shortcuts, fortunately the ctrl key does not suffer from modal issues.&nbsp;Unfortunately&nbsp;the same is not true of the alt or Windows keys, both of which are modal. Worse still the behaviour of the alt and Windows keys are inconsistent.<br />The alt key is generally used to move focus to the menu bar and for window management (eg, alt + f4 to close, alt + tab to switch to another window), but occasionally the alt key is used in &lsquo;normal&rsquo; shortcuts. The key press cycle of alt key in a normal application (eg Notepad, Windows Explorer, Internet Explorer) is as follows:<br /></span><ul class="(null)"><li><span style="color:#333333;">The alt key is pressed in. This moves the focus to the menu bar, illustrated by an the underlining of letters required to access the menus.</span></li><li><span style="color:#333333;">At this point there are 4 possible sequence of events:</span></li></ul><ul class="(null)"><li><ul class="(null)"><li><span style="color:#333333;">Alt key is released resulting in the focus moving to the first menu (normal the File menu).</span></li></ul></li><li><ul class="(null)"><li><span style="color:#333333;">A key that is underlined is press which results in the associated menu being displayed and the focus moving to the first item of that menu.</span></li></ul></li><li><ul class="(null)"><li><span style="color:#333333;">Another valid key is pressed (eg, F4 or alt)</span></li></ul></li><li><ul class="(null)"><li><span style="color:#333333;">A key that is not underlined is press resulting in the focus remaining in its current loci (eg the text area in Notepad).</span></li></ul></li></ul><span style="color:#333333;">The biggest culprit of modal operation in these possibilities is the first - releasing of the alt key without a second key press. This puts the system into an unnecessary and potentially confusing mode. The&nbsp;simplest&nbsp;way to remedy this is to not move the focus until a second key is pressed - i.e. make it quasi-modal.<br />The key press cycle of the Windows key is as follows:<br /></span><ul class="(null)"><li><span style="color:#333333;">Windows Key is pressed in (there is no on screen indication that this has occurred).</span></li><li><span style="color:#333333;">At this point there are 3 possible sequence of events.Note that events b and c can occur numerous times without releasing the Windows key:</span></li></ul><ul class="(null)"><li><ul class="(null)"><li><span style="color:#333333;">The key is released resulting in the Start menu being displayed and the&nbsp; focus moving to it.</span></li></ul></li><li><ul class="(null)"><li><span style="color:#333333;">A valid key is pressed resulting in the related action being executed (the only way to discover valid keys is to read the documentation). When the Windows key is finally released the Start menu is not displayed.</span></li></ul></li><li><ul class="(null)"><li><span style="color:#333333;">A non valid key is pressed. The key press is ignored by the Windows key and is handled by the application with focus. When the Windows key is finally released the Start menu is not displayed.&nbsp;</span></li></ul></li></ul><span style="color:#333333;">The behaviour of the Windows key is confusing. When it is pressed with no subsequent key presses it behaves modally, but when key presses do follow it behaves quasi-modally (depending on the command). The Windows key strikes me as a wasted opportunity. For such a prominent key it provides very little functionality, and the functionality it does provide is almost impossible to discover.<br /></span><span style="color:#333333;font-weight:bold; ">Labelling:<br /></span><span style="color:#333333;">The on screen labelling of shortcuts in OS X and Windows are largely similar. Both try to use mnemonic to imply a system. For example cmd +</span><span style="color:#333333;font-weight:bold; ">s</span><span style="color:#333333;"> is </span><span style="color:#333333;font-weight:bold; ">s</span><span style="color:#333333;">aves, cmd + </span><span style="color:#333333;font-weight:bold; ">l</span><span style="color:#333333;"> is </span><span style="color:#333333;font-weight:bold; ">l</span><span style="color:#333333;">oads and cmd + </span><span style="color:#333333;font-weight:bold; ">p</span><span style="color:#333333;"> is </span><span style="color:#333333;font-weight:bold; ">p</span><span style="color:#333333;">rint. There are limitations to this approach.<br />Firstly conflicts soon arise, for example should cmd + s be save or search? Windows applications tend to address this problem by using a different letter, thus breaking the mnemonic system. OS X sometimes uses a different letter but also uses additional&nbsp;modifier&nbsp;keys, but which additional&nbsp;modifier&nbsp;key is unpredictable. Both of these approaches are some what arbitary as they are not part of a system which the user can learn and therefore predict the shortcut. (OS X has a convention of using the shift key to perform related actions. For example cmd + s is save cmd + shift + s is save as, cmd + z is undo cmd + shift + z is redo.)<br />The second problem is&nbsp;internationalisation. The mnemonic system is fine when the system is in english but becomes arbitary when the same shortcuts are used in&nbsp;conjunction&nbsp;with other languages.<br />In addition to the onscreen labeling it is also worth noting the keyboard labelling. In OS X the labelling of&nbsp;these keys are largely consistent with their behaviour; the cmd key is used when issuing commands, the alt/options key will often give an alternative option, and the ctrl key will show controls. In Windows this is not the case, modifier keys are assigned without regard to their label.<br /></span><span style="color:#333333;font-weight:bold; ">Sidenote: interaction with the mouse</span><span style="color:#333333;"><br />It is not sensible to consider the keyboard without mentioning the mouse. Most people are right handed (70% to 90% according to &nbsp;</span><span style="color:#3465F2;"><a href="http://en.wikipedia.org/wiki/Right-handed">Wikipedia</a></span><span style="color:#333333;">) and therefore operate the mouse with their right hand. While mousing the&nbsp;available&nbsp;keys are limited to those which are accessible by the non-dominate hand (ie the left hand in most cases). I am left handed. For example, when I use Safari to browser the web I use a combination of the cursor and keyboard to navigate. I use my right hand to switch between tabs while my left hand moves the cursor to links and other things that catch my eye. The shortcuts I use to switch between tabs are cmd + alt + left and cmd + alt + right. This approach would not work for a right handed person.<br /></span><span style="font-size:14px; color:#333333;font-weight:bold; ">Improvements & alternate implementation<br /></span><span style="color:#333333;">What can be done to improve keyboard shortcuts? The most effective fixes need to take place at the operating system level, which is unfortunate as it means little can be done by individual developers. It is possible for an application to alter the standard operation but this leads to </span><span style="color:#3465F2;"><a href="http://www.useit.com/alertbox/ok-cancel.html">inconsistencies between applications which cause more problems that it solves</a></span><span style="color:#333333;">.<br />My suggestions are simply to implement what I have discussed above.<br /></span><span style="color:#333333;font-weight:bold; ">Shortcuts should use thumb based modifier keys<br /></span><span style="color:#333333;">Jef Raskin points out in The Humane Interface that the current keyboard design makes poor use of our thumbs. Raskin was involved with the </span><span style="color:#3465F2;"><a href="http://en.wikipedia.org/wiki/Canon_Cat">Canon Cat</a></span><span style="color:#333333;"> which had two &lsquo;leap&rsquo; keys&nbsp;beneath&nbsp;the space bar. The &lsquo;leap&rsquo; keys allowed the user to &lsquo;leap&rsquo; forward and backwards in a document. While I question the usefulness of leap keys in relation to modern GUIs it is certainly true that our thumbs are still &lsquo;twiddling&rsquo; and should be put to better use.<br /></span><span style="color:#333333;font-weight:bold; ">Limited use of modes - shortcuts should utilize quasi-modes<br /></span><span style="color:#333333;">Modes are an inherent feature of the desktop/windowing metaphor. However we can certainly reduce their negative impact by carefully considered design. Keep to the any standard shortcuts that are in use by the operating system. (The alternative is to purse other computing metaphors such as ZUIs (as outlined in the Humane Interface), or </span><span style="color:#3465F2;"><a href="http://cs-www.cs.yale.edu/homes/freeman/lifestreams.html">life streams</a></span><span style="color:#333333;">).<br /></span><span style="color:#333333;font-weight:bold; ">Clear labelling<br /></span><span style="color:#333333;">Clearer labelling is harder to achieve, however there are a few systems for doing this. Digidesign produce </span><span style="color:#3465F2;"><a href="http://digidesign.com/index.cfm?navid=224&langid=51&itemid=27965&action=news_details">custom keyboards for their Pro Tools system</a></span><span style="color:#333333;">. Having used one of these keyboard I can testify to their usefulness. The problem with having the details printed on the key is that they are only applicable to one application.<br />A more generic solution to keyboard&nbsp;labelling&nbsp;is the </span><span style="color:#3465F2;"><a href="http://www.artlebedev.com/everything/optimus/">Optimus Maximus</a></span><span style="color:#333333;"> keyboard. Each key of the Optimus Maximus has an embeded OLED screen. These screens are used to show different glyphs in different circumstance. For example when using Photoshop the keyboard displays the icons of the on screen tools. Unfortunately the Optimus Maximus is considerable more expensive than a standard keyboard (it also has received </span><span style="color:#3465F2;"><a href="http://www.engadget.com/2008/02/22/optimus-maximus-at-long-last-we-bring-one-home-to-test/">critisim for its typing experiance</a></span><span style="color:#333333;">). However the Optimus Maximus is the first of its kind - I expect more affordable and more tightly&nbsp;integrated&nbsp;solutions will soon emerge.<br /></span><span style="font-size:14px; color:#333333;font-weight:bold; ">Further Reading<br /></span><ul class="disc"><li><span style="color:#3465F2;"><a href="http://www.amazon.com/Design-Everyday-Things-Donald-Norman/dp/0465067107/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217150663&sr=8-1">Donald Norman - Design of Everyday Things</a></span><span style="color:#333333;"> (I highly recommend this book).</span></li><li><span style="color:#3465F2;"><a href="http://www.amazon.com/Humane-Interface-Directions-Designing-Interactive/dp/0201379376/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1217152578&sr=1-1">Jef Raskin - The Humane Interface</a></span><span style="color:#333333;">.</span></li></ul>]]></content:encoded></item><item><title>REST + XMLHTTPRequest + 401 &#x21;= joy</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>Web development</category><dc:date>2008-05-27T15:38:00+01:00</dc:date><link>http://benedictcohen.co.uk/files/f28c38111a1da2019a0ef278056d2ccc-1.php#unique-entry-id-1</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/f28c38111a1da2019a0ef278056d2ccc-1.php#unique-entry-id-1</guid><content:encoded><![CDATA[<span style="font:13px Tahoma; ">For the last few months I&rsquo;ve been working on a web app using PHP that I&rsquo;m trying to be as RESTful I can. It&rsquo;s been a learning curve, and has been both satisfying and infuriating. &nbsp;Over the weekend I&rsquo;ve been working on the authentication. As it is a RESTful app HTTP digest authentication is the obvious (only?) choice. This being 2008 I also want the app to be pretty, like all the other web 2.0 apps (I hate the term &ldquo;2.0&Prime;. If the internet was made of technologies that could be broken in to discrete versions then life would be so much easier. While IE6 is still around the web will be stuck in beta testing).<br />Unfortunately, after much keyboard thumping and bouts of pseudo-tourette, I&rsquo;ve reach the conclusion that RESTful apps haven&rsquo;t got the style to get into Club Web 2.0.<br />This conclusion is based on the assumption that the standard browser authentication dialog box should be banished to 1997 and has no place in a 2008 web app. I must mention that I have only tested this on Firefox 2, Safari 3 and Opera 9 on OS X 10.4. FF and Safari both suffer from the problem outlined below. (Opera will always display the ugly dialog box even if a username and password were supplied to the xmlhttprequest object).&nbsp;<br />There are a few tutorials that say that you can use the xmlhttprequest object to suppress the browsers dialog box. It is true that the xmlhttprequest object can do this, but it only works in very select conditions. This is because of two features (bugs?) of the xmlhttprequest:<br />1. Firstly the XHR only answers the first 401 response per resource. Any subsequent 401 responses will cause the ugly dialog box to pop up. There a quite a few scenarios where the server might respond with a 2nd 401 response. The most common is when the username and password supplied to the XHR object are incorrect. Another common occurrence is that the nonce used in the digest expires causing the server to send a new nonce with the 401.<br />2. Above I mentioned that &ldquo;the XHR only answers the first 401 response </span><span style="font:13px Tahoma-Bold; font-weight:bold; font-weight:bold; ">per resource</span><span style="font:13px Tahoma; ">&ldquo;. This means that we could re-authenticate using a different resource. The problem with this is that browser send a mix and match of digest information. Here&rsquo;s an example:<br />Lets say that www.example.com/restricted/ requires authentication. Once the server has authenticated the client, the client will continues to send the &nbsp;the authentication details to all resources within www.example.com/restricted/. This is the correct behaviour.&nbsp;<br />Next the client tries to access www.example.com/restricted/secrets.html. When the client sends the request it also sends the authentication headers as before but this time the server response with a 401. The credentials that were valid for the rest of the site are not valid for this one resource. If we this request is made with the XHR object then it counts as the first 401 response from that resource. Therefore the XHR sends the request again using the username and password. So where&rsquo;s the problem? The problem lies with the fact that the client (Firefox 2 and Safari 3 at least), continue to send the nonce from the very first 401 response. The server may not accept the old nonce for this request and will send another 401 response. This second 401 response will cause the client to show the ugly dialog boxes.<br />&nbsp;<br />I have developed methods to work around both of these problems so that the XHR could be used. I&rsquo;m not going to use either of them because they are ugly and complicated. I always strive for simplicity as simple code is easier to understand and there&rsquo;s less chance for things to go wrong. Introducing unnecessary complication into an authentication system is asking for trouble.</span>]]></content:encoded></item><item><title>Shuttle K45 - optical drive? Check.</title><dc:creator>ben@benedictcohen.co.uk</dc:creator><category>Hardware</category><dc:date>2008-04-20T18:41:00+01:00</dc:date><link>http://benedictcohen.co.uk/files/test.php#unique-entry-id-0</link><guid isPermaLink="true">http://benedictcohen.co.uk/files/test.php#unique-entry-id-0</guid><content:encoded><![CDATA[<span style="color:#333333;">I recently bought a Shuttle K45 to run Ubuntu server. I&rsquo;m waiting until Hardy Heron is released proper until I set to work setting up the software. However, there are a few things about the K45 that I think are of interest.<br /></span><ul class="(null)"><li><span style="color:#333333;">Firstly, there is space in the case for an optical drive:<br /></span><img class="imageStyle" alt="k45-front" src="http://benedictcohen.co.uk/files/k45-front.jpg" width="480" height="360"/><img class="imageStyle" alt="k45-top-nodrive" src="http://benedictcohen.co.uk/files/k45-top-nodrive.jpg" width="480" height="640"/><img class="imageStyle" alt="k45-top-drive" src="http://benedictcohen.co.uk/files/k45-top-drive.jpg" width="480" height="640"/><img class="imageStyle" alt="k45-inside-front" src="http://benedictcohen.co.uk/files/k45-inside-front.jpg" width="480" height="360"/><span style="color:#333333;"><br /><br /><br />&nbsp; As you can see from these photos there is space for an optical drive, albeit a slim line one. The problem is that the plastic image sheet and the perspex that cover the front (abscent in the photos) don&rsquo;t have a slot for the drive. This is a only a minor problem, however.</span></li><li><span style="color:#333333;">I bought my K45 from </span><span style="color:#3465F2;"><a href="http://www.misco.co.uk/applications/SearchTools/item-details.asp?EdpNo=309497&CatId=3002">Misco</a></span><span style="color:#333333;">. It didn&rsquo;t come supplied with the Shuttle ICE cooling system. The ICE system is far quieter than the standard CPU fan that comes with the </span><span style="color:#3465F2;"><a href="http://www.misco.co.uk/applications/SearchTools/item-details.asp?EdpNo=279729&CatId=493">Celeron I bought</a></span><span style="color:#333333;">. Also the instructions (which are a bit thin, consisting only of one large colour sheet) show and refer to thumb screws. I like thumb screws, they&rsquo;re nice and chunky, however, my K45 only came with normal screws. Boo.</span></li><li><span style="color:#333333;">The IDE socket is very picky. My original plan was to have two SATA hard drives and an compact flash to IDE converter. I was going use the CF/IDE to run the OS from and use the harddrives exclusively for storing data. Unfortunately the K45 doesn&rsquo;t like CF/IDE converters. I tried two of them and each time the K45 refused to </span><span style="color:#333333;"><em>boot</em></span><span style="color:#333333;"> from them, no BIOS fiddling seemed to fix this. I empathises &lsquo;boot&rsquo; as it does recognise the drive. Infact, I managed to install Ubuntu to the CF/IDE but it wouldn&rsquo;t boot from it. This isn&rsquo;t a major problem, but it is an inconvenience. My first attempt at a solution was to use a USB CF reader and run the OS from that. But the CF reader I bought wasn&rsquo;t bootable, so I&rsquo;ve gone for a normal USB flash drive which will complicate the install, but where would the fun be if everything was easy?</span></li></ul>]]></content:encoded></item></channel>
</rss>