<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8892828254544321690</id><updated>2011-09-02T10:57:34.825-07:00</updated><category term='Swing'/><category term='SwingX'/><category term='GIS'/><category term='taskboard'/><category term='jquery'/><category term='couchdb'/><category term='KML'/><category term='Google Earth'/><category term='Jetty'/><category term='scrum'/><category term='VLDocking'/><category term='Substance'/><category term='javascript'/><category term='JXTable'/><category term='kanban'/><category term='GPS'/><category term='JHLabs'/><category term='Java'/><category term='OpenMap'/><category term='JavaFX'/><title type='text'>Carstens blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>12</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-7575236724149432321</id><published>2011-08-03T13:48:00.000-07:00</published><updated>2011-08-05T08:21:34.822-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='kanban'/><category scheme='http://www.blogger.com/atom/ns#' term='jquery'/><category scheme='http://www.blogger.com/atom/ns#' term='couchdb'/><category scheme='http://www.blogger.com/atom/ns#' term='taskboard'/><category scheme='http://www.blogger.com/atom/ns#' term='scrum'/><title type='text'>CouchBoard - Porting a ROR/JQuery application to CouchDB/JQuery</title><content type='html'>&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-12LpzIwcOxA/Tjm9CubPHJI/AAAAAAAAA0o/I0ITSvtfzfI/s1600/taskboard.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 347px; height: 400px;" src="http://1.bp.blogspot.com/-12LpzIwcOxA/Tjm9CubPHJI/AAAAAAAAA0o/I0ITSvtfzfI/s400/taskboard.png" alt="" id="BLOGGER_PHOTO_ID_5636744263150541970" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Looking for a replacement for our small company &lt;a href="https://scrumy.com/"&gt;Scrummy&lt;/a&gt; taskboard I stumbled over &lt;a href="https://github.com/CognifideLabs/taskboard"&gt;CognifidesLabs Taskboard&lt;/a&gt; Ruby On Rails (&lt;a href="http://rubyonrails.org/"&gt;ROR&lt;/a&gt;) application. It looked useful but it seemed stale and being a complete ROR imbecile and a JavaScript novice I initially gave up as the entry threshold just seemed to big.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-xCXtRDbO5Fg/Tjv-rKDfNnI/AAAAAAAAA1A/pDAVgiARw4E/s1600/taskboard1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 347px; height: 400px;" src="http://1.bp.blogspot.com/-xCXtRDbO5Fg/Tjv-rKDfNnI/AAAAAAAAA1A/pDAVgiARw4E/s400/taskboard1.png" alt="" id="BLOGGER_PHOTO_ID_5637379375971120754" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;But after fooling around with &lt;a href="http://couchdb.apache.org/"&gt;CouchDB&lt;/a&gt; in another context I realized that maybe I could scrap the entire ROR backend as the data exchange format was JSON and just port the http requests to the ROR backend to CouchDB JavaScript.&lt;br /&gt;&lt;br /&gt;At first this seemed as a daunting task as most tutorials etc. for doing CouchDB application development uses &lt;a href="http://couchapp.org/"&gt;couchapp&lt;/a&gt; so even a simple task as figuring out how to port the login logic was hard. Eventually I found &lt;a href="https://github.com/amysue/couchdb-login-jquery"&gt;couchdb-login-jquery&lt;/a&gt; and from there on the porting job was as easy a calling the  CouchDB JavaScript CRUD  &lt;a href="https://github.com/lenalena/couchdb-http-api-docs/blob/master/couch_js_document_methods.markdown"&gt;functions&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The ROR back end is approximately 1700 lines of Ruby code this was exchanged for an additional 200 lines of JavaScript. For somebody used to setting up Eclipse, Maven, Tomcat, Spring, Spring Security, PostgreSQL just to get started it seems unreal to just use a text editor,  &lt;a href="http://code.google.com/p/reupholster/downloads/list"&gt;reupholster&lt;/a&gt; and Firefox/Firebug for the entire developmet process.&lt;br /&gt;&lt;br /&gt;On top of this all that is needed to host the application is a free account at &lt;a href="https://cloudant.com/"&gt;cloudant&lt;/a&gt; where you get a scalable, fault-tolerant, distributed database to host your applications in.&lt;br /&gt;&lt;br /&gt;In summary porting the ROR backend to pure CouchDB/JavaScript was surprisingly easy. The most diffuclt part was acctual to understand the CouchDB security model and then learn that the cloudant (BigCouch) model was incompatible.&lt;br /&gt;&lt;br /&gt;In case you need a small and simple to manage scrum/kanban board you can get the code from &lt;a href="https://github.com/cmadsen/couch-board"&gt;here&lt;/a&gt; and you can test the application &lt;a href="https://cmadsen.cloudant.com/couch-board/_design/app/login.html"&gt;here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-7575236724149432321?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/7575236724149432321/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=7575236724149432321' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/7575236724149432321'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/7575236724149432321'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2011/08/couchboard-porting-rorjquery.html' title='CouchBoard - Porting a ROR/JQuery application to CouchDB/JQuery'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-12LpzIwcOxA/Tjm9CubPHJI/AAAAAAAAA0o/I0ITSvtfzfI/s72-c/taskboard.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-8321713052606868606</id><published>2010-10-15T00:09:00.000-07:00</published><updated>2011-08-01T04:14:31.939-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='GIS'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenMap'/><title type='text'>Preliminary GRIB rendering for OpenMap</title><content type='html'>I have managed to render &lt;a href="http://en.wikipedia.org/wiki/GRIB"&gt;GRIB&lt;/a&gt; weather data in a OpenMap layer. It should support GRIB data from a numbers of free sources like NOAA.&lt;br /&gt;&lt;br /&gt;Looks pretty cool with the isobars, wind arrows and a wind heat map.&lt;br /&gt;&lt;br /&gt;The images below are showing a storm front (&lt;a href="http://en.wikipedia.org/wiki/Xynthia_%28storm%29"&gt;Xynthia&lt;/a&gt;) hitting Western Europe.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-GkSUELlxKjo/TjZz-oK0hfI/AAAAAAAAAzg/35mhwwh_NUQ/s1600/grib9.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://3.bp.blogspot.com/-GkSUELlxKjo/TjZz-oK0hfI/AAAAAAAAAzg/35mhwwh_NUQ/s400/grib9.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635819503472641522" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-Lrw98teZmjQ/TjZz-WSMA2I/AAAAAAAAAzY/P_jTLbUPbL8/s1600/grib8.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://2.bp.blogspot.com/-Lrw98teZmjQ/TjZz-WSMA2I/AAAAAAAAAzY/P_jTLbUPbL8/s400/grib8.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635819498671702882" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-YtQfNhtZeaE/TjZz-JeFRJI/AAAAAAAAAzQ/KG7kgVu_XCc/s1600/grib7.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://2.bp.blogspot.com/-YtQfNhtZeaE/TjZz-JeFRJI/AAAAAAAAAzQ/KG7kgVu_XCc/s400/grib7.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635819495231931538" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/-vC0x3W82wH4/TjZz93aTskI/AAAAAAAAAzI/taVzTzcEi6A/s1600/grib6.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://3.bp.blogspot.com/-vC0x3W82wH4/TjZz93aTskI/AAAAAAAAAzI/taVzTzcEi6A/s400/grib6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635819490384261698" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-IXZy0Z0PkV8/TjZz-_J0R-I/AAAAAAAAAzo/x4thHVxA7nA/s1600/grib10.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://4.bp.blogspot.com/-IXZy0Z0PkV8/TjZz-_J0R-I/AAAAAAAAAzo/x4thHVxA7nA/s400/grib10.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635819509642446818" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-UBBaghMt-jM/TjZzuaH3aLI/AAAAAAAAAy4/dKGlwonEGIA/s1600/grib4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://1.bp.blogspot.com/-UBBaghMt-jM/TjZzuaH3aLI/AAAAAAAAAy4/dKGlwonEGIA/s400/grib4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635819224824244402" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/-vdCBk9Ntjio/TjZzuLUpkaI/AAAAAAAAAyw/S-56EJZ90cY/s1600/grib3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://2.bp.blogspot.com/-vdCBk9Ntjio/TjZzuLUpkaI/AAAAAAAAAyw/S-56EJZ90cY/s400/grib3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635819220851331490" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-HTLml-WEjIA/TjZzt_0gIAI/AAAAAAAAAyo/lWQPL7000yc/s1600/grib2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://4.bp.blogspot.com/-HTLml-WEjIA/TjZzt_0gIAI/AAAAAAAAAyo/lWQPL7000yc/s400/grib2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635819217763704834" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/-LXASfRpEH_I/TjZzt1Fg_BI/AAAAAAAAAyg/ps2nA2Ldup4/s1600/grib1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 312px;" src="http://4.bp.blogspot.com/-LXASfRpEH_I/TjZzt1Fg_BI/AAAAAAAAAyg/ps2nA2Ldup4/s400/grib1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635819214882274322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/-RsHQPtfnJZI/TjZzugVudxI/AAAAAAAAAzA/9QHPnDNsmC4/s1600/grib5.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 357px;" src="http://1.bp.blogspot.com/-RsHQPtfnJZI/TjZzugVudxI/AAAAAAAAAzA/9QHPnDNsmC4/s400/grib5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5635819226492991250" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_7ROeMUNozjM/TLf-rb5bwFI/AAAAAAAAAwc/RKZNhbwYd2k/s1600/grib.png"&gt;&lt;img style="cursor: pointer; width: 372px; height: 400px;" src="http://2.bp.blogspot.com/_7ROeMUNozjM/TLf-rb5bwFI/AAAAAAAAAwc/RKZNhbwYd2k/s400/grib.png" alt="" id="BLOGGER_PHOTO_ID_5528167089797054546" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Comments are welcome!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-8321713052606868606?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/8321713052606868606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=8321713052606868606' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/8321713052606868606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/8321713052606868606'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2010/10/prelimiary-grib-rendering-for-openmap.html' title='Preliminary GRIB rendering for OpenMap'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-GkSUELlxKjo/TjZz-oK0hfI/AAAAAAAAAzg/35mhwwh_NUQ/s72-c/grib9.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-240046756095933597</id><published>2010-08-18T23:21:00.000-07:00</published><updated>2010-08-19T00:30:06.466-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenMap'/><title type='text'>Geonames location searcher for OpenMap</title><content type='html'>Here is an integration of &lt;a href=http://openmap.bbn.com&gt;openmap&lt;/a&gt; with geonames that will add a combobox that can be used to search &lt;a href="http://geonames.org"&gt;geonames.org&lt;/a&gt; to the toolbar by adding the following to your openmap.properties file:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;openmap.components=... geonamessearcher&lt;br /&gt;geonamessearcher.class=GeoNamesSearcher&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here is the code&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;import java.awt.event.ActionEvent;&lt;br /&gt;import java.awt.event.ActionListener;&lt;br /&gt;&lt;br /&gt;import javax.swing.DefaultComboBoxModel;&lt;br /&gt;import javax.swing.DefaultListCellRenderer;&lt;br /&gt;import javax.swing.JComboBox;&lt;br /&gt;import javax.swing.JComponent;&lt;br /&gt;import javax.swing.JList;&lt;br /&gt;import javax.swing.plaf.basic.BasicComboBoxEditor;&lt;br /&gt;&lt;br /&gt;import net.miginfocom.swing.MigLayout;&lt;br /&gt;&lt;br /&gt;import org.apache.log4j.Logger;&lt;br /&gt;import org.geonames.Toponym;&lt;br /&gt;import org.geonames.ToponymSearchCriteria;&lt;br /&gt;import org.geonames.ToponymSearchResult;&lt;br /&gt;import org.geonames.WebService;&lt;br /&gt;&lt;br /&gt;import com.bbn.openmap.event.CenterListener;&lt;br /&gt;import com.bbn.openmap.event.CenterSupport;&lt;br /&gt;import com.bbn.openmap.gui.OMToolComponent;&lt;br /&gt;&lt;br /&gt;public class GeoNamesSearcher extends OMToolComponent {&lt;br /&gt;&lt;br /&gt; private static final Logger log = Logger.getLogger(GeoNamesSearcher.class&lt;br /&gt;   .getName());&lt;br /&gt;&lt;br /&gt; private JComboBox searchBox;&lt;br /&gt;&lt;br /&gt; private CenterSupport centerDelegate;&lt;br /&gt;&lt;br /&gt; private DefaultComboBoxModel searchBoxModel = new DefaultComboBoxModel();&lt;br /&gt;&lt;br /&gt; public GeoNamesSearcher() {&lt;br /&gt;  centerDelegate = new CenterSupport(this);&lt;br /&gt;  setLayout(new MigLayout());&lt;br /&gt;  searchBox = new JComboBox(searchBoxModel);&lt;br /&gt;  searchBox.setEditable(true);&lt;br /&gt;  searchBox.setMaximumRowCount(25);&lt;br /&gt;  searchBox&lt;br /&gt;    .setToolTipText("Enter part of location to search for (and center to).");&lt;br /&gt;  searchBox.setRenderer(new DefaultListCellRenderer() {&lt;br /&gt;   @Override&lt;br /&gt;   public JComponent getListCellRendererComponent(JList list,&lt;br /&gt;     Object value, int index, boolean isSelected,&lt;br /&gt;     boolean cellHasFocus) {&lt;br /&gt;    super.getListCellRendererComponent(list, value, index,&lt;br /&gt;      isSelected, cellHasFocus);&lt;br /&gt;    if (value instanceof Toponym) {&lt;br /&gt;     Toponym toponym = (Toponym) value;&lt;br /&gt;     setText(toponym.getName() + " " + toponym.getCountryCode());&lt;br /&gt;    }&lt;br /&gt;    return this;&lt;br /&gt;   }&lt;br /&gt;  });&lt;br /&gt;  searchBox.setEditor(new BasicComboBoxEditor() {&lt;br /&gt;   @Override&lt;br /&gt;   public void setItem(Object anObject) {&lt;br /&gt;    if (anObject != null) {&lt;br /&gt;     if (anObject instanceof Toponym) {&lt;br /&gt;      Toponym toponym = (Toponym) anObject;&lt;br /&gt;      editor.setText(toponym.getName() + " "&lt;br /&gt;        + toponym.getCountryCode());&lt;br /&gt;      // oldValue = anObject;&lt;br /&gt;     } else {&lt;br /&gt;      super.setItem(anObject);&lt;br /&gt;     }&lt;br /&gt;    } else {&lt;br /&gt;     editor.setText("");&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  });&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  searchBox.addActionListener(new ActionListener() {&lt;br /&gt;   @Override&lt;br /&gt;   public void actionPerformed(ActionEvent evt) {&lt;br /&gt;    JComboBox cb = (JComboBox) evt.getSource();&lt;br /&gt;&lt;br /&gt;    Object selectedItem = cb.getSelectedItem();&lt;br /&gt;&lt;br /&gt;    if ("comboBoxEdited".equals(evt.getActionCommand())) {&lt;br /&gt;     // User has typed in a string; only possible with an&lt;br /&gt;     // editable combobox&lt;br /&gt;     try {&lt;br /&gt;      searchBoxModel.removeAllElements();&lt;br /&gt;      ToponymSearchCriteria searchCriteria = new ToponymSearchCriteria();&lt;br /&gt;      // searchCriteria.setCountryCode("DK");&lt;br /&gt;      searchCriteria.setQ((String) selectedItem);&lt;br /&gt;      ToponymSearchResult searchResult = WebService&lt;br /&gt;        .search(searchCriteria);&lt;br /&gt;      for (Toponym toponym : searchResult.getToponyms()) {&lt;br /&gt;       searchBoxModel.addElement(toponym);&lt;br /&gt;      }&lt;br /&gt;      if (searchResult.getTotalResultsCount() == 1) {&lt;br /&gt;       Toponym t = searchResult.getToponyms().get(0);&lt;br /&gt;       centerDelegate.fireCenter(t.getLatitude(), t&lt;br /&gt;         .getLongitude());&lt;br /&gt;      } else if (searchResult.getTotalResultsCount() &gt; 1) {&lt;br /&gt;       searchBox.showPopup();&lt;br /&gt;      }&lt;br /&gt;     } catch (Exception e) {&lt;br /&gt;      log.error("", e);&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;    } else if ("comboBoxChanged".equals(evt.getActionCommand())) {&lt;br /&gt;     // User has selected an item; it may be the same item&lt;br /&gt;     if (cb.getSelectedItem() instanceof Toponym) {&lt;br /&gt;      Toponym newItem = (Toponym) cb.getSelectedItem();&lt;br /&gt;      centerDelegate.fireCenter(newItem.getLatitude(),&lt;br /&gt;        newItem.getLongitude());&lt;br /&gt;     }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;   }&lt;br /&gt;  });&lt;br /&gt;  add(searchBox);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public synchronized void addCenterListener(CenterListener listener) {&lt;br /&gt;  centerDelegate.add(listener);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; /**&lt;br /&gt;  * Remove a CenterListener&lt;br /&gt;  *&lt;br /&gt;  * @param listener&lt;br /&gt;  *            CenterListener&lt;br /&gt;  */&lt;br /&gt; public synchronized void removeCenterListener(CenterListener listener) {&lt;br /&gt;  centerDelegate.remove(listener);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public void findAndInit(Object obj) {&lt;br /&gt;  if (obj instanceof CenterListener) {&lt;br /&gt;   addCenterListener((CenterListener) obj);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public void findAndUndo(Object obj) {&lt;br /&gt;  if (obj instanceof CenterListener) {&lt;br /&gt;   removeCenterListener((CenterListener) obj);&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-240046756095933597?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/240046756095933597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=240046756095933597' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/240046756095933597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/240046756095933597'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2010/08/geonames-location-searcher-for-openmap.html' title='Geonames location searcher for OpenMap'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-5826173775726447634</id><published>2009-09-23T04:21:00.000-07:00</published><updated>2009-09-23T06:26:58.348-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JavaFX'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><title type='text'>Using JavaFX Classes Directly From Java</title><content type='html'>Sitting on the Swing side of the fence the grass on the JavaFX side certainly sometimes seems a lot greener. &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_7ROeMUNozjM/SroJ8LXpj9I/AAAAAAAAAu4/CNLMceZqZC0/s1600-h/fxclock.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 295px; height: 325px;" src="http://2.bp.blogspot.com/_7ROeMUNozjM/SroJ8LXpj9I/AAAAAAAAAu4/CNLMceZqZC0/s400/fxclock.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5384627233923633106" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Knowing that the latest and greatest &lt;a href="https://scenegraph.dev.java.net/"&gt;scene graph&lt;/a&gt; code is available somewhere in the pile of JavaFX jars it is tempting to try and get access to it from the Swing side without being "bothered" with the JavaFX language. &lt;br /&gt;&lt;br /&gt;Other people like Matt Hicks have had the same thoughts (see &lt;a href="http://www.matthicks.com/2009/02/i-hate-javafx-i-love-javafx.html"&gt;I Hate JavaFX; I Love JavaFX!&lt;/a&gt;) so I started out with trying Matt's port of the &lt;a href="http://java.sun.com/javafx/1/tutorials/build-javafx-nb-app/"&gt;JavaFX Clock&lt;/a&gt; and after some fiddling I got it up and running with JavaFX 1.2. Try it by pushing the launch button below.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;script src="http://java.com/js/deployJava.js"&gt;&lt;/script&gt;&lt;script&gt;var url = "http://www.navicon.dk/com/fxclock.jnlp";deployJava.createWebStartLaunchButton(url, '+1.6.0');&lt;/script&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;The code follows (add all the JavaFX SDK jars to your classpath before trying this):&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;/**&lt;br /&gt; * @author Matt Hicks (matt@matthicks.com)&lt;br /&gt; */&lt;br /&gt;public class Clock {&lt;br /&gt; private float radius = 77;&lt;br /&gt; private float centerX = 144;&lt;br /&gt; private float centerY = 144;&lt;br /&gt; private Calendar calendar = Calendar.getInstance();&lt;br /&gt; private int hours;&lt;br /&gt; private int minutes;&lt;br /&gt; private int seconds;&lt;br /&gt;&lt;br /&gt; private FloatVariable hoursVariable;&lt;br /&gt; private FloatVariable minutesVariable;&lt;br /&gt; private FloatVariable secondsVariable;&lt;br /&gt;&lt;br /&gt; public Clock() throws IOException {&lt;br /&gt;  nextTick();&lt;br /&gt;&lt;br /&gt;  // Build JavaFX clock&lt;br /&gt;  Group group = new Group();&lt;br /&gt;  {&lt;br /&gt;   ImageView imageView = new ImageView();&lt;br /&gt;   Image image = new Image();&lt;br /&gt;   // should be image.set$url() but does not work ?&lt;br /&gt;   image.loc$platformImage().set(&lt;br /&gt;     ImageIO.read(getClass().getClassLoader().getResource(&lt;br /&gt;       "clock_background.png")));&lt;br /&gt;   imageView.set$image(image);&lt;br /&gt;   group.loc$content().insert(imageView);&lt;br /&gt;&lt;br /&gt;   Group face = new Group();&lt;br /&gt;   {&lt;br /&gt;    Translate translate = new Translate();&lt;br /&gt;    translate.set$x(centerX);&lt;br /&gt;    translate.set$y(centerY);&lt;br /&gt;    face.loc$transforms.insert(translate);&lt;br /&gt;&lt;br /&gt;    // Every third hour&lt;br /&gt;    for (int i = 3; i &lt;= 12; i += 3) {&lt;br /&gt;     Text text = new Text();&lt;br /&gt;     translate = new Translate();&lt;br /&gt;     translate.set$x(-5.0f);&lt;br /&gt;     translate.set$y(5.0f);&lt;br /&gt;     text.loc$transforms.insert(translate);&lt;br /&gt;     text.set$font(Font.font("Arial", 16));&lt;br /&gt;     text.set$x(radius * ((i + 0) % 2 * (2 - i / 3)));&lt;br /&gt;     text.set$y(radius * ((i + 1) % 2 * (3 - i / 3)));&lt;br /&gt;     text.set$content(String.valueOf(i));&lt;br /&gt;     face.loc$content.insert(text);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Black circle for the rest of the hours&lt;br /&gt;    for (int i = 1; i &lt; 12; i++) {&lt;br /&gt;     if (i % 3 == 0) {&lt;br /&gt;      continue; // Don't show a circle on every third hour&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     Circle circle = new Circle();&lt;br /&gt;     Rotate rotate = new Rotate();&lt;br /&gt;     rotate.set$angle(30.0f * i);&lt;br /&gt;     circle.loc$transforms.insert(rotate);&lt;br /&gt;     circle.set$centerX(radius);&lt;br /&gt;     circle.set$radius(3.0f);&lt;br /&gt;     circle.set$fill(Color.$BLACK);&lt;br /&gt;     face.loc$content.insert(circle);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Center circles&lt;br /&gt;    Circle circle = new Circle();&lt;br /&gt;    circle.set$radius(5.0f);&lt;br /&gt;    circle.set$fill(Color.$DARKRED);&lt;br /&gt;&lt;br /&gt;    face.loc$content.insert(circle);&lt;br /&gt;    circle = new Circle();&lt;br /&gt;    circle.set$radius(3.0f);&lt;br /&gt;    circle.set$fill(Color.$RED);&lt;br /&gt;    face.loc$content.insert(circle);&lt;br /&gt;&lt;br /&gt;    // Second hand&lt;br /&gt;    Line line = new Line();&lt;br /&gt;    {&lt;br /&gt;     Rotate rotate = new Rotate();&lt;br /&gt;     BindingExpression exp = new AbstractBindingExpression() {&lt;br /&gt;      @Override&lt;br /&gt;      public void compute() {&lt;br /&gt;       pushValue(seconds * 6f);&lt;br /&gt;      }&lt;br /&gt;     };&lt;br /&gt;     secondsVariable = FloatVariable.make(exp);&lt;br /&gt;     rotate.loc$angle().bind(false, secondsVariable);&lt;br /&gt;&lt;br /&gt;     line.loc$transforms.insert(rotate);&lt;br /&gt;&lt;br /&gt;     line.set$endY(-radius - 3.0f);&lt;br /&gt;     line.set$strokeWidth(2.0f);&lt;br /&gt;     line.set$stroke(Color.$RED);&lt;br /&gt;    }&lt;br /&gt;    face.loc$content.insert(line);&lt;br /&gt;&lt;br /&gt;    // Hour hand&lt;br /&gt;    Path path = new Path();&lt;br /&gt;    {&lt;br /&gt;     Rotate rotate = new Rotate();&lt;br /&gt;     BindingExpression exp = new AbstractBindingExpression() {&lt;br /&gt;      @Override&lt;br /&gt;      public void compute() {&lt;br /&gt;       pushValue((float) (hours + minutes / 60) * 30 - 90);&lt;br /&gt;      }&lt;br /&gt;     };&lt;br /&gt;&lt;br /&gt;     hoursVariable = FloatVariable.make(exp);&lt;br /&gt;     rotate.loc$angle().bind(false, hoursVariable);&lt;br /&gt;     path.loc$transforms.insert(rotate);&lt;br /&gt;&lt;br /&gt;     path.set$fill(Color.$BLACK);&lt;br /&gt;&lt;br /&gt;     MoveTo e1 = new MoveTo();&lt;br /&gt;     e1.set$x(4.0f);&lt;br /&gt;     e1.set$y(4.0f);&lt;br /&gt;     path.loc$elements.insert(e1);&lt;br /&gt;     ArcTo e2 = new ArcTo();&lt;br /&gt;     e2.set$x(4.0f);&lt;br /&gt;     e2.set$y(-4.0f);&lt;br /&gt;     e2.set$radiusX(1.0f);&lt;br /&gt;     e2.set$radiusY(1.0f);&lt;br /&gt;     path.loc$elements.insert(e2);&lt;br /&gt;     LineTo e3 = new LineTo();&lt;br /&gt;     e3.set$x(radius - 15.0f);&lt;br /&gt;     e3.set$y(0.0f);&lt;br /&gt;     path.loc$elements.insert(e3);&lt;br /&gt;    }&lt;br /&gt;    face.loc$content.insert(path);&lt;br /&gt;&lt;br /&gt;    // Minute hand&lt;br /&gt;    path = new Path();&lt;br /&gt;    {&lt;br /&gt;     Rotate rotate = new Rotate();&lt;br /&gt;     BindingExpression exp = new AbstractBindingExpression() {&lt;br /&gt;      public void compute() {&lt;br /&gt;       pushValue((float) minutes * 6 - 90);&lt;br /&gt;      }&lt;br /&gt;     };&lt;br /&gt;     minutesVariable = FloatVariable.make(exp);&lt;br /&gt;     rotate.loc$angle().bind(false, minutesVariable);&lt;br /&gt;&lt;br /&gt;     path.loc$transforms.insert(rotate);&lt;br /&gt;     path.set$fill(Color.$BLACK);&lt;br /&gt;&lt;br /&gt;     MoveTo e1 = new MoveTo();&lt;br /&gt;     e1.set$x(4.0f);&lt;br /&gt;     e1.set$y(4.0f);&lt;br /&gt;     path.loc$elements.insert(e1);&lt;br /&gt;     ArcTo e2 = new ArcTo();&lt;br /&gt;     e2.set$x(4.0f);&lt;br /&gt;     e2.set$y(-4.0f);&lt;br /&gt;     e2.set$radiusX(1.0f);&lt;br /&gt;     e2.set$radiusY(1.0f);&lt;br /&gt;     path.loc$elements.insert(e2);&lt;br /&gt;     LineTo e3 = new LineTo();&lt;br /&gt;     e3.set$x(radius);&lt;br /&gt;     e3.set$y(0.0f);&lt;br /&gt;     path.loc$elements.insert(e3);&lt;br /&gt;    }&lt;br /&gt;    face.loc$content.insert(path);&lt;br /&gt;&lt;br /&gt;    group.loc$content.insert(face);&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  Timeline timeline = new Timeline();&lt;br /&gt;  timeline.set$repeatCount(Timeline.$INDEFINITE);&lt;br /&gt;&lt;br /&gt;  KeyFrame kf = new KeyFrame();&lt;br /&gt;  kf.set$time(Duration.valueOf(1000.0f));&lt;br /&gt;  kf.set$canSkip(true);&lt;br /&gt;  kf.set$action(new Function0&amp;lt;Void&amp;gt;() {&lt;br /&gt;   public Void invoke() {&lt;br /&gt;    nextTick();&lt;br /&gt;    return null;&lt;br /&gt;   }&lt;br /&gt;  });&lt;br /&gt;  timeline.loc$keyFrames.insert(kf);&lt;br /&gt;  // this is somewhat hairy JFxtras does it like this I think&lt;br /&gt;  Scene scene = new Scene();&lt;br /&gt;  scene.loc$content().insert(group);&lt;br /&gt;  JPanel panel = new JPanel(new BorderLayout());&lt;br /&gt;  TKScene fxNode = scene.get$javafx$scene$Scene$impl_peer();&lt;br /&gt;  panel.add(((SwingScene) fxNode).scenePanel, BorderLayout.CENTER);&lt;br /&gt;  JFrame frame = new JFrame("JavaFX Clock Example");&lt;br /&gt;  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);&lt;br /&gt;  frame.add(panel);&lt;br /&gt;  frame.setSize(295, 325);&lt;br /&gt;  frame.setVisible(true);&lt;br /&gt;  timeline.play();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public void nextTick() {&lt;br /&gt;  calendar.setTimeInMillis(System.currentTimeMillis());&lt;br /&gt;  seconds = calendar.get(Calendar.SECOND);&lt;br /&gt;  minutes = calendar.get(Calendar.MINUTE);&lt;br /&gt;  hours = calendar.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;  // trigger bindings to re calc and move hands&lt;br /&gt;  if (secondsVariable != null) {&lt;br /&gt;   secondsVariable.invalidate();&lt;br /&gt;   minutesVariable.invalidate();&lt;br /&gt;   hoursVariable.invalidate();&lt;br /&gt;  }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public static void main(String[] args) throws Exception {&lt;br /&gt;  SwingUtilities.invokeLater(new Runnable() {&lt;br /&gt;   @Override&lt;br /&gt;   public void run() {&lt;br /&gt;    try {&lt;br /&gt;     new Clock();&lt;br /&gt;    } catch (Exception e) {&lt;br /&gt;     e.printStackTrace();&lt;br /&gt;    }&lt;br /&gt;   }&lt;br /&gt;  });&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For comparison the JavaFX version follows here:&lt;br /&gt;&lt;pre class="brush:jfx"&gt;&lt;br /&gt;public class Clock extends CustomNode {&lt;br /&gt;&lt;br /&gt;    public var radius: Number = 77;&lt;br /&gt;    public var centerX: Number = 144;&lt;br /&gt;    public var centerY: Number = 144;&lt;br /&gt;&lt;br /&gt;    public var hours:Number;&lt;br /&gt;    public var minutes:Number;&lt;br /&gt;    public var seconds:Number;&lt;br /&gt;&lt;br /&gt;    public function nextTick () {&lt;br /&gt;        var now = new Date();&lt;br /&gt;        seconds = now.getSeconds();&lt;br /&gt;        minutes = now.getMinutes();&lt;br /&gt;        hours = now.getHours();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override function create() : Node {&lt;br /&gt;        return Group {&lt;br /&gt;            content: [&lt;br /&gt;                ImageView {&lt;br /&gt;                    image: Image {&lt;br /&gt;                        url: "{__DIR__}clock_background.png"&lt;br /&gt;                    }&lt;br /&gt;                },&lt;br /&gt;                Group {&lt;br /&gt;                    transforms: Translate {&lt;br /&gt;                        x: centerX,&lt;br /&gt;                        y: centerY&lt;br /&gt;                    }&lt;br /&gt;                    content: [&lt;br /&gt;                        // code to display the numbers for every third hour&lt;br /&gt;                        for (i in [3, 6, 9, 12])&lt;br /&gt;                        Text {&lt;br /&gt;                            transforms: Translate {&lt;br /&gt;                                x: -5,&lt;br /&gt;                                y: 5&lt;br /&gt;                            }&lt;br /&gt;                            font: Font {&lt;br /&gt;                                size: 16&lt;br /&gt;                            }&lt;br /&gt;                            x: radius * (( i + 0 ) mod 2 * ( 2 - i / 3))&lt;br /&gt;                            y: radius * (( i + 1 ) mod 2 * ( 3 - i / 3))&lt;br /&gt;                            content: "{i}"&lt;br /&gt;                        },  //Text&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                        //code to display a black circle for the rest of the hours on the clock&lt;br /&gt;                        for (i in [1..12])&lt;br /&gt;                        if (i mod 3 != 0 ) then Circle {&lt;br /&gt;                            transforms: Rotate {&lt;br /&gt;                                angle: 30 * i&lt;br /&gt;                            }&lt;br /&gt;                            centerX: radius&lt;br /&gt;                            radius: 3&lt;br /&gt;                            fill: Color.BLACK&lt;br /&gt;                        } //for&lt;br /&gt;                        else [ ],&lt;br /&gt;&lt;br /&gt;                        // code for the clock's first center circle&lt;br /&gt;                        Circle {&lt;br /&gt;                            radius: 5&lt;br /&gt;                            fill: Color.DARKRED&lt;br /&gt;                        }, //Circle&lt;br /&gt;                        //code for the smaller center circle&lt;br /&gt;                        Circle {&lt;br /&gt;                            radius: 3&lt;br /&gt;                            fill: Color.RED&lt;br /&gt;                        }, //Circle&lt;br /&gt;                        //code for the seconds hand&lt;br /&gt;                        Line {&lt;br /&gt;                            transforms: Rotate {&lt;br /&gt;                                angle: bind seconds * 6&lt;br /&gt;                            }&lt;br /&gt;                            endY: -radius - 3&lt;br /&gt;                            strokeWidth: 2&lt;br /&gt;                            stroke: Color.RED&lt;br /&gt;                        },  //Line&lt;br /&gt;                        //code for the hour hand&lt;br /&gt;                        Path {&lt;br /&gt;                            transforms: Rotate {&lt;br /&gt;                                angle: bind (hours + minutes / 60) * 30 - 90&lt;br /&gt;                            }&lt;br /&gt;                            fill: Color.BLACK&lt;br /&gt;                            elements: [&lt;br /&gt;                                MoveTo {&lt;br /&gt;                                    x: 4,&lt;br /&gt;                                y: 4},&lt;br /&gt;                                ArcTo {&lt;br /&gt;                                    x: 4&lt;br /&gt;                                    y: -4&lt;br /&gt;                                    radiusX: 1&lt;br /&gt;                                radiusY: 1},&lt;br /&gt;                                LineTo{&lt;br /&gt;                                    x: radius - 15&lt;br /&gt;                                y: 0},&lt;br /&gt;                            ] //elements&lt;br /&gt;                        },  // Path&lt;br /&gt;                        // code for the minutes hand&lt;br /&gt;                        Path {&lt;br /&gt;                            transforms: Rotate {&lt;br /&gt;                                angle: bind minutes * 6 - 90&lt;br /&gt;                            }&lt;br /&gt;                            fill: Color.BLACK&lt;br /&gt;                            elements: [&lt;br /&gt;                                MoveTo {&lt;br /&gt;                                    x: 4,&lt;br /&gt;                                y: 4},&lt;br /&gt;                                ArcTo {&lt;br /&gt;                                    x: 4&lt;br /&gt;                                    y: -4&lt;br /&gt;                                    radiusX: 1&lt;br /&gt;                                radiusY: 1},&lt;br /&gt;                                LineTo{&lt;br /&gt;                                    x: radius&lt;br /&gt;                                y: 0},&lt;br /&gt;                            ] // elements&lt;br /&gt;                        } // Path&lt;br /&gt;                    ] //content&lt;br /&gt;                }&lt;br /&gt;            ]&lt;br /&gt;        };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    init {&lt;br /&gt;        var timeline = Timeline {&lt;br /&gt;            repeatCount: Timeline.INDEFINITE&lt;br /&gt;            keyFrames: [&lt;br /&gt;                KeyFrame {&lt;br /&gt;                    time: 1s&lt;br /&gt;                    canSkip: true&lt;br /&gt;                    action: function() {&lt;br /&gt;                        nextTick();&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            ]&lt;br /&gt;        }&lt;br /&gt;        timeline.play();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Web start depolyment is rather easy as it is possible to take advantage of the JavaFX extension and just add:  &lt;br /&gt;&lt;pre class="brush:xml"&gt;&lt;br /&gt;&lt;extension name="JavaFX Runtime" href="http://dl.javafx.com/1.2/javafx-rt.jnlp"/&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;to your jnlp file and then do the usual jnlp stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-5826173775726447634?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/5826173775726447634/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=5826173775726447634' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/5826173775726447634'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/5826173775726447634'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2009/09/using-javafx-from-java.html' title='Using JavaFX Classes Directly From Java'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_7ROeMUNozjM/SroJ8LXpj9I/AAAAAAAAAu4/CNLMceZqZC0/s72-c/fxclock.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-7129354096685340652</id><published>2009-09-12T05:07:00.000-07:00</published><updated>2009-09-17T02:13:31.842-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><title type='text'>Country Flag Decorations On Your Swing Components</title><content type='html'>Here is how to get country flag icon decorations on your JTable cells, JList cells, JCombobox'es and JTextFields.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_7ROeMUNozjM/SrH7J4gIKvI/AAAAAAAAAuw/AUbcInIZU7A/s1600-h/snap13.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 285px; height: 400px;" src="http://3.bp.blogspot.com/_7ROeMUNozjM/SrH7J4gIKvI/AAAAAAAAAuw/AUbcInIZU7A/s400/snap13.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5382359176888986354" /&gt;&lt;/a&gt;&lt;center&gt;&lt;br /&gt;&lt;script src="http://java.com/js/deployJava.js"&gt;&lt;/script&gt;&lt;script&gt;var url = "http://www.navicon.dk/com/countryflags.jnlp";deployJava.createWebStartLaunchButton(url, '+1.6.0');&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;First you need to grab the &lt;a href="http://www.famfamfam.com/lab/icons/flags/"&gt;Flag Icons&lt;/a&gt; from the famfamfam site and package them into a jar file and add it to your classpath. The JTextField flag decoration is done via the BuddySupport in the &lt;a href="http://code.google.com/p/xswingx/"&gt;xswingx&lt;/a&gt; project.&lt;br /&gt;&lt;br /&gt;Then we need to set up a mapping of country names to famfamfam icon names like this:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;  private final String[] countries = { "AFGHANISTAN", "AF", "ÅLAND ISLANDS",...}&lt;br /&gt;  Map&amp;lt;String, String&amp;gt; countryMap = new HashMap&amp;lt;String, String&amp;gt;();&lt;br /&gt;  for (int i = 0; i &lt; countries.length;) {&lt;br /&gt;   countryMap.put(countries[i], countries[i + 1]);&lt;br /&gt;   i += 2;&lt;br /&gt;  }&lt;br /&gt;  countryFlagDecorator = new CountryFlagDecorator(countryMap);&lt;br /&gt;  // lazy do CountryFlagDecorator.getInstance() and skip the above mapping setup&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now we can decorate e.g., a JCombobox like this:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;  JComboBox flagCombo = new JComboBox(new String[] { "DENMARK", "SWEDEN",&lt;br /&gt;    "NORWAY" });&lt;br /&gt;  countryFlagDecorator.addCountryFlagDecorations(flagCombo);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A JTable cell like this:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;  JTable jt = new JTable(data, fields);&lt;br /&gt;  TableColumn col = jt.getColumnModel().getColumn(2);&lt;br /&gt;  col.setCellRenderer(new CountryFlagTableCellRendere(&lt;br /&gt;    countryFlagDecorator));&lt;br /&gt;  col.setCellEditor(new CountryFlagCellEditor(countryFlagDecorator,&lt;br /&gt;    new String[] { "DENMARK", "SWEDEN", "NORWAY" }));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A Jlist (with a small twist)&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;  JList flagList = new JList(new String[] { "DK", "SE", "NO", "US" });&lt;br /&gt;  flagList.setCellRenderer(new CountryFlagListCellRendere(&lt;br /&gt;    countryFlagDecorator, new CountryNameConverter() {&lt;br /&gt;     @Override&lt;br /&gt;     public String convertCountryName(String countryName) {&lt;br /&gt;      if ("DK".equals(countryName)) {&lt;br /&gt;       return "DENMARK";&lt;br /&gt;      } else if ("SE".equals(countryName)) {&lt;br /&gt;       return "SWEDEN";&lt;br /&gt;      } else if ("NO".equals(countryName)) {&lt;br /&gt;       return "NORWAY";&lt;br /&gt;      } else if ("US".equals(countryName)) {&lt;br /&gt;       return "UNITED STATES";&lt;br /&gt;      }&lt;br /&gt;      return null;&lt;br /&gt;     }&lt;br /&gt;    }));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And a JTextField like this:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;  JTextField flagField = new JTextField("");&lt;br /&gt;  PromptSupport.setPrompt("Write name of a country, e.g., DENMARK", flagField);&lt;br /&gt;  countryFlagDecorator.addCountryFlag(flagField, null);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Download the &lt;a href="http://www.navicon.dk/com/countryflags.tgz"&gt;source&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-7129354096685340652?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/7129354096685340652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=7129354096685340652' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/7129354096685340652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/7129354096685340652'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2009/09/country-flag-decorations-on-your-swing.html' title='Country Flag Decorations On Your Swing Components'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_7ROeMUNozjM/SrH7J4gIKvI/AAAAAAAAAuw/AUbcInIZU7A/s72-c/snap13.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-1306758668577147078</id><published>2009-09-09T02:43:00.000-07:00</published><updated>2009-09-09T02:59:15.031-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='KML'/><category scheme='http://www.blogger.com/atom/ns#' term='Google Earth'/><category scheme='http://www.blogger.com/atom/ns#' term='Jetty'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><title type='text'>Google Earth 3D Vessel Models With Swing &amp; Jetty</title><content type='html'>Using a Swing GUI with an embedded instance of Jetty a real time stream of vessel position information (&lt;a href="http://en.wikipedia.org/wiki/Automatic_Identification_System"&gt;AIS data&lt;/a&gt;) is converted into KML.This converts Google Earth into a low cost (free) AIS Display system. Vessels can be displayed as 3D models that are scaled according to AIS information&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;image src="http://www.navicon.dk/AIS/demo/ge-small.png"/&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;&lt;br /&gt;You can give it a spin (&lt;a href="http://earth.google.com/"&gt;Google Earth&lt;/a&gt; needs to be installed) by pushing the launch button below.&lt;br /&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;script src="http://java.com/js/deployJava.js"&gt;&lt;/script&gt;&lt;script&gt;var url = "http://www.navicon.dk/aisgegui/application/launch.jnlp";deployJava.createWebStartLaunchButton(url, '+1.6.0');&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-1306758668577147078?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/1306758668577147078/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=1306758668577147078' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/1306758668577147078'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/1306758668577147078'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2009/09/google-earth-3d-vessel-models-with.html' title='Google Earth 3D Vessel Models With Swing &amp; Jetty'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-7593040817905846864</id><published>2009-09-06T04:52:00.000-07:00</published><updated>2009-09-06T06:04:27.995-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JHLabs'/><category scheme='http://www.blogger.com/atom/ns#' term='SwingX'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><title type='text'>Fancy JLabels With JHLabs Filters</title><content type='html'>Recently I was looking for a way to create "fancy" text for some title panes and I stumbled over &lt;a href="http://www.jhlabs.com/ip/filters/index.html"&gt;JHLabs Image Filters&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_7ROeMUNozjM/SqOi7q9X1MI/AAAAAAAAAuQ/l8Ld4C9S_t4/s1600-h/jhlabs-label.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 400px;" src="http://3.bp.blogspot.com/_7ROeMUNozjM/SqOi7q9X1MI/AAAAAAAAAuQ/l8Ld4C9S_t4/s400/jhlabs-label.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5378321526038189250" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;center&gt;&lt;br /&gt; &lt;script src="http://java.com/js/deployJava.js"&gt;&lt;/script&gt;&lt;script&gt;var url = "http://www.navicon.dk/com/jhlabs-labels.jnlp";deployJava.createWebStartLaunchButton(url, '+1.6.0');&lt;/script&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;Over at JHLabs there are examples of how to create e.g., &lt;a href="http://www.jhlabs.com/ie/glow.html"&gt;glowing text&lt;/a&gt;:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;a href="http://www.jhlabs.com/ie/glow.html"&gt;&lt;image src="http://www.jhlabs.com/ie/glow5.gif"/&gt;&lt;/a&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;Or &lt;a href="http://www.jhlabs.com/ip/filters/ChromeFilter.html"&gt;chrome like&lt;/a&gt; text:&lt;br /&gt;&lt;center&gt;&lt;br /&gt;&lt;a href="http://www.jhlabs.com/ip/filters/ChromeFilter.html"&gt;&lt;image src="http://www.jhlabs.com/ip/filters/ChromeFilter4.jpg"/&gt;&lt;/a&gt;&lt;br /&gt;&lt;/center&gt;&lt;br /&gt;To get a simmlar effect on a JLabel just replace the JLabel with a JHLabsLabel e.g.;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;JLabel label = new JHLabsLabel("Hello World", new ChromeFilter(), new ShadowFilter(5, 5, 2, .7f));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here is the code for JHLabsLabel:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt; /**&lt;br /&gt;  * Notice that this is not perfect wrt alignment to see just uncomment super.paintComponent(g) &lt;br /&gt;  * Maybe somebody with BasicLabelUI knowledge could help?&lt;br /&gt;  * &lt;br /&gt;  */&lt;br /&gt; public static final class JHLabsLabel extends JLabel {&lt;br /&gt;&lt;br /&gt;  private int textX;&lt;br /&gt;&lt;br /&gt;  private int textY;&lt;br /&gt;&lt;br /&gt;  private AbstractBufferedImageOp[] filters;&lt;br /&gt;&lt;br /&gt;  public JHLabsLabel(String string, AbstractBufferedImageOp... filters) {&lt;br /&gt;   super(string);&lt;br /&gt;   this.filters = filters;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void paintComponent(Graphics g) {&lt;br /&gt;&lt;br /&gt;   // super.paintComponent(g);&lt;br /&gt;&lt;br /&gt;   BufferedImage img = createTextImage(getText(), getFont());&lt;br /&gt;&lt;br /&gt;   for (AbstractBufferedImageOp f : filters) {&lt;br /&gt;    img = f.filter(img, null);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   // g.drawImage(f.filter(img, null), textX, textY, null);&lt;br /&gt;   g.drawImage(img, textX, textY, null);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private BufferedImage createTextImage(String text, Font font) {&lt;br /&gt;&lt;br /&gt;   Rectangle paintIconR = new Rectangle();&lt;br /&gt;   Rectangle paintTextR = new Rectangle();&lt;br /&gt;   Rectangle paintViewR = new Rectangle();&lt;br /&gt;   Insets paintViewInsets = new Insets(0, 0, 0, 0);&lt;br /&gt;&lt;br /&gt;   paintViewInsets = getInsets(paintViewInsets);&lt;br /&gt;   paintViewR.x = paintViewInsets.left;&lt;br /&gt;   paintViewR.y = paintViewInsets.top;&lt;br /&gt;   paintViewR.width = getWidth()&lt;br /&gt;     - (paintViewInsets.left + paintViewInsets.right);&lt;br /&gt;   paintViewR.height = getHeight()&lt;br /&gt;     - (paintViewInsets.top + paintViewInsets.bottom);&lt;br /&gt;&lt;br /&gt;   String clippedText = SwingUtilities.layoutCompoundLabel(&lt;br /&gt;     (JComponent) this, getFontMetrics(getFont()), text,&lt;br /&gt;     getIcon(), getVerticalAlignment(),&lt;br /&gt;     getHorizontalAlignment(), getVerticalTextPosition(),&lt;br /&gt;     getHorizontalTextPosition(), paintViewR, paintIconR,&lt;br /&gt;     paintTextR, getIconTextGap());&lt;br /&gt;&lt;br /&gt;   boolean isAntiAliased = true;&lt;br /&gt;   boolean usesFractionalMetrics = false;&lt;br /&gt;   FontRenderContext frc = new FontRenderContext(null, isAntiAliased,&lt;br /&gt;     usesFractionalMetrics);&lt;br /&gt;   TextLayout layout = new TextLayout(clippedText, font, frc);&lt;br /&gt;   Rectangle2D bounds = layout.getBounds();&lt;br /&gt;   int w = (int) Math.ceil(bounds.getWidth());&lt;br /&gt;   int h = (int) Math.ceil(bounds.getHeight());&lt;br /&gt;   BufferedImage image = new BufferedImage(w, h,&lt;br /&gt;     BufferedImage.TYPE_INT_ARGB);&lt;br /&gt;   Graphics2D g = image.createGraphics();&lt;br /&gt;   g.setColor(new Color(0, 0, 0, 0));&lt;br /&gt;   g.fillRect(0, 0, w, h);&lt;br /&gt;   g.setColor(getForeground());&lt;br /&gt;   g.setFont(font);&lt;br /&gt;   Object antiAliased = isAntiAliased ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON&lt;br /&gt;     : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF;&lt;br /&gt;   g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,&lt;br /&gt;     antiAliased);&lt;br /&gt;   Object fractionalMetrics = usesFractionalMetrics ? RenderingHints.VALUE_FRACTIONALMETRICS_ON&lt;br /&gt;     : RenderingHints.VALUE_FRACTIONALMETRICS_OFF;&lt;br /&gt;   g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,&lt;br /&gt;     fractionalMetrics);&lt;br /&gt;   g.drawString(clippedText, (float) -bounds.getX(), (float) -bounds&lt;br /&gt;     .getY());&lt;br /&gt;   // g.drawString(clippedText, (float) 0, (float) 0);&lt;br /&gt;   g.dispose();&lt;br /&gt;&lt;br /&gt;   textX = paintTextR.x;&lt;br /&gt;   textY = paintTextR.y;// + getFontMetrics(font).getAscent() / 2;&lt;br /&gt;   System.out.println(String.format("X=%d Y=%d, w=%d h=%d", textX,&lt;br /&gt;     textY, w, h));&lt;br /&gt;&lt;br /&gt;   return image;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I also could not resist to play to the JHLabs texture filters as background painters e.g.,&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;JXPanel woodPanel = new JXPanel();&lt;br /&gt;woodPanel.setBackgroundPainter(new JHTexturePainter&amp;lt;JXPanel&amp;gt;(new CausticsFilter(), new SparkleFilter()));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Creates the initial background for the demo.&lt;br /&gt;&lt;br /&gt;Here is the code for JHTexturePainter:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt; /**&lt;br /&gt;  * &lt;br /&gt;  * Paint the background using a combination of the JHLabs image filters&lt;br /&gt;  * &lt;br /&gt;  * @param &amp;lt;T&amp;gt;&lt;br /&gt;  */&lt;br /&gt; static final class JHTexturePainter&amp;lt;T&amp;gt; implements Painter&amp;lt;T&amp;gt; {&lt;br /&gt;&lt;br /&gt;  private AbstractBufferedImageOp[] filters;&lt;br /&gt;&lt;br /&gt;  public JHTexturePainter(AbstractBufferedImageOp... filters) {&lt;br /&gt;   this.filters = filters;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Override&lt;br /&gt;  public void paint(Graphics2D g2d, T arg1, int w, int h) {&lt;br /&gt;   BufferedImage image = new BufferedImage(w, h,&lt;br /&gt;     BufferedImage.TYPE_INT_ARGB);&lt;br /&gt;   Graphics2D g = image.createGraphics();&lt;br /&gt;   g.setColor(new Color(0, 0, 0, 0));&lt;br /&gt;   g.fillRect(0, 0, w, h);&lt;br /&gt;&lt;br /&gt;   for (AbstractBufferedImageOp f : filters) {&lt;br /&gt;    image = f.filter(image, null);&lt;br /&gt;   }&lt;br /&gt;   g.dispose();&lt;br /&gt;   g2d.drawImage(image, 0, 0, null);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-7593040817905846864?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/7593040817905846864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=7593040817905846864' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/7593040817905846864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/7593040817905846864'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2009/09/fancy-jlabels-with-jhlabs-filters.html' title='Fancy JLabels With JHLabs Filters'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_7ROeMUNozjM/SqOi7q9X1MI/AAAAAAAAAuQ/l8Ld4C9S_t4/s72-c/jhlabs-label.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-4969245854949106332</id><published>2009-08-28T10:50:00.000-07:00</published><updated>2009-08-29T06:35:04.646-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='GIS'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenMap'/><category scheme='http://www.blogger.com/atom/ns#' term='GPS'/><title type='text'>Build your own GPS/GIS system in less than 200 lines with OpenMap</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_7ROeMUNozjM/Spjb2vjGpTI/AAAAAAAAAtw/0hiLqbven3k/s1600-h/gps.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 294px;" src="http://3.bp.blogspot.com/_7ROeMUNozjM/Spjb2vjGpTI/AAAAAAAAAtw/0hiLqbven3k/s320/gps.png" alt="" id="BLOGGER_PHOTO_ID_5375287888789808434" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Here is how to do your own (simplistic) GPS/GIS system using &lt;a href="http://openmap.bbn.com/"&gt;OpenMap&lt;/a&gt; in less than 200 lines of code. To get started you will need to download and install OpenMap.&lt;br /&gt;&lt;br /&gt;The GPS Layer for OpenMap is as follows. Notice that the code is somewhat crude with regards to threading, drizzel some synchronized on to it as appropriate.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class GPSLayer extends OMGraphicHandlerLayer {&lt;br /&gt;&lt;br /&gt;private static String GPSDATA = "gpsData";&lt;br /&gt;&lt;br /&gt;private static final double KT2MPS = 1852.0 / 3600.0;&lt;br /&gt;&lt;br /&gt;private static final double speedVectorLengthInMinutes = 6;&lt;br /&gt;&lt;br /&gt;private String gpsDataPath = "";&lt;br /&gt;&lt;br /&gt;private float latitude, longitude, speed, course;&lt;br /&gt;&lt;br /&gt;private OMGraphicList graphics = new OMGraphicList();;&lt;br /&gt;&lt;br /&gt;private OMRect gpsPosition = new OMRect(0, 0, 0, 0, 10, 10);&lt;br /&gt;&lt;br /&gt;private OMLine speedVector;&lt;br /&gt;&lt;br /&gt;private OMText gpsText = new OMText(10, 20, "GPS Data",&lt;br /&gt;OMText.JUSTIFY_LEFT);&lt;br /&gt;&lt;br /&gt;private Timer timer;&lt;br /&gt;&lt;br /&gt;public GPSLayer() {&lt;br /&gt;gpsText.setFillPaint(Color.WHITE);&lt;br /&gt;gpsText.setTextMatteColor(new Color(182, 235, 219));&lt;br /&gt;gpsPosition.setFillPaint(Color.pink);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public void setProperties(String prefix, Properties props) {&lt;br /&gt;super.setProperties(prefix, props);&lt;br /&gt;gpsDataPath = props.getProperty(prefix + "." + GPSDATA);&lt;br /&gt;// redraw every 5 secs&lt;br /&gt;timer = new Timer(5000, this);&lt;br /&gt;timer.start();&lt;br /&gt;&lt;br /&gt;// emulate reading GPS data (threading issue here access to members not&lt;br /&gt;// protected!)&lt;br /&gt;new Thread(new Runnable() {&lt;br /&gt;public void run() {&lt;br /&gt; try {&lt;br /&gt;  BufferedReader in = new BufferedReader(new FileReader(&lt;br /&gt;    gpsDataPath));&lt;br /&gt;  String str;&lt;br /&gt;  while ((str = in.readLine()) != null) {&lt;br /&gt;   Thread.sleep(100);&lt;br /&gt;   if (str.startsWith("$GPRMC")) {&lt;br /&gt;    String[] fields = str.split(",");&lt;br /&gt;    // utc_date = fields[1];&lt;br /&gt;    double lat = Double.parseDouble(fields[3]);&lt;br /&gt;    double degrees = Math.floor((lat / 100.0));&lt;br /&gt;    double minute = (lat / 100.0) - degrees;&lt;br /&gt;    lat = (degrees) + ((minute * 100.0) / 60);&lt;br /&gt;    if (fields[4].equals("S"))&lt;br /&gt;     lat = -lat;&lt;br /&gt;    latitude = (float) lat;&lt;br /&gt;&lt;br /&gt;    double lon = Double.parseDouble(fields[5]);&lt;br /&gt;    degrees = Math.floor((lon / 100.0));&lt;br /&gt;    minute = (lon / 100.0) - degrees;&lt;br /&gt;    lon = (degrees) + ((minute * 100.0) / 60);&lt;br /&gt;    if (fields[6].equals("W"))&lt;br /&gt;     lon = -lon;&lt;br /&gt;    longitude = (float) lon;&lt;br /&gt;&lt;br /&gt;    speed = (float) (Double.parseDouble(fields[7]) * KT2MPS);&lt;br /&gt;&lt;br /&gt;    if (!fields[8].equals("")) {&lt;br /&gt;     course = (float) Double.parseDouble(fields[8]);&lt;br /&gt;    }&lt;br /&gt;    // could parse date but to lazy&lt;br /&gt;    // date = fields[9];&lt;br /&gt;   }&lt;br /&gt;  }&lt;br /&gt;  in.close();&lt;br /&gt; } catch (Exception e) {&lt;br /&gt;  e.printStackTrace();&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;}).start();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public synchronized OMGraphicList prepare() {&lt;br /&gt;gpsPosition.setLocation(latitude, longitude, -5, -5, 5, 5);&lt;br /&gt;&lt;br /&gt;// calc. speed vector length using OM GIS functions&lt;br /&gt;LatLonPoint startPos = new LatLonPoint(latitude, longitude);&lt;br /&gt;float length = (float) Length.KM.toRadians(speedVectorLengthInMinutes&lt;br /&gt; * ((speed * 3.6) / 60.0));&lt;br /&gt;LatLonPoint endPos = startPos.getPoint(length, (float) ProjMath&lt;br /&gt; .degToRad(course));&lt;br /&gt;speedVector = new OMLine(startPos.getLatitude(), startPos&lt;br /&gt; .getLongitude(), endPos.getLatitude(), endPos.getLongitude(),&lt;br /&gt; OMLine.LINETYPE_STRAIGHT);&lt;br /&gt;// vec.addArrowHead(OMArrowHead.ARROWHEAD_DIRECTION_FORWARD, 100, 3, 1);&lt;br /&gt;speedVector.setLinePaint(Color.DARK_GRAY);&lt;br /&gt;&lt;br /&gt;graphics.clear();&lt;br /&gt;// order of add determines what is rendered on top&lt;br /&gt;graphics.add(speedVector);&lt;br /&gt;graphics.add(gpsPosition);&lt;br /&gt;gpsText.setData(String.format("GPS Data\n%4.2f Km/h",&lt;br /&gt; (speed * 3.60)));&lt;br /&gt;graphics.add(gpsText);&lt;br /&gt;&lt;br /&gt;graphics.project(getProjection());&lt;br /&gt;return graphics;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public void actionPerformed(ActionEvent ae) {&lt;br /&gt;doPrepare();&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you have a GPS antenna you can use one of the free GPS servers (gpsd on linux) to make its data available on a socket and then modify the &lt;tt&gt;in&lt;/tt&gt; variable in reader thread to the following:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;uc = new URL(gpsDataPath).openConnection(); // gps.gpsData=http://localhost:2244&lt;br /&gt;InputStreamReader icr = new InputStreamReader(uc.getInputStream());&lt;br /&gt;in = new BufferedReader(icr);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To run this put the above class into a jar file and copy it to the lib dir of the OpenMap installation. Then in the share dir create a openmap.properties file with the following content:&lt;pre&gt;&lt;br /&gt;openmap.layers=gps graticule shapePolitical&lt;br /&gt;openmap.startUpLayers=gps graticule shapePolitical&lt;br /&gt;&lt;br /&gt;gps.class=GPSLayer&lt;br /&gt;gps.prettyName=GPS Position&lt;br /&gt;gps.gpsData=/tmp/gpslog.txt&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then go to the bin dir of the OpenMap installation and do &lt;tt&gt;./openmap(.bat)&lt;/tt&gt; and your GPS/GIS system will be running.&lt;br /&gt;&lt;br /&gt;Then following can be used as test data&lt;pre&gt;&lt;br /&gt;$GPRMC,143346,A,5616.9232,N,01008.2504,E,074.6,011.3,110105,000.9,E,A*13&lt;br /&gt;$GPRMC,143347,A,5616.9435,N,01008.2571,E,074.5,010.4,110105,000.9,E,A*14&lt;br /&gt;$GPRMC,143348,A,5616.9638,N,01008.2632,E,074.4,009.5,110105,000.9,E,A*18&lt;br /&gt;$GPRMC,143349,A,5616.9842,N,01008.2686,E,074.3,008.4,110105,000.9,E,A*12&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-4969245854949106332?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/4969245854949106332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=4969245854949106332' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/4969245854949106332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/4969245854949106332'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2009/08/build-you-own-gpsgis-system-in-less.html' title='Build your own GPS/GIS system in less than 200 lines with OpenMap'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_7ROeMUNozjM/Spjb2vjGpTI/AAAAAAAAAtw/0hiLqbven3k/s72-c/gps.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-5155181005828098654</id><published>2009-08-21T00:30:00.000-07:00</published><updated>2009-08-26T08:27:04.878-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='SwingX'/><category scheme='http://www.blogger.com/atom/ns#' term='JXTable'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><title type='text'>Persisting JXTable's Column Control Settings</title><content type='html'>Here is how to persist (save/restore) the users settings (ordering of columns, visbility etc) of a JXTable using the &lt;a href="https://appframework.dev.java.net/"&gt;Swing Application Framework&lt;/a&gt; aka SAF (JSR-296). You will need to download the jar for SAF to get the stuff below working.&lt;br /&gt;&lt;br /&gt;(Notice that all of this is inspirede by &lt;a href="http://puces-blog.blogspot.com/2009/04/netbeans-platform-meets-swing.html"&gt;NetBeans Platform meets Swing Application Framework: SessionStorage&lt;/a&gt; but without all the NetBeans clutter.)&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;/**&lt;br /&gt; * &lt;br /&gt; * @See http://puces-blog.blogspot.com/2009/04/netbeans-platform-meets-swing.html&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;public class ModuleApplicationContext extends ApplicationContext {&lt;br /&gt;&lt;br /&gt; private String storageDirectoryPath = "";&lt;br /&gt;&lt;br /&gt; static {&lt;br /&gt;&lt;br /&gt;// download from https://jdnc-incubator.dev.java.net/source/browse/jdnc-incubator/trunk/src/kleopatra/java/org/jdesktop/appframework/swingx/XProperties.java?rev=3198&amp;view=markup&lt;br /&gt;  new XProperties().registerPersistenceDelegates();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public ModuleApplicationContext(String path) {&lt;br /&gt;  // Needed due to issue&lt;br /&gt;  // https://appframework.dev.java.net/issues/show_bug.cgi?id=112&lt;br /&gt;  setLocalStorage(new ModuleLocalStorage(this));&lt;br /&gt;  // getLocalStorage().setDirectory(getModuleSessionStorageDir(moduleInfo));&lt;br /&gt;  storageDirectoryPath = path;&lt;br /&gt;  getLocalStorage().setDirectory(new File(storageDirectoryPath));&lt;br /&gt;  getSessionStorage().putProperty(JXTable.class,&lt;br /&gt;    new XProperties.XTableProperty());&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;/**&lt;br /&gt; * A LocalStorage for modules. It respects the direcory property in JNLP mode. &lt;BR/&gt;&lt;br /&gt; * &lt;BR/&gt;&lt;br /&gt; * Needed due to issue &lt;A&lt;br /&gt; * HREF="https://appframework.dev.java.net/issues/show_bug.cgi?id=112"&gt;&lt;br /&gt; * https://appframework.dev.java.net/issues/show_bug.cgi?id=112&lt;/A&gt;&lt;br /&gt; * &lt;br /&gt; * @author puce&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;public class ModuleLocalStorage extends LocalStorage {&lt;br /&gt;&lt;br /&gt; public ModuleLocalStorage(ApplicationContext context) {&lt;br /&gt;  super(context);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public boolean deleteFile(String fileName) throws IOException {&lt;br /&gt;  File path = new File(getDirectory(), fileName);&lt;br /&gt;  return path.delete();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public InputStream openInputFile(String fileName) throws IOException {&lt;br /&gt;  File path = new File(getDirectory(), fileName);&lt;br /&gt;  return new BufferedInputStream(new FileInputStream(path));&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; public OutputStream openOutputFile(String fileName) throws IOException {&lt;br /&gt;  File path = new File(getDirectory(), fileName);&lt;br /&gt;  return new BufferedOutputStream(new FileOutputStream(path));&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then you can use the ModuleApplicationContext to save the column control settings of a JXTable doing something like below:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class TestJXTable extends JFrame {&lt;br /&gt;&lt;br /&gt; String data[][] = { { "John", "Sutherland", "Student" },&lt;br /&gt;   { "George", "Davies", "Student" },&lt;br /&gt;   { "Melissa", "Anderson", "Associate" },&lt;br /&gt;   { "Stergios", "Maglaras", "Developer" }, };&lt;br /&gt;&lt;br /&gt; String fields[] = { "Name", "Surname", "Status" };&lt;br /&gt;&lt;br /&gt; ModuleApplicationContext mac;&lt;br /&gt;&lt;br /&gt; JXTable jt;&lt;br /&gt;&lt;br /&gt; JScrollPane pane;&lt;br /&gt;&lt;br /&gt; public static void main(String[] argv) {&lt;br /&gt;  SwingUtilities.invokeLater(new Runnable() {&lt;br /&gt;   @Override&lt;br /&gt;   public void run() {&lt;br /&gt;    TestJXTable myExample = new TestJXTable(&lt;br /&gt;      "JXTable Example");&lt;br /&gt;   }&lt;br /&gt;  });&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public TestJXTable(String title) {&lt;br /&gt;  super(title);&lt;br /&gt;  // save settings in users home dir&lt;br /&gt;  mac = new ModuleApplicationContext(System.getProperty("user.home"));&lt;br /&gt;  setSize(150, 150);&lt;br /&gt;  addWindowListener(new WindowAdapter() {&lt;br /&gt;   public void windowClosing(WindowEvent we) {&lt;br /&gt;    dispose();&lt;br /&gt;    try {&lt;br /&gt;     jt.getParent().remove(jt);&lt;br /&gt;     mac.getSessionStorage().save(jt, "testTable.xml");&lt;br /&gt;    } catch (IOException e) {&lt;br /&gt;     e.printStackTrace();&lt;br /&gt;    }&lt;br /&gt;    System.exit(0);&lt;br /&gt;   }&lt;br /&gt;  });&lt;br /&gt;  init();&lt;br /&gt;  pack();&lt;br /&gt;  setVisible(true);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private void init() {&lt;br /&gt;  jt = new JXTable(data, fields);&lt;br /&gt;  jt.setColumnControlVisible(true);&lt;br /&gt;  jt.setName("testTable");&lt;br /&gt;  pane = new JScrollPane(jt);&lt;br /&gt;  pane.setName("testPane");&lt;br /&gt;  try {&lt;br /&gt;   mac.getSessionStorage().restore(jt, "testTable.xml");&lt;br /&gt;  } catch (IOException e) {&lt;br /&gt;   e.printStackTrace();&lt;br /&gt;  }&lt;br /&gt;  getContentPane().add(pane);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-5155181005828098654?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/5155181005828098654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=5155181005828098654' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/5155181005828098654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/5155181005828098654'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2009/08/persisting-jxtables-column-control.html' title='Persisting JXTable&apos;s Column Control Settings'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-3935488296646924703</id><published>2009-08-18T02:48:00.000-07:00</published><updated>2009-08-18T03:11:31.501-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenMap'/><category scheme='http://www.blogger.com/atom/ns#' term='Substance'/><title type='text'>Font sizer in OpenMap statusbar</title><content type='html'>If you run &lt;a href="http://openmap.bbn.com/"&gt;OpenMap&lt;/a&gt; (beta5) under the &lt;a href="https://substance.dev.java.net/"&gt;Substance&lt;/a&gt; 5.2 LAF you can add a font size slider to the OpenMap statusbar doing this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class FontPanel extends OMComponentPanel {&lt;br /&gt;&lt;br /&gt;    public FontPanel() {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void findAndInit(Object obj) {&lt;br /&gt;        if (obj instanceof InformationDelegator) {&lt;br /&gt;            InformationDelegator delgator = (InformationDelegator) obj;&lt;br /&gt;            GridBagConstraints c = new GridBagConstraints();&lt;br /&gt;            c.weightx = 1;&lt;br /&gt;            c.weighty = 1;&lt;br /&gt;            c.anchor = GridBagConstraints.EAST;&lt;br /&gt;            c.fill = GridBagConstraints.HORIZONTAL;&lt;br /&gt;            c.insets = new Insets(0, 0, 0, 4);&lt;br /&gt;            Component statusPanel = DialogUtils.getChildNamed(delgator,&lt;br /&gt;                    StatusLightPanel.class);&lt;br /&gt;            delgator.remove(statusPanel);&lt;br /&gt;            delgator.add(FontSizePanel.getPanel(), c);&lt;br /&gt;            delgator.add(statusPanel);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Add the above class to your openmap.components in openmap.properties and then run OM with &lt;pre&gt;-Dswing.defaultlaf=org.jvnet.substance.skin.SubstanceCremeLookAndFeel&lt;/pre&gt; Click &lt;a href="http://4.bp.blogspot.com/_7ROeMUNozjM/SoprdJ8HwJI/AAAAAAAAAtQ/kZHGytVi4Yw/s1600-h/snap10.png"&gt;here&lt;/a&gt; to see how this looks.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.java2s.com/Open-Source/Java-Document/Swing-Library/substance-look-feel/test/check/statusbar/FontSizePanel.java.htm"&gt;FontSizePanel.java&lt;/a&gt; can be found here or downloaded from the &lt;a href="https://substance.dev.java.net/"&gt;Substance&lt;/a&gt; homepage.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-3935488296646924703?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/3935488296646924703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=3935488296646924703' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/3935488296646924703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/3935488296646924703'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2009/08/font-sizer-in-openmap-statusbar.html' title='Font sizer in OpenMap statusbar'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-2244023413899603161</id><published>2009-08-18T01:26:00.000-07:00</published><updated>2009-08-21T02:49:06.045-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VLDocking'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><category scheme='http://www.blogger.com/atom/ns#' term='Substance'/><title type='text'>Substance with VLDocking Framework</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_7ROeMUNozjM/SoprdJ8HwJI/AAAAAAAAAtQ/kZHGytVi4Yw/s1600-h/snap10.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_7ROeMUNozjM/SoprdJ8HwJI/AAAAAAAAAtQ/kZHGytVi4Yw/s320/snap10.png" alt="" id="BLOGGER_PHOTO_ID_5371223654221201554" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Here is a simple UI integration of the &lt;a href="http://www.vlsolutions.com/en/products/docking/"&gt;VLDocking&lt;/a&gt; Framework with &lt;a href="https://substance.dev.java.net/"&gt;Substance&lt;/a&gt; 5.2.&lt;br /&gt;&lt;br /&gt;In main do:&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;DockingUISettings.getInstance().installUI();&lt;br /&gt;//and start customizing... MyDockViewTitleBarUI&lt;br /&gt;UIManager.put("DockViewTitleBarUI", "MyDockViewTitleBarUI");&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class MyDockViewTitleBarUI extends DockViewTitleBarUI {&lt;br /&gt;&lt;br /&gt;public MyDockViewTitleBarUI(DockViewTitleBar tb) {&lt;br /&gt;super(tb);&lt;br /&gt;SubstanceLookAndFeel.setDecorationType(tb,&lt;br /&gt;DecorationAreaType.PRIMARY_TITLE_PANE);&lt;br /&gt;tb.setForeground(SubstanceColorUtilities&lt;br /&gt;.getForegroundColor(SubstanceColorSchemeUtilities&lt;br /&gt;.getColorScheme(tb, ComponentState.ACTIVE)));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;static public MyDockViewTitleBarUI createUI(JComponent tb) {&lt;br /&gt;return new MyDockViewTitleBarUI((DockViewTitleBar) tb);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public void paint(Graphics g, JComponent c) {&lt;br /&gt;DockViewTitleBar tb = (DockViewTitleBar) c;&lt;br /&gt;&lt;br /&gt;SubstanceSkin skin = SubstanceCoreUtilities.getSkin(tb);&lt;br /&gt;if (skin != null) {&lt;br /&gt;SubstanceDecorationUtilities&lt;br /&gt;.paintDecorationBackground(g, tb, false);&lt;br /&gt;} else {&lt;br /&gt;super.paint(g, tb);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-2244023413899603161?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/2244023413899603161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=2244023413899603161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/2244023413899603161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/2244023413899603161'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2009/08/substance-with-vldocking-framework.html' title='Substance with VLDocking Framework'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_7ROeMUNozjM/SoprdJ8HwJI/AAAAAAAAAtQ/kZHGytVi4Yw/s72-c/snap10.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8892828254544321690.post-8485311755954841933</id><published>2009-08-18T00:45:00.000-07:00</published><updated>2009-09-09T06:09:34.404-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='SwingX'/><category scheme='http://www.blogger.com/atom/ns#' term='JXTable'/><category scheme='http://www.blogger.com/atom/ns#' term='Swing'/><category scheme='http://www.blogger.com/atom/ns#' term='Substance'/><title type='text'>JXTable Striping with Substance 5.2</title><content type='html'>Here is how I got table striping to work on &lt;a href="https://swingx.dev.java.net/"&gt;JXTable&lt;/a&gt; with &lt;a href="https://substance.dev.java.net/"&gt;Substance&lt;/a&gt; 5.2.&lt;br /&gt;&lt;pre class="brush: java"&gt;&lt;br /&gt;&lt;br /&gt;public class DefaultTableFactory implements TableFactory {&lt;br /&gt;&lt;br /&gt; public JTable createTable() {&lt;br /&gt;  JXTable result = new JXTable();&lt;br /&gt;  return configureTable(result);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; public JTable createTable(TableModel model) {&lt;br /&gt;  JXTable result = new JXTable(model);&lt;br /&gt;  return configureTable(result);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; private JXTable configureTable(JXTable result) {&lt;br /&gt;  result.getSelectionMapper().setEnabled(false);&lt;br /&gt;  result.setColumnControlVisible(true);&lt;br /&gt;  result.setHighlighters(createHighlighter(result), new ColorHighlighter(&lt;br /&gt;    HighlightPredicate.ROLLOVER_ROW, null, Color.BLUE));&lt;br /&gt;  result.setRolloverEnabled(true);&lt;br /&gt;  result.setHorizontalScrollEnabled(true);&lt;br /&gt;  return result;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;public CompoundHighlighter createHighlighter(JXTable t) { &lt;br /&gt;ColorHighlighter first = new SubstanceHighLighter(HighlightPredicate.EVEN, t);&lt;br /&gt;ColorHighlighter hl = new SubstanceHighLighter(HighlightPredicate.ODD,t);&lt;br /&gt;return new CompoundHighlighter(first, hl);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// get striping on jxtable to work with substance&lt;br /&gt;public class SubstanceHighLighter extends ColorHighlighter {&lt;br /&gt;&lt;br /&gt;private JXTable comp;&lt;br /&gt;&lt;br /&gt;SubstanceHighLighter(HighlightPredicate pred, JXTable t) {&lt;br /&gt;setHighlightPredicate(pred);&lt;br /&gt;comp = t;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Override&lt;br /&gt;public Color getBackground() {&lt;br /&gt;return SubstanceColorUtilities.getStripedBackground(comp,&lt;br /&gt;getHighlightPredicate() == HighlightPredicate.EVEN ? 1 : 0);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There is still a problem with some of the cell renders installed by JXTable...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8892828254544321690-8485311755954841933?l=carsten-oland.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://carsten-oland.blogspot.com/feeds/8485311755954841933/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8892828254544321690&amp;postID=8485311755954841933' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/8485311755954841933'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8892828254544321690/posts/default/8485311755954841933'/><link rel='alternate' type='text/html' href='http://carsten-oland.blogspot.com/2009/08/jxtable-striping-with-substance-52.html' title='JXTable Striping with Substance 5.2'/><author><name>Carsten</name><uri>http://www.blogger.com/profile/06616747652802352036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry></feed>
