Subscribe

Inside Shoes 2

December 6th 07:59
by why

The second “stable” release of Shoes has flown. We still have a lot to do. But, hey. It’s happening, right?

This time I have some detailed release notes, with screenshots and code fragments to help sort it all out.

Inside Shoes 2: The second release of Shoes (called “Raisins” by many) is a culmination of a year of feature-filled additions to the first, experimental release of Shoes (titled “Curious”.)

This release adds a built-in manual, an error console, RubyGems integration, simple asynchronous downloads, an in-memory and database-backed image cache, support for external fonts, and, most prominently, its own unique library for packaging apps into little executables. OS X support is significantly better, as we switched from Carbon to Cocoa.

A lot of these features were fleshed out here on the blog, with your responses proving very so very valuable indeedy.

So, thanks for following along. Shoes 3 ("Policeman") will come around in, oh, January, I’d hazard.

The Frustrating Magical Aspect

December 4th 17:29
by why

Julien Léonard: Actually, a graphic is foremost a composition of basic shapes and color. It is not their absolute values (that is absolute spatial and color coordinates) but their relations that matters. This is even more true because our visual perceptive chain processes its inputs in a relative way, as paradoxical visual games highlight it.

Seven Years Later, Proce55ing Leaves Beta!

November 25th 07:20
by why

Daniel Shiffman: At New York University’s graduate ITP program, Processing is taught alongside its sister project Arduino and PHP as part of the foundation course for 100 incoming students each year. At UCLA, undergraduates in the Design | Media Arts program use Processing to learn the concepts and skills needed to imagine the next generation of web sites and video games. At Lincoln Public Schools in Nebraska and the Phoenix Country Day School in Arizona, middle school teachers are experimenting with Processing to supplement traditional algebra and geometry classes.

Running Hot

November 22nd 16:38
by why

Yes-s-s, Zed takes me on! Here’s a good part:

Zed Shaw: Why actually blessed me with his presence during one of my hacking sessions and made me feel smarter by association. I showed him Ragel (which he used to write Hpricot), and showed him some vim tricks, and he talked to Obie. It was great just having him warming the air near me.

A Costly Parade

November 21st 07:59
by why

Adam Wiggins: First, Rubyists love elegance.

Daniel Lyons: Every programmer worth a damn thinks they love elegance.

Something Like PyArg_ParseTuple For Ruby

November 17th 23:58
by why
 rb_arg_list args;
 /* "k" means Class, "h" means Hash */
 switch (rb_parse_args(argc, argv, "kh,h,", &args))
 {
   case 1: /* "kh" - style(Link, :background => white) */ break;
   case 2: /* "h"  - style(:width => "100%") */ break;
   case 3: /* ""   - style() => {...hash of styles...} */ break;
 }

Hpricot Strikes Back

November 3rd 19:13
by why

This fruit is tiny, shiny and can be spit-polished in a single weekend.

Mixing Our Way Out Of Instance Eval?

October 6th 17:36
by why
 require 'mixico'

 def Builder.capture &blk
   mix_eval(self, &blk)
 end

Textarea Resize And Curly Quotes For Conkeror

September 27th 22:29
by why
 function resize_textarea_up(field) {
   var h = field.offsetHeight;
   if (h > 120)
     field.style.height = (h - 60) + "px";
 }
 function resize_textarea_down(field) {
   field.style.height = (parseInt(field.offsetHeight) + 60) + "px";
 }
 interactive(
   "resize-textarea-up",
   "Resize a textarea to be smaller.",
   function (I) call_on_focused_field(I, resize_textarea_up)
 );
 interactive(
   "resize-textarea-down",
   "Resize a textarea to be taller.",
   function (I) call_on_focused_field(I, resize_textarea_down)
 );
 define_key(content_buffer_textarea_keymap, "C-up", "resize-textarea-up", $category = "Movement");
 define_key(content_buffer_textarea_keymap, "C-down", "resize-textarea-down", $category = "Movement");

A Legend Never To Be Solved

September 25th 06:33
by why

Documents Reveal Django Pony, Caught In Tail Of Lies

September 15th 06:07
by why

Sorting Out Libskia

September 9th 18:09
by why

Vladimir Vukićević: Another graphics library, Skia, has recently appeared as part of the Google Chrome code drop. It’s unfortunate that Google felt they needed to develop their own alternative in a closed fashion instead of joining an existing open source project. The Cairo project, and through it the many open source projects that depend on it, could have benefitted from the work that was done on Skia behind closed doors. Even worse, unlike most of the rest of the Chrome code, Skia is licensed under the Apache Public License v2.0. This creates difficulties in being able to reuse the Skia code in most projects.

However, on a happy note, hopefully it will ignite a performance race between itself and Cairo. I also wonder if Cairo will ever pick up what Skia has in the way of effects and animation. Cairo does have filters, gradients. But not blurs and lighting effects.

The biggest obstacle to using Skia on its own, though, is that Skia is really only partially released. It’s a 403. Allegedly, some folks were able to nab the source during a brief window on March 4th of last year. And the source code in the Chrome tree is a snapshot that seems incomplete. For example, much of the native code (to paint directly to X11, Windows, OS X contexts) seems missing.

For my part, I’d like to see how Shoes would run if forked to be Skia-powered. Can’t seem to hook it all up just yet.


Skia can be built seperately, though.

$ git clone git://github.com/why/skistrap.git
$ cd skistrap
$ make fetch
$ make

