<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-5275464027504437639</id><updated>2011-11-27T17:59:27.931-08:00</updated><category term='linux'/><category term='cocos2d'/><category term='programming'/><category term='zombies'/><category term='ipad'/><category term='gestures'/><category term='games'/><category term='cloud'/><category term='Java'/><category term='QuerySet'/><category term='Google App Engine'/><category term='screen sharing'/><category term='draggable controls'/><category term='iphone'/><category term='ChromeOS'/><category term='Linq'/><category term='mac'/><category term='iphone-sdk'/><category term='dropbox'/><category term='windows'/><category term='teamviewer'/><category term='UIGestureView'/><category term='songbird'/><category term='ubuntu'/><category term='JDO'/><category term='OS'/><title type='text'>Joel's Nerd Blog</title><subtitle type='html'>Programming, computers, and whatever else I feel like.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.joelj.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>40</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-9222520264268059677</id><published>2011-07-22T20:00:00.000-07:00</published><updated>2011-07-22T20:06:30.494-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cocos2d'/><category scheme='http://www.blogger.com/atom/ns#' term='games'/><category scheme='http://www.blogger.com/atom/ns#' term='programming'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='zombies'/><title type='text'>iPhone Game part 1: Zombies!</title><content type='html'>I'm learning to use &lt;a href="http://www.cocos2d-iphone.org/"&gt;cocos2d-iphone&lt;/a&gt;. To do so I decided to make a simple game and blog what/how I'm doing each step of the way. Hopefully this will be useful for others trying to learn as well.&lt;br /&gt;&lt;br /&gt;For my demo game I decided to make a very simple clone of Plants VS Zombies. Here's the end result of this phase:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-c0A1x9vsXEk/TiosTDmFLzI/AAAAAAAAA4w/0vzZv49ABS4/s1600/pt1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="170" src="http://4.bp.blogspot.com/-c0A1x9vsXEk/TiosTDmFLzI/AAAAAAAAA4w/0vzZv49ABS4/s320/pt1.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Let's begin:&lt;br /&gt;&lt;br /&gt;I started by downloading and installing &lt;a href="http://www.cocos2d-iphone.org/download"&gt;Cocos2d&lt;/a&gt;. I'm using 1.0.0 stable. In the archive there's a file that tells you how to install Cocos2d. It's easy enough -- run the following command:&lt;br /&gt;&lt;br /&gt;sudo ./install-templates.sh&lt;br /&gt;&lt;br /&gt;from the extracted archive you downloaded. After that you should be able to just open Xcode (I'm using 4.2) and choose New Project -&amp;gt; Cocos2d Project.&lt;br /&gt;&lt;br /&gt;Now that you have your project started notice there's a class called "HelloWorldLayer.m". We're not going to use it much more than just a template. So add a new class to the project and call it "ZombieGameLayer". Then copy and paste the contents of HelloWorldLayer.m and HelloWorldLayer.h into your new .m and .h files you just created. Make sure you rename all references to "HelloWorldLayer" to "ZombieGameLayer".&lt;br /&gt;&lt;br /&gt;Now open AppDelegate.m and change line 13 to:&lt;br /&gt;import "ZombieGameLayer.h"&lt;br /&gt;&lt;br /&gt;then on line 113 change it to:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[[[CCDirector sharedDirector] runWithScene: [ZombieGameLayer scene]];]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Now open ZombieGameLayer.m and change your init method to be the same as this one:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[-(id) init {    if(!(self=[super init])) {        return nil;    }    return self;}]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now for the fun stuff.&lt;br /&gt;&lt;br /&gt;The goal of this part is to simple have a zombie walk from the right side of the screen and then off the right side of the screen. First we need a zombie sprite. Since I'm not very artistic, I chose to take a screenshot of Plants vs Zombies using my iPhone (press both buttons at the same time), email it to myself, open it in photoshop and remove the background of the image. You can go ahead and choose whatever zombie image you want. My zombie image is 42x72px, you should probably make yours the same.&lt;br /&gt;&lt;br /&gt;So we want every X seconds a new wave of zombies to come on the screen. We can do this by scheduling a timed event in the init method. Add the following line to your init method:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[[self schedule:@selector(newWaveOfZombiesEvent:) interval:1.0];]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;That basically says, every 1 second, call the newWaveOfZombiesEvent: method. So lets create that event method now:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[-(void)newWaveOfZombiesEvent:(ccTime)dt {    int row = [self randomMin:0 max:5];    [self addZombieOnRow:row];}//created this simple method for clarity-(int)randomMin:(int)min max:(int)max {    //min is INCLUSIVE, max is EXCLUSIVE    return (arc4random() % (max - min)) + min;}]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;For now we're just adding one zombie per wave, but we can easily change this method later to add a random number of zombies or to have a bunch of small waves then a huge wave. This will do for now. Now lets create the addZombieOnRow: method. What we need to do is the following:&lt;br /&gt;Create a new sprite with our zombie.png&lt;br /&gt;Figure out where to we want to position it based on the row we're given&lt;br /&gt;Tell the zombie to move towards the other side of the screen until it falls off the screen&lt;br /&gt;here's that translated to code:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[-(void)addZombieOnRow:(int)row {    // load sprite    CCSprite* zombie = [CCSprite spriteWithFile:@"zombie.png" rect:CGRectMake(0, 0, 42, 72)];         // initialize position    CGSize winSize = [[CCDirector sharedDirector] winSize];    int startX = winSize.width + (zombie.contentSize.width/2);    int startY = (row * 265 / NUMBER_ROWS) + BOTTOM_PADDING + zombie.contentSize.height/2; //I declared NUMBER_ROWS to be 5 and BOTTOM_PADDING to be 12    zombie.position = ccp(startX, startY);    [self addChild:zombie];        // move the zombie    int speed = 75;    id moveAction = [CCMoveTo actionWithDuration:speed position:ccp(-zombie.contentSize.width/2, startY)];    id doneAction = [CCCallFuncN actionWithTarget:self selector:@selector(zombieReachedEdge:)];    [zombie runAction:[CCSequence actions:moveAction, doneAction, nil]];}]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;That should be mostly straight forward. The first line simply loads the zombie.png file and creates a sprite that is 42x72px in size. Then we position it off the screen.&lt;br /&gt;How we decide to tell the zombie to move is by creating two actions. The first is an action that we are basically saying, "move the zombie at a rate so that it takes it 75 seconds to get to the given position." The second action we are simply saying, "tell me when the zombie is done moving." We sew those two actions together as a Sequence, which will run the first one until it's done, then run the next one and so on. Then we tell the zombie to run that action. I chose 75 seconds because I counted how long it takes the zombie to walk 3 squares in the iphone game, then I multiplied that number by 3. So it's pretty close to the speed of the original game (not perfect, considering the zombies in the real game only have to make it to the house... not the edge of the screen.) I left the speed as a variable rather than defining it as a constant because one day I might want to refactor the zombie into it's own class and allow the speed to be defined for different difficulties and such. But for now we'll leave it as a local variable.&lt;br /&gt;&lt;br /&gt;Now we just need to decide what to do with the zombie when it reaches the left side of the screen. Which is easy:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[-(void)zombieReachedEdge:(id)sender {    CCSprite* sprite = (CCSprite*) sender;    [self removeChild:sprite cleanup:YES];}]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Later we might want to add something cool like, "Zombies ate your neighbors!" or something when this happens, but for now we'll just send the zombie back to the graveyard.&lt;br /&gt;&lt;br /&gt;That's it! Pretty simple. But we're just getting started. Stay tuned for the next part, Plants!&lt;br /&gt;&lt;br /&gt;Special thanks to &lt;a href="http://www.raywenderlich.com/352/how-to-make-a-simple-iphone-game-with-cocos2d-tutorial"&gt;this tutorial&lt;/a&gt; for getting me started.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-9222520264268059677?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/9222520264268059677/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=9222520264268059677' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/9222520264268059677'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/9222520264268059677'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2011/07/iphone-game-part-1-zombies.html' title='iPhone Game part 1: Zombies!'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-c0A1x9vsXEk/TiosTDmFLzI/AAAAAAAAA4w/0vzZv49ABS4/s72-c/pt1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-594736180030477039</id><published>2011-01-11T20:14:00.000-08:00</published><updated>2011-01-11T21:30:40.953-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OS'/><category scheme='http://www.blogger.com/atom/ns#' term='cloud'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><category scheme='http://www.blogger.com/atom/ns#' term='dropbox'/><category scheme='http://www.blogger.com/atom/ns#' term='ChromeOS'/><title type='text'>ChromeOS: Is Google going the wrong way?</title><content type='html'>I was one of 60,000 lucky people who received a &lt;a href="http://www.google.com/chromeos/pilot-program-cr48.html"&gt;CR-48&lt;/a&gt; for Christmas. When I first heard about ChromeOS oh so long ago, I was really excited to hear that Google was making a Linux based operating system. If anyone could pull it off, I thought, it was Google. But then I heard what ChromeOS was: a browser. I thought that was a horrible idea. I went ahead and registered for the pilot program when it was announced, and to my surprise I actually received one in the mail. I'll admit it: I love it. In fact, I might even recommend it to my friends and family when a Chromiumbook goes on sale.&lt;br /&gt;&lt;br /&gt;However, there is just one thing nagging at me: I think Google went the wrong way.&amp;nbsp;ChromeOS takes the idea that the browser is really an operating system, and makes it a reality. I'm proposing the opposite: the operating system should be the browser.&lt;br /&gt;&lt;br /&gt;Why not create a way to have web-apps launched from your desktop the same way programs are now. I'm not talking about the hack job &lt;a href="http://prism.mozillalabs.com/"&gt;Prism&lt;/a&gt; and other related ideas. I mean an operating system that will allow you to develop a webapp, an application that lives online, but is seamlessly integrated with your operating system. (Probably using a system closer to Adobe's &lt;a href="http://www.adobe.com/products/air/"&gt;Air&lt;/a&gt;, but with content that is stored on "the cloud" rather than locally.)&lt;br /&gt;&lt;br /&gt;This is how I imagine it would work. You turn on your computer and you get a login screen. This screen will allow you to log in with some kind of open standard authentication system. Something like&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/OpenID"&gt;OpenID&lt;/a&gt;, but maybe something else. After you log in, it will display your wallpaper, theme, and all your shortcuts as they are stored online. You can set up your Documents folder to sync with whatever service you want: Google Docs, Microsoft Office, Dropbox, etc. You have your Pictures folder synced with another service: Picasa Web, SmugMug, etc. Or maybe you have your entire Home folder synced with one service. Whatever you choose. You browse through the folders like you do on your Windows/Linux/Mac box you have now. When you open an image, it will open in whatever default program you have set (SmugMug, Picasa Web, whatever) in it's own frame. It will add said webapp's icon to your dock/taskbar to show that you have that webapp open. You can minimize, maximize, or move the window just like on a "real" operating system.&lt;br /&gt;Webapps would be allowed to send you notifications (calendar reminders, chats, etc), they will be allowed to save documents to your documents folder or wherever else you want them to go, they could launch your &lt;a href="http://www.picnik.com/"&gt;default image editor&lt;/a&gt;&amp;nbsp;or Amazon's ebook webapp could open a book preview in your default ebook reader, they could even index all your files to let you search. Of course you could launch a browser window and browse the web like you do now. Of course, each webapp would be required to tell you want it's going to do (index, notifications, etc) when you "install" it, so you don't have to worry about some rogue program doing something you didn't expect it to. Imagine: Google Docs in it's own window, with it's own tabs, with it's own icon in the task bar.&lt;br /&gt;&lt;br /&gt;On my own machines, I love tools like Mac's Spotlight, Gnome Do, Window 7's start menu search. I imagine on my cloud OS I would go ahead and install the &lt;a href="http://duckduckgo.com/"&gt;DuckDuckGo&lt;/a&gt;&amp;nbsp;search app, hit the search key, type in the file/image/program/websearch-query/whatever and out pops search results.&lt;br /&gt;&lt;br /&gt;Now when you go the library, use a friends computer, or go home for the weekend, you can sign into that computer and have everything exactly the way you want it. Now when you get that super slim 10 inch tablet you've been dreaming of, you will turn it on for the first time, sign in, and BAM. Instant access to everything just with a Tablet UI rather than a Desktop UI.&lt;br /&gt;&lt;br /&gt;I don't imagine this would hurt too much in battery life, processing time, memory usage, startup/shutdown times, or hard drive space when compared to ChromeOS. Considering it would be the exact same thing, only with a different presentation.&lt;br /&gt;&lt;br /&gt;If Google would've made the operating system a webbrowser, rather than the browser an operating system. I think ChromeOS wouldn't only put up a fight in the netbook world, but would really disrupt the desktop world as we know it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-594736180030477039?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/594736180030477039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=594736180030477039' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/594736180030477039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/594736180030477039'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2011/01/chromeos-is-google-going-wrong-way.html' title='ChromeOS: Is Google going the wrong way?'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-7506477092744688220</id><published>2010-08-20T21:13:00.000-07:00</published><updated>2010-08-20T21:14:41.853-07:00</updated><title type='text'>C# Servlets... We have liftoff</title><content type='html'>http://code.google.com/p/csharp-servlets/&lt;br /&gt;&lt;br /&gt;I just committed version 0.1 of my lastest project. A Java Sevlet style web server. I have built it from scratch using C#/Mono. Currently it accepts all forms of HTTP Methods (get, post, put, delete, etc) and parses the request into an easy-to-use object. Letting you access properties sent from the browser in both the POST body and the query string. It will call the correct "Servlets" according to the URL map you set using Attributes. And lets you write output back out using the easy-to-use response object. Here's an example:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[[Servlet]public class MyServlet{  [GetMethod("/index")]  public void SomeGetMethod(IRequest request, IResponse response) {     response.OutputStream("Hello " + request.QueryString["name"] + "!");  }  [PostMethod("/newUser")]  public void SomePostMethod(IRequest request, IResponse response) {     response.OutputStream("Created new user " + request.Body["user"] + "!");  }}]]&gt;    &lt;/script&gt;&lt;br /&gt;simple as pie. Download the source and let me know what you think!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-7506477092744688220?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/7506477092744688220/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=7506477092744688220' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/7506477092744688220'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/7506477092744688220'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/08/c-servlets-we-have-liftoff.html' title='C# Servlets... We have liftoff'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-7898384827927729827</id><published>2010-08-20T15:07:00.000-07:00</published><updated>2010-08-20T15:07:10.902-07:00</updated><title type='text'>Undelete</title><content type='html'>A friend showed me this blog post the other day:&lt;br /&gt;http://spin.atomicobject.com/2010/08/18/undelete?utm_source=y-combinator&amp;utm_medium=social-media&amp;utm_campaign=technical&lt;br /&gt;&lt;br /&gt;Using GREP he was able to undelete a file accidentally erased. Brilliant.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-7898384827927729827?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/7898384827927729827/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=7898384827927729827' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/7898384827927729827'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/7898384827927729827'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/08/undelete.html' title='Undelete'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-6926603142856325085</id><published>2010-08-14T15:03:00.000-07:00</published><updated>2010-08-14T15:04:46.050-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDO'/><category scheme='http://www.blogger.com/atom/ns#' term='QuerySet'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Google App Engine'/><category scheme='http://www.blogger.com/atom/ns#' term='Linq'/><title type='text'>Simplified JDO Queries</title><content type='html'>I've been playing with Google App Engine lately. I wanted a simple way to get and filter objects from the Datastore. I made a base class called &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ModelBase&lt;/span&gt; that has a single static method on it.&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[import javax.jdo.PersistenceManager;public abstract class ModelBase{ public static &lt;t extends ModelBase&gt; Query&lt;t&gt; all(PersistenceManager pm, Class&lt;t&gt; type) {  return new Query&lt;t&gt;(pm, type); }}]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;That makes use of my custom&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Query&lt;t&gt;&lt;/t&gt;&lt;/span&gt; object. This is what it looks like:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[import java.util.LinkedList;import java.util.List;import javax.jdo.PersistenceManager;public class Query&lt;t extends ModelBase&gt;{ private Class&lt;t&gt; type; private PersistenceManager pm;  private List&lt;string&gt; where = new LinkedList&lt;string&gt;(); private List&lt;string&gt; orderBy = new LinkedList&lt;string&gt;();  Query(PersistenceManager pm, Class&lt;t&gt; type) {  this.type = type;  this.pm = pm; }  public Query&lt;t&gt; filter(String field, String value) {  return this.filter(field, Evaluation.EqualTo, value); }  public Query&lt;t&gt; filter(String field, Evaluation e, String value) {  where.add(field + " " +e + " '" + value +"'");  return this; }  public Query&lt;t&gt; orderBy(String orderBy, OrderBy order) {  if(order == OrderBy.Descending) {   orderBy += " desc";  }  else {   orderBy += " asc";  }  this.orderBy.add(orderBy);  return this; }  public T get() {  return this.get(1).get(0); }  @SuppressWarnings("unchecked") public List&lt;t&gt; getAll() {  String query = buildQuery();  List&lt;t&gt; result = (List&lt;t&gt;)pm.newQuery(query).execute();  return result; }  public List&lt;t&gt; get(int count) {  return this.get(0, count); }  @SuppressWarnings("unchecked") public List&lt;t&gt; get(int start, int end) {  String query = buildQuery(start, end);  List&lt;t&gt; result = (List&lt;t&gt;)pm.newQuery(query).execute();  return result; }  private String buildQuery() {  String qry = "select from " +type.getName();    qry += buildWhere();  qry += buildOrderBy();    return qry; }  private String buildQuery(int start, int end) {  String qry = "select from " +type.getName();    qry += buildWhere();  qry += buildOrderBy();  qry += " range " + start + ", " + end;    return qry; } private String buildWhere() {  String qry = "";  if(this.where.size() &gt; 0) {   boolean first = true;   for(String where : this.where) {    if(first) {     qry += " where " + where;     first = false;    } else {     qry += " &amp;&amp; " + where;    }   }  }  return qry; }  private String buildOrderBy() {  String qry = "";  if(this.orderBy.size() &gt; 0) {   qry += " order by";   for(String order : this.orderBy) {    qry += " " + order;   }  }  return qry; }}]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Then, for simplicity sake, in each child class I overload the static&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;all()&lt;/span&gt; method so that I don't have to pass in the class type every time I call it.&lt;br /&gt;&lt;br /&gt;Now I can get all object like this:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[List&lt;customer&gt; allCustomers = Customer.all(myPersistenceManager).getAll();]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Filter like this:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[List&lt;customer&gt; allJohnsons = Customer.all(myPersistenceManager).filter("lastname", "Johnson").getAll();]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Even filter using operations other than EQUALS:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[List&lt;customer&gt; allAdults = Customer.all(myPersistenceManager).filter("age", Evaluation.GreaterThanOrEqualTo, "18").getAll();]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Even chain filter calls:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[List&lt;customer&gt; allAdults = Customer.all(myPersistenceManager).filter("age", Evaluation.GreaterThanOrEqualTo, "13").filter("age", Evaluation.LessThanOrEqualTo, "19").getAll();]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;Or I can get a single object like this:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[Customer myCustomer = Customer.all(myPersistenceManager).filter("email", "mycustomer@company.com").get();]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;or for paging:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[List&lt;customer&gt; allJohnsons = Customer.all(myPersistenceManager).filter("lastname", "Johnson").getAll(10,20); // returns results 10 to 20]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;br /&gt;However, on Google's page, I read that the way I do paging is actually quite&amp;nbsp;inefficient, so I need to look into optimizing that. I'll update this post when I do.&lt;br /&gt;&lt;br /&gt;There still might be bugs in the code as I haven't written any tests for it. Just been playing around with it in code. I'll update this post when I fix or change something.&lt;br /&gt;&lt;br /&gt;And here's the Evaluation enum:&lt;br /&gt;&lt;br /&gt;&lt;script class="brush: java" type="syntaxhighlighter"&gt;&lt;![CDATA[public enum Evaluation{ EqualTo {  public String toString()  {   return "==";  } },  NotEqualTo{  public String toString()  {   return "!=";  } },  GreaterThan{  public String toString()  {   return "&gt;";  } },  GreaterThanOrEqualTo{  public String toString()  {   return "&gt;=";  } },  LessThan{  public String toString()  {   return "&lt;";  } },  LessThanOrEqualTo{  public String toString()  {   return "&lt;=";  } }}]]&gt;    &lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-6926603142856325085?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/6926603142856325085/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=6926603142856325085' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/6926603142856325085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/6926603142856325085'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/08/simplified-jdo-queries.html' title='Simplified JDO Queries'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-8444999784159058709</id><published>2010-06-08T18:29:00.000-07:00</published><updated>2010-06-11T09:04:55.755-07:00</updated><title type='text'>Fixed code blocks</title><content type='html'>I found a syntax highlighting script for the blog. I updated my most popular post to use it, but have been too lazy to fix my other posts.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-8444999784159058709?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/8444999784159058709/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=8444999784159058709' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/8444999784159058709'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/8444999784159058709'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/06/moved-to-my-own-domain.html' title='Fixed code blocks'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-7453592212072100663</id><published>2010-05-29T17:14:00.000-07:00</published><updated>2010-05-29T17:14:10.844-07:00</updated><title type='text'>The Perfect Email Regex</title><content type='html'>I'm sure there are links to this all over the place right now. But I didn't want to lose this. I figured I'd post it here so I always know where to find it.&lt;br /&gt;&lt;br /&gt;Source: http://fightingforalostcause.net/misc/2006/compare-email-regex.php&lt;br /&gt;&lt;br /&gt;Regex: &lt;br /&gt;&lt;br /&gt;&lt;code&gt;/^([\w\!\#$\%\&amp;\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&amp;\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,6})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)$/i&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-7453592212072100663?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/7453592212072100663/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=7453592212072100663' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/7453592212072100663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/7453592212072100663'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/05/perfect-email-regex.html' title='The Perfect Email Regex'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-5092732558236252098</id><published>2010-05-07T21:20:00.000-07:00</published><updated>2010-05-08T11:57:14.148-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iphone-sdk'/><category scheme='http://www.blogger.com/atom/ns#' term='draggable controls'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='ipad'/><category scheme='http://www.blogger.com/atom/ns#' term='gestures'/><category scheme='http://www.blogger.com/atom/ns#' term='UIGestureView'/><title type='text'>UIGestureView = UIView++; (UIView with built in gesture support)</title><content type='html'>Everything I've found online relating to touch gestures on UIViews in the iPhone SDK, requires you to implement those gestures manually. Since many gestures are relatively common (such as single-tap, double-tap, two-finger-tap, tap-and-hold) I made a base class that implements those gestures. When the gesture is made, it calls a method that can be overridden in a class that extends the base, or it forwards that event to a delegate.&lt;br /&gt;&lt;br /&gt;Here's the code:&lt;br /&gt;&lt;br /&gt;&lt;u&gt;GestureUIDelegate.h&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@protocol GestureUIDelegate&lt;br /&gt;&lt;br /&gt;-(void) singleTapGesture:(UITouch*)touch;&lt;br /&gt;-(void) doubleTapGesture:(UITouch*)touch;&lt;br /&gt;-(void) twoFingerTouchGestureAt:(UITouch*)touch1 and:(UITouch*)touch2;&lt;br /&gt;-(void) touchAndHoldGesture:(UITouch*)touch;&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;UIGestureView.h&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#import "GestureUIDelegate.h"&lt;br /&gt;&lt;br /&gt;@interface UIBase : UIView&lt;br /&gt;{&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;id&lt;gestureuidelegate&gt; gestureDelegate; //bug with blogger. it won't show that id implements the GestureUIDelegate protocol &lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;BOOL movable;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;BOOL resizable;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;BOOL userMoving;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;BOOL userResizing;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;CGPoint lastPoint;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;int resizeHandleSize;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;double touchDelay;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;double tapDelay;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;@private&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;UIImageView* border;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;NSTimer* touchTimer;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;UITouch* heldTouch;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;float minWidth;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;float minHeight;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;NSTimer* tapTimer;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;UITouch* tapTouch;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#pragma mark Properties&lt;br /&gt;@property (nonatomic, retain) id&lt;gestureuidelegate&gt; gestureDelegate;&lt;/gestureuidelegate&gt;&lt;br /&gt;&lt;br /&gt;@property BOOL movable;&lt;br /&gt;@property BOOL resizable;&lt;br /&gt;&lt;br /&gt;@property float minWidth;&lt;br /&gt;@property float minHeight;&lt;br /&gt;@property float x;&lt;br /&gt;@property float y;&lt;br /&gt;@property float width;&lt;br /&gt;@property float height;&lt;br /&gt;&lt;br /&gt;#pragma mark Public Methods&lt;br /&gt;-(void) initializeDefaults;&lt;br /&gt;&lt;br /&gt;#pragma mark Custom Events&lt;br /&gt;-(void) singleTapGesture:(UITouch*)touch;&lt;br /&gt;-(void) doubleTapGesture:(UITouch*)touch;&lt;br /&gt;-(void) twoFingerTouchGestureAt:(UITouch*)touch1 and:(UITouch*)touch2;&lt;br /&gt;-(void) touchAndHoldGesture:(UITouch*)touch;&lt;br /&gt;&lt;br /&gt;#pragma mark Private Methods&lt;br /&gt;&lt;br /&gt;-(BOOL) touchInWindow:(UITouch*) touch;&lt;br /&gt;-(BOOL) touchInBottomRightCorner:(UITouch*) touch;&lt;br /&gt;&lt;br /&gt;-(void) startTouchAndHold:(UITouch*)touch;&lt;br /&gt;-(void) cancelTouchAndHold;&lt;br /&gt;&lt;br /&gt;-(void) startSingleTouch:(UITouch*)touch;&lt;br /&gt;-(void) cancelSingleTouch;&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;/gestureuidelegate&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;&lt;span class="Apple-style-span" style="-webkit-text-decorations-in-effect: none;"&gt;&lt;u&gt;UIGestureView&lt;/u&gt;&lt;/span&gt;.m&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/div&gt;&lt;div&gt;&lt;code&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;div&gt;#import "UIGestureView.h"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;@implementation UIBase&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;@synthesize resizable;&lt;/div&gt;&lt;div&gt;@synthesize movable;&lt;/div&gt;&lt;div&gt;@synthesize gestureDelegate;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;@dynamic x;&lt;/div&gt;&lt;div&gt;@dynamic y;&lt;/div&gt;&lt;div&gt;@dynamic width;&lt;/div&gt;&lt;div&gt;@dynamic height;&lt;/div&gt;&lt;div&gt;@dynamic minWidth;&lt;/div&gt;&lt;div&gt;@dynamic minHeight;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(id) initWithFrame:(CGRect)frame&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;self = [super initWithFrame:frame];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;if(!self)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;return nil;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[self initializeDefaults];&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return self;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) initializeDefaults&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;self.minWidth = 50;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;self.minHeight = 50;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;resizeHandleSize = 20;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;self.backgroundColor = [UIColor redColor];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;self.multipleTouchEnabled = YES;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;touchDelay = 0.5;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;tapDelay = 0.2;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;//self.resizable = YES;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;//self.movable = YES;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#pragma mark Touch Events&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[[self superview] bringSubviewToFront:self];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;UITouch* touch = [touches anyObject];&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;if(touch.tapCount == 2)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;[self cancelSingleTouch];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;[self doubleTapGesture:touch];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;else if(touch.tapCount == 1)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;if([touches count] == 1)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;lastPoint = [touch locationInView:self.superview];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;BOOL touchInWindow = [self touchInWindow:touch];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;if(touchInWindow)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;    &lt;/span&gt;userResizing = [self touchInBottomRightCorner:touch] &amp;amp;&amp;amp; resizable;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;    &lt;/span&gt;if(!userResizing)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;    &lt;/span&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;     &lt;/span&gt;[self startTouchAndHold:touch];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;     &lt;/span&gt;userMoving = touchInWindow &amp;amp;&amp;amp; movable;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;    &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[self cancelTouchAndHold];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;UITouch* touch = [touches anyObject];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;CGPoint point = [touch locationInView:self.superview];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;float xChange = point.x - lastPoint.x;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;float yChange = point.y - lastPoint.y;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;if(userResizing)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;float width = self.frame.size.width + xChange;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;float height = self.frame.size.height + yChange;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;if (width &amp;gt;= self.minWidth &amp;amp;&amp;amp; height &amp;gt;= self.minHeight)&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;self.width = width;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;self.height = height;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;[self setNeedsDisplay];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;else if(userMoving)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;float oldX = self.frame.origin.x;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;float oldY = self.frame.origin.y;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;float x = oldX + xChange;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;float y = oldY + yChange;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;self.x = x;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;self.y = y;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;lastPoint = point;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[self cancelTouchAndHold];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;if([touches count] &amp;gt;= 2)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;UITouch* touch1 = [[touches allObjects] objectAtIndex:0];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;UITouch* touch2 = [[touches allObjects] objectAtIndex:1];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;[self twoFingerTouchGestureAt:touch1 and:touch2];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;else&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;UITouch* touch = [touches anyObject];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;if([touch tapCount]== 1)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;[self startSingleTouch:touch];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;userResizing = NO;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;userMoving = NO;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#pragma mark Private Methods&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) singleTapGestureSucceeded&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;UITouch* touch = tapTouch;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[self cancelSingleTouch];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[self singleTapGesture:touch];&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) startSingleTouch:(UITouch*)touch&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;tapTouch = touch;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;tapTimer = [[NSTimer scheduledTimerWithTimeInterval:tapDelay target:self selector:@selector(singleTapGestureSucceeded) userInfo:nil repeats:NO] retain];&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) cancelSingleTouch&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;if(tapTimer)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;[tapTimer invalidate];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;[tapTimer release];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;tapTouch = nil;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;tapTimer = nil;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) startTouchAndHold:(UITouch*)touch&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;heldTouch = touch;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;touchTimer = [[NSTimer scheduledTimerWithTimeInterval:touchDelay target:self selector:@selector(touchHasBeenHeld) userInfo:nil repeats:NO] retain];&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) cancelTouchAndHold&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;if(touchTimer)&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;[touchTimer invalidate];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;[touchTimer release];&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;touchTimer = nil;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;heldTouch = nil;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) touchHasBeenHeld&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;userMoving = NO;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;UITouch* touch = heldTouch;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[self cancelTouchAndHold];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[self touchAndHoldGesture:touch];&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(BOOL) touchInWindow:(UITouch*) touch&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;CGPoint location = [touch locationInView:self];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;int x = location.x;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;int y = location.y;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;int width = self.frame.size.width;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;int height = self.frame.size.height;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return (x &amp;gt; 0 &amp;amp;&amp;amp; x &amp;lt; width) &amp;amp;&amp;amp; (y &amp;gt; 0 &amp;amp;&amp;amp; y &amp;lt; height);&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(BOOL) touchInBottomRightCorner:(UITouch*) touch&lt;/div&gt;&lt;div&gt;{&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;CGPoint location = [touch locationInView:self];&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;int x = location.x;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;int y = location.y;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;int width = self.frame.size.width;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;int height = self.frame.size.height;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return (x &amp;gt; width - resizeHandleSize &amp;amp;&amp;amp; x &amp;lt; width) &amp;amp;&amp;amp; (y &amp;gt; height - resizeHandleSize &amp;amp;&amp;amp; y &amp;lt; height);&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#pragma mark Gestures&lt;/div&gt;&lt;div&gt;-(void) singleTapGesture:(UITouch*)touch&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[gestureDelegate singleTapGesture:touch];&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;-(void) doubleTapGesture:(UITouch*)touch&amp;nbsp;&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[gestureDelegate doubleTapGesture:touch];&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;-(void) twoFingerTouchGestureAt:(UITouch*)touch1 and:(UITouch*)touch2&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[gestureDelegate twoFingerTouchGestureAt:touch1 and:touch2];&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;-(void) touchAndHoldGesture:(UITouch*)touch&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[gestureDelegate touchAndHoldGesture:touch];&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;#pragma mark Properties&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(float) x&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return self.frame.origin.x;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) setX:(float) x&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;CGRect newFrame = CGRectMake(x, self.y, self.width, self.height);&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;self.frame = newFrame;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(float) y&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return self.frame.origin.y;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) setY:(float) y&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;CGRect newFrame = CGRectMake(self.x, y, self.width, self.height);&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;self.frame = newFrame;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(float) width&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return self.frame.size.width;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) setWidth:(float) width&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;CGRect newFrame = CGRectMake(self.x, self.y, width, self.height);&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;self.frame = newFrame;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(float) height&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return self.frame.size.height;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) setHeight:(float) height&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;CGRect newFrame = CGRectMake(self.x, self.y, self.width, height);&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;self.frame = newFrame;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(float) minWidth&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return minWidth;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) setMinWidth:(float)width&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;minWidth = width;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(float) minHeight&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return minHeight;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-(void) setMinHeight:(float)height&lt;/div&gt;&lt;div&gt;{&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;minHeight = height;&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;@end&lt;/div&gt;&lt;/code&gt;&lt;/div&gt;&lt;code&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As you can see, I'm pretty lazy with what I call "Private" methods. You can put those into a hidden interface/implementation if you want.&lt;br /&gt;&lt;br /&gt;This is very simple to use. You use it just like a UIView. If you want to use it as a base class, you just override the gesture methods you want. Make sure you call the super's implementation if you want it to still forward the gesture events to the delegate.&amp;nbsp;If you want to make the UIView movable or resizable, just set the respective properties to YES.&lt;br /&gt;&lt;br /&gt;Let me know what you think in the comments. Suggestions and questions are welcome.&lt;br /&gt;I plan to eventually add in support for the pinch gestures.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-5092732558236252098?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/5092732558236252098/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=5092732558236252098' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5092732558236252098'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5092732558236252098'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/05/uigestureview-uiview-uiview-with-built.html' title='UIGestureView = UIView++; (UIView with built in gesture support)'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-70727601761300659</id><published>2010-05-02T22:18:00.000-07:00</published><updated>2010-05-02T22:18:27.976-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='screen sharing'/><category scheme='http://www.blogger.com/atom/ns#' term='teamviewer'/><title type='text'>TeamViewer</title><content type='html'>&lt;a href="http://www.teamviewer.com/"&gt;TeamViewer&lt;/a&gt; has become one of my new favorite programs. It allows you to remote to another machine to do screensharing. They support Linux, Mac OS X, and Windows. They even have an iPhone app.&lt;br /&gt;&lt;br /&gt;The other day my little sister IM'd me and asked me to help fix a problem on Windows XP. I had her download their QuickSupport app that doesn't require any install. She ran it, gave me the user number provided to her, I plugged that into the application, hit go and I had nice, smooth access to her computer. I fixed the problem in just a minute or two. Best part is, I didn't have to try to explain it over the phone of IM or try to work around firewalls. It just worked!&lt;br /&gt;&lt;br /&gt;I highly recommend this to anyone who has ever had to help someone fix their computer over the phone.&lt;br /&gt;&lt;br /&gt;And here's the good news: TeamViewer is free for non-commercial use.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-70727601761300659?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/70727601761300659/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=70727601761300659' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/70727601761300659'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/70727601761300659'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/05/teamviewer.html' title='TeamViewer'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-5504089855859810974</id><published>2010-04-23T23:09:00.000-07:00</published><updated>2010-04-23T23:11:51.856-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='draggable controls'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='ipad'/><title type='text'>iPhone SDK - Moving and scrolling a UITextView with one finger</title><content type='html'>After implementing the draggable UIViews in my previous post, I added a UITextView to the control. Needless to say, when the user touches and drags on the text view it attempts to scroll the text rather than move the view around. At first, I thought I would have to change my moving to be two finger movement or something similar. Searching around &lt;a href="http://google.com/"&gt;Google&lt;/a&gt; and &lt;a href="http://stackoverflow.com/"&gt;StackOverFlow.com&lt;/a&gt; only gave me suggestions that I really didn't want to do. Such as subclassing different controls and overriding their touch events. Too much work and way to sloppy of an implementation. I wanted something simple to implement, and simple to read and follow in the future. This is what I came up with.&lt;br /&gt;&lt;br /&gt;In my subclasses UIView from the previous post, I added this as an instance variable:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;UIView* cover;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;then in my initialization method I added this:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;cover = [[UIView alloc] initWithFrame:textViewFrame];&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;cover.backgroundColor = [UIColor clearColor];&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[self addSubview:cover];&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I cover the UITextView with an invisible cover. However, this creates the problem of not being able to select or scroll the UITextView.&lt;br /&gt;&lt;br /&gt;So, to fix that I set my UITextView's delegate to self and implemented these two methods:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;-(BOOL) textViewShouldBeginEditing:(UITextView *)textView&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;NSLog(@"textViewShouldBeginEditing");&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[cover removeFromSuperview];&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return YES;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;-(BOOL) textViewShouldEndEditing:(UITextView *)textView&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;NSLog(@"textViewShouldEndEditing");&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;[self addSubview:cover];&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;return YES;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;When the textview gains focus, the cover is hidden. When the textview loses focus, the cover is put back into place.&lt;br /&gt;&lt;br /&gt;Now you have to decide how you want to give the textview focus. I decided to give the textview focus when I double-tapped my UIView. So in the&amp;nbsp;touchesBegan:withEvent: method, I added the following:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;if(touch.tapCount == 2)&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;{&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;  &lt;/span&gt;[self.textView becomeFirstResponder];&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There, now the UIView is movable as expected. Then the user can double-tap the view to edit the text and scroll through the contents. I think this is a much cleaner approach than more subclassing other controls.&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-5504089855859810974?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/5504089855859810974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=5504089855859810974' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5504089855859810974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5504089855859810974'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/04/iphone-sdk-moving-and-scrolling.html' title='iPhone SDK - Moving and scrolling a UITextView with one finger'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-5390233817473301046</id><published>2010-04-21T21:36:00.000-07:00</published><updated>2010-06-08T16:04:58.411-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='draggable controls'/><category scheme='http://www.blogger.com/atom/ns#' term='iphone'/><category scheme='http://www.blogger.com/atom/ns#' term='ipad'/><title type='text'>iPhone SDK - Movable and resizable UIViews</title><content type='html'>&lt;div&gt;I needed to do this for a project I'm working on. It was actually pretty simple to do. Complete with a border.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I made my draggable UIView a subclass of UIView, rather than making a delegate object or something because I needed to add other functionality to the control, so it just made sense to do it this way.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;We'll start with the interface:&lt;/div&gt;&lt;div&gt;&lt;script class="brush: cpp" type="syntaxhighlighter"&gt;&lt;![CDATA[@interface Notecard : UIView{ float borderWidth;  BOOL userResizing; BOOL userMoving; CGPoint lastPoint; UIImageView* border;  int minWidth; int minHeight;}]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now this should be pretty self-explanatory. borderWidth is used to set how thick I want my border. lastPoint is used to remember the last place the user touched. This is useful for both dragging the UIView and resizing. I also have minWidth and minHeight to use to prevent the user from making the control too small. I also made properties for borderWidth, minWidth, and minHeight. I didn't include it here because it's not really necessary for this example.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;I created a simple method to be called from all my -(id)initWith... methods. That way it doesn't matter how they are initialized, the same values will always be set.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;so add this line of code to your initWith... methods:&lt;/div&gt;&lt;div&gt;&lt;script type="syntaxhighlighter" class="brush: cpp"&gt;&lt;![CDATA[[self defaultInit];]]&gt;    &lt;/script&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;and add this method:&lt;/div&gt;&lt;div&gt;&lt;script type="syntaxhighlighter" class="brush: cpp"&gt;&lt;![CDATA[-(void) defaultInit{ self.backgroundColor = [UIColor yellowColor]; self.borderWidth = 3.0; [self setUserInteractionEnabled:YES];  border = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; minWidth = 50; minHeight = 50;}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So those are just some simple default values. I set the background color to yellow, because the default is white and in my project the main window's background color is white as well. Making it yellow made it easier to see what exactly was going on.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now for the meat:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;script type="syntaxhighlighter" class="brush: cpp"&gt;&lt;![CDATA[-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [[self superview] bringSubviewToFront:self ];  UITouch* touch = [touches anyObject]; lastPoint = [touch locationInView:self.superview];  BOOL touchInWindow = [self touchInWindow:touch]; if(touchInWindow) {  userResizing = [self touchInBottomRightCorner:touch];    if(!userResizing) userMoving = touchInWindow; }}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I do a simple check: if the touch is in the window, I set the userMoving boolean to be true. I also added a check, if the user is touching in the bottom right corner of the control, then set it to resizing. It might be better to only set userMoving if userResizing is false, but the way I do the next method makes it not really matter.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;script type="syntaxhighlighter" class="brush: cpp"&gt;&lt;![CDATA[-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ UITouch* touch = [touches anyObject]; CGPoint point = [touch locationInView:self.superview];  float xChange = point.x - lastPoint.x; float yChange = point.y - lastPoint.y;  if(userResizing) {  int width = self.frame.size.width + xChange;  int height = self.frame.size.height + yChange;  if (width &gt;= self.minWidth &amp;&amp; height &gt;= self.minHeight)  {   self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, width, height);   [self setNeedsDisplay];  } } else if(userMoving) {  float oldX = self.frame.origin.x;  float oldY = self.frame.origin.y;  float x = oldX + xChange;  float y = oldY + yChange;  self.frame = CGRectMake(x, y, self.frame.size.width, self.frame.size.height); }  lastPoint = point;}-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ userResizing = NO; userMoving = NO;}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So in the touchesMoved method, I get the distance the touch has moved. If the userResizing flag is true, then I change the size of the window by the amount the touch has moved. The moving logic is pretty much identical, but I adjust the location of the control rather than the size.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the touchesEnded method, I just set both flags to false.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then to draw the border, I override the drawRect method:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;script type="syntaxhighlighter" class="brush: cpp"&gt;&lt;![CDATA[- (void)drawRect:(CGRect)rect{ if(border &amp;&amp; border.image) {  border.image = nil;  border.frame = rect; }    UIGraphicsBeginImageContext(self.frame.size);  CGContextRef currentContex = UIGraphicsGetCurrentContext(); CGContextSetLineWidth(currentContex, self.borderWidth); CGContextSetRGBStrokeColor(currentContex, 0.0, 0.0, 0.0, 1.0); CGRect myRect = CGContextGetClipBoundingBox(currentContex); CGContextStrokeRect(currentContex, myRect); UIImage* backgroundImage = (UIImage*)UIGraphicsGetImageFromCurrentImageContext(); [border setImage:backgroundImage];  UIGraphicsEndImageContext();  [self addSubview:border];}]]&gt;&lt;/script&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That's pretty much all there is to it. Let me know in the comments of any questions or comments you have on this.&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;Also, if you know of a better way to draw a border, I'm wide open for suggestions. This was the best way I could find.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-5390233817473301046?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/5390233817473301046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=5390233817473301046' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5390233817473301046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5390233817473301046'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/04/iphone-sdk-movable-and-resizable.html' title='iPhone SDK - Movable and resizable UIViews'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-4794711842045249809</id><published>2010-04-02T22:19:00.000-07:00</published><updated>2010-04-02T22:38:16.545-07:00</updated><title type='text'>Website sizes</title><content type='html'>Dear Web Developers of the World,&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let me introduce myself a little. I have a resolution of 1920x1200 on both my laptop and monitor. If you didn't know, that's pretty big. Probably the biggest resolution an average computer user is ever going to use. I use a large resolution because I like to have multiple windows open at once without having to minimize and hide windows. I absolutely do not like having horizontal scrollbars on webpages I am viewing. It takes away from the whole experience to have to scroll the window over as I'm reading, then scroll it back at the start of the new line. Obviously, I'm not alone in the hatred of horizontal-scrolling. Word-wrap is my evidence. I also happen to really love the Aero-Snap feature of Windows 7. (You know, the feature where you can dock a window to the left half or right half of the screen.) I love it so much, that I have installed scripts on both my Mac desktop and my Ubuntu laptop so I can use that feature on all my operating systems. I can't remember the last time I fully maximized a window and actually used it that way. I just love docking my windows to the side -- &lt;b&gt;especially&lt;/b&gt; my browser. I couldn't be the only person who does this. Windows 7 is becoming a fairly popular and very much loved operating system. People will soon find that they can have a webpage open on one side of the screen, and a word document open on the other side (a fairly common need for students or anyone else writing a paper or report of any kind). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With all of that said, I must ask: Why in the world do you, as a web developer, make your websites not resize down to half of 1920px properly? I mean, &lt;i&gt;seriously&lt;/i&gt;. Is it &lt;i&gt;really&lt;/i&gt; that hard? Having your page resize, properly I must add, to a 960px width is just not worth your time? I am starting to see this everywhere: Apple Developer page, OMG! Ubuntu, and many other pages I just stumbled upon while browsing the internet. It's getting out of hand. If it was just one or two websites that this happened on, I wouldn't have taken notice. But I'm frequently running into this that I just can't take it anymore. Get off your lazy rears and just fix the dang problem. It's not that hard. If you must shrink one of those annoying ads or trim down your stupid menu that no one likes, then do it. But please don't force me to scroll horizontally when it's not absolutely necessary. It doesn't make me want to come back. Seriously.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Thanks for listening,&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Joel Johnson&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-4794711842045249809?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/4794711842045249809/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=4794711842045249809' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/4794711842045249809'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/4794711842045249809'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/04/website-sizes.html' title='Website sizes'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-3178070819659699763</id><published>2010-03-22T22:14:00.000-07:00</published><updated>2010-03-22T22:16:05.067-07:00</updated><title type='text'>Clonezilla</title><content type='html'>Just stumbled across &lt;a href="http://clonezilla.org/"&gt;Clonezilla&lt;/a&gt;. It's an opensource alternative to Norton Ghost. It lets you backup your entire hard drive and reimage a disk rather quickly. They say that Clonezilla can clone an image to 40 different machines in 10minutes. Now THAT, is awesome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-3178070819659699763?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/3178070819659699763/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=3178070819659699763' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3178070819659699763'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3178070819659699763'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/03/clonezilla.html' title='Clonezilla'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-336872607963320602</id><published>2010-03-20T23:27:00.000-07:00</published><updated>2010-03-20T23:29:25.303-07:00</updated><title type='text'>Running a Software Business on 5 Hours</title><content type='html'>Just stumbled across this article titled, &lt;a href="http://www.kalzumeus.com/2010/03/20/running-a-software-business-on-5-hours-a-week/"&gt;Running a Software Business On 5 Hours a Week&lt;/a&gt;. Read it, it has some awesome advice.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-336872607963320602?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/336872607963320602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=336872607963320602' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/336872607963320602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/336872607963320602'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/03/running-software-business-on-5-hours.html' title='Running a Software Business on 5 Hours'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-1039291165787159851</id><published>2010-03-20T15:34:00.000-07:00</published><updated>2010-03-20T15:35:52.458-07:00</updated><title type='text'>Cheap TV Advertising</title><content type='html'>I just watched &lt;a href="http://slatev.com/video/how-i-ran-ad-fox-news/"&gt;this video&lt;/a&gt; today.&lt;div&gt;I thought it was pretty awesome. Opening up the way to allow no-named startups and such get a TV advertising spot pretty easy.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-1039291165787159851?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/1039291165787159851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=1039291165787159851' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/1039291165787159851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/1039291165787159851'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/03/cheap-tv-advertising.html' title='Cheap TV Advertising'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-3745623073749749751</id><published>2010-03-20T00:11:00.000-07:00</published><updated>2010-03-20T00:21:57.686-07:00</updated><title type='text'>Ubuntu 10.04</title><content type='html'>I've been very impressed with Ubuntu since 9.04 (Jaunty). I've been using Ubuntu as my primary OS for about a year and a half now, and ever since 9.10 (Karmic) came out, I've been hooked. I don't miss windows at all. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Today Ubuntu 10.04 Lucid Lynx Beta 1 was released. If you haven't been following, Lucid introduces new default themes, improved startup times, fix many-a-bugs, among other things.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's looking great. I'm really excited for the next release.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.ubuntu.com/testing/lucid/beta1"&gt;More Here&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-3745623073749749751?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/3745623073749749751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=3745623073749749751' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3745623073749749751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3745623073749749751'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/03/ubuntu-1004.html' title='Ubuntu 10.04'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-5016308063339920762</id><published>2010-01-11T09:50:00.001-08:00</published><updated>2010-01-11T09:50:58.242-08:00</updated><title type='text'>tunneling via svn</title><content type='html'>ssh -L fakeport:theirIp:realport uname@extip&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-5016308063339920762?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/5016308063339920762/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=5016308063339920762' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5016308063339920762'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5016308063339920762'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/01/tunneling-via-svn.html' title='tunneling via svn'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-8903001743528018986</id><published>2010-01-04T18:44:00.000-08:00</published><updated>2010-01-04T18:47:20.931-08:00</updated><title type='text'>Aero-snap-like feature with Compiz</title><content type='html'>&lt;a href="http://www.omgubuntu.co.uk/2009/11/aero-snap-ubuntu-linux.html"&gt;http://www.omgubuntu.co.uk/2009/11/aero-snap-ubuntu-linux.html&lt;/a&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I didn't to the edge of the screen part, but I made it when I press [Super]+[Left/Right] it docks to that side. Works well. It's a hack job, so it doesn't work as well as Windows 7's Aero Snap, but it does what I want it too. With this and DockbarX, I have everything I miss the most from the Windows world.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-8903001743528018986?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/8903001743528018986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=8903001743528018986' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/8903001743528018986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/8903001743528018986'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2010/01/aero-snap-like-feature-with-compiz.html' title='Aero-snap-like feature with Compiz'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-6954588875683670099</id><published>2009-12-28T20:42:00.000-08:00</published><updated>2009-12-28T20:46:16.467-08:00</updated><title type='text'>Auto Sort Script</title><content type='html'>I wrote an auto-sort script for the video files my camera creates. All I have to do is drop the files from the SD card into the Videos folder, run the script, it uses ffmpeg to convert them into mpeg files, then it moves them all into folders named by the date the video was recorded.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;#based on code found at:&lt;br /&gt;#http://www.opencodeproject.com/article.php/44/making+dvds+from+jvc+everio+mod+files+using+ubuntu+winff+avidemux+and+devede&lt;br /&gt;#ffmpeg line generated by WinFF&lt;br /&gt;#all other code written by Joel Johnson&lt;br /&gt;&lt;br /&gt;for file in `ls MOV*.MOD`&lt;br /&gt;do&lt;br /&gt;   number=${file#*V}    #last 3 should be "000-fff"&lt;br /&gt;   number=${number%.*}&lt;br /&gt;   number=`echo "ibase=16;obase=A;${number}" | bc`&lt;br /&gt;   echo "Converting ${file} to MOV${number}.MOD"&lt;br /&gt;   mv -f ${file} "MOV${number}.MOD"&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;for file in `ls MOV*.MOI`&lt;br /&gt;do&lt;br /&gt;   number=${file#*V}    #last 3 should be "000-fff"&lt;br /&gt;   number=${number%.*}&lt;br /&gt;   number=`echo "ibase=16;obase=A;${number}" | bc`&lt;br /&gt;   echo "Converting ${file} to MOV${number}.MOI"&lt;br /&gt;   mv -f ${file} "MOV${number}.MOI"&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;#for renumbering the new files for easy&lt;br /&gt;#avidemux processing&lt;br /&gt;#the following numbers the files 1-n&lt;br /&gt;#pardon the weird coding method, it's a hack job&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;currNum=1&lt;br /&gt;for file in `ls -v MOV*.MOI`&lt;br /&gt;do    &lt;br /&gt;   tempNum=$currNum&lt;br /&gt;   if [ "$tempNum" -lt 10 ]; then&lt;br /&gt;       tempNum=`echo 000${tempNum}`&lt;br /&gt;   elif [ "$tempNum" -lt 100 ];        then&lt;br /&gt;       tempNum=`echo 00${tempNum}`&lt;br /&gt;   elif [ "$tempNum" -lt 1000 ];       then&lt;br /&gt;       tempNum=`echo 0${tempNum}`&lt;br /&gt;   fi&lt;br /&gt;   echo "Converting ${file} to MOV_${tempNum}.MOD"&lt;br /&gt;&lt;br /&gt; MODDATE=$(stat -c %y $file)&lt;br /&gt; MODDATE=${MODDATE%% *} &lt;br /&gt;&lt;br /&gt; foldername="./${MODDATE}"&lt;br /&gt; mkdir $foldername&lt;br /&gt;&lt;br /&gt; filename="${foldername}/MOV_${tempNum}"&lt;br /&gt;   mv -f ${file} "${filename}.MOI"&lt;br /&gt; mv ${filename}.MOI ${foldername}&lt;br /&gt;&lt;br /&gt;   currNum=`echo $((currNum+1))`&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;currNum=1&lt;br /&gt;for file in `ls -v MOV*.MOD`&lt;br /&gt;do    &lt;br /&gt;   tempNum=$currNum&lt;br /&gt;   if [ "$tempNum" -lt 10 ]; then&lt;br /&gt;       tempNum=`echo 000${tempNum}`&lt;br /&gt;   elif [ "$tempNum" -lt 100 ];        then&lt;br /&gt;       tempNum=`echo 00${tempNum}`&lt;br /&gt;   elif [ "$tempNum" -lt 1000 ];       then&lt;br /&gt;       tempNum=`echo 0${tempNum}`&lt;br /&gt;   fi&lt;br /&gt;   echo "Converting ${file} to MOV_${tempNum}.MOD"&lt;br /&gt;&lt;br /&gt; MODDATE=$(stat -c %y $file)&lt;br /&gt; MODDATE=${MODDATE%% *} &lt;br /&gt;&lt;br /&gt; foldername="./${MODDATE}"&lt;br /&gt; mkdir $foldername&lt;br /&gt;&lt;br /&gt; filename="${foldername}/MOV_${tempNum}"&lt;br /&gt;   mv -f ${file} "${filename}.MOD"&lt;br /&gt;&lt;br /&gt; ffmpeg -i "${filename}.MOD" -f dvd -target ntsc-dvd -r 29.97 -s 720x480 -aspect 16:9 -b 8000kb -g 12 -mbd rd -trellis -mv0 -cmp 0 -subcmp 2 "${filename}.mpg" -timestamp now&lt;br /&gt;&lt;br /&gt;   currNum=`echo $((currNum+1))`&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-6954588875683670099?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/6954588875683670099/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=6954588875683670099' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/6954588875683670099'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/6954588875683670099'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/12/auto-sort-script.html' title='Auto Sort Script'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-2701779446254218840</id><published>2009-12-27T21:13:00.000-08:00</published><updated>2009-12-27T21:16:52.434-08:00</updated><title type='text'>New JVC camera</title><content type='html'>&lt;div&gt;My wife's parents just got me and my wife a JVC Everio S Video camera. We really like it a lot. It uses an SD card for storage. No hard drive, no tapes. It's wonderful. Unfortunately, it saves the videos as MOD files.  Ubuntu had a difficult time playing them. Both Movie Player and Gloobus-Preview struggled playing the videos back. VLC did a great job, but I didn't like that it was the only one. I found &lt;a href="http://www.opencodeproject.com/article.php/44/making+dvds+from+jvc+everio+mod+files+using+ubuntu+winff+avidemux+and+devede"&gt;this&lt;/a&gt; site that shows you step by step what to install to convert the files to a more usable file type and burn them to a DVD. I suggest checking it out.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-2701779446254218840?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/2701779446254218840/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=2701779446254218840' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/2701779446254218840'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/2701779446254218840'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/12/new-jvc-camera.html' title='New JVC camera'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-508823492589753921</id><published>2009-07-06T00:17:00.001-07:00</published><updated>2009-07-06T00:17:15.985-07:00</updated><title type='text'>Songbird in Jaunty</title><content type='html'>&lt;code&gt;sudo apt-get remove libvisual-0.4-plugins&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-508823492589753921?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/508823492589753921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=508823492589753921' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/508823492589753921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/508823492589753921'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/07/songbird-in-jaunty.html' title='Songbird in Jaunty'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-5364854613664582808</id><published>2009-04-01T00:46:00.000-07:00</published><updated>2009-04-01T00:50:29.239-07:00</updated><title type='text'>Link Linux Documents/etc folders with Windows</title><content type='html'>ln -s /mnt/windows/Users/joeljohnson/Documents/ /home/joel/Documents&lt;br /&gt;ln -s /mnt/windows/Users/joeljohnson/Pictures/ /home/joel/Pictures&lt;br /&gt;ln -s /mnt/windows/Users/joeljohnson/Music/ /home/joel/Music&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-5364854613664582808?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/5364854613664582808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=5364854613664582808' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5364854613664582808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5364854613664582808'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/04/link-linux-documentsetc-folders-with.html' title='Link Linux Documents/etc folders with Windows'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-4145859969240756611</id><published>2009-04-01T00:43:00.000-07:00</published><updated>2009-04-01T00:44:47.118-07:00</updated><title type='text'>Mount NTFS</title><content type='html'>&lt;code&gt;sudo gedit /etc/fstab&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;add:&lt;br /&gt;"&lt;code&gt;/dev/sda1    /mnt/windows    ntfs    defaults    0    0&lt;/code&gt;"&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-4145859969240756611?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/4145859969240756611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=4145859969240756611' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/4145859969240756611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/4145859969240756611'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/04/mount-ntfs.html' title='Mount NTFS'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-7859275213683670249</id><published>2009-02-10T14:48:00.001-08:00</published><updated>2009-02-10T14:48:58.641-08:00</updated><title type='text'>Ubuntu 8.10 JDK</title><content type='html'>&lt;code&gt;&lt;span class="amc_default"&gt;sudo apt-get install sun-java6-jre sun-java6-jdk sun-java6-plugin&lt;/span&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-7859275213683670249?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/7859275213683670249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=7859275213683670249' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/7859275213683670249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/7859275213683670249'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/02/ubuntu-810-jdk.html' title='Ubuntu 8.10 JDK'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-5987894464345694971</id><published>2009-02-03T09:56:00.000-08:00</published><updated>2009-02-03T10:28:37.877-08:00</updated><title type='text'>Ubuntu Update of Wireless drivers for T61p</title><content type='html'>&lt;code&gt;sudo apt-get install subversion&lt;br /&gt;svn co https://svn.madwifi-project.org/madwifi/trunk&lt;br /&gt;cd trunk/&lt;br /&gt;sudo make&lt;br /&gt;sudo make install&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;restart your computer and now you can delete the ~/trunk folder&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-5987894464345694971?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/5987894464345694971/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=5987894464345694971' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5987894464345694971'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5987894464345694971'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/02/ubuntu-update-of-wireless-drivers-for.html' title='Ubuntu Update of Wireless drivers for T61p'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-8744348739034540056</id><published>2009-01-22T21:41:00.000-08:00</published><updated>2009-01-22T21:42:56.939-08:00</updated><title type='text'>MS Office 2007 Converter</title><content type='html'>&lt;a href="http://katana.oooninja.com/w/odf-converter-integrator"&gt;odf-converter-integrator&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I'm hoping it'll work! I'm still installing...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-8744348739034540056?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/8744348739034540056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=8744348739034540056' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/8744348739034540056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/8744348739034540056'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/01/ms-office-2007-converter.html' title='MS Office 2007 Converter'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-2988845574827000555</id><published>2009-01-21T16:09:00.000-08:00</published><updated>2009-01-21T16:12:31.321-08:00</updated><title type='text'>MacOSX VirtualBox - Fail</title><content type='html'>Many people have been able to get MacOSX running in VMWare. So I decided to try to get it running in VirtualBox using that same image... Well... it hangs up during boot. :( It was worth a shot!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-2988845574827000555?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/2988845574827000555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=2988845574827000555' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/2988845574827000555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/2988845574827000555'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/01/macosx-virtualbox-fail.html' title='MacOSX VirtualBox - Fail'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-6604689437835564621</id><published>2009-01-15T22:45:00.000-08:00</published><updated>2009-01-15T22:46:09.555-08:00</updated><title type='text'>4gb ram in 32bit Ubuntu</title><content type='html'>&lt;a href="http://samiux.wordpress.com/2008/06/15/use-more-than-3gb-ram-on-32-bit-ubuntu-804/"&gt;http://samiux.wordpress.com/2008/06/15/use-more-than-3gb-ram-on-32-bit-ubuntu-804/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-6604689437835564621?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/6604689437835564621/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=6604689437835564621' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/6604689437835564621'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/6604689437835564621'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/01/4gb-ram-in-32bit-ubuntu.html' title='4gb ram in 32bit Ubuntu'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-3885735322984584433</id><published>2009-01-13T23:40:00.001-08:00</published><updated>2009-01-13T23:40:59.962-08:00</updated><title type='text'>Auto-Login Windows - Auto-Lock</title><content type='html'>&lt;a href="http://forums.techarena.in/windows-xp-support/621461.htm"&gt;http://forums.techarena.in/windows-xp-support/621461.htm&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-3885735322984584433?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/3885735322984584433/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=3885735322984584433' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3885735322984584433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3885735322984584433'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2009/01/auto-login-windows-auto-lock.html' title='Auto-Login Windows - Auto-Lock'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-2029381760319714557</id><published>2008-12-28T00:23:00.000-08:00</published><updated>2008-12-28T00:26:36.286-08:00</updated><title type='text'>Non-Realistic Photo (NPR) Rendering - A New Found Love</title><content type='html'>I was shown &lt;a href="http://uk.youtube.com/watch?v=gT9qU_fJNuw"&gt;this video&lt;/a&gt; today of a WYSIWYG NPR Rendering system. I'm just imagining a full fledged game rendered this way. Kindof like &lt;a href="http://en.wikipedia.org/wiki/XIII_(video_game)"&gt;XVIII&lt;/a&gt; but even more. Kindof like the snow rendering near the end of the video. That would be AWESOME. I shall learn to do this, and one day it will happen.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-2029381760319714557?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/2029381760319714557/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=2029381760319714557' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/2029381760319714557'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/2029381760319714557'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/12/non-realistic-photo-npr-rendering-new.html' title='Non-Realistic Photo (NPR) Rendering - A New Found Love'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-8916276366828303688</id><published>2008-12-27T21:44:00.000-08:00</published><updated>2008-12-27T22:02:34.814-08:00</updated><title type='text'>iRecipes - Old Project Revisited</title><content type='html'>I'm starting over on an old project I started in C# forever ago. Code name - iRecipes. I call it that because I designed it to have the same UI as iTunes (you must admit, that is something Apple does well, UI). Also, it's a Recipe organizer. The idea is to make a quick and easy way to store/retrieve your recipes.&lt;div&gt;&lt;br /&gt;I'll post a screenshot of the one I made in C#, as my new one... well, I just started it. This time I'm making it in Adobe &lt;a href="http://www.adobe.com/products/flex/"&gt;Flex&lt;/a&gt;/&lt;a href="http://www.adobe.com/products/air/"&gt;Air&lt;/a&gt;. I'm doing this for two main reasons: First, I'm learning a new hot language, I get to add another tool to my belt. Second, I have a few friends who use a Mac who have been bugging me to finish this project. As awesome as Mono is, it's just not good enough yet. So C# was out of the question. So, I chose Flex.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's what my old one looked like (click to enlarge):&lt;/div&gt;&lt;div&gt;&lt;a href="http://i17.photobucket.com/albums/b92/xahrepap/iRecipe.png"&gt;&lt;img src="http://s17.photobucket.com/albums/b92/xahrepap/th_iRecipe.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The new one will look different, but it'll have the same idea.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;I'll post a brainstorm of features and ideas I plan to have, and eventually a road map.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Post any suggestions in the comments&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-8916276366828303688?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/8916276366828303688/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=8916276366828303688' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/8916276366828303688'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/8916276366828303688'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/12/irecipes-old-project-revisited.html' title='iRecipes - Old Project Revisited'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-3861485687325566115</id><published>2008-12-10T14:32:00.001-08:00</published><updated>2008-12-10T14:32:46.035-08:00</updated><title type='text'>Free X-Chat for Windows</title><content type='html'>http://www.silverex.org/news/&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-3861485687325566115?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/3861485687325566115/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=3861485687325566115' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3861485687325566115'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3861485687325566115'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/12/free-x-chat-for-windows.html' title='Free X-Chat for Windows'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-2184405606669799945</id><published>2008-10-13T20:40:00.001-07:00</published><updated>2008-10-13T20:43:16.066-07:00</updated><title type='text'>Ubuntu - Transparent Titlebars - REMOVED</title><content type='html'>I didn't really like how the titlebars would go transparent when they lost focus.  So I found how to get rid of that effect today:&lt;br /&gt;&lt;code&gt;terminal-&gt; "gconf-editor"&lt;br /&gt;"/apps/gwd/" -&gt; metacity_theme_opacity = 1&lt;/code&gt;&lt;br /&gt;now it looks a lot better :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-2184405606669799945?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/2184405606669799945/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=2184405606669799945' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/2184405606669799945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/2184405606669799945'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/10/ubuntu-transparent-titlebars-removed.html' title='Ubuntu - Transparent Titlebars - REMOVED'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-6187873582841715993</id><published>2008-10-13T20:06:00.000-07:00</published><updated>2008-10-13T20:10:12.079-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='songbird'/><category scheme='http://www.blogger.com/atom/ns#' term='ubuntu'/><title type='text'>Songbird Problem - FIXED</title><content type='html'>I was having problems in Ubuntu with Songbird.  If I had it open first, nothing else would play sounds (Firefox embedded videos, aMSN, etc).  And if I had Firefox open first, Songbird wouldn't work.  But I just fixed it by typing "gstreamer-properties" in the terminal, and changing the output plugin to "ALSA".&lt;br /&gt;&lt;br /&gt;&lt;a href="http://getsongbird.com/"&gt;Get Songbird!&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-6187873582841715993?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/6187873582841715993/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=6187873582841715993' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/6187873582841715993'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/6187873582841715993'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/10/songbird-problem-fixed.html' title='Songbird Problem - FIXED'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-5545231265043903661</id><published>2008-10-11T23:38:00.001-07:00</published><updated>2008-10-11T23:50:25.698-07:00</updated><title type='text'>Back to something important - Dashboard</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_1sUciF-HOg8/SPGdfQcfJ0I/AAAAAAAAABE/GuEzy4ChA90/s1600-h/db.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_1sUciF-HOg8/SPGdfQcfJ0I/AAAAAAAAABE/GuEzy4ChA90/s400/db.png" alt="" id="BLOGGER_PHOTO_ID_5256155400434034498" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Ok, so I've had my fun, and if anyone reads this, I probably bored them with my whole Ubuntu episode.&lt;br /&gt;&lt;br /&gt;I started back on my &lt;a href="http://joel-llamaduck.blogspot.com/2008/09/llamaduck-dashboard-almost-finished.html"&gt;Dashboard Application&lt;/a&gt; again today.  I added a very simple Twitter gadget, and I started on a scripture search gadget.&lt;br /&gt;&lt;br /&gt;Again here's my list of gadgets I want to have done (! = finished):&lt;br /&gt;-Weather&lt;br /&gt;-Calander&lt;br /&gt;-Daily Planner&lt;br /&gt;-Alarm&lt;br /&gt;-Lyric search&lt;br /&gt;-Scripture search&lt;br /&gt;-Language translator&lt;br /&gt;-Dictionary&lt;br /&gt;-Thesaurous&lt;br /&gt;-Spell Check&lt;br /&gt;-Wikipedia&lt;br /&gt;-Quick Email&lt;br /&gt;-YouTube&lt;br /&gt;-Less basic Twitter (get updates from friends)&lt;br /&gt;! Basic Twitter (see your current status, and change it)&lt;br /&gt;! Sticky Notes&lt;br /&gt;! Calculator&lt;br /&gt;&lt;br /&gt;It's quite the list, but several of them will be mixed together.  If you have any suggestions, please let me know!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-5545231265043903661?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/5545231265043903661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=5545231265043903661' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5545231265043903661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/5545231265043903661'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/10/back-to-something-important-dashboard.html' title='Back to something important - Dashboard'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_1sUciF-HOg8/SPGdfQcfJ0I/AAAAAAAAABE/GuEzy4ChA90/s72-c/db.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-2139693711428311018</id><published>2008-10-09T20:40:00.000-07:00</published><updated>2008-10-09T20:46:25.907-07:00</updated><title type='text'>Ubuntu - Just the way I like it</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_1sUciF-HOg8/SO7Oyy26-LI/AAAAAAAAAA8/FrrfQHgepJA/s1600-h/Screenshot.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_1sUciF-HOg8/SO7Oyy26-LI/AAAAAAAAAA8/FrrfQHgepJA/s400/Screenshot.png" alt="" id="BLOGGER_PHOTO_ID_5255365187228858546" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;So I've got mono working, so I've pretty much got Ubuntu running the way I want it to be. :)  I'm currently looking for a way to rip streaming videos from Hulu and/or NBC.com.  Doesn't look like there's anything.  I don't even care if the comercials are still there, I just want something so I don't have to put up with buffering or so I can watch videos offline (Like if I'm in the car or something).&lt;br /&gt;&lt;br /&gt;There are a few glitches in mono though.  Example: In that screenshot one of the labels is off.  But if you take a looks at the form designer in the background, it's aligned properly.  Annoying, I know.  I'm wondering if I really have everything installed right for mono, because mono.com has some pretty slick screen shots, and I don't see any problems like what I'm seeing, but of course they wouldn't put up any glitches when they're showing off.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-2139693711428311018?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/2139693711428311018/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=2139693711428311018' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/2139693711428311018'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/2139693711428311018'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/10/ubuntu-just-way-i-like-it.html' title='Ubuntu - Just the way I like it'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_1sUciF-HOg8/SO7Oyy26-LI/AAAAAAAAAA8/FrrfQHgepJA/s72-c/Screenshot.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-3969600382968158788</id><published>2008-10-08T10:04:00.001-07:00</published><updated>2008-12-28T00:09:15.783-08:00</updated><title type='text'>Install Mono 2.0 on Ubuntu</title><content type='html'>&lt;code&gt;sudo apt-get install libmono-accessibility2.0-cil libmono-cairo2.0-cil libmono-corlib2.0-cil libmono-data-tds2.0-cil libmono-microsoft-build2.0-cil libmono-peapi2.0-cil libmono-security2.0-cil libmono-sqlite2.0-cil libmono-system-data2.0-cil libmono-system-runtime2.0-cil libmono-system-web2.0-cil libmono-system2.0-cil libmono-winforms2.0-cil libmono2.0-cil mono-gmcs libmono-ldap2.0-cil libmono-system-messaging2.0-cil&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-3969600382968158788?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/3969600382968158788/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=3969600382968158788' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3969600382968158788'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3969600382968158788'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/10/install-mono-20-on-ubuntu.html' title='Install Mono 2.0 on Ubuntu'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-7667245531760874033</id><published>2008-10-07T23:09:00.000-07:00</published><updated>2008-10-08T00:12:01.880-07:00</updated><title type='text'>Ubuntu</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_1sUciF-HOg8/SOxZp0amVdI/AAAAAAAAAA0/ZTfwBX6BW3w/s1600-h/visualstudio.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_1sUciF-HOg8/SOxZp0amVdI/AAAAAAAAAA0/ZTfwBX6BW3w/s320/visualstudio.png" alt="" id="BLOGGER_PHOTO_ID_5254673440214242770" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I'm moving on in life.  I have recently installed Ubuntu 8.04 on my laptop using Wubi.  Before I was always saying that Linux isn't far along enough for the typical desktop user.  Which I still don't think it is, but it just might be far enough along for me.&lt;br /&gt;&lt;br /&gt;The biggest thing that has held me back from Linux is that lack of NICE developer tools.  And by nice, I mean that I'm a Visual Studio user... that's what I want in Linux. :)  At least, something to rival it.  Nothing has come close to it, no not even eclipse... in fact, I hate eclipse.&lt;br /&gt;&lt;br /&gt;So, my friend linked me to a site that showed how you can seamlessly run a Windows virtual machine in Linux.  Which sounded pretty cool, I could do that.  Run Visual Studio in a VM, and make it look like it's running in natively on my computer?   I'm all for that.  I own a legal copy of Windows anyway.&lt;br /&gt;&lt;br /&gt;So I downloaded the Ubuntu 8.04 x64 iso, burned it to a CD and installed it on my Windows partition using Wubi.  That lasted about a night.  64bit support is poop right now aparently.  I tried installing a few 32bit apps (because there wasn't a 64bit edition) and it yelled at me, and I read I had to manually install libraries and stuff.  Sure, that's okay for a Linux junkie, but I'm not going to put up with that, especially when I'm still learning to use Linux.  So I uninstalled and installed the 32bit version.  Which is disappointing, becuase now it'll only use 3gb of my 4gb of ram.  And since I'll be using a virtual machine a lot, that gig of ram would be nice.  OH WELL.  My own fault for being lazy :)&lt;br /&gt;&lt;br /&gt;After everything was set up, I went on my way installing everything I wanted.  I installed VirtualBox and then Windows XP Pro on top of that.  I messed around with some 3rd party seamless stuff I was reading on the internet.  Then I discovered that VirtualBox has a seamless mode built in... BINGO!  or so I thought.  The seamless mode is supposed to blend the two desktops together, making it look like all the windows and the taskbar are all in the same environment as your Linux windows and panels.  It did that... but the two OS's were constantly fighting over who drew what.  I figure I did something wrong in setting it up... but I didn't want to fight anymore.  But I did discover that there was a mode in VirtualBox that shared a clipboard and let me set the VM window size to whatever I want, and it would adjust the resolution to whatever I wanted.  So I decided just to use that and put Visual Studio in full screen mode.   It actually feels completely natural doing it that way.  The only problem is memory usage is pretty high.  I really wish that Visual Studio worked well in WINE and then the compiled EXEs just run in Mono, but no, it doesn't.  Blah.  But this way really isn't that bad.  I named the virtual machine "Visual Studio 2008" so that it would appear as such in on my task panel in Ubuntu.  It totally feels natural to me now.&lt;br /&gt;&lt;br /&gt;I also installed Songbird for my mp3 player, VLC for my movie player, aMSN for chat (I really don't like pidgen, and I only use MSN anyway), and Thunderbird for my email.  I was able to find a deb package for Songbird &lt;a href="http://getdeb.agetta.de/ubuntu/hardy/so/songbird_0.7.0-0%7Egetdeb1_i386.deb"&gt;here&lt;/a&gt;.  Everything else I got using the "Add-Remove" feature.&lt;br /&gt;&lt;br /&gt;Something really cool that was shown to me was Envy.  Which is a script/applicatoin that finds and installs the best drivers for your video card.  Which is AWESOME.  I got that simply by typing "sudo apt-get install envyng-gtk" into the terminal, which installs a shortcut in the System Tools menu.&lt;br /&gt;&lt;br /&gt;The last thing was Mono.  Ironically enough, I read that Mono 2.0 came out today on slashdot.  What luck.  The only problem is that stinking novell doesn't have a DEB package for it.  Stupid.  REALLY stupid.  So I poked around for awhile to no avail.  My brother was finally able to show me what billion libs to install using apt-get.  THAT is why I think Linux still has a way to go.  I don't care what your arguement is in the whole GUI -VS- Console war, the fact is: it's much easier to double click a stinking installer and hit a next button a few times, than it is to play this STUPID game that almost every Linux app makes you play in the console.  "Now what's the command?... what's the library?..."  stupid.  It's stupid.  Why must there be an installer for opensuse, redhat, and debian?  Why can't we just have ONE?  Seriously, is it really that hard?  Apt-get just doesn't cut the cake.&lt;br /&gt;&lt;br /&gt;Now what I need to do is figure out a way to make it so when I compile a C# app, it auto transfers the EXE to a folder on ubuntu and runs it there using mono.  THAT would rock.  But for now, I'll live with what I have.&lt;br /&gt;&lt;br /&gt;The best part is... after I got it all the way I wanted and felt like I could actually USE Linux, and was almost to the point where I was going to say "I'm about ready to drop Windows" (except for games, of course...) I put Linux to sleep.  when I tried to resume... NOTHING, blackness.  Lameness.  I let it sit for a bit, trying to recover.  Finally I forced it to power off, then powered it back on.  It would boot half way up, then sit in some console thingy.  Never booting into Gnome.  Since I'm pretty much a Linux newbie, I had no idea what to do.  I searched the internet, and someone had the EXACT same problem... I tried his solution and.... it pretty much killed my linux install.  BRAVO to whomever you are out there.  I can't really blame you, because it was probably my stupididy that did it, but I have to have someone to blame, right?&lt;br /&gt;&lt;br /&gt;At this point, I've got everything back to where I had it before, except I don't have Mono 2.0 installed....  I just don't remember what I have to install.  BLAH.  This time I'll learn and post it here when I figure it all out.   Maybe by then someone will have a deb package for me to use.&lt;br /&gt;&lt;br /&gt;Well, that's my Linux adventure for the week!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-7667245531760874033?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/7667245531760874033/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=7667245531760874033' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/7667245531760874033'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/7667245531760874033'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/10/ubuntu.html' title='Ubuntu'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_1sUciF-HOg8/SOxZp0amVdI/AAAAAAAAAA0/ZTfwBX6BW3w/s72-c/visualstudio.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-784249104131815467</id><published>2008-09-23T19:16:00.000-07:00</published><updated>2008-09-26T10:17:18.125-07:00</updated><title type='text'>LlamaDuck Dashboard almost finished!</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_1sUciF-HOg8/SNmkBeGerPI/AAAAAAAAAAs/WfQjI0R04F0/s1600-h/Llamaduck.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer;" src="http://3.bp.blogspot.com/_1sUciF-HOg8/SNmkBeGerPI/AAAAAAAAAAs/WfQjI0R04F0/s320/Llamaduck.jpg" alt="" id="BLOGGER_PHOTO_ID_5249407185844088050" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;My Dashboard application is now pretty much done.  I've been playing around with it all day, haven't had a crash yet.  I just need to make a bunch of gadgets, and continue debugging.&lt;br /&gt;&lt;br /&gt;You can now change the background color and adjust how transparent you want the background to be as well. I also put a LlamaDuck watermark in the background, which I think looks really good there.&lt;br /&gt;&lt;br /&gt;All your settings and the position of all your gadgets are saved, so if you close out or restart your computer, it's all in the same place you left it.  I also made it so if you close a gadget, it will stay closed until you reopen it manually (Rightclick the blackness -&gt; Gadgets -&gt; Gadget you want to open)&lt;br /&gt;&lt;br /&gt;I'm going to make some gadgets to launch off with, here's my list:&lt;br /&gt;-Daily Planner&lt;br /&gt;-Alarm&lt;br /&gt;-Lyric search&lt;br /&gt;-Language translator&lt;br /&gt;-Dictionary&lt;br /&gt;-Thesaurus&lt;br /&gt;-Spell Check&lt;br /&gt;-Wikipedia&lt;br /&gt;-Quick Email&lt;br /&gt;-YouTube search&lt;br /&gt;&lt;br /&gt;I also plan on making "Hot corners", so when you put the mouse in one of the corners of the screen (Which one, all, or none, will be a user setting) it'll pop up the Dashboard, then when you place your mouse back into a corner again, it'll close back down.&lt;br /&gt;&lt;br /&gt;Any other suggestions?  Email me!&lt;br /&gt;&lt;a class="linkification-ext" href="mailto:johnson.joel.86@gmail.com" title="Linkification: mailto:johnson.joel.86@gmail.com"&gt;johnson.joel.86@gmail.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-784249104131815467?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/784249104131815467/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=784249104131815467' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/784249104131815467'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/784249104131815467'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/09/llamaduck-dashboard-almost-finished.html' title='LlamaDuck Dashboard almost finished!'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_1sUciF-HOg8/SNmkBeGerPI/AAAAAAAAAAs/WfQjI0R04F0/s72-c/Llamaduck.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-5275464027504437639.post-3488825052331348540</id><published>2008-09-21T13:34:00.000-07:00</published><updated>2008-09-22T00:37:37.617-07:00</updated><title type='text'>New Project - Gadget Manager</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://i17.photobucket.com/albums/b92/xahrepap/gadgets.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px;" src="http://i17.photobucket.com/albums/b92/xahrepap/gadgets.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;In the last ten weeks I've been using Vista.  At first I didn't like the side bar, because I just didn't really see a reason for it.  But I decided to try it out for a while.  I since then have noticed more and more reasons why I like it, and been noticing what else I would want with it (planner, notes, system monitor, email, etc).  But I never really liked having all those things constantly visible in the sidebar.  So with gadgets such as notes or a daily planner, I wouldn't use, because it didn't want them in the way.&lt;br /&gt;&lt;br /&gt;Early this last week I was with my friend, who uses a Mac (I haven't had as much experience with mac os X as I would like).  My friend was doing her Spanish homework, there was a word she couldn't remember, so she popped up her widgets, typed it into her translator widget, and then closed the widgets.  Suddenly I knew what I wanted.  I tried to find a way to do that with the Vista side bar... of course nothing.  The closest I could find was when you press the WindowsKey + Space bar it'll bring focus to the gadgets.  But Mac fades the screen out when you do that, so it's easier to tell what you're doing.  Vista's sidebar just didn't cut the cake for me.&lt;br /&gt;&lt;br /&gt;I tried out Google Gadgets.  I liked it well enough, but it still just didn't do what I wanted it to.&lt;br /&gt;&lt;br /&gt;So I decided that I would make my own.  One that I could assign a key combination to (like ctr-space) to fade the screen and pop up my gadgets.  Then hide them when I'm done.  Also, I wanted one that I could program my gadgets in C#, because I love C#.  So I got started.&lt;br /&gt;&lt;br /&gt;I found some code for a &lt;a href="http://www.codeproject.com/KB/cs/CSLLKeyboardHook.aspx"&gt;low level keyboard hook on CodeProject.com&lt;/a&gt;.  And I also made it so you could compile a windows form to a DLL, put it in the gadgets folder and it would open like I wanted to.&lt;br /&gt;&lt;br /&gt;But now I've ran into a problem.  It's a strange problem I've never seen before.  If I run the program without debugging, it'll just crash randomly (No exception, just crashes).  Or if I run with debugging I get this:&lt;br /&gt;&lt;br /&gt;CallbackOnCollectedDelegate was detected&lt;br /&gt;Message: A callback was made on a garbage collected delegate of type 'Llamaduck-Gadgets!Llamaduck_Gadgets.GlobalKeyboardHook+keyboardHookProc::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.&lt;br /&gt;&lt;br /&gt;Apparently there's a problem with my usage of delegates.  But I can't figure out what's wrong.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; PROBLEM FIXED!  Aparently, what the code was doing was passing the delegate to a DLL method, which wasn't a .net dll.  So when I was making the call, I was making the delegate in the the scope of the method that was calling the dll method (I hope that makes sense).  So it would make the DLL call, then the method in my program would end, and the garbage collector would see the delegate and think it was done, because the managed part of the code was done with it, even though the external DLL wasn't done with it.  So the garbage collecetor would collect the delegate prematurly.  I fixed it by creating the delegate in the class scope, rather than the method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5275464027504437639-3488825052331348540?l=blog.joelj.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.joelj.com/feeds/3488825052331348540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=5275464027504437639&amp;postID=3488825052331348540' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3488825052331348540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/5275464027504437639/posts/default/3488825052331348540'/><link rel='alternate' type='text/html' href='http://blog.joelj.com/2008/09/new-project-gadget-manager.html' title='New Project - Gadget Manager'/><author><name>Joel</name><uri>http://www.blogger.com/profile/14900253966317833651</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://3.bp.blogspot.com/_1sUciF-HOg8/SezwwNPk6FI/AAAAAAAAALc/6pyGaAiD6VQ/S220/Me.jpg'/></author><thr:total>0</thr:total></entry></feed>
