<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Along Came Betty &#187; swing</title>
	<atom:link href="http://blog.darevay.com/category/swing/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.darevay.com</link>
	<description>You know, software and some other stuff like maybe guitar or something</description>
	<lastBuildDate>Sat, 28 Jan 2012 13:27:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>JSplitPainInTheAss: A less abominable fix for setDividerLocation</title>
		<link>http://blog.darevay.com/2011/06/jsplitpainintheass-a-less-abominable-fix-for-setdividerlocation/</link>
		<comments>http://blog.darevay.com/2011/06/jsplitpainintheass-a-less-abominable-fix-for-setdividerlocation/#comments</comments>
		<pubDate>Sun, 12 Jun 2011 21:30:21 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[swing]]></category>
		<category><![CDATA[seesaw]]></category>

		<guid isPermaLink="false">http://blog.darevay.com/?p=425</guid>
		<description><![CDATA[Update: Some discussion of this idea and code updates are in the gist here. Hubris. If you use Swing much there will come a time when you&#8217;d like to create a splitter, aka JSplitPane. Overall, it works fine, but it has one lame, lame, lame feature; if you want to set the divider&#8217;s initial position [...]]]></description>
			<content:encoded><![CDATA[<p><i><b>Update:</b> Some discussion of this idea and code updates are in the gist <a href="https://gist.github.com/1021984">here</a></i>. Hubris.</p>
<p>If you use Swing much there will come a time when you&#8217;d like to create a splitter, aka <code><a href="http://download.oracle.com/javase/6/docs/api/javax/swing/JSplitPane.html">JSplitPane</a></code>. Overall, it works fine, but it has one lame, lame, lame feature; if you want to set the divider&#8217;s <em>initial</em> position proportionally, you&#8217;re screwed. I say feature, because the documentation for <code><a href="http://download.oracle.com/javase/6/docs/api/javax/swing/JSplitPane.html#setDividerLocation%28double%29">JSplitPane.setDividerLocation</a></code> clearly states that it won&#8217;t work if the component hasn&#8217;t been &#8220;displayed&#8221; yet. </p>
<p>I bet that 95% of the time the programmer using this function is calling it at start-up before anything is displayed. Way to cover the 5% case there.</p>
<p>Anyway, you&#8217;ll go to Google and try to find a solution to this problem and you&#8217;ll find a lot of discussion and <a href="http://stackoverflow.com/questions/1879091/jsplitpane-setdividerlocation-problem">many</a> <a href="http://www.jguru.com/faq/view.jsp?EID=27191">variations</a> on the <a href="http://www.java-forums.org/awt-swing/36321-swing-jsplitpane-setdividerlocation-double-problem.html">same</a> <a href="http://www.velocityreviews.com/forums/t373012-jsplitpane-set-divider-location.html">workaround</a>. But they inevitably rely on sub-classing (isn&#8217;t that the solution to everything in Swing?) and hacking in some logic to fix things right before the splitter gets painted the first time. Nasty.</p>
<p>I&#8217;ve been thinking about this in terms of <a href="https://github.com/daveray/seesaw">Seesaw</a>, a Clojure/Swing API I&#8217;ve been working on. I want <code>setDividerLocation</code> to cover the 95% case and I don&#8217;t want to sub-class anything if I can help it. It&#8217;s not composable. So I thought about it a bit and came up with a much more elegant solution that works on a vanilla <code>JSplitPane</code>. Since I think this will be much more interesting to the Java Swing developers toiling away out there, I&#8217;ve coded it in pure Java. Here it is, a simple function:</p>
<p><script src="https://gist.github.com/1021984.js"> </script></p>
<p>If you can&#8217;t see any code, look <a href="https://gist.github.com/1021984">here</a>.</p>
<p><i>By the way, this code is insanely shorter in Clojure. Just sayin&#8217;.</i></p>
<p><del datetime="2011-06-13T23:27:10+00:00">The basic idea is to keep putting off the call to <code>setDividerLocation</code> using <code>invokeLater</code> until the splitter is realized on the screen. No fuss, no muss.</del> &#8230; strike that. The <code>invokeLater</code> approach did indeed work, but under certain circumstances, a split pane that wasn&#8217;t displayed very soon would result in an infinite cascade of <code>invokeLater</code> events. The main problem with this is that the processor never gets to sleep, etc, etc. So I came up with an alternate approach which takes advantage of a <code>HierarchyChange</code> event to detect when the split pane is displayed (learn something new every day) optionally followed by a resize listener because the hierarchy event may arrive before the split pane&#8217;s been laid out by its parent. Swing&#8217;s exhausting.</p>
<p>Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darevay.com/2011/06/jsplitpainintheass-a-less-abominable-fix-for-setdividerlocation/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Painting Widgets with Seesaw</title>
		<link>http://blog.darevay.com/2011/06/painting-widgets-with-seesaw/</link>
		<comments>http://blog.darevay.com/2011/06/painting-widgets-with-seesaw/#comments</comments>
		<pubDate>Sat, 11 Jun 2011 03:24:06 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[clojure]]></category>
		<category><![CDATA[seesaw]]></category>
		<category><![CDATA[swing]]></category>

		<guid isPermaLink="false">http://blog.darevay.com/?p=415</guid>
		<description><![CDATA[The functionality describe here will be in the 1.0.7 release of Seesaw in the next week or so. Say for some reason, you want a label with a red X on it. A bad, bad label. If you&#8217;re working with Swing in Java, you&#8217;ll create a new class, extend JLabel, override paintComponent, make some drawing [...]]]></description>
			<content:encoded><![CDATA[<p><i>The functionality describe here will be in the 1.0.7 release of <a href="https://github.com/daveray/seesaw">Seesaw</a> in the next week or so.</i></p>
<p><a href="http://blog.darevay.com/wp-content/uploads/2011/06/seesaw-painting.png"><img src="http://blog.darevay.com/wp-content/uploads/2011/06/seesaw-painting.png" alt="" title="seesaw-painting" width="469" height="287" class="aligncenter size-full wp-image-422" /></a></p>
<p>Say for some reason, you want a label with a red X on it. A bad, bad label. If you&#8217;re working with Swing in Java, you&#8217;ll create a new class, extend JLabel, override <code>paintComponent</code>, make some drawing calls, etc. Not terrible, but not that fun either. Something like this:</p>
<pre>
public class BadLabel extends JLabel {
  public BadLabel(String text) {
    super(text);
  }
  @Override
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    final int w = getWidth();
    final int h = getHeight();
    final int d = 5;
    g.setColor(Color.RED);
    g.drawLine(d, d, w - d, h - d);
    g.drawLine(w-d, d, d, h - d);
  }
}
</pre>
<p>That&#8217;s pretty minimal if we ignore imports and stuff. Enabling anti-aliasing would be nice. It&#8217;d also be nice to set the width of the lines. And if you wanted to draw the X on a button or something else, you could pull all the drawing code into a function, but you couldn&#8217;t avoid a new, possibly anonymous, class for each type of component you want to use it on.</p>
<p>In Seesaw, we use the <code>paintable</code> macro to do all the dirty work for us. Give it a function to handle the painting and a description of the widget you want, and you&#8217;re done. It handles anti-aliasing and there&#8217;s functions that make styling the lines a little less tedious.</p>
<p>Below is the equivalent Clojure code using Seesaw. Note that here we can easily apply the red X to a label or a button. Of course this also puts the widgets in a frame and displays them too. I&#8217;ll spare you that part in Java :)</p>
<p>The code for this example is also <a href="https://github.com/daveray/seesaw/blob/90219aae91c2e402110279efe3609d2e7fd9712a/src/seesaw/examples/paintable.clj">here</a>.</p>
<pre>
(ns seesaw.examples.paintable
  (:use [seesaw core graphics]))

(defn draw-a-red-x
  "Draw a red X on a widget with the given graphics context"
  [c g]
  (let [w          (width c)
        h          (height c)
        line-style (style :foreground "#FF0000" :stroke 3 :cap :round)
        d 5]
    (draw g
      (line d d (- w d) (- h d)) line-style
      (line (- w d) d d (- h d)) line-style)))

(defn content []
  (flow-panel
    :border 5
    :items [
      (label           :text "I'm a good label!" :font "ARIAL-BOLD-40" :foreground "#00AA00")
      <b>; *** Make a label and button with a red X on them ***
      (paintable label :text "I'm a bad label!"  :font "ARIAL-BOLD-40"
                              :paint draw-a-red-x)
      (paintable button :text "I'm a bad button!"  :font "ARIAL-BOLD-40"
                                :paint draw-a-red-x)]))</b>

(defn -main [&#038; args]
  (invoke-later
    (->
      (frame :title "Seesaw (paintable) example"
             :content (content))
      pack!
      show!)))
</pre>
<p><code>(paintable)</code> is still a macro so it comes with all the limitations associated with them. Unfortunately with Swing you have to sub-class to paint on a widget and in Clojure you can&#8217;t (as far as I know) sub-class at run-time.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darevay.com/2011/06/painting-widgets-with-seesaw/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Brief Note on Seesaw Selectors</title>
		<link>http://blog.darevay.com/2011/06/a-brief-note-on-seesaw-selectors/</link>
		<comments>http://blog.darevay.com/2011/06/a-brief-note-on-seesaw-selectors/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 05:00:21 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[clojure]]></category>
		<category><![CDATA[seesaw]]></category>
		<category><![CDATA[swing]]></category>

		<guid isPermaLink="false">http://blog.darevay.com/?p=407</guid>
		<description><![CDATA[Just wanted to note that I finally got around to a full implementation of CSS-style selectors in Seesaw, the Clojure UI library I&#8217;ve been working on. The updated doc for the (seesaw.core/select) function has most of the details, but here are a couple examples: ; All JLabels, no sub-classes allowed (select root [:&#60;javax.swing.JLabel!&#62;]) ; All [...]]]></description>
			<content:encoded><![CDATA[<p>Just wanted to note that I finally got around to a full implementation of CSS-style selectors in <a href="https://github.com/daveray/seesaw">Seesaw</a>, the Clojure UI library I&#8217;ve been working on. The <a href="https://github.com/daveray/seesaw/blob/66025c7914fe1a155c6e1ee387cebb371727caf2/src/seesaw/core.clj#L2325">updated doc</a> for the <code>(seesaw.core/select)</code> function has most of the details, but here are a couple examples:</p>
<pre>
      ; All JLabels, no sub-classes allowed
      (select root [:&lt;javax.swing.JLabel!&gt;])

      ; All JSliders that are descendants of a JPanel with id foo
      (select root [:JPanel#foo :JSlider])

      ; All JSliders (and sub-classes) that are immediate children of a
      ; JPanel with id foo
      (select root [:JPanel#foo :&gt; :&lt;javax.swing.JSlider&gt;])
</pre>
<p>To implement the selectors, I hacked up the zipper-based selector code in the very cool <a href="https://github.com/cgrand/enlive">Enlive</a> project. It was surprisingly straightforward:</p>
<ul>
<li>Modify zipper construction to create a zipper over a Swing widget hierarchy instead of an HTML doc</li>
<li>Hack up the parser a little bit to allow my Java-class-matching extensions</li>
<li>Update the predicate sets to work on widgets instead of DOM nodes
</ul>
<p>Hats off to Christophe Grand for writing such a well-factored piece of Clojure code that I could get this working in an evening.</p>
<p>I&#8217;ll write more (like what this could be useful for) when it&#8217;s not the middle of the night.</p>
<p>p.s. this will be in the 1.0.6 release on <a href="http://clojars.org/seesaw">Clojars</a> sometime this week after I beat on it a bit more.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darevay.com/2011/06/a-brief-note-on-seesaw-selectors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nice Weather for Some Clojure (UIs)</title>
		<link>http://blog.darevay.com/2011/05/nice-weather-for-some-clojure-uis/</link>
		<comments>http://blog.darevay.com/2011/05/nice-weather-for-some-clojure-uis/#comments</comments>
		<pubDate>Wed, 25 May 2011 02:01:08 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[clojure]]></category>
		<category><![CDATA[seesaw]]></category>
		<category><![CDATA[swing]]></category>

		<guid isPermaLink="false">http://blog.darevay.com/?p=378</guid>
		<description><![CDATA[Summary: I tried build something slightly non-trivial with Seesaw and learned some things. And so it came to pass that it seemed like I needed to start dog-fooding Seesaw a bit. I&#8217;ve been steadily adding features and building tiny toy apps to demonstrate them. Others (and others) have apparently found it useful, but I haven&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Summary</strong>: I tried build something slightly non-trivial with <a href="https://github.com/daveray/seesaw">Seesaw</a> and learned some things.</p>
<hr />
<p>And so it came to pass that it seemed like I needed to start dog-fooding <a href="https://github.com/daveray/seesaw">Seesaw</a> a bit. I&#8217;ve been steadily adding features and building tiny toy apps to demonstrate them. <a href="http://blog.raynes.me/?p=146">Others</a> (and <a href="https://github.com/macourtney/Dark-Exchange">others</a>) have apparently found it useful, but I haven&#8217;t tried anything myself.</p>
<p>So, I decided to write Gaidica, a little app that displays weather info for user-selected cities. The whole process wasn&#8217;t terrible, but shows that there&#8217;s work to do. I&#8217;d guess about 4 hours of work including fixing Seesaw bugs as I hit them and at least an hour puzzling over Clojure XML stuff. Here&#8217;s a screenshot of the forecasts:</p>
<p><a href="http://blog.darevay.com/wp-content/uploads/2011/05/gaidica-forecasts.png"><img src="http://blog.darevay.com/wp-content/uploads/2011/05/gaidica-forecasts.png" alt="" title="gaidica-forecasts" width="676" height="675" class="aligncenter size-full wp-image-383" /></a></p>
<p>The code is all available on <a href="https://github.com/daveray/seesaw/tree/master/examples">github</a>.</p>
<h2>Intro</h2>
<p>Just to make sure we&#8217;re on the same page, Seesaw is an API/DSL for building user interfaces in Clojure. It happens to be built on Swing as you&#8217;ll see below, but please don&#8217;t judge it too harshly. I&#8217;m working hard to make it so you never need to know that Swing&#8217;s even there.</p>
<h2>The Data</h2>
<p>I decided to use <a href="http://wiki.wunderground.com/index.php/API_-_XML">Weather Underground&#8217;s XML API</a> for the data. It provides the data in a simple format and as a bonus, includes icons for weather conditions, which saved me some work. Additionally, I got to do some XML wrangling in Clojure. Let&#8217;s just say that that deserves a blog post of its own.</p>
<p>In any case, I just point Clojure&#8217;s <a href="http://clojure.github.com/clojure/clojure.xml-api.html"><code>(xml/parse)</code></a> function at the URL and get back some results. All this is done in a background thread using <a href="http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/future"><code>(future)</code></a> to keep the UI responsive.</p>
<h2>The Good</h2>
<p>I mostly want to focus on the bad in this post, but despite any difficulties I had, building this was more enjoyable in Clojure+Seesaw than the equivalent Clojure+Swing or raw Java code. The lack of <a href="http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/proxy"><code>(proxy)</code></a> and <a href="http://clojure.github.com/clojure/clojure.core-api.html#clojure.core/reify"><code>(reify)</code></a> usage is testament to that.</p>
<p>Seesaw&#8217;s table support, seen in the webcam tab below, really paid off. Compared to the equivalent JTable-wrangling you&#8217;d have to do, it was downright dreamy.</p>
<p><a href="http://blog.darevay.com/wp-content/uploads/2011/05/gaidica-webcams.png"><img src="http://blog.darevay.com/wp-content/uploads/2011/05/gaidica-webcams.png" alt="" title="gaidica-webcams" width="676" height="675" class="aligncenter size-full wp-image-384" /></a></p>
<p>Here&#8217;s the code to create that table:</p>
<pre>
(defn make-webcam-table []
  (table
    :id :webcam-table
    :model
      [:columns
        [{:key :handle :text "Name" }
         :lat :lon
         {:key :updated :text "Last Updated"}
         {:key :image :text "Image"}]]))
</pre>
<h2>The Bad</h2>
<p>I learned a lot during this exercise. One thing I noticed is that Swing is a pain in the ass. I think when you&#8217;re in the depths of a Java-based Swing app, you don&#8217;t even notice it because you&#8217;re already so mired in Java verbosity. It&#8217;s a form of <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Stockholm_syndrome">Stockholm Syndrome</a> I guess.</p>
<p>Most of the pain centered around, you guessed it, layout. I wanted to do it with the vanilla Swing layouts provided by Seesaw (border-panel, vertical-panel, etc), but after fiddling with component alignments and lame resize problems, I eventually surrendered and ran back to <a href="http://www.miglayout.com/">MigLayout</a>. It&#8217;s powerful and pretty easy to use, but it&#8217;s yet another little language to learn. Luckily Seesaw <a href="https://github.com/daveray/seesaw/issues/1">already has Mig support</a>.</p>
<p>Otherwise, most of the other issues I had were just missing functionality. Swing methods not yet wrapped by Seesaw. The nice thing is that since Seesaw&#8217;s a fairly thin wrapper, it&#8217;s easy to drop down to raw Swing when needed. Some random functionality that I&#8217;m going to address as a result:</p>
<ul>
<li>Manipulation of the widget hierarchy needs to be seamless. This has historically been a problem in Swing (<code>invalidate(); revalidate(); repaint()</code>!!)
<li>Widget styling. Sprinkling fonts and colors throughout the code is a hassle. The main question is whether I just add convenience options for this, or go whole hog and try for a CSS-style styling.
<li>Saner defaults for &#8220;vanilla&#8221; layouts. I think I can tune some of the defaults and add some dials to make it less frustrating. It still really bugs me that I had to use Mig for something so simple.
</ul>
<h2>Conclusion</h2>
<p>From the perspective of a potential Seesaw user, already suspicious of Swing, all of this is a problem. I&#8217;ll take it as a challenge to continue making Seesaw a buffer between them and the occasional craziness of Swing. Feedback welcome!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darevay.com/2011/05/nice-weather-for-some-clojure-uis/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>20 Minute File Explorer with Seesaw</title>
		<link>http://blog.darevay.com/2011/04/20-minute-file-explorer-with-seesaw/</link>
		<comments>http://blog.darevay.com/2011/04/20-minute-file-explorer-with-seesaw/#comments</comments>
		<pubDate>Sun, 01 May 2011 03:40:23 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[clojure]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[seesaw]]></category>
		<category><![CDATA[swing]]></category>

		<guid isPermaLink="false">http://blog.darevay.com/?p=356</guid>
		<description><![CDATA[Seesaw, my Clojure/Swing experiment has been making a lot of progress. Earlier today I added basic support for JTree which is kind of the last major Swing component that had no support in Seesaw. As an test, I thought I&#8217;d try making a file explorer with the directory tree on the left and file list [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/daveray/seesaw">Seesaw</a>, my Clojure/Swing experiment has been making a lot of progress. Earlier today I added basic support for JTree which is kind of the last major Swing component that had no support in Seesaw. As an test, I thought I&#8217;d try making a file explorer with the directory tree on the left and file list on the right. It took about 20 minutes and was way less tedious than the equivalent raw Swing code you&#8217;d write in Java or Clojure.</p>
<p>The full code for the example can be found on <a href="https://github.com/daveray/seesaw/blob/master/src/seesaw/examples/explorer.clj">github</a>.</p>
<p>Here&#8217;s what it ended up looking like:</p>
<p><a href="http://blog.darevay.com/wp-content/uploads/2011/04/20-minute-file-explorer.png"><img class="aligncenter size-full wp-image-357" title="20-minute-file-explorer" src="http://blog.darevay.com/wp-content/uploads/2011/04/20-minute-file-explorer.png" alt="" width="490" height="408" /></a></p>
<h2>Code Highlights</h2>
<p>There are three code highlights.</p>
<p>Set up a model for the tree using the same pattern as (cloure.core/tree-seq):</p>
<pre>
; Make a model for the directory tree
(def tree-model
  (simple-tree-model
    #(.isDirectory %)
    (fn [f] (filter #(.isDirectory %) (.listFiles f)))
    (File. ".")))
</pre>
<p>Set up the structure of the frame. I think this reads pretty nicely:</p>
<pre>
  (frame :title "File Explorer" :width 500 :height 500 :pack? false :content
    (border-panel :border 5 :hgap 5 :vgap 5
      :north (label :id :current-dir :text "Location")

      :center (left-right-split
                (scrollable (tree :id :tree :model tree-model :renderer render-file-item))
                (scrollable (listbox :id :list :renderer render-file-item)))

      :south (label :id :status :text "Ready")))
</pre>
<p>Set up selection event handling:</p>
<pre>
  (listen (select [:#tree]) :selection
    (fn [e]
      (if-let [dir (-> (selection e) first last)]
        (let [files (.listFiles dir)]
          (config (select [:#current-dir]) :text (.getAbsolutePath dir))
          (config (select [:#status]) :text (format "Ready (%d items)" (count files)))
          (config (select [:#list]) :model files))))))
</pre>
<p>Here, the widgets are being retrieved by id with the (select) function. Alternatively, I could have just bound them to variables and used them directly. I&#8217;m still thinking about how this should work.</p>
<h2>Conclusion</h2>
<p>This is obviously still a toy (no sorting, doesn&#8217;t update, etc, etc), but I think shows promise. I like the separation of the structure and behavior, but the selector stuff needs more thought. Probably the biggest gain over raw Swing is that Seesaw takes care of all the yucky reify and proxy stuff for you. In this example alone, a raw implementation would need two (reify)s and a (proxy) call. Building up the widget structure is also pretty tedious with raw Swing.</p>
<p>I&#8217;d love to to hear feedback and criticism of the API since this is my first attempt at real Clojure code. Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darevay.com/2011/04/20-minute-file-explorer-with-seesaw/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Use enum to define JTable columns</title>
		<link>http://blog.darevay.com/2008/11/use-enum-to-define-jtable-columns/</link>
		<comments>http://blog.darevay.com/2008/11/use-enum-to-define-jtable-columns/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 04:39:21 +0000</pubDate>
		<dc:creator>dave</dc:creator>
				<category><![CDATA[java]]></category>
		<category><![CDATA[swing]]></category>

		<guid isPermaLink="false">http://blog.darevay.com/?p=70</guid>
		<description><![CDATA[Last week while tediously defining another Swing TableModel, I had a little epiphany. Typically, I&#8217;d define column headers, types, etc with a list of integer constants, and some arrays: public class MyTableModel extends AbstractTableModel { private final int NAME_COLUMN = 0; private final int VALUE_COLUMN = 1; private final String NAMES[] = { "Name", "Value" [...]]]></description>
			<content:encoded><![CDATA[<p>Last week while tediously defining another Swing <a href="http://java.sun.com/javase/6/docs/api/javax/swing/table/TableModel.html">TableModel</a>, I had a little epiphany. Typically, I&#8217;d define column headers, types, etc with a list of integer constants, and some arrays:</p>
<pre name="code" class="java">
public class MyTableModel extends AbstractTableModel
{
    private final int NAME_COLUMN = 0;
    private final int VALUE_COLUMN = 1;

    private final String NAMES[] = { "Name", "Value" };
    private final Class CLASSES[] = { String.class, Double.class };

    . . .

   public String getColumnName(int columnIndex)
   {
      return NAMES[columnIndex];
   }

   . . .
}
</pre>
<p>This code is pretty tedious to maintain. In particular, switching column order involves a bunch of changes that are easy to get wrong. How about this instead&#8230; use an <strong>enum</strong> to define the columns!!</p>
<pre name="code" class="java">
public class MyTableModel extends AbstractTableModel
{
    private static enum Columns
    {
        Name(String.class), Value(Double.class);

        final Class<?> klass;

        Columns(Class<?> klass)
        {
             this.klass = klass;
        }
    }

    . . .

   public int getColumnCount() { return Columns.values().length; }

   public Class<?> getColumnClass(int columnIndex)
   {
      return Columns.values()[columnIndex].klass;
   }

   public String getColumnName(int columnIndex)
   {
      return Columns.values()[columnIndex].toString();
   }

   . . .
}
</pre>
<p>Now rearranging column order just works. Furthermore, you can add whatever column-specific functionality you like as methods on the enum. I think this approach can be generified with an interface for the enum to implement and a new abstract table model base class that can handle all the boilerplate above (<code>getColumnCount()</code>, <code>getColumnName()</code>, etc). When I get around to trying it out, I&#8217;ll post an update.</p>
<p>Late breaking: Of course, a quick search reveals <a href="http://www.basilv.com/psd/blog/2006/advanced-uses-of-java-5-enums">I&#8217;m not the first person to think of this</a>. Typical.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.darevay.com/2008/11/use-enum-to-define-jtable-columns/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