Presuming you have the includes and libs for libpng, libjpeg, libgif and libX11, you’ll end up with libskia.so.

There’s also a make test, but I haven’t got it hooked up to X11 quite yet, as there’s no ports/SkOSWindow_Unix.cpp or the like. And it looks like the GL bindings it uses are for other platforms.

The Funny Chip

August 28th 19:53
by why

Henri Bergson: This is just why the tragic poet is so careful to avoid anything calculated to attract attention to the material side of his heroes. No sooner does anxiety about the body manifest itself than the intrusion of a comic element is to be feared. On this account, the hero in a tragedy does not eat or drink or warm himself. He does not even sit down any more than can be helped. To sit down in the middle of a fine speech would imply that you remembered you had a body. Napoleon, who was a psychologist when he wished to be so, had noticed that the transition from tragedy to comedy is effected simply by sitting down.

Oh, is that all? Merely take a seat and it’s comedy? Hot socks. I’m afraid we have seriously overdone it. Prevailing notions of today dictate that a sit must be accompanied by a stamp of the foot, three Porky Pig impersonations and an offstage fart. How outmoded is this Napoleon?

Threaded XMLHttpRequest In Shoes

August 15th 17:36
by why

Threads can be tough and don’t suit beginners very well. And, well, Ruby threads can tie up the main app thread.

So, Shoes steals the underpinnings of Ajax to give you asynchronous downloads without needing to get into threading. Many of the young Sneakers are building Twitter and Flickr apps; it seemed the morally upright thing to do. In addition, I was able to use these HTTP threads to load remote images in the background. So, in Shoes, images loaded from the web will appear as they load.

Here’s the simple-downloader.rb from the samples that come with Shoes:

To achieve this, Shoes uses platform code for both threading and HTTP. On Windows, CreateThread and WinHTTP. On Linux, pthread and curl. And, on OS X, NSURLDownload — which does the threading for you.

Downloading is reduced to a single line:

Shoes.app { download "http://shoooes.net/shoes.png", :save => "shoes.png" }

This happens asynchronously, so shoes.png won’t be there yet when this method ends. It might be huge. It might appear an hour later. You can attach a finish event to be notified when the download is complete.

Shoes.app do
  download "http://shoooes.net/shoes.png", :save => "shoes.png" do |dl|
    alert "Scuse me. Your shoes.png has arrived."
  end
end

Omit the :save option and you can get back the download as a string.

Shoes.app do
  download "http://hacketyhack.net/pkg/osx/shoes" do |dl|
    alert "The latest OS X download is: #{dl.response.body}"
  end
end

You can also attach :method, :headers and :body options to the download, if you want to customize the request beyond that. I studied XMLHttpRequest closely and tried to be sure the same things could be done with this.


As for events, you get four of them: start, progress, finish and error. You can either pass proc objects in as options:

Shoes.app do
  url = "http://shoooes.net/dist/shoes-0.r905.exe"
  status = para "Downloading #{url}"

  download url, :save => "shoes.exe",
    :start => proc { |dl| status.text = "Connecting..." },
    :progress => proc { |dl| status.text = "#{dl.percent}% complete" },
    :finish => proc { |dl| status.text = "Download finished" },
    :error => proc { |dl, err| status.text = "Error: #{err}" }
end

Or, use the method syntax:

Shoes.app do
  url = "http://shoooes.net/dist/shoes-0.r905.exe"
  status = para "Downloading #{url}"

  get = download url, :save => "shoes.exe"
  get.start { |dl| status.text = "Connecting..." }
  get.progress { |dl| status.text = "#{dl.percent}% complete" }
  get.finish { |dl| status.text = "Download finished" }
  get.error { |dl, err| status.text = "Error: #{err}" }
end

The last thing I will mention is that every queued download is attached to the window containing it. When you close the window, the download stops. So, if you’re queueing a download from a temporary popup, be sure to queue it on the main app window.

Those Vintage P K D Covers

August 13rd 04:54
by why

Here’s a shot of an updated book page, with the real cover.

See? A fine, illustrated cover from days of yore. Devoid of panicky torsos and their ilk.

Git Hooks For Ditz

June 26th 18:04
by why

~/.ditz/hooks/after_add.rb:

Ditz::HookManager.on :after_add do |project, config, issues|
  issues.each do |issue|
    `git add #{issue.pathname}`
  end
end

~/.ditz/hooks/after_delete.rb:

Ditz::HookManager.on :after_delete do |project, config, issues|
  issues.each do |issue|
    `git rm #{issue.pathname}`
  end
end

Calling Cocoa Commandline

June 25th 19:31
by why
[win center];
[win setLevel: NSFloatingWindowLevel];
[win makeKeyAndOrderFront: nil];

Stamping EXEs And DMGs

June 19th 15:15
by why

Martin DeMello's Gooey Challenge

June 12nd 17:57
by why

Martin DeMello: One of the most interesting facets of a desktop GUI system is how easy it makes it to go off the beaten track, particularly how well you can add “first class” components to the system. (Using ‘first class’ here to mean ‘on an equal footing with the widgets supplied by the toolkit’). Also, as a ruby programmer, I’d naturally rather not drop down into C (or Java) to do this.

So how does Shoes hold up against this challenge? And i mean: without hacking anything new into Shoes, using syntax introduced before the challenge was posed.

Dismantling BrowserPlus

June 9th 08:58
by why

I had to peek a little. And to pry it open like the upturned crab it was.