<?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</title>
	<atom:link href="http://hexapixel.com/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-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.2</generator>
		<item>
		<title>Still no news!</title>
		<link>http://hexapixel.com/2011/09/06/still-no-news</link>
		<comments>http://hexapixel.com/2011/09/06/still-no-news#comments</comments>
		<pubDate>Tue, 06 Sep 2011 13:21:35 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Site Related]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=876</guid>
		<description><![CDATA[I&#8217;m still here, but I&#8217;m still swamped with a thousand projects, so both bugfixing and other stuff has suffered. I&#8217;m trying to catch up but I&#8217;m making no promises right now (such is life in open source). If there&#8217;s an urgent bug that you reported that I missed responding to, feel free to ping me [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m still here, but I&#8217;m still swamped with a thousand projects, so both bugfixing and other stuff has suffered. I&#8217;m trying to catch up but I&#8217;m making no promises right now (such is life in open source). If there&#8217;s an urgent bug that you reported that I missed responding to, feel free to ping me and I&#8217;ll try to take a look. New features will have to come later! </p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2011/09/06/still-no-news/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Various Tidbits</title>
		<link>http://hexapixel.com/2010/11/10/various-tidbits</link>
		<comments>http://hexapixel.com/2010/11/10/various-tidbits#comments</comments>
		<pubDate>Wed, 10 Nov 2010 03:12:01 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Site Related]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=868</guid>
		<description><![CDATA[I know it&#8217;s been ages since any updates, but I have not had much time to write long articles between work and other projects. I&#8217;m also still rather stuck in the world of Silverlight, which is a whole different story. Microsoft is doing funny things there as well, it might not even survive beyond a [...]]]></description>
			<content:encoded><![CDATA[<p>I know it&#8217;s been ages since any updates, but I have not had much time to write long articles between work and other projects. I&#8217;m also still rather stuck in the world of Silverlight, which is a whole different story. Microsoft is doing funny things there as well, it might not even survive beyond a mobile platform.</p>
<p>It&#8217;s worth mentioning however, that the <a href="/software/ganttwidget">GanttChart</a> has had quite a few bug fixes lately as well as improvements (new features) so if you&#8217;re a user of that it may be worth testing the latest nightly build and see if it makes life better on your end. I know there&#8217;s requests for Millisecond and Second &#8220;zoom views&#8221; but apart from some sketchy code that isn&#8217;t working as I want it, it hasn&#8217;t made it into any release yet, but it&#8217;s on the big TODO list and a priority.</p>
<p>Also, the Eclipse Nebula project &#8220;build system&#8221; has been broken for quite a while, so if you want the latest code (as always), use CVS or grab it from the <a href="/software/nightly-builds">nightly builds</a> section on this site.</p>
<p>I&#8217;m hoping I&#8217;ll find time for some new articles going forward.</p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2010/11/10/various-tidbits/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>Server Move</title>
		<link>http://hexapixel.com/2009/09/16/server-move</link>
		<comments>http://hexapixel.com/2009/09/16/server-move#comments</comments>
		<pubDate>Wed, 16 Sep 2009 11:37:26 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Site Related]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=788</guid>
		<description><![CDATA[The Hexapixel.com server is moving to a new data center. Hopefully downtime should be minimal but it&#8217;s possible DNS propagation can take a little longer for some people (depending on ISP). The move is taking place over the next week. The lack of recent articles is due to being completely swamped. I&#8217;m hoping to find [...]]]></description>
			<content:encoded><![CDATA[<p>The Hexapixel.com server is moving to a new data center. Hopefully downtime should be minimal but it&#8217;s possible DNS propagation can take a little longer for some people (depending on ISP). The move is taking place over the next week. </p>
<p>The lack of recent articles is due to being completely swamped. I&#8217;m hoping to find some time to write a few more soon!</p>
<p>Also, a new version of the Source Helper should arrive soon, with Eclipse 3.5 support and a whole lot of fixes.</p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2009/09/16/server-move/feed</wfw:commentRss>
		<slash:comments>2</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>
<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>
<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>
<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>
<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>28</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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>
<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>Java Source Helper 0.2.4</title>
		<link>http://hexapixel.com/2009/05/09/javasourcehelper-024</link>
		<comments>http://hexapixel.com/2009/05/09/javasourcehelper-024#comments</comments>
		<pubDate>Sat, 09 May 2009 15:26:16 +0000</pubDate>
		<dc:creator>Emil</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[sourcehelper]]></category>

		<guid isPermaLink="false">http://hexapixel.com/?p=677</guid>
		<description><![CDATA[I&#8217;ve released a new version of the JavaSourceHelper, 0.2.4, which fixes the following: Brackets inside comments are no longer mistaken for “matching” brackets If the starting bracket and end bracket were not in the same location, the connecting line would draw funny, now it draws a bend Preferences page moved to under Java then “Java [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve released a new version of the JavaSourceHelper, 0.2.4, which fixes the following:</p>
<ol>
<li>Brackets inside comments are no longer mistaken for “matching” brackets</li>
<li>If the starting bracket and end bracket were not in the same location, the connecting line would draw funny, now it draws a bend</li>
<li>Preferences page moved to under Java then “Java Editor”. Search for helper if you can’t find it in the Preferences dialog.</li>
</ol>
<p>Here&#8217;s a picture of the &#8220;fixed&#8221; line drawing:</p>
<p><img src="http://hexapixel.com/wp-content/uploads/2009/05/improved_line.gif" alt="Improved Line Drawing" title="" width="604" height="130" /></p>
<p>You can update via the update site or download and install/update manually. For more info go to <a href="/projects/sourcehelper">the java source helper page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://hexapixel.com/2009/05/09/javasourcehelper-024/feed</wfw:commentRss>
		<slash:comments>3</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>
<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>
<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>
<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>
	</channel>
</rss>
