<?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>Hexapixel &#187; Articles</title>
	<atom:link href="http://hexapixel.com/category/articles/feed" rel="self" type="application/rss+xml" />
	<link>http://hexapixel.com</link>
	<description>Programming, Eclipse, SWT and everything inbetween</description>
	<lastBuildDate>Tue, 06 Sep 2011 13:21:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>XAML in SWT / Where The Ribbon Is</title>
		<link>http://hexapixel.com/2010/01/06/xaml-in-swt-and-where-the-ribbon-is</link>
		<comments>http://hexapixel.com/2010/01/06/xaml-in-swt-and-where-the-ribbon-is#comments</comments>
		<pubDate>Wed, 06 Jan 2010 15:04:11 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Eclipse Articles]]></category>
		<category><![CDATA[SWT]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=826</guid>
		<description><![CDATA[I get loads of traffic and email thanks the Ribbon. It&#8217;s truly an alpha project that went completely beyond what I had imagined. It&#8217;s exciting of course, but as much as it should give me a warm fuzzy feeling, it actually makes me rather nauseous. The thing is, a lot of the code is a [...]]]></description>
			<content:encoded><![CDATA[<p>I get loads of traffic and email thanks the Ribbon. It&#8217;s truly an alpha project that went completely beyond what I had imagined. It&#8217;s exciting of course, but as much as it should give me a warm fuzzy feeling, it actually makes me rather nauseous. The thing is, a lot of the code is a total mess, it&#8217;s embarrassing, and I&#8217;ll freely admit it. It was never written as a &#8220;thought out&#8221; project, it was simply written as a not-so-quick &#8220;test&#8221; to see if it was possible to do a Ribbon component in pure SWT. The answer was &#8220;kind of&#8221;, and that&#8217;s where it got left off.</p>
<p>After having worked with <a href="http://silverlight.net/" target="_new">Microsoft Silverlight</a> and <a href="http://en.wikipedia.org/wiki/Extensible_Application_Markup_Language" target="_new">XAML</a> lately I realized how simple XAML makes it to do stuff that I spent hours writing code for in the Ribbon. For example; rounded corners, gradient borders, multi-gradient fills, etc. It&#8217;s a pleasure to work with, easy to change, and it moves you forward at a good pace &#8211; and that&#8217;s how I feel it should be. I doubt anyone would download the Ribbon source as it is now, look at the render classes and think &#8220;great, I&#8217;ll make a change riiiight here&#8221;, it&#8217;s just too complicated and non-customizable. A user wanting to change colors would have to spend hours, days even, just to figure out what pixel is drawn where, and when I look at the code now, I get the same feelings.</p>
<p>Instead of continuing work on the Ribbon to finish &#8220;the mess&#8221;, I decided that if it was ever going to finish the project and take it out of Alpha, I was going to do all the rendering stuff the right way. And thus started a little test project with Brushes with the intention that if I could make things as easy as writing XAML, I could write all the Ribbon widgets in no-time.</p>
<p><span id="more-826"></span><br />
<h3>Brushes</h3>
<p>A Brush object in XAML (and in a lot of other languages) is like a paint brush, it defines a direction and a stroke, colors, etc. The Ribbon basically uses a whole ton of Brushes.</p>
<p>Here&#8217;s a quick list of the things that the Ribbon currently uses lots of:</p>
<ul>
<li>2-color and Multi-color gradients in Horizontal and Vertical orientation, there are no diagonal or radial gradients (although brushes in XAML support any angle).</li>
<li>&#8220;Border&#8221; controls that contain other controls (pretty much all controls have some sort of border around them). A Border control in <a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation" target="_new">WPF</a> is a control that can contain only 1 other control, and it can display a border and a background and allows for rounding of the borders.</li>
<li>Various paddings and margins between controls to space them out between one another.</li>
<li>Colors, colors and more colors.</li>
</ul>
<p>If you think about it, that&#8217;s pretty much any control in an normal GUI library as at some level of the OS, there will be a programmatic &#8220;pen&#8221; that is drawing everything you see, pixel by pixel. Everything built on top of that is convenience to the user. And how many people know how to programatically draw a gradient between 2 colors if there isn&#8217;t an API to do it with? Probably very few.</p>
<p>(If you want to see a fully functional Ribbon in Silverlight (built on XAML) do a google search for &#8220;SandRibbon&#8221;. I&#8217;d link to it here but it&#8217;s commercial and costs a fortune, so I don&#8217;t feel like promoting it with a cross-link.)</p>
<h3>Multi-color Gradients</h3>
<p>My &#8220;Pseudo&#8221; code that I started from to &#8220;realize&#8221; this was the following:</p>
<pre>
<pre class="syntax-highlight:java">
LinearGradientBrush yrb = new LinearGradientBrush(new DPoint(0.5, 0), new DPoint(0.5, 1));
yrb.addGradientStop(new AlphaColor(&quot;#FFfff900&quot;), 0);
yrb.addGradientStop(new AlphaColor(&quot;#FFf90005&quot;), 0.5);
yrb.addGradientStop(new AlphaColor(&quot;#FF1100ad&quot;), 1);
</pre>
</pre>
<p>It&#8217;s very WPF/XAML, and what it says is &#8220;Create a brush that will draw a gradient vertically (each DPoint is x/y coordinates of how the fill should draw), add 3 color stops, one at 0%, one at 50% and one at 100%&#8221;. </p>
<p>XAML, by the way, for a typical LinearGradientBrush looks like this:</p>
<pre>
<pre class="syntax-highlight:xml">
&lt;LinearGradientBrush EndPoint=&quot;0.5,1&quot; StartPoint=&quot;0.5,0&quot; x:Key=&quot;ToolbarButtonBackgroundStrokeNormal&quot;&gt;
     	&lt;GradientStop Color=&quot;#FFfff900&quot; Offset=&quot;0&quot;/&gt;
        &lt;GradientStop Color=&quot;#FFf90005&quot; Offset=&quot;0.5&quot;/&gt;
        &lt;GradientStop Color=&quot;#FF1100ad&quot; Offset=&quot;1&quot;/&gt;
&lt;/LinearGradientBrush&gt;
</pre>
</pre>
<p>If we were to do this in Photoshop it&#8217;d look exactly like this (on a 400&#215;400 canvas):</p>
<p><a href="http://hexapixel.com/wp-content/uploads/2010/01/gradient.jpg"><img src="http://hexapixel.com/wp-content/uploads/2010/01/gradient.jpg" alt="gradient" title="gradient" width="400" height="400" /></a></p>
<p>To support multi-color gradients when using pattern fills (as SWT doesn&#8217;t), I had to write some code that split each section that I intend to fill into smaller rectangles and fill each one. Each section is 2 colors. So in the above case, we have 2 patterns we need to create, one from 0% to 50% and one from 50% to 100%. In the picture this would be from 1 to 2, and from 2 to 3.</p>
<p>Implementing it wasn&#8217;t that hard, and despite the code not being that long I think it&#8217;s easier you look at the source itself if you want the details as it&#8217;s a bit spread out. The source is at the bottom of the article.</p>
<h3>A SWT Border Control</h3>
<p>The &#8220;Border&#8221; control in WPF takes a few interesting attributes. One is the Brush that is used to fill the border, the second is the Brush used to fill the background. Then it allows for a setting the border &#8220;roundness&#8221;, the padding and the margin, and a few other things. All of that is mostly getters/setters and in the end we will have a <code>GraphicsObjectRenderer</code> class that deals with actually drawing it. If there was a border control in SWT it might look a bit like this:</p>
<pre>
<pre class="syntax-highlight:java">
Border b = new Border(parentControl);
b.setBorderBrush(ourBorderBrush);
b.setFillBrush(ourFillBrush);
b.setBorderThickness(1);
b.setCornerRadius(20);
b.setWidth(100);
b.setHeight(100);
b.setMargin(new Margin(50));
</pre>
</pre>
<p>Pretty straight forward.</p>
<p>The result from running this code looks something like this:</p>
<p><a href="http://hexapixel.com/wp-content/uploads/2010/01/bordertest.jpg"><img src="http://hexapixel.com/wp-content/uploads/2010/01/bordertest.jpg" alt="bordertest" title="bordertest" width="400" height="399" /></a></p>
<h3>Oh no, Issues&#8230;</h3>
<p>This is how far I got before I hit a wall. I actually started writing the article as I wrote the code because I was quite excited how seemingly well it worked. So what halted me? A few bugs in SWT. Normally a lot of things can be worked around if they don&#8217;t work 100% as intended, however, the bugs I came across were not of that type. The main issues are as follows:</p>
<ul>
<li>Pattern fills in SWT start drawing the pattern in the wrong place. I&#8217;ve filed a bug for this which can be found <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=297467" target="_new">here</a>. This one is rather critical as most of the brush drawing depends on it.</li>
<li>A rounded rectangle is not drawn in the same way as a round rectangle, causing the border around it to be in weird places around the rectangle itself. An old bug is filed <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=181676" target="_new">here</a>.</li>
<li>Other GC draw-related bugs.</li>
</ul>
<h3>Conclusion</h3>
<p>Probably not the conclusion you or I wanted, but as I see it, I cannot really continue this project until the bugs are fixed (or worked around), and considering GC-related bugs are probably low on the fix-list, the Ribbon will have to sleep for a while longer, along with this project. AWT has a very good <code>MultipleGradientPaint</code> implementation and I successfully manged to convert AWT drawings to SWT, but the AWT code is rather slow and converting it over is also slow, so it&#8217;s not really an option.</p>
<h3>Code</h3>
<p>If you want to play with the code I have so far, you can download it here. Under the &#8220;test&#8221; package directory you&#8217;ll find various classes. <code>BorderTester.java</code> is the main test class. The code is truly &#8220;as is&#8221;, it&#8217;s just zipped up from what I had at the time I ran into issues.</p>
<p><a href='http://hexapixel.com/wp-content/uploads/2010/01/com.hexapixel.advanced.graphics.zip'>Download Source</a></p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2010/01/06/xaml-in-swt-and-where-the-ribbon-is/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Printing SWT Tables with PaperClips</title>
		<link>http://hexapixel.com/2009/09/18/printing-swt-tables-with-paperclips</link>
		<comments>http://hexapixel.com/2009/09/18/printing-swt-tables-with-paperclips#comments</comments>
		<pubDate>Fri, 18 Sep 2009 06:56:33 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Eclipse Articles]]></category>
		<category><![CDATA[Printing]]></category>
		<category><![CDATA[SWT]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=563</guid>
		<description><![CDATA[In this article I will explain how to print a table using PaperClips (as of this writing PaperClips is in process of moving to the Eclipse Nebula project). When I say print, I mean print literally, as in printing on a printer. PaperClips is a lightweight API that makes building printable pages very easy. It [...]]]></description>
			<content:encoded><![CDATA[<p>In this article I will explain how to print a table using <a href="http://code.google.com/p/swt-paperclips/" target="_new">PaperClips</a> (as of this writing PaperClips is in process of moving to the <a href="http://www.eclipse.org/nebula/" target="_new">Eclipse Nebula project</a>). When I say print, I mean print literally, as in printing on a printer. PaperClips is a lightweight API that makes building printable pages very easy. It uses a simple and logical structure that has many useful features and it&#8217;s surprisingly flexible. One of the many possibilities is the ability to print tables quite nicely as it has a &#8220;GridPrinter&#8221; (which is what this article will cover. But you can of course use PaperClips to print nearly anything). </p>
<p>The code for this article will let you print pretty much any SWT table widget of your choice as all you need to do is wrap your table in an interface and off you go. But since this is an article, let&#8217;s stick to the plain old SWT table for the sake of the demo. I will mostly go over important snippets of the code and the rest you can download and re-use (download link is at the bottom of the article). </p>
<p>Let&#8217;s list a few things we want to achieve with our implementation:</p>
<ul>
<li>Print preview (PaperClips gives us most of this already).</li>
<li>The option to print either just a selection or all items.</li>
<li>Customizable header and footer.</li>
<li>Printing table with column sizes as they are in the table.</li>
<li>Options to specify if headers are printed, where lines are drawn and so on.</li>
</ul>
<p><span id="more-563"></span></p>
<p>The table that we intend to print for this article looks like this (just run the <code>Tester.java</code> class in Eclipse):</p>
<p><a href="http://hexapixel.com/wp-content/uploads/2009/09/pp1.gif"><img src="http://hexapixel.com/wp-content/uploads/2009/09/pp1.gif" alt="Table Screenshot" title="Table Screenshot" width="558" height="286" /></a></p>
<p>We use <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet38.java?view=co">Snippet38</a> and add a button at the bottom for printing.</p>
<h2><b>Understanding Paperclips</b></h2>
<p>It&#8217;s probably ideal that you understand the PaperClips syntax before you keep reading. PaperClips has certain letters and things that let you specify column widths, how things span and wrap etc. Please do a quick scan of <a href="http://code.google.com/p/swt-paperclips/wiki/GridPrint" target="_new">this page</a> if you are unfamiliar with the syntax. It will take no more than a few minutes to learn, it&#8217;s that easy.</p>
<h2><b>Creating a GridPrint</b></h2>
<p>As mentioned, the GridPrint class is basically a class for printing grids. It will allow you to set things such as columns, headers etc. Think of it as a table widget, but as if it was drawn on a piece of paper.</p>
<p>Our main class that will handle all the printing will be called <code>GridPrinter.java</code>, and the constructor looks like this:</p>
<pre>
<pre class="syntax-highlight:java">
public PrintResultCode printTable(IGenericTable tableImpl, boolean printSelectionOnly, boolean showPreview, String docTitle, final Shell parentShell) {
 ...
}
</pre>
</pre>
<p>The <code>IGenericTable</code> is an interface that you use to wrap the SWT table you want to print. It contains simple methods such as getting the name or width of a column, or an item on a specific row (methods that most table implementations already have). The second attribute defines whether everything is printed or only what the user has selected is printed. The third defines if we show a Print Preview dialog or just print straight to the printer. The fourth is the title of our document that we are printing and finally it&#8217;s the shell that will be the parent shell of the print preview dialog (if we are previewing). </p>
<p>Now that we have all the &#8220;data&#8221; we need, the first thing we want to do is to create the column headers. This is done via a very short loop;</p>
<pre>
<pre class="syntax-highlight:java">
for (int i = 0; i &lt; cols.size(); i++) {
    String name = concat(tableImpl.getColumnTitle(cols.get(i)), widths.get(i), concatGc, headerFont);
    print.addHeader(new TextPrint(name, _headerFontData));
}
</pre>
</pre>
<p>We get the table column text and then concatenate it if it&#8217;s longer than the actual width of the column itself (just like the table does as a widget). <code>print</code> is our GridPrint, and to that we simply say &#8220;add this header&#8221;, and then create a <code>TextPrint</code> with the name and our specified header font. A TextPrint can be thought of as a basic cell that contains text with or without a font. Do note that pretty much everything is a &#8220;print&#8221;, so you can add a GridPrint to a GridPrint to a GridPrint etc. You get the idea.</p>
<p>Now that we have our table column header added, let&#8217;s add the cell data that goes below.</p>
<pre>
<pre class="syntax-highlight:java">
for (IDataObject gi : sel) {
    for (int i = 0; i &lt; cols.size(); i++) {
        String colText = gi.getColumnText(cols.get(i));
        if (colText == null) {
            colText = &quot;&quot;;
        }
        String text = concat(colText, widths.get(i), concatGc, cellFont);
        print.add(tp(text, _cellFontData));
    }
}
</pre>
</pre>
<p>It&#8217;s nearly identical but instead of adding it as a header to the GridPrint we just add it normally. We do the same concatenation as in the header as we want to print exactly what the table looks like (so if the user resizes a column in the table widget, that&#8217;s the size that is used for the printed version as well). The <code>sel</code> array represents all selected items. If we called our constructor with the option to print all items, it will contain all items, and if we called it and said &#8220;only print the selected items&#8221;, it will contain those. The code also contains logic for spacing out cells, so if you were to select individual cells like this&#8230;</p>
<pre>
# - - # - -
- # # - - -
- - - - - #
</pre>
<p>&#8230; it would print it in the way you would expect it to.</p>
<h2><b>Multiple Pages and Large Prints</b></h2>
<p>As the code is not a human and has no idea of how big your table actually is, it&#8217;s quite possible it spans multiple pages both horizontally or vertically. A GridPrint does not handle this by default. But remember that pretty much all print-classes can be children of each other? To support large prints (basically anything beyond the size of a single printed sheet of paper), we need to wrap our page (the GridPrint) in a <code>BigPrint</code>. Just by doing that via a simple&#8230;</p>
<pre>
<pre class="syntax-highlight:java">
BigPrint big = new BigPrint(print);
</pre>
</pre>
<p>&#8230; we can now support multiple pages. Easy wasn&#8217;t it? </p>
<h2><b>Headers, Footers and Spacing</b></h2>
<p>Normally you will want headers and footers on the printed paper. The header tends to contain your company logo and the document title. The footer usually contains what page it is and perhaps a date or such. To accommodate this, there is a <code>PagePrint</code> class that will let you customize all of these aspects. To use it we want that to be our &#8220;outermost&#8221; parent, so the order is: PagePrint -&gt; BigPrint -&gt; GridPrint.</p>
<p>Here&#8217;s how we create the PagePrint:</p>
<pre>
<pre class="syntax-highlight:java">
PagePrint pp = new PagePrint(new PrintHeader(_printHandler, docTitle), big, new PrintFooter(getFooterText()));
pp.setHeaderGap(9);
pp.setFooterGap(18);
</pre>
</pre>
<p>In the constructor, we tell it &#8220;here&#8217;s our header, our BigPrint and our footer&#8221;. We also tell it how much spacing we want between the header/footer and the content of the page. It&#8217;s usually nice to space them out slightly so it&#8217;s not too packed together. </p>
<p>The header and footer classes are both classes that implement the PaperClips <code>PageDecoration</code> interface. They&#8217;re very simple to use and only require one method. All this method forces you to return is a &#8220;Print&#8221; that represents your header (or footer). They can be of any print-class you like, a GridPrint, a TextPrint, etc. For example, here&#8217;s our header:</p>
<pre>
<pre class="syntax-highlight:java">
@Override
public Print createPrint(PageNumber arg0) {
    DefaultGridLook dgl = new DefaultGridLook(0, 3);
    GridPrint gp = new GridPrint(&quot;p, C:D:GROW&quot;, dgl);
    FontData fd = Display.getDefault().getSystemFont().getFontData()[0];
    fd.height = 14;
    fd.setStyle(SWT.BOLD);

    if (_handler.getActivePrintLogo() != null) {
        gp.add(new ImagePrint(_handler.getActivePrintLogo().getImageData(), Display.getDefault().getDPI()));
        gp.add(new TextPrint(&quot;&quot;));
        gp.add(SWT.CENTER, new TextPrint(_title, fd, SWT.CENTER), GridPrint.REMAINDER);
    }

    return gp;
}
</pre>
</pre>
<p>In this code we create a new &#8220;Grid Look and Feel&#8221; (this is a PaperClips class that simply draws borders around cells etc). Then we create a very simple GridPrint that has 2 columns. The first is in a <b>p</b>referred size as we don&#8217;t know the size of the image that will go there (there might be no image even). The second takes up all available space and is centered so that the text shows the title of the document in the middle, but we push it down a row to make it truly centered or the size of the image would push it off.</p>
<h2><b>Previewing the Print</b></h2>
<p>Once we have our PagePrint all set up it&#8217;s finally time to print! PaperClips has a &#8220;ui&#8221; package that contains a PrintPreview dialog. In the downloadable code you will find that this class has been wrapped as I wanted button images in the dialog to be customizable. To show our print preview dialog we call:</p>
<pre>
<pre class="syntax-highlight:java">
PrintPreviewDialog ppd = new PrintPreviewDialog(pp, parentShell, _printHandler);
ppd.open();
</pre>
</pre>
<p>(The PrintHandler is an interface that lets us define what images we use etc)</p>
<p>The result is more or less the following (when fully zoomed out):</p>
<p><a href="http://hexapixel.com/wp-content/uploads/2009/09/pp2.gif"><img src="http://hexapixel.com/wp-content/uploads/2009/09/pp22.gif" alt="Zoomed Out Picture" title="Zoomed Out" width="659" height="599"  /></a></p>
<p>And when zoomed in a bit:</p>
<p><a href="http://hexapixel.com/wp-content/uploads/2009/09/pp3.gif"><img src="http://hexapixel.com/wp-content/uploads/2009/09/pp3.gif" alt="Zoomed In Picture" title="Zoomed In" /></a></p>
<p>Do note that even if the preview may not be 100% perfect look-wise (pixelated etc), the printed version will come out fine. </p>
<h2><b>Conclusions</b></h2>
<p>With PaperClips you can go from zero print-functionality in your application to some pretty fancy reports in just a few hours of work. That&#8217;s its #1 strength and it&#8217;s a very strong argument for using PaperClips. Sure, you can create very fancy reports using <a href="http://www.eclipse.org/birt/phoenix/" target="_new">Eclipse BIRT</a> or <a href="http://www.jaspersoft.com/jasperreports" target="_new">JasperReports</a> (which has sadly gone mostly commercial). For &#8220;normal printing&#8221; however, there&#8217;s no reason to dig into a big reporting engine, just stick to PaperClips!</p>
<h2><b>Download The Code</b></h2>
<p>The code for this article is an Eclipse Project that contains everything necessary to run what you have seen in this Article (you may need to adjust the SWT-jar import paths). It may seem like there&#8217;s a lot of code but in reality it&#8217;s mostly some extra interfaces to make things customizable. That way it&#8217;s not just article code, but code you can actually use. That&#8217;s how I prefer to write articles. Most people want as much customization as possible, and for those that don&#8217;t, they can take out the parts that they need.</p>
<p><a href="http://hexapixel.com/wp-content/uploads/2009/09/com.hexapixel.articles.paperclips.zip">Download Code</a></p>
<p>Happy printing!</p>
<p>(PaperClips version 1.0.4 was used in this article).</p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2009/09/18/printing-swt-tables-with-paperclips/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating a Notification Popup Widget</title>
		<link>http://hexapixel.com/2009/06/30/creating-a-notification-popup-widget</link>
		<comments>http://hexapixel.com/2009/06/30/creating-a-notification-popup-widget#comments</comments>
		<pubDate>Tue, 30 Jun 2009 12:00:24 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Eclipse Articles]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[SWT]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=760</guid>
		<description><![CDATA[In this article I will explain how to create a custom widget that displays a popup notification dialog in the bottom right corner of your screen (usually above the toolbar on Windows). Here&#8217;s what it will look like when we&#8217;re done: We could custom draw everything which would allow us more control over the widget, [...]]]></description>
			<content:encoded><![CDATA[<p>In this article I will explain how to create a custom widget that displays a popup notification dialog in the bottom right corner of your screen (usually above the toolbar on Windows). Here&#8217;s what it will look like when we&#8217;re done:</p>
<p><img src="http://hexapixel.com/wp-content/uploads/2009/06/tray_popup_example.gif" alt="Example Image" title="Example Image" width="397" height="147" /></p>
<p>We could custom draw everything which would allow us more control over the widget, but for the sake of this article lets stick to using basic SWT components inside a normal Shell that we will make a bit prettier than your typical SWT Shell.</p>
<p>(Do note this has only been tested on Windows, it&#8217;s quite possible tweaks are necessary for other platforms).</p>
<p><span id="more-760"></span><br />
<h3>The Shell</h3>
<p>What we want is a Shell that stays on top of our application (but not on top of all applications) and doesn&#8217;t steal the active focus or else it would show up in your task manager or move focus away from where the user is now. We also don&#8217;t any normal Shell &#8220;trim&#8221; borders, we&#8217;ll draw our own. Creating it is easy as all of our requirements are available via SWT flags. Thus we can create the Shell as follows:
<pre class="java" name="code">
<pre class="syntax-highlight:java">
_shell = new Shell(Display.getDefault().getActiveShell(), SWT.NO_FOCUS | SWT.NO_TRIM);
</pre>
</pre>
<p>As we have SWT widgets inside our shell and we intend to use a gradient background on the shell itself, all the widgets need to be transparent. This is done by setting the Background Mode on the shell to <code>SWT.INHERIT_DEFAULT</code>. This tells the widgets to inherit the background of their parents, and gives us what we want. So after we create the shell we simply call;
<pre class="java" name="code">
<pre class="syntax-highlight:java">
_shell.setBackgroundMode(SWT.INHERIT_DEFAULT);
</pre>
</pre>
<p>So how do we get a gradient background on a shell? It certainly don&#8217;t support it by default. You can set a foreground and a background but that&#8217;s about it. The trick is to paint an image with the colors we want and use that as the shell&#8217;s background. To set it at the right time, we listen to the <code>SWT.Resize</code> event on the shell and do it then with the following code;</p>
<pre class="java" name="code">
<pre class="syntax-highlight:java">
_shell.addListener(SWT.Resize, new Listener() {
    @Override
    public void handleEvent(Event e) {
	try {
	    // get the size of the drawing area
	    Rectangle rect = _shell.getClientArea();
	    // create a new image with that size
	    Image newImage = new Image(Display.getDefault(), Math.max(1, rect.width), rect.height);
	    // create a GC object we can use to draw with
	    GC gc = new GC(newImage);

	    // fill background
	    gc.setForeground(_bgFgGradient);
	    gc.setBackground(_bgBgGradient);
	    gc.fillGradientRectangle(rect.x, rect.y, rect.width, rect.height, true);

	    // draw shell edge
	    gc.setLineWidth(2);
	    gc.setForeground(_borderColor);
	    gc.drawRectangle(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2);
	    // remember to dipose the GC object!
	    gc.dispose();

	    // now set the background image on the shell
	    _shell.setBackgroundImage(newImage);

	    // remember/dispose old used iamge
	    if (_oldImage != null) {
		_oldImage.dispose();
	    }
	    _oldImage = newImage;
	}
	catch (Exception err) {
	    err.printStackTrace();
	}
    }
});
</pre>
</pre>
<h3>The Contents</h3>
<p>Our shell consists of 3 sections, an image at the top left (which is a normal CLabel). Then a label that contains the header text (also a CLabel), and finally a label which represents our message (a normal Label). We use a Label at the end instead of a CLabel as Labels support wrapping and multi-lines better than the CLabel does. You could of course use pretty much any widgets you want. Here&#8217;s an outline of what section each label covers:</p>
<p><img src="http://hexapixel.com/wp-content/uploads/2009/06/tray_popup_example_lines.gif" alt="tray_popup_example_lines" title="tray_popup_example_lines" width="350" height="99" /></p>
<p>We use a GridLayout with some 5px margins (except at the top) and the widgets are created normally without any special magic, so I won&#8217;t show that code here (it&#8217;s all at the bottom for you to download). </p>
<h3>Some Eye Candy &#8211; Fading</h3>
<p>Shells support alpha values as of SWT 3.4, so we&#8217;ll use this to make our &#8220;appearing&#8221; and &#8220;disappearing&#8221; a bit prettier. All we need to do to make a shell fade in and out is to have a thread that loops and increases/decreases the alpha channel value for the shell. As we need to be on the Display thread to do this it&#8217;s easiest to do it all via a runnable that we let the Display object run for us at a given interval. </p>
<p>We need to remember to continuously check to see if the shell is disposed as it can happen when we&#8217;re on a thread. When we&#8217;re finished fading in, we want the shell to stay visible for a certain amount of time, and then we want to fade out. So basically the chain is this:</p>
<ul>
<li>Create shell</li>
<li>Fade in shell</li>
<li>Stay visible for X seconds</li>
<li>Fade out shell</li>
<li>Dispose shell</li>
</ul>
<p>All these timers are more or less similar in terms of how the code looks, so I&#8217;ll show one example here and for the rest you can look at the complete source downloadable below. We have some global variables here that should be explained. </p>
<ul>
<li><code>FADE_IN_STEP</code> is how much we increase the alpha value for each iteration.</li>
<li><code>FINAL_ALPHA</code> is a value that declares what the final alpha value will be for the shell when it stays visible. I find that a slightly transparent shell gives a better effect, so by default this value is 225 (out of 255 which is a solid [opaque] shell).</li>
<li><code>FADE_TIMER</code> is how long we wait until increasing the Alpha value again. When the shell has reached it&#8217;s max-alpha value we call the startTimer() method, which is a thread that sleeps for a certain number of seconds before calling the fadeOut() method.</li>
</ul>
<pre class="java" name="code">
<pre class="syntax-highlight:java">
private static void fadeIn(final Shell _shell) {
    Runnable run = new Runnable() {

        @Override
        public void run() {
            try {
                if (_shell == null || _shell.isDisposed()) { return; }

                int cur = _shell.getAlpha();
                cur += FADE_IN_STEP;

                if (cur &gt; FINAL_ALPHA) {
                    _shell.setAlpha(FINAL_ALPHA);
                    startTimer(_shell);
                    return;
                }

                _shell.setAlpha(cur);
                Display.getDefault().timerExec(FADE_TIMER, this);
            }
            catch (Exception err) {
                err.printStackTrace();
            }
        }

    };
    Display.getDefault().timerExec(FADE_TIMER, run);
}
</pre>
</pre>
<h3>Stacked Notifications</h3>
<p>There&#8217;s one last thing we want to support, which is stacked notifications. Assume our notification shell&#8217;s entire life-span is about 5 seconds, what if we have another notify call before the first one has finished showing? We could dispose the first shell and replace it with the new one of course, but a much prettier approach is to simply move the previous shell up, and show the new notification below it. The effect of this is something like this (this screenshot was taken just as the old shells started to fade out, hence the higher alpha on them):</p>
<p><img src="http://hexapixel.com/wp-content/uploads/2009/06/tray_stacked.gif" alt="tray_stacked" title="tray_stacked" width="362" height="431" /></p>
<p>What we do to achieve this effect is rather simple. Every time a notification shell is opened, we keep a reference of it in a static array of shells. When it&#8217;s faded out (and disposed), it&#8217;s removed from the list. Thus, when a new shell is created we simply check to see what&#8217;s already in the array and then set the location for each old shell in the array to <code>-heightOfNewNotificationShell</code> (so to speak). Thus, the old shells move up to make room, but continue their fade-in/fade-out cycles just like before. </p>
<h3>Further Improvements</h3>
<p>Everything could be made prettier than it already is of course, perhaps you want an &#8220;X&#8221; close button, or different colored text, or rounded shell corners. None of that is in the current code, but the code should give you enough to go on to implement most of that without any major problems. </p>
<p>Also note that I currently use <code>Display.getDefault().getActiveShell()</code> for the parent shell of the popup. You may want to refactor it to use a more permanent shell as otherwise a disposal of whatever the parent shell was whenever the popup was displayed will cause the notification to dispose as well.</p>
<p>The code is not perfect, it&#8217;s an example to build on (if you so wish).</p>
<h3>Download Code</h3>
<p>I&#8217;ve created an Eclipse project with the code and also the ImageCache/FontCache/ColorCache classes I use in the code (all they do is keep already used images etc in memory so that they don&#8217;t need to be re-created). There&#8217;s also a jar with the images I&#8217;ve used in this example. If you like them and want more like it, there&#8217;s a massive image pack with exactly these icons and more here: <a href="http://code.google.com/p/gnome-colors/" target="_new">Gnome Colors Icons</a>.</p>
<p>Do note you may need to adjust your CLASSPATH settings for the project to reflect the location of your SWT jars.</p>
<p>To run the code, simply run the <code>Tester.java</code> class and push the big button to create a notification. Push it again before the first one fades away to see the stacking. A random image will be used every time you push it.</p>
<p><a href='http://hexapixel.com/wp-content/uploads/2009/06/notification_widget.zip'>DOWNLOAD CODE</a></p>
<h3>Conclusion</h3>
<p>Hopefully this gives you an insight into how to create a &#8220;custom widget&#8221; (without much custom painting). Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2009/06/30/creating-a-notification-popup-widget/feed</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>The Secondary ID</title>
		<link>http://hexapixel.com/2009/06/16/the-secondary-id</link>
		<comments>http://hexapixel.com/2009/06/16/the-secondary-id#comments</comments>
		<pubDate>Tue, 16 Jun 2009 13:36:25 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Eclipse Articles]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JFace]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=739</guid>
		<description><![CDATA[In many RCP applications your views (ViewParts) will not be singletons. Perhaps you have a tree or project view which is probably a &#8220;show only once&#8221; view, but for others it&#8217;s more likely you have them flagged in the plugin xml to say allowMultiple="true" in the &#60;view /&#62; tag. For multiple views sharing the same [...]]]></description>
			<content:encoded><![CDATA[<p>In many RCP applications your views (ViewParts) will not be singletons. Perhaps you have a tree or project view which is probably a &#8220;show only once&#8221; view, but for others it&#8217;s more likely you have them flagged in the <code>plugin xml</code> to say <code>allowMultiple="true"</code> in the <code>&lt;view /&gt;</code> tag. For multiple views sharing the same primary ID you are probably already aware that you can (and have to) set a secondary id on them to make them unique. This secondary id will stay with the view as long as that view is open (even if you restart your application as the secondary id is saved in the Eclipse metadata and then re-set when your RCP application starts up again &#8211; assuming the view is set to be restorable). </p>
<p>But there&#8217;s some things that can be a bit frustrating, which is the point of writing this article. First, as your view has to be defined in the <code>plugin.xml</code> and [should you want to] Eclipse/RCP has currently no way of hiding views in &#8220;Show View&#8221; (see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=249451">Bug 249451</a> for details and possible workaround to hiding views from &#8220;show view&#8221;). Any view opened with Show View won&#8217;t have a secondary id. </p>
<p>Second, you may want to control what that secondary id looks like, as you may want to use it as an &#8220;ID&#8221; for saving custom view-specific settings (for example, grid-specific data such as column widths, column orders etc). </p>
<p>Third, you want a central place where the creation of those multi-views are handled where you know that the ID set on them will be of the format you defined. </p>
<p>And lastly, you probably want some of them to be automatically opened in your &#8220;default&#8221; perspective with proper secondary ids. So let&#8217;s get to it and see how we can make all this work for us with the goal of us not having to think about it any more once we&#8217;ve created the necessary code.</p>
<p><span id="more-739"></span><br />
<h2><b>The ActionNewView Action</b></h2>
<p>As we will continuously reference &#8220;the place&#8221; where the secondary id is set on the view, lets start with the &#8220;view creator&#8221;. This could be considered a Factory, but as it&#8217;s kind of nice to tie it in with <code>Actions</code> lets make this factory an Action which also allows us to use it in menus, toolbars, etc.</p>
<p>The action will take the [primary] ID of the view that should be opened as a parameter in the constructor (the same ID you specify in <code>plugin.xml</code>) and in the <code>run()</code> method it will create the view with a secondary id of our choice. This is all quite easy and we don&#8217;t have to write much code to accomplish it, in fact, you&#8217;ve undoubtedly done something like this already. In this article we will use a <a href="http://en.wikipedia.org/wiki/UUID" target="_new">UUID</a> as our secondary ID as it&#8217;s unique and the structure of it is good as it&#8217;s a long string without strange characters (except the &#8216;-&#8217; character) and it&#8217;s more or less guaranteed to be unique. You may of course use whatever you prefer as a unique ID.</p>
<p>Our action class will look like this:</p>
<pre class="java" name="code">
<pre class="syntax-highlight:java">
public class ActionNewView extends Action {

    private String _viewIdToOpen = null;

    public ActionNewView(String viewIdToOpen) {
        _viewIdToOpen = viewIdToOpen;
    }

    @Override
    public void run() {
        try {
            // this will become the secondary ID used in the view
            String secondaryId = UUID.randomUUID().toString();

            IWorkbenchWindow window = Activator.getDefault().getWorkbench().getActiveWorkbenchWindow();
            if (window != null) {
                IWorkbenchPage page = window.getActivePage();
                if (page != null) {
                    // these two lines open (create) and focus on the view
                    page.showView(_viewIdToOpen, secondaryId, IWorkbenchPage.VIEW_CREATE);
                    IViewPart justActivated = page.showView(_viewIdToOpen, secondaryId, IWorkbenchPage.VIEW_ACTIVATE);

                    // ... do something with justActivated if needed
                }
            }

        }
        catch (Exception err) {
            //TODO: deal with exception
        }
    }
}
</pre>
</pre>
<p>I don&#8217;t think it needs much explanation as it&#8217;s a pretty straight forward &#8220;view creation&#8221; call with a secondary id, as specified in the Eclipse manual etc. </p>
<h2><b>Dealing With &#8220;Show View&#8221;</b></h2>
<p>Now that we have our &#8220;view opener class&#8221; we&#8217;re ready to deal with some of the aspects mentioned in the beginning. The next stop is to get secondary id&#8217;s onto views opened via &#8220;Show View&#8221; as they don&#8217;t get one by default. If you don&#8217;t already have an abstract parent class for all of your multi views, perhaps now is the time to create one as it will make it easier, but you can of course put the same snippet of code elsewhere. </p>
<p>One method is always called upon view creation, and that&#8217;s where we want to check if the view being created has a secondary id. If it doesn&#8217;t, we want to dispose (hide) that view right away and call our ActionNewView instead and open the same view again but <b>with</b> a secondary id. The method we check in is the <code>createPartControl(Composite parent)</code> method which is an implementation of the <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/IWorkbenchPart.html#createPartControl(org.eclipse.swt.widgets.Composite)" target="_new">IWorkbenchPart</a> interface. Here&#8217;s what our code will look like:</p>
<pre class="java" name="code">
<pre class="syntax-highlight:java">
@Override
public void createPartControl(final Composite parent) {
    try {
        // get the secondary id that the view was created with
        String secondaryId = getViewSite().getSecondaryId();

        // If the secondary id was null that means that Eclipse opened the view, and not us. That&#039;s bad because it
        // creates a view without a secondary ID and causes the view to be &quot;different&quot; from one that we opened ourselves.
        // Thus, if we see a view opened without an ID, we quickly close it and tell the &quot;open new action&quot; to open
        // the same view right away. The result may be a very slight flicker as the old view comes to existance and is
        // destroyed right away, but it&#039;s mostly not noticeable by the end user.
        if (secondaryId == null) {
            // we need to do it asynchronously as we can&#039;t close the view until the create code has finished
            Display.getDefault().asyncExec(new Runnable() {
                @Override
                public void run() {
                    // destroy ourselves
                    getViewSite().getPage().hideView(ThisAbstractClass.this);
                    // open the same view our way
                    ActionNewView anv = new ActionNewView(getViewSite().getId());
                    anv.run();
                }
            });

            // return now as we&#039;re done with the non-secondary-id view
            return;
        }

        // do normal view creation stuff here...
    }
    catch (Exception err) {
        //TODO: deal with exception
    }
}
</pre>
</pre>
<p><code>ThisAbstractClass</code> is of course whatever class you put this code in, but most likely it&#8217;s your abstract multi-view parent class.</p>
<p>So, as the comment states, when a view is created and it doesn&#8217;t have a secondary id, that view is discarded as soon as it finished being created and the same view is opened again but this time via our action, which in turn ensures it gets a secondary id to our standards. </p>
<h2><b>Dealing With Perspectives</b></h2>
<p>We&#8217;re almost done, but there&#8217;s one more place where views may get secondary id&#8217;s that aren&#8217;t what we want, and that&#8217;s the views that are opened when the <code>Perspective</code> is new or reset. In our <code>DefaultPerspective</code> class (or whatever perspective class you want) we define the layout in the <code>createInitialLayout(IPageLayout layout)</code> and we also set whatever views are open at the start and where non-opened views go (placeholders). In here we need to change a few things so that whatever views are opened from the start get opened with a secondary id like above.</p>
<p>The API documentation for <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ui/IPageLayout.html" target="_new">IPageLayout</a> states:</p>
<p><i>In some cases, multiple instances of a particular view may need to be added to the same layout. These are disambiguated using a secondary id. In layout methods taking a view id, the id can have the compound form: primaryId [':' secondaryId]. If a secondary id is given, the view must allow multiple instances by having specified <code>allowMultiple="true"</code> in its extension. View placeholders may also have a secondary id.</i></p>
<p>So we can either create the secondary id on the fly and call <code>layout.showView("primaryId:secondaryId")</code> or we can just add placeholders and asynchronously call our Action to create the views. It&#8217;s really up to you how you want to do it, if your ID generator is a simple static call, you may just want to put the secondary ID&#8217;s in there and be done. But for the sake of the article, lets have everything go through our action. </p>
<p>Presume we have a perspective layout of 1 folder on the left, and 3 folders on the right, each taking up 33% of the space vertically. Something like this:</p>
<pre>
+-----------+--------+
|           |folder 1|
|           +--------+
| folder 0  |folder 2|
|           +--------+
|           |folder 3|
+-----------+--------+
</pre>
<p>The &#8220;folder 0&#8243; will get a non-multi view, and folder 1,2,3 will get multi-views, 1 each for this example. We will tell the folder 1,2,3 that they contain view placeholders, and folder 0 will get a view right away. Our code will look like this:</p>
<pre class="java" name="code">
<pre class="syntax-highlight:java">
public class DefaultPerspective implements IPerspectiveFactory {

    // Marker for saying &quot;any id following the primary id&quot; (which is the secondary id)
    private static final String MULTI_VIEW = &quot;:*&quot;;

    @Override
    public void createInitialLayout(IPageLayout layout) {
        String editorArea = layout.getEditorArea();
        layout.setEditorAreaVisible(false);

        // list of ID&#039;s that will be created at &quot;reset perspective&quot; / first startup
        final String[] ids = new String[] { ViewForFolder1.ID, ViewForFolder2.ID, ViewForFolder3.ID };

        layout.addShowViewShortcut(OurWorkspaceView.ID);
        layout.addShowViewShortcut(ViewForFolder1.ID);
        layout.addShowViewShortcut(ViewForFolder2.ID);
        layout.addShowViewShortcut(ViewForFolder3.ID);

        // left side
        IFolderLayout workspace = layout.createFolder(&quot;Folder0&quot;, IPageLayout.LEFT, 0.2f, editorArea);
        workspace.addView(OurWorkspaceView.ID);

        // right side
        IFolderLayout f1 = layout.createFolder(&quot;Folder1&quot;, IPageLayout.RIGHT, 0.25f, editorArea);
        f1.addPlaceholder(ViewForFolder1.ID + MULTI_VIEW);

        IFolderLayout f2 = layout.createFolder(&quot;Folder2&quot;, IPageLayout.BOTTOM, 0.33f, &quot;Folder1&quot;);
        f2.addPlaceholder(ViewForFolder2.ID + MULTI_VIEW);

        IFolderLayout f3 = layout.createFolder(&quot;Folder3&quot;, IPageLayout.BOTTOM, 0.5f, &quot;Folder2&quot;);
        f3.addPlaceholder(ViewForFolder3.ID + MULTI_VIEW);

        // create all views asynchronously as they need to be created after the folders etc
        // have been laid-out. This ensures they have a secondary id according to our standards.
        Display.getDefault().asyncExec(new Runnable() {

            @Override
            public void run() {
                for (String id : ids) {
                    ActionNewView anv = new ActionNewView(id);
                    anv.run();
                }
            }

        });

        // rest of your code...
    }
}
</pre>
</pre>
<p>So when the Perspective is opened for the first time (or reset) we create the layout, set multi-view placeholders and then asynchronously call our action to create the views. As we told them where to go, they will show up in each respective folder in the order specified by the string array. As mentioned previously you can of course call <code>addView</code> directly with a secondary id, but I&#8217;m showing the &#8220;route it through our ActionNewView class&#8221; way here.</p>
<h2><b>Done!</b></h2>
<p>This concludes the article on harnessing the Secondary ID in your RCP (or Eclipse) applications. This is by no means the only way to do it as everyone seem to find their own way of doing similar things. This is simply &#8220;one way&#8221;, but the above way works well. Hopefully the article gave you an insight into how the Secondary ID is used in a multi-view environment and the places you may need to &#8220;catch it&#8221; as views can be created from the Eclipse framework without your direct interaction.</p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2009/06/16/the-secondary-id/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MenuManagers and You</title>
		<link>http://hexapixel.com/2009/05/22/menumanagers-and-you</link>
		<comments>http://hexapixel.com/2009/05/22/menumanagers-and-you#comments</comments>
		<pubDate>Fri, 22 May 2009 10:23:13 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Eclipse Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[JFace]]></category>
		<category><![CDATA[SWT]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=689</guid>
		<description><![CDATA[If you&#8217;re using Eclipse RCP (or even standalone SWT with JFace) you are most likely using MenuManagers in various places, for popup menus, toolbar menus, etc. You might be happily using them without much of a thought or care of where they end up after they have been shown or how their internal workings actually [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re using Eclipse RCP (or even standalone SWT with JFace) you are most likely using MenuManagers in various places, for popup menus, toolbar menus, etc. You might be happily using them without much of a thought or care of where they end up after they have been shown or how their internal workings actually &#8220;work&#8221;. Danger lies down that happy path. </p>
<p>You probably never paid much attention to the disposal of widgets except that &#8220;master widget&#8221; you call <code>dispose()</code> on (usually a shell).. and just because of this, it&#8217;s time to dig into the &#8220;why&#8221;, &#8220;what&#8221; and &#8220;no kidding&#8221; of MenuManagers as there are undoubtedly a few of the &#8220;no kidding&#8221; unless you are already fully familiar with them.</p>
<p><span id="more-689"></span>If you look at the MenuManager API, you&#8217;ll see an often overlooked <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/action/MenuManager.html#dispose()" target="_new">dispose()</a> method. MenuManagers need disposal?! Yep, they sure do. Here&#8217;s a seemingly harmless sample snippet. We create a Shell, a Toolbar, on which we create a MenuManager, and then we dispose the toolbar. You&#8217;d think that the MenuManager would get disposed also wouldn&#8217;t you? It doesn&#8217;t. Where is it? In memory.</p>
<pre>
<pre class="syntax-highlight:java">
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;

public class MenuManagerTest1 {

    public MenuManagerTest1() {
        Display display = new Display();
        Shell shell = new Shell(display, SWT.SHELL_TRIM);
        shell.setLayout(new FillLayout());

        ToolBarManager tbm = new ToolBarManager(SWT.FLAT | SWT.RIGHT);
        tbm.add(new OneAction());
        ToolBar tb = tbm.createControl(shell);

        MenuManager mm = new MenuManager(&quot;Test Menu&quot;);
        mm.add(new OneAction());
        tbm.setContextMenuManager(mm);

        // dispose shell, this will dispose all sub-widgets as well
        shell.dispose();

        // check status of our stuff
        System.out.println(&quot;Toolbar is disposed? - &quot; + tb.isDisposed());
        System.out.println(&quot;Menu is disposed? - &quot; + mm.getMenu().isDisposed());
        System.out.println(&quot;ToolbarManager contains what? &quot; + tbm.getItems());
        System.out.println(&quot;MenuManager contains what? &quot; + mm.getItems());
    }

    class OneAction extends Action {
        public OneAction() {
            super(&quot;Test Action&quot;);
        }

        @Override
        public void run() {
            System.out.println(&quot;Action was run&quot;);
        }
    }

    public static void main(String[] args) {
        new MenuManagerTest1();
    }

}
</pre>
</pre>
<p>The printout when running this will look like;
<pre><font color="green"><b>
Toolbar is disposed? - true
Menu is disposed? - true
ToolbarManager contains what? [Lorg.eclipse.jface.action.IContributionItem;@16fe0f4
MenuManager contains what? [Lorg.eclipse.jface.action.IContributionItem;@19d0a1
</b></font></pre>
<p>Ok, so that's not the most intriguing printout ever, but it's mostly to show that the items are still there. The reason a manager doesn't get disposed should be pretty obvious: It's not a widget, it has no disposable parent (which would also have to be a widget), thus, it exists as long as you let it exist. There is of course a reference to the actual Menu inside the MenuManager, which is disposed as you can see above.</p>
<p>So why aren't MenuManagers auto-disposed in some other fashion, like when the menu is disposed? For good reason. You can create them without a parent widget which means you can keep them around and re-use them like a Factory and because of this, there is no auto-dispose when the menu is hidden. It's actually to make life easier for you even if it sometimes doesn't feel that way.</p>
<h2><b>Disposing MenuManagers</b></h2>
<p>There's two ways you can go about dealing with disposing your MenuManagers. Here's the first one (which might be obvious);</p>
<p>Assume you have a few MenuManagers in your ViewParts or EditParts. If you are creating them inside methods, you will want to refactor them out and create them only once for your class. They should be accessible and re-used throughout the life of the ViewPart and disposed when the ViewPart is disposed. This is very important! If you do not dispose it, it will not be gone, and you will most likely end up with a memory leak (as the above snippet showed). Here's a typical ViewPart dispose() override:</p>
<pre>
<pre class="syntax-highlight:java">
@Override
public void dispose() {
        try {
            if (_toolbarMenu != null) {
                _toolbarMenu.dispose();
                _toolbarMenu = null;
            }

        }
        catch (Exception err) {
            // do something with exception
        }

	    // remember to keep it going!
        super.dispose();
}
</pre>
</pre>
<p>The second option is for the "show once" menus that you may have. How do you dispose those? Ideally the same as #1 but if you really have to dispose them differently, the easiest way to do it is to "auto dispose" them once the user has seen the menu and closed it or selected something from it. You will most likely create your <code>Menu</code> object from a call to <code>menuManager.createContextMenu(...)</code>, so after this when you have the Menu object available, you do something like this;</p>
<pre>
<pre class="syntax-highlight:java">
final MenuManager mm = new MenuManager(&quot;Menu&quot;);

// ... various manager-related code here

// create menu object on widget
Menu menu = mm.createContextMenu(parentWidget);

// add a listener that disposes the MenuManager once user has seen the menu
menu.addMenuListener(new MenuListener() {

	 @Override
	 public void menuHidden(MenuEvent e) {
	     // dispose asynchronously or it&#039;ll dispose too fast and menu item clicked won&#039;t be run
	     Display.getDefault().asyncExec(new Runnable() {

		 @Override
		 public void run() {
		     mm.dispose();
		 }

	     });
	 }

	 @Override
	 public void menuShown(MenuEvent e) {
	 }

});
</pre>
</pre>
<p>It's not the prettiest solution, but it works. Ok, so the disposal is covered now, no more leaks. Yay for us!</p>
<p>There is one more thing to bring up that you may/may not encounter, but if you do, it would probably be a head-scratcher. </p>
<h2><b>Dynamic Menu Items</b></h2>
<p>Here's a scenario that happened to me and at first seemed to be a bug:</p>
<p>We have a lot of tables in our application. We also have a section where users can create their own custom filters. These filters show up in our menus when you right click a table or open a menu on the toolbar. When a filter is in use, the corresponding menu item for that filter is checked. Each filter is wrapped in an IAction that overrides <code>equals()</code> and <code>hashCode()</code> that both check to see if the wrapped Filter object is the same. Thus, any action using the same filter object will return true in the <code>equals()</code> check. </p>
<p>We have an <a href="http://help.eclipse.org/ganymede/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/action/IMenuListener.html" target="_new">IMenuListener</a> on the menu, so whenever the user opens the menu, just as it's being shown, we remove all old menu items in the "Filters" menu and re-create them (as filters may have changed by the user without our knowledge). We then "check" (checkbox) them according to what filters are active in the table. All this works fine, and here's where the issue arose;</p>
<p>We also have a MenuManager on our toolbar (ToolbarManager) associated with the table. This toolbar menu shows the exact same filter menu when popped up, through the same methods. The issue is easiest described through this chain of events...</p>
<ol>
<li>User opens right click filter menu, selects a filter, item is checked, filter is applied to table.</li>
<li>User looks at toolbar menu, sees filter checked (do note this is the first time the toolbar menu was opened). Closes menu without selecting anything.</li>
<li>User opens right click filter menu again, selects same filter as before (the now checked one). Item is no longer checked, filter is removed from table.</li>
<li>User opens toolbar menu again, <b>sees the recently cleared filter still checked</b>(!). At this point it will always stay checked. Had we looked at the menu when stuff was unchecked, it would forever be unchecked.</li>
</ol>
<p>I debugged this for a long time until I to my horror realized that despite me calling <code>removeAll()</code> and re-creating all MenuManager items in the "Filters" menu on each popup, internally, in the Menu widget itself, the <code>removeAll()</code> on the MenuManager removed nothing on the Menu widget. All MenuItems were still there! Hmm, what was going on? what was I missing? Why didn't <code>removeAll()</code> remove all MenuItems as well? </p>
<p>I debugged some more and noticed some code inside the MenuManager source code that looks like this:</p>
<pre>
<pre class="syntax-highlight:java">
for (int i = 0; i &lt; mi.length; i++) {
    Object data = mi[i].getData();

    if (data == null || !clean.contains(data)) {
	mi[i].dispose();
    } else if (data instanceof IContributionItem
	    &amp;amp;&amp;amp; ((IContributionItem) data).isDynamic()
	    &amp;amp;&amp;amp; ((IContributionItem) data).isDirty()) {
	mi[i].dispose();
    }
}
</pre>
</pre>
<p>This loop first of all removes all items that are not the same as before (that are in the <code>clean</code> array), that's good. But as I checked what got disposed, our filter items were never removed... as they are the same as before! Aha! So the second part of the if-statement checks to see if the item is Dirty or Dynamic. This was the first I had heard of Dynamic menu items and it felt like I had read the API through and through many times. The API for <code>isDynamic()</code> says:</p>
<p><i>Returns whether this contribution item is dynamic. A dynamic contribution item contributes items conditionally, dependent on some internal state.</i></p>
<p>Cryptic to say the least, and easily overlooked as it's very non-descriptive, but with the above looping code and how we deal with these special actions - it kind of fits. We depend on the items having checkmarks which depend on an internal state (which is; if the table filter is active or not). The MenuManager can't figure that out by itself of course, so we need to help it. The solution to this problem is obvious at this point. If <code>isDynamic()</code> returns true it will be disposed for us, so we need to implement that and return <code>true</code>.</p>
<p>In our code more or less everything is an IAction, for our FilterAction we create a DynamicFilterAction class that extends <code>ActionContributionItem</code> and then we override <code>isDynamic()</code> and return <code>true</code>. </p>
<p>This ensures that there is no "old" items in the menu (as now our Dynamic menu items get disposed) when we create the new one, and as such, the "checkbox issue" goes away and everything works as intended. The final code looks something like this;</p>
<pre>
<pre class="syntax-highlight:java">
class DynamicFilterAction extends ActionContributionItem {

        private FilterAction _action;

        public DynamicFilterAction(DataFilter df) {
            super(new FilterAction(df));
            _action = (FilterAction)super.getAction();
        }

        public void setChecked(boolean checked) {
            _action.setChecked(checked);
        }

        @Override
        public boolean isDynamic() {
            return true;
        }
}
</pre>
</pre>
<h2><b>Final Words</b></h2>
<p>Hopefully this gives you a better insight into the rather simple but tricky world of MenuManagers and how they work. Taking good care of them will ensure that you at least don't have to worry about them sticking around in memory or doing things you didn't expect.</p>
<p>Happy menu managing!</p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2009/05/22/menumanagers-and-you/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Maven Version Clash Detection (and Software)</title>
		<link>http://hexapixel.com/2009/03/17/maven-and-dependency-version-clash-detection</link>
		<comments>http://hexapixel.com/2009/03/17/maven-and-dependency-version-clash-detection#comments</comments>
		<pubDate>Tue, 17 Mar 2009 17:26:46 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Maven]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=603</guid>
		<description><![CDATA[Maven is a great tool for building Java projects, there&#8217;s no doubt about that. Unfortunately there is one great feature still lacking of Maven which is important when you use third party dependencies, namely detecting when your components use dependencies of different versions without your knowledge. What does that mean? It&#8217;s probably easier to explain [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://maven.apache.org/" target="_new">Maven</a> is a great tool for building Java projects, there&#8217;s no doubt about that. Unfortunately there is one great feature still lacking of Maven which is important when you use third party dependencies, namely detecting when your components use dependencies of different versions without your knowledge. </p>
<p>What does that mean? It&#8217;s probably easier to explain by example. Imagine you have a project that has two dependencies (can be your own created jars or third party, or anything Maven-buildable really). Your first dependency uses Log4J v1.0. Your second dependency uses Log4J v1.1.  When you compile this project Maven will by default use the &#8220;nearest wins&#8221; strategy, meaning it might pick Log4J v1.0 or Log4J v1.1, whichever is nearer in the <a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html" target="_new">transitive hull of dependencies</a>. What you probably wanted however, was for the compilation to tell you that you have two &#8220;modules&#8221; depending on the same library, but different versions of that library. Log4J is perhaps not the best example, but imagine that the dependency in question is a mission-critical dependency, and that any version discrepancy may cause catastrophic failures that can be very hard to track down via debugging.</p>
<p>To solve this I wrote a Maven plugin nearly a year ago that we are now using for every Maven-built project in our company. It&#8217;s a simple plugin that does the complex task of detecting all version clashes (even deeply nested ones) and will report them back to you either as warnings or errors (or ignore them). This project was submitted to the Maven team a while back but has not been integrated as a default Maven plugin yet, so it will now become a downloadable Software Project on Hexapixel until it hopefully becomes a standard module. </p>
<p><span id="more-603"></span></p>
<p>So how do you use it? Here&#8217;s a brief explanation and some examples of usage. If you&#8217;d rather skip to the plugin &#8220;homepage&#8221;, please follow <a href="/software/maven-version-clash-plugin">this link</a>.</p>
<h2><strong>Usage / Configuration</strong></h2>
<p>You can either run the clash-detector manually from the command line, or (the best option) is to add it to your POM (ideally your parent POM that all your projects use, you do have one right?) so that it is run automatically whenever you do builds.</p>
<p>There are only two options you can configure, one is the level of warning the plugin should do. By default the level is <code>FAIL</code>, meaning your build will fail if the plugin detects any clashes. The level can be changed either on the command line by supplying the parameter <code>-Dhalt=</code> where the right hand of the equals sign is one of <code>FAIL, WARN or DEBUG</code>. For the POM the same parameter is configured by supplying the same keyword inside a <code>&lt;halt /&gt;</code> tag such as: <code>&lt;halt&gt;WARN&lt;/halt&gt;</code></p>
<p>The second parameter is the level of detection the plugin should do. There are two modes, <code>SHALLOW and DEEP</code>. By default the level is <code>DEEP</code> where clash detection is not limited to the immediate level of the dependency, but also deeply nested dependencies. Shallow detection is only one level down and will not detect deeply nested dependency clashes. This is for example good for when you only care about clashes of your own jars (although I would strongly advice never using it unless really necessary).</p>
<p>Here are two snippets showing how to run the clash detector from the command line and how to configure it inside your POM.</p>
<p><b><strong>Command Line</strong></b></p>
<p>To invoke it from the command line you simply run it like this: </p>
<pre>
<pre class="syntax-highlight:xml">
mvn breakonversionclash:clash-detection -Dhalt=FAIL -Ddepth=SHALLOW
</pre>
</pre>
<p><b>In your POM</b></p>
<pre>
<pre class="syntax-highlight:xml">
&lt;build&gt;
	&lt;plugins&gt;
		&lt;plugin&gt;
			&lt;groupId&gt;com.hexapixel.maven.plugins&lt;/groupId&gt;
			&lt;artifactId&gt;
				maven-breakonversionclash-plugin
			&lt;/artifactId&gt;
			&lt;version&gt;1.0.1&lt;/version&gt;
			&lt;executions&gt;
				&lt;execution&gt;
					&lt;configuration&gt;
						&lt;!-- Options: FAIL, WARN, DEBUG (default is FAIL) --&gt;
						&lt;halt&gt;WARN&lt;/halt&gt;
						&lt;!-- Options: SHALLOW, DEEP (default is DEEP) --&gt;
						&lt;depth&gt;DEEP&lt;/depth&gt;
					&lt;/configuration&gt;
					&lt;phase&gt;compile&lt;/phase&gt;
					&lt;goals&gt;
						&lt;goal&gt;clash-detection&lt;/goal&gt;
					&lt;/goals&gt;
				&lt;/execution&gt;
			&lt;/executions&gt;
		&lt;/plugin&gt;
	&lt;/plugins&gt;
&lt;/build&gt;
</pre>
</pre>
<h2><strong>Plugin in Action</strong></h2>
<p>Here is a typical output the plugin will produce:</p>
<pre>
<pre class="syntax-highlight:xml">
 [INFO] [breakonversionclash:clash-detection {execution: default}]
 [INFO] Checking for dependency version clashes...
 [INFO] Halt mode is: &#039;warn&#039;. Depth mode is: &#039;deep&#039;.
 [WARNING] ------------------------------------------------------------------------
 [WARNING] Dependency version clash on &#039;commons-logging&#039; [1.0.4, 1.1.1]
 [WARNING] ------------------------------------------------------------------------
 [WARNING] Clash 1: commons-logging:commons-logging:1.0.4
 [WARNING] Clash 2: commons-logging:commons-logging:1.1.1
 [WARNING]
 [WARNING] Artifacts using different versions of &#039;commons-logging:commons-logging&#039;:
 [WARNING] - org.hibernate:hibernate:jar:3.2.6.ga
 [WARNING] - com.our.project:plugin-domain:jar:1.0.0.0-SNAPSHOT
 [WARNING]
 [WARNING] Dependency trail for &#039;commons-logging:commons-logging:1.0.4&#039;
 [WARNING] - Node 1: com.our.project:plugin-testdata:pom:1.0.0.0-SNAPSHOT
 [WARNING] - Node 2: com.our.project:plugin-testdata-source:zip:small-datasets:1.0.0.0-SNAPSHOT
 [WARNING] - Node 3: com.our.project:plugin-testdata-generator:jar:1.0.0.0-SNAPSHOT
 [WARNING] - Node 4: com.our.project:plugin-domain:jar:1.0.0.0-SNAPSHOT
 [WARNING] - Node 5: org.hibernate:hibernate:jar:3.2.6.ga
 [WARNING]
 [WARNING] Dependency trail for &#039;commons-logging:commons-logging:1.1.1&#039;
 [WARNING] - Node 1: com.our.project:plugin-testdata:pom:1.0.0.0-SNAPSHOT
 [WARNING] - Node 2: com.our.project:plugin-testdata-source:zip:small-datasets:1.0.0.0-SNAPSHOT
 [WARNING] - Node 3: com.our.project:plugin-testdata-generator:jar:1.0.0.0-SNAPSHOT
 [WARNING] - Node 4: com.our.project:plugin-domain:jar:1.0.0.0-SNAPSHOT
 [WARNING] Found 1 dependency version clash
</pre>
</pre>
<p>Let&#8217;s go over this even though it might be mostly self explanatory. </p>
<p>We have configured the plugin to only warn us when there is a clash, and to do a &#8220;deep&#8221; check, meaning it will not only check immediate dependencies, but also dependencies of dependencies.</p>
<p>It tells us that we have a clash on the usage of &#8216;commons-logging&#8217; and that the two clashing versions are version 1.0.4 and version 1.1.1 of commons-logging.</p>
<p>Then it tells us what jars are using commons-logging, in this case it&#8217;s our dependency on Hibernate and our own plugin-domain project. </p>
<p>It then shows us the dependency &#8220;trail&#8221; for each clash, meaning, it shows what depends on what all the way to the actual dependency of &#8216;commons-logging&#8217;, so that you can easily pinpoint what jars need adjusting so that the clash goes away.</p>
<h2><strong>Download / More Info</strong></h2>
<p>For downloads (binary and source) and more info, please go to the <a href="/software/maven-version-clash-plugin">Version Clash Plugin Page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2009/03/17/maven-and-dependency-version-clash-detection/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RCP Workspaces</title>
		<link>http://hexapixel.com/2009/01/12/rcp-workspaces</link>
		<comments>http://hexapixel.com/2009/01/12/rcp-workspaces#comments</comments>
		<pubDate>Mon, 12 Jan 2009 20:37:42 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Eclipse Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[JFace]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=483</guid>
		<description><![CDATA[An &#8220;Eclipse workspace&#8221; is basically a directory where all your metadata preference files are stored (Eclipse specific files, there&#8217;s a lot of them). It&#8217;s also where your projects are stored, your source files, jars, and so on. It&#8217;s useful to have all of this one one place, and Eclipse itself requires it or your workspace [...]]]></description>
			<content:encoded><![CDATA[<p>An &#8220;Eclipse workspace&#8221; is basically a directory where all your metadata preference files are stored (Eclipse specific files, there&#8217;s a lot of them). It&#8217;s also where your projects are stored, your source files, jars, and so on. It&#8217;s useful to have all of this one one place, and Eclipse itself requires it or your workspace probably won&#8217;t load. As it&#8217;s such a useful feature, I know a lot of people have tried to implement the existing &#8220;Switch Workspace&#8221; and the rest of the &#8220;Workspace&#8221; logic into their RCP applications, but I have yet to see many successes. The issue is that it&#8217;s most likely a feature you will want to customize (and in some aspects, you have to, as the &#8220;Workspace&#8221; implementation in Eclipse is not that open), and that&#8217;s where it gets tricky and possibly messy.</p>
<p>In our case, we wanted the normal Eclipse workspace logic so that users could create multiple &#8220;RCP Workspaces&#8221; and load whichever they wanted at startup, but we also wanted all of our custom RCP application specific data in the same directory (along with any other files we felt like creating), and we wanted to customize the dialog where the user picks a workspace. In the end, as you have probably guessed by now, we used nearly none of the default Eclipse workspace implementation, but managed to get RCP to believe that we were, and we got all the features we required in there as well.</p>
<p>This article will explain how we went about doing this, and will show you (with full source code of course) how you can implement exactly the same thing. And it&#8217;s much easier than it may sound.</p>
<p><span id="more-483"></span></p>
<h2><strong>The Magic Parameter</strong></h2>
<p>Everything starts with one little command line parameter that tells Eclipse we will be in charge of specifying where the workspace goes. Obviously we need to do this very early in the application or else by the time we have a UI, Eclipse has no place to put preferences. And if we do it too late, Eclipse will exit with an exception saying that it has no workspace. The &#8220;Program Argument&#8221; that makes it possible for us to define a workspace at runtime looks like this: <code>-data @noDefault</code>.</p>
<p>If you look at your &#8220;Run Configurations&#8221; in Eclipse (&#8220;Run&#8221; menu, then &#8220;Run Configurations&#8230;&#8221;) and click the &#8220;Arguments&#8221; tab, you will probably see a few cryptic entries that Eclipse has created for you, they look like this: <code>-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl}</code>. By appending our @noDefault argument, we end up with this: <code>-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -data @noDefault</code>.</p>
<p>Here is a screenshot of how it would look when appended:<br />
<img title="Arguments Tab" src="http://hexapixel.com/wp-content/uploads/2009/01/args_tab.gif" alt="Arguments Tab" width="522" height="131" /></p>
<p>So what does that parameter do? It simply tells Eclipse not to use any default workspace location (or &#8220;OSGI instance area&#8221; as it&#8217;s called in the API) when it starts up and expects us to provide it instead. Here&#8217;s an API link to the document explaining the different <a href="http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/misc/runtime-options.html" target="_new">Eclipse runtime options</a> you can set (including the ones mentioned here).</p>
<h4><strong>Telling Eclipse The Location Manually</strong></h4>
<p>So, where and how do we tell Eclipse that we have a &#8220;workspace home&#8221; that we want it to use? As I mentioned before, we need to do it early. That means we need to do it in <code>Application.java</code> and more specifically in the <code>public Object start(IApplicationContext context) throws Exception {</code> method. By default this method will mostly be empty except for some Eclipse specific code (undoubtedly generated by Eclipse when you created the RCP project), but we&#8217;ll soon change that. Eclipse will expect us to set the necessary location by modifying the &#8220;InstanceLocation&#8221; on the Platform. We can get the <code>Location</code> by doing a one-line call like this: <code>Location instanceLoc = Platform.getInstanceLocation();</code>. Assuming we already have a specific workspace location in mind, we could do the following:</p>
<pre>
<pre class="syntax-highlight:java">
try {
	// fetch the Location that we will be modifying
	Location instanceLoc = Platform.getInstanceLocation();

	// set location to c:\temp
	instanceLoc.set(new URL(&quot;file&quot;, null, &quot;c:\\temp&quot;), false);
}
catch (Exception err) {
	...
}
</pre>
</pre>
<p>When we create the URL we tell it that the protocol to use is a file. We also tell it that the host is null and that the file in question is <code>c:\temp</code> (which is actually a directory of course). The last <code>false</code> that we pass to the set method is whether we want to lock the workspace location (which we don&#8217;t).</p>
<p>We have now satisfied Eclipse&#8217;s needs for custom-defining a workspace, and when you start your product or RCP application, you should see that Eclipse has created a <code>.metadata</code> directory underneath it. But as we hardcoded the path to <code>c:\temp</code>, this doesn&#8217;t let us &#8220;customize&#8221; it much does it? What about &#8220;Switch Workspace&#8221; functionality and asking the user what workspace they would like to pick? (or create)</p>
<h2><strong>Asking The User</strong></h2>
<p>In our case, we ask users at startup what workspace we should use (Just like Eclipse does). We do various checks to see if the directory they pick is already a workspace, if it&#8217;s writable/readable, and so on. If everything is OK, we return the selected directory to the previous code exmple and put it where we used <code>c:\temp</code> before.</p>
<p>To make it easy, you could re-use code from the &#8220;Select workspace dialog&#8221; from Eclipse, but we want ours custom, so I&#8217;ll explain how that&#8217;s done. </p>
<p>Let&#8217;s create a class called <code>PickWorkspaceDialog</code>, as we&#8217;ll re-use this for the Switch Workspace action later, we&#8217;ll make it with a constructor that takes a boolean that defines whether it&#8217;s the normal &#8220;startup pick workspace&#8221; dialog or if it&#8217;s the &#8220;switch workspace&#8221; dialog. As Eclipse already has a pretty nice dialog that we can re-use that lets us put an image and a message at the top, we&#8217;ll be extending <code>TitleAreaDialog</code>.</p>
<p>While we&#8217;re at it, lets create features for cloning a workspace and a combo that remembers our last selected ones as well.</p>
<p>As it&#8217;s a lot of code to paste into an article &#8211; and I think a lot of it is straight forward &#8211; I will simply link to the entire java class and show some selective snippets below. For starters, this class was created using layouts with the <a href="/files/layout.jar" target="_new">LatticeLayout</a> layout manager (Update: Site is down, old lik was <a href="http://www.quirk.biz/quirkdownloads/index.html" target="_new">here</a>, I&#8217;ve changed link to the direct jar download which contains javadoc and sources as well), so if you don&#8217;t want to re-code those sections, go grab it. (This is a simpler <a href="http://www.miglayout.com" target="_new">MigLayout</a> layout manager) similar to Swing&#8217;s TableLayout. Should you not wish to use either, it should be easy to change the layouts to anything you want (GridLayout for example).</p>
<p>You can download the Java file <a href="/files/posts/PickWorkspaceDialog.java">here</a> (and at the bottom of the article). I suggest you browse through it quickly before we continue as it will make it much easier to follow. Do note that this class has been optimized to &#8220;fit in one class&#8221;, as normally some of the methods found in there would undoubtedly be split up into other places. But for the making this article it was combined into one file.</p>
<h4><strong>Using Preferences</strong></h4>
<p>Normally in a RCP application we would be using an <code>IPreferenceStore</code> to save/load our preferences. But as we need to save the location of what workspace we used last &#8211; before we have access our preference store (which is saved in our not-yet-selected workspace location), we need to save/load from somewhere else. The most logical solution is to use the <a href="http://java.sun.com/j2se/1.4.2/docs/guide/lang/preferences.html" target="_new">java Preferences API</a>. By defining a preference location along the lines of;</p>
<pre>
<pre class="syntax-highlight:java">
// create/get our preferences location based on the class
private static Preferences _preferences = Preferences.userNodeForPackage(PickWorkspaceDialog.class);

// lets define the keys we will be saving
private static final String _KeyWorkspaceRootDir   = &quot;wsRootDir&quot;;
private static final String _KeyRememberWorkspace  = &quot;wsRemember&quot;;
private static final String _KeyLastUsedWorkspaces = &quot;wsLastUsedWorkspaces&quot;;
</pre>
</pre>
<p>we can now save/load those preferences as early or late as we want. Do note that any user launching the application on the same computer will be seeing the same saved preferences, so if you need a more secure or private solution this may not be ideal for you. But for 99% of us this is fine. If you do not know how the Java Preferences API works, take a quick look at the <a href="http://java.sun.com/j2se/1.4.2/docs/guide/lang/preferences.html" target="_new">API</a> or the <a href="/files/posts/PickWorkspaceDialog.java">PickWorkspaceDialog.java</a> file.</p>
<h4><strong>Identifying Our Workspace</strong></h4>
<p>When a user selects a directory, we want to check if that directory is a &#8220;Our Application&#8221; workspace directory or some other plain directory. We do this by creating an empty file when the workspace is created, so that later, if they select an existing directory, we can say if it&#8217;s a valid &#8220;Our Application&#8221; workspace directory or not. In the <code>PickWorkspaceDialog.java</code> class you will see a method named <code>checkWorkspaceDirectory</code> that deals with both checking if a directory already exists or not (to ask if the user wants to create a new workspace there), and it also deals with checking any existing directory to ensure it&#8217;s a workspace directory for our application. The filename is defined at the top of the class, just look for <code>public static final String  WS_IDENTIFIER = ".our_rcp_workspace";</code></p>
<p>You will also see code that checks to ensure the user doesn&#8217;t select a subdirectory of an existing workspace directory, as that could cause an infinite recursive directory-creating loop, which is obviously bad.</p>
<p>Running the code from within RCP will give you a dialog that looks like this (assuming you gave it a nice image to display &#8211; the wizard image used in the screenshot is part of the Eclipse platform, so you can find most of them inside the eclipse jars):</p>
<p><img title="Select Workspace Dialog" src="http://hexapixel.com/wp-content/uploads/2009/01/sel_workspace.gif" alt="Select Workspace Dialog" width="457" height="244" /></p>
<p>As we need to hook it up to actual code, showing the screenshot before we do so makes it easier when I mention things as the &#8220;remember&#8221; checkbox.</p>
<h4><strong>Hooking It Up</strong></h4>
<p>Back in <code>Application.java</code> we now want to change our previous code to use the dialog to ask the user for a workspace. We also need to check if the user selected the &#8220;remember&#8221; checkbox as then we don&#8217;t show the dialog at all (unless the previously selected workspace directory can&#8217;t be found). We also want to check that the old workspace directory is still OK in terms of reading/writing etc. All in all, we want something like this (excuse the formatting, the sourcecode formatter doesn&#8217;t like large deeply nested blocks):</p>
<pre>
<pre class="syntax-highlight:java">
public Object start(IApplicationContext context) throws Exception {
	try {
		// the old Eclipse generated code
		Display display = PlatformUI.createDisplay();
		// and so on..

		// get what the user last said about remembering the workspace location
		boolean remember = PickWorkspaceDialog.isRememberWorkspace();

		// get the last used workspace location
		String lastUsedWs = PickWorkspaceDialog.getLastSetWorkspaceDirectory();

		// if we have a &quot;remember&quot; but no last used workspace, it&#039;s not much to remember
		if (remember &amp;&amp; (lastUsedWs == null || lastUsedWs.length() == 0)) {
		    remember = false;
		}

		// check to ensure the workspace location is still OK
		if (remember) {
		    // if there&#039;s any problem whatsoever with the workspace, force a dialog which in its turn will tell them what&#039;s bad
		    String ret = PickWorkspaceDialog.checkWorkspaceDirectory(Display.getDefault().getActiveShell(), lastUsedWs, false, false);
		    if (ret != null) {
			remember = false;
		    }

		}

		// if we don&#039;t remember the workspace, show the dialog
		if (!remember) {
		    PickWorkspaceDialog pwd = new PickWorkspaceDialog(false);
		    int pick = pwd.open();

		    // if the user cancelled, we can&#039;t do anything as we need a workspace, so in this case, we tell them and exit
		    if (pick == Window.CANCEL) {
			if (pwd.getSelectedWorkspaceLocation()  == null) {
			    MessageDialog.openError(display.getActiveShell(), &quot;Error&quot;,
				    &quot;The application can not start without a workspace root and will now exit.&quot;);
			    try {
				PlatformUI.getWorkbench().close();
			    } catch (Exception err) {

			    }
			    System.exit(0);
			    return IApplication.EXIT_OK;
			}
		    }
		    else {
			// tell Eclipse what the selected location was and continue
			instanceLoc.set(new URL(&quot;file&quot;, null, pwd.getSelectedWorkspaceLocation()), false);
		    }
		}
		else {
		    // set the last used location and continue
		    instanceLoc.set(new URL(&quot;file&quot;, null, lastUsedWs), false);
		}	

		// this is the normal default code from here on out
		int returnCode = PlatformUI.createAndRunWorkbench(display, new ApplicationWorkbenchAdvisor());
		if (returnCode == PlatformUI.RETURN_RESTART) { return IApplication.EXIT_RESTART; }
		return IApplication.EXIT_OK;

	}
	catch (Exception err) {
		...
	}
	finally {
	    display.dispose();
	}
}
</pre>
</pre>
<p>And that&#8217;s it. We now have a fully working and modifiable &#8220;Select Workspace&#8221; dialog that tells Eclipse where to put the metadata and we can modify any of it to our hearts content. With that all out of the way, the only thing remaining is the &#8220;Switch Workspace&#8221; action.</p>
<h2><strong>Switch Workspace</strong></h2>
<p>Eclipse has a built-in Switch Workspace action that you could access from the <code>ActionFactory</code>, but as we custom implemented our workspace picker, this wouldn&#8217;t help us much. Our dialog is already set up to handle a workspace switch (pretty much all it does is show a different message after all).</p>
<p>So, lets create an Action that will be our Switch Workspace action. It will be surprisingly short, and look like this:</p>
<pre>
<pre class="syntax-highlight:java">
public class ActionSwitchWorkspace extends Action {

    private Image _titleImage;

    public ActionSwitchWorkspace(Image titleImage) {
        super(&quot;Switch Workspace&quot;);
        _titleImage = titleImage;
    }

    @Override
    public void run() {
        PickWorkspaceDialog pwd = new PickWorkspaceDialog(true, _titleImage);
        int pick = pwd.open();
        if (pick == Dialog.CANCEL)
            return;

        MessageDialog.openInformation(Display.getDefault().getActiveShell(), &quot;Switch Workspace&quot;, &quot;The client will now restart with the new workspace&quot;);

        // restart client
        PlatformUI.getWorkbench().restart();
    }
}
</pre>
</pre>
<p>As all necessary variables and workspace locations are handled in the <code>PickWorkspaceDialog</code> class we don&#8217;t need to do anything else than tell the picked that it is now a &#8220;Switch Workspace&#8221; dialog, and then restart the RCP application if the user pressed &#8220;OK&#8221;.</p>
<p>Ideally we&#8217;d add this action in our <code>ActionBarAdvisor</code> class (default name is <code>ApplicationActionBarAdvisor</code>) under the File menu somewhere.</p>
<p>The result when run will look like this:</p>
<p><img title="Switch Workspace Dialog" src="http://hexapixel.com/wp-content/uploads/2009/01/sw_workspace.gif" alt="Switch Workspace Dialog" width="457" height="244" /></p>
<h2><strong>That&#8217;s It</strong></h2>
<p>With the code mentioned in this article you now have full &#8220;workspace&#8221; functionality for your Eclipse RCP application without having to dig in to extension points or other XML-based overrides, and you have the ability to customize any of it as much as you want. As you see it doesn&#8217;t take that much code as most of the big code is methods for copying files and checking directories.</p>
<h2><strong>All Code</strong></h2>
<p>Here are download links to all code referenced in this article:</p>
<div id="bulletlist">
<ol>
<li><a href="/files/posts/PickWorkspaceDialog.java">PickWorkspaceDialog.java</a></li>
</ol>
</div>
<p>(For the <code>Application.java</code> code please copy the big block in the article as it shows all code related to that class.)</p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2009/01/12/rcp-workspaces/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Glazed Lists + SWT Tables == True</title>
		<link>http://hexapixel.com/2009/01/02/glazed-lists-swt-tables-true</link>
		<comments>http://hexapixel.com/2009/01/02/glazed-lists-swt-tables-true#comments</comments>
		<pubDate>Fri, 02 Jan 2009 18:01:19 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Eclipse Articles]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JFace]]></category>
		<category><![CDATA[SWT]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=387</guid>
		<description><![CDATA[If you haven&#8217;t heard about Glazed Lists until now, it&#8217;s about time you do, because it&#8217;s probably the last tables and grid sorting/filtering API you will ever need. It will also be the last time you rip your hair out when someone asks you for a multi-sort-multi-thread-asynchronously-updated-filtered-unique-table (which happens all the time, right?). From here [...]]]></description>
			<content:encoded><![CDATA[<p>If you haven&#8217;t heard about <a href="http://www.publicobject.com/glazedlists/">Glazed Lists</a> until now, it&#8217;s about time you do, because it&#8217;s probably the last tables and grid sorting/filtering API you will ever need. It will also be the last time you rip your hair out when someone asks you for a multi-sort-multi-thread-asynchronously-updated-filtered-unique-table (which happens all the time, right?). From here on out you&#8217;ll just be saying &#8220;oh, sure, give me 30 minutes&#8221; when you need to implement something along those lines. Sounds too good to be true doesn&#8217;t it? It is! So, what are Glazed Lists?</p>
<p>Glazed Lists is an API built on top of <code>java.util.List</code> which adds a notification framework and allows you to &#8220;stack&#8221; or &#8220;chain&#8221; lists together. This in and by itself may not sound so exciting. What this gives you though is the ability to take a Sorted list, stack it with a Filtered list, stack it with a Unique list, stack it with a asynchronously updated Unique list (and keep stacking), and whenever you modify the source list, it automatically tells the other lists in the chain to update so that their lists are always up to date. Last but not least, the list reports back to you and tells you to update your view with a specific list of changes. So imagine this &#8220;chained list&#8221; is the input for your TableViewer and perhaps you&#8217;re starting to see the potential.</p>
<p>I&#8217;ve been using Glazed Lists continuously for the last year, and it&#8217;s no short of astounding how powerful it is. I&#8217;ve used them on JFace TableViewers, The <a href="http://www.eclipse.org/nebula/widgets/grid/grid.php" target="_blank">Nebula Grid</a> widget, and the great rising-star <a href="http://nattable.org/drupal/" target="_blank">NatTable</a> which deserves it&#8217;s own article down the road (the only table widget I&#8217;ve found that can handle huge amounts of data without choking). On each of those widgets it was only a matter of creating a couple of smaller classes, a few lines of code, and I had the most powerful sorting and filtering API at my fingertips, ready for anything upper management could throw at me in terms of features. So often I see posts on the Eclipse Newsgroups asking about multi column sorting, and usually few concrete replies. &#8220;Glazed Lists&#8221; would be my reply.  To give an idea of what kind of sorting/filtering you can do, here&#8217;s a snapshot of  some of the available list types:</p>
<p><i>Sorted List. Filtered List. Unique List. Transformed List. Range List. Threshold List. Collection List. Freezable List. Popularity List. Separator List. Sequence List. Transaction List. Observable Lists</i>.. and the list goes on.</p>
<p>So instead of talking about how great they are in an entire post, how about some example implementations and actual code? Alright, let&#8217;s get to it!</p>
<p><span id="more-387"></span></p>
<p>To make this article &#8220;worth it&#8221; for everyone, I will cover implementing Glazed Lists on no less than 3 table/grid widgets. The standard JFace TableViewer (which is the least feature rich table component out there as it uses the SWT Table). The Nebula Grid widget (which is feature rich and very good, but has a big memory footprint on large tables) and the NatTable widget (as it will undoubtedly rise to fame soon with the next few versions (once some of the bigger bugs are ironed out)). Before you start copying and pasting code, all code is downloadable in each respective section and at the bottom of the article.</p>
<p>If you prefer to follow along or want to get a head start on downloading required jars, here are links to all the third party packages you might need:</p>
<div id="bulletlist">
<ol>
<li><a href="http://www.publicobject.com/glazedlists/glazedlists-1.7.0/" target="_new">Glazed Lists v1.7</a> (you do need this one)</li>
<li><a href="http://www.eclipse.org/nebula/widgets/grid/grid.php" target="_new">Nebula Grid (and Grid Viewer, required for the Nebula framework)</a></li>
<li><a href="http://sourceforge.net/project/showfiles.php?group_id=207809" target="_new">Nat Table v1.6.3 (grab both jars)</a></li>
<li><a href="http://logging.apache.org/log4j/1.2/download.html" target="_new">Apache Log4J</a> (Nat table needs this)</li>
<li><a href="http://commons.apache.org/downloads/download_lang.cgi" target="_new">Apache Commons Lang</a> (Nat table uses this internally for some odd reason)</li>
<li><a href="http://www.eclipse.org/downloads/" target="_new">Eclipse IDE / SWT</a></li>
</ol>
</div>
<p>Let&#8217;s start with the basics of Glazed Lists, as everything starts there.</p>
<h2><strong>Glazed Lists In a Nutshell</strong></h2>
<p>I could send you to the <a href="http://sites.google.com/site/glazedlists/documentation/tutorial" target="_new">Glazed Lists Tutorials</a> and tell you to follow those and come back, but I hate that kind of &#8220;teaching&#8221;, and the small &#8220;problem&#8221; with the tutorials is that they are all Java Swing based which is of little use to us (but by all means read them, they&#8217;re good). You might also want to check out the very good screen casts located <a href="http://publicobject.com/glazedlistsdeveloper/" target="_new">here</a> as they will give you a good idea of the different types of lists that can be used in Glazed Lists. In any case, everything in Glazed Lists starts with one thing, the root list. The root list contains all your items that you want to display before they are filtered or sorted. This list is probably in some random you-don&#8217;t-care order  which is perfectly fine. This list will serve as the input for all other chained lists. Think of it as layers, where the bottom layer is the raw list, and the higher up you go, the more refined and specific each layer is. So you have a sorting layer, a filter layer, etc. They can be active or not active, a bit like Photoshop. As we are using Glazed Lists, we need to take our root list and turn it into a Glazed Lists &#8220;EventList&#8221;, which is the Glazed Lists root-list equivalent. Here&#8217;s how that&#8217;s done:</p>
<pre>
<pre class="syntax-highlight:java">
List&lt;?&gt; rootList = .... // this comes from you
EventList&lt;?&gt; eventList = GlazedLists.eventList(rootList);
</pre>
</pre>
<p>As you can see everything uses Generics, just like normal Lists in Java 5+.</p>
<p>Any &#8220;normal&#8221; table in the UI-world will undoubtedly have Sorting and Filtering. With the code above we&#8217;re currently no different from any other plain old table implementation as we haven&#8217;t done sorting/filtering yet. So lets create the sorting/filtering layers that will be on top of the event list. We should think about order when it comes to our layers, as if we create a sorted list on top of a filtered list that&#8217;s not the same as creating a filtered list on top of a sorted list. Logically, we sort first, then apply a filter. To create our new lists we continue the code:</p>
<pre>
<pre class="syntax-highlight:java">
List&lt;?&gt; rootList = .... // this comes from you
EventList&lt;?&gt; eventList = GlazedLists.eventList(rootList);
SortedList sortedList = new SortedList(eventList, null);
FilterList(sortedList, new OurFilterMatcher());
</pre>
</pre>
<p>As you can see we keep using the last list as the input for the new list, as that&#8217;s our &#8220;chain&#8221;. The second parameter for the SortedList is the <code>Comparator</code> we want to use when sorting. I&#8217;m passing in <code>null</code> here to point out that it can be created when constructing the list (and not passing in null may actually throw an exception). Normally you don&#8217;t want the table sorted unless the user sorts it, so <code>null</code> makes sense. The <code>OurFilterMatcher</code> will be explained when we do the actual implementation, but just remember that it&#8217;s the &#8220;Matcher&#8221; that is used to filter a table (which is very much like a <code>ViewerFilter</code>).</p>
<p>There&#8217;s one more important aspect of Glazed Lists &#8211; locking. As lists can be updated on multiple threads (if you so wish) you need to tell the list when to &#8220;lock&#8221; and &#8220;unlock&#8221; so that only 1 thread is actively writing to the list at the same time. As such, it&#8217;s important we always do this when reading and writing to the list (and even if we don&#8217;t plan on multithread updates, it&#8217;s still good practice and takes little time to do). We could lock the lists when creating them even, but that&#8217;s a bit overkill, so keep en eye out for the locking code in the implementation part and in the framework code available for download. Glazed Lists even supports reading while writing, and their homepage has an example of an asynchronously updated list. Do check it out if you need advanced implementations. To give a quick example of locking/unlocking a list, here&#8217;s how it&#8217;s done:</p>
<pre>
<pre class="syntax-highlight:java">
_eventList.getReadWriteLock().writeLock().lock();
// ... modify list here ...
_eventList.getReadWriteLock().writeLock().unlock();
</pre>
</pre>
<h4><strong>The Callbacks</strong></h4>
<p>The whole idea of Glazed Lists is that when you modify the event list (and this is important: <strong>you <span style="text-decoration: underline;">always</span> modify the EventList</strong>!), it fires events to tell you what you need to change in your table implementation. Glazed has a lot of pre-built hooks for Swing, so there you don&#8217;t have to do much work, but as we use SWT we have to do pretty much all the work ourselves (great huh?). It&#8217;s not as bad as it sounds however. The callback interface that we care about here is <code>ListEventListener</code> which contains a method callback called <code>public void listChanged(ListEvent&lt;?&gt; listChanges)</code>. This list of changes <code>listChanges</code> tells us, <strong>in the correct order</strong>, what indexes and objects to update, delete and insert. It&#8217;s as easy as looping through that list, checking what the change is, and performing it. Here&#8217;s a barebones example of how it would look implemented:<a name="nutshell_code"></a></p>
<pre>
<pre class="syntax-highlight:java">
_filterList.addListEventListener(new ListEventListener&lt;?&gt;() {

	@Override
	public void listChanged(ListEvent&lt;?&gt; listChanges) {
		// get the list of changes (prior to looping, very important as it&#039;ll change as it&#039;s read)
		final List&lt;?&gt; changeList = listChanges.getSourceList();

		// go through all changes
		while (listChanges.next()) {
			// get the table index location of the change
			int sourceIndex = listChanges.getIndex();
			// get the change type
			int changeType = listChanges.getType();

			// update the table depending on the change type
			switch (changeType) {
				case ListEvent.DELETE:
					// delete row
					break;
				case ListEvent.INSERT:
					// insert row
					break;
				case ListEvent.UPDATE:
					// refresh row labels etc
					break;

			}
		}
	}

});
</pre>
</pre>
<p>That&#8217;s actually the most complex code we&#8217;ll be adding to make all of this work, and we can re-use that section of code for all our table widget implementations. </p>
<p>You might ask &#8220;why is the listener on the filter list if we were told to only modify the event list?&#8221;, which is a good and valid question. The answer is that if you were to listen on the event list instead, only base-level adds and deletes would be reported to you. As we also care about when stuff is re-ordered or moved in the list (which is what happens when users sort and filter) we want any list-changes to notify us. As our filtered list is the &#8220;topmost&#8221; or &#8220;last&#8221; list in the chain, it will get all notifications from all previous lists in the chain. Remember, all lists in the chain tell the next list down the line what changed (think of it as one-way gossip). By listening on the Filtered list we get all events, regardless on what list they happened. With that information we&#8217;re well on our way to putting Glazed into real use.</p>
<h2><strong>SWT TableViewer</strong></h2>
<p>Personally I was never a big fan of the SWT Table. A good thing about it is that it renders column headers natively, but it can be quite slow, sometimes buggy (first-column image support) and not very intuitive. It doesn&#8217;t support much customization and the second you need a table that can do a little more than a plain x/y grid, you soon hit those limitations head on. <a href="http://www.eclipse.org/articles/article.php?file=Article-CustomDrawingTableAndTreeItems/index.html" target="_new">Owner Draw</a> does help, but there&#8217;s still a lot of customization that is not possible. That said, as a &#8220;basic table&#8221; it does just fine and it&#8217;s getting better for each new SWT version. And of course, it&#8217;s native.</p>
<p>Normally when someone asks &#8220;can I sort a <code>SWT.VIRTUAL</code> table?&#8221; the answer is no or &#8220;not really&#8221;. The reason is that a virtual table only really knows what it shows in the current viewport (the visual area of the table), and how many items it has. Anything that you can&#8217;t see is not really &#8220;there&#8221;, except in memory. This obviously makes such a useful feature as <code>SWT.VIRTUAL</code> fairly useless in a sort scenario. The workaround in that case is to custom implement a sorter and replace the entire table content whenever the user sorts or filters. As we use Glazed Lists we don&#8217;t really care about this limitation, we&#8217;re working around it as we update the table with our changes whenever they occur thanks to the callback from Glazed Lists.</p>
<p>There&#8217;s a few special things we need apart from a &#8220;normal&#8221; Virtual TableViewer implementation. First, we&#8217;ll be using the <code>IStructuredContentProvider</code> for the Content provider. The <code>ILazyContentProvider</code> exists as well, but I had some odd issues with it in testing. If you want an example on how to create a virtual TableViewer, there&#8217;s a good snippet here: <a href="http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.jface.snippets/Eclipse%20JFace%20Snippets/org/eclipse/jface/snippets/viewers/Snippet029VirtualTableViewer.java?revision=1.1&amp;view=markup" target="_new">Snippet029VirtualTableViewer</a>. In the <code>IStructuredContentProvider</code> we simply return the topmost layer (which is the FilterList) as follows;</p>
<pre>
<pre class="syntax-highlight:java">
class GlazedContentProvider implements IStructuredContentProvider {

	@Override
	public Object[] getElements(Object inputElement) {
		return _filterList.toArray();
	}

	@Override
	public void dispose() {
	}

	@Override
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
	}

}
</pre>
</pre>
<p>We also need to implement a Comparator which will be used by the SortedList, as well as a Matcher for the FilterList. The Comparator is a normal java Comparator whereas the Matcher is a Glazed Lists implementation. However, these are <a href="http://en.wikipedia.org/wiki/Immutable_object" target="_new">immutable</a> so they need to be new every time they are set on the respective lists. For the sake of simplicity, lets create an object called RowObject that represents one row in our table. All it does is keep track of the row number and it has a <code>getColumnText</code> method.</p>
<pre>
<pre class="syntax-highlight:java">
class RowObject {
	private int	_row;

	public RowObject(int row) {
		_row = row;
	}

	public int getRow() {
		return _row;
	}

	public String getColumnText(int col) {
		return &quot;&quot; + (_row + col);
	}
}
</pre>
</pre>
<p>With this all set up, we can now create the Comparator and Matcher. Lets start with the Comparator. As we&#8217;re basically returning an integer as display value for each cell in <code>getColumnText</code> we&#8217;ll use this as the basis for our comparison. Thus, our Comparator looks as follows;</p>
<pre>
<pre class="syntax-highlight:java">
class GlazedSortComparator implements Comparator&lt;RowObject&gt; {

	private int	_col;
	private int	_direction;

	public GlazedSortComparator(int col, int direction) {
		_col = col;
		_direction = direction;
	}

	@Override
	public int compare(RowObject o1, RowObject o2) {
		int ret = Integer.valueOf(o1.getColumnText(_col)).compareTo(Integer.valueOf(o2.getColumnText(_col)));

		if (_direction == SWT.DOWN)
			ret = -ret;

		return ret;
	}

}
</pre>
</pre>
<p>And now we create the Matcher which is used by the FilterList. The Matcher implementation in Glazed Lists asks us if a row object &#8220;matches&#8221; and not much more. This may seem confusing at first, but it&#8217;s quite similar to the <a href="http://help.eclipse.org/stable/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ViewerFilter.html" target="_new">ViewerFilter</a>. In our code we will have a textbox and a button that represents a &#8220;search&#8221; box. When the user presses the button we set a String field called &#8220;_filterText&#8221; to whatever the user entered, and then we set a new matcher on the FilterList. As such, our code implementation looks like this:</p>
<pre>
<pre class="syntax-highlight:java">
class GlazedMatcher implements Matcher&lt;RowObject&gt; {
	@Override
	public boolean matches(RowObject row) {
		for (int i = 0; i &lt; _table.getColumnCount(); i++) {
			if (row.getColumnText(i).indexOf(_filterText) &gt; -1)
				return true;
		}

		return false;
	}
}
</pre>
</pre>
<p>Now we can add two methods that actually do the updating when we filter and when we sort. Like this:</p>
<pre>
<pre class="syntax-highlight:java">
// update the table filter
private void updateFilter() {
	// if the search text is blank, remove the matcher
	if (_filterText == null || _filterText.length() == 0) {
		_filterList.setMatcher(null);
	}
	else {
		_filterList.setMatcher(new GlazedMatcher());
	}
}

// sorts a table on the given column
private void sortColumn(int col) {
	// do some normal UP/DOWN checking and updating
	int dir = SWT.UP;
	int current = _table.getSortDirection();

	TableColumn tc = _table.getColumn(col);
	if (_table.getSortColumn() == tc) {
		dir = (current == SWT.UP ? SWT.DOWN : SWT.UP);
	}

	_table.setSortColumn(tc);
	_table.setSortDirection(dir);

	// now tell the sorted list we&#039;ve updated
	_sortedList.setComparator(new GlazedSortComparator(col, dir));
}
</pre>
</pre>
<p>At this point we&#8217;re basically there. All that&#8217;s missing is a proper <code>listChanged</code> that reflects how we update a TableViewer. So with a few modifications to the code I posted in the <a href="#nutshell_code">nutshell section</a>, we get code that looks like this:</p>
<pre>
<pre class="syntax-highlight:java">
_filterList.addListEventListener(new ListEventListener&lt;RowObject&gt;() {

	@Override
	public void listChanged(ListEvent&lt;RowObject&gt; listChanges) {
		try {
			_table.setRedraw(false);

			// get the list PRIOR to looping, otherwise it won&#039;t be the same list as it&#039;s modified continuously
			final List&lt;RowObject&gt; changeList = listChanges.getSourceList();

			while (listChanges.next()) {
				int sourceIndex = listChanges.getIndex();
				int changeType = listChanges.getType();

				switch (changeType) {
					case ListEvent.DELETE:
						// note the remove of the object fetched from the event list here, we need to remove by index which the viewer does not support
						// and we&#039;re removing the object index location from the event list, not the filtered list
						_viewer.remove(_eventList.get(sourceIndex));
						break;
					case ListEvent.INSERT:
						final RowObject obj = changeList.get(sourceIndex);
						_viewer.insert(obj, sourceIndex);
						_viewer.replace(_filterList.get(sourceIndex), sourceIndex);
						break;
					case ListEvent.UPDATE:
						_viewer.replace(_filterList.get(sourceIndex), sourceIndex);
						break;
				}
			}

			// most important, we update the table size after the update
			_viewer.setItemCount(_filterList.size());
		}
		catch (Exception err) {
			err.printStackTrace();
		}
		finally {
			_table.setRedraw(true);
		}
	}

});
</pre>
</pre>
<p>The result, when combined with the rest of the necessary boilerplate code, looks like this:</p>
<p><img title="TableViewer using Glazed Lists" src="http://hexapixel.com/wp-content/uploads/2009/01/tv_glazed.gif" alt="tv_glazed" width="646" height="400" /></p>
<h4><strong>Download Code</strong></h4>
<p><a href="/files/posts/TableViewerGlazedExample.java">TableViewerGlazedExample.java</a></p>
<h2><strong>Nebula Grid</strong></h2>
<p>Whereas the normal SWT table only supports single column sort (unless you <a href="http://www.eclipse.org/articles/article.php?file=Article-CustomDrawingTableAndTreeItems/index.html" target="_new">owner draw</a>) the Nebula grid can do more. It can do multiple column sorting (visually), grouped columns, and other custom features not available in the default grid. The Nebula Grid has a Viewer implementation, but unfortunately at the time of writing this article, it does not support <code>SWT.VIRTUAL</code> mode. As Nebula sticks very much to the SWT API in terms of naming conventions and implementation, it should be little trouble to convert it over when it does.</p>
<p>Depending on how you look at it, you are about to get quite lucky. For my job I wrote an entire framework implementation wrapping Glazed Lists in a Nebula Grid. It&#8217;s much more generically implemented (with interfaces etc) than our TableViewer example which was written purely for this article. Because of this I don&#8217;t feel like actually ripping it apart into something smaller, so I will use this Framework as the basis for the examples. Thus, this implementation comes with the option to use both the GridViewer implementation (which might be good if you are doing smaller tables that don&#8217;t need Virtual mode) or the grid in <code>SWT.VIRTUAL</code> mode.</p>
<p>One of the bigger differences when we&#8217;re not in viewer mode, is that on the <code>DELETE, INSERT</code> and <code>UPDATE</code> we need to create <code>GridItems</code> instead of just telling the viewer that it&#8217;s changed. It&#8217;s a bit more clunky and object-heavy of course, but it&#8217;s not as bad as it sounds. The switch statement that we used in the previous example becomes this:</p>
<pre>
<pre class="syntax-highlight:java">
switch (changeType) {
    case ListEvent.DELETE:
        removeItem(sourceIndex);
        break;
    case ListEvent.INSERT:
        final IDataObject insert = list.get(sourceIndex);
        addItem(insert, sourceIndex);
        break;
    case ListEvent.UPDATE:
        final IDataObject update = list.get(sourceIndex);
        removeItem(sourceIndex);
        addItem(update, sourceIndex);
        break;
}
</pre>
</pre>
<p>As you can see each one calls a sub-method of the class, and those methods look like this:</p>
<pre>
<pre class="syntax-highlight:java">
private void removeItem(int index) {
	_parent.getTableViewer().remove(_parent.getTableViewer().getElementAt(index));
}

private void addItem(IDataObject msg, int index) {
	GridItem gi = new GridItem(_parent.getGrid(), SWT.NONE, index);
	gi.setData(msg);

	try {
		for (int i = 0; i &lt; _parent.getGrid().getColumnCount(); i++) {
			Color fg = msg.getForeground(i, index % 2 == 0);
			Color bg = msg.getBackground(i, index % 2 == 0);
			Font f = msg.getFont(i);
			String txt = msg.getColumnText(i);
			Image image = msg.getColumnImage(i);

			if (fg != null) {
				gi.setForeground(i, fg);
			}
			if (bg != null) {
				gi.setBackground(i, bg);
			}
			if (f != null) {
				gi.setFont(i, f);
			}
			if (txt != null) {
				gi.setText(i, txt);
			}
			if (image != null) {
				gi.setImage(i, image);
			}
		}
	}
	catch (Exception err) {
		err.printStackTrace();
	}
}
</pre>
</pre>
<p>In this code we use an interface <code>IDataObject</code> that is basically our <code>RowObject</code> code from before. This object has various getter methods for returning column texts, images, fonts and so on.</p>
<p>So how do we go about creating a Nebula Grid based grid with this framework? Mostly it&#8217;s the same way it&#8217;s done with pretty much any SWT widget, along the lines of:</p>
<pre>
<pre class="syntax-highlight:java">
GlazedGridViewer viewer = new GlazedGridViewer(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.VIRTUAL, this, true, null, null, false);
viewer.setAllowMultiColumnSort(true);
viewer.getGrid().setCellSelectionEnabled(true);
</pre>
</pre>
<p>Some pointers: The <code>this</code> parameter is an interface implementation of <code>IGenericGridTable</code> which forces the implementor of the code to include methods for returning a Comparator and a Matcher, like we created before in the previous example. <code>true</code> is the option to create the grid as a plain grid, or to false to create a viewer. The last 3 parameters are a String id used for saving/loading the table state (column order, sizes etc), an <code>IPreferenceStore</code> where it would be saved on, and lastly a <code>true</code>/<code>false</code> whether the table should be saving the state at all.</p>
<p>The framework comes with a default implementation of a Label provider and a Content provider which hooks into the <code>IDataObject</code>. They are created automatically depending on the table type you picked. Column creation is also handled by the framework as the column wrapping implementation allows for individual setting of if a column is sortable, movable, hide-able etc. The API looks like:</p>
<pre>
<pre class="syntax-highlight:java">
public GridViewerColumn(IGlazedGridViewer parentTable, String name, boolean frozen, boolean moveable, boolean sortable, boolean hideable) {
     ...
}
</pre>
</pre>
<p>But when you create a column you do it via the framework as:</p>
<pre>
<pre class="syntax-highlight:java">
GridViewerColumn col = viewer.addColumn(str, false, true, true, true);
col.getGridColumn().setWidth(100);
</pre>
</pre>
<p>And finally, to add objects and set the table input, it&#8217;s again much like the TableViewer, for example:</p>
<pre>
<pre class="syntax-highlight:java">
List&lt;IDataObject&gt; input = new ArrayList&lt;IDataObject&gt;();
for (int i = 0; i &lt; 1000; i++) {
	input.add(new OurIDataObjectClass(i));
}
viewer.setInput(input);
</pre>
</pre>
<p>I don&#8217;t think much more needs to be said about the framework. It has a lot of API in it already and a test class as well. I suggest you download it if you want to give it a go. </p>
<p><strong>Important:</strong> as I currently am not using the framework due to the fact that the Nebula Grid was too slow and memory hungry for what we needed it for (40,000+ rows) I converted the entire framework over to use a NatTable and kept the work going from there. It should be fine, but there may be some minor issues here and there as it was never fully tested. If you find problems and fix them, do send me the code so that everyone can benefit. For the NatTable implementation of the framework, that&#8217;s the next section of this article.</p>
<p>All put together, the test code looks like this when run (with shameless self-promo selection):</p>
<p><img title="Glazed Nebula Grid" src="http://hexapixel.com/wp-content/uploads/2009/01/tv_nebula.gif" alt="tv_nebula" width="681" height="382" /></p>
<p>No filter box in this example, but I think the TableViewer one shows how it works so it&#8217;s not necessary. A point worth making though is that all filters are <code>DataFilter</code> based (framework class). That class extends <code>ViewerFilter</code> so that if you need more than one table implementation, you can re-use your filters should you so wish. That filter also comes with &#8220;whole word&#8221;, &#8220;regular expression&#8221; and &#8220;case sensitive&#8221; filter/search options in the filter itself.</p>
<h4><strong>Download Code</strong></h4>
<p><a href="/files/glazed_nebula_framework.zip">Glazed Lists &#8211; Nebula Grid Framework</a></p>
<h2><strong>Nat Table</strong></h2>
<p>The <a href="http://nattable.org/drupal/" target="_blank">NatTable</a> Widget (Nat stands for Natalie, the girlfriend of the original widget author) is a fairly new Grid widget and one that I personally was quite impressed with after having researched pretty much all SWT grid widgets out there. It&#8217;s still in active development, and not everything is working 100% yet (grouped columns are problematic, some random drawing issues, frozen columns behave oddly, listeners are quite messy), but overall it&#8217;s in a good enough shape that we decided to use it in production. The reason I decided we should use it was simple; We needed a table that could deal with 40,000+ rows in 20+ columns without any lag or any drawing slowdowns whatsoever. It needed to be customizable and I wanted Glazed Lists on it. NatTable is inherently virtual, so you don&#8217;t tell it that it&#8217;s virtual, it just is. It only draws what you see in the viewport which makes redraws near instant and the overall feel is &#8220;snappy&#8221;.</p>
<p>The NatTable API is also quite different from most SWT widgets. Pretty much every part of the table can be extended or implemented in a custom way, and there&#8217;s a lot of classes and places to do this in. At the same time, the API feels sometimes half-finished as simple methods such as <code>selectAll()</code> are nowhere to be found, and trying to figure out how to do it can be a bit of a head-scratcher.  So, It takes a while to wrap your head around the API, but with help from a few examples on their homepage it shouldn&#8217;t be too much of a deal (and most of those kinds of methods are in the framework). The table is model driven, which I suppose is the third type of table model I see used in tables (first being no model and row-item based, second being a viewer on top of a row-item based grid).</p>
<p>All that said, I truly hope the current development team keeps this widget going (and from the looks of it it&#8217;s very active), because it just might be the best SWT grid-table currently out there. The Nebula Grid had huge potential, but development on it is slow going. I know Tom Shindl is doing work on it, but I don&#8217;t know what the roadmap is.</p>
<p>Ok, lets get going with the framework I&#8217;ve built for NatTable. It&#8217;s not complete, just like the Nebula Grid framework which it is based on, but it will get you a very long way. As this framework has gotten further it has more utility methods and automation than it&#8217;s predecessor. It will even mimic the Windows column headers through a custom header drawer if so desired. It also has full color-customization support via interfaces and so on. It would be a long list if I wrote it all here, so I suggest you check out the API.</p>
<p>To create a table using the framework, you can use various constructors, of which the biggest is:</p>
<pre>
<pre class="syntax-highlight:java">
public GlazedNatGridViewer(Composite parent, int style, IGenericNatGridTable generic, String tableId, IPreferenceStore store, boolean allowStateSaving, AbstractGlazedNatVisualConfig config) {
       ...
}
</pre>
</pre>
<p>You will notice the <code>IGenericNatGridTable</code> is the same interface as in the Nebula Grid framework and works the same way (just different name). The last parameter, <code>AbstractGlazedNatVisualConfig</code> is if you want to pass in custom settings for colors, fonts, widths, heights etc. A whole load of things can be customized, or you can stick to the defaults (<code>DefaultGlazedNatVisualConfig</code>).</p>
<p>In our test class we will do the same as we&#8217;ve done in the previous examples, we&#8217;ll create some columns, some row data and do a sort. Using the framework we create a new table as follows:</p>
<pre>
<pre class="syntax-highlight:java">
GlazedNatGridViewer viewer = new GlazedNatGridViewer(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.FULL_SELECTION, this, new DefaultGlazedNatVisualConfig());
viewer.setAllowMultiColumnSort(true);

for (int i = 0; i &lt; 10; i++) {
	NatGridViewerColumn col = viewer.addColumn(&quot;Column &quot;+i, false, true, true, true);
	col.setDefaultWidth(100);
}

List&lt;OneRow&gt; input = new ArrayList&lt;OneRow&gt;();
for (int i = 0; i &lt; 1000; i++) {
	input.add(new OneRow(i));
}

viewer.setInput(input);
</pre>
</pre>
<p>Our <code>OneRow</code> class implements <code>IDataObject</code> which contains getters for all things table related (column text etc). It also contains a getter specifically for returning a value that should be used when comparing column data when sorting. By default we simply return the same column text as the visible-to-user text:</p>
<pre>
<pre class="syntax-highlight:java">
class OneRow implements IDataObject {

	private int _row;

	public OneRow(int row) {
		_row = row;
	}

	@Override
	public String getColumnText(int column) {
		return &quot;&quot;+(_row+column);
	}

	@Override
	public String getSearchMatchText(int column) {
		return getColumnText(column);
	}

	...
}
</pre>
</pre>
<p>The multi column sort feature is already built in, and uses Glazed Lists ability to chain comparators. So whenever you sort more than one column, it will ask for a Comparator for each sorted column, and combine them in the order that you sorted the columns. You multi-sort by holding down the shift key to add more columns, and I&#8217;ve also added so it draws a number on the column header for displaying which order it was sorted in. The sort happens as soon as you let go of the shift key (and you can modify the columns by pressing the shift key again before clicking the column header).</p>
<p>Running the test class we get a table that looks like this:</p>
<p><img title="Glazed Nat Table Viewer" src="http://hexapixel.com/wp-content/uploads/2009/01/tv_nat.gif" alt="Glazed Nat Table Viewer" width="625" height="342" /></p>
<p>That pretty much sums it up for the Nat Table. Regardless of what table implementation you are going with or decide to go with, I&#8217;m sure you will agree that the power and simplicity of Glazed Lists is amazing. And we&#8217;ve only scratched the surface on it here. For much more information and examples with deeper complexity I suggest visiting the homepage and checking the Glazed Lists API. They have some built-in support for SWT as well (such as putting your updates on the UI thread), so they&#8217;re not 100% Swing-based even though most of their pre-implemented table-realted items are for Swing components. </p>
<h4><strong>Download Code</strong></h4>
<p><a href="/files/glazed_nat_framework.zip">Glazed Lists &#8211; Nat Table Framework</a></p>
<h2><strong>Closing words</strong></h2>
<p>This was a long article. It took me 2 full days to write and much longer if you count the hours put into creating both frameworks. My hopes is that you will find the article and Glazed Lists useful in your future table and grid implementations, and that this wonderful package becomes as part of your projects as <a href="http://www.miglayout.com/">MigLayout</a> or other &#8220;must have&#8221; API&#8217;s that make our lives coding UI&#8217;s much easier. Personally I cannot live without Glazed Lists, and I only wish I had found out about them sooner. </p>
<p>And again, I highly recommend the <a href="http://publicobject.com/glazedlistsdeveloper/">screen casts</a> for more information on each type of list you can create.</p>
<p>Do let me know if you spot errors in the article, it&#8217;s hard to cover everything on the first try. I will put these files + a link to this post into the Projects section later as well.</p>
<h2><strong>All Code</strong></h2>
<p>Here are download links to all code referenced in this article:</p>
<div id="bulletlist">
<ol>
<li><a href="/files/posts/TableViewerGlazedExample.java">TableViewer code</a></li>
<li><a href="/files/glazed_nebula_framework.zip">Glazed Lists &#8211; Nebula Grid Framework</a></li>
<li><a href="/files/glazed_nat_framework.zip">Glazed Lists &#8211; Nat Table Framework</a></li>
<li><a href="/files/glazed_nebula_and_nat_frameworks.zip">Glazed Lists &#8211; Both Frameworks Combined</a></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2009/01/02/glazed-lists-swt-tables-true/feed</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Managing Experienced Developers</title>
		<link>http://hexapixel.com/2008/12/29/managing-experienced-developers</link>
		<comments>http://hexapixel.com/2008/12/29/managing-experienced-developers#comments</comments>
		<pubDate>Mon, 29 Dec 2008 18:46:10 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Management]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Project Management]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=322</guid>
		<description><![CDATA[First, the mandatory Dilbert cartoon&#8230; Having worked in many companies over the years there are a few things I know better than my managers, and the longer I&#8217;m in this business the more frustrated I get when things are simply not working the way they should due to bad management. If I as a senior [...]]]></description>
			<content:encoded><![CDATA[<p class="aligncenter">First, the mandatory Dilbert cartoon&#8230;</p>
<p style="text-align: center;"><img class="aligncenter size-full wp-image-345" title="dilbert_managers" src="http://hexapixel.com/wp-content/uploads/2008/12/dilbert_managers.gif" alt="dilbert_managers" width="592" height="213" /></p>
<p>Having worked in many companies over the years there are a few things I know better than my managers, and the longer I&#8217;m in this business the more frustrated I get when things are simply not working the way they should due to bad management. If I as a senior programmer have to step in to do actual project management because my technical project manager fails to do it, something is wrong. Unfortunately this is more common than it should be. A big issue is that managers that are put in charge of development teams are often under-educated when it comes to development and the development process. In fact, they may know nothing about programming at all, and they&#8217;re thrown into a world of developers who can build them anything they request &#8211; assuming upper management has a good plan on what needs to be built.</p>
<p>Why and how these managers end up in a technical management positions is always the question, but any programmer who&#8217;s been around for a while can usually sniff out the bad ones in mere seconds. A good manager is a mediator, someone who knows they may not always know better, but listens to their team, suggests solutions based on what the team has told them and mediates between the dev team and the rest of the company (and upper management). A good manager could be compared to a good army commander. The troops know they can trust them, and will follow them into battle knowing that all decisions are calculated and weighed and probably the best ones. A bad manager however is one who undoubtedly will cause massive team issues and communication breakdown. In the troop scenario the team would undoubtedly get into serious trouble, and if it were a pirate ship, mutiny would soon ensue.</p>
<p>Down the road bad management leads to anger and frustration, and ultimately to the dark side. I&#8217;ve been in many meetings where the programming team starts talking tech issues and the manager sits silently like a question mark watching a tennis match because they have no idea what people are talking about. This is very bad, and a sign of probable project failure down the road (or lots of code re-writes due to miscommunicated features). It&#8217;s OK to not understand <em>everything</em>, but if you manage programmers (especially experienced programmers) you need to be someone who understands the field, and understands it well. A developer who knows that their manager does not understand what they tell them will start communicating less and less, and in the end will probably stop altogether as it does not help them in any way. This leads to a team that is disconnected from management, and undoubtedly a manager who has no clue about the status of the project.</p>
<p>Another issue, seemingly common, is that the product manager (who is literally in charge of the product and the outcome thereof) does not even know what the product is. This usually leads to constant feature changes, and a very angry team. A lot of this can be solved with a good specification early on, but with deadlines looming and budgets shrinking, tech specs are a dying breed.</p>
<p>There was a great thread on Slashdot a few weeks back called &#8220;<a href="http://ask.slashdot.org/article.pl?sid=08%2F12%2F12%2F1947251&amp;from=rss" target="_new">Managing Seasoned Developers</a>&#8221; which is the basis for this post, and despite the random seasoning jokes, there is some really great information in there. As I don&#8217;t expect you to go through that thread to dig out the good stuff, I decided to take the best parts and make a list of &#8220;What a good development team manager should and should not do&#8221;. I also added a few other worthy entries from other places and adjusted some to reflect my own experiences.</p>
<p><span id="more-322"></span><br />
<strong>How to deal with experienced developers as a manager (in random order)</strong>:</p>
<div id="bulletlist">
<ol>
<li>Focus on getting them what they need, staying out of their way, and keeping management related items out of their way. If you want them to manage, make them managers. They can&#8217;t do both at the same time, and if they are forced to do so, they will most likely get quite frustrated and possibly angry.</li>
<li>Professionals typically don&#8217;t enjoy working for someone that doesn&#8217;t give them the respect that they&#8217;ve earned. When this happens your good employees will no longer feel good about the job they are doing and go find a new one. Requiring silly things of your good people is a sure way to see them leave for something better.</li>
<li>Unless your project is 100% exciting to everyone on the team, the answer is, you won&#8217;t be able to manage it without adding some junior programmers. An engineer with 10 years of experience and multiple death marches under his belt will simply find it hard to get excited about the mundane. That&#8217;s not what he&#8217;s there for. He&#8217;s there to take on the big challenges, design stuff that works and implement it in a way that he&#8217;s not embarrassed by it five years from now. If you can&#8217;t accept that, he will surely walk out the door soon.</li>
<li>A company that lacks or literally blocks communication between employees on the same team is not a company worth working for. Communication is the cornerstone of a successful team. A quiet project is as bad as a quiet patch in the forest, you just know something is wrong and &#8220;dead&#8221; around the corner.</li>
<li>Good software engineers enjoy solving tough problems. So present them with the problems you are trying to solve and let them come up with their own solutions. If you don&#8217;t understand the technology, don&#8217;t be afraid or ashamed to ask. Read up on what they&#8217;re proposing. Chances are they are suggesting technology that won&#8217;t come back and bite you in the ass 5 years down the road.</li>
<li>The manager is a domain expert, and can evaluate the product as it is being created. If she can&#8217;t do this, or relies on self-assessment of her reports, the product is going to suck or fail.</li>
<li>Don&#8217;t say that something is undoable if you do not know if it&#8217;s actually doable or not. Ask the developers! They will certainly know if it&#8217;s a possible or impossible task. Not asking them and instead making up things makes you look very dumb.</li>
<li>Chit-chatting and making jokes when you can&#8217;t even manage a project makes you look horrible in the eyes of a good developer. If you can&#8217;t manage them or the team, do you really think they will appreciate that you&#8217;re trying to get on their good side?</li>
<li>The end user of the product is the client, not the project manager. Don&#8217;t expect to know what the client wants without asking them, about everything. There&#8217;s nothing more irritating when a client comes back and says they want it a completely different way, and the engineer has to re-write half the code because you didn&#8217;t ask them beforehand what they wanted.</li>
<li>Never criticize them for something you also fail at. Instead, announce that you&#8217;re looking to improve that aspect in yourself and they&#8217;ll get the message.</li>
<li>When your best engineers have to lead the project because the manager doesn&#8217;t know what they&#8217;re talking about, it&#8217;s time to find someone who can actually manage the project, or send the manager to training so that they can keep up.</li>
<li>If there are issues in the product that are only brought up at the next team meeting, don&#8217;t bring them up unless you have the guts to tell the developer(s) with enough time beforehand so they have time to look at those issues and possibly fix them instead of hearing them as &#8220;issues&#8221;. If they&#8217;re big issues, bring them up right away. If they&#8217;re small issues, make a list and go over it with the developers.</li>
<li>Be open to criticism and be willing to change course in response to it.</li>
<li>The best developers need a set of requirements, a deadline, a good working environment and caffeinated drinks. Not much more. They will deliver.</li>
<li>There&#8217;s nothing better than a good developer who can design, code, document and communicate, and does not need constant supervision. On the other hand, there&#8217;s nothing worse than one that pretends to do those things and turns out to be a disaster for the project. If there are employees who fall into the latter category on more than one occasion, it&#8217;s probably time to reconsider their placement or job.</li>
<li>Managers are not programmers just like programmers are not managers. It doesn&#8217;t matter if you programmed in the past, you&#8217;re a manager, get used to it. So please do not embarrass your team by trying to make code changes or additions. Leave it to them. They will do it in 1/10th of the time and with 1/10th of the bugs.</li>
<li>Use technologies (bugtracking etc) that are easy to use and easy to update. Overly complicated and complex software to do &#8220;simple tasks&#8221; will do nothing but slow down the entire development process. This is especially true for complex version-control software.</li>
<li>Feedback feedback feedback. Don&#8217;t overdo it on the pats on the back, but for the love of god, don&#8217;t forget them. If an engineer goes above and beyond, they expect to be treated like it and respected.</li>
<li>Think &#8220;How would I like to be treated?&#8221;. The answer is most likely &#8220;With respect, open communication, acknowledgment of work done, incentive for above and beyond&#8230;&#8221;. Get to learn who they are.</li>
<li>If you&#8217;re part of a bigger team (10+) and rarely or never show up at team meetings, don&#8217;t expect that any of your words will mean much to the team. They know you&#8217;re not there, and you&#8217;re letting the team down. Coming along later and saying &#8220;great job!&#8221; is a slap in the face and viewed as you getting all the credit for their hard work. Never do this.</li>
<li>To a seasoned programmer, you as a manager are redundant unless you can prove otherwise. If you fail at your task, they will work around you and go above your head with all matters until they get heard. This will come back to bite you sooner or later.</li>
<li>When experienced programmers learn that other lesser-individuals earn more than them (they will), either deal with it swiftly or watch them walk out the door. Salaries, just like interesting projects, are extremely important. A &#8220;very good&#8221; programmer expects to be paid &#8220;very well&#8221;, as he or she is most likely pulling more than their own weight on all the projects they are involved with.</li>
<li>Claiming your best programmers have to be at work on certain dates and plan their vacations long times in advance because of risk of &#8220;failure&#8221; means you need more good people on your team. Everyone needs vacation, it&#8217;s what makes us come back to work harder. Work them to death or set limitations and you will only increase their stress level.</li>
<li>Every time you interrupt someone in the middle of their task, you probably wasted 10 minutes more for them to get back &#8220;into it&#8221;.</li>
<li>Good developers can multitask like a quad-core processor. If you think they&#8217;re not working because they&#8217;re browsing a website not work-related, be careful before you judge. They&#8217;re most likely taking a 1 minute brain pause, compiling in the background, or upgrading the kernel with their left hand. Let them continue, because those small pauses may be all they get while their brains work overtime.</li>
<li>Follow and adjust to <a href="http://www.codinghorror.com/blog/archives/000666.html" target="_new">The Programmer&#8217;s Bill of Rights</a>. Nothing else needs to be said about this, it speaks for itself.</li>
</ol>
</div>
<p>It&#8217;s also worth mentioning that managers need to be told some of these things (their weak spots), so don&#8217;t be afraid to put your foot down, it just might make them better!</p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2008/12/29/managing-experienced-developers/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

