<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.*, tr.object_id FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;, &#039;post_tag&#039;) AND tr.object_id IN (345, 343, 340, 337, 331, 332, 322, 321, 317, 310) ORDER BY t.name ASC</code></p>
			</div><?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.3.1" -->
<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/"
	>

<channel>
	<title>LimeWire Blog</title>
	<link>http://blog.limewire.org</link>
	<description>The LimeWire Blog: Open Source, P2P, Independent Media</description>
	<pubDate>Wed, 10 Jun 2009 17:26:11 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.3.1</generator>
	<language>en</language>
			<item>
		<title>JavaOne Followup</title>
		<link>http://blog.limewire.org/?p=345</link>
		<comments>http://blog.limewire.org/?p=345#comments</comments>
		<pubDate>Wed, 10 Jun 2009 15:16:21 +0000</pubDate>
		<dc:creator>meverett</dc:creator>
		<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;) AND tr.object_id IN (345) ORDER BY t.name ASC</code></p>
			</div><div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;post_tag&#039;) AND tr.object_id IN (345) ORDER BY t.name ASC</code></p>
			</div>
		<guid isPermaLink="false">http://blog.limewire.org/?p=345</guid>
		<description><![CDATA[Thanks for everyone who attended our session at JavaOne 2009.
Anyone who was there knows we promised to post our slides and demo source code. So here you go:

LimeWire: Swing for the Masses.pdf
Guice-Demo.zip
GlazedLists-Demo.zip
JXLayer-Demo.zip
Painting-Demo.zip

If you&#8217;d like to see slides from other talks, all of the slides from JavaOne can be found here.
LimeWire is also open source. So [...]]]></description>
			<content:encoded><![CDATA[<p>Thanks for everyone who attended our session at JavaOne 2009.</p>
<p>Anyone who was there knows we promised to post our slides and demo source code. So here you go:</p>
<ul>
<li><a href="http://blog.limewire.org/wp-content/uploads/2009/06/ts-5162-limewire_swing_for_the_masses.pdf" title="LimeWire: Swing for the Masses.pdf">LimeWire: Swing for the Masses.pdf</a></li>
<li><a href="http://blog.limewire.org/wp-content/uploads/2009/06/javaone-guice.zip" title="Guice-Demo.zip">Guice-Demo.zip</a></li>
<li><a href="http://blog.limewire.org/wp-content/uploads/2009/06/javaone-glazedlists.zip" title="GlazedLists-Demo.zip">GlazedLists-Demo.zip</a></li>
<li><a href="http://blog.limewire.org/wp-content/uploads/2009/06/javaone-jxlayer.zip" title="JXLayer-Demo.zip">JXLayer-Demo.zip</a></li>
<li><a href="http://blog.limewire.org/wp-content/uploads/2009/06/javaone-painting.zip" title="Painting-Demo.zip">Painting-Demo.zip</a></li>
</ul>
<p>If you&#8217;d like to see slides from other talks, all of the slides from JavaOne can be found <a href="http://developers.sun.com/learning/javaoneonline/j1online.jsp?track=embedded&amp;yr=2009" title="here" target="_blank">here</a>.</p>
<p>LimeWire is also open source. So if you would like to see more complex examples of everything done in the demos, be sure to checkout our <a href="http://wiki.limewire.org/index.php?title=Checkcode" title="src" target="_blank">cvs</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.limewire.org/?feed=rss2&amp;p=345</wfw:commentRss>
		</item>
		<item>
		<title>Swing for the Masses</title>
		<link>http://blog.limewire.org/?p=343</link>
		<comments>http://blog.limewire.org/?p=343#comments</comments>
		<pubDate>Thu, 28 May 2009 14:52:21 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
		<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;) AND tr.object_id IN (343) ORDER BY t.name ASC</code></p>
			</div><div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;post_tag&#039;) AND tr.object_id IN (343) ORDER BY t.name ASC</code></p>
			</div>
		<guid isPermaLink="false">http://blog.limewire.org/?p=343</guid>
		<description><![CDATA[Sam and Mike are presenting &#8220;Developing LimeWire: Swing for the Masses&#8221; at JavaOne, this Wednesday at 1:30. Their presentation is for all Swing developers targeting the Java™ 1.6 or later platform and discusses LimeWire’s new UI architecture. It covers tips and examples for using various technologies such as core Swing, SwingX, AppFramework, GlazedLists, and XUL. [...]]]></description>
			<content:encoded><![CDATA[<p>Sam and Mike are presenting &#8220;Developing LimeWire: Swing for the Masses&#8221; at <a href="http://java.sun.com/javaone/" title="JavaOne" target="_blank">JavaOne</a>, this Wednesday at 1:30. Their presentation is for all Swing developers targeting the Java™ 1.6 or later platform and discusses LimeWire’s new UI architecture. It covers tips and examples for using various technologies such as core Swing, SwingX, AppFramework, GlazedLists, and XUL. The session focuses on what is required to easily create good-looking interfaces in Swing.</p>
<p>From their talk, you&#8217;ll get information on:<br />
• SwingX painters - These help customize widget rendering.<br />
• AppFramework - @Resource helps easily change icons and colors.<br />
• Wireframes - Developing a wireframe before adding paint is good.<br />
• Layers - JXLayer or JLayeredPane make great additions.<br />
• Light weight versus heavy weight - Sometimes mixing is a necessary evil.</p>
<p>Hear how the Lime Wire team planned a new interface, fleshed it out and made it all pretty. (We&#8217;ll provide links to the slides and demo code here after the presentation.)</p>
<p>Here&#8217;s LimeWire 5 from the paper prototype through our latest beta:</p>
<p><embed src="http://www.youtube.com/v/tYzGa_AhUgs&amp;hl=en&amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.limewire.org/?feed=rss2&amp;p=343</wfw:commentRss>
		</item>
		<item>
		<title>Create a range slider</title>
		<link>http://blog.limewire.org/?p=340</link>
		<comments>http://blog.limewire.org/?p=340#comments</comments>
		<pubDate>Tue, 19 May 2009 19:19:12 +0000</pubDate>
		<dc:creator>Ernie Yu</dc:creator>
		<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;) AND tr.object_id IN (340) ORDER BY t.name ASC</code></p>
			</div><div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;post_tag&#039;) AND tr.object_id IN (340) ORDER BY t.name ASC</code></p>
			</div>
		<guid isPermaLink="false">http://blog.limewire.org/?p=340</guid>
		<description><![CDATA[The upcoming version of LimeWire adds advanced filtering features to help you refine search results and locate files.  These features display controls to select from several file attributes, such as category, file extension, and file size.  In particular, the file size control uses a dual-thumb slider to allow you to select a range of sizes [...]]]></description>
			<content:encoded><![CDATA[<p>The upcoming version of LimeWire adds advanced filtering features to help you refine search results and locate files.  These features display controls to select from several file attributes, such as category, file extension, and file size.  In particular, the file size control uses a dual-thumb slider to allow you to select a range of sizes to display. <o></o></p>
<pre style="margin-left: 60px">
<img src="http://blog.limewire.org/wp-content/uploads/2009/05/range-slider.png" alt="Slider" /></pre>
<p>In order to create this range slider, we need a new Swing component because the existing JSlider component only displays a single thumb to adjust the slider value.  (Interestingly, even though JSlider only allows you to update a single value, its data model actually provides support for two values that define an internal range within the minimum and maximum bounds. )</p>
<p>The internal range is defined by the slider value and an &#8220;extent&#8221;, which is the length of the inner range that begins at the slider value.  In DefaultBoundedRangeModel, the default &#8220;extent&#8221; is zero and not normally used for anything.  We add it to the slider value to define the upper value of the selected range.</p>
<pre style="margin-left: 60px">public void setUpperValue(int value) {
    // Compute new extent.
    int lowerValue = getValue();
    // Set extent to set upper value.int
    newExtent = Math.min(Math.max(0, value - lowerValue),
    getMaximum() - lowerValue);
    setExtent(newExtent);
}</pre>
<p>Our new dual-thumb slider component takes advantage of the built-in definition for DefaultBoundedRangeModel, and is implemented with just two classes:</p>
<p>-&gt; <strong>RangeSlider</strong> extends JSlider to install a UI delegate and provide value change methods, and</p>
<p>-&gt; <strong>RangeSliderUI</strong> extends BasicSliderUI to paint the two thumbs and handle user events.</p>
<p><strong>RangeSlider</strong> provides methods to set the lower and upper values in the selected range.  We define the existing slider value as the lower value, and the upper value as the lower value plus the extent.  To access these values, we override some methods, and add a couple of our own.</p>
<p>-&gt; We add setUpperValue(int) to calculate the extent based on the current lower value.  We apply limits to ensure that the upper value is bounded by the lower value and the maximum.</p>
<p>-&gt; We override setValue(int) to calculate the extent to ensure that the upper value does not change.  We apply limits to ensure that the lower value stays bounded by the minimum and the upper value.</p>
<p>-&gt; We override updateUI() to install a custom UI delegate to render the two thumbs.</p>
<p><strong>RangeSliderUI</strong> provides a customized rendering of the two thumbs and handles user events to update their values.  This is somewhat involved so we will only highlight the primary aspects of this code.  (Here&#8217;s the source: <a href="http://blog.limewire.org/wp-content/uploads/2009/05/rangesliderdemo.zip" title="Range Slider Demo code">Range Slider Demo code</a>.)</p>
<p>The main tasks are: (1) calculating the thumb sizes and locations, (2) painting the thumbs, and (3) handling mouse and keyboard input events on the thumbs.</p>
<p><strong>Step 1: thumb sizes and locations </strong></p>
<p>To calculate the thumb sizes and locations, we need to override several UI delegate methods.</p>
<p>-&gt; We override installUI(JComponent) to initialize a new upperThumbRect attribute, which we use to store the size and position of the upper thumb.</p>
<p>-&gt; We override calculateThumbSize() to update the size of the upper thumb, which is defined to be the same as the lower thumb.</p>
<p>-&gt; We override calculateThumbLocation() to update the location of the upper thumb, which is based on the upper value stored in the slider component.  The thumb is always positioned to be centered over its value on the track.  The logic is essentially copied from the superclass method and applied to upperThumbRect.</p>
<p>-&gt; We override getThumbSize() to return the dimensions of the thumb.  In LimeWire, we use custom images for our thumbs, although any shape will do.</p>
<p><strong>Step 2: paint</strong></p>
<p>To paint the slider component, we need to override the default implementations of various paint methods in the UI delegate, and add a few of our own.</p>
<p>-&gt; We override paintThumb(Graphics) to do nothing.  This is called by the superclass paint() to draw the single thumb, and we want to replace this with our own logic for two thumbs.</p>
<p>-&gt; We override paint(Graphics, JComponent) to draw the two thumbs as needed.  We define an upperThumbSelected indicator to keep track of which thumb was last selected, so we can draw the unselected thumb first, and draw the selected one on top of it.</p>
<p>-&gt; We add paintLowerThumb(Graphics) and paintLowerThumb(Graphics).  The two methods are similar - they draw a thumb in the appropriate rectangular region.  (The sample code uses a colored shape for the thumb.)</p>
<p>-&gt; We override paintTrack(Graphics) to draw the slider track, and highlight the selected range.</p>
<p><strong>Step 3: handle input</strong></p>
<p>To handle mouse drag events on the thumbs, we define a RangeTrackListener inner class that extends the TrackListener class in BasicSliderUI.  We also override createTrackListener(JSlider) to return a new instance of the class.  In RangeTrackListener, we implement several methods.</p>
<p>-&gt; We override mousePressed(MouseEvent) to detect which thumb is being pressed.</p>
<p>-&gt; We override mouseDragged(MouseEvent) to adjust the appropriate slider value as the thumb is dragged.</p>
<p>-&gt; We override mouseReleased(MouseEvent) to reset indicators.</p>
<p>-&gt; We add moveLowerThumb() and moveUpperThumb() to update the slider values and repaint the thumbs.</p>
<p>Finally, to handle keyboard events on the thumbs, such as the arrow keys, we override a pair of methods used to move the slider by increments.</p>
<p>-&gt; We override scrollByBlock(int) to move the selected thumb by a block increment.  This is called when the Page Up or Page Down key is pressed.</p>
<p>-&gt; We override scrollByUnit(int) to move the selected thumb by a unit increment.  This is called when one of the arrow keys is pressed.</p>
<p><strong>Summary</strong></p>
<p>The dual-thumb slider component allows you to select a range by adjusting its lower and upper bounds.  And by implementing our own UI delegate, we can adjust the appearance of the component to suit our needs.  (This can be very useful when working with visual designers who are creating a unique vision.)</p>
<p>Check out the <a href="http://blog.limewire.org/wp-content/uploads/2009/05/rangesliderdemo.zip" title="Range Slider Demo code">Range Slider Demo code</a> which contains a complete example of <strong>RangeSlider</strong> and <strong>RangeSliderUI</strong>, minus the custom images we use for the thumbs in LimeWire.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.limewire.org/?feed=rss2&amp;p=340</wfw:commentRss>
		</item>
		<item>
		<title>On the Fly Thumbnail Creation</title>
		<link>http://blog.limewire.org/?p=337</link>
		<comments>http://blog.limewire.org/?p=337#comments</comments>
		<pubDate>Thu, 09 Apr 2009 16:30:18 +0000</pubDate>
		<dc:creator>meverett</dc:creator>
		<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;) AND tr.object_id IN (337) ORDER BY t.name ASC</code></p>
			</div><div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;post_tag&#039;) AND tr.object_id IN (337) ORDER BY t.name ASC</code></p>
			</div>
		<guid isPermaLink="false">http://blog.limewire.org/?p=337</guid>
		<description><![CDATA[One of the features we added into LimeWire 5 was a thumbnail view for images which solves a lot of problems. In older versions, images appeared as a list of filenames. There are few problems with this.
1)  Most images are poorly named. Digital cameras have not helped this at all; it&#8217;s impossible to remember that [...]]]></description>
			<content:encoded><![CDATA[<p>One of the features we added into LimeWire 5 was a thumbnail view for images which solves a lot of problems. In older versions, images appeared as a list of filenames. There are few problems with this.</p>
<p>1)  Most images are poorly named. Digital cameras have not helped this at all; it&#8217;s impossible to remember that the photo from last night of you and your friend is named IMG_00101.</p>
<p>2) This can result in inadvertent file sharing which is something we tried to prevent in the newest LimeWire. Try remembering if you wanted to share IMG_00101 or was it IMG_001101.</p>
<p>3)  This is just a bad user experience. Images are meant to be seen.</p>
<p><a href="http://blog.limewire.org/?attachment_id=339" rel="attachment wp-att-339" title="blogimage2.PNG"><img src="http://blog.limewire.org/wp-content/uploads/2009/04/blogimage2.PNG" alt="blogimage2.PNG" /></a></p>
<p>There have been some very good <a href="http://today.java.net/pub/a/today/2007/04/03/perils-of-image-getscaledinstance.html" title="The Perils of Image.getScaledInstance()" target="_blank">articles</a>  and <a href="http://filthyrichclients.org/" title="Filthy Rich Clients" target="_blank">books</a> that discuss the proper way to load and scale images. They especially point out the fact that you should never use <strong>Image.getScaledInstance()</strong>. So I will reiterate that point, don&#8217;t use <strong>Image.getScaledInstance()</strong>. For details on why and the alternative methods follow one of the links above which give very good explanations and alternatives for scaling images.</p>
<p>For the thumbnails in LimeWire 5, we use a modified version of the <strong>getFasterScaledInstance()</strong> in the book, <em>Filthy Rich Clients</em>. This creates high quality thumbnails in a relatively short period of time. I was occasionally running into three different problems,</p>
<p>1) the thumbnails were being created relatively fast but not quite fast enough. This became more noticeable as the file size of the image increased (the solution was going to be write the thumbnails to disk for future use).</p>
<p>2) large images were occasionally failing to load. This was occurring very randomly where the same set of images would fail 20% of the time, and</p>
<p>3) when creating large numbers of thumbnails Out Of Memory exceptions would start happening.</p>
<p>After reading many articles and forums, I came to a solution that solved all three of these problems. The solution we use is to perform <strong>subsampling </strong>on large images. Subsampling is a process of reading every nth pixel in every nth line. The technique alone is a bit crude for creating thumbnails. All you can specify is the number of lines to skip in an image. So a subsampling factor of 1 will read every line, a subSampling factor of 2 will read every other line, etc. Alone this technique doesn&#8217;t produce very nice results, however used in combination with the <strong>getFasterScaledInstance(),</strong> it creates high quality thumbnails very fast and all the failed image loads and OOM exceptions nicely disappeared.</p>
<p>Below is the code that we use to read an image into a <strong>BufferedImage</strong> prior to calling <strong>getFasterScaledInstance()</strong> to create the final thumbnail.</p>
<pre style="margin-left: 60px">
private static final float subSamplingFactor = ThumbnailManager.WIDTH * 4.20f;<font color="#339966">
/**
 * Loads a file into a BufferedImage. If the image is longer than a subSamplingFactor,
 * rows are sampled out to reduce the size of the BufferedImage. This can go a long way
 * towards reducing OutOfMemoryExceptions when loading large compressed images.
 */</font>
private BufferedImage getSubSampleImage(File file) throws FileNotFoundException, IOException {
    BufferedImage image;
    ImageInputStream imageInputStream = null;
    try {
        final ImageReader imgReader = ImageIO.getImageReadersBySuffix(FileUtils.getFileExtension(file)).next();
        imageInputStream = ImageIO.createImageInputStream(new BufferedInputStream(new FileInputStream(file)));
        imgReader.setInput(ImageInputStream);
        int longEdge = (Math.max(imgReader.getHeight(0), imgReader.getWidth(0)));
        int subSample = (int)(longEdge/subSamplingFactor);
        final ImageReadParam readParam = imgReader.getDefaultReadParam();<font color="#339966">
        // subSample the image</font>
        if(subSample &gt; 1) {
            readParam.setSourceSubsampling(subSample, subSample, 0, 0);
        }
        image = imgReader.read(0, readParam);
    } finally {
        if(imageInputStream != null)
            imageInputStream.close();
    }
    return image;
}</pre>
<p>Using this technique, we ensure that all images we read and pass to the <strong>getFasterScaledInstance()</strong> will always be a reasonable size. Our <strong>subSamplingFactor</strong> works on a sliding scale so as the image gets larger, more and more lines are skipped when first being read. Using this two step process allows enough information to be left in the original <strong>BufferedImage</strong> for <strong>getFasterScaledInstance()</strong> to produce a crisp image.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.limewire.org/?feed=rss2&amp;p=337</wfw:commentRss>
		</item>
		<item>
		<title>MigLayout, how to make a panel float</title>
		<link>http://blog.limewire.org/?p=331</link>
		<comments>http://blog.limewire.org/?p=331#comments</comments>
		<pubDate>Fri, 13 Mar 2009 21:39:17 +0000</pubDate>
		<dc:creator>meverett</dc:creator>
		<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;) AND tr.object_id IN (331) ORDER BY t.name ASC</code></p>
			</div><div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;post_tag&#039;) AND tr.object_id IN (331) ORDER BY t.name ASC</code></p>
			</div>
		<guid isPermaLink="false">http://blog.limewire.org/?p=331</guid>
		<description><![CDATA[Take a look at the image below. There are three major components: a top header that spans the width, a left hand nav and a main panel that fills the remaining width and height. It would be pretty easy to lay out these three components using BorderLayout.

Now suppose we wanted to add a floating component [...]]]></description>
			<content:encoded><![CDATA[<p>Take a look at the image below. There are three major components: a top header that spans the width, a left hand nav and a main panel that fills the remaining width and height. It would be pretty easy to lay out these three components using BorderLayout.</p>
<p><a href="http://blog.limewire.org/?attachment_id=333" rel="attachment wp-att-333" title="floating1.PNG"><img src="http://blog.limewire.org/wp-content/uploads/2009/03/floating1.PNG" alt="floating1.PNG" /></a></p>
<p>Now suppose we wanted to add a floating component over top of these. The idea is this floating component would be centered both vertically and horizontally regardless of how big the parent grew.</p>
<p><a href="http://blog.limewire.org/?attachment_id=334" rel="attachment wp-att-334" title="floating2.PNG"><img src="http://blog.limewire.org/wp-content/uploads/2009/03/floating2.PNG" alt="floating2.PNG" /></a></p>
<p><a href="http://blog.limewire.org/?attachment_id=335" rel="attachment wp-att-335" title="floating3.PNG"><img src="http://blog.limewire.org/wp-content/uploads/2009/03/floating3.PNG" alt="floating3.PNG" /></a></p>
<p><a href="http://blog.limewire.org/?attachment_id=336" rel="attachment wp-att-336" title="floating4.PNG"><img src="http://blog.limewire.org/wp-content/uploads/2009/03/floating4.PNG" alt="floating4.PNG" /></a></p>
<p>There are a few different ways to achieve this effect.</p>
<p><strong>GlassPane</strong>: One way would be to use the GlassPane. Position the first three components using BorderLayout and then add the floating component in the GlassPane. This works but fails if the three components don&#8217;t fill the entire screen. It also prevents you from using the GlassPane for something else (like ghost dragging for example).</p>
<p><strong>JXLayer</strong>: Another approach would be to use the JXLayer. This certainly works but is a bit code heavy for simple uses.</p>
<p><strong>StackLayout </strong>: A third approach might be to use the StackLayout found in the SwingX jar. This is a relatively simple solution but has the downside of still needing to use three layout managers, one for the first three components, one for the floating component and finally the StackLayout to put the two together. This of course creates excess components for the sake of laying out components, something we would like to avoid.</p>
<p>Let&#8217;s solve this problem using MigLayout. As I mentioned in a previous <a href="http://blog.limewire.org/?p=310" target="_blank" title="MigLayout">post</a>, MigLayout allows us to mix different types of layouts in the same manager. So we will use the docking layout to layout the top and left components, the grid layout for the center component, then relative positioning to layout the floating component. Here&#8217;s how the code looks:</p>
<pre> setLayout(new MigLayout("gap 0, insets 0, fill"));
 add(createFloatingPanel(), "pos 0.50al 0.5al");
 add(createPanel("Top", Color.yellow), "dock north");
 add(createPanel("Left", Color.red), "dock west");
 add(createPanel("Center", Color.green), "grow");</pre>
<p>That&#8217;s all it takes, five lines of code and no extra components.  The most important features in the constructor is the use of the keyword &#8220;fill&#8221; which ensures that we take up all the space in the parent.</p>
<p>Let&#8217;s look at the docking components. Using the keyword &#8220;dock&#8221; along with &#8220;north&#8221; &amp; &#8220;west&#8221; act like BorderLayout. Adding the north component first ensures that it fills the horizontal space rather than the west component filling the vertical space. We then add the center component using the generic grid layout with the keyword &#8220;grow&#8221;. This ensures that the center component will fill any remaining space.</p>
<p>The most interesting thing here is the pos .5al .5al. This tells the floating panel to ignore the grid positioning. Instead it aligns it 50% vertically and 50% horizontally within the parent container.</p>
<p>Five lines of code to again achieve a pretty impressive layout. Two important things to note here:</p>
<p>1) Notice that the floating panel is added first. If it&#8217;s added after the other components, it will be drawn behind them.</p>
<p>2) This technique won&#8217;t always work. If one of the components behind the floating panel is a JTable or JList which contains cell Renderers, then this layout method will fail.</p>
<p>In LW 5, we use this miglayout technique whenever there isn&#8217;t a table or list behind a floating component and use JXLayer to achieve the same effect when there is a table or list.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.limewire.org/?feed=rss2&amp;p=331</wfw:commentRss>
		</item>
		<item>
		<title>LimeWire @ JavaOne</title>
		<link>http://blog.limewire.org/?p=332</link>
		<comments>http://blog.limewire.org/?p=332#comments</comments>
		<pubDate>Fri, 27 Feb 2009 23:33:57 +0000</pubDate>
		<dc:creator>sam</dc:creator>
		<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;) AND tr.object_id IN (332) ORDER BY t.name ASC</code></p>
			</div><div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;post_tag&#039;) AND tr.object_id IN (332) ORDER BY t.name ASC</code></p>
			</div>
		<guid isPermaLink="false">http://blog.limewire.org/?p=332</guid>
		<description><![CDATA[Yesterday I got an email from Sun that a talk I submitted for JavaOne titled, &#8220;Developing LimeWire: Swing for the Masses&#8221; was accepted!  (If you follow LimeWire&#8217;s twitter account, you already know.)  Pretty nifty, considering it&#8217;s the first time I (or anyone here) has submitted a proposal to talk at JavaOne.  Mike E &#38; I [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday I got an email from Sun that a talk I submitted for JavaOne titled, &#8220;Developing LimeWire: Swing for the Masses&#8221; was accepted!  (If you follow <a href="http://twitter.com/limewiredev" title="LimeWire's Twitter account">LimeWire&#8217;s twitter account</a>, you already know.)  Pretty nifty, considering it&#8217;s the first time I (or anyone here) has submitted a proposal to talk at JavaOne.  Mike E &amp; I are going to be giving the presentation.  Here&#8217;s a short teaser of the abstract, &#8220;LimeWire is arguably the most popular Swing application around.  With more than 10 million unique LimeWire users per day from all over the world, the technology behind LimeWire has to be stable and the interface has to appeal to all audiences.  LimeWire recently rebuilt the entire interface from scratch, using Swing.&#8221;  We&#8217;ll cover how and why LimeWire 5 was created, including details about how we used SwingX, AppFramework, and much more.</p>
<p>See you at JavaOne!.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.limewire.org/?feed=rss2&amp;p=332</wfw:commentRss>
		</item>
		<item>
		<title>Great People lead to great things</title>
		<link>http://blog.limewire.org/?p=322</link>
		<comments>http://blog.limewire.org/?p=322#comments</comments>
		<pubDate>Fri, 06 Feb 2009 20:02:09 +0000</pubDate>
		<dc:creator>sam</dc:creator>
		<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;) AND tr.object_id IN (322) ORDER BY t.name ASC</code></p>
			</div><div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;post_tag&#039;) AND tr.object_id IN (322) ORDER BY t.name ASC</code></p>
			</div>
		<guid isPermaLink="false">http://blog.limewire.org/?p=322</guid>
		<description><![CDATA[Editor&#8217;s note: this blog is another account of the LW 5 Post Mortem.
Some things That Went Right
The LimeWire client team has some amazing people on it. Every single person on the team cares about the quality of the product, code, and the other people. It&#8217;s easy to find someone who just cares about one of [...]]]></description>
			<content:encoded><![CDATA[<p><em>Editor&#8217;s note: this blog is another account of the <a href="http://blog.limewire.org/?p=317" target="_blank" title="LW 5 Post Mortem">LW 5 Post Mortem</a>.</em></p>
<p><strong>Some things That Went Right</strong></p>
<p>The LimeWire client team has some amazing people on it. Every single person on the team cares about the quality of the product, code, and the other people. It&#8217;s easy to find someone who just cares about one of those three things &#8212; but it&#8217;s incredibly hard to build a team of people who care about all of them.</p>
<p>There&#8217;s no way that LimeWire 5 could exist without the work that every person on the team put forward. I think back to what each individual worked on, how hard they worked, and I can&#8217;t help but be bewildered at the incredibly ease with which LimeWire 5 came together. What follows are just small tidbits of what each person worked on, but they highlight how a distributed effort came together seamlessly.</p>
<p>David worked on rewriting the &#8220;search&#8221; logic so that a keyword search could apply to all metadata. That single piece of code enabled a simple single search box. Tim worked on integrating XMPP code. Once 5 took shape, the XMPP code became the fundamental basis for all friend features. Felix started using event listeners in a new way &#8230; suddenly the entire UI and much of the core became event-based and loosely coupled in a way that pushed development at a faster pace. I spent a weekend and wrote the frame &amp; code framework for the new UI and another weekend giving it some rudimentary paint, shortly afterward progress on the UI skyrocketed. Peter tackled every odd &amp; end you can imagine, getting drag &amp; drop working, fixing file associations, adding system notifications, and much more. Matt was the first person actively start working on 5. He located and integrated the MozSwing browser, which is why LimeWire can integrate so nicely with webpages. Mario figured out how to do crazy tricks so that search results can be shown in a highly interactive list view. Dan worked tirelessly to reproduce bugs and QA our fixes. Mike E rewrote the way LimeWire handles file management, creating multiple &#8220;file lists&#8221; instead of a single &#8220;shared with gnutella&#8221; list, ultimately paving the way for sharing with friends. Michael R dove into the XMPP code and made sure it worked with arbitrary servers, letting us add an &#8220;Other&#8221; option that actually works. Michael T became our &#8220;master painter&#8221; and learned all about ways to make Swing look pretty. Mike S spent insane amounts of time writing UI specifications and gauging user feedback. Ernie spent his first week here writing the advanced panels, so people can still get the look and feel of the old LimeWire. Peng continued studying the DHT to see if there were ways to improve LimeWire&#8217;s use of it. Anthony designed mock screenshot after mock screenshot as templates for the developers. Jorge developed a ton of new icons to keep the look and feel fresh.</p>
<p>Every single person worked on things so disparate, all with a common purpose. We had a few things going for us: the code was designed so that UI developers could work against interfaces instead of directly against the core and for rapid development, we created a &#8220;mock core&#8221; and reused it during usability tests.</p>
<p>Still, the best code design in the world is nothing without great people. I&#8217;m proud of the team, and proud that we worked together and in an amazing display of cooperation.</p>
<p><strong>LW 5 Needs Fixing tasks</strong></p>
<p>10/16:</p>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/02/tasks1.png" alt="tasks1.png" /></p>
<p>11/12:</p>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/02/tasks2.png" alt="tasks2.png" /></p>
<p>12/29:</p>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/02/tasks3.png" alt="tasks3.png" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.limewire.org/?feed=rss2&amp;p=322</wfw:commentRss>
		</item>
		<item>
		<title>Usability interviews and tests</title>
		<link>http://blog.limewire.org/?p=321</link>
		<comments>http://blog.limewire.org/?p=321#comments</comments>
		<pubDate>Thu, 05 Feb 2009 22:18:20 +0000</pubDate>
		<dc:creator>Dan</dc:creator>
		<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;) AND tr.object_id IN (321) ORDER BY t.name ASC</code></p>
			</div><div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;post_tag&#039;) AND tr.object_id IN (321) ORDER BY t.name ASC</code></p>
			</div>
		<guid isPermaLink="false">http://blog.limewire.org/?p=321</guid>
		<description><![CDATA[Editor&#8217;s note: this blog is another account of the LW 5 Post Mortem.
Some things That Went Right
Who&#8217;s your audience and what do they want?
I&#8217;ve read about it, seen the tire swing cartoon and heard co-workers mention the customer is key, but it was always lip service everywhere I worked. At least until the user experience [...]]]></description>
			<content:encoded><![CDATA[<p><em>Editor&#8217;s note: this blog is another account of the <a href="http://blog.limewire.org/?p=317" target="_blank" title="LW 5 Post Mortem">LW 5 Post Mortem</a>.</em></p>
<p><strong>Some things That Went Right</strong></p>
<p>Who&#8217;s your audience and what do they want?</p>
<p>I&#8217;ve read about it, seen the <a href="http://www.cubiccompass.com/blogs/main/content/binary/TireSwingCartoon.png" title="What the user wanted" target="_blank">tire swing cartoon</a> and heard co-workers mention the customer is key, but it was always lip service everywhere I worked. At least until the user experience guy brought in over 50 people for usability tests.</p>
<p>He interviewed power users who saw the Internet as a requirement in their life, people who used LW all the time, and users who never heard of LW. He asked them what they liked about software in general, what they thought about new software versions, what they wanted from programs. Then he asked them to perform a series of steps in front of a computer while staffers took notes to see what was confusing.</p>
<p>The interviews came at all stages of development &#8230; before a single decision about LW 5 was made, before any software was coded (we had paper prototypes where people had to simulate clicking or typing and I acted like a chose your own adventure book flipping to the proper next page), throughout code development and before launching.</p>
<p>LW 5 changed after each usability test. Originally there were two search bars but since no one used the one on the left, it was zapped. At first there were icons galore that some liked, but most found it was too much, so we tapered. Also, people had trouble finding how to sign into Friends. Some didn&#8217;t like the colors and expected it to be more limey &#8230; others didn&#8217;t like the download status on the left and wanted it more like the old version across the bottom of the UI.</p>
<p>In addition to the usability tests, the LimeWire forums gave a lot of feedback, helped find edge cases we missed, and steered LW 5 to be a product they wanted to use. More feedback is coming daily and the team is listening and responding &#8230;</p>
<p>LimeWire 5 and its UI evolved as we received user feedback.</p>
<p>Paper prototype, two search boxes:</p>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/02/lw5_1.png" alt="LW5" /></p>
<p>Downloads on the side:</p>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/02/lw5_2.png" alt="LW5" /></p>
<p>Too many icons and not limey enough:</p>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/02/lw5_3.png" alt="LW5" /></p>
<p>Friends sign in hard to find:</p>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/02/lw5_4.png" alt="LW5" /></p>
<p>Getting there &#8230; but it&#8217;s sure to evolve.</p>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/02/lw5_5.png" alt="LW5" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.limewire.org/?feed=rss2&amp;p=321</wfw:commentRss>
		</item>
		<item>
		<title>LW 5: Post Mortem</title>
		<link>http://blog.limewire.org/?p=317</link>
		<comments>http://blog.limewire.org/?p=317#comments</comments>
		<pubDate>Wed, 04 Feb 2009 21:40:12 +0000</pubDate>
		<dc:creator>Mike S</dc:creator>
		<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;) AND tr.object_id IN (317) ORDER BY t.name ASC</code></p>
			</div><div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;post_tag&#039;) AND tr.object_id IN (317) ORDER BY t.name ASC</code></p>
			</div>
		<guid isPermaLink="false">http://blog.limewire.org/?p=317</guid>
		<description><![CDATA[It&#8217;s a July afternoon and Sam, our team lead, called a meeting. He&#8217;s got a smile and he starts writing dates on the board. Alpha: in months, Beta: a few weeks later. Final release: Christmas 2008. The remainder of the team is in silence, just nodding their heads in agreement at him while we were [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s a July afternoon and Sam, our team lead, called a meeting. He&#8217;s got a smile and he starts writing dates on the board. Alpha: in months, Beta: a few weeks later. Final release: Christmas 2008. The remainder of the team is in silence, just nodding their heads in agreement at him while we were all thinking the same thing to ourselves: &#8220;Is he f*%&amp;!ing crazy?&#8221;</p>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/02/lw5schedule.jpg" alt="LW 5 Schedule" /></p>
<p>The next few blog posts are about the gritty details of taking LimeWire, the 9 year old product that 60 million users have come to love, and having a hard look at it. We&#8217;ll talk about how we did a complete redesign of the user&#8217;s experience and front-end code, integrated social features, and reworked the way we develop software. What went right and how it couldn&#8217;t have gone better &#8230; and how when something went wrong &#8230; it really went wrong.</p>
<p><strong>Some things That Went Right</strong></p>
<p><strong>Iterative design in development, </strong>by Mike S</p>
<p>&#8220;Redoing this UI has been a pipe dream for me&#8221;, Sam said.</p>
<p>Two year ago, the LimeWire team was 4 developers. One year later (when I first started), the team grew to about 6 developers, 1 technical writer and 1 user experience designer. Currently, we have a team of 17 people: 6 network developers, 4 core developers, 2 UI developers, 2 visual designers, a user experience designer, a technical writer and a product manager.</p>
<p>The point isn&#8217;t that more people build a better product, but getting people of varying skills help make the best product possible. Developers constantly questioned one another about the best way to code something, I questioned when the visual design was excessively &#8220;artsy&#8221;, the developers questioned things I came up with wanting more power, and Anthony, our visual designer, told me I am over thinking the solution to a problem. There was a checks and balances system in place and even though there were countless arguments and disagreements (and there still are &#8212; even after the release), just having different people thinking about different things helped make sure that we weren&#8217;t doing one thing that just one person really wanted.</p>
<p>For this release, we tried to give focus to answer the question, &#8220;What is LimeWire?&#8221; Once we did some initial user research, surveys, scenarios, requirements, we started wire-frames, doing paper prototype usability tests, and then eventually building a flash prototype that we tested with users. All before any front-end swing code was written. In the meantime, the developers tested front-end toolkits and made all the back-end changes that were needed to get this design up and running. Once we were ready to integrate, I wrote interaction spec documents that got handed off to the developers. While they were doing that, Anthony wrote visual spec documents. By the time he finished those, the developers were done with my specs and they started on his. We got into a great circular flow between the developers and designers.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.limewire.org/?feed=rss2&amp;p=317</wfw:commentRss>
		</item>
		<item>
		<title>3 Reasons to love MigLayout</title>
		<link>http://blog.limewire.org/?p=310</link>
		<comments>http://blog.limewire.org/?p=310#comments</comments>
		<pubDate>Fri, 30 Jan 2009 19:31:32 +0000</pubDate>
		<dc:creator>meverett</dc:creator>
		<div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;category&#039;) AND tr.object_id IN (310) ORDER BY t.name ASC</code></p>
			</div><div id='error'>
			<p class='wpdberror'><strong>WordPress database error:</strong> [Got error 28 from storage engine]<br />
			<code>SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN wp_term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN (&#039;post_tag&#039;) AND tr.object_id IN (310) ORDER BY t.name ASC</code></p>
			</div>
		<guid isPermaLink="false">http://blog.limewire.org/?p=310</guid>
		<description><![CDATA[One of my favorite new libraries we added to LimeWire 5 is MigLayout. I had never used MigLayout but it was always one of those libraries I was interested in trying and it always seems to popup in blog posts and articles. I added the MigLayout jar to my local repository and fell in love [...]]]></description>
			<content:encoded><![CDATA[<p>One of my favorite new libraries we added to LimeWire 5 is MigLayout. I had never used MigLayout but it was always one of those libraries I was interested in trying and it always seems to popup in blog posts and articles. I added the MigLayout jar to my local repository and fell in love with it instantly. Within a few weeks of adding it to CVS, all the developers were using it almost exclusively.</p>
<p><strong>Why MigLayout?</strong></p>
<p>There are dozens of layout managers so why is this one so special? There are three main reasons:</p>
<p>1) it&#8217;s extremely powerful. You can easily mimic everything from Gridbag Layout to BorderLayout to FlowLayout to Absolute Layout.</p>
<p>2) it&#8217;s extremely simple. There&#8217;s a handful of keywords and concepts to learn and most of the API can be committed to memory very quickly.</p>
<p>3) you don&#8217;t need any special plugins to layout or modify the code and you can use it virtually everywhere you need a layout manager.</p>
<p><strong>Quick Overview</strong></p>
<p>There are essentially three different ways to arrange components in MigLayout:</p>
<p>1) The default and most common usage is to treat the space as a grid with columns and rows. Components can be added to rows and columns and can span multiple rows and columns.</p>
<p>2) You can also mimic BorderLayout with docking components to the north, south, center, etc.</p>
<p>3) You can use absolute positioning. This allows you to place components in relation to the parent container or in relation to other components in the container.</p>
<p>The best part is you can combine all of these arrangements in a single component. You could, for instance, dock a component to the top, then use the grid to layout the remaining components below that. For a much more detailed overview, check out the tutorials at <a target="_blank" href="http://www.miglayout.com/" title="http://www.miglayout.com/">http://www.miglayout.com/</a>.</p>
<p><strong>Docking with MigLayout</strong></p>
<p>This code mimics BorderLayout. The main difference is MigLayout allows you to add multiple components to the same area. In this case there are two components added using &#8220;dock north&#8221;. This is extremely useful since it allows you to perform complex layouts without wrapping components inside of a JPanel for the sake of laying out components. Notice that the order in which components are added effects how they are displayed, the first &#8220;North&#8221; panel fills the entire X-axis while the &#8220;North 2&#8243; panel is bookmarked between &#8220;West&#8221; and &#8220;East&#8221; since it was added after those components.</p>
<blockquote><p><font color="#339966">//it&#8217;s important to note the order in which the components are added<br />
//effects their width and height in relation to other components</font><br />
setLayout(new MigLayout(&#8221;fill&#8221;));<br />
add(createPanel(&#8221;North&#8221;), &#8220;dock north&#8221;);<br />
add(createPanel(&#8221;East&#8221;), &#8220;dock east&#8221;);<br />
add(createPanel(&#8221;West&#8221;), &#8220;dock west&#8221;);<br />
add(createPanel(&#8221;North 2&#8243;), &#8220;dock north&#8221;);<br />
add(createPanel(&#8221;Center&#8221;), &#8220;dock center&#8221;);</p></blockquote>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/01/docking.PNG" alt="MigLayout Docking" /></p>
<p><strong>Flow Layout</strong></p>
<p>This code mimics Flow Layout in both the horizontal and vertical direction. The only difference between vertical and horizontal is we add the keyword &#8220;wrap&#8221;. The &#8220;wrap&#8221; keyword tells the next component added to begin on a new row in the layout grid.</p>
<blockquote><p>setLayout(new MigLayout(&#8221;fill&#8221;));<br />
<font color="#339966">//grow tells the component to fill its entire grid space</font><br />
add(createPanel(&#8221;Item 1&#8243;), &#8220;grow&#8221;);<br />
add(createPanel(&#8221;Item 2&#8243;), &#8220;grow&#8221;);<br />
add(createPanel(&#8221;Item 3&#8243;));<br />
add(createPanel(&#8221;Item 4&#8243;), &#8220;grow&#8221;);<br />
add(createPanel(&#8221;Item 5&#8243;), &#8220;grow&#8221;);</p></blockquote>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/01/flowlayout.PNG" alt="MigLayout Flow Layout" /></p>
<blockquote><p><font color="#339966">//wrap set on the constructor will put each<br />
//component added on its own row in the grid</font><br />
setLayout(new MigLayout(&#8221;fill, wrap&#8221;));<br />
add(createPanel(&#8221;Item 1&#8243;), &#8220;grow&#8221;);<br />
add(createPanel(&#8221;Item 2&#8243;), &#8220;grow&#8221;);<br />
add(createPanel(&#8221;Item 3&#8243;));<br />
add(createPanel(&#8221;Item 4&#8243;), &#8220;grow&#8221;);<br />
add(createPanel(&#8221;Item 5&#8243;), &#8220;grow&#8221;);</p></blockquote>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/01/verticalflowlayout.PNG" alt="MigLayout Vertical Flow Layout" /></p>
<p><strong>More Complicated Layouts</strong></p>
<p>These are rather trivial uses of MigLayout. The real power comes when you want to layout something a bit more complex. Typically you&#8217;d find Gridbag Layout being used for this or nested Border Layouts. The result usually ends up being very verbose and hard to maintain. If you notice, I add 7 components to the container and have only 7 lines of code. MigLayout provides a very clean, readable, and easily modified code base while laying out a rather complex component.</p>
<blockquote><p><font color="#339966">// fill entire space provided, 2 pixel gap between components and<br />
// 10 pixel insets from all edges</font><br />
setLayout(new MigLayout(&#8221; fill, insets 10, gap 2&#8243;));<br />
<font color="#339966">// first line<br />
// </font><font color="#339966">span all the columns, </font><font color="#339966">wrap: put next component on the next row</font><br />
add(createLabel(&#8221;Login&#8221;), &#8220;span, wrap&#8221;);<br />
<font color="#339966">// second line<br />
// textfield should fill the remaining horizontal space</font><br />
add(createLabel(&#8221;User Name&#8221;));<br />
add(createTextField(), &#8220;growx, wrap&#8221;);<br />
<font color="#339966">// third line<br />
// passfield should fill the remaining horizontal space</font><br />
add(createLabel(&#8221;Password&#8221;));<br />
add(createPasswordField(), &#8220;growx, wrap&#8221;);<br />
<font color="#339966">// fourth line<br />
// ok skips first column, split puts ok/cancel button in same cell<br />
// using tag: ok/cancel allows miglayout to swap their order based on the OS preference</font><br />
add(createButton(&#8221;Ok&#8221;), &#8220;skip 1, split, alignx right, tag ok&#8221;);<br />
add(createButton(&#8221;Cancel&#8221;), &#8220;tag cancel&#8221;);</p></blockquote>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/01/basicmiglayout.PNG" alt="basicmiglayout.PNG" /></p>
<p>Finally, adding the keyword &#8220;debug&#8221; to the constructor, allows you to visually see what&#8217;s going on internally. The red lines outline each cell in the grid, while the blue lines outline how that particular component fills its cell. Here you can see there are four rows and two columns. Comparing it to the code, you can see the login label spans two columns, the ok/cancel are put into the same cell and skip the first column, you can also see the 2 pixel gap between rows/columns and the 10 pixel inset. This is such an amazing feature and has saved me countless hours while trying to figure out complex layouts.</p>
<p><img src="http://blog.limewire.org/wp-content/uploads/2009/01/basicdebugmiglayout.PNG" alt="basicdebugmiglayout.PNG" /></p>
<p>Hopefully it gave you a feel for how powerful MigLayout is while also having very clean and readable code. Here&#8217;s the source code for the demos: <a href="http://blog.limewire.org/wp-content/uploads/2009/01/miglayout-demo-src.zip" title="miglayout-demo-src.zip">miglayout-demo-src.zip</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.limewire.org/?feed=rss2&amp;p=310</wfw:commentRss>
		</item>
	</channel>
</rss>
