<?xml version="1.0" encoding="UTF-8"?><feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xml:lang="en"
  >
  <id>http://livingcode.org/feed/atom</id>
  <updated>2009-11-13T19:33:25Z</updated>
  <title type="text">Living Code</title>
  <subtitle type="text">Programming for the Fun of It</subtitle>
  <link rel="self" type="application/atom+xml" href="http://livingcode.org/feed" />
  <link rel="alternate" href="http://livingcode.org" />
  <rights type="text">Copyright 2009</rights>
  <generator uri="http://wordpress.org/" version="2.8.6">WordPress</generator>
      <entry>
    <id>http://livingcode.org/2005/not-dead-yet</id>
    <title type="html"><![CDATA[Not dead yet]]></title>
    <updated>2008-01-26T04:30:22Z</updated>
    <published>2005-01-21T04:19:45Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2005/01/20/not-dead-yet/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2005/01/20/not-dead-yet" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[I&#8217;m still here. I&#8217;m going to post the previous examples .dmg with some corrections pointed out by Bob Ippolito (4-space indents, don&#8217;t modify data directly in the Bundle). I&#8217;ve been quiet because a) I&#8217;ve been hitting some walls with Renaissance and investigating work-arounds and alternatives, and b) my coding/blogging time is pretty much between the [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2005/01/20/not-dead-yet"><![CDATA[<p>I&#8217;m still here. I&#8217;m going to post the previous examples .dmg with some corrections pointed out by Bob Ippolito (4-space indents, don&#8217;t modify data directly in the Bundle). I&#8217;ve been quiet because a) I&#8217;ve been hitting some walls with Renaissance and investigating work-arounds and alternatives, and b) my coding/blogging time is pretty much between the time I get the kids to bed and the time my wife comes home from tutoring.</p>
<p>I&#8217;m investigating the PyGUI and Wax APIs, to see if they are worth porting to run on top of Cocoa (PyGUI runs on Carbon, Wax runs on top of wxPython). Both are attempts to make GUI creation more &#8220;Pythonic,&#8221; which is a <span style="font-weight: bold">Good Thing™</span>. I have figured out how to get the menus initialized using pure Python (on top of PyObjC, of course), or maybe the newer pyobjc/py2app has fixed the problem, but it is possible to build applications in Python with no Nib file (or Renaissance .gsmarkup file) at all. My earlier inabillity to do that is what drove me to Renaissance in the first place.</p>
<p>I&#8217;ve also discovered the nibtool utility, which I did not know about. This allows you to see a textual representation of the nibs created by Interface Builder, search and replace strings (class names, etc.). This is a major discovery. Now if you could take the textual representation and put it back&#8230; I&#8217;m going to have to investigate this further.</p>
<p>In other news, I will be giving a presentation on Tuesday, February 1 at the Vancouver Zope and Python Users Group (<a href="http://www.vanpyz.org/news">VanPyZ</a>) at 7:00 p.m. It will be a variation on the talk I gave in December to the XML users group, updated with what I&#8217;ve been exploring since then. Specifically I will show a simple (Hello World) application built three different ways, with Renaissance, with Interface Builder, and in pure Python. I&#8217;ll also show some apps written in other toolkits (wxPython, tkinter) for comparison. I hope some of my readers are close enough to make it.</p>
<p>I&#8217;ll also be attending the <a href="http://www.northernvoice.ca/">Northern Voice</a> blogging conference here in Vancouver on Saturday, February 19th. I&#8217;m looking forward to meeting some fellow bloggers face to face, rather than RSS to RSS.</p>
<p>Finally, I managed to install Python 2.4 today, and so far nothing has been obviously screwed up, so I&#8217;ll be exploring some of the crunchy new features here in the near future.</p>
<p>More posts coming soon. Honest!</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/slides-and-code-posted</id>
    <title type="html"><![CDATA[Slides and code posted]]></title>
    <updated>2008-01-26T05:02:41Z</updated>
    <published>2004-12-19T04:30:23Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/12/18/slides-and-code-posted/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/12/18/slides-and-code-posted" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[My talk at VanX last night was a success. Not many people showed (too close to Xmas), but the ones who did seemed to enjoy my presentation on Cocoa, Python, and Renaissance. Gerald was a great host, SchemaSoft provided a good (and convenient!) venue, Paul came to show support, and BlastRadius (my employer) sponsored the [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/12/18/slides-and-code-posted"><![CDATA[<p>My talk at <a href="http://vanx.org/">VanX</a> last night was a success. Not many people showed (too close to Xmas), but the ones who did seemed to enjoy my presentation on Cocoa, Python, and Renaissance. Gerald was a great host, <a href="http://schemasoft.com/">SchemaSoft</a> provided a good (and convenient!) venue, <a href="http://prescod.net/">Paul</a> came to show support, and <a href="http://blastradius.com/">BlastRadius</a> (my employer) sponsored the snacks. After we went to Mira in Yaletown for beers and tech talk, had the whole place to ourselves, and a musician playing Flamenco guitar, then I walked across the bridge to home. A great end to a great evening.</p>
<p>I&#8217;ve posted my slides at <a href="http://livingcode.org/slides/renaissance.html">livingcode.org/slides/renaissance.html</a> using Eric Meyer&#8217;s neat S5 tool to put the whole slideshow into one HTML file.</p>
<p>I&#8217;ve also built a new .dmg containing all the source code and built, runnable examples (seven of them now), although they&#8217;re not all fully functional yet. More example gsmarkup to view, improved setup scripts, and they all have icons now. The file is <a href="http://sourceforge.net/project/showfiles.php?group_id=19654">examples 2004-12-17</a> on SourceForge.</p>
<p>I&#8217;ve been working hard to put this all together, which hasn&#8217;t left much time for posting, but I will have a lot more to say real soon now.</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/oblique-strategies</id>
    <title type="html"><![CDATA[Oblique Strategies]]></title>
    <updated>2008-01-26T05:13:58Z</updated>
    <published>2004-11-25T05:02:43Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/24/oblique-strategies/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/24/oblique-strategies" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[Today&#8217;s Example is a simple, but full application. Our setup file is getting more complicated as we give the app a custom icon and a name which isn&#8217;t taken from the main python file. We&#8217;re finally using the menus for more than just default behaviors. We&#8217;re loading in resources at runtime. We&#8217;re adding a custom [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/24/oblique-strategies"><![CDATA[<p>Today&#8217;s Example is a simple, but full application. Our setup file is getting more complicated as we give the app a custom icon and a name which isn&#8217;t taken from the main python file. We&#8217;re finally using the menus for more than just default behaviors. We&#8217;re loading in resources at runtime. We&#8217;re adding a custom About box. And we&#8217;re taking advantage of Python standard libraries from within a Cocoa program. One icon file + 224 lines of python, XML, and HTML.</p>
<p>Some years ago Brian Eno and Peter Schmidt created a deck of cards for brainstorming your way through artistic blocks. Each card had one idea, and they were called Oblique Strategies. The Whole Earth Review published a list of some of the strategies, the decks went through several editions, and there were quite a number of programs written to simulate drawing a card from the deck. The <a href="http://www.rtqe.net/ObliqueStrategies/">Oblique Strategies Web Site</a> has more details. You can buy the deck from <a href="http://www.enoshop.co.uk/">Brian Eno&#8217;s site</a>. And a group called curvedspace created a nice<a href="http://www.curvedspace.org/software/oblique.html"> OS X version</a> which you can download for free from their site.</p>
<p>The curvedspace app is so nice, in fact, that we&#8217;re going to slavishly imitate it. There are only a couple of problems with it. First, you can&#8217;t add your own quotes and sayings to the mix. Second, it&#8217;s free, but not open source, so you can&#8217;t patch it to allow you to add your own quotes. Tonight&#8217;s example will build a version identical to the curvedspace tool, but which allows you to choose from among several quote files, not just the Oblique Strategies. A future exercise will be to allow the user to customize it with new quotes from within the running application.</p>
<p>Since there&#8217;s quite a bit more code, and by reader request, this example is contained on a downloadable .dmg file. The file contains both the finished, runnable application, and all the source code. I&#8217;ll just be describing highlights of what&#8217;s different from earlier examples. You can download it all <a href="http://prdownloads.sourceforge.net/livingcode/ObliqueStrategies.dmg?download">here</a>.</p>
<p>What&#8217;s new? First of all, the <span class="code">setup.py</span> defines a plist resource inline to map some of the application features. This gives the application a name (&#8221;Oblique Strategies&#8221; rather than picking up &#8220;oblique&#8221; from the python file, and sets up some info for the About box. The setup call is a little more complex too, including English.lproj (which holds our icon) and Credits.html (which is the content of our About box), and passing in the plist we defined.</p>
<p>In the <span class="code">MainMenu.gsmarkup</span> we have added a bunch of menu items to the File menu, to allow the user to pick a quotation file. What&#8217;s interesting is that we&#8217;ve implemented &#8216;About Oblique Strategies&#8217; and Edit-&gt;Copy, but those menu items didn&#8217;t have to change.</p>
<p>In <span class="code">oblique.py</span>, the main script, we implement a subclass of NSWindow called TexturedWindow. This is to work around a limitation of the current version of Renaissance, which doesn&#8217;t support so-called Metal windows (because GNUstep doesn&#8217;t have them). Nicola has fixed this in CVS, so it will be in the next release, but in the meantime it is a simple class (4 lines of code) and we use the <span class="code">instanceOf</span> attribute of <span class="code">&lt;window /&gt;</span> to call our subclass in the <span class="code">MainWindow.gsmarkup</span>.</p>
<p>Our AppDelegate is similar to earlier examples, but has grown a couple of methods. The <span class="code">change()</span> method is called by our one button to select another quotation at random from the selected file (or a random file if you like). The <span class="code">chooseFile_(</span>) method checks to see which menu item called it, and based on the menu item, selects the file for future calls to <span class="code">change()</span>. There is one support function, <span class="code">getQuote(filename)</span> which uses Python standard file manipulation and the random module to pick a quote (much less verbose than doing this from Objective-C).</p>
<p>All that&#8217;s left are the quote files. These are simple text files with short quotations, one to a line. If a quote requires newlines, they can be embedded with &#8216;<span class="code">\n</span>&#8216;. The included files have quotes from Martin Fowler&#8217;s book &#8220;Refactoring,&#8221; the book &#8220;The Pragmatic Programmer,&#8221; the Magic 8-Ball, Jenny Holzer&#8217;s Truisms, and more. Enjoy!</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/pre-built-examples</id>
    <title type="html"><![CDATA[Pre-built examples]]></title>
    <updated>2004-11-12T05:13:59Z</updated>
    <published>2004-11-12T05:13:59Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/11/pre-built-examples/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/11/pre-built-examples" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[I&#8217;ve been requested to make binary packages of the applications for people who haven&#8217;t been following along at home. The first application I&#8217;ve made available is the GMarkup Browser, so you&#8217;ll need some GMarkup files to browse with it, either from the example here, the Renaissance site (the source package has lots of examples in [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/11/pre-built-examples"><![CDATA[<p>I&#8217;ve been requested to make binary packages of the applications for people who haven&#8217;t been following along at home. The first application I&#8217;ve made available is the GMarkup Browser, so you&#8217;ll need some GMarkup files to browse with it, either from the example here, the Renaissance site (the source package has lots of examples in the Examples folder) or by writing your own (the whole point is that that it isn&#8217;t hard to do). It&#8217;s available from the <a href="http://sourceforge.net/projects/livingcode">Living Code</a> project on SourceForge.</p>
<p>I&#8217;ll make others available as I get the chance, now that I&#8217;ve figured out the SourceForge release system (sort of) and the steps for making a disk image for distribution. Soon I need to figure the Mac Package Manager and Installer (which py2app supports) so folks who want to install several apps don&#8217;t end up with multiple copies of Renaissance too. Baby steps for now, there&#8217;s a lot to learn.</p>
<p>Mac OS 10.3 only. Feedback appreciated. Coming soon: applications that I can post meaningful screenshots of.</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/housekeeping</id>
    <title type="html"><![CDATA[Housekeeping]]></title>
    <updated>2008-01-26T05:27:01Z</updated>
    <published>2004-11-11T05:23:42Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/10/housekeeping/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/10/housekeeping" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[Various small improvements. Switched the template so code doesn&#8217;t run off the edge so easily. Fixed whitespace, which I forgot to do after switching the template (thanks, Xavier, for pointing that out!). All the code for the renaissance examples is available via cvs from the SourceForge Living Code project, in the somewhat predictable cvs module, [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/10/housekeeping"><![CDATA[<p>Various small improvements. Switched the template so code doesn&#8217;t run off the edge so easily. Fixed whitespace, which I forgot to do after switching the template (thanks, Xavier, for pointing that out!). All the code for the renaissance examples is available via cvs from the SourceForge <a href="http://sourceforge.net/projects/livingcode/">Living Code</a> project, in the somewhat predictable cvs module, <a href="http://cvs.sourceforge.net/viewcvs.py/livingcode/renaissance_examples/">renaissance_examples</a>. As some of the examples grow, I may only publish the highlights in the blog, and put the remainder in CVS. We&#8217;ll se how it goes.</p>
<p>Coming attractions. I&#8217;m researching how to build the Renaissance projects so they can be distributed (I haven&#8217;t forgotten you, Jorjun, I&#8217;m just still figuring it out myself). I can do it now (thanks, Bob!), but I want something more straightforward to build. Hopefully later tonight.</p>
<p>Now that we&#8217;ve got a brower for Renaissance files (see previous post), I wanted to create a markup file to show off most of the widgets and options, but realized there is no markup for tabbed views, so I&#8217;m going to try creating new tags from Python, and show how to do that. When I&#8217;ve got the tags which represent Cocoa widgets that do not yet have Renaissance representations working, then I&#8217;ll put together the demo gsmarkup file.</p>
<p>Then back to the Small Nerd examples and a couple of other applications (ports of existing tools, nothing terribly original yet).</p>
<p>It&#8217;s been nice to hear from people who are enjoying this series. If there are specific things you&#8217;d like to see, let me know, either in the comments, or at dethe(at)livingcode.org</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/packaging-frameworks</id>
    <title type="html"><![CDATA[Packaging Frameworks]]></title>
    <updated>2008-01-26T23:43:13Z</updated>
    <published>2004-11-11T05:15:42Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/10/packaging-frameworks/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/10/packaging-frameworks" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[Packaging Renaissance applications (or any other frameworks) takes a bit more care than just wrapping your Python scripts. Today&#8217;s exercise helps us get our apps out into the world.
Now that we can build cool OS X applications with Python and Renaissance, it would be cool if we could share them with others, wouldn&#8217;t it. And [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/10/packaging-frameworks"><![CDATA[<p>Packaging Renaissance applications (or any other frameworks) takes a bit more care than just wrapping your Python scripts. Today&#8217;s exercise helps us get our apps out into the world.</p>
<p>Now that we can build cool OS X applications with Python and Renaissance, it would be cool if we could share them with others, wouldn&#8217;t it. And that stumped me for a bit. We&#8217;re using <span class="code">py2app</span> to package our scripts as applications, and it knows how to include a framework, but it takes a bit more than that. Specifically, the wrapper which imports the framework into Python has to be a tiny bit smarter. Let&#8217;s take a look at the wrapper I provided earlier in this series, to go in Python&#8217;s <span class="code">site-packages/Renaissance/</span> folder.</p>
<p><strong>Old __init__.py</strong></p>
<pre class="code">import objc, AppKit, Foundation</pre>
<pre class="code">objc.loadBundle('Renaissance', globals(),</pre>
<pre class="code">    bundle_path='/Library/Frameworks/Renaissance.framework')</pre>
<pre class="code">del objc, AppKit, Foundation</pre>
<p>And the new, smarter version, which handles bundling.</p>
<p><strong>__init__.py</strong></p>
<pre class="code">import objc, AppKit, Foundation, os</pre>
<pre class="code">if 'site-packages.zip' in __file__:</pre>
<pre class="code">    base_path = os.path.join(os.path.dirname(os.getcwd()), 'Frameworks')</pre>
<pre class="code">else:</pre>
<pre class="code">    base_path = '/Library/Frameworks'</pre>
<pre class="code">bundle_path = os.path.abspath(os.path.join(base_path, 'Renaissance.framework'))</pre>
<pre class="code">objc.loadBundle('Renaissance', globals(), bundle_path=bundle_path)</pre>
<pre class="code">del objc, AppKit, Foundation, os, base_path, bundle_path</pre>
<p>That takes care of importing the Renaissance framework, now we just need to make sure it gets included in our application bundle. You can do this by passing it on the command line</p>
<p><span class="code">python setup.py py2app &#8211;framework=Renaissance.framework </span></p>
<p>But I&#8217;d prefer to put it into the setup.py so we don&#8217;t have to remember command-line flags. Py2app is new enough that the documentation is a little rough, but Bob Ippolito (author of py2app) is very responsive on the pythonmac mailing list and he gave the following advice.</p>
<blockquote><p>If you use a python module that links to Renaissance, it will automatically get included. Otherwise, you have to specify it as a framework.</p>
<p>% python setup.py py2app -f Renaissance.framework<br />
(you can specify a full path to the framework or the dylib inside the framework if you want)</p>
<p>or from setup.py it would look like:<br />
setup(<br />
app = [...],<br />
options = dict(py2app=dict(<br />
frameworks=['Renaissance.framework'],<br />
)),<br />
)<br />
This command is your friend:<br />
% python setup.py &#8211;help py2app</p>
<p>Every &#8220;long name&#8221; in the list corresponds to an option you can pass via the options dict. Hypens are converted to underscores. This same dance works for any distutils command, btw.</p></blockquote>
<p>That&#8217;s good to know about <span class="code">distutils</span>, I&#8217;ve had trouble figuring out the mapping between command-line parameters and <span class="code">setup.py</span> configuration. So here&#8217;s the new version of setup.py for the browser app:</p>
<p><strong>setup.py<br />
</strong></p>
<pre class="code">'''</pre>
<pre class="code">Smarter setup.py example, run with:</pre>
<pre class="code">% python setup.py py2app</pre>
<pre class="code">'''</pre>
<pre class="code">from distutils.core import setup</pre>
<pre class="code">import py2app</pre>
<pre class="code">setup(</pre>
<pre class="code">    data_files = ['MainMenu.gsmarkup'],</pre>
<pre class="code">    app = ['browser.py',],</pre>
<pre class="code">    options=dict(py2app=dict(frameworks=['Renaissance.framework'],)),</pre>
<pre class="code">)</pre>
<p>There&#8217;s still a lot more we can do with py2app, like adding custom icons, giving the application a better name, a version, the ability to advertise its ability to open certain types of files, etc. We&#8217;re just getting to the good stuff.</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/gmarkup-browser</id>
    <title type="html"><![CDATA[GMarkup Browser]]></title>
    <updated>2008-01-26T05:31:19Z</updated>
    <published>2004-11-10T05:27:02Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/09/gmarkup-browser/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/09/gmarkup-browser" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[Today&#8217;s exercise was to port the GMarkup Browser, an Objective-C program which comes with Renaissance, to Python. Using this allows you to see what various gmarkup files will look like when they are loaded, which is very handy as you&#8217;re developing a program&#8217;s UI, without having to build a program around them. The source code [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/09/gmarkup-browser"><![CDATA[<p>Today&#8217;s exercise was to port the GMarkup Browser, an Objective-C program which comes with Renaissance, to Python. Using this allows you to see what various gmarkup files will look like when they are loaded, which is very handy as you&#8217;re developing a program&#8217;s UI, without having to build a program around them. The source code of Renaissance (available separately from the binary we installed a few entries ago) contains an Examples folder showing all of the tags in use, both as small toy examples and tests, and as full-fledged applications. It&#8217;s well worth downloading this and poking around in it with the Browser.</p>
<p>There are three files today, the <span class="code">setup.py</span>, a simple <span class="code">MainMenu.gsmarkup</span>, and the <span class="code">browser.py</span> application. Note that loading resources, especially menu resources, into a running program can cause bad side effects. So far I&#8217;ve been able to exit by ctrl-clicking the application icon and selecting quit, even when the menus disappeared, but use caution. Also, buttons wired up to the &#8220;<span class="code">terminate:</span>&#8221; selector will exit your program if you click on them. With great power comes great responsibility, or something like that. Caveats aside, you can open multiple gsmarkup files at a time, just use the File-&gt;Open menu or Cmd-O.</p>
<p><strong>MainMenu.gsmarkup</strong></p>
<pre class="code">&lt;?xml version="1.0"?&gt;</pre>
<pre class="code">&lt;!DOCTYPE gsmarkup&gt;</pre>
<pre class="code">&lt;gsmarkup&gt;</pre>
<pre class="code">    &lt;objects&gt;</pre>
<pre class="code">        &lt;menu type="main"&gt;</pre>
<pre class="code">            &lt;menu title="GSMarkup Browser" type="apple"&gt;</pre>
<pre class="code">                &lt;menuItem title="About GSMarkup Browser"</pre>
<pre class="code">                    action="orderFrontStandardAboutPanel:"/&gt;</pre>
<pre class="code">                &lt;menuSeparator/&gt;</pre>
<pre class="code">                &lt;menu title="Services" type="services"/&gt;</pre>
<pre class="code">                &lt;menuSeparator/&gt;</pre>
<pre class="code">                &lt;menuItem title="Hide GSMarkup Browser" action="hide:" key="h"/&gt;</pre>
<pre class="code">                &lt;menuItem title="Hide Others" action="hideOtherApplications:"/&gt;</pre>
<pre class="code">                &lt;menuItem title="Show All" action="unhideAllApplications:"/&gt;</pre>
<pre class="code">                &lt;menuSeparator/&gt;</pre>
<pre class="code">                &lt;menuItem title="Quit GSMarkup Browser" action="terminate:" key="q"/&gt;</pre>
<pre class="code">            &lt;/menu&gt;</pre>
<pre class="code">            &lt;menu title="File"&gt;</pre>
<pre class="code">                &lt;menuItem title="Open" action="open:" key="o"/&gt;</pre>
<pre class="code">            &lt;/menu&gt;</pre>
<pre class="code">            &lt;menu title="Window" type="windows"&gt;</pre>
<pre class="code">                &lt;menuItem title="Minimize Window" action="performMiniaturize:" key="m"/&gt;</pre>
<pre class="code">                &lt;menuSeparator/&gt;</pre>
<pre class="code">                &lt;menuItem title="Bring All to Front" action="arrangeInFront:"/&gt;</pre>
<pre class="code">            &lt;/menu&gt;</pre>
<pre class="code">        &lt;/menu&gt;</pre>
<pre class="code">    &lt;/objects&gt;</pre>
<pre class="code">&lt;/gsmarkup&gt;</pre>
<p><strong>browser.py </strong></p>
<pre class="code">'''</pre>
<pre class="code">Port of GSMarkupBrowser from Objective-C to Python</pre>
<pre class="code">'''</pre>
<pre class="code">from Foundation import *</pre>
<pre class="code">from AppKit import *</pre>
<pre class="code">from Renaissance import *</pre>
<pre class="code">class Owner(NSObject):</pre>
<pre class="code">def takeValue_forKey_(self, obj, key):</pre>
<pre class="code">    #print 'Set value %s for key %s of NSOwner' % (obj, key)</pre>
<pre class="code">    pass</pre>
<pre class="code">def bundleDidLoadGSMarkup_(self, notification):</pre>
<pre class="code">    if NSUserDefaults.standardUserDefaults().boolForKey_('DisplayAutoLayout'):</pre>
<pre class="code">        topLevelObjects = notification.userInfo().objectForKey_('NSTopLevelObjects')</pre>
<pre class="code">        for obj in topLevelObjects:</pre>
<pre class="code">            if obj.isKindOfClass_(NSWindow) or obj.isKindOfClass_(NSView):</pre>
<pre class="code">                obj.setDisplayAutoLayoutContainers_(True)</pre>
<pre class="code">def applicationDidFinishLaunching_(self, notification):</pre>
<pre class="code">    self.open_(self)</pre>
<pre class="code">def open_(self, notification):</pre>
<pre class="code">    filetypes = ['gsmarkup']</pre>
<pre class="code">    panel = NSOpenPanel.openPanel()</pre>
<pre class="code">    result = panel.runModalForDirectory_file_types_(None, None, filetypes)</pre>
<pre class="code">    if result == NSOKButton:</pre>
<pre class="code">        self.pathname = panel.filenames()[0]</pre>
<pre class="code">        #print 'Loading', self.pathname</pre>
<pre class="code">        didLoad = NSBundle.loadGSMarkupFile_externalNameTable_withZone_localizableStringsTable_inBundle_(</pre>
<pre class="code">            self.pathname,</pre>
<pre class="code">            {'NSOwner': self}, None, None, None)</pre>
<pre class="code">        if didLoad:</pre>
<pre class="code">            print self.pathname, 'loaded!'</pre>
<pre class="code">        else:</pre>
<pre class="code">            #print 'Could not load', self.pathname</pre>
<pre class="code">            NSBeep()</pre>
<pre class="code">def main():</pre>
<pre class="code">    defaults = NSUserDefaults.standardUserDefaults()</pre>
<pre class="code">    defaults.registerDefaults_({'DisplayAutoLayout': 'NO'})</pre>
<pre class="code">    app = NSApplication.sharedApplication()</pre>
<pre class="code">    owner = Owner.alloc().init()</pre>
<pre class="code">    app.setDelegate_(owner)</pre>
<pre class="code">    NSBundle.loadGSMarkupNamed_owner_('MainMenu', owner)</pre>
<pre class="code">    NSApp().run()</pre>
<pre class="code">if __name__ == '__main__': main()</pre>
<p><strong>setup.py </strong></p>
<pre><span class="code">'''
Minimal setup.py example, run with:
% python setup.py py2app
'''
from distutils.core import setup
import py2app
setup(
    data_files = ['MainMenu.gsmarkup'],
    app = ['browser.py'],
)</span></pre>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/vancouver-xml-users-group</id>
    <title type="html"><![CDATA[Vancouver XML Users Group]]></title>
    <updated>2004-11-08T05:31:24Z</updated>
    <published>2004-11-08T05:31:24Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/07/vancouver-xml-users-group/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/07/vancouver-xml-users-group" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[I&#8217;ll be presenting on Renaissance, OS X, and Python at the VanX meeting at 6:30 p.m. on Thursday, December 16th. By then I should have a lot more programs and utilities to show.
]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/07/vancouver-xml-users-group"><![CDATA[<p>I&#8217;ll be presenting on Renaissance, OS X, and Python at the <a href="http://vanx.org/">VanX</a> meeting at 6:30 p.m. on Thursday, December 16th. By then I should have a lot more programs and utilities to show.</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/renaissance-tags</id>
    <title type="html"><![CDATA[Renaissance Tags]]></title>
    <updated>2008-01-26T05:44:32Z</updated>
    <published>2004-11-06T05:37:50Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/05/renaissance-tags/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/05/renaissance-tags" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[Nicola Pera has done a great job building Renaissance, and has worked hard to document it well. The manual is clear and easy to follow, but is not complete yet. He invited me to help with the documentation, and I&#8217;ve found the source code easy enough to read that I might do that (Objective-C is [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/05/renaissance-tags"><![CDATA[<p>Nicola Pera has done a great job building Renaissance, and has worked hard to document it well. The <a href="http://www.gnustep.it/Renaissance/Manual/index.html">manual</a> is clear and easy to follow, but is not complete yet. He invited me to help with the documentation, and I&#8217;ve found the source code easy enough to read that I might do that (Objective-C is actually quite Pythonic), but it&#8217;s been years since I&#8217;ve hacked LaTeX and I&#8217;d rather spend my time posting examples of working code. So for now I&#8217;ll just stick my notes here about the Renaissance elements which have not yet been documented in the manual.</p>
<pre class="code">&lt;browser /&gt;</pre>
<pre class="code">    titled="yes|no" (default: no)</pre>
<pre class="code">    allowsBranchSelection="yes|no" (default: yes)</pre>
<pre class="code">    allowsEmptySelection="yes|no" (default: no)</pre>
<pre class="code">    allowsMultipleSelection="yes|no" (default: no)</pre>
<pre class="code">    takesTitleFromPreviousColumn="yes|no" (default: yes)</pre>
<pre class="code">    separatesColumns="yes|no" (default: yes)</pre>
<pre class="code">    acceptsArrowKeys="yes|no" (default: yes)</pre>
<pre class="code">    hasHorizontalScrollbars="yes|no" (default: no)</pre>
<pre class="code">    doubleAction="[selector]"</pre>
<pre class="code">    minColumnWidth="[number]"</pre>
<pre class="code">    maxVisibleColumns="[number]"</pre>
<pre class="code">    matrixClass="[subclass of NSMatrix]"</pre>
<pre class="code">    cellClass="[subclass of NSCell]"</pre>
<pre class="code">&lt;colorwell/&gt;</pre>
<pre class="code">    color="[Color]" (See section 2.3.3.6 of the manual for info on Color attributes)</pre>
<pre class="code">&lt;form/&gt;</pre>
<pre class="code">    titleFont="[Font]" (See section 2.3.3.7 of the manual for info on Font attributes)</pre>
<pre class="code">    titleAlignment="left|right|center"</pre>
<pre class="code">&lt;label/&gt;</pre>
<pre class="code">    color="[Color]"</pre>
<pre class="code">    backgroundColor="[Color]"</pre>
<pre class="code">    font="[Font]"</pre>
<pre class="code">    align="left|right|center"</pre>
<pre class="code">&lt;matrix/&gt; (contains matrixRow elements)</pre>
<pre class="code">    doubleAction="[Selector]"</pre>
<pre class="code">&lt;matrixRow/&gt; (contains matrixCell elements)</pre>
<pre class="code">&lt;matrixCell/&gt;</pre>
<pre class="code">    title="[String]"</pre>
<pre class="code">    action="[Selector]"</pre>
<pre class="code">    editable="yes|no"</pre>
<pre class="code">    selectable="yes|no"</pre>
<pre class="code">    tag="(???)" (I'm not sure how tags are used yet)</pre>
<pre class="code">&lt;outlineView/&gt;</pre>
<pre class="code">    outlineColumn="[Number]"</pre>
<pre class="code">&lt;popupButton/&gt; (contains popupButtonItems)</pre>
<pre class="code">    title="[String]"</pre>
<pre class="code">    pullsDown="yes|no"</pre>
<pre class="code">    autoenabledItems="yes|no" (default: yes)</pre>
<pre class="code">&lt;popupButtonItems/&gt;</pre>
<pre class="code">    tag="(???)"</pre>
<pre class="code">    action="[Selector]"</pre>
<pre class="code">    key="(???)"</pre>
<pre class="code">    title="[String]"</pre>
<pre class="code">&lt;scrollView/&gt;</pre>
<pre class="code">    hasHorizontalScroller="yes|no"</pre>
<pre class="code">    hasVerticalScroller="yes|no"</pre>
<pre class="code">    borderType="none|line|bezel|groove"</pre>
<pre class="code">&lt;secureTextField/&gt;</pre>
<pre class="code">&lt;splitView/&gt;</pre>
<pre class="code">    vertical="yes|no"</pre>
<pre class="code">&lt;tableColumn/&gt;</pre>
<pre class="code">    identifier="(???)"</pre>
<pre class="code">    editable="yes|no"</pre>
<pre class="code">    title="[String]"</pre>
<pre class="code">    minWidth="[Number]"</pre>
<pre class="code">    maxWidth="[Number]"</pre>
<pre class="code">    width="[Number]"</pre>
<pre class="code">    resizable="yes|no"</pre>
<pre class="code">&lt;tableView/&gt; (contains tableColumns)</pre>
<pre class="code">    dataSource="[Outlet]"</pre>
<pre class="code">    delegate="[Outlet]"</pre>
<pre class="code">    doubleAction="[Selector]"</pre>
<pre class="code">    allowsColumnReordering="yes|no"</pre>
<pre class="code">    allowsColumnResizing="yes|no"</pre>
<pre class="code">    allowsMultipleSelection="yes|no"</pre>
<pre class="code">    allowsEmptySelection="yes|no"</pre>
<pre class="code">    backgroundColor="[Color]"</pre>
<pre class="code">    drawsGrid="yes|no"</pre>
<pre class="code">    gridColor="[Color]"</pre>
<pre class="code">    autosaveName="[String]"</pre>
<pre class="code">&lt;textField/&gt;</pre>
<pre class="code">    editable="yes|no"</pre>
<pre class="code">    selectable="yes|no"</pre>
<pre class="code">    align="left|right|center"</pre>
<pre class="code">&lt;textView/&gt; **(Note: Always put a textView inside a scrollView!)**</pre>
<pre class="code">    editable="yes|no"</pre>
<pre class="code">    selectable="yes|no"</pre>
<pre class="code">    richText="yes|no"</pre>
<pre class="code">    usesFontPanel="yes|no"</pre>
<pre class="code">    allowsUndo="yes|no"</pre>
<pre class="code">    usesRuler="yes|no"</pre>
<pre class="code">    importGraphic="yes|no"</pre>
<p>Well, that&#8217;s what I have so far. I will try to keep this updated as I learn more, or simply point to the manual as it becomes more complete.</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/a-new-renaissance</id>
    <title type="html"><![CDATA[A New Renaissance]]></title>
    <updated>2008-01-26T05:54:02Z</updated>
    <published>2004-11-04T05:49:54Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/03/a-new-renaissance/feed" thr:count="1"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/03/a-new-renaissance" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[Yesterday I laid out the issues I have with using Interface Builder to create Cocoa applications (whether in Objective-C or Python), and my requirements for a replacement. To sum up, here are the requirements again:

Declarative
Simple and powerful
Able to replace NIB files and Interface Builder
Text-based, not binary
Agile for rapid development, adapts to rapidly changing code
Able to [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/03/a-new-renaissance"><![CDATA[<p>Yesterday I laid out the issues I have with using Interface Builder to create Cocoa applications (whether in Objective-C or Python), and my requirements for a replacement. To sum up, here are the requirements again:</p>
<ul>
<li>Declarative</li>
<li>Simple and powerful</li>
<li>Able to replace NIB files and Interface Builder</li>
<li>Text-based, not binary</li>
<li>Agile for rapid development, adapts to rapidly changing code</li>
<li>Able to specify simple apps completely, in code, without resorting to pictures or talking the user through mouse gestures</li>
</ul>
<p>As I hinted at previously, I think I&#8217;ve found the tool I was looking for in GNUstep Renaissance, and as an added bonus, it can be used to create applications for Linux, unix, and Windows using the GNUstep framework. So although I&#8217;m interested mainly in building applications for OS X, there is still a chance for cross-platform compatibility.</p>
<p>So what does Renaissance look like? It&#8217;s and XML format, similar to HTML and Mozilla XUL (but simpler than XUL). Today I will cover how to install Renaissance and set it up to use from PyObjC.</p>
<p>Prerequisites (this is my setup, others may work, but I haven&#8217;t tested them).</p>
<ol>
<li>A Mac</li>
<li>OS X (10.3)</li>
<li>PyObjC (1.1), available from <a href="http://pyobjc.sourceforge.net/">http://pyobjc.sourceforge.net/</a></li>
<li>py2app (0.1.4), available from <a href="http://pythonmac.org/wiki/py2app">http://pythonmac.org/wiki/py2app</a> (we&#8217;ll use this to build our double-clickable applications)</li>
<li>Renaissance framework (0.8), available from <a href="http://www.gnustep.it/Renaissance/Download.html">http://www.gnustep.it/Renaissance/Download.html</a> (this is the secret sauce)</li>
</ol>
<p>Once you have the prerequisites installed, you need to make Renaissance available from Python. In your site-packages directory (on my machine this is <em>/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/site-packages</em>) add a Renaissance directory containing the following file:</p>
<p><strong>__init__.py </strong></p>
<pre class="code">import objc, AppKit, Foundation</pre>
<pre class="code">objc.loadBundle('Renaissance', globals(),</pre>
<pre class="code">    bundle_path='/Library/Frameworks/Renaissance.framework')</pre>
<pre class="code">del objc, AppKit, Foundation</pre>
<p>Well, that was easy enough. Next up, a Hello World application.</p>
]]></content>
        </entry>
  </feed>
