<?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-3099599922593802324</id><updated>2011-10-24T21:50:10.278+02:00</updated><category term='xml'/><category term='libsigc++'/><category term='mime'/><category term='doxygen'/><category term='gtkmm'/><category term='cdt'/><category term='personal'/><category term='dia'/><category term='pango'/><category term='pattern'/><category term='uml'/><category term='fun'/><category term='eclipse'/><category term='ggredit'/><category term='Windows'/><category term='data compression'/><category term='c++'/><category term='cairomm'/><category term='freedesktop'/><category term='usability'/><category term='gnome'/><category term='HIG'/><title type='text'>Kapo C++</title><subtitle type='html'>C++ standard, Linux development tools, gtkmm, glademm, object oriented, uml</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>66</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-7260359623315545154</id><published>2011-05-05T11:09:00.000+02:00</published><updated>2011-05-05T11:09:05.639+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><title type='text'>Remove folder contents based on folder name</title><content type='html'>FOR /D %%X IN (&lt;i&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;SEARCH_CRITERIA&lt;/span&gt;&lt;/i&gt;*) DO DEL /Q "%%X"\*.*&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-7260359623315545154?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/7260359623315545154/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2011/05/remove-folder-contents-based-on-folder.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7260359623315545154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7260359623315545154'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2011/05/remove-folder-contents-based-on-folder.html' title='Remove folder contents based on folder name'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-327778465301471294</id><published>2010-09-23T17:55:00.000+02:00</published><updated>2010-09-23T17:55:36.537+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='cdt'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>[DRAFT] Using Gtkmm on Windows with Eclipse CDT</title><content type='html'>This would be the first and the last post on my blog that deal with windows. It seems that many people like to use Gtkmm with Eclipse on this minor operative system.&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SdBmixjjrhI/AAAAAAAAAvc/O-M2nThcCXI/s1600-h/nin-bsod.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318863907528617490" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SdBmixjjrhI/AAAAAAAAAvc/O-M2nThcCXI/s320/nin-bsod.jpg" style="cursor: pointer; display: block; height: 240px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h3&gt;Prepare the environment&lt;/h3&gt;&lt;br /&gt;The fast way to prepare the environment is to download &lt;a href="http://wascana.sourceforge.net/"&gt;Waskana Desktop Developer&lt;/a&gt;, an Eclipse distribution that includes all you need to start write c++ applications on windows. If you choose to install Waskana you can skip next sections and go directly to install Gtkmm for windows.&lt;br /&gt;If you prefer a custom environment let's start. What we need is:&lt;br /&gt;&lt;lu&gt;&lt;br /&gt;&lt;/lu&gt;&lt;br /&gt;&lt;li&gt;Java runtime (if not already installed)&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Eclipse CDT&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;MinGW&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;MSys&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Gtkmm for windows&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Java runtime&lt;/h2&gt;&lt;br /&gt;Probably you have already installed some java runtime, on the rare case you have a virgin PC go to &lt;a href="http://www.java.com/"&gt;http://www.java.com&lt;/a&gt; and download latest version.&lt;br /&gt;&lt;h2&gt;Eclipse CDT&lt;/h2&gt;&lt;br /&gt;From Eclipse website on the &lt;a href="http://www.eclipse.org/downloads/"&gt;download section&lt;/a&gt; you can download directly the Eclipse version with CDT.&lt;br /&gt;The download is a zip archive, simply extract it on your preferred directory&lt;br /&gt;&lt;h2&gt;MinGW&lt;/h2&gt;&lt;br /&gt;For use GNU compiler on windows I prefer &lt;a href="http://www.mingw.org/"&gt;MinGW&lt;/a&gt;. For install MinGW go to the download page and download the latest &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=2435&amp;amp;package_id=240780"&gt;Automated MinGW Installer&lt;/a&gt;. This application is a wizard for download all desired packages.&lt;br /&gt;&lt;br /&gt;Welcome...&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SdB3KyXMrEI/AAAAAAAAAvk/KEI0Tqc_P8Q/s1600-h/inst-1.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318882187126025282" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SdB3KyXMrEI/AAAAAAAAAvk/KEI0Tqc_P8Q/s320/inst-1.jpg" style="cursor: pointer; display: block; height: 248px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Download and install, next...&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SdB3L95PnLI/AAAAAAAAAvs/eAlgy_VaKZM/s1600-h/inst-2.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318882207401483442" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SdB3L95PnLI/AAAAAAAAAvs/eAlgy_VaKZM/s320/inst-2.jpg" style="cursor: pointer; display: block; height: 248px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I agree...&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SdB3MK4QeeI/AAAAAAAAAv0/r7yiXYARLX4/s1600-h/inst-3.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318882210887006690" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SdB3MK4QeeI/AAAAAAAAAv0/r7yiXYARLX4/s320/inst-3.jpg" style="cursor: pointer; display: block; height: 248px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Current, next...&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SdB3MnzIJII/AAAAAAAAAv8/gREfD32OoyU/s1600-h/inst-4.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318882218650117250" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SdB3MnzIJII/AAAAAAAAAv8/gREfD32OoyU/s320/inst-4.jpg" style="cursor: pointer; display: block; height: 248px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This step require an interaction, from the checkbox list add "g++ compiler" and "MinGW Make", next...&lt;br /&gt;&lt;a href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SdB3NEVpP6I/AAAAAAAAAwE/j841H_BCMw4/s1600-h/inst-5.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318882226311085986" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SdB3NEVpP6I/AAAAAAAAAwE/j841H_BCMw4/s320/inst-5.jpg" style="cursor: pointer; display: block; height: 248px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Select installation directory. Is recommended to install MinGW on a directory without spaces, so do not install MinGW on "Program Files" or "My Documents", I use "C:\MinGW".&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SdB57P04uCI/AAAAAAAAAwM/s1UMtHtC5Ko/s1600-h/inst-6.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318885218692151330" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SdB57P04uCI/AAAAAAAAAwM/s1UMtHtC5Ko/s320/inst-6.jpg" style="cursor: pointer; display: block; height: 248px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Start menu, Install...&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SdB6aHyTpcI/AAAAAAAAAwU/0Ag7GonTtkc/s1600-h/inst-7.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318885749109794242" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SdB6aHyTpcI/AAAAAAAAAwU/0Ag7GonTtkc/s320/inst-7.jpg" style="cursor: pointer; display: block; height: 248px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The application start download...&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SdB-xMdvgmI/AAAAAAAAAwc/benPrhMHVDk/s1600-h/inst-8.JPG" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318890543549219426" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SdB-xMdvgmI/AAAAAAAAAwc/benPrhMHVDk/s320/inst-8.JPG" style="cursor: pointer; display: block; height: 106px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If your installation complete with the error "bad header checksum", like this:&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SdB_LtQ5W8I/AAAAAAAAAwk/tnjO4_Z4Rg4/s1600-h/inst-9-error.JPG" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318890999030307778" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SdB_LtQ5W8I/AAAAAAAAAwk/tnjO4_Z4Rg4/s320/inst-9-error.JPG" style="cursor: pointer; display: block; height: 248px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;you need to delete the archive (the file is located on the same directory of the installer) and try to restart installation, usually the problem is due to the sourceforge mirror selection. You can also try to download manually required package (and put the file on the same directory of the installer).&lt;br /&gt;&lt;br /&gt;If your installation compelete successfully...&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SdCGWCRu2KI/AAAAAAAAAws/04-45dZsw1E/s1600-h/inst-9-success.JPG" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5318898873051044002" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SdCGWCRu2KI/AAAAAAAAAws/04-45dZsw1E/s320/inst-9-success.JPG" style="cursor: pointer; display: block; height: 248px; margin: 0px auto 10px; text-align: center; width: 320px;" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When the MinGW installation is complete ensure that environment variables are correctly updated. The PATH variable must include the MinGW bin directory (for example "C:\MinGW\bin"), the lib varibale must include the MinGW lib directory (for example "C:\MinGW\lib" and the include variable must include the MinGW include directory (for eaxample "C:\MinGW\include").&lt;br /&gt;Other infos on &lt;a href="http://www.mingw.org/wiki/Getting_Started"&gt;MinGW Getting Started&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-327778465301471294?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/327778465301471294/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2010/09/draft-using-gtkmm-on-windows-with.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/327778465301471294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/327778465301471294'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2010/09/draft-using-gtkmm-on-windows-with.html' title='[DRAFT] Using Gtkmm on Windows with Eclipse CDT'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/SdBmixjjrhI/AAAAAAAAAvc/O-M2nThcCXI/s72-c/nin-bsod.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-3186952127682074204</id><published>2009-12-02T14:30:00.000+01:00</published><updated>2009-12-02T14:30:37.126+01:00</updated><title type='text'>Prototipo per Ubucompilator</title><content type='html'>Visto che Gusions sul &lt;a href="http://www.arresojas.it/dilemmi/cercasi-consigli-per-interfaccia-grafica-ubucompilator"&gt;suo blog&lt;/a&gt; cerca consigli sull'interfaccia di Ubucompilator, mi permetto di sottoporre questo prototipo:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SxZrZtEm2MI/AAAAAAAAA0U/PKubHNhALno/s1600-h/prototipo_main.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SxZrZtEm2MI/AAAAAAAAA0U/PKubHNhALno/s320/prototipo_main.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-3186952127682074204?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/3186952127682074204/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2009/12/prototipo-per-ubucompilator.html#comment-form' title='3 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/3186952127682074204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/3186952127682074204'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2009/12/prototipo-per-ubucompilator.html' title='Prototipo per Ubucompilator'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/SxZrZtEm2MI/AAAAAAAAA0U/PKubHNhALno/s72-c/prototipo_main.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-4462710410046717270</id><published>2009-11-12T10:42:00.003+01:00</published><updated>2009-11-12T10:55:13.999+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fun'/><title type='text'>Cheap multitouch</title><content type='html'>Come rendere multitouch un normale monitor LCD.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Calis svela in anteprima assoluta solo per KapoC++ un &lt;a href="https://addons.mozilla.org/it/firefox/"&gt;Add-on&lt;/a&gt; per firefox in grado di rendere multitouch un normale monitor LCD.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;La teconologia utilizzata è coperta dalla massima segretezza, l'unica informazione che sono riuscito a strappare è "l'importante non è quello che si vede ma quello che non si vede..." e dopo è scappato coperto da una nuvola di fumo.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-76e63c4a0c476749" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v2.nonxt4.googlevideo.com/videoplayback?id%3D76e63c4a0c476749%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1329938071%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D3869EF2A2B29AE787445DF2A2100B8564D87030F.3C43D5EFB487A7CCE9C1D395C2144BDF3C4EEB09%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D76e63c4a0c476749%26offsetms%3D5000%26itag%3Dw160%26sigh%3DXZNjyKainZQy_oZYVRirrYz6Kqs&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v2.nonxt4.googlevideo.com/videoplayback?id%3D76e63c4a0c476749%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1329938071%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D3869EF2A2B29AE787445DF2A2100B8564D87030F.3C43D5EFB487A7CCE9C1D395C2144BDF3C4EEB09%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D76e63c4a0c476749%26offsetms%3D5000%26itag%3Dw160%26sigh%3DXZNjyKainZQy_oZYVRirrYz6Kqs&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-4462710410046717270?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=76e63c4a0c476749&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/4462710410046717270/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2009/11/cheap-multitouch.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/4462710410046717270'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/4462710410046717270'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2009/11/cheap-multitouch.html' title='Cheap multitouch'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-5737886826141253183</id><published>2009-10-29T14:23:00.002+01:00</published><updated>2009-10-29T14:27:26.705+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ggredit'/><title type='text'>Intelligent connectors</title><content type='html'>Intelligent connector demo:&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-5b721f75a988c3b7" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v21.nonxt2.googlevideo.com/videoplayback?id%3D5b721f75a988c3b7%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1329938071%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D7E3C1B068B8FBAD73446C2C33C4D6222FAA2417B.A6FF3E390615C2DA94FD8868A99FF4CA34A89E0%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D5b721f75a988c3b7%26offsetms%3D5000%26itag%3Dw160%26sigh%3DAtIE7S95k4YaK09D5LyyUhqBg7o&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v21.nonxt2.googlevideo.com/videoplayback?id%3D5b721f75a988c3b7%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1329938071%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D7E3C1B068B8FBAD73446C2C33C4D6222FAA2417B.A6FF3E390615C2DA94FD8868A99FF4CA34A89E0%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D5b721f75a988c3b7%26offsetms%3D5000%26itag%3Dw160%26sigh%3DAtIE7S95k4YaK09D5LyyUhqBg7o&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-5737886826141253183?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=5b721f75a988c3b7&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/5737886826141253183/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2009/10/intelligent-connectors.html#comment-form' title='10 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5737886826141253183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5737886826141253183'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2009/10/intelligent-connectors.html' title='Intelligent connectors'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-5972780825332054431</id><published>2009-03-10T09:10:00.004+01:00</published><updated>2009-03-10T14:28:22.851+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='dia'/><category scheme='http://www.blogger.com/atom/ns#' term='gnome'/><title type='text'>Sta arrivando Dia 0.97</title><content type='html'>Sembra che qualcosa finalmente si stia muovendo in &lt;a href="http://live.gnome.org/Dia"&gt;Dia&lt;/a&gt;, lo storico editor di diagrammi di GNOME.&lt;br /&gt;Dopo due anni di silenzio, l'ultima versione, la 0.96.1, è datata 29/03/2007, finalmente una prerelease che preannuncia la 0.97.&lt;br /&gt;Questo silenzio, tralaltro, mi ha spinto a sviluppare un &lt;a href="http://kapo-cpp.blogspot.com/2009/02/ddraw-and-ggredit-002-alpha-release.html"&gt;mio editor di diagrammi&lt;/a&gt;, ma questa è un'altra storia.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://projects.gnome.org/dia/dia-0-97-coming-soon.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 602px; height: 469px;" src="http://projects.gnome.org/dia/dia-0-97-coming-soon.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;La nuova versione includerà molte novità, qualche informazione è disponibile nella mailing list del progetto: "&lt;a href="http://mail.gnome.org/archives/dia-list/2009-February/msg00048.html"&gt;dia-0.97-pre2 - get it while it is hot;)&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;Molti bug sono stati risolti, tra tutti sarà possibile premere il tasto &lt;span style="font-style:italic;"&gt;[Canc]&lt;/span&gt; mentre si modifica del testo senza per questo cancellare tutto l'oggetto, un baco imbarazzante che ci stiamo tenendo da due anni.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://projects.gnome.org/dia/dia-0.97-integrated-ui.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 900px; height: 640px;" src="http://projects.gnome.org/dia/dia-0.97-integrated-ui.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Degna di nota è l'introduzione di una nuova interfaccia grafica, che si affianca alla vecchia (multifinestre stile Gimp) ed è utilizzabile a discrezione dell'utente. La nuova interfaccia visualizza l'intera applicazione in un'unica finestra ed ogni documento viene aperto in un nuovo tab. Questo rende l'aspetto di DIA più ordinato ed inoltre ne consente l'utilizzo sugli eeePC con Ubuntu NetBook Remix, usato dal sottoscritto, che massimizzando in automatico le finestre rende praticamente inutilizzabili tutte le applicazioni multifinestre.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SbZqzvfLFVI/AAAAAAAAAug/QhHKGVEviiE/s1600-h/01.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 229px;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SbZqzvfLFVI/AAAAAAAAAug/QhHKGVEviiE/s320/01.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5311550247683167570" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Un nuovo tool "Outline" consente di inserire del testo e ruotarlo specificando un'angolo nelle finestra delle proprietà. Con questo tool è inoltre possibile definire il colore del contorno ed il colore di riempimento del testo.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-5972780825332054431?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='text/html' href='http://mail.gnome.org/archives/dia-list/2009-February/msg00048.html' length='0'/><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/5972780825332054431/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2009/03/sta-arrivando-dia-097.html#comment-form' title='103 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5972780825332054431'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5972780825332054431'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2009/03/sta-arrivando-dia-097.html' title='Sta arrivando Dia 0.97'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_sQJ1m4QDkME/SbZqzvfLFVI/AAAAAAAAAug/QhHKGVEviiE/s72-c/01.JPG' height='72' width='72'/><thr:total>103</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-8725324733121406211</id><published>2009-02-09T11:58:00.003+01:00</published><updated>2009-02-09T12:02:45.286+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ggredit'/><title type='text'>DDraw and GGredit 0.0.2 alpha release</title><content type='html'>A new ddraw release 0.0.2 alpha is now available, &lt;a href="http://sourceforge.net/project/platformdownload.php?group_id=215891"&gt;here the debian packages hosted by SourceForge&lt;/a&gt;. &lt;br /&gt; &lt;br /&gt;This is an alpha version and is not possible to create the large number of diagrams, anyway the project seems to take shape. &lt;br /&gt; &lt;br /&gt;This version include many new features and fix major bugs: &lt;br /&gt; &lt;br /&gt;- a new tool allow to draw regular polygons specifying sides number &lt;br /&gt;- all objects can be easily rotated when selected using a drag point &lt;br /&gt;- fill and stroke color can have an alpha value from 0 to 100 for change opacity &lt;br /&gt;- active page can be exported to SVG or PDF file using the File/Export menu option &lt;br /&gt;- text is rendered using fill and stroke properties instead of the simple text color &lt;br /&gt;- images can be stretched using the stretch property &lt;br /&gt;- fill properties and stroke propeties are shown grouped on the properties browser &lt;br /&gt;- various bugs fixed &lt;br /&gt;&lt;br /&gt;Here a short video of this release:&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-10629424dfa198f3" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v12.nonxt8.googlevideo.com/videoplayback?id%3D10629424dfa198f3%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1329938071%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D2E2F7DEE59ECB08E8A5F7878D80C3B3B0255230.7A375B60231FB181C94F9D7E7836557077647D5%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D10629424dfa198f3%26offsetms%3D5000%26itag%3Dw160%26sigh%3DmVr-qoNRALm5EMEgmYTECDLXneg&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v12.nonxt8.googlevideo.com/videoplayback?id%3D10629424dfa198f3%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1329938071%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D2E2F7DEE59ECB08E8A5F7878D80C3B3B0255230.7A375B60231FB181C94F9D7E7836557077647D5%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D10629424dfa198f3%26offsetms%3D5000%26itag%3Dw160%26sigh%3DmVr-qoNRALm5EMEgmYTECDLXneg&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-8725324733121406211?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=10629424dfa198f3&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/8725324733121406211/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2009/02/ddraw-and-ggredit-002-alpha-release.html#comment-form' title='7 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/8725324733121406211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/8725324733121406211'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2009/02/ddraw-and-ggredit-002-alpha-release.html' title='DDraw and GGredit 0.0.2 alpha release'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-6681371250167837727</id><published>2009-01-09T07:53:00.019+01:00</published><updated>2009-01-09T14:43:01.422+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='cairomm'/><category scheme='http://www.blogger.com/atom/ns#' term='ggredit'/><title type='text'>Drawing regular polygons on Cairo</title><content type='html'>The next object I want to implement on GGredit is an object that allow to draw a generic &lt;a href="http://en.wikipedia.org/wiki/Regular_polygon"&gt;regular polygon&lt;/a&gt;, the user can define the number of sides and GGredit draw this polygon (&lt;a href="http://www.inkscape.org/"&gt;inkscape&lt;/a&gt; have a similar tool named "Polygon and Star").&lt;br /&gt;&lt;div align="center"&gt;&lt;div id="kapo-image"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SWb-VrxeA2I/AAAAAAAAAr8/SwSnwBuRN3s/s1600-h/800px-The_Pentagon_US_Department_of_Defense_building.jpg"&gt;&lt;img src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SWb-VrxeA2I/AAAAAAAAAr8/SwSnwBuRN3s/s320/800px-The_Pentagon_US_Department_of_Defense_building.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5289194460874146658" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;The Ellipse&lt;/h3&gt;&lt;br /&gt;Once you know how to draw an ellipse is easy to draw regular polygons or stars. For draw an ellipse we need on input:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;double cx&lt;/b&gt;: the x center of the ellipse&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;double cy&lt;/b&gt;: the y center of the ellipse&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;double rx&lt;/b&gt;: the horizzontal radius of the ellipse&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;b&gt;double ry&lt;/b&gt;: the vertical radius of the ellipse&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;These values can be easily evaluated starting from a rectangle.&lt;br /&gt;Since the size of a full circle is 2π, we need a loop that draw all point between 0 and 2 * M_PI (M_PI is the constant on cmath for &lt;a href="http://en.wikipedia.org/wiki/Pi"&gt;PI&lt;/a&gt;).&lt;br /&gt;&lt;div id="kapo-code"&gt;&lt;pre&gt;&lt;br /&gt;#include &lt;cmath&gt;&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;for (double alpha = 0; alpha &lt;= 2 * M_PI; aplha+=0.1)&lt;br /&gt;{&lt;br /&gt;  double px = cx + rx * cos (alpha);&lt;br /&gt;  double py = cy + ry * sin (alpha);&lt;br /&gt;  // px, py is current point&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;For loop radians I use a step of 0.1, this is only for simplify since in effect we have infinite points on an ellipse.&lt;br /&gt;Draw al points on Cairo is a beat more sophisticated since we need to define a path using &lt;a href="http://www.cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html#4086700b5f780fd3fb94bea941895022"&gt;move_to()&lt;/a&gt; and &lt;a href="http://www.cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html#e305a9f8a79cc0e0693393a940ee1de8"&gt;line_to()&lt;/a&gt; functions. So we need to call the move_to() function for the first point out of the loop and the call all the line_to() functions on the loop.&lt;br /&gt;&lt;div id="kapo-code"&gt;&lt;pre&gt;&lt;br /&gt;double alpha = 0;&lt;br /&gt;double alpha_step = 0.1;&lt;br /&gt;&lt;br /&gt;// First point&lt;br /&gt;double px1 = cx + rx * cos (alpha);&lt;br /&gt;double py1 = cy + ry * sin (alpha);&lt;br /&gt;cr-&gt;move_to (px1, py1); // cr is the cairo context&lt;br /&gt;&lt;br /&gt;for (double alpha = 0; alpha &lt;= 2 * M_PI; aplha+=alpha_step)&lt;br /&gt;{&lt;br /&gt;  double px = cx + rx * cos (alpha);&lt;br /&gt;  double py = cy + ry * sin (alpha);&lt;br /&gt;  cr-&gt;line_to (px, py); // cr is the cairo context&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;This is only theory, Cairo have the &lt;a href="http://www.cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html#aa96080beea581244f0a3838fb7c9ee6"&gt;arc()&lt;/a&gt; function for draw ellipses.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Polygons&lt;/h3&gt;&lt;br /&gt;The step of the loop is the key for draw polygons. If whe take only three equidistant points of an ellipse we have a triangle. For get three equidistant points we simply need to evaluate the alpha_step using: &lt;b&gt;(M_PI * 2) / 3&lt;/b&gt;. &lt;br /&gt;&lt;div align="center"&gt;&lt;div id="kapo-image"&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SWdSbACAP9I/AAAAAAAAAsE/MMxrTktABKI/s1600-h/triangle.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 300px; height: 300px;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SWdSbACAP9I/AAAAAAAAAsE/MMxrTktABKI/s320/triangle.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5289286911188287442" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;We can generically evaluate the step needed for draw a polygon by dividing &lt;b&gt;M_PI * 2&lt;/b&gt; for the number of sides of the required polygon: &lt;b&gt;(M_PI * 2) / sides_count&lt;/b&gt;.&lt;br /&gt;This is a Gtk::DrawingArea inherited widget that display a polygon:&lt;br /&gt;&lt;div id="kapo-code"&gt;&lt;pre&gt;&lt;br /&gt;/*&lt;br /&gt; * PolygonView.h&lt;br /&gt; *&lt;br /&gt; *  Created on: Sep 9, 2008&lt;br /&gt; *      Author: user&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;#ifndef POLYGONVIEW_H_&lt;br /&gt;#define POLYGONVIEW_H_&lt;br /&gt;&lt;br /&gt;#include &lt;gtkmm.h&gt;&lt;br /&gt;&lt;br /&gt;class PolygonView : public Gtk::DrawingArea&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt; PolygonView();&lt;br /&gt; virtual ~PolygonView();&lt;br /&gt;&lt;br /&gt; double getSidesCount() const { return sides_count_; };&lt;br /&gt; void setSidesCound(double value) { sides_count_ = value; };&lt;br /&gt;&lt;br /&gt; void rotate(double cx, double cy, double radians);&lt;br /&gt; void saveSvg(const std::string&amp; file_name);&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt; Gdk::Color back_color_;&lt;br /&gt; Gdk::Color stroke_color_;&lt;br /&gt; Gdk::Color fill_color_;&lt;br /&gt; Gdk::Color help_color_;&lt;br /&gt; Gdk::Color rotation_color_;&lt;br /&gt; Gdk::Rectangle polygon_bounds_;&lt;br /&gt; double rotation_center_x_;&lt;br /&gt; double rotation_center_y_;&lt;br /&gt; double rotation_degrees_;&lt;br /&gt; double sides_count_;&lt;br /&gt; bool draw_help_;&lt;br /&gt; bool draw_rotation_;&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt; bool on_expose_event(GdkEventExpose* event);&lt;br /&gt;&lt;br /&gt; void draw(Cairo::RefPtr&lt; Cairo::Context &gt; context_ref);&lt;br /&gt; void draw_ellipse(Cairo::RefPtr&lt; Cairo::Context &gt; context_ref, const Gdk::Rectangle&amp; bounds);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif /* POLYGONVIEW_H_ */&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;PolygonView.h&lt;br /&gt;&lt;br /&gt;&lt;div id="kapo-code"&gt;&lt;pre&gt;&lt;br /&gt;/*&lt;br /&gt; * PolygonView.cpp&lt;br /&gt; *&lt;br /&gt; *  Created on: Sep 9, 2008&lt;br /&gt; *      Author: user&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;#include "PolygonView.h"&lt;br /&gt;&lt;br /&gt;#include &lt;iostream&gt;&lt;br /&gt;#include &lt;cmath&gt;&lt;br /&gt;&lt;br /&gt;PolygonView::PolygonView() :&lt;br /&gt; back_color_( "white" ),&lt;br /&gt; stroke_color_( "black" ),&lt;br /&gt; fill_color_( "white" ),&lt;br /&gt; help_color_( "gray" ),&lt;br /&gt; rotation_color_( "red" ),&lt;br /&gt; polygon_bounds_( 20, 20, 200, 200),&lt;br /&gt; rotation_center_x_( 110 ),&lt;br /&gt; rotation_center_y_( 110 ),&lt;br /&gt; rotation_degrees_( 0 ),&lt;br /&gt; sides_count_( 5 ),&lt;br /&gt; draw_help_( true ),&lt;br /&gt; draw_rotation_( false )&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PolygonView::~PolygonView()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void PolygonView::rotate(double cx, double cy, double radians)&lt;br /&gt;{&lt;br /&gt; rotation_center_x_ = cx;&lt;br /&gt; rotation_center_y_ = cy;&lt;br /&gt; rotation_degrees_ = radians;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;bool PolygonView::on_expose_event(GdkEventExpose *event)&lt;br /&gt;{&lt;br /&gt; Glib::RefPtr&lt; Gdk::Window &gt; window_ref = get_window();&lt;br /&gt;&lt;br /&gt; if (window_ref)&lt;br /&gt; {&lt;br /&gt;  Gtk::Allocation allocation = get_allocation();&lt;br /&gt;&lt;br /&gt;  Cairo::RefPtr&lt; Cairo::Context &gt; context_ref = window_ref-&gt;create_cairo_context();&lt;br /&gt;&lt;br /&gt;  if (event)&lt;br /&gt;  {&lt;br /&gt;   context_ref-&gt;rectangle (event-&gt;area.x, event-&gt;area.y, event-&gt;area.width, event-&gt;area.height);&lt;br /&gt;   context_ref-&gt;clip();&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Draw background&lt;br /&gt;  context_ref-&gt;set_source_rgb (back_color_.get_red_p(),&lt;br /&gt;    back_color_.get_green_p(),&lt;br /&gt;    back_color_.get_blue_p());&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;rectangle (0, 0, allocation.get_width(), allocation.get_height());&lt;br /&gt;  context_ref-&gt;fill();&lt;br /&gt;&lt;br /&gt;  draw (context_ref);&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; return true;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void PolygonView::saveSvg(const std::string&amp; file_name)&lt;br /&gt;{&lt;br /&gt; double wx =  polygon_bounds_.get_width() + polygon_bounds_.get_x() * 2;&lt;br /&gt; double wy =  polygon_bounds_.get_height() + polygon_bounds_.get_y() * 2;&lt;br /&gt; Cairo::RefPtr&lt; Cairo::SvgSurface &gt; surface_ref = Cairo::SvgSurface::create ( file_name, wx, wy);&lt;br /&gt; Cairo::RefPtr&lt; Cairo::Context &gt; context_ref = Cairo::Context::create (surface_ref);&lt;br /&gt;&lt;br /&gt; draw (context_ref);&lt;br /&gt;&lt;br /&gt; context_ref-&gt;show_page();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void PolygonView::draw(Cairo::RefPtr&lt; Cairo::Context &gt; context_ref)&lt;br /&gt;{&lt;br /&gt; // Draw not rotated vector&lt;br /&gt; if (draw_rotation_)&lt;br /&gt; {&lt;br /&gt;  context_ref-&gt;save();&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;set_source_rgba (help_color_.get_red_p(),&lt;br /&gt;    help_color_.get_green_p(),&lt;br /&gt;    help_color_.get_blue_p(), 0.5);&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;move_to (rotation_center_x_, rotation_center_y_);&lt;br /&gt;  context_ref-&gt;line_to (rotation_center_x_ + 20, rotation_center_y_);&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;restore();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; context_ref-&gt;save();&lt;br /&gt;&lt;br /&gt; // Set rotation&lt;br /&gt; context_ref-&gt;translate (rotation_center_x_, rotation_center_y_);&lt;br /&gt; context_ref-&gt;rotate (rotation_degrees_);&lt;br /&gt; context_ref-&gt;translate (-rotation_center_x_, -rotation_center_y_);&lt;br /&gt;&lt;br /&gt; // Draw polygon&lt;br /&gt; double rx = polygon_bounds_.get_width() / 2.0;&lt;br /&gt; double ry = polygon_bounds_.get_height() / 2.0;&lt;br /&gt; double cx = polygon_bounds_.get_x() + rx;&lt;br /&gt; double cy = polygon_bounds_.get_y() + ry;&lt;br /&gt;&lt;br /&gt; // Define first vertex&lt;br /&gt; double alpha = 0.0;&lt;br /&gt; context_ref-&gt;move_to (cx + rx * cos(alpha), cy + ry * sin(alpha));&lt;br /&gt;&lt;br /&gt; // Define other vertexes&lt;br /&gt; double alpha_step = 2 * M_PI / sides_count_;&lt;br /&gt; for (int i = 1; i &lt; sides_count_; i++)&lt;br /&gt; {&lt;br /&gt;  alpha += alpha_step;&lt;br /&gt;  context_ref-&gt;line_to (cx + rx * cos(alpha), cy + ry * sin(alpha));&lt;br /&gt; }&lt;br /&gt; context_ref-&gt;close_path();&lt;br /&gt;&lt;br /&gt; // Stroke and fill polygon&lt;br /&gt; context_ref-&gt;set_source_rgb (stroke_color_.get_red_p(),&lt;br /&gt;   stroke_color_.get_green_p(),&lt;br /&gt;   stroke_color_.get_blue_p());&lt;br /&gt;&lt;br /&gt; context_ref-&gt;stroke_preserve();&lt;br /&gt;&lt;br /&gt; context_ref-&gt;set_source_rgb (fill_color_.get_red_p(),&lt;br /&gt;   fill_color_.get_green_p(),&lt;br /&gt;   fill_color_.get_blue_p());&lt;br /&gt;&lt;br /&gt; context_ref-&gt;fill();&lt;br /&gt;&lt;br /&gt; if (draw_rotation_)&lt;br /&gt; {&lt;br /&gt;  // Draw rotation center&lt;br /&gt;  context_ref-&gt;set_source_rgba (rotation_color_.get_red_p(),&lt;br /&gt;    rotation_color_.get_green_p(),&lt;br /&gt;    rotation_color_.get_blue_p(), 0.5);&lt;br /&gt;&lt;br /&gt;  Gdk::Rectangle rot_center (rotation_center_x_ - 3, rotation_center_y_ - 3, 6, 6);&lt;br /&gt;&lt;br /&gt;  draw_ellipse (context_ref, rot_center);&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;move_to (rotation_center_x_, rotation_center_y_ - 6);&lt;br /&gt;  context_ref-&gt;line_to (rotation_center_x_, rotation_center_y_ + 6);&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;move_to (rotation_center_x_ - 6, rotation_center_y_);&lt;br /&gt;  context_ref-&gt;line_to (rotation_center_x_ + 6, rotation_center_y_);&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;move_to (rotation_center_x_, rotation_center_y_);&lt;br /&gt;  context_ref-&gt;line_to (rotation_center_x_ + 20, rotation_center_y_);&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; if (draw_help_)&lt;br /&gt; {&lt;br /&gt;  // Draw center&lt;br /&gt;  context_ref-&gt;set_source_rgba (help_color_.get_red_p(),&lt;br /&gt;    help_color_.get_green_p(),&lt;br /&gt;    help_color_.get_blue_p(), 0.5);&lt;br /&gt;&lt;br /&gt;  Gdk::Rectangle center (cx - 3, cy - 3, 6, 6);&lt;br /&gt;&lt;br /&gt;  draw_ellipse (context_ref, center);&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;move_to (cx, cy - 6);&lt;br /&gt;  context_ref-&gt;line_to (cx, cy + 6);&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;move_to (cx - 6, cy);&lt;br /&gt;  context_ref-&gt;line_to (cx + 6, cy);&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  // Draw 0, M_PI/2, M_PI, M_PI/2*3&lt;br /&gt;  context_ref-&gt;move_to (cx + (rx - 3) * cos(0.0), cy + (ry - 3) * sin(0.0));&lt;br /&gt;  context_ref-&gt;line_to (cx + (rx + 3) * cos(0.0), cy + (ry + 3) * sin(0.0));&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;move_to (cx + (rx - 3) * cos(M_PI / 2.0), cy + (ry - 3) * sin(M_PI / 2.0));&lt;br /&gt;  context_ref-&gt;line_to (cx + (rx + 3) * cos(M_PI / 2.0), cy + (ry + 3) * sin(M_PI / 2.0));&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;move_to (cx + (rx - 3) * cos(M_PI), cy + (ry - 3) * sin(M_PI));&lt;br /&gt;  context_ref-&gt;line_to (cx + (rx + 3) * cos(M_PI), cy + (ry + 3) * sin(M_PI));&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  context_ref-&gt;move_to (cx + (rx - 3) * cos(M_PI / 2.0 * 3.0), cy + (ry - 3) * sin(M_PI / 2.0 * 3.0));&lt;br /&gt;  context_ref-&gt;line_to (cx + (rx + 3) * cos(M_PI / 2.0 * 3.0), cy + (ry + 3) * sin(M_PI / 2.0 * 3.0));&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt;&lt;br /&gt;  // Draw bounds ellipse&lt;br /&gt;  draw_ellipse (context_ref, polygon_bounds_);&lt;br /&gt;  context_ref-&gt;stroke();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; context_ref-&gt;restore();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void PolygonView::draw_ellipse(Cairo::RefPtr&lt; Cairo::Context &gt; context_ref, const Gdk::Rectangle&amp; bounds)&lt;br /&gt;{&lt;br /&gt; context_ref-&gt;save();&lt;br /&gt;&lt;br /&gt; context_ref-&gt;translate (bounds.get_x() + (bounds.get_width() / 2.0),&lt;br /&gt;   bounds.get_y() + (bounds.get_height() / 2.0));&lt;br /&gt;&lt;br /&gt; context_ref-&gt;scale (bounds.get_width() / 2.0,&lt;br /&gt;   bounds.get_height() / 2.0);&lt;br /&gt;&lt;br /&gt; context_ref-&gt;arc (0.0, 0.0, 1.0, 0.0, 2 * M_PI);&lt;br /&gt;&lt;br /&gt; context_ref-&gt;restore();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;PolygonView.cpp&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-6681371250167837727?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/6681371250167837727/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2009/01/drawing-regular-polygons-on-cairo.html#comment-form' title='4 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/6681371250167837727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/6681371250167837727'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2009/01/drawing-regular-polygons-on-cairo.html' title='Drawing regular polygons on Cairo'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/SWb-VrxeA2I/AAAAAAAAAr8/SwSnwBuRN3s/s72-c/800px-The_Pentagon_US_Department_of_Defense_building.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-1320727262716280839</id><published>2009-01-07T12:02:00.003+01:00</published><updated>2009-01-08T08:22:42.834+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ggredit'/><title type='text'>GGredit web site is up</title><content type='html'>Today I upload the first &lt;a href="http://ggredit.sourceforge.net/"&gt;web site of GGredit&lt;/a&gt; on SourceForge.&lt;br /&gt;&lt;br /&gt;Here you can find also the first downloadable package, so now you can try DDraw the diagram editor.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-1320727262716280839?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/1320727262716280839/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2009/01/ggredid-web-site-is-up.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/1320727262716280839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/1320727262716280839'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2009/01/ggredid-web-site-is-up.html' title='GGredit web site is up'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-1725263647033764362</id><published>2008-12-23T16:20:00.002+01:00</published><updated>2008-12-23T16:51:24.453+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ggredit'/><title type='text'>GGredit Demo</title><content type='html'>Just some day before Christmas here is a short video that show an overview of GGredit.&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-ec4669b3a19e914b" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v21.nonxt7.googlevideo.com/videoplayback?id%3Dec4669b3a19e914b%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1329938071%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D48DDE3C9790F46A0A5CB542D79DA12AD4E2A2F65.54697F077C6BC2BEBCC50BFB6CF87245AB2F09AA%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Dec4669b3a19e914b%26offsetms%3D5000%26itag%3Dw160%26sigh%3DbhOKPtsa3z5sH175WKq4nGjYIF4&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v21.nonxt7.googlevideo.com/videoplayback?id%3Dec4669b3a19e914b%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1329938071%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D48DDE3C9790F46A0A5CB542D79DA12AD4E2A2F65.54697F077C6BC2BEBCC50BFB6CF87245AB2F09AA%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Dec4669b3a19e914b%26offsetms%3D5000%26itag%3Dw160%26sigh%3DbhOKPtsa3z5sH175WKq4nGjYIF4&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;I would have liked to release this pre-alpha version before Christmas but I need some day more.&lt;br /&gt;In the video you can see the main features:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;shape drawing&lt;/li&gt;&lt;li&gt;edit properties&lt;/li&gt;&lt;li&gt;shape selection&lt;/li&gt;&lt;li&gt;connectors&lt;/li&gt;&lt;li&gt;pages management&lt;/li&gt;&lt;li&gt;shape resize&lt;/li&gt;&lt;li&gt;snap lines alignment&lt;/li&gt;&lt;li&gt;clipboard management&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Stay tuned for the first GGredit release...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-1725263647033764362?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=ec4669b3a19e914b&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/1725263647033764362/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/12/ggredit-demo.html#comment-form' title='2 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/1725263647033764362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/1725263647033764362'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/12/ggredit-demo.html' title='GGredit Demo'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-2594713910384062187</id><published>2008-10-31T07:59:00.004+01:00</published><updated>2008-10-31T15:45:29.724+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Inheriting from Gtk::CellRendererCombo</title><content type='html'>On ggredit the user can change properties of the selected object using a properties browser, implemented using the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1TreeView.html"&gt;Gtk::TreeView&lt;/a&gt; object. On my previous post &lt;a href="http://kapo-cpp.blogspot.com/2008/05/different-cellrenderers-on-same-column.html"&gt;"Different CellRenderers on the same Column"&lt;/a&gt; I explain the way I use for renderer each property with a different cell-renderer. Later I see that the deceased &lt;a href="http://crow-designer.sourceforge.net/"&gt;crow designer&lt;/a&gt; use the same method.&lt;br /&gt;For select enumeration values (i.e. alignment can be left, right or center) I would like to use a &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRendererCombo.html"&gt;Gtk::CellRendererCombo&lt;/a&gt;, but my derived class never start editing. In effect a simple Gtk::CellRendererCombo inherited class like this:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;font color="0000ff"&gt;&lt;strong&gt;#include &lt;font color="#008000"&gt;&amp;lt;gtkmm.h&amp;gt;&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;class&lt;/strong&gt; &lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt; &lt;font color="4444FF"&gt;:&lt;/font&gt; &lt;strong&gt;public&lt;/strong&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;CellRendererCombo&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt; &lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;  &lt;font color="#2040a0"&gt;Glib&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;ObjectBase&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;strong&gt;typeid&lt;/strong&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;,&lt;br /&gt;  &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;CellRendererCombo&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;strong&gt;virtual&lt;/strong&gt; ~&lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;never start edit. On the gtkmm mailing list someone ask for this &lt;a href="http://mail.gnome.org/archives/gtkmm-list/2007-February/msg00104.html"&gt;"subclassing Gtk::CellRendererCombo"&lt;/a&gt; issue but no one answer.&lt;br /&gt;I start to write my own combo as a custom cell renderer, following the &lt;a href="http://svn.gnome.org/viewvc/gtkmm-documentation/trunk/examples/others/cellrenderercustom/"&gt;gtkmm example&lt;/a&gt;. At the end the custom cell renderer result a poor combo.&lt;br /&gt;So I come back to the Gtk::CellRendererCombo, first I look at the gtkmm source. This is the constructor of the CellRendererCombo:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;font color="#2040a0"&gt;CellRendererCombo&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;CellRendererCombo&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;  &lt;font color="#444444"&gt;// Mark this class as non-derived to allow C++ vfuncs to be skipped.&lt;/font&gt;&lt;br /&gt;  &lt;font color="#2040a0"&gt;Glib&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;ObjectBase&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;0&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;,&lt;br /&gt;  &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;CellRendererText&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;Glib&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;ConstructParams&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;cellrenderercombo_class_&lt;/font&gt;.&lt;font color="#2040a0"&gt;init&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;  &lt;br /&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The CellRendererCombo call the &lt;a href="http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/classGlib_1_1ObjectBase.html"&gt;Glib::ObjectBase&lt;/a&gt; constructor passing &lt;span style="font-weight:bold;"&gt;zero&lt;/span&gt; instead of the &lt;span style="font-weight:bold;"&gt;typeid&lt;/span&gt; of the class.&lt;br /&gt;I try to revrite the CellRendererComboDerived class in this way:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;font color="0000ff"&gt;&lt;strong&gt;#include &lt;font color="#008000"&gt;&amp;lt;gtkmm.h&amp;gt;&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;class&lt;/strong&gt; &lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt; &lt;font color="4444FF"&gt;:&lt;/font&gt; &lt;strong&gt;public&lt;/strong&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;CellRendererCombo&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt; &lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;  &lt;font color="#2040a0"&gt;Glib&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;ObjectBase&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;0&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;,&lt;br /&gt;  &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;CellRendererCombo&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;strong&gt;virtual&lt;/strong&gt; ~&lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;and the cell renderer start work as expected, when the user click on the cell the edit start.&lt;br /&gt;&lt;h3&gt;The editing_started signal&lt;/h3&gt;&lt;br /&gt;For modify the combo used as editable from the CellRendererCombo we must catch the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRenderer.html#60b9029e8524d8908161c6e99e6bf31b"&gt;signal_editing_started&lt;/a&gt; signal.&lt;br /&gt;The gtkmm documentation says that this signal does not work yet (&lt;a href="http://bugzilla.gnome.org/show_bug.cgi?id=301597"&gt;Bug 301597&lt;/a&gt;). &lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SQrjBjvhRYI/AAAAAAAAAo8/1wb_TM9BOqQ/s1600-h/Cquote1.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 48px; height: 38px;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SQrjBjvhRYI/AAAAAAAAAo8/1wb_TM9BOqQ/s200/Cquote1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5263268730449773954" /&gt;&lt;/a&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SQrjLNsTqsI/AAAAAAAAApE/k0LhMRl332E/s1600-h/Cquote2.png"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 48px; height: 38px;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SQrjLNsTqsI/AAAAAAAAApE/k0LhMRl332E/s200/Cquote2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5263268896329411266" /&gt;&lt;/a&gt;&lt;span style="font-style:italic;"&gt;Note that this signal does not work yet in gtkmm. See http://bugzilla.gnome.org/show_bug.cgi?id=301597&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I try to use it:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;font color="0000ff"&gt;&lt;strong&gt;#include &lt;font color="#008000"&gt;&amp;lt;gtkmm.h&amp;gt;&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="0000ff"&gt;&lt;strong&gt;#include &lt;font color="#008000"&gt;&amp;lt;iostream&amp;gt;&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;class&lt;/strong&gt; &lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt; &lt;font color="4444FF"&gt;:&lt;/font&gt; &lt;strong&gt;public&lt;/strong&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;CellRendererCombo&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;public&lt;/strong&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt; &lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;br /&gt;  &lt;font color="#2040a0"&gt;Glib&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;ObjectBase&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#FF0000"&gt;0&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;,&lt;br /&gt;  &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;CellRendererCombo&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;  &lt;strong&gt;this&lt;/strong&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;signal_editing_started&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;.&lt;font color="#2040a0"&gt;connect&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;br /&gt;    &lt;font color="#2040a0"&gt;sigc&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;mem_fun&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;strong&gt;this&lt;/strong&gt;, &lt;font color="4444FF"&gt;&amp;amp;&lt;/font&gt;&lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;on_editing_started&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;strong&gt;virtual&lt;/strong&gt; ~&lt;font color="#2040a0"&gt;CellRendererComboDerived&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;strong&gt;virtual&lt;/strong&gt; &lt;strong&gt;void&lt;/strong&gt; &lt;font color="#2040a0"&gt;on_editing_started&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;CellEditable&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt; &lt;font color="#2040a0"&gt;editable&lt;/font&gt;, &lt;strong&gt;const&lt;/strong&gt; &lt;font color="#2040a0"&gt;Glib&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;ustring&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;amp;&lt;/font&gt; &lt;font color="#2040a0"&gt;path&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;  &lt;font color="#2040a0"&gt;std&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;cout&lt;/font&gt; &lt;font color="4444FF"&gt;&amp;lt;&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;lt;&lt;/font&gt; &lt;font color="#008000"&gt;&amp;quot;Editing started editable: &amp;quot;&lt;/font&gt; &lt;font color="4444FF"&gt;&amp;lt;&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;lt;&lt;/font&gt; editable &lt;font color="4444FF"&gt;&amp;lt;&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;lt;&lt;/font&gt; &lt;font color="#2040a0"&gt;std&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;endl&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;the signal is emitted but the editable pointer is always null. &lt;br /&gt;Murray Cumming on Bugzilla tell us to use the C API (&lt;a href="http://library.gnome.org/devel/gobject/unstable/gobject-Signals.html#g-signal-connect"&gt;g_signal_connect()&lt;/a&gt;). I never use the C API, so I first have a look at how to use &lt;span style="font-weight:bold;"&gt;g_signal_connect()&lt;/span&gt;, we have to give a callback to this function, and the callback must be a static function. So we can not pass a class member function, but we can pass a raw &lt;span style="font-weight:bold;"&gt;gpointer&lt;/span&gt; parameter and use this for invoke a class member function. The code may be more clear, this is the header:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#ifndef CELLRENDERERCOMBODERIVED_H_&lt;br /&gt;#define CELLRENDERERCOMBODERIVED_H_&lt;br /&gt;&lt;br /&gt;#include &amp;lt;gtkmm.h&amp;gt;&lt;br /&gt;&lt;br /&gt;class CellRendererComboDerived : public Gtk::CellRendererCombo&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    CellRendererComboDerived();&lt;br /&gt;    virtual ~CellRendererComboDerived();&lt;br /&gt;&lt;br /&gt;    virtual void on_editing_started(Gtk::ComboBox* combo_ptr, const Glib::ustring&amp;amp; path);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif /* CELLRENDERERCOMBODERIVED_H_ */&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;and this is the implementation:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#include &amp;quot;CellRendererComboDerived.h&amp;quot;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;br /&gt;void cb_editing_started(GtkCellRenderer* cell,&lt;br /&gt;                        GtkCellEditable* editable,&lt;br /&gt;                        const gchar* path,&lt;br /&gt;                        gpointer data)&lt;br /&gt;{&lt;br /&gt;    reinterpret_cast&amp;lt; CellRendererComboDerived* &amp;gt;(data)-&amp;gt;on_editing_started (&lt;br /&gt;            Glib::wrap(reinterpret_cast&amp;lt; GtkComboBox* &amp;gt;(editable), true), path);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;CellRendererComboDerived::CellRendererComboDerived() :&lt;br /&gt;    Glib::ObjectBase (0),&lt;br /&gt;    Gtk::CellRendererCombo()&lt;br /&gt;{&lt;br /&gt;    g_signal_connect (this-&amp;gt;gobj(), &amp;quot;editing-started&amp;quot;, G_CALLBACK(cb_editing_started), (gpointer)this);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;CellRendererComboDerived::~CellRendererComboDerived()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void CellRendererComboDerived::on_editing_started(Gtk::ComboBox* combo_ptr, const Glib::ustring&amp;amp; path)&lt;br /&gt;{&lt;br /&gt;    std::cout &amp;lt;&amp;lt; &amp;quot;Editing started columns: &amp;quot; &amp;lt;&amp;lt; combo_ptr-&amp;gt;get_model()-&amp;gt;get_n_columns() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;On the constructor we use &lt;span style="font-weight:bold;"&gt;g_signal_connect()&lt;/span&gt; for connect the function &lt;span style="font-weight:bold;"&gt;cb_editing_started&lt;/span&gt; to the signal &lt;span style="font-weight:bold;"&gt;editing-started&lt;/span&gt;, and we give also the &lt;span style="font-weight:bold;"&gt;this&lt;/span&gt; pointer.&lt;br /&gt;Whe the signal was emitted the function cb_editing_started was called, the function receive on the &lt;span style="font-weight:bold;"&gt;data&lt;/span&gt; parameter the pointer we give on the contructor. So the function cast the pointer to the &lt;span style="font-weight:bold;"&gt;CellRendererComboDerived&lt;/span&gt; class. For create a gtkmm Gtk::ComboBox class from the &lt;span style="font-weight:bold;"&gt;GtkCellEditable &lt;/span&gt;we can use the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1ComboBox.html#da4ea19b874086ba879aa6d3df0469f5"&gt;Glib::wrap()&lt;/a&gt; function.&lt;br /&gt;Now I need to implement this on ggredit...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-2594713910384062187?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/2594713910384062187/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/10/inheriting-from-gtkcellrenderercombo.html#comment-form' title='2 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/2594713910384062187'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/2594713910384062187'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/10/inheriting-from-gtkcellrenderercombo.html' title='Inheriting from Gtk::CellRendererCombo'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_sQJ1m4QDkME/SQrjBjvhRYI/AAAAAAAAAo8/1wb_TM9BOqQ/s72-c/Cquote1.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-5142571561635906948</id><published>2008-10-13T13:48:00.008+02:00</published><updated>2008-10-13T16:51:33.233+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='cairomm'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Drawing arrows with Cairo</title><content type='html'>For my ggredit project I need to draw connectors between objects, connectors are simple lines that can have an arrow head at the begin and/or at the end.&lt;br /&gt;But how to draw an arrowed line? We have to come back at school days, when we learn trigonometry.&lt;br /&gt;&lt;h3&gt;Basics&lt;/h3&gt;&lt;br /&gt;With the function &lt;a href="http://en.wikipedia.org/wiki/Atan2"&gt;atan2&lt;/a&gt; we can obtain the angle of the source line. Adding to this angle a defined sub-angle (arrow_degrees_) we can get the left and right angle of the arrow arms. With this two angles and using a defined lenght for the arrow arms (arrow_lenght_) we can finally achieve two points to use for perform drawing operations.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SPNK1WVRPiI/AAAAAAAAAoM/4NB7VCWtlpg/s1600-h/arrow.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SPNK1WVRPiI/AAAAAAAAAoM/4NB7VCWtlpg/s320/arrow.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5256627470459813410" /&gt;&lt;/a&gt;&lt;br /&gt;Now return to the future...we need to transform this on c++ code.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    void calcVertexes(double start_x, double start_y, double end_x, double end_y, double&amp;amp; x1, double&amp;amp; y1, double&amp;amp; x2, double&amp;amp; y2)&lt;br /&gt;    {&lt;br /&gt;        double angle = atan2 (end_y - start_y, end_x - start_x) + M_PI;&lt;br /&gt;&lt;br /&gt;        x1 = end_x + arrow_lenght_ * cos(angle - arrow_degrees_);&lt;br /&gt;        y1 = end_y + arrow_lenght_ * sin(angle - arrow_degrees_);&lt;br /&gt;        x2 = end_x + arrow_lenght_ * cos(angle + arrow_degrees_);&lt;br /&gt;        y2 = end_y + arrow_lenght_ * sin(angle + arrow_degrees_);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;h3&gt;Effective arrow object&lt;/h3&gt;&lt;br /&gt;We want to offer many kinds of arrows to the user, like on the wikipedia page for the &lt;a href="http://en.wikipedia.org/wiki/Arrow_(symbol)"&gt;symbol Arrow&lt;/a&gt;. I start to define this kind of arrows:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    enum ArrowStyle&lt;br /&gt;    {&lt;br /&gt;        ARROW_OPEN,&lt;br /&gt;        ARROW_SOLID,&lt;br /&gt;        ARROW_SOLID_FILLED,&lt;br /&gt;        ARROW_DIAMOND,&lt;br /&gt;        ARROW_DIAMOND_FILLED,&lt;br /&gt;        ARROW_CIRCLE,&lt;br /&gt;        ARROW_CIRCLE_FILLED&lt;br /&gt;    };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;But we do not like to put an &lt;a href="http://en.wikipedia.org/wiki/If-then-else"&gt;if-then-else&lt;/a&gt; evry time we need to draw the arrow. Is better to define an ArrowHead base class with an abstract method draw, and implements all different styles inheriting from the ArrowHead class.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SPNN_OyQU5I/AAAAAAAAAoU/uwj919gsrJI/s1600-h/arrow_class.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SPNN_OyQU5I/AAAAAAAAAoU/uwj919gsrJI/s320/arrow_class.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5256630938767479698" /&gt;&lt;/a&gt;&lt;br /&gt;The ArrowHead class is the base class.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class ArrowHead&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    enum ArrowStyle&lt;br /&gt;    {&lt;br /&gt;        ARROW_OPEN,&lt;br /&gt;        ARROW_SOLID,&lt;br /&gt;        ARROW_SOLID_FILLED,&lt;br /&gt;        ARROW_DIAMOND,&lt;br /&gt;        ARROW_DIAMOND_FILLED,&lt;br /&gt;        ARROW_CIRCLE,&lt;br /&gt;        ARROW_CIRCLE_FILLED&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    ArrowHead() :&lt;br /&gt;        arrow_lenght_( 15 ),&lt;br /&gt;        arrow_degrees_( 0.5 )&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    virtual ~ArrowHead()&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void calcVertexes(double start_x, double start_y, double end_x, double end_y, double&amp;amp; x1, double&amp;amp; y1, double&amp;amp; x2, double&amp;amp; y2)&lt;br /&gt;    {&lt;br /&gt;        double angle = atan2 (end_y - start_y, end_x - start_x) + M_PI;&lt;br /&gt;&lt;br /&gt;        x1 = end_x + arrow_lenght_ * cos(angle - arrow_degrees_);&lt;br /&gt;        y1 = end_y + arrow_lenght_ * sin(angle - arrow_degrees_);&lt;br /&gt;        x2 = end_x + arrow_lenght_ * cos(angle + arrow_degrees_);&lt;br /&gt;        y2 = end_y + arrow_lenght_ * sin(angle + arrow_degrees_);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    virtual void draw(Cairo::RefPtr&amp;lt; Cairo::Context &amp;gt; context_ref, double start_x, double start_y, double end_x, double end_y) = 0;&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt;    double arrow_lenght_;&lt;br /&gt;    double arrow_degrees_;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The Arrow object has two arrow head, for draw the begin and the end arrow.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    std::auto_ptr&amp;lt; ArrowHead &amp;gt; start_arrow_head_ptr_;&lt;br /&gt;    std::auto_ptr&amp;lt; ArrowHead &amp;gt; end_arrow_head_ptr_;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;we can use this object for draw the arrow:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;        start_arrow_head_ptr_-&amp;gt;draw (context_ref, x2, y2, x1, y1);&lt;br /&gt;        end_arrow_head_ptr_-&amp;gt;draw (context_ref, x1, y1, x2, y2);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we need to implements all classes for the effective renderering. We can start with the ARROW_OPEN, like this:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SPNY-WMkolI/AAAAAAAAAoc/TGYafogXIIw/s1600-h/ArrowOpen.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SPNY-WMkolI/AAAAAAAAAoc/TGYafogXIIw/s320/ArrowOpen.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5256643018204947026" /&gt;&lt;/a&gt;&lt;br /&gt;We simply need to draw two lines, the first line from end_x, end_y to x1, y1 the second line from end_x, end_y to x2, y2.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class ArrowOpen : public ArrowHead&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    ArrowOpen() :&lt;br /&gt;        ArrowHead(),&lt;br /&gt;        line_color_( &amp;quot;black&amp;quot; )&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    virtual ~ArrowOpen()&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void draw(Cairo::RefPtr&amp;lt; Cairo::Context &amp;gt; context_ref, double start_x, double start_y, double end_x, double end_y)&lt;br /&gt;    {&lt;br /&gt;        double x1;&lt;br /&gt;        double y1;&lt;br /&gt;        double x2;&lt;br /&gt;        double y2;&lt;br /&gt;&lt;br /&gt;        calcVertexes (start_x, start_y, end_x, end_y, x1, y1, x2, y2);&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;set_source_rgb (line_color_.get_red_p(), line_color_.get_blue_p(), line_color_.get_green_p());&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;move_to (end_x, end_y);&lt;br /&gt;        context_ref-&amp;gt;line_to (x1, y1);&lt;br /&gt;        context_ref-&amp;gt;stroke();&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;move_to (end_x, end_y);&lt;br /&gt;        context_ref-&amp;gt;line_to (x2, y2);&lt;br /&gt;        context_ref-&amp;gt;stroke();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt;    Gdk::Color line_color_;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We can implement the ARROW_SOLID, like this:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SPNZa6YRObI/AAAAAAAAAok/CUqyq15Bjs0/s1600-h/ArrowSolid.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SPNZa6YRObI/AAAAAAAAAok/CUqyq15Bjs0/s320/ArrowSolid.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5256643508954020274" /&gt;&lt;/a&gt;&lt;br /&gt;In this case we need to draw a triangle using the three vertexes: end_x, end_y; x1, y1 and x2, y2.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class ArrowSolid : public ArrowHead&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    ArrowSolid() :&lt;br /&gt;        ArrowHead(),&lt;br /&gt;        line_color_( &amp;quot;black&amp;quot; ),&lt;br /&gt;        fill_color_( &amp;quot;white&amp;quot; )&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    virtual ~ArrowSolid()&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void draw(Cairo::RefPtr&amp;lt; Cairo::Context &amp;gt; context_ref, double start_x, double start_y, double end_x, double end_y)&lt;br /&gt;    {&lt;br /&gt;        double x1;&lt;br /&gt;        double y1;&lt;br /&gt;        double x2;&lt;br /&gt;        double y2;&lt;br /&gt;&lt;br /&gt;        calcVertexes (start_x, start_y, end_x, end_y, x1, y1, x2, y2);&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;move_to (end_x, end_y);&lt;br /&gt;        context_ref-&amp;gt;line_to (x1, y1);&lt;br /&gt;        context_ref-&amp;gt;line_to (x2, y2);&lt;br /&gt;        context_ref-&amp;gt;close_path();&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;set_source_rgb (line_color_.get_red_p(), line_color_.get_blue_p(), line_color_.get_green_p());&lt;br /&gt;        context_ref-&amp;gt;stroke_preserve();&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;set_source_rgb (fill_color_.get_red_p(), fill_color_.get_blue_p(), fill_color_.get_green_p());&lt;br /&gt;        context_ref-&amp;gt;fill();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt;    Gdk::Color line_color_;&lt;br /&gt;    Gdk::Color fill_color_;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We can implement the ARROW_DIAMOND, like this:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SPNafRErOxI/AAAAAAAAAos/ML0Dy-Mi0Zg/s1600-h/ArrowDiamond.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SPNafRErOxI/AAAAAAAAAos/ML0Dy-Mi0Zg/s320/ArrowDiamond.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5256644683276958482" /&gt;&lt;/a&gt;&lt;br /&gt;In this case we need four vertexes, but for now we have only three vertexes. The fourth vertex is also a point on the source line (so for the same angle of the source line), I use this method:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class ArrowDiamond : public ArrowHead&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    ArrowDiamond() :&lt;br /&gt;        ArrowHead(),&lt;br /&gt;        line_color_( &amp;quot;black&amp;quot; ),&lt;br /&gt;        fill_color_( &amp;quot;white&amp;quot; )&lt;br /&gt;    {&lt;br /&gt;        arrow_lenght_ = 10.0;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    virtual ~ArrowDiamond()&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void draw(Cairo::RefPtr&amp;lt; Cairo::Context &amp;gt; context_ref, double start_x, double start_y, double end_x, double end_y)&lt;br /&gt;    {&lt;br /&gt;        double angle = atan2 (end_y - start_y, end_x - start_x) + M_PI;&lt;br /&gt;&lt;br /&gt;        double x1 = end_x + arrow_lenght_ * cos(angle - arrow_degrees_);&lt;br /&gt;        double y1 = end_y + arrow_lenght_ * sin(angle - arrow_degrees_);&lt;br /&gt;        double x2 = end_x + arrow_lenght_ * cos(angle + arrow_degrees_);&lt;br /&gt;        double y2 = end_y + arrow_lenght_ * sin(angle + arrow_degrees_);&lt;br /&gt;        double x3 = end_x + arrow_lenght_ * 2 * cos(angle);&lt;br /&gt;        double y3 = end_y + arrow_lenght_ * 2 * sin(angle);&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;move_to (end_x, end_y);&lt;br /&gt;        context_ref-&amp;gt;line_to (x1, y1);&lt;br /&gt;        context_ref-&amp;gt;line_to (x3, y3);&lt;br /&gt;        context_ref-&amp;gt;line_to (x2, y2);&lt;br /&gt;        context_ref-&amp;gt;close_path();&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;set_source_rgb (line_color_.get_red_p(), line_color_.get_blue_p(), line_color_.get_green_p());&lt;br /&gt;        context_ref-&amp;gt;stroke_preserve();&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;set_source_rgb (fill_color_.get_red_p(), fill_color_.get_blue_p(), fill_color_.get_green_p());&lt;br /&gt;        context_ref-&amp;gt;fill();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt;    Gdk::Color line_color_;&lt;br /&gt;    Gdk::Color fill_color_;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The last implementation is the ARROW_CIRCLE, like this:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SPNbZYZ-ypI/AAAAAAAAAo0/JbYaNQIHRDE/s1600-h/ArrowCircl.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SPNbZYZ-ypI/AAAAAAAAAo0/JbYaNQIHRDE/s320/ArrowCircl.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5256645681677781650" /&gt;&lt;/a&gt;&lt;br /&gt;For draw a circle we need to have the center and the radius. We can define a radius (using arrow_lenght_) and then put the center on the source line.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class ArrowCircle : public ArrowHead&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    ArrowCircle() :&lt;br /&gt;        ArrowHead(),&lt;br /&gt;        line_color_( &amp;quot;black&amp;quot; ),&lt;br /&gt;        fill_color_( &amp;quot;white&amp;quot; )&lt;br /&gt;    {&lt;br /&gt;        arrow_lenght_ = 7.0;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    virtual ~ArrowCircle()&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void draw(Cairo::RefPtr&amp;lt; Cairo::Context &amp;gt; context_ref, double start_x, double start_y, double end_x, double end_y)&lt;br /&gt;    {&lt;br /&gt;        double angle = atan2 (end_y - start_y, end_x - start_x) + M_PI;&lt;br /&gt;&lt;br /&gt;        double xc = end_x + arrow_lenght_ * cos(angle);&lt;br /&gt;        double yc = end_y + arrow_lenght_ * sin(angle);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;arc (xc, yc, arrow_lenght_, 0.0, 2 * M_PI);&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;set_source_rgb (line_color_.get_red_p(), line_color_.get_blue_p(), line_color_.get_green_p());&lt;br /&gt;        context_ref-&amp;gt;stroke_preserve();&lt;br /&gt;&lt;br /&gt;        context_ref-&amp;gt;set_source_rgb (fill_color_.get_red_p(), fill_color_.get_blue_p(), fill_color_.get_green_p());&lt;br /&gt;        context_ref-&amp;gt;fill();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt;    Gdk::Color line_color_;&lt;br /&gt;    Gdk::Color fill_color_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we need only two functions for set the begin and end arrow style:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void CairoArea::setStartArrowStyle(ArrowHead::ArrowStyle style)&lt;br /&gt;{&lt;br /&gt;    switch (style)&lt;br /&gt;    {&lt;br /&gt;        case ArrowHead::ARROW_OPEN:&lt;br /&gt;            start_arrow_head_ptr_ = std::auto_ptr&amp;lt; ArrowHead &amp;gt;( new ArrowOpen() );&lt;br /&gt;            break;&lt;br /&gt;        case ArrowHead::ARROW_SOLID_FILLED:&lt;br /&gt;            start_arrow_head_ptr_ = std::auto_ptr&amp;lt; ArrowHead &amp;gt;( new ArrowSolid() );&lt;br /&gt;            break;&lt;br /&gt;        case ArrowHead::ARROW_DIAMOND_FILLED:&lt;br /&gt;            start_arrow_head_ptr_ = std::auto_ptr&amp;lt; ArrowHead &amp;gt;( new ArrowDiamond() );&lt;br /&gt;            break;&lt;br /&gt;        case ArrowHead::ARROW_CIRCLE_FILLED:&lt;br /&gt;            start_arrow_head_ptr_ = std::auto_ptr&amp;lt; ArrowHead &amp;gt;( new ArrowCircle() );&lt;br /&gt;            break;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void CairoArea::setEndArrowStyle(ArrowHead::ArrowStyle style)&lt;br /&gt;{&lt;br /&gt;    switch (style)&lt;br /&gt;    {&lt;br /&gt;        case ArrowHead::ARROW_OPEN:&lt;br /&gt;            end_arrow_head_ptr_ = std::auto_ptr&amp;lt; ArrowHead &amp;gt;( new ArrowOpen() );&lt;br /&gt;            break;&lt;br /&gt;        case ArrowHead::ARROW_SOLID_FILLED:&lt;br /&gt;            end_arrow_head_ptr_ = std::auto_ptr&amp;lt; ArrowHead &amp;gt;( new ArrowSolid() );&lt;br /&gt;            break;&lt;br /&gt;        case ArrowHead::ARROW_DIAMOND_FILLED:&lt;br /&gt;            end_arrow_head_ptr_ = std::auto_ptr&amp;lt; ArrowHead &amp;gt;( new ArrowDiamond() );&lt;br /&gt;            break;&lt;br /&gt;        case ArrowHead::ARROW_CIRCLE_FILLED:&lt;br /&gt;            end_arrow_head_ptr_ = std::auto_ptr&amp;lt; ArrowHead &amp;gt;( new ArrowCircle() );&lt;br /&gt;            break;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;You can download the complete Eclipse project &lt;a href="http://www.box.net/shared/6zi2rzo72c"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-5142571561635906948?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/5142571561635906948/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/10/drawing-arrows-with-cairo.html#comment-form' title='5 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5142571561635906948'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5142571561635906948'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/10/drawing-arrows-with-cairo.html' title='Drawing arrows with Cairo'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_sQJ1m4QDkME/SPNK1WVRPiI/AAAAAAAAAoM/4NB7VCWtlpg/s72-c/arrow.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-5190055024088712434</id><published>2008-09-01T14:25:00.004+02:00</published><updated>2008-09-01T14:31:49.512+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>The prizes</title><content type='html'>Finally the eclipse prizes for the ganymede contest arrives...&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SLvgNFv5A5I/AAAAAAAAAeU/RtwOc_rxHYA/s1600-h/sborata.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SLvgNFv5A5I/AAAAAAAAAeU/RtwOc_rxHYA/s320/sborata.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5241029106861671314" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-5190055024088712434?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/5190055024088712434/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/09/prizes.html#comment-form' title='3 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5190055024088712434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5190055024088712434'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/09/prizes.html' title='The prizes'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_sQJ1m4QDkME/SLvgNFv5A5I/AAAAAAAAAeU/RtwOc_rxHYA/s72-c/sborata.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-1878848536618918510</id><published>2008-08-22T08:32:00.008+02:00</published><updated>2008-08-22T16:55:19.994+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='gnome'/><category scheme='http://www.blogger.com/atom/ns#' term='HIG'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Recents management with gtkmm</title><content type='html'>Recently I "discover" the &lt;a href="http://library.gnome.org/devel/hig-book/stable/"&gt;GNOME Human Interface Guidelines&lt;/a&gt;, so I start to implements on my &lt;a href="http://sourceforge.net/projects/ggredit/"&gt;ggredit&lt;/a&gt; project this specifications.&lt;br /&gt;The GNOME HIG is a comprehensive document and give a great help to the developer, this is also a well known project so I don't want to talk about HIG. This document give me the chance to know how to manage recents on GNOME with gtkmm.&lt;br /&gt;If we follow the HIG on the &lt;span style="font-weight:bold;"&gt;File&lt;/span&gt; menu we have to display recently used documents (see &lt;a href="http://library.gnome.org/devel/hig-book/stable/menus-standard.html.en#generic-file-menu"&gt;HIG File menu section&lt;/a&gt;).&lt;br /&gt;No news, this is the common way to manage recents on all decent applications. In example &lt;a href="http://www.gnome.org/projects/gedit/"&gt;gedit&lt;/a&gt; display the list of recently used documents before the exit option:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SK5wZ9x_RlI/AAAAAAAAAcE/DX1eCerFP_Q/s1600-h/gedit-recents.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SK5wZ9x_RlI/AAAAAAAAAcE/DX1eCerFP_Q/s320/gedit-recents.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5237247008061736530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.inkscape.org/"&gt;Inkscape &lt;/a&gt;instead display an "Open recent" option with a sub-menu containing the list of recently used docuements:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SK5w2dQkdaI/AAAAAAAAAcM/bI700IEhUs8/s1600-h/inkscape-recents.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SK5w2dQkdaI/AAAAAAAAAcM/bI700IEhUs8/s320/inkscape-recents.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5237247497547838882" /&gt;&lt;/a&gt;&lt;br /&gt;Gtk provide a set of API's for manage recents on the GNOME desktop. On gtkmm documentation the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/chapter-recent-documents.html"&gt;Chapter 19&lt;/a&gt; explain how to manage recents.&lt;br /&gt;&lt;h3&gt;Add a file to recents&lt;/h3&gt;&lt;br /&gt;For add a file to recents we have to use the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentManager.html"&gt;Gtk::RecentManager&lt;/a&gt; class. We do not need to create a new instance of this class, using the static function &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentManager.html#6147eea0bc983c8f84cf9b0657280412"&gt;get_default()&lt;/a&gt; we can obtain an unique instance to use in all the application.&lt;br /&gt;For add an item on the recents list we need to call the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentManager.html#6ed8039a13e90ad09a36d7214798b87d"&gt;add_item()&lt;/a&gt; function. We can call &lt;span style="font-weight:bold;"&gt;add_item()&lt;/span&gt; in two ways:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentManager.html#40399f4843c5ab7ab83736a7be08eb36"&gt;add_item(uri)&lt;/a&gt;: we provide only the uri for the file to add on the recents list, the system retrieve other required data from the uri and fill unknown values using defaults&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentManager.html#6ed8039a13e90ad09a36d7214798b87d"&gt;add_item(uri, data)&lt;/a&gt;: we provide the uri and we fill the data structure, this function let us the ownership to give all informations to the system&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;I prefer the second way. So for add a new item on the recents list we need first to fill the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentManager_1_1Data.html"&gt;Gtk::RecentManager::Data&lt;/a&gt; structure, then we can call the &lt;span style="font-weight:bold;"&gt;add_item()&lt;/span&gt; function. On my ggredit I use:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;&lt;strong&gt;void&lt;/strong&gt; &lt;font color="#2040a0"&gt;MainWindow&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;addToRecent&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;font color="#444444"&gt;// Fill Data structure&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RecentManager&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;Data&lt;/font&gt; &lt;font color="#2040a0"&gt;data&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;data&lt;/font&gt;.&lt;font color="#2040a0"&gt;app_exec&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#008000"&gt;&amp;quot;ddraw %u&amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;data&lt;/font&gt;.&lt;font color="#2040a0"&gt;app_name&lt;/font&gt;  &lt;font color="4444FF"&gt;=&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;ddraw&amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;data&lt;/font&gt;.&lt;font color="#2040a0"&gt;groups&lt;/font&gt;.&lt;font color="#2040a0"&gt;push_back&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;ddraw&amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;data&lt;/font&gt;.&lt;font color="#2040a0"&gt;description&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;ddraw diagram&amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;data&lt;/font&gt;.&lt;font color="#2040a0"&gt;display_name&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;getDocumentTitle&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;data&lt;/font&gt;.&lt;font color="#2040a0"&gt;mime_type&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;application_x_ggr_diagram&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;// Get unique instance of RecentManager&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;Glib&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RefPtr&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;lt;&lt;/font&gt;&lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RecentManager&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt; &lt;font color="#2040a0"&gt;recent_manager&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RecentManager&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;get_default&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;br /&gt; &lt;font color="#444444"&gt;// Add the new item&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_manager&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;add_item&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;file://&amp;quot;&lt;/font&gt; &lt;font color="4444FF"&gt;+&lt;/font&gt; &lt;font color="#2040a0"&gt;document_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;getFileName&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;, &lt;font color="#2040a0"&gt;data&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Is importart to use a well formed uri, so for a file we need to specify the "file://" part.&lt;br /&gt;After add a file to the recents list we can see on the GNOME Desktop menu the file we add.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SK6I0wg7XAI/AAAAAAAAAcU/bFttGZaGkyg/s1600-h/gnome-recents-menu.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SK6I0wg7XAI/AAAAAAAAAcU/bFttGZaGkyg/s320/gnome-recents-menu.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5237273856636050434" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Display the recents menu&lt;/h3&gt;&lt;br /&gt;Now we need to display the recents list on the menu of our application. For create the menu on ggredit I use the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1UIManager.html"&gt;Gtk::UIManager&lt;/a&gt; as explained on the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/chapter-menus-and-toolbars.html"&gt;Chapter 11&lt;/a&gt; of gtkmm documentation.&lt;br /&gt;Using the &lt;span style="font-weight:bold;"&gt;UIManager&lt;/span&gt; we can define menu and toolbar appearance with xml and then link each menu item to a &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Action.html"&gt;Gtk::Action&lt;/a&gt; object. So we can define the new menu item this (this is the complete ggredit menu definition):&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    Glib::ustring ui_info =&lt;br /&gt;        &amp;quot;&amp;lt;ui&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;  &amp;lt;menubar name='MenuBar'&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menu action='MenuFile'&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='New'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Open'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Save'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='SaveAs'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='RevertToSaved'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='PageSetup'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='PrintPreview'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Print'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &lt;span style="font-weight:bold;"&gt;&amp;quot;      &amp;lt;menuitem action='FileRecentFiles'/&amp;gt;&amp;quot;&lt;/span&gt;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Quit'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;/menu&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menu action='MenuEdit'&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Undo'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Redo'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Cut'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Copy'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Paste'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Delete'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='SelectAll'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='DeselectAll'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='InsertPage'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;/menu&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menu action='MenuView'&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Toolbar'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Statusbar'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='ObjectsToolbar'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='DocumentBrowser'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='PropertiesBrowser'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='ZoomIn'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='ZoomOut'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='Zoom100'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='ZoomFit'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;/menu&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menu action='MenuGo'&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='PreviousPage'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='NextPage'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='GotoPage'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='FirstPage'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='LastPage'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;/menu&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menu action='Help'&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;      &amp;lt;menuitem action='About'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;/menu&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;  &amp;lt;/menubar&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;  &amp;lt;toolbar  name='ToolBar'&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;toolitem action='New'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;toolitem action='Open'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;toolitem action='Save'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;toolitem action='Print'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;toolitem action='Undo'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;toolitem action='Redo'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;toolitem action='Cut'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;toolitem action='Copy'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;toolitem action='Paste'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;  &amp;lt;/toolbar&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;  &amp;lt;popup name='EditorPopupMenu'&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menuitem action='Cut'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menuitem action='Copy'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menuitem action='Paste'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menuitem action='Delete'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;  &amp;lt;/popup&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;  &amp;lt;popup name='PagePopupMenu'&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menuitem action='Cut'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menuitem action='Copy'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menuitem action='Paste'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menuitem action='InsertPage'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;separator/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;    &amp;lt;menuitem action='Delete'/&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;  &amp;lt;/popup&amp;gt;&amp;quot;&lt;br /&gt;        &amp;quot;&amp;lt;/ui&amp;gt;&amp;quot;;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we need to link an &lt;span style="font-weight:bold;"&gt;Action&lt;/span&gt;. The &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentAction.html"&gt;Gtk::RecentAction&lt;/a&gt; class is what we need. We can add the Action to the ActionGroup like all Actions:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt;     &lt;font color="#444444"&gt;// Create the recent action&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RecentAction&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;create&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;FileRecentFiles&amp;quot;&lt;/font&gt;,&lt;br /&gt;   &lt;font color="#2040a0"&gt;_&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;_Recent Files&amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;signal_item_activated&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;.&lt;font color="#2040a0"&gt;connect&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;br /&gt;   &lt;font color="#2040a0"&gt;sigc&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;mem_fun&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;strong&gt;this&lt;/strong&gt;, &lt;font color="4444FF"&gt;&amp;amp;&lt;/font&gt;&lt;font color="#2040a0"&gt;MainWindow&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;onMenuFileRecentFiles&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;action_group_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;add&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The system emit the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentChooser.html#4df51949b01941dc12d25623c4e16b1e"&gt;signal_item_activated()&lt;/a&gt; signal when the user select an item from the recents list. The result must be like this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SK6wm3wJKNI/AAAAAAAAAc0/knj_B4Kv9xM/s1600-h/ggredit-recents-all.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SK6wm3wJKNI/AAAAAAAAAc0/knj_B4Kv9xM/s320/ggredit-recents-all.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5237317598525860050" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;A new menu option on the &lt;span style="font-weight:bold;"&gt;File &lt;/span&gt;menu with a sub-menu containing the list of recent used documents. There is a problem, on the recents list are displayed all documents, but we want to display only file managed by our application. We have to use the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentFilter.html"&gt;Gtk::RecentFilter&lt;/a&gt; class.&lt;br /&gt;With the Gtk::RecentFilter class we can define a filter criteria for the recents list, then we can use the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentChooser.html#827e5cf870766ca4f2c66cb22b0d4d83"&gt;add_filter()&lt;/a&gt; function of the Gtk::RecentAction object. This is the complete code:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt; &lt;font color="#444444"&gt;// Create the recent action&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RecentAction&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;create&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;FileRecentFiles&amp;quot;&lt;/font&gt;,&lt;br /&gt;   &lt;font color="#2040a0"&gt;_&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;_Recent Files&amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;// Create the recent filter for display only&lt;/font&gt;&lt;br /&gt; &lt;font color="#444444"&gt;// ggredit files&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RecentFilter&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt; &lt;font color="#2040a0"&gt;recent_filter_ptr&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;manage&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RecentFilter&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_filter_ptr&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;add_mime_type&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;application_x_ggr_diagram&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;set_filter&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="#2040a0"&gt;recent_filter_ptr&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;signal_item_activated&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;.&lt;font color="#2040a0"&gt;connect&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;br /&gt;   &lt;font color="#2040a0"&gt;sigc&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;mem_fun&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;strong&gt;this&lt;/strong&gt;, &lt;font color="4444FF"&gt;&amp;amp;&lt;/font&gt;&lt;font color="#2040a0"&gt;MainWindow&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;onMenuFileRecentFiles&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;action_group_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;add&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;With the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentFilter.html#230612101528ddfa56c9a9edcb5a39ca"&gt;add_mime_type()&lt;/a&gt; we can filter only document of a mime type. This is the result:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SK6zZUSHOVI/AAAAAAAAAc8/Mnxvhz8kAkI/s1600-h/ggredit-recents-filter.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SK6zZUSHOVI/AAAAAAAAAc8/Mnxvhz8kAkI/s320/ggredit-recents-filter.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5237320664201247058" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;That's all.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Beautify&lt;/h3&gt;&lt;br /&gt;For complete the recents list we can display the number of each entry (this allow the user to select an item with the corrispondent key) and display the list sorted by date (Most Recent Used).&lt;br /&gt;The &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentChooserMenu.html#e5582f5a3baccd3abbce27a6ef78cd5a"&gt;set_show_numbers()&lt;/a&gt; functions enable the number visibility near each item.&lt;br /&gt;The &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1RecentChooser.html#e90c5478e8b4ff8d8d22925fc9f8be5d"&gt;set_sort_type()&lt;/a&gt; function allow to specify the sort criteria, one of the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/group__gtkmmEnums.html#gc02d49f6d49650abf59e27291e3ef111"&gt;Gtk::RecentSortType&lt;/a&gt; enumeration.&lt;br /&gt;The finally code is:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;br /&gt; &lt;font color="#444444"&gt;// Create the recent action&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RecentAction&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;create&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;FileRecentFiles&amp;quot;&lt;/font&gt;,&lt;br /&gt;   &lt;font color="#2040a0"&gt;_&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;_Recent Files&amp;quot;&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;// Create the recent filter for display only&lt;/font&gt;&lt;br /&gt; &lt;font color="#444444"&gt;// ggredit files&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RecentFilter&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt; &lt;font color="#2040a0"&gt;recent_filter_ptr&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;manage&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;strong&gt;new&lt;/strong&gt; &lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RecentFilter&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_filter_ptr&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;add_mime_type&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;application_x_ggr_diagram&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;set_filter&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="#2040a0"&gt;recent_filter_ptr&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;set_show_numbers&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;strong&gt;true&lt;/strong&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;set_sort_type&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;Gtk&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;RECENT_SORT_MRU&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;signal_item_activated&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;.&lt;font color="#2040a0"&gt;connect&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;br /&gt;   &lt;font color="#2040a0"&gt;sigc&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;mem_fun&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;strong&gt;this&lt;/strong&gt;, &lt;font color="4444FF"&gt;&amp;amp;&lt;/font&gt;&lt;font color="#2040a0"&gt;MainWindow&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="4444FF"&gt;:&lt;/font&gt;&lt;font color="#2040a0"&gt;onMenuFileRecentFiles&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;action_group_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;add&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;recent_action_ptr_&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and the result is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SK7P4K7siAI/AAAAAAAAAdE/GcKE-XmF_nk/s1600-h/ggredit-beautified.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SK7P4K7siAI/AAAAAAAAAdE/GcKE-XmF_nk/s320/ggredit-beautified.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5237351980592826370" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;&lt;br /&gt;With Gtk+ we can manage recents very easily, we have to write only few rows. The framework is integrated on the GNOME desktop environment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-1878848536618918510?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/1878848536618918510/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/08/recents-management-with-gtkmm.html#comment-form' title='2 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/1878848536618918510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/1878848536618918510'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/08/recents-management-with-gtkmm.html' title='Recents management with gtkmm'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_sQJ1m4QDkME/SK5wZ9x_RlI/AAAAAAAAAcE/DX1eCerFP_Q/s72-c/gedit-recents.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-7675150773594984701</id><published>2008-08-18T07:56:00.004+02:00</published><updated>2008-08-18T08:31:51.131+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>And the winner is...me???</title><content type='html'>It's real...&lt;a href="http://www.eclipse.org/org/press-release/20080812_aroundtheworldwinners.php"&gt;I win the Ganymede around the world contest&lt;/a&gt;!!!&lt;br /&gt;I am so honored, now I can thank all like a music star:&lt;br /&gt;&lt;span style="font-style:italic;"&gt;"I want to thank my family and friends for their support, and I want to thank God"&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-7675150773594984701?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/7675150773594984701/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/08/and-winner-isme.html#comment-form' title='1 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7675150773594984701'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7675150773594984701'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/08/and-winner-isme.html' title='And the winner is...me???'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-8000386100408063570</id><published>2008-07-21T08:29:00.006+02:00</published><updated>2008-12-11T09:43:40.357+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='data compression'/><title type='text'>Data compression with ZLib</title><content type='html'>As you read on my previous post for store images on ggredit file I write the raw Pixbuf buffer using Base64 encoding. However for big images this method cause performance to fall down. If I load an image that take 3Mb on memory, when I store it on the ggredit file it take 4Mb, this cause a slowly file reading/writing (using libXml2) and also a generic slow because ggredit store this buffer n-times (for undo/redo). My idea is to use data compression.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SIRWcOS3WRI/AAAAAAAAAbM/0qFmoEdxiLA/s1600-h/press.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SIRWcOS3WRI/AAAAAAAAAbM/0qFmoEdxiLA/s320/press.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5225396510530165010" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My first approach was to write my own &lt;a href="http://en.wikipedia.org/wiki/Data_compression"&gt;compression&lt;/a&gt; algorithm. I start to implement the &lt;a href="http://en.wikipedia.org/wiki/Lzw"&gt;lzw &lt;/a&gt;algorithm, this algorithm fascinate me. But when I read about some patents on this algorithm (&lt;a href="http://en.wikipedia.org/wiki/Lzw#Patents"&gt;LZW Patents&lt;/a&gt;), sicerly I don't understand this long story, so for avoid any problem I try to search an other way.&lt;br /&gt;I have a look to &lt;a href="http://www.inkscape.org/"&gt;Inkscape&lt;/a&gt; (my favourite gtkmm project) references and I find &lt;a href="http://www.zlib.net/"&gt;ZLib&lt;/a&gt;.&lt;br /&gt;ZLib is a C library that implement the &lt;a href="http://en.wikipedia.org/wiki/DEFLATE"&gt;Deflate&lt;/a&gt; algorithm (originally used by PKZip, many many years ago, I remember its use at school time).&lt;br /&gt;So I start to write a tiny C++ wrapper.&lt;br /&gt;On ZLib each function refer to a &lt;a href="http://www.zlib.net/manual.html#z_stream_s"&gt;z_stream&lt;/a&gt; object, and we can use a z_stream object for inflate or for deflate using the initialization functions: &lt;a href="http://www.zlib.net/manual.html#deflateInit"&gt;deflateInit &lt;/a&gt;for create a compression stream or &lt;a href="http://www.zlib.net/manual.html#inflateInit"&gt;inflateInit &lt;/a&gt;for create a decompression stream. If the z_stream object was initialized using deflateInit we need to call &lt;a href="http://www.zlib.net/manual.html#deflateEnd"&gt;deflateEnd &lt;/a&gt;when the compression operation is complete, if the z_stream object was initialized using inflateInit. we need to call &lt;a href="http://www.zlib.net/manual.html#inflateEnd"&gt;inflateEnd &lt;/a&gt;when the decompression operation is complete.&lt;br /&gt;This is my ZStream architecture (very simple):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SIRFlJhZ_BI/AAAAAAAAAbE/wyRrDYUPJeI/s1600-h/ZStream-Diagram-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SIRFlJhZ_BI/AAAAAAAAAbE/wyRrDYUPJeI/s320/ZStream-Diagram-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5225377972170128402" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The ZStreamBase class is the z_stream wrapper. &lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/*!&lt;br /&gt; * @brief Base class for Zlib streams&lt;br /&gt; */&lt;br /&gt;class ZStreamBase&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    /*!&lt;br /&gt;     * @brief Buffert type&lt;br /&gt;     */&lt;br /&gt;    typedef unsigned char char_t;&lt;br /&gt;&lt;br /&gt;    /*!&lt;br /&gt;     * @brief Constructor&lt;br /&gt;     */&lt;br /&gt;    ZStreamBase();&lt;br /&gt;&lt;br /&gt;    /*!&lt;br /&gt;     * @brief Destructor&lt;br /&gt;     */&lt;br /&gt;    virtual ~ZStreamBase();&lt;br /&gt;&lt;br /&gt;    /*!&lt;br /&gt;     * @brief Byte available in input&lt;br /&gt;     *&lt;br /&gt;     * @return true if not data are available in input&lt;br /&gt;     */&lt;br /&gt;    bool isInEmpty() const { return z_stream_.avail_in == 0; };&lt;br /&gt;&lt;br /&gt;    /*!&lt;br /&gt;     * @briet Byte available in output&lt;br /&gt;     *&lt;br /&gt;     * @return true if not data are available in output&lt;br /&gt;     */&lt;br /&gt;    bool isOutEmpty() const { return z_stream_.avail_out == 0; };&lt;br /&gt;&lt;br /&gt;    /*!&lt;br /&gt;     * @brief Stream input complete on inflate&lt;br /&gt;     *&lt;br /&gt;     * @return true if the stream input is compltete on inflate&lt;br /&gt;     */&lt;br /&gt;    bool isStreamEnd() const { return stream_end_; }&lt;br /&gt;&lt;br /&gt;    /*!&lt;br /&gt;     * @brief Write a buffer to the ZLib stream&lt;br /&gt;     *&lt;br /&gt;     * @param buf pointer to the buffer&lt;br /&gt;     * @param buf_size buffer size&lt;br /&gt;     */&lt;br /&gt;    void write(char_t* buf, size_t buf_size);&lt;br /&gt;&lt;br /&gt;    /*!&lt;br /&gt;     * @brief Read a buffer from the ZLib stream&lt;br /&gt;     *&lt;br /&gt;     * @param buf pointer to the buffer&lt;br /&gt;     * @param buf_size buffer size&lt;br /&gt;     */&lt;br /&gt;    virtual void read(char_t* buf, size_t buf_size) = 0;&lt;br /&gt;&lt;br /&gt;    /*!&lt;br /&gt;     * @brief Read all ZLib output stream&lt;br /&gt;     *&lt;br /&gt;     * Use the read function for read each data chunk until&lt;br /&gt;     * the output buffer is empty, isOutEmpty return true.&lt;br /&gt;     *&lt;br /&gt;     * @param buf return a new allocated buffer&lt;br /&gt;     * @param buf_size return the size of the allocated buffer&lt;br /&gt;     */&lt;br /&gt;    void readAll(char_t** buf, size_t&amp;amp; buf_size);&lt;br /&gt;&lt;br /&gt;    /*!&lt;br /&gt;     * @brief Mark as complete the write operation&lt;br /&gt;     */&lt;br /&gt;    void flush() { flush_ = true; };&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt;    z_stream z_stream_;&lt;br /&gt;    bool flush_;&lt;br /&gt;    bool stream_end_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Initialization&lt;/h3&gt;&lt;br /&gt;The two inherited classes ZDeflateStream and ZInflateStream initialize the z_stream object for compress and for decompress data.&lt;br /&gt;The deflate stream require the compression level when we initialize the structure. I use an optional argument equal to &lt;a href="http://www.zlib.net/manual.html#Z_DEFAULT_COMPRESSION"&gt;Z_DEFAULT_COMPRESSION&lt;/a&gt; for default.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;ZDeflateStream::ZDeflateStream(int compression_level/*=Z_DEFAULT_COMPRESSION*/) :&lt;br /&gt;    compression_level_( compression_level )&lt;br /&gt;{&lt;br /&gt;    int ret = deflateInit (&amp;amp;z_stream_, compression_level_);&lt;br /&gt;&lt;br /&gt;    if (ret != Z_OK)&lt;br /&gt;        throw ZError (&amp;quot;Can not initialize deflate stream&amp;quot;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ZDeflateStream::~ZDeflateStream()&lt;br /&gt;{&lt;br /&gt;    deflateEnd (&amp;amp;z_stream_);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The inflate stream does not need to specify the compression level.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;ZInflateStream::ZInflateStream()&lt;br /&gt;{&lt;br /&gt;    z_stream_.avail_in = 0;&lt;br /&gt;    z_stream_.next_in = Z_NULL;&lt;br /&gt;&lt;br /&gt;    int ret = inflateInit (&amp;amp;z_stream_);&lt;br /&gt;&lt;br /&gt;    if (ret != Z_OK)&lt;br /&gt;        throw ZError (&amp;quot;Can not initialize inflate stream&amp;quot;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ZInflateStream::~ZInflateStream()&lt;br /&gt;{&lt;br /&gt;    inflateEnd (&amp;amp;z_stream_);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Read and write data&lt;/h3&gt;&lt;br /&gt;For read and write data we have to use the &lt;span style="font-weight:bold;"&gt;next_in&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;avail_in&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;next_out&lt;/span&gt;, &lt;span style="font-weight:bold;"&gt;avail_out&lt;/span&gt; members of the z_stream structure.&lt;br /&gt;We can write data setting the &lt;span style="font-weight:bold;"&gt;next_in&lt;/span&gt; to the pointer to the buffer we want to write and put on &lt;span style="font-weight:bold;"&gt;avail_in&lt;/span&gt; the buffer size. On this way we can write either compressed or decompressed data, so I implement the write method in the base class.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void ZStreamBase::write(char_t* buf, size_t buf_size)&lt;br /&gt;{&lt;br /&gt;    z_stream_.avail_in = buf_size;&lt;br /&gt;    z_stream_.next_in = reinterpret_cast&amp;lt; Bytef* &amp;gt;(buf);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The read operation instead depend on the type of stream, on deflate stream we have to call &lt;a href="http://www.zlib.net/manual.html#deflate"&gt;deflate()&lt;/a&gt; function, on inflate stream we have to call &lt;a href="http://www.zlib.net/manual.html#inflate"&gt;inflate()&lt;/a&gt; function. Those two functions read the buffer in &lt;span style="font-weight:bold;"&gt;next_in&lt;/span&gt; and write compressed or decompressed data on the &lt;span style="font-weight:bold;"&gt;next_out&lt;/span&gt; buffer.&lt;br /&gt;On deflate stream we read compressed data, we have to pass to the deflate() function an argument that tell if the input stream is complete. I use the boolean attribute &lt;span style="font-weight:bold;"&gt;flush_&lt;/span&gt; that is set to true when the &lt;span style="font-weight:bold;"&gt;flush()&lt;/span&gt; method is called.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void ZDeflateStream::read(char_t* buf, size_t buf_size)&lt;br /&gt;{&lt;br /&gt;    z_stream_.avail_out = buf_size;&lt;br /&gt;    z_stream_.next_out = reinterpret_cast&amp;lt; Bytef* &amp;gt;(buf);&lt;br /&gt;&lt;br /&gt;    int ret = deflate (&amp;amp;z_stream_, flush_ ? Z_FINISH : Z_NO_FLUSH);&lt;br /&gt;&lt;br /&gt;    if (ret == Z_STREAM_ERROR)&lt;br /&gt;        throw ZError( &amp;quot;Error on deflate&amp;quot; );&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When we read from an inflate stream we read decompressed data.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void ZInflateStream::read(char_t* buf, size_t buf_size)&lt;br /&gt;{&lt;br /&gt;    z_stream_.avail_out = buf_size;&lt;br /&gt;    z_stream_.next_out = reinterpret_cast&amp;lt; Bytef* &amp;gt;(buf);&lt;br /&gt;&lt;br /&gt;    int ret = inflate (&amp;amp;z_stream_, Z_NO_FLUSH);&lt;br /&gt;&lt;br /&gt;    switch (ret)&lt;br /&gt;    {&lt;br /&gt;        case Z_STREAM_ERROR:&lt;br /&gt;            throw ZError( &amp;quot;The stream structure was inconsistent&amp;quot; );&lt;br /&gt;            break;&lt;br /&gt;        case Z_NEED_DICT:&lt;br /&gt;            throw ZError( &amp;quot;A preset dictionary is needed&amp;quot; );&lt;br /&gt;            break;&lt;br /&gt;        case Z_DATA_ERROR:&lt;br /&gt;            throw ZError( &amp;quot;Input data was corrupted&amp;quot; );&lt;br /&gt;            break;&lt;br /&gt;        case Z_MEM_ERROR:&lt;br /&gt;            throw ZError( &amp;quot;Not enough memory&amp;quot; );&lt;br /&gt;            break;&lt;br /&gt;        case Z_STREAM_END:&lt;br /&gt;            stream_end_ = true;&lt;br /&gt;            break;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The ZStreamBase base class implement also a readAll method that read all data from the input buffer and return an allocated buffer, on this way we have not to take care of the buffer size.&lt;br /&gt;The std::stringstream class help us to allocate the temporary buffer.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;const size_t ChunkSize = 16384;&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;.&lt;br /&gt;void ZStreamBase::readAll(char_t** buf, size_t&amp;amp; buf_size)&lt;br /&gt;{&lt;br /&gt;    std::stringstream out_stream;&lt;br /&gt;&lt;br /&gt;    char_t out_buf[ChunkSize];&lt;br /&gt;&lt;br /&gt;    do&lt;br /&gt;    {&lt;br /&gt;        read (out_buf, ChunkSize);&lt;br /&gt;&lt;br /&gt;        size_t out_size = ChunkSize - z_stream_.avail_out;&lt;br /&gt;        out_stream.write (reinterpret_cast&amp;lt; const char* &amp;gt;(out_buf), out_size);&lt;br /&gt;&lt;br /&gt;        if (out_stream.bad())&lt;br /&gt;            throw ZError( &amp;quot;Error writing temporary stream&amp;quot; );&lt;br /&gt;&lt;br /&gt;    } while (isOutEmpty());&lt;br /&gt;&lt;br /&gt;    buf_size = out_stream.str().size();&lt;br /&gt;    *buf = new char_t[buf_size];&lt;br /&gt;    out_stream.read (reinterpret_cast&amp;lt; std::stringstream::char_type* &amp;gt;(*buf), buf_size);;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I use this technique on ggredit, and the performance  now are immproved. LibXml2 have to read less data, so the file loading (and parsing) now is fast. Also the copy of the buffer is fast, and this is strange because the complexity is increased.&lt;br /&gt;My first method was encode the buffer using Base64 for generate a string from a source object, decode the Base64 string and create a second buffer on the destination object. Now I compress the source buffer, encode the compressed data using Base64 for generate a string from a source object, decode the Base64 string for obtain compressed buffer, decompress the buffer and finally I get the destination object.&lt;br /&gt;&lt;br /&gt;So sometimes the size make the difference.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-8000386100408063570?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/8000386100408063570/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/07/data-compression-with-zlib.html#comment-form' title='4 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/8000386100408063570'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/8000386100408063570'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/07/data-compression-with-zlib.html' title='Data compression with ZLib'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_sQJ1m4QDkME/SIRWcOS3WRI/AAAAAAAAAbM/0qFmoEdxiLA/s72-c/press.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-5548050249622059486</id><published>2008-07-18T14:16:00.005+02:00</published><updated>2008-12-11T09:43:40.647+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>Fixing my Base64 functions</title><content type='html'>On my previous post "&lt;a href="http://kapo-cpp.blogspot.com/2008/05/base64.html"&gt;Base64&lt;/a&gt;" I introduce two functions for encode and decode a buffer using Base64.&lt;br /&gt;I use those functions for read-from and write-to an xml file a Pibux buffer on my ggredit project.&lt;br /&gt;All goese well...&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SICQ-C2UhbI/AAAAAAAAAa0/orgbwaMJhFQ/s1600-h/120px-Dialog-error-round.svg.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SICQ-C2UhbI/AAAAAAAAAa0/orgbwaMJhFQ/s320/120px-Dialog-error-round.svg.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5224334963340772786" /&gt;&lt;/a&gt;&lt;br /&gt;I have some perfomance problem since any stream encoded using Base64 grows of a quarter of it orginal size, and my files using this technique were too large. I start to write a second decoder for compress and expand the Pixbuf buffer (on next post I will explain this argument). So now: on write I first compress the Pixbuf buffer and then I encode compressed buffer using Base64, on read first I decode from Base64 then I expand compressed data.&lt;br /&gt;This implementation let me discover a critical bug on the decode function, the buffer decoded is different from the encoded buffer. I don't know how but using ggredit I never notice strange behavior.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #e2ebf8;font-size: 12px;border: 1px;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SLuMPrvaTDI/AAAAAAAAAeE/oQCLt9nwq2E/s1600-h/86333-ladybug48.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SLuMPrvaTDI/AAAAAAAAAeE/oQCLt9nwq2E/s200/86333-ladybug48.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5240936792443210802" /&gt;&lt;/a&gt;I would like also to thanks Chrono© for report the bad code at line 137.&lt;/pre&gt;&lt;br /&gt;This is the bug fixed code:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#ifndef BASE64_H_&lt;br /&gt;#define BASE64_H_&lt;br /&gt;&lt;br /&gt;#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;#include &amp;lt;sstream&amp;gt;&lt;br /&gt;#include &amp;lt;memory&amp;gt;&lt;br /&gt;&lt;br /&gt;namespace base64&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;const char base64chars[] = &amp;quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&amp;quot;;&lt;br /&gt;const char base64pad = '=';&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * @brief Encode a buffer on a string base64 encoded&lt;br /&gt; *&lt;br /&gt; * Base 64 encoding converts 3 bytes into 4 encoded ASCII&lt;br /&gt; * characters.&lt;br /&gt; * If the encoded string lenght is not multiple of 4&lt;br /&gt; * the padding character &amp;quot;=&amp;quot; is added for fill the buffer.&lt;br /&gt; * If the buf_size is 0 an empty string was returned.&lt;br /&gt; *&lt;br /&gt; * @param buf_ptr pointer to the source buffer&lt;br /&gt; * @param buf_size size of the buffer&lt;br /&gt; *&lt;br /&gt; * @return a string base64 encoded&lt;br /&gt; *&lt;br /&gt; * @see http://en.wikipedia.org/wiki/Base64&lt;br /&gt; */&lt;br /&gt;std::string encode(uint8_t* buf_ptr, size_t buf_size)&lt;br /&gt;{&lt;br /&gt;    // If the buf_size is 0 return an empty string&lt;br /&gt;    if (buf_size == 0)&lt;br /&gt;        return &amp;quot;&amp;quot;;&lt;br /&gt;&lt;br /&gt;    uint32_t n = 0;&lt;br /&gt;    uint8_t n0, n1, n2, n3;&lt;br /&gt;    std::stringstream ss_result;&lt;br /&gt;&lt;br /&gt;    // Iterate over the buffer&lt;br /&gt;    for (size_t x = 0; x &amp;lt; buf_size; x += 3)&lt;br /&gt;    {&lt;br /&gt;        // Get 3 bytes of 8 bit from the buffer&lt;br /&gt;        n = buf_ptr[x] &amp;lt;&amp;lt; 16;&lt;br /&gt;&lt;br /&gt;        if ((x + 1) &amp;lt; buf_size)&lt;br /&gt;        {&lt;br /&gt;            n += buf_ptr[x + 1] &amp;lt;&amp;lt; 8;&lt;br /&gt;&lt;br /&gt;            if ((x + 2) &amp;lt; buf_size)&lt;br /&gt;            {&lt;br /&gt;                n += buf_ptr[x + 2];&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // Transform on 4 bytes of 6 bit&lt;br /&gt;        n0 = (uint8_t)(n &amp;gt;&amp;gt; 18) &amp;amp; 63;&lt;br /&gt;        n1 = (uint8_t)(n &amp;gt;&amp;gt; 12) &amp;amp; 63;&lt;br /&gt;        n2 = (uint8_t)(n &amp;gt;&amp;gt; 6) &amp;amp; 63;&lt;br /&gt;        n3 = (uint8_t)n &amp;amp; 63;&lt;br /&gt;&lt;br /&gt;        // Write first 2 bytes into the stream&lt;br /&gt;        ss_result &amp;lt;&amp;lt; base64chars[n0];&lt;br /&gt;        ss_result &amp;lt;&amp;lt; base64chars[n1];&lt;br /&gt;&lt;br /&gt;        // Test if only 2 bytes&lt;br /&gt;        if ((x + 1) &amp;lt; buf_size)&lt;br /&gt;        {&lt;br /&gt;            // Write 3rd into the stream&lt;br /&gt;            ss_result &amp;lt;&amp;lt; base64chars[n2];&lt;br /&gt;&lt;br /&gt;            // Test if only 3 bytes&lt;br /&gt;            if ((x + 2) &amp;lt; buf_size)&lt;br /&gt;            {&lt;br /&gt;                // Write 4th into the stream&lt;br /&gt;                ss_result &amp;lt;&amp;lt; base64chars[n3];&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Add padding character for fill the output string&lt;br /&gt;    for (int pad_count = 0; pad_count &amp;lt; ss_result.str().size() % 4; pad_count++)&lt;br /&gt;    {&lt;br /&gt;        ss_result &amp;lt;&amp;lt; base64pad;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return ss_result.str();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/*!&lt;br /&gt; * @brief Compute size of decoded stream&lt;br /&gt; *&lt;br /&gt; * @param encoded_size size of the encoded stream&lt;br /&gt; * @return the size of the decoded stream&lt;br /&gt; */&lt;br /&gt;size_t decoded_size(size_t encoded_size)&lt;br /&gt;{&lt;br /&gt;    return (encoded_size + 3) / 4 * 3;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * @brief Decode a string base64 encoded and return a raw buffer&lt;br /&gt; *&lt;br /&gt; * The function allocate a buffer with size:&lt;br /&gt; * @code (text.size() + 3) / 4 * 3&lt;br /&gt; * and return the pointer. The caller has the ownership of the&lt;br /&gt; * pointer.&lt;br /&gt; * The source string lenght must be multiple of 4.&lt;br /&gt; * Use is_base_64 for test if a string is Base64 well formed.&lt;br /&gt; *&lt;br /&gt; * @param text the base64 string encoded&lt;br /&gt; *&lt;br /&gt; * @return the pointer to the decoded buffer&lt;br /&gt; */&lt;br /&gt;std::auto_ptr&amp;lt; uint8_t &amp;gt; decode(const std::string&amp;amp; text)&lt;br /&gt;{&lt;br /&gt;    // Create the decode matrix&lt;br /&gt;    uint8_t decode_base64chars[256];&lt;br /&gt;    memset (decode_base64chars, 0, 256);&lt;br /&gt;&lt;br /&gt;    for (uint8_t i = 0; i &amp;lt;= 63; i++)&lt;br /&gt;    {&lt;br /&gt;        decode_base64chars[(int)base64chars[(int)i]] = i;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Allocate output buffer&lt;br /&gt;    uint8_t* buf_ptr = new uint8[decoded_size(text.size())];&lt;br /&gt;&lt;br /&gt;    // Start decode source string&lt;br /&gt;    size_t buf_idx = 0;&lt;br /&gt;    for (size_t i = 0; i &amp;lt; text.size(); i += 4, buf_idx += 3)&lt;br /&gt;    {&lt;br /&gt;        // Put first base64 char on the first output-byte&lt;br /&gt;        buf_ptr[buf_idx] = decode_base64chars[(int)text[i]] &amp;lt;&amp;lt; 2;&lt;br /&gt;&lt;br /&gt;        // Test for string end&lt;br /&gt;        if ((i + 1 &amp;lt; text.size()) &amp;amp;&amp;amp; (text[i + 1] != base64pad))&lt;br /&gt;        {&lt;br /&gt;            // Add to the first output-byte 2 bit of the second base64 char&lt;br /&gt;            buf_ptr[buf_idx] += (decode_base64chars[(int)text[i + 1]] &amp;gt;&amp;gt; 4) &amp;amp; 0x3;&lt;br /&gt;&lt;br /&gt;            // Put remaining 4 bit of the second base64 char on the second output-byte&lt;br /&gt;            buf_ptr[buf_idx + 1] = decode_base64chars[(int)text[i + 1]] &amp;lt;&amp;lt; 4;&lt;br /&gt;&lt;br /&gt;            // Test for string end&lt;br /&gt;            if ((i + 2 &amp;lt; text.size()) &amp;amp;&amp;amp; (text[i + 2] != base64pad))&lt;br /&gt;            {&lt;br /&gt;                // Add to the second output-byte 4 bit of the third base64 char&lt;br /&gt;                buf_ptr[buf_idx + 1] += (decode_base64chars[(int)text[i + 2]] &amp;gt;&amp;gt; 2) &amp;amp; 0xf;&lt;br /&gt;&lt;br /&gt;                // Put remaining 2 bit of the third base64 char on the third output-byte&lt;br /&gt;                buf_ptr[buf_idx + 2] = decode_base64chars[(int)text[i + 2]] &amp;lt;&amp;lt; 6;&lt;br /&gt;&lt;br /&gt;                // Test for string end&lt;br /&gt;                if ((i + 1 &amp;lt; text.size()) &amp;amp;&amp;amp; (text[i + 3] != base64pad))&lt;br /&gt;                {&lt;br /&gt;                    // Add to the third output-byte the forth base64 char&lt;br /&gt;                    buf_ptr[buf_idx + 2] += decode_base64chars[(int)text[i + 3]];&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return std::auto_ptr&amp;lt;uint8_t&amp;gt;(buf_ptr);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * @brief Test if a string is well Base64 encoded&lt;br /&gt; *&lt;br /&gt; * @param text the string Base64 encoded&lt;br /&gt; *&lt;br /&gt; * @return true if the string is well formed&lt;br /&gt; */&lt;br /&gt;bool is_base_64(const std::string&amp;amp; text)&lt;br /&gt;{&lt;br /&gt;    // Create the decode matrix&lt;br /&gt;    uint8_t decode_base64chars[256];&lt;br /&gt;    memset (decode_base64chars, 65, 256);&lt;br /&gt;&lt;br /&gt;    for (uint8_t i = 0; i &amp;lt;= 63; i++)&lt;br /&gt;    {&lt;br /&gt;        decode_base64chars[(int)base64chars[(int)i]] = i;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Add padding character&lt;br /&gt;    decode_base64chars[(int)'='] = 64;&lt;br /&gt;&lt;br /&gt;    // Test string characters&lt;br /&gt;    for (size_t i = 0; i &amp;lt; text.size(); i++)&lt;br /&gt;    {&lt;br /&gt;        if (decode_base64chars[(int)text[i]] == 65)&lt;br /&gt;        {&lt;br /&gt;            // Invalid character found&lt;br /&gt;            return false;&lt;br /&gt;        }&lt;br /&gt;        else if ((decode_base64chars[(int)text[i]] == 64) &amp;amp;&amp;amp; (i &amp;lt; text.size() - 3))&lt;br /&gt;        {&lt;br /&gt;            // Padding character at invalid position&lt;br /&gt;            return false;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return true;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif /*BASE64_H_*/&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-5548050249622059486?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/5548050249622059486/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/07/fixing-my-base64-functions.html#comment-form' title='4 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5548050249622059486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5548050249622059486'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/07/fixing-my-base64-functions.html' title='Fixing my Base64 functions'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_sQJ1m4QDkME/SICQ-C2UhbI/AAAAAAAAAa0/orgbwaMJhFQ/s72-c/120px-Dialog-error-round.svg.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-2458543298362439200</id><published>2008-07-10T07:58:00.003+02:00</published><updated>2008-12-11T09:43:40.765+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='personal'/><title type='text'>Noi alfisti di oggi</title><content type='html'>La mia 159 è arrivata al concessionario e ieri sono andato a vederla...che emozione!&lt;br /&gt;&lt;span style="font-size:85%;"&gt;(Google translation: "My 159 came to the dealer and yesterday I went to see ... that emotion!")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SHWm3ec7jrI/AAAAAAAAAas/FGTMU7fvuHE/s1600-h/159.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SHWm3ec7jrI/AAAAAAAAAas/FGTMU7fvuHE/s320/159.png" alt="" id="BLOGGER_PHOTO_ID_5221262815003381426" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: center; font-style: italic;"&gt;Con l' "alfa" rossa fa quello che vuole&lt;br /&gt;&lt;br /&gt;dentro al fuoco di cento saette!&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-2458543298362439200?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/2458543298362439200/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/07/noi-alfisti-di-oggi.html#comment-form' title='2 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/2458543298362439200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/2458543298362439200'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/07/noi-alfisti-di-oggi.html' title='Noi alfisti di oggi'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_sQJ1m4QDkME/SHWm3ec7jrI/AAAAAAAAAas/FGTMU7fvuHE/s72-c/159.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-2841967754973457526</id><published>2008-07-09T09:46:00.003+02:00</published><updated>2008-12-11T09:43:40.969+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>LibXml2 and Schema validation performance</title><content type='html'>Yesterday I was very happy since my ggredit project seems on full growth, it advance to a stable initial version. So I let my friend Aprile test ggredit for enjoy some feedback from a third person.&lt;br /&gt;He add one big picture on one page and then duplicate this page five times (finally the whole document size was 31.7 MB). He save this document and after he re-open the same document...we wait...I was embarassed...we wait...he was bewildered...we wait...and I stop to be happy.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SHR8TB2SdGI/AAAAAAAAAaM/RJEDCHzjxw8/s1600-h/Hourglass.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SHR8TB2SdGI/AAAAAAAAAaM/RJEDCHzjxw8/s320/Hourglass.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5220934534384743522" /&gt;&lt;/a&gt;&lt;br /&gt;This morning I try to understand the reason of this long waiting time.&lt;br /&gt;As you know I write my own libxml2 c++ wrapper (&lt;a href="http://kapo-cpp.blogspot.com/2008/02/working-with-xml-on-linux.html"&gt;Working with XML on linux&lt;/a&gt;), I store the document on xml format validated with a schema. For save images I store the buffer on the xml document using base 64 encoding (&lt;a href="http://kapo-cpp.blogspot.com/2008/05/base64.html"&gt;Base64&lt;/a&gt;).&lt;br /&gt;I use the old method of measure time of execution for all critical methods. When I detect the method I measure the time of execution of each "part". Finally I got it, the cause is:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;bool Schema::validate(const Glib::ustring&amp;amp; filename)&lt;br /&gt;{&lt;br /&gt;    bool result = false;&lt;br /&gt;&lt;br /&gt;    if (xmlSchemaValidCtxtPtr validity_context_ptr = xmlSchemaNewValidCtxt (schema_ptr_))&lt;br /&gt;    {&lt;br /&gt;      result = xmlSchemaValidateFile (validity_context_ptr, filename.c_str(), 0) == 0;&lt;br /&gt;      xmlSchemaFreeValidCtxt (validity_context_ptr);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;the schema validation method. Almost all the time is spent to validate the xml document using the &lt;a href="http://xmlsoft.org/html/libxml-xmlschemas.html#xmlSchemaValidateFile"&gt;xmlSchemaValidateFile&lt;/a&gt; api.&lt;br /&gt;For a moment I think the problem was unsolvable, then I think to remove the schema validation, but this is too drastic. I try to parse the document using &lt;a href="http://xmlsoft.org/xmllint.html"&gt;xmllint&lt;/a&gt; specifing to validate using my schema, xmllint parse and validate the document on short time. So the problem is not libxml2?&lt;br /&gt;I return to &lt;a href="http://xmlsoft.org/"&gt;libxml2 web page&lt;/a&gt; and I try to find a solution. I see the &lt;a href="http://xmlsoft.org/html/libxml-xmlschemas.html#xmlSchemaValidateDoc"&gt;xmlSchemaValidateDoc&lt;/a&gt; function, that validate an already loaded xml document. So I create a new validate method:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;bool Schema::validate(const XmlDocument&amp;amp; xml_doc)&lt;br /&gt;{&lt;br /&gt;    bool result = false;&lt;br /&gt;&lt;br /&gt;    if (xmlSchemaValidCtxtPtr validity_context_ptr = xmlSchemaNewValidCtxt (schema_ptr_))&lt;br /&gt;    {&lt;br /&gt;      result = xmlSchemaValidateDoc (validity_context_ptr, xml_doc.getDocPtr()) == 0;&lt;br /&gt;      xmlSchemaFreeValidCtxt (validity_context_ptr);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;and using this method the time occured for load the xml document decrease and become acceptable. While using xmlSchemaValidateFile the validation take 50 seconds, now using xmlSchemaValidateDoc it take 4 seconds! And if we use a calculator we can determine that the speed increase of 12.5 times...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-2841967754973457526?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/2841967754973457526/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/07/libxml2-and-schema-validation.html#comment-form' title='6 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/2841967754973457526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/2841967754973457526'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/07/libxml2-and-schema-validation.html' title='LibXml2 and Schema validation performance'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/SHR8TB2SdGI/AAAAAAAAAaM/RJEDCHzjxw8/s72-c/Hourglass.jpg' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-8840733481569345598</id><published>2008-06-26T07:49:00.020+02:00</published><updated>2008-12-11T09:43:42.860+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cdt'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>Finally Ganymede</title><content type='html'>&lt;h3&gt;Width CDT 5.0, the best c++ IDE on Linux&lt;/h3&gt;&lt;br /&gt;After install all Ganymede milestone versions and all release candidate finally Ganymede is here.&lt;br /&gt;On this post I try to summarize all previous post about this new version of Eclipse and CDT, I never see an IDE like this for Linux.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Uninstall previous version&lt;/h3&gt;&lt;br /&gt;It is not necessary to uninstall previous version, you can also have two different version of Eclipse, just use two different directory (as I told on the post "&lt;a href="http://kapo-cpp.blogspot.com/2008/06/install-eclipse-ganymede-rc2-with-cdt.html"&gt;Install Eclipse Ganymede RC2 (with CDT 5.0)&lt;/a&gt;").&lt;br /&gt;You can follow my post "&lt;a href="http://kapo-cpp.blogspot.com/2008/06/uninstall-eclipse.html"&gt;Uninstall Eclipse&lt;/a&gt;" for see how to remove Eclipse. I have installed on my machine &lt;span style="font-weight:bold;"&gt;Eclipse Europa&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;Eclipse Ganymede RC4&lt;/span&gt; so I remove all using:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo rm /usr/share/applications/eclipse-ganymede-rc4.desktop&lt;br /&gt;sudo rm /usr/bin/eclipse-ganymede-rc4&lt;br /&gt;sudo rm -rf /opt/eclipse-ganymede-rc4/&lt;br /&gt;&lt;br /&gt;sudo rm /usr/share/applications/eclipse.desktop&lt;br /&gt;sudo rm /usr/bin/eclipse&lt;br /&gt;sudo rm -rf /opt/eclipse/&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we do not have Eclipse installed on our machine...inhale slowly and don't panic.&lt;br /&gt;&lt;br /&gt;The only part we not remove is the &lt;span style="font-weight:bold;"&gt;.eclipse&lt;/span&gt; directory in the home, where are stored user settings. If you want to clear all you need to remove also this directory.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Install Ganymede&lt;/h3&gt;&lt;br /&gt;For Eclipse installation I prefer to download it from the Web instead of use Ubuntu repositories, we need to wait too much time for see the new version debianized on repositories.&lt;br /&gt;Download the Eclipse package for your platform from the &lt;a href="http://www.eclipse.org/downloads/"&gt;Eclipse download page&lt;/a&gt;.&lt;br /&gt;Usually, as you know, I install Eclipse in the &lt;span style="font-weight:bold;"&gt;/opt/&lt;/span&gt; directory, this seems to me the clean way, but you can also extract the archive and double-click on the eclipse icon.&lt;br /&gt;I already told on how to install Eclipse in the &lt;span style="font-weight:bold;"&gt;/opt/&lt;/span&gt; directory on my most readed post "&lt;a href="http://kapo-cpp.blogspot.com/2008/01/using-eclipse-for-your-gtkmm-project.html"&gt;Using Eclipse for your gtkmm project (new version)&lt;/a&gt;". &lt;br /&gt;Open a Terminal and first we need to extract the archive and move it on the right place. I download the archive on my &lt;span style="font-weight:bold;"&gt;Public&lt;/span&gt; directory, the first row move on the download directory.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;user@ubuntu710desktop:~$ &lt;span style="font-weight:bold;"&gt;cd Public/&lt;/span&gt;&lt;br /&gt;user@ubuntu710desktop:~/Public$ &lt;span style="font-weight:bold;"&gt;tar xzf eclipse-cpp-ganymede-linux-gtk.tar.gz&lt;/span&gt; &lt;br /&gt;user@ubuntu710desktop:~/Public$ &lt;span style="font-weight:bold;"&gt;sudo mv eclipse /opt/eclipse&lt;/span&gt;&lt;br /&gt;[sudo] password for user:&lt;br /&gt;user@ubuntu710desktop:~/Public$ &lt;span style="font-weight:bold;"&gt;cd /opt/&lt;/span&gt;&lt;br /&gt;user@ubuntu710desktop:/opt$ &lt;span style="font-weight:bold;"&gt;sudo chown -R root:root eclipse&lt;/span&gt;&lt;br /&gt;user@ubuntu710desktop:/opt$ &lt;span style="font-weight:bold;"&gt;sudo chmod -R +r eclipse&lt;/span&gt;&lt;br /&gt;user@ubuntu710desktop:/opt$ &lt;span style="font-weight:bold;"&gt;sudo chmod +x `sudo find eclipse -type d`&lt;/span&gt;&lt;br /&gt;user@ubuntu710desktop:/opt$ &lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we can create the launcher in the &lt;span style="font-weight:bold;"&gt;/bin/&lt;/span&gt; directory:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;user@ubuntu710desktop:/opt$ &lt;span style="font-weight:bold;"&gt;sudo touch /usr/bin/eclipse&lt;/span&gt;&lt;br /&gt;user@ubuntu710desktop:/opt$ &lt;span style="font-weight:bold;"&gt;sudo chmod 755 /usr/bin/eclipse&lt;/span&gt;&lt;br /&gt;user@ubuntu710desktop:/opt$ &lt;span style="font-weight:bold;"&gt;sudo gedit /usr/bin/eclipse&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The last command run &lt;span style="font-weight:bold;"&gt;gedit&lt;/span&gt; (you can use your preferred text editor), we need to paste this text on the file:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#!/bin/sh&lt;br /&gt;#export MOZILLA_FIVE_HOME=&amp;quot;/usr/lib/mozilla/&amp;quot;&lt;br /&gt;export ECLIPSE_HOME=&amp;quot;/opt/eclipse&amp;quot;&lt;br /&gt;&lt;br /&gt;$ECLIPSE_HOME/eclipse $*&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;save the file and close gedit.&lt;br /&gt;Now we can add the Gnome menu entry (I use gedit):&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;user@ubuntu710desktop:/opt$ &lt;span style="font-weight:bold;"&gt;sudo gedit /usr/share/applications/eclipse.desktop&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;we can paste this text:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;[Desktop Entry]&lt;br /&gt;Encoding=UTF-8&lt;br /&gt;Name=Eclipse&lt;br /&gt;Comment=Eclipse IDE&lt;br /&gt;Exec=eclipse&lt;br /&gt;Icon=/opt/eclipse/icon.xpm&lt;br /&gt;Terminal=false&lt;br /&gt;Type=Application&lt;br /&gt;Categories=GNOME;Application;Development;&lt;br /&gt;StartupNotify=true&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;save the file and close gedit.&lt;br /&gt;&lt;h3&gt;Running Eclipse&lt;/h3&gt;&lt;br /&gt;Now on the Gnome menu we can see the Eclipse entry:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SGM-yELTSMI/AAAAAAAAAY0/vVOksF8vDMQ/s1600-h/Ganymede-Gnome-Menu.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SGM-yELTSMI/AAAAAAAAAY0/vVOksF8vDMQ/s320/Ganymede-Gnome-Menu.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216081823260690626" /&gt;&lt;/a&gt;&lt;br /&gt;Unfortunately we don't have the eclipse icon so on the menu we have an anonymous icon. On gnome-look you can find an Eclipse icon (&lt;a href="http://www.gnome-look.org/content/show.php/Eclipse+IDE+icon?content=20398"&gt;here&lt;/a&gt;), if you want to use this icon type the correct name on the "Icon=" line.&lt;br /&gt;So we can run Eclipse, the splash screen of Ganymede is darker:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SGND6FVqqVI/AAAAAAAAAY8/uoVzhDdSD6s/s1600-h/Screenshot-Eclipse+Platform+.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SGND6FVqqVI/AAAAAAAAAY8/uoVzhDdSD6s/s320/Screenshot-Eclipse+Platform+.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216087458569693522" /&gt;&lt;/a&gt;&lt;br /&gt;and, as usual, when we install a new version we need to select a workspace:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SGNEuEEw_SI/AAAAAAAAAZE/NZZFh98WACM/s1600-h/Screenshot-Workspace+Launcher+.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SGNEuEEw_SI/AAAAAAAAAZE/NZZFh98WACM/s320/Screenshot-Workspace+Launcher+.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216088351583567138" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h3&gt;Features&lt;/h3&gt;&lt;br /&gt;On the CDT Wiki site we can find the page "&lt;a href="http://wiki.eclipse.org/CDT/User/NewIn50"&gt;New in CDT 5.0&lt;/a&gt;" with the list of all new features.&lt;br /&gt;The first feature I notice was the spell cecking, enabled by default.&lt;br /&gt;I already write a post on the new features when I try the RC2 "&lt;a href="http://kapo-cpp.blogspot.com/2008/06/install-eclipse-ganymede-rc2-with-cdt.html"&gt;Install Eclipse Ganymede RC2 (with CDT 5.0)&lt;/a&gt;", but since I join the &lt;a href="http://www.eclipse.org/ganymede/map.php"&gt;Ganymede Around the World&lt;/a&gt; contest, I need to rewrite my impression.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Spell checking&lt;/h3&gt;&lt;br /&gt;At first sight I notice the spell checking feature (enabled by default) for strings and comments. I read that this plugin already exist on the previous Eclipse version, but this feature impress me. If you make a mistake writing a comment the unknown word become underlined in red and if you move the mouse pointer over the wrong word a tooltip display availabe fixes.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SGNzGzBQJ2I/AAAAAAAAAZM/FWoBGOU96Bg/s1600-h/Ganymede-Spell.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SGNzGzBQJ2I/AAAAAAAAAZM/FWoBGOU96Bg/s320/Ganymede-Spell.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216139354037036898" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Doxygen integration&lt;/h3&gt;&lt;br /&gt;A good news is the &lt;a href="http://www.stack.nl/~dimitri/doxygen/index.html"&gt;doxygen &lt;/a&gt;integration in the editor. If you enable this option for the project when you start a function documentation using "&lt;span style="font-weight:bold;"&gt;/*!&lt;/span&gt;", when you press [enter] Eclipse automatically add all the doxygen tags for the current function, insert a "&lt;span style="font-weight:bold;"&gt;@param&lt;/span&gt;" tag for each function parameter and the "&lt;span style="font-weight:bold;"&gt;@return&lt;/span&gt;" tag if the function does not return void.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SGOR_mSYTZI/AAAAAAAAAZU/Pg7MZ6ggtkc/s1600-h/Screenshot-Doxygen-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SGOR_mSYTZI/AAAAAAAAAZU/Pg7MZ6ggtkc/s320/Screenshot-Doxygen-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216173315220589970" /&gt;&lt;/a&gt;&lt;br /&gt;And if you want to write the documentation for an enum, always using "/*!" before the enum declaration, when we press [enter] Eclipse automatically put the documentation for each enum member:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SGOT2IuTW5I/AAAAAAAAAZc/uGjoIU0Aonc/s1600-h/Screenshot-Doxygen-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SGOT2IuTW5I/AAAAAAAAAZc/uGjoIU0Aonc/s320/Screenshot-Doxygen-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216175351689075602" /&gt;&lt;/a&gt;&lt;br /&gt;The documentation plugin suggest us also the list of tags when we press [ctrl+space].&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Refactoring&lt;/h3&gt;&lt;br /&gt;While on previous CDT version we have only the "Rename" &lt;a href="http://en.wikipedia.org/wiki/Refactoring"&gt;refactoring&lt;/a&gt;, now we can:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Generate Getter Setters&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hide Method&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Implement Method&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Extract Constant&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Extract Function&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;When we select a refactoring Eclipse display a preview window before apply changes on the code.&lt;br /&gt;&lt;h4&gt;Generate Getter and Setters&lt;/h4&gt;&lt;br /&gt;This refactoring simplify the class attribute writing. If we declare a private variable:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;int value_;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;and then right-click on this and select from the menu "Refactor-&gt;Generate Getters and Setters", with a wizard (or assistant) Eclipse automatically write the two functions for get and set this variable:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    int getValue() const&lt;br /&gt;    {&lt;br /&gt;        return value_;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void setValue(int value_)&lt;br /&gt;    {&lt;br /&gt;        this-&amp;gt;value_ = value_;&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The const get function and the void set function. From the wizard dialog we can choose also if we want to create only the getter or both.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SGSDYLZdl8I/AAAAAAAAAZk/S614GjkD6f4/s1600-h/Screenshot-Ref-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SGSDYLZdl8I/AAAAAAAAAZk/S614GjkD6f4/s320/Screenshot-Ref-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216438719801563074" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4&gt;Hide Method&lt;/h4&gt;&lt;br /&gt;This refactoring "move" a public function in the private section of the class. If we declare a public function:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class BaseClass&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    BaseClass();&lt;br /&gt;    virtual ~BaseClass();&lt;br /&gt;&lt;br /&gt;    int getValue() const&lt;br /&gt;    {&lt;br /&gt;        return value_;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void setValue(int value_)&lt;br /&gt;    {&lt;br /&gt;        this-&amp;gt;value_ = value_;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void myMethod(int arg);&lt;br /&gt;&lt;br /&gt;private:&lt;br /&gt;    int value_;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;When we right-click on desired function and select from the menu "Refactor-&gt;Hide method" we get:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;class BaseClass&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    BaseClass();&lt;br /&gt;    virtual ~BaseClass();&lt;br /&gt;&lt;br /&gt;    int getValue() const&lt;br /&gt;    {&lt;br /&gt;        return value_;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    void setValue(int value_)&lt;br /&gt;    {&lt;br /&gt;        this-&amp;gt;value_ = value_;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;private:&lt;br /&gt;    int value_;&lt;br /&gt;    void myMethod(int arg);&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;If we have not a private section on the class Eclipse automatically add this section.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SGSHz5AIoMI/AAAAAAAAAZs/ex2_mzPxBdY/s1600-h/Screenshot-Ref-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SGSHz5AIoMI/AAAAAAAAAZs/ex2_mzPxBdY/s320/Screenshot-Ref-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216443593946341570" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Implement Method&lt;/h4&gt;&lt;br /&gt;This is for me the more useful refactoring. If we declare a function in the header file:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    void myMethod(int arg);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt; &lt;br /&gt;when we right-click on the function and select from the menu "Refactor-&gt;Implement Method", Eclipse automatically declare the function in the implementation file.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void BaseClass::myMethod(int arg)&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Usually I write the implementation with a sophisticated [ctrl-c] [ctrl-v], but I am waiting for this refactoring from long time.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SGSNm9nnh9I/AAAAAAAAAZ0/7lAOhUIZynA/s1600-h/Screenshot-Ref-3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SGSNm9nnh9I/AAAAAAAAAZ0/7lAOhUIZynA/s320/Screenshot-Ref-3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216449968917153746" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4&gt;Extract Constant&lt;/h4&gt;&lt;br /&gt;This is a more sophisticated refactoring. If we write bad code and spread constant value on the code, like this:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void BaseClass::myMethod(int arg)&lt;br /&gt;{&lt;br /&gt;    arg += 100;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void BaseClass::myMethod2(int arg)&lt;br /&gt;{&lt;br /&gt;    arg += 100;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;when we right-click on one occurrence of the value we want to declare as constant, select from the menu "Refactor-&gt;Extract constant", we are prompted to enter the constant name and to choose the visibilty, and finally we get:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;namespace &lt;br /&gt;{&lt;br /&gt;    const int Step_ = 100;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;void BaseClass::myMethod(int arg)&lt;br /&gt;{&lt;br /&gt;    arg += Step_;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void BaseClass::myMethod2(int arg)&lt;br /&gt;{&lt;br /&gt;    arg += Step_;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;More convenient than search and replace.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SGSXu2jlYJI/AAAAAAAAAZ8/_U51mKQAgnw/s1600-h/Screenshot-Ref-4.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SGSXu2jlYJI/AAAAAAAAAZ8/_U51mKQAgnw/s320/Screenshot-Ref-4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216461099576418450" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h4&gt;Extract Function&lt;/h4&gt;&lt;br /&gt;This is the most complicated refactoring. We can use this refactoring when we have a piece of code in a function and we need to extract only this lines and create a new function. This is not simply move some lines, if this piece of code reference a variable declared is some other place this means we need an argument on the new function. Suppose we have this function:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void BaseClass::myMethod(int arg)&lt;br /&gt;{&lt;br /&gt;    int b = arg + 10;&lt;br /&gt;&lt;br /&gt;    arg = b;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;we want to extract the first line and create a new function. We select the line and from the menu we select "Refactor-&gt;Extract function". On the refactoring dialog we have to set the new function name, we can also see the arguments required by the new function. For my example the new function require the &lt;span style="font-weight:bold;"&gt;arg&lt;/span&gt; integer parameter. The refactored code is:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;int BaseClass::addStep(int &amp;amp; arg)&lt;br /&gt;{&lt;br /&gt;    int b = arg + 10;&lt;br /&gt;    return b;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void BaseClass::myMethod(int arg)&lt;br /&gt;{&lt;br /&gt;    int b = addStep(arg);&lt;br /&gt;&lt;br /&gt;    arg = b;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;I try this refactoring on different contexts and it always generate the correct function.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SGScwrBCvRI/AAAAAAAAAaE/ox56rYveImw/s1600-h/Screenshot-Ref-5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SGScwrBCvRI/AAAAAAAAAaE/ox56rYveImw/s320/Screenshot-Ref-5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5216466628396629266" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-8840733481569345598?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/8840733481569345598/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/06/finally-ganymede.html#comment-form' title='10 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/8840733481569345598'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/8840733481569345598'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/06/finally-ganymede.html' title='Finally Ganymede'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/SGM-yELTSMI/AAAAAAAAAY0/vVOksF8vDMQ/s72-c/Ganymede-Gnome-Menu.png' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-3941584852400693097</id><published>2008-06-23T08:52:00.002+02:00</published><updated>2008-06-23T08:59:46.828+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>Uninstall Eclipse</title><content type='html'>If you follow &lt;a href="http://kapo-cpp.blogspot.com/2008/01/using-eclipse-for-your-gtkmm-project.html"&gt;my guide&lt;/a&gt; for install Eclipse or you try to &lt;a href="http://kapo-cpp.blogspot.com/2008/06/install-eclipse-ganymede-rc2-with-cdt.html"&gt;install the Ganymede RC2&lt;/a&gt; on the same way, and now you want to uninstall it you simply need to remove all generated files.&lt;br /&gt;Remove the Gnome menu entry:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo rm /usr/share/applications/eclipse-ganymede-rc2.desktop&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Remove the launcher on &lt;span style="font-weight:bold;"&gt;/usr/bin&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo rm /usr/bin/eclipse-ganymede-rc2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Remove the directory &lt;span style="font-weight:bold;"&gt;/opt/eclipse&lt;/span&gt; where we copy the extracted archive:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo rm -rf /opt/eclipse-ganymede-rc2/&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we can try Eclipse Ganymede RC4&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-3941584852400693097?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/3941584852400693097/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/06/uninstall-eclipse.html#comment-form' title='4 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/3941584852400693097'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/3941584852400693097'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/06/uninstall-eclipse.html' title='Uninstall Eclipse'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-8855341078482806583</id><published>2008-06-10T07:53:00.012+02:00</published><updated>2008-12-11T09:43:45.051+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>Install Eclipse Ganymede RC2 (with CDT 5.0)</title><content type='html'>I'm waiting for this version of Eclipse from long time, when I read the CDT 5.0 plan. I think that with this version we have the best open source C++ IDE (but may be I don't try all IDEs of the world).&lt;br /&gt;If you read my blog you are already using Eclipse (installed as I told on &lt;a href="http://kapo-cpp.blogspot.com/2008/01/using-eclipse-for-your-gtkmm-project.html"&gt;this post&lt;/a&gt;). Since we don't want to wait until the end of june we will install the RC2 version but mantaining the old stable version, in this way we can test the RC2 and use both.&lt;br /&gt;Go to the Eclipse Ganymede RC2 &lt;a href="http://www.eclipse.org/downloads/packages/"&gt;download page&lt;/a&gt; and select &lt;span style="font-weight:bold;"&gt;Eclipse IDE for C/C++ Developers&lt;/span&gt; for download Eclipse with CDT plugin.&lt;br /&gt;It's hard but we need to wait until the download is complete.&lt;br /&gt;Ok, now we can install Eclipse on the &lt;span style="font-weight:bold;"&gt;/opt&lt;/span&gt; directory. We will install Eclipse RC2 on the &lt;span style="font-weight:bold;"&gt;/opt/eclipse-ganymede-rc2&lt;/span&gt; directory, we already have &lt;span style="font-weight:bold;"&gt;/opt/eclipse&lt;/span&gt;.&lt;br /&gt;Now open a Terminal.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;tar xzf eclipse-cpp-ganymede-RC2-linux-gtk.tar.gz&lt;br /&gt;sudo mv eclipse /opt/eclipse-ganymede-rc2&lt;br /&gt;cd /opt/&lt;br /&gt;sudo chown -R root:root eclipse-ganymede-rc2/&lt;br /&gt;sudo chmod -R +r eclipse-ganymede-rc2/&lt;br /&gt;sudo chmod +x `sudo find eclipse-ganymede-rc2 -type d`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we can create the lunch script on &lt;span style="font-weight:bold;"&gt;/usr/bin&lt;/span&gt; using gedit:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo touch /usr/bin/eclipse-ganymede-rc2&lt;br /&gt;sudo chmod 755 /usr/bin/eclipse-ganymede-rc2&lt;br /&gt;sudo gedit /usr/bin/eclipse-ganymede-rc2&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;and paste this:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#!/bin/sh&lt;br /&gt;#export MOZILLA_FIVE_HOME=&amp;quot;/usr/lib/mozilla/&amp;quot;&lt;br /&gt;export ECLIPSE_HOME=&amp;quot;/opt/eclipse-ganymede-rc2&amp;quot;&lt;br /&gt;&lt;br /&gt;$ECLIPSE_HOME/eclipse $*&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Save the file and close gedit.&lt;br /&gt;Now we can create the menu item using gedit:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo gedit /usr/share/applications/eclipse-ganymede-rc2.desktop&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;and paste this (I use the old Eclipse icon on /opt/eclipse since it is not present in the RC2 package):&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;[Desktop Entry]&lt;br /&gt;Encoding=UTF-8&lt;br /&gt;Name=Eclipse Ganymede RC2&lt;br /&gt;Comment=Eclipse IDE&lt;br /&gt;Exec=eclipse-ganymede-rc2&lt;br /&gt;Icon=/opt/eclipse/icon.xpm&lt;br /&gt;Terminal=false&lt;br /&gt;Type=Application&lt;br /&gt;Categories=GNOME;Application;Development;&lt;br /&gt;StartupNotify=true&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Save and close gedit.&lt;br /&gt;&lt;h2&gt;Using Eclipse&lt;/h2&gt;&lt;br /&gt;Now if we open the Gnome menu we can see:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SE4lUZAfiTI/AAAAAAAAAXU/wMSR9M3P2d8/s1600-h/Screenshot-Eclipse-RC2-Menu-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SE4lUZAfiTI/AAAAAAAAAXU/wMSR9M3P2d8/s320/Screenshot-Eclipse-RC2-Menu-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210142851154807090" /&gt;&lt;/a&gt;&lt;br /&gt;We can lunch Eclipse Ganymede RC2 and see Eclipse splash:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SE46kAay8WI/AAAAAAAAAXc/dHKu7X2w94E/s1600-h/Screenshot-Eclipse-RC2-Splash-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SE46kAay8WI/AAAAAAAAAXc/dHKu7X2w94E/s320/Screenshot-Eclipse-RC2-Splash-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210166209176334690" /&gt;&lt;/a&gt;&lt;br /&gt;and after this we have to select the workspace. I use my default workspace, the same I use for the Eclipse stable version: &lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SE4_k_Xo9AI/AAAAAAAAAXk/Qu8o58zwQW8/s1600-h/Screenshot-Eclipse-RC2-Workspace-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SE4_k_Xo9AI/AAAAAAAAAXk/Qu8o58zwQW8/s320/Screenshot-Eclipse-RC2-Workspace-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210171723632669698" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h3&gt;Spell check&lt;/h3&gt;&lt;br /&gt;The first visible feature is the spell-checking on comments and string constants. I think this is a good idea, especially for me since I don't know english very well but I insist on write comment in eglish. If a word is not in the dictionary the editor underline the word and when we move the mouse pointer on the word a tooltip display suggestions.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SE5uMa-fFmI/AAAAAAAAAXs/HQS9MjOJ__4/s1600-h/Screenshot-Eclipse-RC2-SpellCheck-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SE5uMa-fFmI/AAAAAAAAAXs/HQS9MjOJ__4/s320/Screenshot-Eclipse-RC2-SpellCheck-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210222978593134178" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;h3&gt;Refactoring&lt;/h3&gt;&lt;br /&gt;The main feature, for me, is the refactoring. On CDT 5.0 we have not only the "Rename" option, further we can: "Extract constant", "Extract function", "Hide method" and the two refactoring I wait: "Generate getters and setters" and "Implement method".&lt;br /&gt;The "Generate getters and setters" write for us the get and set functions for a class attribute. We simply need to right-click on a class attribute and select from the Refactor menu the "Generate getters and setters" option.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SE6FLFlc6DI/AAAAAAAAAX0/snOolVd49E4/s1600-h/Screenshot-Eclipse-RC2-Refactoring1-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SE6FLFlc6DI/AAAAAAAAAX0/snOolVd49E4/s320/Screenshot-Eclipse-RC2-Refactoring1-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210248244438558770" /&gt;&lt;/a&gt;&lt;br /&gt;A wizard dialog appear and we can choose desired functions:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SE6FLX9ZSNI/AAAAAAAAAX8/g9WX4TBPqXc/s1600-h/Screenshot-Eclipse-RC2-Refactoring1-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SE6FLX9ZSNI/AAAAAAAAAX8/g9WX4TBPqXc/s320/Screenshot-Eclipse-RC2-Refactoring1-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210248249370822866" /&gt;&lt;/a&gt;&lt;br /&gt;when we click Next we can see the refactoring preview:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SE6FLrNnsHI/AAAAAAAAAYE/F7XYeOU8wRY/s1600-h/Screenshot-Eclipse-RC2-Refactoring1-3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SE6FLrNnsHI/AAAAAAAAAYE/F7XYeOU8wRY/s320/Screenshot-Eclipse-RC2-Refactoring1-3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210248254539149426" /&gt;&lt;/a&gt;&lt;br /&gt;and if we click Finish the changes to the code are applied.&lt;br /&gt;The "Implement method" refactoring is my preferred, I think to this refactor evry time I need to write a function. If we declare a function in the header file using this refactor Eclipse automatically add required code on the implementation file. We can select "Implement method" from the Refactor menu.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SE6OGyqsr4I/AAAAAAAAAYM/zWAXmSNX8ZM/s1600-h/Screenshot-Eclipse-RC2-Refactoring2-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SE6OGyqsr4I/AAAAAAAAAYM/zWAXmSNX8ZM/s320/Screenshot-Eclipse-RC2-Refactoring2-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210258066245463938" /&gt;&lt;/a&gt;&lt;br /&gt;On the Refactoring dialog we can see the preview:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SE6OHUNkTJI/AAAAAAAAAYU/XEWGpC0Bi1A/s1600-h/Screenshot-Eclipse-RC2-Refactoring2-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SE6OHUNkTJI/AAAAAAAAAYU/XEWGpC0Bi1A/s320/Screenshot-Eclipse-RC2-Refactoring2-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210258075250085010" /&gt;&lt;/a&gt;&lt;br /&gt;if we click Finish the refactoring update the cpp file.&lt;br /&gt;Also the "Extract function" refactoring is a new entry, but rarely we need to perform this refactoring. We can select a piece of code from an existing function and when we select "Extract function" from the Refactor menu.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SE6TzBVUd9I/AAAAAAAAAYc/jYwTiSNrEiI/s1600-h/Screenshot-Eclipse-RC2-Refactoring3-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SE6TzBVUd9I/AAAAAAAAAYc/jYwTiSNrEiI/s320/Screenshot-Eclipse-RC2-Refactoring3-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210264323654711250" /&gt;&lt;/a&gt;&lt;br /&gt;The Refactoring wizard appear and we can enter the name of the new function to generate. We can see also the list of the new function arguments. This arguments are automatically detected depending on selected code, and it works!&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SE6TzYjcHzI/AAAAAAAAAYk/wGeO4b5-7CI/s1600-h/Screenshot-Eclipse-RC2-Refactoring3-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SE6TzYjcHzI/AAAAAAAAAYk/wGeO4b5-7CI/s320/Screenshot-Eclipse-RC2-Refactoring3-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210264329887948594" /&gt;&lt;/a&gt;&lt;br /&gt;If we click Next we can see the preview.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SE6TzfoNDuI/AAAAAAAAAYs/UYNy8luK8uM/s1600-h/Screenshot-Eclipse-RC2-Refactoring3-3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SE6TzfoNDuI/AAAAAAAAAYs/UYNy8luK8uM/s320/Screenshot-Eclipse-RC2-Refactoring3-3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5210264331786981090" /&gt;&lt;/a&gt;&lt;br /&gt;When we click finish the new function is automatically generated.&lt;br /&gt;&lt;h3&gt;Autotools&lt;/h3&gt;&lt;br /&gt;The only feature I miss is the autotools integration. I try the CDT plugin for autotools but for me is not complete (or may be I am not be able to use it).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-8855341078482806583?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/8855341078482806583/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/06/install-eclipse-ganymede-rc2-with-cdt.html#comment-form' title='5 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/8855341078482806583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/8855341078482806583'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/06/install-eclipse-ganymede-rc2-with-cdt.html' title='Install Eclipse Ganymede RC2 (with CDT 5.0)'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/SE4lUZAfiTI/AAAAAAAAAXU/wMSR9M3P2d8/s72-c/Screenshot-Eclipse-RC2-Menu-2.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-7632535014466094601</id><published>2008-05-23T07:55:00.004+02:00</published><updated>2008-12-11T09:43:45.197+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='cairomm'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Resize a Pixbuf</title><content type='html'>As you know for my ggredit the user can edit properties of selected objects using the properties-browser, a TreeView with custom CellRenderers. On the post "&lt;a href="http://kapo-cpp.blogspot.com/2008/05/different-cellrenderers-on-same-column.html"&gt;Different CellRenderers on the same Column&lt;/a&gt;" I start to implement a method for display different CellRenderers on the same TreeViewColumn, and I am be able to display Colors and Text on the same column using two different CellRenderers.&lt;br /&gt;For edit Image properties I would like to use a widget that show a miniature of selected image in the properties-browser.&lt;br /&gt;For Image management we have the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html"&gt;Gdk::Pixbuf&lt;/a&gt; class. I draw the Pixbuf on a &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html"&gt;Cairo::Context&lt;/a&gt; on the way I already told on my post "&lt;a href="http://kapo-cpp.blogspot.com/2008/01/drawing-pixbuf-to-cairo-context-2.html"&gt;Drawing pixbuf to Cairo context (2)&lt;/a&gt;".&lt;br /&gt;The first method I use for resize the source Pixbuf was to apply a transformation matrix to the Cairo::Coontext, like this:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Compute scale&lt;br /&gt;    double required_size = 22;&lt;br /&gt;    double max_in_size = std::max(image_ptr_-&amp;gt;get_width(), image_ptr_-&amp;gt;get_height());&lt;br /&gt;    double f_scale = required_size / max_img_size;&lt;br /&gt;    &lt;br /&gt;    // Set context scale&lt;br /&gt;    context-&amp;gt;scale (f_scale, f_scale);&lt;br /&gt;    &lt;br /&gt;    // Draw the source image&lt;br /&gt;    context-&amp;gt;set_source (image_surface_ptr_, 0.0, 0.0);&lt;br /&gt;    context-&amp;gt;rectangle (0.0, 0.0, image_ptr_-&amp;gt;get_width(), image_ptr_-&amp;gt;get_height());&lt;br /&gt;    context-&amp;gt;fill();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;But the result of the resize operation is ugly, Cairo resize the image without using interpolation so the output is not good.&lt;br /&gt;I don't know the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#73e2c7be0469e402cc20fbad27015767"&gt;Gdk::Pixbuf::scale_simple&lt;/a&gt; function, this function create a new Pixbuf from an already loaded Pixbuf. We can give to this function required &lt;span style="font-style:italic;"&gt;width&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;height &lt;/span&gt;and the interpolation type. The interpolation type can be one of the enumeration &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/group__gdkmmEnums.html#g709a35a3eb48c0b819041e3414715fac"&gt;Gdk::InterpType&lt;/a&gt;, and define the algorithm to use for resize the source Pixbuf. Gtkmm documentation suggest to use Gdk::INTERP_BILINEAR. On the bilinear interpolation algorithm each pixel color is the average of neighborhood pixels, and the output result is good.&lt;br /&gt;So we can resize a Pixbuf using:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    double required_size = 22;&lt;br /&gt;    double max_img_size = std::max (image_ptr_-&amp;gt;get_width(), image_ptr_-&amp;gt;get_height());&lt;br /&gt;    int scaled_width = int(required_size * (image_ptr_-&amp;gt;get_width() / max_img_size));&lt;br /&gt;    int scaled_height = int(required_size * (image_ptr_-&amp;gt;get_height() / max_img_size));&lt;br /&gt;    &lt;br /&gt;    icon_image_ptr_ = image_ptr-&amp;gt;scale_simple(scaled_width, scaled_height, Gdk::INTERP_BILINEAR);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For mantain aspect ratio I compute required width and height using the the maximum dimension of the source image. In this way the maximum dimension of the source image fit required size, the other dimension was modified for respect aspect ratio.&lt;br /&gt;I use this method for render a Pixbuf on the TreeViewColumn. And this is the result:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SDaNkvo7tEI/AAAAAAAAAXM/hXzUTEIchvo/s1600-h/Screenshot-GraphicEditor-Resize-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SDaNkvo7tEI/AAAAAAAAAXM/hXzUTEIchvo/s320/Screenshot-GraphicEditor-Resize-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5203502081876145218" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-7632535014466094601?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/7632535014466094601/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/05/resize-pixbuf.html#comment-form' title='3 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7632535014466094601'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7632535014466094601'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/05/resize-pixbuf.html' title='Resize a Pixbuf'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_sQJ1m4QDkME/SDaNkvo7tEI/AAAAAAAAAXM/hXzUTEIchvo/s72-c/Screenshot-GraphicEditor-Resize-2.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-4517643617795671544</id><published>2008-05-16T12:40:00.003+02:00</published><updated>2008-12-11T09:43:45.363+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>Base64</title><content type='html'>For store binary data on an xml file the most used way is to encode data using &lt;a href="http://en.wikipedia.org/wiki/Base64"&gt;Base64&lt;/a&gt;.&lt;br /&gt;With &lt;a href="http://xmlsoft.org/"&gt;libxml2&lt;/a&gt; we can encode data and write the Base64 string to the xml file using &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html#xmlTextWriterWriteBase64"&gt;xmlTextWriterWriteBase64&lt;/a&gt;, unfortunately we can not decode this string when we read the xml file using libxml2, the function of decode Base64 was not implemented (or I don't be able to found it).&lt;br /&gt;On Wikipedia there is a good explanation of how Base64 works. And searching on Google we can find many algorithm for this issue. This is my way, a c++ approach.&lt;br /&gt;The &lt;span style="font-style:italic;"&gt;encode&lt;/span&gt; function accept a raw-pointer as argument (the source buffer) and return an &lt;a href="http://www.cplusplus.com/reference/string/string/"&gt;std::string&lt;/a&gt;, created using &lt;a href="http://www.cplusplus.com/reference/iostream/stringstream/"&gt;std::stringstream&lt;/a&gt;. This function is based on the one published on Wikipedia (using C).&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;std::string encode(uint8_t* buf_ptr, size_t buf_size)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;span style="font-style:italic;"&gt;decode&lt;/span&gt; function accept an &lt;span style="font-weight:bold;"&gt;std::string&lt;/span&gt; as argument (the source encoded) and return a pointer to the decoded buffer using &lt;a href="http://en.wikipedia.org/wiki/Auto_ptr"&gt;std::auto_ptr&lt;/a&gt; (the ownership return to the caller).&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;std::auto_ptr&amp;lt; uint8_t &amp;gt; decode(const std::string&amp;amp; text)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Here is the code:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #e2ebf8;font-size: 12px;border: 1px;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/SICR1uI3ZbI/AAAAAAAAAa8/lvuv8fy5US8/s1600-h/dialog-warning.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/SICR1uI3ZbI/AAAAAAAAAa8/lvuv8fy5US8/s200/dialog-warning.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5224335919854085554" /&gt;&lt;/a&gt;This code does not work well look &lt;a href="http://kapo-cpp.blogspot.com/2008/07/fixing-my-base64-functions.html"&gt;here&lt;/a&gt; for the bug fixed version.&lt;/pre&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#ifndef BASE64_H_&lt;br /&gt;#define BASE64_H_&lt;br /&gt;&lt;br /&gt;#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;#include &amp;lt;string&amp;gt;&lt;br /&gt;#include &amp;lt;sstream&amp;gt;&lt;br /&gt;#include &amp;lt;memory&amp;gt;&lt;br /&gt;&lt;br /&gt;namespace base64&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;const char base64chars[] = &amp;quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&amp;quot;;&lt;br /&gt;const char base64pad = '=';&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * @brief Encode a buffer on a string base64 encoded&lt;br /&gt; * &lt;br /&gt; * Base 64 encoding converts 3 bytes into 4 encoded ASCII &lt;br /&gt; * characters.&lt;br /&gt; * If the encoded string lenght is not multiple of 4&lt;br /&gt; * the padding character &amp;quot;=&amp;quot; is added for fill the buffer.&lt;br /&gt; *  &lt;br /&gt; * @param buf_ptr pointer to the source buffer&lt;br /&gt; * @param buf_size size of the buffer&lt;br /&gt; * &lt;br /&gt; * @return a string base64 encoded&lt;br /&gt; * &lt;br /&gt; * @see http://en.wikipedia.org/wiki/Base64&lt;br /&gt; */&lt;br /&gt;std::string encode(uint8_t* buf_ptr, size_t buf_size)&lt;br /&gt;{&lt;br /&gt;   uint32_t n = 0;&lt;br /&gt;   uint8_t n0, n1, n2, n3;&lt;br /&gt;   std::stringstream ss_result;&lt;br /&gt;   &lt;br /&gt;   // Iterate over the buffer&lt;br /&gt;   for (size_t x = 0; x &amp;lt; buf_size; x += 3) &lt;br /&gt;   {&lt;br /&gt;      // Get 3 bytes of 8 bit from the buffer &lt;br /&gt;      n = buf_ptr[x] &amp;lt;&amp;lt; 16;&lt;br /&gt; &lt;br /&gt;      if ((x+1) &amp;lt; buf_size)&lt;br /&gt;      {&lt;br /&gt;          n += buf_ptr[x+1] &amp;lt;&amp;lt; 8;&lt;br /&gt; &lt;br /&gt;          if ((x+2) &amp;lt; buf_size)&lt;br /&gt;          {&lt;br /&gt;             n += buf_ptr[x+2];&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;      &lt;br /&gt;      // Transform on 4 bytes of 6 bit&lt;br /&gt;      n0 = (uint8_t)(n &amp;gt;&amp;gt; 18) &amp;amp; 63;&lt;br /&gt;      n1 = (uint8_t)(n &amp;gt;&amp;gt; 12) &amp;amp; 63;&lt;br /&gt;      n2 = (uint8_t)(n &amp;gt;&amp;gt; 6) &amp;amp; 63;&lt;br /&gt;      n3 = (uint8_t)n &amp;amp; 63;&lt;br /&gt; &lt;br /&gt;      // Write first 2 bytes into the stream&lt;br /&gt;      ss_result &amp;lt;&amp;lt; base64chars[n0];&lt;br /&gt;      ss_result &amp;lt;&amp;lt; base64chars[n1];&lt;br /&gt;&lt;br /&gt;      // Test if only 2 bytes&lt;br /&gt;      if ((x+1) &amp;lt; buf_size)&lt;br /&gt;      {&lt;br /&gt;          // Write 3rd into the stream&lt;br /&gt;          ss_result &amp;lt;&amp;lt; base64chars[n2];&lt;br /&gt; &lt;br /&gt;          // Test if only 3 bytes&lt;br /&gt;          if ((x+2) &amp;lt; buf_size)&lt;br /&gt;          {&lt;br /&gt;              // Write 4th into the stream&lt;br /&gt;              ss_result &amp;lt;&amp;lt; base64chars[n3];&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;   }  &lt;br /&gt; &lt;br /&gt;   // Add padding character for fill the output string&lt;br /&gt;   for (int pad_count = buf_size % 3; pad_count &amp;lt; 3; pad_count++) &lt;br /&gt;   { &lt;br /&gt;       ss_result &amp;lt;&amp;lt; base64pad;&lt;br /&gt;   } &lt;br /&gt;   &lt;br /&gt;   return ss_result.str();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * @brief Decode a string base64 encoded and return a raw buffer&lt;br /&gt; * &lt;br /&gt; * The function allocate a buffer with size: &lt;br /&gt; * @(text.size() + 3) / 4 * 3&lt;br /&gt; * and return the pointer. The caller has the ownership of the&lt;br /&gt; * pointer.&lt;br /&gt; * The source string lenght must be multiple of 4.&lt;br /&gt; *  &lt;br /&gt; * @param text the base64 string encoded&lt;br /&gt; * &lt;br /&gt; * @return the pointer to the decoded buffer&lt;br /&gt; */&lt;br /&gt;std::auto_ptr&amp;lt; uint8_t &amp;gt; decode(const std::string&amp;amp; text)&lt;br /&gt;{&lt;br /&gt;    // Create the decode matrix&lt;br /&gt;    uint8_t decode_base64chars[256];&lt;br /&gt;    memset (decode_base64chars, 0, 256);&lt;br /&gt;    &lt;br /&gt;    for (uint8_t i = 0; i &amp;lt;= 63; i++)&lt;br /&gt;    {&lt;br /&gt;        decode_base64chars[(int)base64chars[(int)i]] = i;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Allocate output buffer&lt;br /&gt;    uint8_t* buf_ptr = new guint8[(text.size() + 3) / 4 * 3];&lt;br /&gt;    &lt;br /&gt;    // Start decode source string&lt;br /&gt;    size_t buf_idx = 0;&lt;br /&gt;    for (size_t i = 0; i &amp;lt; text.size(); i += 4, buf_idx += 3)&lt;br /&gt;    {&lt;br /&gt;        // Put first base64 char on the first output-byte&lt;br /&gt;        buf_ptr[buf_idx] = decode_base64chars[(int)text[i]] &amp;lt;&amp;lt; 2;&lt;br /&gt;        &lt;br /&gt;        // Test for string end&lt;br /&gt;        if ((i + 1 &amp;lt; text.size()) &amp;amp;&amp;amp; (text[i + 1] != base64pad))&lt;br /&gt;        {&lt;br /&gt;            // Add to the first output-byte 2 bit of the second base64 char&lt;br /&gt;            buf_ptr[buf_idx] += (decode_base64chars[(int)text[i + 1]] &amp;gt;&amp;gt; 6) &amp;amp; 0x3;&lt;br /&gt;        &lt;br /&gt;            // Put remaining 4 bit of the second base64 char on the second output-byte&lt;br /&gt;            buf_ptr[buf_idx + 1] = decode_base64chars[(int)text[i + 1]] &amp;lt;&amp;lt; 4;&lt;br /&gt;            &lt;br /&gt;            // Test for string end&lt;br /&gt;            if ((i + 2 &amp;lt; text.size()) &amp;amp;&amp;amp; (text[i + 2] != base64pad))&lt;br /&gt;            {&lt;br /&gt;                // Add to the second output-byte 4 bit of the third base64 char&lt;br /&gt;                buf_ptr[buf_idx + 1] += (decode_base64chars[(int)text[i + 2]] &amp;gt;&amp;gt; 4) &amp;amp; 0xf;&lt;br /&gt;                &lt;br /&gt;                // Put remaining 2 bit of the third base64 char on the third output-byte&lt;br /&gt;                buf_ptr[buf_idx + 2] = decode_base64chars[(int)text[i + 2]] &amp;lt;&amp;lt; 6;&lt;br /&gt;                &lt;br /&gt;                // Test for string end&lt;br /&gt;                if ((i + 1 &amp;lt; text.size()) &amp;amp;&amp;amp; (text[i + 3] != base64pad))&lt;br /&gt;                {&lt;br /&gt;                    // Add to the third output-byte the forth base64 char&lt;br /&gt;                    buf_ptr[buf_idx + 2] += decode_base64chars[(int)text[i + 3]];&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    return std::auto_ptr&amp;lt;uint8_t&amp;gt;(buf_ptr);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif /*BASE64_H_*/&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-4517643617795671544?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/4517643617795671544/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/05/base64.html#comment-form' title='7 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/4517643617795671544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/4517643617795671544'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/05/base64.html' title='Base64'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_sQJ1m4QDkME/SICR1uI3ZbI/AAAAAAAAAa8/lvuv8fy5US8/s72-c/dialog-warning.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-7559741623391906100</id><published>2008-05-16T10:35:00.000+02:00</published><updated>2008-05-16T10:39:28.583+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Raw Pixbuf image data</title><content type='html'>For my ggredit I need to serialize a &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html"&gt;Gdk::Pixbuf&lt;/a&gt; into an &lt;a href="http://www.w3.org/XML/"&gt;xml&lt;/a&gt; file (using &lt;a href="http://en.wikipedia.org/wiki/Base64"&gt;base 64 encoding&lt;/a&gt;) and subsequently retrieve the Gdk::Pixbuf from the xml file. &lt;br /&gt;First I save on the ggredit xml file the full path and name of the image, but in this way the user can not share his ggredit file without coping also all referenced images and using the same directory structure (like html). So I prefer to include images on my ggredit file.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;Using &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#df7f4e324769b180dc0f0bfd053ff47a"&gt;Gdk::Pixbuf::get_pixels()&lt;/a&gt; we have access to raw datas of the Gdk::Pixbuf, we can read on the documentation:&lt;br /&gt;&lt;blockquote&gt;A pointer to the pixbuf's pixel data. Please see &amp;lt;xref linkend="image-data"/&amp;gt; for information about how the pixel data is stored in memory.&lt;/blockquote&gt;&lt;br /&gt;I search for the "image-data" on Gtkmm documentation but I don't find nothing. I think the real link should point the section "&lt;a href="http://developer.gimp.org/api/2.0/gdk-pixbuf/gdk-pixbuf-gdk-pixbuf.html#image-data"&gt;Image data&lt;/a&gt;" on GNOME documentation.&lt;br /&gt;The &lt;span style="font-weight:bold;"&gt;Gdk::Pixbuf::get_pixels()&lt;/span&gt; function return the raw pointer but we don't know the size of the buffer. The &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#ef37137e7f42a5734deb0f9be25ef030"&gt;Gdk::Pixbuf::get_rowstride()&lt;/a&gt; return the size of a single row but on GNOME we can read that last row can have a different size. The size of the buffer is:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Get Pixbuf from an image&lt;br /&gt;    Glib::RefPtr&amp;lt; Gdk::Pixbuf &amp;gt; pixbuf_ref = source_image_.get_pixbuf();&lt;br /&gt;    // Size except last row&lt;br /&gt;    size_t buf_size = pixbuf_ref-&amp;gt;get_rowstride() * (pixbuf_ref-&amp;gt;get_height() - 1);&lt;br /&gt;    // Add last row size&lt;br /&gt;    buf_size += pixbuf_ref-&amp;gt;get_width() * ((pixbuf_ref-&amp;gt;get_n_channels() * pixbuf_ref-&amp;gt;get_bits_per_sample() + 7) / 8);&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The reverse operation, we have a raw buffer for create a Gdk::Pixbuf, is done by the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#8a3b524f26acd2f9efc4abe9c294d341"&gt;Gdk::Pixbuf::create_from_data()&lt;/a&gt; static member function. We need to give:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;data&lt;/span&gt;: the raw buffer&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;colorspace&lt;/span&gt;: the constant &lt;span style="font-weight:bold;"&gt;Gdk::COLORSPACE_RGB&lt;/span&gt; is the only allowed value (see &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/group__gdkmmEnums.html#g866d716154abb7f5be26bd36b3017d3f"&gt;Colorspace&lt;/a&gt;)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;has_alpha&lt;/span&gt;: the value returned by &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#f467c7efa88fa42b067de1b98428fad7"&gt;get_has_alpha()&lt;/a&gt; on the source Pixbuf&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;bits_per_sample&lt;/span&gt;: the value returned by &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#e9e2312c80e5ebc911c469c822dee96e"&gt;get_bits_per_sample()&lt;/a&gt; on the source Pixbuf&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;width&lt;/span&gt;: the value returned by &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#a465be4bf65b9fedf471848c21bfab98"&gt;get_width()&lt;/a&gt; on the source Pixbuf&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;height&lt;/span&gt;: the value returned by &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#2a65cd750a2048a621a8f199cb2c3d68"&gt;get_height()&lt;/a&gt; on the source Pixbuf&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;span style="font-style:italic;"&gt;rowstride&lt;/span&gt;: the value returned by &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#ef37137e7f42a5734deb0f9be25ef030"&gt;get_rowstride()&lt;/a&gt; on the source Pixbuf&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;So if we want to create a Pixbuf from a raw buffer we need also to know: &lt;span style="font-style:italic;"&gt;width&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;height&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;has_alpha&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;bits_per_sample&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;rowstride&lt;/span&gt; of the source Pixbuf.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Create a Pixbuf from raw buffer&lt;br /&gt;    Glib::RefPtr&amp;lt; Gdk::Pixbuf &amp;gt; pixbuf_ref = Gdk::Pixbuf::create_from_data( buf_ptr.get(), &lt;br /&gt;            Gdk::COLORSPACE_RGB, has_alpha, bits_per_sample, width, height, rowstride);&lt;br /&gt;    &lt;br /&gt;    // Assign the Pixbuf to the Image widget&lt;br /&gt;    source_image_.property_pixbuf() = pixbuf_ref; &lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;I use the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Image.html#103ba389637345835faedfccc9737ce6"&gt;property_pixbuf()&lt;/a&gt; property of the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Image.html"&gt;Gtk::Image&lt;/a&gt; widget for display the Pixbuf on the Image, it seems the set_pixbuf function was not implemented.&lt;br /&gt;When we create a Pixbuf from a buffer we have the ownership of the pointer. I use the &lt;a href="http://en.wikipedia.org/wiki/Auto_ptr"&gt;std::auto_ptr&lt;/a&gt; for manage this pointer. Is also possible to use a second form of the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#526129d481ff04e8953c18b0b12c4c55"&gt;create_from_data()&lt;/a&gt; and give also a signal handler for manage delete of buffer.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-7559741623391906100?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/7559741623391906100/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/05/raw-pixbuf-image-data.html#comment-form' title='4 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7559741623391906100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7559741623391906100'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/05/raw-pixbuf-image-data.html' title='Raw Pixbuf image data'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-1937591022944070480</id><published>2008-05-09T08:19:00.005+02:00</published><updated>2008-12-11T09:43:46.155+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Different CellRenderers on the same Column</title><content type='html'>&lt;h2&gt;How to breach a contract without pay&lt;/h2&gt;&lt;br /&gt;The &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1TreeView.html"&gt;TreeView&lt;/a&gt; widget allow to display data stored on a model (&lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1TreeModel.html"&gt;Gtk::TreeModel&lt;/a&gt;) and to bind each property of the model to a &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1TreeViewColumn.html"&gt;Gtk::TreeViewColumn&lt;/a&gt;,  the column use a &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRenderer.html"&gt;Gtk::CellRenderer&lt;/a&gt; for draw values and (finally) the renderer create a &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellEditable.html"&gt;Gtk::CellEditable&lt;/a&gt; for edit selected value. One constraint is that for each TreeViewColumn we can link only one CellRenderer, this is correct considering that each TreeViewColumn display always data of the same type...&lt;br /&gt;However on my ggredit I display on a TreeView (the properties browser) items of different types (colors, fonts, coordinates, ...), I rappresent all these values as string but I want to treat each type with a custom CellRenderer.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SCP2vtMBkzI/AAAAAAAAAWg/KX1c2VQEQq4/s1600-h/no-contract.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SCP2vtMBkzI/AAAAAAAAAWg/KX1c2VQEQq4/s320/no-contract.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5198269694359999282" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;I drink a &lt;a href="http://en.wikipedia.org/wiki/Mojito"&gt;Mojito&lt;/a&gt; and smoke some cigarette...mumble...mumble...&lt;br /&gt;I got it...we can create a custom CellRenderer containing Children-CellRenderers, when the Mother-CellRenderer was called it can forward the call to the correct Child-CellRenderer.&lt;br /&gt;I call the Mother-CellRenderer CellRendererRouter.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SCQVztMBk0I/AAAAAAAAAWo/mD9qs9gZJ14/s1600-h/MultipleTreeView2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SCQVztMBk0I/AAAAAAAAAWo/mD9qs9gZJ14/s320/MultipleTreeView2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5198303847939937090" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;I already told about write custom CellRenderer (&lt;a href="http://kapo-cpp.blogspot.com/2008/04/create-custom-celleditable-for.html"&gt;here&lt;/a&gt; and &lt;a href="http://kapo-cpp.blogspot.com/2008/04/custom-cellrenderer.html"&gt;here&lt;/a&gt;), we need to override &lt;span style="font-style:italic;"&gt;get_size_vfunc&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;render_vfunc&lt;/span&gt;, &lt;span style="font-style:italic;"&gt;activate_vfunc&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;start_editing_vfunc&lt;/span&gt; protected functions. We need to forward these call to the Children-CellRenderers, but since these functions are protected we have not access from the CellRendererRouter. For solve this issue I create the template class CellRendererProxy. The CellRendererProxy class accept a class T (that must inherit from Gtk::CellRenderer) as template argument, implements get_size_vfunc, render_vfunc, activate_vfunc and start_editing_vfunc as public and each public function call the same function of the base class.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/**&lt;br /&gt; * @brief Proxy class for CellRenderer stored on CellRendererRouter&lt;br /&gt; * &lt;br /&gt; * Implement the CellRendererChildInterface for expose public functions&lt;br /&gt; * and forward call to the baseT (a CellRenderer) class.&lt;br /&gt; * &lt;br /&gt; * The baseT class must implement properties:&lt;br /&gt; * - property_editable of type bool&lt;br /&gt; * - property_text of type Glib::ustring&lt;br /&gt; * &lt;br /&gt; * @param baseT a CellRenderer inherited class&lt;br /&gt; */&lt;br /&gt;template&amp;lt; class baseT &amp;gt;&lt;br /&gt;class CellRendererProxy : public virtual CellRendererChildInterface, public baseT&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    CellRendererProxy(CellRendererRouter* parent_ptr) :&lt;br /&gt;        Glib::ObjectBase( typeid(CellRendererProxy) ),&lt;br /&gt;        baseT(),&lt;br /&gt;        parent_ptr_( parent_ptr )&lt;br /&gt;    {&lt;br /&gt;        //Make the CellRenderer editable, and handle its editing signals:&lt;br /&gt;#ifdef GLIBMM_PROPERTIES_ENABLED&lt;br /&gt;        baseT::property_editable() = true;&lt;br /&gt;#else&lt;br /&gt;        baseT::set_property(&amp;quot;editable&amp;quot;, true);&lt;br /&gt;#endif&lt;br /&gt;        baseT::signal_edited().connect (sigc::mem_fun (*this, &amp;amp;CellRendererProxy::onEdited));&lt;br /&gt;        &lt;br /&gt;    }&lt;br /&gt;    virtual ~CellRendererProxy()&lt;br /&gt;    {&lt;br /&gt;        &lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /* implements */virtual void set_text(const Glib::ustring&amp;amp; value)&lt;br /&gt;    {&lt;br /&gt;#ifdef GLIBMM_PROPERTIES_ENABLED&lt;br /&gt;        baseT::property_text() = value;&lt;br /&gt;#else&lt;br /&gt;        baseT::set_property(&amp;quot;text&amp;quot;, value);&lt;br /&gt;#endif        &lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /* implements */virtual void get_size_vfunc (Gtk::Widget&amp;amp; widget, const Gdk::Rectangle* cell_area, int* x_offset, int* y_offset, int* width, int* height) const&lt;br /&gt;    {&lt;br /&gt;        baseT::get_size_vfunc (widget, cell_area, x_offset, y_offset, width, height);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /* implements */virtual void render_vfunc (const Glib::RefPtr&amp;lt;Gdk::Drawable&amp;gt;&amp;amp; window, Gtk::Widget&amp;amp; widget, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, const Gdk::Rectangle&amp;amp; expose_area, Gtk::CellRendererState flags)&lt;br /&gt;    {&lt;br /&gt;        baseT::render_vfunc (window, widget, background_area, cell_area, expose_area, flags);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /* implements */virtual bool activate_vfunc (GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags)&lt;br /&gt;    {&lt;br /&gt;        return baseT::activate_vfunc (event, widget, path, background_area, cell_area, flags);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /* implements */virtual Gtk::CellEditable* start_editing_vfunc(GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags)&lt;br /&gt;    {&lt;br /&gt;        return baseT::start_editing_vfunc(event, widget, path, background_area, cell_area, flags);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    CellRendererRouter* parent_ptr_;&lt;br /&gt;    &lt;br /&gt;    void onEdited(const Glib::ustring&amp;amp; path_string, const Glib::ustring&amp;amp; new_text);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * @brief Tell the CellRendererRouter to emit the edited signal&lt;br /&gt; */&lt;br /&gt;template&amp;lt; class baseT &amp;gt;&lt;br /&gt;void CellRendererProxy&amp;lt; baseT &amp;gt;::onEdited(const Glib::ustring&amp;amp; path_string, const Glib::ustring&amp;amp; new_text)&lt;br /&gt;{&lt;br /&gt;    parent_ptr_-&amp;gt;notifyEdited (path_string, new_text);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we can call *_vfunc functions from the CellRendererRouter. We need to store CellRendererProxy&amp;lt; class baseT &amp;gt; classes on a container, and we can not directly use CellRendererProxy (is a template class), so I create the CellRendererChildInterface abstract class. The CellRendererProxy implements this interface, the CellRendererRouter contains items of CellRendererChildInterface type.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/**&lt;br /&gt; * @brief Interface for CellRenderer stored on CellRendererRouter&lt;br /&gt; */&lt;br /&gt;class CellRendererChildInterface&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    CellRendererChildInterface()&lt;br /&gt;    {&lt;br /&gt;    }&lt;br /&gt;    virtual ~CellRendererChildInterface()&lt;br /&gt;    {    &lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    virtual void set_text(const Glib::ustring&amp;amp; value) = 0;&lt;br /&gt;    &lt;br /&gt;    virtual void get_size_vfunc (Gtk::Widget&amp;amp; widget, const Gdk::Rectangle* cell_area, int* x_offset, int* y_offset, int* width, int* height) const = 0;&lt;br /&gt;    virtual void render_vfunc (const Glib::RefPtr&amp;lt;Gdk::Drawable&amp;gt;&amp;amp; window, Gtk::Widget&amp;amp; widget, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, const Gdk::Rectangle&amp;amp; expose_area, Gtk::CellRendererState flags) = 0;&lt;br /&gt;    virtual bool activate_vfunc (GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags) = 0;&lt;br /&gt;    virtual Gtk::CellEditable* start_editing_vfunc(GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags) = 0;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we can implement the CellRendererRouter. This is the CellRenderer used by the TreeViewColumn of the TreeView widget. The CellRendererRouter class select a CellRendererProxy contained class using a type as identifier. This is the declaration:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/**&lt;br /&gt; * @brief Multiple CellRenderer for single column&lt;br /&gt; * &lt;br /&gt; * Add a CellRendererRouter to a TreeView for implement&lt;br /&gt; * multiple CellRenderer for a single colum.&lt;br /&gt; * The CellRendererRouter is called by the system for&lt;br /&gt; * render or start edit, and it simply forward the call&lt;br /&gt; * to the registered CellRenderer for the current type.&lt;br /&gt; * Use registerTypeRenderer for define all CellRenderer&lt;br /&gt; * managed by the CellRendererRouter class.&lt;br /&gt; */&lt;br /&gt;class CellRendererRouter : public Gtk::CellRenderer&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    typedef CellRendererChildInterface* cell_renderer_ptr_t;&lt;br /&gt;    typedef std::map&amp;lt; Glib::ustring, cell_renderer_ptr_t &amp;gt; cell_renderer_map_t;&lt;br /&gt;    typedef cell_renderer_map_t::iterator iterator_t;&lt;br /&gt;    &lt;br /&gt;    CellRendererRouter();&lt;br /&gt;    virtual ~CellRendererRouter();&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * @brief Register a CellRenderer for a type-id&lt;br /&gt;     * &lt;br /&gt;     * At least one CellRenderer must be registered and at least one&lt;br /&gt;     * CellRenderer must be registered as default. The default CellRenderer&lt;br /&gt;     * is used when the system ask for some operation on a row that&lt;br /&gt;     * was not defined. If more than one CellRenderer are&lt;br /&gt;     * registered as default only the last one is the default.&lt;br /&gt;     * &lt;br /&gt;     * @param type_id the type-id&lt;br /&gt;     * @param renderer_ptr the CellRenderer&lt;br /&gt;     * @param is_default use the CellRenderer for unknown path&lt;br /&gt;     */&lt;br /&gt;    void registerTypeRenderer(const Glib::ustring&amp;amp; type_id, cell_renderer_ptr_t renderer_ptr, bool is_default=false);&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * @brief Select a registered CellRenderer as default&lt;br /&gt;     * &lt;br /&gt;     * @param type_id type-id of a registered CellRenderer&lt;br /&gt;     */&lt;br /&gt;    void selectDefaultTypeRenderer(const Glib::ustring&amp;amp; type_id);&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * @brief Return the CellRenderer registered for gived type-id&lt;br /&gt;     * &lt;br /&gt;     * If no CellRenderer is registered for gived type-id the default&lt;br /&gt;     * CellRenderer is returned&lt;br /&gt;     * &lt;br /&gt;     * @param type_id the type-id to search for&lt;br /&gt;     * &lt;br /&gt;     * @return the CellRenderer registered for gived type-id or NULL if&lt;br /&gt;     * no CellRenderer is registerer and the default CellRenderer is not set&lt;br /&gt;     */&lt;br /&gt;    cell_renderer_ptr_t getTypeRenderer(const Glib::ustring&amp;amp; type_id) const; &lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * @brief Remove an already registered CellRenderer&lt;br /&gt;     * &lt;br /&gt;     * When a default CellRenderer is removed call selectDefaultTypeRenderer&lt;br /&gt;     * for select a new default CellRenderer.&lt;br /&gt;     * &lt;br /&gt;     * @param type_id the type-id of the registered CellRenderer to remove&lt;br /&gt;     */&lt;br /&gt;    void unregisterTypeRenderer(const Glib::ustring&amp;amp; type_id);&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * @brief Remove all registered CellRenderer&lt;br /&gt;     */&lt;br /&gt;    void unregisterAll();&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * @brief Emit the edited signal&lt;br /&gt;     * &lt;br /&gt;     * @param path_string path of edited item&lt;br /&gt;     * @param new_text new value of the item&lt;br /&gt;     */&lt;br /&gt;    void notifyEdited(const Glib::ustring&amp;amp; path_string, const Glib::ustring&amp;amp; new_text);&lt;br /&gt;    &lt;br /&gt;    /** @name Properties&lt;br /&gt;     */    &lt;br /&gt;    //@{&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * @brief Item text value&lt;br /&gt;     */&lt;br /&gt;    Glib::PropertyProxy&amp;lt; Glib::ustring &amp;gt; property_text();&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * @brief Item type&lt;br /&gt;     */&lt;br /&gt;    Glib::PropertyProxy&amp;lt; Glib::ustring &amp;gt; property_type();&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * @brief Item editable state&lt;br /&gt;     */&lt;br /&gt;    Glib::PropertyProxy&amp;lt; bool &amp;gt; property_editable();&lt;br /&gt;    &lt;br /&gt;    //@}&lt;br /&gt;    &lt;br /&gt;    /** @name Signals&lt;br /&gt;     */    &lt;br /&gt;    //@{&lt;br /&gt;&lt;br /&gt;    typedef sigc::signal&amp;lt; void, const Glib::ustring &amp;amp;, const Glib::ustring&amp;amp; &amp;gt; signal_edited_t;&lt;br /&gt;    signal_edited_t&amp;amp; signal_edited();&lt;br /&gt;    &lt;br /&gt;    //@}&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt;    cell_renderer_map_t type_renderer_map_;&lt;br /&gt;    Glib::ustring default_renderer_;&lt;br /&gt;    Glib::Property&amp;lt; Glib::ustring &amp;gt; property_text_;&lt;br /&gt;    Glib::Property&amp;lt; Glib::ustring &amp;gt; property_type_;&lt;br /&gt;    Glib::Property&amp;lt; bool &amp;gt; property_editable_;&lt;br /&gt;    signal_edited_t signal_edited_;&lt;br /&gt;    &lt;br /&gt;    /* override */virtual void get_size_vfunc (Gtk::Widget&amp;amp; widget, const Gdk::Rectangle* cell_area, int* x_offset, int* y_offset, int* width, int* height) const;&lt;br /&gt;    /* override */virtual void render_vfunc (const Glib::RefPtr&amp;lt;Gdk::Drawable&amp;gt;&amp;amp; window, Gtk::Widget&amp;amp; widget, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, const Gdk::Rectangle&amp;amp; expose_area, Gtk::CellRendererState flags);&lt;br /&gt;    /* override */virtual bool activate_vfunc (GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags);&lt;br /&gt;    /* override */virtual Gtk::CellEditable* start_editing_vfunc(GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags);&lt;br /&gt;    &lt;br /&gt;    // property_text events&lt;br /&gt;    virtual void onTextChanged();&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For configure the CellRendererRouter I create the methods registerTypeRenderer, selectDefaultTypeRenderer, getTypeRenderer, unregisterTypeRenderer and unregisterAll. This functions allow to register a CellRendererProxy class for a specified type identifier. The CellRendererRouter class assume at least one CellRendererProxy used for default to use in case of unrecognized types (the default probably will be the Gtk::CellRendererText class).&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void CellRendererRouter::registerTypeRenderer(const Glib::ustring&amp;amp; type_id, cell_renderer_ptr_t renderer_ptr, bool is_default/*=false*/)&lt;br /&gt;{&lt;br /&gt;    if (type_renderer_map_.find(type_id) != type_renderer_map_.end())&lt;br /&gt;        throw std::runtime_error ( &amp;quot;A CellRenderer was already registered for type: &amp;quot; + type_id );&lt;br /&gt;    &lt;br /&gt;    // TODO: who manage the pointer?&lt;br /&gt;    type_renderer_map_.insert (std::make_pair (type_id, renderer_ptr));&lt;br /&gt;    &lt;br /&gt;    if (is_default)&lt;br /&gt;        default_renderer_ = type_id;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void CellRendererRouter::selectDefaultTypeRenderer(const Glib::ustring&amp;amp; type_id)&lt;br /&gt;{&lt;br /&gt;    default_renderer_ = type_id;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;CellRendererRouter::cell_renderer_ptr_t CellRendererRouter::getTypeRenderer(const Glib::ustring&amp;amp; type_id) const&lt;br /&gt;{&lt;br /&gt;    // Search for the CellRenderer to use&lt;br /&gt;    if (type_renderer_map_.find (type_id) != type_renderer_map_.end())&lt;br /&gt;    {&lt;br /&gt;        // Use registered CellRenderer&lt;br /&gt;        return type_renderer_map_.at(property_type_);&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        // Use default CellRenderer&lt;br /&gt;        if (type_renderer_map_.find (default_renderer_) != type_renderer_map_.end())&lt;br /&gt;        {&lt;br /&gt;            return type_renderer_map_.at(default_renderer_);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // TODO: Critical, throw an exception? &lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void CellRendererRouter::unregisterTypeRenderer(const Glib::ustring&amp;amp; type_id)&lt;br /&gt;{&lt;br /&gt;    if (type_renderer_map_.find(type_id) == type_renderer_map_.end())&lt;br /&gt;        throw std::runtime_error ( &amp;quot;Non existent CellRenderer registered for type: &amp;quot; + type_id );&lt;br /&gt;    &lt;br /&gt;    type_renderer_map_.erase (type_id);&lt;br /&gt;    &lt;br /&gt;    if (default_renderer_ == type_id)&lt;br /&gt;        default_renderer_.clear();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void CellRendererRouter::unregisterAll()&lt;br /&gt;{&lt;br /&gt;    type_renderer_map_.clear();&lt;br /&gt;    default_renderer_.clear();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;When the system call a *_vfunc function we simply forward the call to the CellRendererProxy registered for the current property_type value (returned from getTypeRenderer).&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/* override */void CellRendererRouter::get_size_vfunc (Gtk::Widget&amp;amp; widget, const Gdk::Rectangle* cell_area, int* x_offset, int* y_offset, int* width, int* height) const&lt;br /&gt;{&lt;br /&gt;    getTypeRenderer(property_type_)-&amp;gt;get_size_vfunc (widget, cell_area, x_offset, y_offset, width, height);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* override */void CellRendererRouter::render_vfunc (const Glib::RefPtr&amp;lt;Gdk::Drawable&amp;gt;&amp;amp; window, Gtk::Widget&amp;amp; widget, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, const Gdk::Rectangle&amp;amp; expose_area, Gtk::CellRendererState flags)&lt;br /&gt;{&lt;br /&gt;    getTypeRenderer(property_type_)-&amp;gt;render_vfunc (window, widget, background_area, cell_area, expose_area, flags);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* override */bool CellRendererRouter::activate_vfunc (GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags)&lt;br /&gt;{&lt;br /&gt;    return getTypeRenderer(property_type_)-&amp;gt;activate_vfunc (event, widget, path, background_area, cell_area, flags);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* override */Gtk::CellEditable* CellRendererRouter::start_editing_vfunc(GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags)&lt;br /&gt;{&lt;br /&gt;    return getTypeRenderer(property_type_)-&amp;gt;start_editing_vfunc(event, widget, path, background_area, cell_area, flags);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For manage item type I add a new property to my model, who load the model know the property type.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/**&lt;br /&gt; * @brief Model used by the PropertiesBrowser TreeView&lt;br /&gt; */&lt;br /&gt;class PropertiesModelColumns : public Gtk::TreeModelColumnRecord&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;&lt;br /&gt;    PropertiesModelColumns()&lt;br /&gt;    { &lt;br /&gt;        add (col_name_); &lt;br /&gt;        add (col_value_);&lt;br /&gt;        add (col_type_);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    Gtk::TreeModelColumn&amp;lt; Glib::ustring &amp;gt; col_name_;&lt;br /&gt;    Gtk::TreeModelColumn&amp;lt; Glib::ustring &amp;gt; col_value_;&lt;br /&gt;    Gtk::TreeModelColumn&amp;lt; Glib::ustring &amp;gt; col_type_;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we can connect the model properties for value and type to the CellRendererRouter properties using &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1TreeViewColumn.html#813d0f18364cd0136b52ee105b6c6f5a"&gt;add_attribute&lt;/a&gt;.&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;I start implement this code on my ggredit, now some screenshot. Color and text items on the same column.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SCQlW9MBk1I/AAAAAAAAAWw/l_5zRcfEsUY/s1600-h/Screenshot-GraphicEditor-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SCQlW9MBk1I/AAAAAAAAAWw/l_5zRcfEsUY/s320/Screenshot-GraphicEditor-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5198320946204742482" /&gt;&lt;/a&gt;&lt;br /&gt;Editing colors.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SCQlw9MBk2I/AAAAAAAAAW4/6PoO_WzYnX8/s1600-h/Screenshot-GraphicEditor-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SCQlw9MBk2I/AAAAAAAAAW4/6PoO_WzYnX8/s320/Screenshot-GraphicEditor-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5198321392881341282" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-1937591022944070480?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/1937591022944070480/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/05/different-cellrenderers-on-same-column.html#comment-form' title='9 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/1937591022944070480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/1937591022944070480'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/05/different-cellrenderers-on-same-column.html' title='Different CellRenderers on the same Column'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/SCP2vtMBkzI/AAAAAAAAAWg/KX1c2VQEQq4/s72-c/no-contract.png' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-5154265166929110444</id><published>2008-05-06T10:13:00.002+02:00</published><updated>2008-12-11T09:43:46.175+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Custom CellRenderer links</title><content type='html'>At &lt;a href="http://referentia.blogspot.com/"&gt;Referentia ad Absurdum&lt;/a&gt; blog there is a good post on "&lt;a href="http://referentia.blogspot.com/2008/04/customising-gtkiconview.html"&gt;Customising Gtk::IconView&lt;/a&gt;". Implementation of a custom CellRenderer inherited from Gtk::CellRendererPixbuf for display Buttons when the mouse move over an item.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_VJ07oWsPKlM/R_6Di0t0kJI/AAAAAAAAAAc/rBnJ_uLELBc/s1600/docbuttons.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px;" src="http://4.bp.blogspot.com/_VJ07oWsPKlM/R_6Di0t0kJI/AAAAAAAAAAc/rBnJ_uLELBc/s1600/docbuttons.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;At &lt;a href="http://www.kulfx.com/index.php"&gt;KulFX site&lt;/a&gt; a post on "&lt;a href="http://www.kulfx.com/index.php?section=articles&amp;item=gtkmm_combobox_cellrenderer"&gt;Gtkmm ComboBox With Custom CellRenderer&lt;/a&gt;". Implementation of a custom CellRenderer for render items using Cairo.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.kulfx.com/images/vector_graphics_combo_box_2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 200px;" src="http://www.kulfx.com/images/vector_graphics_combo_box_2.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-5154265166929110444?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/5154265166929110444/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/05/custom-cellrenderer-links.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5154265166929110444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5154265166929110444'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/05/custom-cellrenderer-links.html' title='Custom CellRenderer links'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_VJ07oWsPKlM/R_6Di0t0kJI/AAAAAAAAAAc/rBnJ_uLELBc/s72-c/docbuttons.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-271035119037412089</id><published>2008-04-30T15:42:00.003+02:00</published><updated>2008-12-11T09:43:46.461+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Custom CellRenderer</title><content type='html'>On the &lt;a href="http://kapo-cpp.blogspot.com/2008/04/create-custom-celleditable-for.html"&gt;previous post&lt;/a&gt; we start to create a custom CellEditable, used from a CellRendererText inherited class. On this post we continue the experiment writing a custom CellRenderer.&lt;br /&gt;At the end we can see on the TreeView the custom column:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/SBhrHWGVTCI/AAAAAAAAAVY/baxh_Erk4B0/s1600-h/Screenshot-GtkmmDemo-CC-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/SBhrHWGVTCI/AAAAAAAAAVY/baxh_Erk4B0/s320/Screenshot-GtkmmDemo-CC-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5195019944107265058" /&gt;&lt;/a&gt;&lt;br /&gt;On the new column we can see a rectangle filled using the selected color and the color as text. When we start edit the new column we will see:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/SBhrxmGVTDI/AAAAAAAAAVg/YElIpO9PfGA/s1600-h/Screenshot-GtkmmDemo-CC-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/SBhrxmGVTDI/AAAAAAAAAVg/YElIpO9PfGA/s320/Screenshot-GtkmmDemo-CC-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5195020669956738098" /&gt;&lt;/a&gt;&lt;br /&gt;A more sofisticated CellEditable (display also selected color).&lt;br /&gt;First we can write the custom CellRenderer inheriting from &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRenderer.html"&gt;Gtk::CellRenderer&lt;/a&gt; class.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#ifndef COLORCELLRENDERER2_H_&lt;br /&gt;#define COLORCELLRENDERER2_H_&lt;br /&gt;&lt;br /&gt;#include &amp;lt;gdkmm.h&amp;gt;&lt;br /&gt;#include &amp;lt;gtkmm/cellrenderer.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;quot;ColorCellEditable2.h&amp;quot;&lt;br /&gt;&lt;br /&gt;class ColorCellRenderer2 : public Gtk::CellRenderer&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    ColorCellRenderer2();&lt;br /&gt;    virtual ~ColorCellRenderer2();&lt;br /&gt;&lt;br /&gt;    // Properties&lt;br /&gt;    Glib::PropertyProxy&amp;lt; Glib::ustring &amp;gt; property_text();&lt;br /&gt;    Glib::PropertyProxy&amp;lt; bool &amp;gt; property_editable();&lt;br /&gt;    &lt;br /&gt;    // Edited signal&lt;br /&gt;    typedef sigc::signal&amp;lt;void, const Glib::ustring&amp;amp;, const Glib::ustring&amp;amp; &amp;gt; signal_edited_t;&lt;br /&gt;    signal_edited_t&amp;amp; signal_edited() { return signal_edited_; };&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    Glib::Property&amp;lt; Glib::ustring &amp;gt; property_text_;&lt;br /&gt;    Glib::Property&amp;lt; bool &amp;gt; property_editable_;&lt;br /&gt;    signal_edited_t signal_edited_;&lt;br /&gt;    ColorCellEditable2* color_cell_edit_ptr_;&lt;br /&gt;    mutable int button_width_; //mutable because it is just a cache for get_size_vfunc&lt;br /&gt;&lt;br /&gt;    // Raise the edited event&lt;br /&gt;    void edited(const Glib::ustring&amp;amp; path, const Glib::ustring&amp;amp; new_text);&lt;br /&gt;    &lt;br /&gt;    /* override */virtual void get_size_vfunc (Gtk::Widget&amp;amp; widget, const Gdk::Rectangle* cell_area, int* x_offset, int* y_offset, int* width, int* height) const;&lt;br /&gt;    /* override */virtual void render_vfunc (const Glib::RefPtr&amp;lt;Gdk::Drawable&amp;gt;&amp;amp; window, Gtk::Widget&amp;amp; widget, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, const Gdk::Rectangle&amp;amp; expose_area, Gtk::CellRendererState flags);&lt;br /&gt;    /* override */virtual bool activate_vfunc (GdkEvent*, Gtk::Widget&amp;amp;, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags);&lt;br /&gt;    /* override */virtual Gtk::CellEditable* start_editing_vfunc(GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags);&lt;br /&gt;    &lt;br /&gt;    // Manage editing_done event for color_cell_edit_ptr_&lt;br /&gt;    void on_editing_done();&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif /*COLORCELLRENDERER2_H_*/&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;If we compare this CellRenderer with the one of the previous post we can see many differences. On the previous post all the rendering work was inherited from the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRendererText.html"&gt;Gtk::CellRendererText&lt;/a&gt; class. Now we do to perform the cell rendering from scratch. We need to implement:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li/&gt;&lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRenderer.html#cd0997118350a0874cdea7be3800c5bb"&gt;get_size_vfunc&lt;/a&gt; for compute cell size&lt;br /&gt;&lt;li/&gt;&lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRenderer.html#ce15422f9ec1e800982209691e90ad09"&gt;render_vfunc&lt;/a&gt; for cell rendering&lt;br /&gt;&lt;li/&gt;&lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRenderer.html#14dc8ee3bc58bf8a2282df1a6dc693da"&gt;activate_vfunc&lt;/a&gt; for enable editing&lt;br /&gt;&lt;li/&gt;&lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRenderer.html#e2d7434b3e136ed8cabd7e312b0f3c81"&gt;start_editing_vfunc&lt;/a&gt; (we already know) for create the CellEditable&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;h2&gt;Compute cell size&lt;/h2&gt;&lt;br /&gt;The custom CellRenderer need to override &lt;span style="font-weight:bold;"&gt;get_size_vfunc&lt;/span&gt; for compute the cell size.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;virtual void get_size_vfunc (Gtk::Widget&amp;amp; widget, const Gdk::Rectangle* cell_area, int* x_offset, int* y_offset, int* width, int* height) const;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And update &lt;span style="font-weight:bold;"&gt;width&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;height&lt;/span&gt; values. The column size is defined by adding to the text-width the button-width and the color-rectangle-width. &lt;br /&gt;We can get the size of the text using &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classPango_1_1Layout.html"&gt;Pango::Layout&lt;/a&gt; class, we will use this class also for render text. Using the method &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classPango_1_1Layout.html#1b97e487748a9221025c2d76a59d205a"&gt;get_pixel_logical_extents&lt;/a&gt; we can obtain the Rectangle bounds.&lt;br /&gt;For compute the button width and the color-area width I follow the gtkmm sample (&lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/examples/others/cellrenderercustom/"&gt;CellRendererList&lt;/a&gt;) using two static functions on the CellEditable class.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/* static */ int ColorCellEditable2::get_button_width()&lt;br /&gt;{&lt;br /&gt;    Gtk::Window window (Gtk::WINDOW_POPUP);&lt;br /&gt;&lt;br /&gt;    Gtk::Button *const button = new Gtk::Button();&lt;br /&gt;    window.add(*Gtk::manage(button));&lt;br /&gt;&lt;br /&gt;    button-&amp;gt;add(*Gtk::manage(new Gtk::Arrow(Gtk::ARROW_DOWN, Gtk::SHADOW_OUT)));&lt;br /&gt;&lt;br /&gt;    // Urgh.  Hackish :/&lt;br /&gt;    window.move(-500, -500);&lt;br /&gt;    window.show_all();&lt;br /&gt;&lt;br /&gt;    Gtk::Requisition requisition = window.size_request();&lt;br /&gt;&lt;br /&gt;    return requisition.width;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* static */ int ColorCellEditable2::get_color_area_width()&lt;br /&gt;{&lt;br /&gt;    return 16;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;span style="font-weight:bold;"&gt;get_button_width&lt;/span&gt; function create a new Popup window, add a Button, display the Window out of the screen (-500, -500) and then get the Button width. This function is very slow and we can not call evry time the &lt;span style="font-weight:bold;"&gt;get_size_vfunc&lt;/span&gt; is called.&lt;br /&gt;The &lt;span style="font-weight:bold;"&gt;get_color_area_width&lt;/span&gt; return a const value 16.&lt;br /&gt;This is the &lt;span style="font-weight:bold;"&gt;get_size_vfunc&lt;/span&gt; implementation:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/* override */void ColorCellRenderer2::get_size_vfunc (Gtk::Widget&amp;amp; widget, const Gdk::Rectangle* cell_area, int* x_offset, int* y_offset, int* width, int* height) const&lt;br /&gt;{&lt;br /&gt;    // We cache this because it takes a really long time to get the width.&lt;br /&gt;    if(button_width_ &amp;lt; 0)&lt;br /&gt;        button_width_ = ColorCellEditable2::get_button_width();&lt;br /&gt;    &lt;br /&gt;    // Compute text width&lt;br /&gt;    Glib::RefPtr&amp;lt;Pango::Layout&amp;gt; layout_ptr = widget.create_pango_layout (property_text_);&lt;br /&gt;    Pango::Rectangle rect = layout_ptr-&amp;gt;get_pixel_logical_extents();&lt;br /&gt;    &lt;br /&gt;    const int calc_width  = property_xpad() * 4 + rect.get_width();&lt;br /&gt;    const int calc_height = property_ypad() * 4 + rect.get_height();&lt;br /&gt;&lt;br /&gt;    // Add button width and color area width&lt;br /&gt;    if( width )&lt;br /&gt;        *width = calc_width + button_width_ + ColorCellEditable2::get_color_area_width();&lt;br /&gt;&lt;br /&gt;    if( height )&lt;br /&gt;        *height = calc_height;    &lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The button width is cached on the &lt;span style="font-weight:bold;"&gt;button_width_&lt;/span&gt; variable, so we can call the &lt;span style="font-weight:bold;"&gt;get_button_width&lt;/span&gt; only once. We need to declare the &lt;span style="font-weight:bold;"&gt;button_width_&lt;/span&gt; variable as &lt;a href="http://www.cppreference.com/keywords/mutable.html"&gt;mutable&lt;/a&gt; since we need to update this value on a const function.&lt;br /&gt;&lt;h2&gt;Cell rendering&lt;/h2&gt;&lt;br /&gt;The custom CellRenderer need to override &lt;span style="font-weight:bold;"&gt;render_vfunc&lt;/span&gt; for compute the cell rendering.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;virtual void render_vfunc (const Glib::RefPtr&amp;lt;Gdk::Drawable&amp;gt;&amp;amp; window, Gtk::Widget&amp;amp; widget, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, const Gdk::Rectangle&amp;amp; expose_area, Gtk::CellRendererState flags);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Here we need to perform all drawing operations. First we need a &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1GC.html"&gt;Gdk::GC&lt;/a&gt;, we can create a graphic context using the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Drawable.html"&gt;Gdk::Drawable&lt;/a&gt; passed as input argument:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Create the graphic context&lt;br /&gt;    Glib::RefPtr&amp;lt; Gdk::GC &amp;gt; gc = Gdk::GC::create (window);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So we can draw the color area rectangle using the graphic context:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Draw color area&lt;br /&gt;    gc-&amp;gt;set_rgb_fg_color( color_value );&lt;br /&gt;    window-&amp;gt;draw_rectangle(gc, &lt;br /&gt;            true, &lt;br /&gt;            cell_area.get_x(), &lt;br /&gt;            cell_area.get_y(), &lt;br /&gt;            ColorCellEditable2::get_color_area_width(), &lt;br /&gt;            cell_area.get_height());&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We need also to know the cell status and draw the item according to this status. The cell status is passed as input argument and is a &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/group__gtkmmEnums.html#g7061270b7c31ba72e053ab001ec2b877"&gt;Gtk::CellRendererState&lt;/a&gt;.&lt;br /&gt;For draw the text using Pango we need to use the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Style.html"&gt;Gtk::Style&lt;/a&gt; of the widget. The &lt;a href="http://developer.gnome.org/doc/GGAD/sec-style.html"&gt;GtkStyle&lt;/a&gt; is an abstraction layer for perform drawing operations using current theme. If we need to draw something first we have to search if exist a &lt;span style="font-style:italic;"&gt;paint_something&lt;/span&gt; in the Style class, and use this.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/* override */void ColorCellRenderer2::render_vfunc (const Glib::RefPtr&amp;lt;Gdk::Drawable&amp;gt;&amp;amp; window, Gtk::Widget&amp;amp; widget, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, const Gdk::Rectangle&amp;amp; expose_area, Gtk::CellRendererState flags)&lt;br /&gt;{&lt;br /&gt;    // Get cell size&lt;br /&gt;    int x_offset = 0, y_offset = 0, width = 0, height = 0;&lt;br /&gt;    get_size (widget, cell_area, x_offset, y_offset, width, height);&lt;br /&gt;    &lt;br /&gt;    // Create the graphic context&lt;br /&gt;    Glib::RefPtr&amp;lt; Gdk::GC &amp;gt; gc = Gdk::GC::create (window);&lt;br /&gt;    &lt;br /&gt;    // Get cell state&lt;br /&gt;    Gtk::StateType state;&lt;br /&gt;    Gtk::StateType text_state;&lt;br /&gt;    if ((flags &amp;amp; Gtk::CELL_RENDERER_SELECTED) != 0)&lt;br /&gt;    {&lt;br /&gt;        state = Gtk::STATE_SELECTED;&lt;br /&gt;        text_state = (widget.has_focus()) ? Gtk::STATE_SELECTED : Gtk::STATE_ACTIVE;&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        state = Gtk::STATE_NORMAL;&lt;br /&gt;        text_state = (widget.is_sensitive()) ? Gtk::STATE_NORMAL : Gtk::STATE_INSENSITIVE;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // Get cell color&lt;br /&gt;    int r = 0;&lt;br /&gt;    int g = 0;&lt;br /&gt;    int b = 0;&lt;br /&gt;&lt;br /&gt;    std::stringstream ss;&lt;br /&gt;    ss &amp;lt;&amp;lt; property_text_;&lt;br /&gt;    ss &amp;gt;&amp;gt; r;&lt;br /&gt;    ss &amp;gt;&amp;gt; g;&lt;br /&gt;    ss &amp;gt;&amp;gt; b;&lt;br /&gt;  &lt;br /&gt;    Gdk::Color color_value;&lt;br /&gt;    color_value.set_rgb_p (r/255.0, g/255.0, b/255.0);&lt;br /&gt;    &lt;br /&gt;    // Draw color area&lt;br /&gt;    gc-&amp;gt;set_rgb_fg_color( color_value );&lt;br /&gt;    window-&amp;gt;draw_rectangle(gc, &lt;br /&gt;            true, &lt;br /&gt;            cell_area.get_x(), &lt;br /&gt;            cell_area.get_y(), &lt;br /&gt;            ColorCellEditable2::get_color_area_width(), &lt;br /&gt;            cell_area.get_height());&lt;br /&gt;&lt;br /&gt;    // Draw color text&lt;br /&gt;    Glib::RefPtr&amp;lt; Gdk::Window &amp;gt; win = Glib::RefPtr&amp;lt;Gdk::Window&amp;gt;::cast_dynamic (window);    &lt;br /&gt;    Glib::RefPtr&amp;lt;Pango::Layout&amp;gt; layout_ptr = widget.create_pango_layout( property_text_ );&lt;br /&gt;    widget.get_style()-&amp;gt;paint_layout (win,&lt;br /&gt;          text_state,&lt;br /&gt;          true,&lt;br /&gt;          cell_area,&lt;br /&gt;          widget,&lt;br /&gt;          &amp;quot;cellrenderertext&amp;quot;,&lt;br /&gt;          cell_area.get_x() + ColorCellEditable2::get_color_area_width() + x_offset + 2 * property_xpad(),&lt;br /&gt;          cell_area.get_y() + y_offset + 2 * property_ypad(),&lt;br /&gt;          layout_ptr);    &lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Style.html#590f68be26f51b6b3238b1affc2c185b"&gt;paint_layout&lt;/a&gt; function of the Style class draw a Pango Layout, so we an draw the color text.&lt;br /&gt;&lt;h2&gt;Cell editing&lt;/h2&gt;&lt;br /&gt;For edit the cell, we know, we need to override the &lt;span style="font-weight:bold;"&gt;start_editing_vfunc&lt;/span&gt; function and return a CellEditable.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;virtual Gtk::CellEditable* start_editing_vfunc(GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;First is important to implement the constructor of the custom CellRenderer:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;ColorCellRenderer2::ColorCellRenderer2() :&lt;br /&gt;    Glib::ObjectBase( typeid(ColorCellRenderer2) ),&lt;br /&gt;    Gtk::CellRenderer(),&lt;br /&gt;    property_text_( *this, &amp;quot;text&amp;quot;, &amp;quot;&amp;quot; ),&lt;br /&gt;    property_editable_( *this, &amp;quot;editable&amp;quot;, true ),&lt;br /&gt;    color_cell_edit_ptr_( 0 ),&lt;br /&gt;    button_width_( -1 )&lt;br /&gt;{&lt;br /&gt;    property_mode() = Gtk::CELL_RENDERER_MODE_EDITABLE;&lt;br /&gt;    property_xpad() = 2;&lt;br /&gt;    property_ypad() = 2;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRenderer.html#4cdd9a7d3b773b3634f470db7ca937bd"&gt;property_mode&lt;/a&gt; of the Gtk::CellRenderer define if the cell is editable, if we does not set the correct value the &lt;span style="font-weight:bold;"&gt;start_editing_vfunc&lt;/span&gt; function was never called.&lt;br /&gt;Now we can implement the start_editing_vfunc, like the one of the previous post:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/* override */Gtk::CellEditable* ColorCellRenderer2::start_editing_vfunc(GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags)&lt;br /&gt;{&lt;br /&gt;    // If the cell isn't editable we return 0.&lt;br /&gt;#ifdef GLIBMM_PROPERTIES_ENABLED&lt;br /&gt;  if (!property_editable())&lt;br /&gt;    return 0;&lt;br /&gt;#else&lt;br /&gt;  if (!(g_object_get_data(G_OBJECT(gobj()), &amp;quot;editable&amp;quot;)))&lt;br /&gt;    return 0;&lt;br /&gt;#endif&lt;br /&gt;          &lt;br /&gt;    std::auto_ptr&amp;lt; ColorCellEditable2 &amp;gt; color_cell_edit_ptr( new ColorCellEditable2( path ) );&lt;br /&gt;    &lt;br /&gt;    Glib::ustring text;&lt;br /&gt;        &lt;br /&gt;#ifdef GLIBMM_PROPERTIES_ENABLED&lt;br /&gt;    text = property_text();&lt;br /&gt;#else&lt;br /&gt;    get_property(&amp;quot;text&amp;quot;, text);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;    color_cell_edit_ptr-&amp;gt;set_text (text);&lt;br /&gt;    color_cell_edit_ptr-&amp;gt;signal_editing_done().connect(sigc::mem_fun(*this, &amp;amp;ColorCellRenderer2::on_editing_done));&lt;br /&gt;    color_cell_edit_ptr-&amp;gt;show();&lt;br /&gt;    &lt;br /&gt;    color_cell_edit_ptr_ = Gtk::manage( color_cell_edit_ptr.release() );&lt;br /&gt;    return color_cell_edit_ptr_;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;I modify the custom CellEditable for display the color when the user editing.&lt;br /&gt;You can download the complete Eclipse project of this sample &lt;a href="http://www.box.net/shared/e3su5tts0k"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-271035119037412089?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/271035119037412089/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/04/custom-cellrenderer.html#comment-form' title='4 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/271035119037412089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/271035119037412089'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/04/custom-cellrenderer.html' title='Custom CellRenderer'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/SBhrHWGVTCI/AAAAAAAAAVY/baxh_Erk4B0/s72-c/Screenshot-GtkmmDemo-CC-1.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-4153569963568849199</id><published>2008-04-29T07:28:00.004+02:00</published><updated>2008-12-11T09:43:46.994+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Create a custom CellEditable for a CellRenderer</title><content type='html'>For my ggredit project I need to implement a properties browser using the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1TreeView.html"&gt;Gtk::TreeView&lt;/a&gt;. I want to display on the TreeView the list of properties of the selected object, two columns: the first show the property name, the second show the property value and allow the user to enter a new value.&lt;br /&gt;The Gtkmm documentation explain how to use TreeView (&lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/ch08.html"&gt;Chapter 8&lt;/a&gt;), here we can learn how to start with TreeView widget.&lt;br /&gt;The TreeView widget use the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRenderer.html"&gt;CellRenderer&lt;/a&gt; class for draw cells, for each column of the model we can have only one CellRenderer, defined when we add the new column using the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1TreeView.html#0253a5477ce006bf84fae8eb205efc73"&gt;append_column&lt;/a&gt; method.&lt;br /&gt;For the properties browser I need to display different value type on the same column, so I need more CellRenderer for the same column, one for each property type.&lt;br /&gt;I don't know why but on Gnome this approach (the properties browser) is used rarely. I found only Gideon-Designer (aka &lt;a href="http://crow-designer.sourceforge.net/"&gt;Crow-designer&lt;/a&gt;). I like this way to work so I want to implement this on my ggredit.&lt;br /&gt;Before work on this issue we need to understand how to implement custom CellRenderer. A good example is provided by gtkmm, the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/examples/others/cellrenderercustom/"&gt;CellRendererList&lt;/a&gt;. Also on the gtkmm mailing list you can find some tips about &lt;a href="http://www.nabble.com/inserting-ColorButton-in-CellRenderer-....-td16018527.html"&gt;ColorButton in CellRenderer&lt;/a&gt;.&lt;br /&gt;On this first tutorial we create a custom CellRenderer inheriting from the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRendererText.html"&gt;Gtk::CellRendererText&lt;/a&gt;,  on this way we can let the base class draw the cell value and implement only the edit functionality (for now).&lt;br /&gt;A custom CellRenderer have to override the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRenderer.html#e2d7434b3e136ed8cabd7e312b0f3c81"&gt;start_editing_vfunc&lt;/a&gt; and return a new instance of a &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellEditable.html"&gt;Gtk::CellEditable&lt;/a&gt;, this object can contains the widget for edit the cell value.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SBbFsWGVTAI/AAAAAAAAAVI/S354YwGN8Tg/s1600-h/edit.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SBbFsWGVTAI/AAAAAAAAAVI/S354YwGN8Tg/s320/edit.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5194556585855503362" /&gt;&lt;/a&gt;&lt;br /&gt;We can start to implement a custom CellRenderer for edit colors.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#ifndef COLORCELLRENDERER_H_&lt;br /&gt;#define COLORCELLRENDERER_H_&lt;br /&gt;&lt;br /&gt;#include &amp;lt;gdkmm.h&amp;gt;&lt;br /&gt;#include &amp;lt;gtkmm/cellrenderertext.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;quot;ColorCellEditable2.h&amp;quot;&lt;br /&gt;&lt;br /&gt;class ColorCellRenderer : public Gtk::CellRendererText&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    ColorCellRenderer();&lt;br /&gt;    virtual ~ColorCellRenderer();&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    // The custom CellEditable&lt;br /&gt;    ColorCellEditable2* color_cell_edit_ptr_;&lt;br /&gt;    &lt;br /&gt;    // Override CellRendererText&lt;br /&gt;    virtual Gtk::CellEditable* start_editing_vfunc(GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags);&lt;br /&gt;    &lt;br /&gt;    // Override CellRendererText&lt;br /&gt;    void on_editing_done();&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif /*COLORCELLRENDERER_H_*/&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;When we implement a Gtkmm object we have to call the constructor of the base class &lt;a href="http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/classGlib_1_1ObjectBase.html"&gt;Glib::ObjectBase&lt;/a&gt; passing the &lt;span style="font-weight:bold;"&gt;typeid&lt;/span&gt; of the new class.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;ColorCellRenderer::ColorCellRenderer() :&lt;br /&gt;    Glib::ObjectBase( typeid(ColorCellRenderer) ),&lt;br /&gt;    Gtk::CellRendererText(),&lt;br /&gt;    color_cell_edit_ptr_( 0 ) &lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ColorCellRenderer::~ColorCellRenderer()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we can implement the &lt;span style="font-weight:bold;"&gt;start_editing_vfunc&lt;/span&gt; function. Here we need to create a new CellEditable object, so before write the &lt;span style="font-weight:bold;"&gt;start_editing_vfunc&lt;/span&gt; we can implement the custom CellEditable.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#ifndef COLORCELLEDITABLE2_H_&lt;br /&gt;#define COLORCELLEDITABLE2_H_&lt;br /&gt;&lt;br /&gt;#include &amp;lt;gtkmm/celleditable.h&amp;gt;&lt;br /&gt;#include &amp;lt;gtkmm/eventbox.h&amp;gt;&lt;br /&gt;#include &amp;lt;gtkmm/box.h&amp;gt;&lt;br /&gt;#include &amp;lt;gdkmm/color.h&amp;gt;&lt;br /&gt;#include &amp;lt;gtkmm/entry.h&amp;gt;&lt;br /&gt;#include &amp;lt;gtkmm/button.h&amp;gt;&lt;br /&gt;&lt;br /&gt;class ColorCellEditable2 : public Gtk::EventBox, public Gtk::CellEditable&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    // Ctor/Dtor&lt;br /&gt;    ColorCellEditable2(const Glib::ustring&amp;amp; path);&lt;br /&gt;    virtual ~ColorCellEditable2();&lt;br /&gt;    &lt;br /&gt;    // Return creation path&lt;br /&gt;    Glib::ustring get_path() const;&lt;br /&gt;&lt;br /&gt;    // Get and set text&lt;br /&gt;    void set_text(const Glib::ustring&amp;amp; text);&lt;br /&gt;    Glib::ustring get_text() const;&lt;br /&gt;    &lt;br /&gt;    // Signal for editing done&lt;br /&gt;    typedef sigc::signal&amp;lt;void&amp;gt; signal_editing_done_t;&lt;br /&gt;    signal_editing_done_t&amp;amp; signal_editing_done() { return signal_editing_done_; };&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    Glib::ustring path_;&lt;br /&gt;    Gtk::Entry* entry_ptr_;&lt;br /&gt;    Gtk::Button* button_ptr_;&lt;br /&gt;    Gdk::Color color_;&lt;br /&gt;    signal_editing_done_t signal_editing_done_;&lt;br /&gt;    &lt;br /&gt;    // Override CellEditable&lt;br /&gt;    virtual void start_editing_vfunc(GdkEvent* event);&lt;br /&gt;&lt;br /&gt;    // Manage button_clicked signal&lt;br /&gt;    virtual void on_button_clicked();&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif /*COLORCELLEDITABLE2_H_*/&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The custom CellEditable inherit from CellEditable and from &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1EventBox.html"&gt;Gtk::EventBox&lt;/a&gt; because we need also to receive events from children widgets (the button_ptr_ Button).&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#include &amp;quot;ColorCellEditable2.h&amp;quot;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;gtkmm.h&amp;gt;&lt;br /&gt;#include &amp;lt;gtk/gtkentry.h&amp;gt; /* see XXX below */&lt;br /&gt;&lt;br /&gt;#include &amp;lt;sstream&amp;gt;&lt;br /&gt;&lt;br /&gt;ColorCellEditable2::ColorCellEditable2(const Glib::ustring&amp;amp; path) :&lt;br /&gt;    Glib::ObjectBase( typeid(ColorCellEditable2) ),&lt;br /&gt;    Gtk::EventBox(),&lt;br /&gt;    Gtk::CellEditable(),&lt;br /&gt;    path_( path ),&lt;br /&gt;    entry_ptr_( 0 ),&lt;br /&gt;    button_ptr_( 0 )&lt;br /&gt;{&lt;br /&gt;  Gtk::HBox *const hbox = new Gtk::HBox(false, 0);&lt;br /&gt;  add (*Gtk::manage( hbox ));&lt;br /&gt;&lt;br /&gt;  entry_ptr_ = new Gtk::Entry();&lt;br /&gt;  hbox-&amp;gt;pack_start (*Gtk::manage(entry_ptr_), Gtk::PACK_EXPAND_WIDGET);&lt;br /&gt;  entry_ptr_-&amp;gt;set_has_frame(false);&lt;br /&gt;  entry_ptr_-&amp;gt;gobj()-&amp;gt;is_cell_renderer = true; // XXX&lt;br /&gt;  &lt;br /&gt;  button_ptr_ = new Gtk::Button();&lt;br /&gt;  hbox-&amp;gt;pack_start (*Gtk::manage( button_ptr_ ), Gtk::PACK_SHRINK);&lt;br /&gt;  button_ptr_-&amp;gt;add (*Gtk::manage(new Gtk::Arrow(Gtk::ARROW_DOWN, Gtk::SHADOW_OUT)));&lt;br /&gt;  &lt;br /&gt;  set_flags(Gtk::CAN_FOCUS);&lt;br /&gt;&lt;br /&gt;  show_all_children();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ColorCellEditable2::~ColorCellEditable2()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The constructor need the path of the current cell, we have to use this value next. We need to call the Glib::ObjectBase constructor. Finally we can add all widgets: one &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Entry.html"&gt;Gtk::Entry&lt;/a&gt; and one &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Button.html"&gt;Gtk::Button&lt;/a&gt; contained on a &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1HBox.html"&gt;Gtk::HBox&lt;/a&gt;.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/SBc1iGGVTBI/AAAAAAAAAVQ/6KfllAzabfQ/s1600-h/cell_edit.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/SBc1iGGVTBI/AAAAAAAAAVQ/6KfllAzabfQ/s320/cell_edit.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5194679555064155154" /&gt;&lt;/a&gt;&lt;br /&gt;The line marked with &lt;span style="font-weight:bold;"&gt;XXX&lt;/span&gt; use the GtkEntry C object (returned by &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Entry.html#7326d9d26b0ab988731fbad3fc79997c"&gt;gobj&lt;/a&gt;) for set a property not wrapped by the Gtk::Entry class.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;entry_ptr_-&amp;gt;gobj()-&amp;gt;is_cell_renderer = true; // XXX&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We can implement properties:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Glib::ustring ColorCellEditable2::get_path() const&lt;br /&gt;{&lt;br /&gt;  return path_;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void ColorCellEditable2::set_text(const Glib::ustring&amp;amp; text)&lt;br /&gt;{&lt;br /&gt;    entry_ptr_-&amp;gt;set_text (text);&lt;br /&gt;  &lt;br /&gt;    int r = 0;&lt;br /&gt;    int g = 0;&lt;br /&gt;    int b = 0;&lt;br /&gt;&lt;br /&gt;    std::stringstream ss;&lt;br /&gt;    ss &amp;lt;&amp;lt; text;&lt;br /&gt;    ss &amp;gt;&amp;gt; r;&lt;br /&gt;    ss &amp;gt;&amp;gt; g;&lt;br /&gt;    ss &amp;gt;&amp;gt; b;&lt;br /&gt;  &lt;br /&gt;    color_.set_rgb_p (r/255.0, g/255.0, b/255.0);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Glib::ustring ColorCellEditable2::get_text() const&lt;br /&gt;{&lt;br /&gt;    std::stringstream ss;&lt;br /&gt;    ss &amp;lt;&amp;lt; int(color_.get_red_p() * 255) &amp;lt;&amp;lt; &amp;quot; &amp;quot;;&lt;br /&gt;    ss &amp;lt;&amp;lt; int(color_.get_green_p() * 255) &amp;lt;&amp;lt; &amp;quot; &amp;quot;; &lt;br /&gt;    ss &amp;lt;&amp;lt; int(color_.get_blue_p() * 255);&lt;br /&gt;    &lt;br /&gt;    return ss.str();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And then override CellEditable functions:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void ColorCellEditable2::start_editing_vfunc(GdkEvent*)&lt;br /&gt;{&lt;br /&gt;    entry_ptr_-&amp;gt;select_region(0, -1);&lt;br /&gt;&lt;br /&gt;    button_ptr_-&amp;gt;signal_clicked().connect (sigc::mem_fun( *this, &amp;amp;ColorCellEditable2::on_button_clicked ));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void ColorCellEditable2::on_button_clicked()&lt;br /&gt;{&lt;br /&gt;    Gtk::ColorSelectionDialog dialog( &amp;quot;Changing color&amp;quot; );&lt;br /&gt;&lt;br /&gt;    dialog.set_transient_for ((Gtk::Window&amp;amp;)(*this-&amp;gt;get_toplevel()));&lt;br /&gt;&lt;br /&gt;    Gtk::ColorSelection* colorsel = dialog.get_colorsel();&lt;br /&gt;    colorsel-&amp;gt;set_previous_color (color_);&lt;br /&gt;    colorsel-&amp;gt;set_current_color (color_);&lt;br /&gt;    colorsel-&amp;gt;set_has_palette (true);&lt;br /&gt;&lt;br /&gt;    if (dialog.run() == Gtk::RESPONSE_OK)&lt;br /&gt;    {&lt;br /&gt;        color_ = colorsel-&amp;gt;get_current_color();&lt;br /&gt;        &lt;br /&gt;        signal_editing_done_.emit();&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;On the &lt;span style="font-weight:bold;"&gt;start_editing_vfunc&lt;/span&gt; we simply select all text on the Gtk::Entry and connect the &lt;span style="font-weight:bold;"&gt;button_clicked&lt;/span&gt; signal to the event handler.&lt;br /&gt;When the user press the button we catch the &lt;span style="font-weight:bold;"&gt;button_clicked&lt;/span&gt; and display the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1ColorSelectionDialog.html"&gt;Gtk::ColorSelectionDialog&lt;/a&gt;. For call the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Window.html#4dc2db7c44546300a7843314cfa21bc8"&gt;set_transient_for&lt;/a&gt; function from the button we can not give &lt;span style="font-weight:bold;"&gt;*this&lt;/span&gt; (like when we open Dialog from a Window), we can use the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1Widget.html#c92a0dc8751c828406ca8755f013b75c"&gt;get_top_level&lt;/a&gt; function.&lt;br /&gt;If the user press the Ok button from the Dialog we can update the selected color and emit the signal &lt;span style="font-weight:bold;"&gt;editing_done&lt;/span&gt; to the CellRenderer.&lt;br /&gt;Now we can return to the CellRenderer implementation, we break on the &lt;span style="font-weight:bold;"&gt;start_editing_vfunc&lt;/span&gt;:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Gtk::CellEditable* ColorCellRenderer::start_editing_vfunc(GdkEvent* event, Gtk::Widget&amp;amp; widget, const Glib::ustring&amp;amp; path, const Gdk::Rectangle&amp;amp; background_area, const Gdk::Rectangle&amp;amp; cell_area, Gtk::CellRendererState flags)&lt;br /&gt;{&lt;br /&gt;// If the cell isn't editable we return 0.&lt;br /&gt;#ifdef GLIBMM_PROPERTIES_ENABLED&lt;br /&gt;  if (!property_editable())&lt;br /&gt;    return 0;&lt;br /&gt;#else&lt;br /&gt;  if (!(g_object_get_data(G_OBJECT(gobj()), &amp;quot;editable&amp;quot;)))&lt;br /&gt;    return 0;&lt;br /&gt;#endif&lt;br /&gt;      &lt;br /&gt;    std::auto_ptr&amp;lt; ColorCellEditable2 &amp;gt; color_cell_edit_ptr( new ColorCellEditable2( path ) );&lt;br /&gt;    &lt;br /&gt;    Glib::ustring text;&lt;br /&gt;    &lt;br /&gt;#ifdef GLIBMM_PROPERTIES_ENABLED&lt;br /&gt;    text = property_text();&lt;br /&gt;#else&lt;br /&gt;    get_property(&amp;quot;text&amp;quot;, text);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;    color_cell_edit_ptr-&amp;gt;set_text (text);&lt;br /&gt;    color_cell_edit_ptr-&amp;gt;signal_editing_done().connect(sigc::mem_fun(*this, &amp;amp;ColorCellRenderer::on_editing_done));&lt;br /&gt;    color_cell_edit_ptr-&amp;gt;show();&lt;br /&gt;    &lt;br /&gt;    color_cell_edit_ptr_ = Gtk::manage( color_cell_edit_ptr.release() );&lt;br /&gt;    return color_cell_edit_ptr_;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We need to use the &lt;span style="font-weight:bold;"&gt;GLIBMM_PROPERTIES_ENABLED&lt;/span&gt; macro for test if we can use properties or we need to use functions. For some platform  is not possible to use properties (depends on how gtkmm was built). First we test &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRendererText.html#216b5af0c1f22b8e71c3338335d00a73"&gt;property_editable&lt;/a&gt; and ensure is &lt;span style="font-weight:bold;"&gt;true&lt;/span&gt;. Then we can create the CellEditable object, and give the value of the selected cell using the property &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRendererText.html#7ea19b142e7096509828f78f2133e302"&gt;property_text&lt;/a&gt;.&lt;br /&gt;Using the show method we can display the CellEditable.&lt;br /&gt;When the user finish to edit the signal &lt;span style="font-weight:bold;"&gt;editing_done&lt;/span&gt; was fired, we catch this event on the &lt;span style="font-weight:bold;"&gt;on_editing_done&lt;/span&gt; event handler:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void ColorCellRenderer::on_editing_done()&lt;br /&gt;{&lt;br /&gt;    edited (color_cell_edit_ptr_-&amp;gt;get_path(), color_cell_edit_ptr_-&amp;gt;get_text());&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We simply call the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRendererText.html#ee211c5f2679e36518ebccc6c4c7d161"&gt;edited&lt;/a&gt; function for emit the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1CellRendererText.html#c395ed00506c75486ed11bec041ff6a7"&gt;edited&lt;/a&gt; signal. The client need to catch this signal for update the model.&lt;br /&gt;The custom CellEditable is now complete. We need to implement a custom CellRenderer, not inheriting from the CellRendererText, on next post...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-4153569963568849199?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/4153569963568849199/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/04/create-custom-celleditable-for.html#comment-form' title='3 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/4153569963568849199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/4153569963568849199'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/04/create-custom-celleditable-for.html' title='Create a custom CellEditable for a CellRenderer'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_sQJ1m4QDkME/SBbFsWGVTAI/AAAAAAAAAVI/S354YwGN8Tg/s72-c/edit.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-7038547997467058332</id><published>2008-03-18T08:20:00.010+01:00</published><updated>2008-12-11T09:43:53.370+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='uml'/><category scheme='http://www.blogger.com/atom/ns#' term='pattern'/><title type='text'>Iterate over a Composite</title><content type='html'>I think the &lt;a href="http://en.wikipedia.org/wiki/Composite_pattern"&gt;composite pattern&lt;/a&gt; is the most used, I use it on ggredit for rappresent the shape model. I use this implementation:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R-DIlbjdBXI/AAAAAAAAAUQ/bvP1LQjA_0U/s1600-h/Composite.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R-DIlbjdBXI/AAAAAAAAAUQ/bvP1LQjA_0U/s320/Composite.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5179360116853245298" /&gt;&lt;/a&gt;&lt;br /&gt;So we can call &lt;span style="font-style:italic;"&gt;draw&lt;/span&gt; for the &lt;span style="font-style:italic;"&gt;Page&lt;/span&gt; class and draw all children objects...no news...the composite can iterate itself.&lt;br /&gt;On next section I will use a more simple implementation, just for simplify. So we can talk about this composite structure:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R-Nalbke2oI/AAAAAAAAAUg/DwEmpnVvbSU/s1600-h/2Composite.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R-Nalbke2oI/AAAAAAAAAUg/DwEmpnVvbSU/s320/2Composite.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5180083595508636290" /&gt;&lt;/a&gt;&lt;br /&gt;This is the implementation:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Primitive&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class Primitive&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    // Ctor/Dtor&lt;br /&gt;    Primitive() {};&lt;br /&gt;    Primitive(const std::string&amp;amp; value) { text_ = value; };&lt;br /&gt;    virtual ~Primitive() {};&lt;br /&gt;&lt;br /&gt;    // Text property&lt;br /&gt;    std::string get_text() const { return text_; };&lt;br /&gt;    void set_text(const std::string&amp;amp; value) { text_ = value; };&lt;br /&gt;    &lt;br /&gt;    // An operation&lt;br /&gt;    virtual void write() { std::cout &amp;lt;&amp;lt; text_ &amp;lt;&amp;lt; std::endl; };&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt;    std::string text_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Composite&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class Composite : public Primitive&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    typedef std::list&amp;lt; Primitive* &amp;gt; list_t;&lt;br /&gt;    typedef list_t::iterator iterator_t;&lt;br /&gt;    &lt;br /&gt;    // Ctor/Dtor&lt;br /&gt;    Composite() {};&lt;br /&gt;    Composite(const std::string&amp;amp; value) { text_ = value; };&lt;br /&gt;    virtual ~Composite() {};&lt;br /&gt;&lt;br /&gt;    // Add child to the composite&lt;br /&gt;    void addChild(Primitive* ptr) { children_.push_back(ptr); };&lt;br /&gt;    &lt;br /&gt;    // An operation&lt;br /&gt;    virtual void write() &lt;br /&gt;    { &lt;br /&gt;        std::cout &amp;lt;&amp;lt; &amp;quot;Composite &amp;quot; &amp;lt;&amp;lt; text_ &amp;lt;&amp;lt; &amp;quot; {&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;        &lt;br /&gt;        for (iterator_t i = children_.begin(); i != children_.end(); i++)&lt;br /&gt;        {&lt;br /&gt;            (*i)-&amp;gt;write();&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        std::cout &amp;lt;&amp;lt; &amp;quot;}&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;    };&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    list_t children_;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;But how to iterate the hierarchical structures from a client class? I found two ways.&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;The Visitor pattern&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;We can make use of the particularity of the Composite to iterate itself and use a light &lt;a href="http://en.wikipedia.org/wiki/Visitor_pattern"&gt;Visitor pattern&lt;/a&gt;.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R-icyrke2pI/AAAAAAAAAUo/_t3EQoNNVmY/s1600-h/welcome.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R-icyrke2pI/AAAAAAAAAUo/_t3EQoNNVmY/s320/welcome.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5181563765792889490" /&gt;&lt;/a&gt;&lt;br /&gt;The &lt;span style="font-style:italic;"&gt;Visitor&lt;/span&gt; class is only an interface, the base class for all concrete visitors. The method &lt;span style="font-style:italic;"&gt;visit&lt;/span&gt; of the Visitor accept a &lt;span style="font-style:italic;"&gt;Primitive&lt;/span&gt; object. On the composite we have to add an &lt;span style="font-style:italic;"&gt;accept&lt;/span&gt; method, this method take a &lt;span style="font-style:italic;"&gt;Visitor&lt;/span&gt; object as parameter and call the &lt;span style="font-style:italic;"&gt;visit&lt;/span&gt; method ginving &lt;span style="font-weight:bold;"&gt;this&lt;/span&gt; as argument. The &lt;span style="font-style:italic;"&gt;Composite&lt;/span&gt; class need to forward the accept method to all childrens.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R-inI7ke2qI/AAAAAAAAAUw/v5AVsgsvlY0/s1600-h/2Composite-Visitor.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R-inI7ke2qI/AAAAAAAAAUw/v5AVsgsvlY0/s320/2Composite-Visitor.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5181575143161256610" /&gt;&lt;/a&gt;&lt;br /&gt;This is not the classic &lt;span style="font-weight:bold;"&gt;for loop&lt;/span&gt;, the loop is implemented on the concrete Visitor, and this is the disadvantage we have to implement a Visitor class for each task.&lt;br /&gt;The example code implements two Visitor classes, the first one for write all children and onethe second one for search text.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Visitor interface&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class Primitive; // Forward declaration&lt;br /&gt;class Composite; // Forward declaration&lt;br /&gt;&lt;br /&gt;class Visitor&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    Visitor() {};&lt;br /&gt;    virtual ~Visitor() {};&lt;br /&gt;    &lt;br /&gt;    virtual bool visit(Primitive* ptr) = 0;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Visitor implementation WriteTextVisitor&lt;br /&gt;//&lt;br /&gt;// Simply write text&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class WriteTextVisitor : public Visitor&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    WriteTextVisitor() {};&lt;br /&gt;    virtual ~WriteTextVisitor() {};&lt;br /&gt;    &lt;br /&gt;    bool visit(Primitive* ptr);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Visitor implementation FindTextVisitor&lt;br /&gt;//&lt;br /&gt;// Search for text&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class FindTextVisitor : public Visitor&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    FindTextVisitor(const std::string&amp;amp; match) :&lt;br /&gt;        match_( match ) {};&lt;br /&gt;    virtual ~FindTextVisitor() {};&lt;br /&gt;    &lt;br /&gt;    bool visit(Primitive* ptr);&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    std::string match_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Primitive&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class Primitive&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    Primitive() {};&lt;br /&gt;    Primitive(const std::string&amp;amp; value) { text_ = value; };&lt;br /&gt;    virtual ~Primitive() {};&lt;br /&gt;    &lt;br /&gt;    std::string get_text() const { return text_; };&lt;br /&gt;    void set_text(const std::string&amp;amp; value) { text_ = value; };&lt;br /&gt;    &lt;br /&gt;    virtual void write() { std::cout &amp;lt;&amp;lt; text_ &amp;lt;&amp;lt; std::endl; };&lt;br /&gt;&lt;br /&gt;    virtual bool accept(Visitor* visitor)&lt;br /&gt;    {&lt;br /&gt;        return visitor-&amp;gt;visit (this);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    std::string text_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Composite&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class Composite : public Primitive&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    typedef std::list&amp;lt; Primitive* &amp;gt; list_t;&lt;br /&gt;    typedef list_t::iterator iterator_t;&lt;br /&gt;    &lt;br /&gt;    Composite() {};&lt;br /&gt;    Composite(const std::string&amp;amp; value) { text_ = value; };&lt;br /&gt;    virtual ~Composite() {};&lt;br /&gt;&lt;br /&gt;    void addChild(Primitive* ptr) { children_.push_back(ptr); };&lt;br /&gt;    &lt;br /&gt;    virtual void write() &lt;br /&gt;    { &lt;br /&gt;        std::cout &amp;lt;&amp;lt; &amp;quot;Composite &amp;quot; &amp;lt;&amp;lt; text_ &amp;lt;&amp;lt; &amp;quot; {&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;        &lt;br /&gt;        for (iterator_t i = children_.begin(); i != children_.end(); i++)&lt;br /&gt;        {&lt;br /&gt;            (*i)-&amp;gt;write();&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        std::cout &amp;lt;&amp;lt; &amp;quot;}&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;    };&lt;br /&gt;    &lt;br /&gt;    virtual bool accept(Visitor* visitor)&lt;br /&gt;    {&lt;br /&gt;        if (!visitor-&amp;gt;visit (this))&lt;br /&gt;            return false;&lt;br /&gt;        &lt;br /&gt;        for (iterator_t i = children_.begin(); i != children_.end(); i++)&lt;br /&gt;        {&lt;br /&gt;            if (!((*i)-&amp;gt;accept (visitor)))&lt;br /&gt;                return false;&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    list_t children_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// WriteTextVisitor implementation&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;bool WriteTextVisitor::visit(Primitive* ptr)&lt;br /&gt;{&lt;br /&gt;    std::cout &amp;lt;&amp;lt; &amp;quot;visit primitive &amp;quot; &amp;lt;&amp;lt; ptr-&amp;gt;get_text() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;    return true; // Continue walk&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// FindTextVisitor implementation&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;bool FindTextVisitor::visit(Primitive* ptr)&lt;br /&gt;{&lt;br /&gt;    if (ptr-&amp;gt;get_text() == match_)&lt;br /&gt;    {&lt;br /&gt;        std::cout &amp;lt;&amp;lt; &amp;quot;Found primitive text '&amp;quot; &amp;lt;&amp;lt; match_ &amp;lt;&amp;lt; &amp;quot;'&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;        return false; // Break walk&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return true; // Continue walk&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This implementation of the visitor is desgined for loop over a composite. For break the loop we can return a boolean value from the Visitor class, testing this value on the Composite class we can exit from the current loop, also the accept value must return this value since we do not know the hierarchy.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;The Iterator pattern [GOF, p173]&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;The &lt;a href="http://en.wikipedia.org/wiki/Iterator_pattern"&gt;iterator pattern&lt;/a&gt; allow to iterate over a Composite on the same way we can iterate evry container.&lt;br /&gt;The implementation of the iterator for the tree hierarchy of a Composite is not so simple. &lt;a href="http://www.vincehuston.org/dp/"&gt;On Vince Huston Design Patterns&lt;/a&gt; site, you can find a &lt;a href="http://www.vincehuston.org/dp/cbimvCpp"&gt;c++ implementation&lt;/a&gt; using Composite, Builder, Iterator, Memento and Visitor pattern.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R_MpKrke2rI/AAAAAAAAAU4/QdZOs8WlAtE/s1600-h/2Composite-Itor.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R_MpKrke2rI/AAAAAAAAAU4/QdZOs8WlAtE/s320/2Composite-Itor.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5184532859504745138" /&gt;&lt;/a&gt;&lt;br /&gt;The Iterator class, like the &lt;a href="http://www.cppreference.com/iterators.html"&gt;iterator of standard library&lt;/a&gt;, allow to read all values of the Composite with forward movement the use is:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;        Iterator i = root.create_iterator();&lt;br /&gt;        i.first();&lt;br /&gt;        while (!i.is_done())&lt;br /&gt;        {&lt;br /&gt;            std::cout &amp;lt;&amp;lt; &amp;quot;Main loop: &amp;quot; &amp;lt;&amp;lt; i.get_current()-&amp;gt;get_text() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;            i.next();&lt;br /&gt;        }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For create an &lt;span style="font-style:italic;"&gt;Iterator &lt;/span&gt;object we can define a &lt;span style="font-style:italic;"&gt;create_iterator&lt;/span&gt; function on the &lt;span style="font-style:italic;"&gt;Composite &lt;/span&gt;class (this is the Builder pattern). We have to implement a next function for move over the hierarchy.&lt;br /&gt;There are many way for iterate over a &lt;a href="http://en.wikipedia.org/wiki/Tree_%28data_structure%29"&gt;tree structure&lt;/a&gt;,&lt;br /&gt;pre-order or post-order, we will implement the pre-order.&lt;br /&gt;So if we have this data:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R_NT3bke2sI/AAAAAAAAAVA/yze2i7ck3MY/s1600-h/tree.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R_NT3bke2sI/AAAAAAAAAVA/yze2i7ck3MY/s320/tree.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5184579807792257730" /&gt;&lt;/a&gt;&lt;br /&gt;the iterator walk on this order: "/", "vmlinuz", "bin", "ls", "home", "vincenzo", "ggredit", "anna", "ligabue".&lt;br /&gt;When the iterator move to next item need to know if this is a &lt;span style="font-style:italic;"&gt;Primitive &lt;/span&gt;or a Composite, if the item is a &lt;span style="font-style:italic;"&gt;Composite &lt;/span&gt;we need to store current position and move to the child, and after walk over all children we need to return to previous position, for this we need to use the Memento pattern.&lt;br /&gt;So we need to modify composite model:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Primitive&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class Primitive&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    enum component_type&lt;br /&gt;    {&lt;br /&gt;        primitive_e,&lt;br /&gt;        composite_e&lt;br /&gt;    };&lt;br /&gt;    &lt;br /&gt;    Primitive()&lt;br /&gt;    {};&lt;br /&gt;    Primitive(const std::string&amp;amp; value) &lt;br /&gt;    { &lt;br /&gt;        text_ = value; &lt;br /&gt;    };&lt;br /&gt;    virtual ~Primitive() {};&lt;br /&gt;    &lt;br /&gt;    virtual component_type get_component_type() const { return primitive_e; };&lt;br /&gt;    &lt;br /&gt;    std::string get_text() const { return text_; };&lt;br /&gt;    void set_text(const std::string&amp;amp; value) { text_ = value; };&lt;br /&gt;    &lt;br /&gt;    virtual void write() { std::cout &amp;lt;&amp;lt; text_ &amp;lt;&amp;lt; std::endl; };&lt;br /&gt;&lt;br /&gt;protected:&lt;br /&gt;    std::string text_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Composite&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class Iterator; // Forward declaration&lt;br /&gt;&lt;br /&gt;class Composite : public Primitive&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    typedef std::list&amp;lt; Primitive* &amp;gt; list_t;&lt;br /&gt;    typedef list_t::iterator iterator_t;&lt;br /&gt;    &lt;br /&gt;    Composite()&lt;br /&gt;    {};&lt;br /&gt;    Composite(const std::string&amp;amp; value) &lt;br /&gt;    { &lt;br /&gt;        text_ = value; &lt;br /&gt;    };&lt;br /&gt;    virtual ~Composite() {};&lt;br /&gt;&lt;br /&gt;    virtual component_type get_component_type() const { return composite_e; };&lt;br /&gt;    &lt;br /&gt;    void add_child(Primitive* ptr) { children_.push_back(ptr); };&lt;br /&gt;    &lt;br /&gt;    iterator_t get_begin() { return children_.begin(); };&lt;br /&gt;    iterator_t get_end() { return children_.end(); };&lt;br /&gt;    &lt;br /&gt;    virtual void write() &lt;br /&gt;    { &lt;br /&gt;        std::cout &amp;lt;&amp;lt; &amp;quot;Composite &amp;quot; &amp;lt;&amp;lt; text_ &amp;lt;&amp;lt; &amp;quot; {&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;        &lt;br /&gt;        for (iterator_t i = children_.begin(); i != children_.end(); i++)&lt;br /&gt;        {&lt;br /&gt;            (*i)-&amp;gt;write();&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        std::cout &amp;lt;&amp;lt; &amp;quot;}&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    Iterator create_iterator();&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    list_t children_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Composite implementation&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;Iterator Composite::create_iterator()&lt;br /&gt;{&lt;br /&gt;    return Iterator(this);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;span style="font-style:italic;"&gt;get_component_type&lt;/span&gt; function return the object type, the &lt;span style="font-style:italic;"&gt;Iterator&lt;/span&gt; class need to test this value for loop over children.&lt;br /&gt;The &lt;span style="font-style:italic;"&gt;create_iterator&lt;/span&gt; function create an &lt;span style="font-style:italic;"&gt;Iterator &lt;/span&gt;object for walk over the composite.&lt;br /&gt;Now we can implement the Iterator class:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// MementoState&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class MementoState&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    typedef Composite::iterator_t iterator_t;&lt;br /&gt;    &lt;br /&gt;    MementoState(iterator_t itor, iterator_t end_itor) :&lt;br /&gt;        itor_( itor ),&lt;br /&gt;        end_itor_( end_itor )&lt;br /&gt;    {};&lt;br /&gt;    &lt;br /&gt;    virtual ~MementoState()&lt;br /&gt;    {};&lt;br /&gt;    &lt;br /&gt;    iterator_t&amp;amp; get_itor() { return itor_; };&lt;br /&gt;&lt;br /&gt;    bool is_end() const { return itor_ == end_itor_; };&lt;br /&gt;    &lt;br /&gt;    void next() { itor_++; };&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    iterator_t itor_;&lt;br /&gt;    iterator_t end_itor_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// ItorMemento&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class ItorMemento&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    typedef MementoState item_t;&lt;br /&gt;    &lt;br /&gt;    ItorMemento() {};&lt;br /&gt;    virtual ~ItorMemento() {};&lt;br /&gt;    &lt;br /&gt;    void push_state(const item_t&amp;amp; obj) { state_stack_.push (obj); };&lt;br /&gt;    void pop_state() { state_stack_.pop(); };&lt;br /&gt;    &lt;br /&gt;    item_t&amp;amp; get_state() { return state_stack_.top(); };&lt;br /&gt;    &lt;br /&gt;    bool empty() const { return state_stack_.empty(); };&lt;br /&gt;    &lt;br /&gt;    void reset()&lt;br /&gt;    {&lt;br /&gt;        while(!state_stack_.empty()) &lt;br /&gt;        {&lt;br /&gt;            state_stack_.pop();&lt;br /&gt;        }                    &lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    MementoState::iterator_t&amp;amp; get_current_itor() { return state_stack_.top().get_itor(); };&lt;br /&gt;    &lt;br /&gt;    void next() { state_stack_.top().next(); };&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    std::stack&amp;lt; item_t &amp;gt; state_stack_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;//&lt;br /&gt;// Iterator&lt;br /&gt;//&lt;br /&gt;//////////////////////////////////////////////////////////////////////////////////////&lt;br /&gt;&lt;br /&gt;class Iterator&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    Iterator(Composite* root_ptr) :&lt;br /&gt;        root_ptr_( root_ptr )&lt;br /&gt;    {&lt;br /&gt;    };&lt;br /&gt;    virtual ~Iterator() {};&lt;br /&gt;    &lt;br /&gt;    void first ()&lt;br /&gt;    {&lt;br /&gt;        itor_memento_.reset();&lt;br /&gt;        &lt;br /&gt;        if (root_ptr_-&amp;gt;get_begin() == root_ptr_-&amp;gt;get_end())&lt;br /&gt;        {&lt;br /&gt;            done_ = true;&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        done_ = false;&lt;br /&gt;        itor_memento_.push_state(MementoState(root_ptr_-&amp;gt;get_begin(), root_ptr_-&amp;gt;get_end()));&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    void next()&lt;br /&gt;    {&lt;br /&gt;        if ((*itor_memento_.get_current_itor())-&amp;gt;get_component_type() == Primitive::composite_e)&lt;br /&gt;        {&lt;br /&gt;            Composite* comp_ptr = dynamic_cast&amp;lt; Composite* &amp;gt;(*itor_memento_.get_current_itor());&lt;br /&gt;            itor_memento_.push_state(MementoState(comp_ptr-&amp;gt;get_begin(), comp_ptr-&amp;gt;get_end()));&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        itor_memento_.next();&lt;br /&gt;        &lt;br /&gt;        while (!itor_memento_.empty() &amp;amp;&amp;amp; itor_memento_.get_state().is_end())&lt;br /&gt;        {&lt;br /&gt;            itor_memento_.pop_state();&lt;br /&gt;            if (!itor_memento_.empty())&lt;br /&gt;            {&lt;br /&gt;                itor_memento_.next();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        if (itor_memento_.empty())&lt;br /&gt;        {&lt;br /&gt;            done_ = true;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    Primitive* get_current() { return *itor_memento_.get_current_itor(); };&lt;br /&gt;    &lt;br /&gt;    bool is_done() { return done_; }&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    ItorMemento itor_memento_;&lt;br /&gt;    Composite* root_ptr_;&lt;br /&gt;    bool done_;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;span style="font-style:italic;"&gt;MementoState&lt;/span&gt; is used only for store the current-iterator and the end-iterator. &lt;br /&gt;The &lt;span style="font-style:italic;"&gt;ItorMemento &lt;/span&gt;class manage provide a method of store current state and a method for restore previous state, using an &lt;a href="http://www.cppreference.com/cppstack/index.html"&gt;std::stack&lt;/a&gt; containing all &lt;span style="font-style:italic;"&gt;MementoState &lt;/span&gt;objects.&lt;br /&gt;The &lt;span style="font-style:italic;"&gt;Iterator &lt;/span&gt;class walk on the tree using the &lt;span style="font-style:italic;"&gt;ItorMemento &lt;/span&gt;for move on the hierarchy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-7038547997467058332?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/7038547997467058332/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/03/iterate-over-composite.html#comment-form' title='8 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7038547997467058332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7038547997467058332'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/03/iterate-over-composite.html' title='Iterate over a Composite'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/R-DIlbjdBXI/AAAAAAAAAUQ/bvP1LQjA_0U/s72-c/Composite.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-866763634085511110</id><published>2008-03-13T14:53:00.004+01:00</published><updated>2008-12-11T09:43:54.377+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ggredit'/><title type='text'>ggredit splash</title><content type='html'>I want a splash screen for ggredit...&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R9lH9bjdBUI/AAAAAAAAAT4/tvk7oq8eym4/s1600-h/splash.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R9lH9bjdBUI/AAAAAAAAAT4/tvk7oq8eym4/s320/splash.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5177248367333147970" /&gt;&lt;/a&gt;&lt;br /&gt;Or...&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R9oiIbjdBVI/AAAAAAAAAUA/TasOLKJK8Cg/s1600-h/splash-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R9oiIbjdBVI/AAAAAAAAAUA/TasOLKJK8Cg/s320/splash-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5177488249846564178" /&gt;&lt;/a&gt;&lt;br /&gt;Or...&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R9uSMbjdBWI/AAAAAAAAAUI/HA87w_okeXM/s1600-h/splash2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R9uSMbjdBWI/AAAAAAAAAUI/HA87w_okeXM/s320/splash2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5177892938845062498" /&gt;&lt;/a&gt;&lt;br /&gt;Comments?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-866763634085511110?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/866763634085511110/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/03/ggredit-splash.html#comment-form' title='3 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/866763634085511110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/866763634085511110'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/03/ggredit-splash.html' title='ggredit splash'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_sQJ1m4QDkME/R9lH9bjdBUI/AAAAAAAAAT4/tvk7oq8eym4/s72-c/splash.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-4464617070242523010</id><published>2008-03-10T08:08:00.005+01:00</published><updated>2008-12-11T09:43:54.825+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cairomm'/><category scheme='http://www.blogger.com/atom/ns#' term='pango'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Render text with Pango on Cairo</title><content type='html'>I do not understand very well what is &lt;a href="http://www.pango.org/"&gt;Pango&lt;/a&gt;, we need to use it for render text (this says &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/sec-drawing-text.html"&gt;gtkmm documentation&lt;/a&gt;, but do not say how). Sure when i read Pango I can figure only &lt;a href="http://en.wikipedia.org/wiki/Pingu"&gt;Pingu&lt;/a&gt; (the children's television series)...nock nock!&lt;br /&gt;Probably Pango is the project documented in the worst way, the &lt;a href="http://library.gnome.org/devel/pango/unstable/"&gt;documentation section&lt;/a&gt; is only a link to the documentation generated with &lt;a href="http://www.gtk.org/gtk-doc/"&gt;GTK-Doc&lt;/a&gt;.&lt;br /&gt;I need to be gratefull with &lt;span style="font-style:italic;"&gt;Roy, Andre Robert&lt;/span&gt; that on &lt;a href="http://mail.gnome.org/mailman/listinfo/gtkmm-list"&gt;gtkmm mailing list&lt;/a&gt; wrote:&lt;br /&gt;&lt;blockquote&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #e2ebf8;font-size: 12px;border: 1px;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Hi folks,&lt;br /&gt;&lt;br /&gt;Just an update, I figured out how to render pango layouts with cairo!! :)&lt;br /&gt;&lt;br /&gt;here are a few lines of text to demonstrate:&lt;br /&gt;&lt;br /&gt;Cairo::RefPtr&amp;lt;Cairo::Context&amp;gt; cr = window-&amp;gt;create_cairo_context();&lt;br /&gt;Glib::RefPtr&amp;lt;Pango::Layout&amp;gt; pangoLayout = Pango::Layout::create (cr);&lt;br /&gt;cr-&amp;gt;move_to(doublexpos,doubleypos);&lt;br /&gt;pangoLayout-&amp;gt;set_text(&amp;quot;text&amp;quot;);&lt;br /&gt;pangoLayout-&amp;gt;update_from_cairo_context(cr);  //gets cairo cursor position&lt;br /&gt;pangoLayout-&amp;gt;add_to_cairo_context(cr);       //adds text to cairos stack of stuff to be drawn&lt;br /&gt;cr-&amp;gt;stroke();                                //tells Cairo to render it's stack&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;In this way I have a start point. On gtkmm documentation there is a sample of Pango and Cairo in the Printing section.&lt;br /&gt;For render text we have to use the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classPango_1_1Layout.html"&gt;Pango::Layout&lt;/a&gt; class. We can create this object using the static method &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classPango_1_1Layout.html#e0e8a32e79465fa38d2c59d0cbe482ae"&gt;create&lt;/a&gt; giving our &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html"&gt;Cairo::Context&lt;/a&gt;.&lt;br /&gt;Is important to call &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classPango_1_1Layout.html#6706a92463a0df36eb3f86f8203413d7"&gt;Pango::Layout::update_from_cairo_context&lt;/a&gt; before use Layout object, this update the private &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classPango_1_1Context.html"&gt;Pango::Context&lt;/a&gt; created from the Cairo::Context.&lt;br /&gt;The method &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classPango_1_1Layout.html#712ff9c7e17b28c9a691992aa072cc4d"&gt;Pango::Layout::add_to_cairo_context&lt;/a&gt; execute the text rendering.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Font&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;We can render text with different fonts using the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classPango_1_1FontDescription.html"&gt;FontDescription&lt;/a&gt; class. For create an instance of this class we need to give a string in the format:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #e2ebf8;font-size: 12px;border: 1px;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;quot;[FAMILY-LIST] [STYLE-OPTIONS] [SIZE]&amp;quot;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a href="http://library.gnome.org/devel/pygtk/2.10/class-pangofontdescription.html"&gt;PyGTK documentation&lt;/a&gt; explain how to compose this string.&lt;br /&gt;Family-list is a comma separated list of &lt;a href="http://en.wikipedia.org/wiki/Font_family_(HTML)"&gt;families&lt;/a&gt; like:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #e2ebf8;font-size: 12px;border: 1px;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sans&lt;br /&gt;serif&lt;br /&gt;serif,monospace&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Style-options define the font effect for slant, weight and stretch.&lt;br /&gt;Common values for slant are:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #e2ebf8;font-size: 12px;border: 1px;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Normal: the font is upright.&lt;br /&gt;Oblique: the font is slanted, but in a roman style.&lt;br /&gt;Italic: the font is slanted in an italic style.&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Common values for weight are:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #e2ebf8;font-size: 12px;border: 1px;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Ultra-Light: the ultralight weight (= 200)&lt;br /&gt;Light: the light weight (=300)&lt;br /&gt;Normal: the default weight (= 400)&lt;br /&gt;Bold: the bold weight (= 700)&lt;br /&gt;Ultra-Bold: the ultra-bold weight (= 800)&lt;br /&gt;Heavy: the heavy weight (= 900)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Common values for stretch are:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #e2ebf8;font-size: 12px;border: 1px;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Ultra-Condensed: the smallest width&lt;br /&gt;Extra-Condensed    &lt;br /&gt;Condensed    &lt;br /&gt;Semi-Condensed    &lt;br /&gt;Normal: the normal width&lt;br /&gt;Semi-Expanded    &lt;br /&gt;Expanded    &lt;br /&gt;Extra-Expanded    &lt;br /&gt;Ultra-Expanded: the widest width&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For browse installed fonts you can browse with Nautilus on the URI location:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #e2ebf8;font-size: 12px;border: 1px;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;fonts:///&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So finally we can use desired font with &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classPango_1_1Layout.html#c2193bc15c036f7322da333ddddef4be"&gt;set_font_description&lt;/a&gt; method of Pango::Layout class:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    Pango::FontDescription font_descr( &amp;quot;sans bold 8&amp;quot; );&lt;br /&gt;    pango_layout_ref-&amp;gt;set_font_description( font_descr);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Pango units&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;The metod used above draw text from current position of Cairo::Context on a single line. If you want to define a width for the paragraph you have to use &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classPango_1_1Layout.html#bb0b47950f32da332d6043c9de9b2b07"&gt;set_width&lt;/a&gt; method. We must give width value, an integer value in &lt;span style="font-style:italic;"&gt;Pango units&lt;/span&gt;, not in pixels. If we have the width in pixels we need to convert it in Pango units using the constant &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/namespacePango.html#20d9629a369a6a5ab40ed9c01f879730"&gt;Pango::SCALE&lt;/a&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    double width = x2 - x1;&lt;br /&gt;    pango_layout_ref-&amp;gt;set_width (static_cast&amp;lt;int&amp;gt;(width * Pango::SCALE));&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Text color&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;For set the text color we can use normal set_source_rgb method of Cairo::Context.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    Gdk::Color color(&amp;quot;AliceBlue&amp;quot;);&lt;br /&gt;    cr-&amp;gt;set_source_rgb(color.get_red_p(), color.get_green_p(), color.get_blue_p());&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;You can read my old post &lt;a href="http://kapo-cpp.blogspot.com/2007/09/rgb-on-cairo.html"&gt;RGB on Cairo&lt;/a&gt; for this.&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Pango on ggredit&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;This is my ggredit showing text using Pango:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R9eJJ7jdBTI/AAAAAAAAATw/fNr6PEZuQFA/s1600-h/Screenshot-GraphicEditor-Pango.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R9eJJ7jdBTI/AAAAAAAAATw/fNr6PEZuQFA/s320/Screenshot-GraphicEditor-Pango.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5176757100383896882" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-4464617070242523010?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/4464617070242523010/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/03/render-text-with-pango-on-cairo.html#comment-form' title='2 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/4464617070242523010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/4464617070242523010'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/03/render-text-with-pango-on-cairo.html' title='Render text with Pango on Cairo'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_sQJ1m4QDkME/R9eJJ7jdBTI/AAAAAAAAATw/fNr6PEZuQFA/s72-c/Screenshot-GraphicEditor-Pango.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-5691322139608536171</id><published>2008-02-29T08:37:00.011+01:00</published><updated>2008-12-11T09:43:56.746+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='cdt'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>CDT 4.0.3 is available for download</title><content type='html'>While we are waiting for &lt;a href="http://wiki.eclipse.org/CDT/planning/5.0"&gt;CDT 5.0&lt;/a&gt; (planned for June 08) and we are writing code using CDT 4.0.2 a new release was deployed the 4.0.3, this release includes only numerous &lt;a href="https://bugs.eclipse.org/bugs/buglist.cgi?query_format=advanced&amp;amp;short_desc_type=allwordssubstr&amp;amp;short_desc=&amp;amp;classification=Tools&amp;amp;product=CDT&amp;amp;target_milestone=4.0.3&amp;amp;long_desc=&amp;amp;bug_file_loc_type=allwordssubstr&amp;amp;bug_file_loc=&amp;amp;status_whiteboard_type=allwordssubstr&amp;amp;status_whiteboard=&amp;amp;keywords_type=allwords&amp;amp;keywords=&amp;amp;resolution=FIXED&amp;amp;emailtype1=substring&amp;amp;email1=&amp;amp;emailtype2=substring&amp;amp;email2=&amp;amp;bugidtype=include&amp;amp;bug_id=&amp;amp;votes=&amp;amp;chfieldfrom=&amp;amp;chfieldto=Now&amp;amp;chfieldvalue=&amp;amp;cmdtype=doit&amp;amp;order=Reuse+same+sort+as+last+time&amp;amp;field0-0-0=noop&amp;amp;type0-0-0=noop&amp;amp;value0-0-0="&gt;bugs fixed&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I think you already install &lt;a href="http://www.eclipse.org/"&gt;Eclipse 3.3&lt;/a&gt; on your linux box, may be you follow my post "&lt;a href="http://kapo-cpp.blogspot.com/2008/01/using-eclipse-for-your-gtkmm-project.html"&gt;Using Eclipse for your gtkmm project&lt;/a&gt;". This post is the most popular of my blog, this let me think that people want to know.&lt;br /&gt;&lt;br /&gt;Is better to close all opened project before proceed to update, we need to use root user and this can lock opened projects on the workspace.&lt;br /&gt;&lt;br /&gt;If you install Eclipse, as explained on my tutorial, on directory &lt;span style="font-weight:bold;"&gt;/opt/eclipse/&lt;/span&gt; you have to run Eclipse as root:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo /usr/bin/eclipse&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;If you never run Eclipse as root it will ask you for select a workspace (as the first time), I select my default workspace.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R8e3I_eth2I/AAAAAAAAASo/6YyUyMMok0Y/s1600-h/Screenshot-0-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R8e3I_eth2I/AAAAAAAAASo/6YyUyMMok0Y/s320/Screenshot-0-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5172304062165387106" /&gt;&lt;/a&gt;&lt;br /&gt;For upgrade CDT to the new version you have to select the menu option &lt;span style="font-weight:bold;"&gt;Help\Software Updates\Find and install...&lt;/span&gt; (always I ask to myself the reason for put Software Update on the Help menu)&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R8e5BPeth3I/AAAAAAAAASw/gYkbFZq5_Pg/s1600-h/Screenshot-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R8e5BPeth3I/AAAAAAAAASw/gYkbFZq5_Pg/s320/Screenshot-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5172306128044656498" /&gt;&lt;/a&gt;&lt;br /&gt;First Eclipse prompt a dialog asking if you want to update an existing feature or if you want to install a new feature. We want to update CDT:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R8e6t_eth4I/AAAAAAAAAS4/owUvP22VFtk/s1600-h/Screenshot-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R8e6t_eth4I/AAAAAAAAAS4/owUvP22VFtk/s320/Screenshot-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5172307996355430274" /&gt;&lt;/a&gt;&lt;br /&gt;When we click Finish button Eclipse will search for updates on installed features, when the search is complete it should display in the list of available updates CDT 4.0.3.xyz&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R8fAFveth5I/AAAAAAAAATA/gXxiCZ3n8qg/s1600-h/Screenshot-3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R8fAFveth5I/AAAAAAAAATA/gXxiCZ3n8qg/s320/Screenshot-3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5172313901935462290" /&gt;&lt;/a&gt;&lt;br /&gt;Next we have to accept license (read carefully)&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R8fAi_eth6I/AAAAAAAAATI/X4yVf-ByhQI/s1600-h/Screenshot-5.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R8fAi_eth6I/AAAAAAAAATI/X4yVf-ByhQI/s320/Screenshot-5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5172314404446635938" /&gt;&lt;/a&gt;&lt;br /&gt;So the list of selected updates will be displayed and we can click on Finish button for install updates.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R8fBsPeth7I/AAAAAAAAATQ/tT-rRVVgUoU/s1600-h/Screenshot-6.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R8fBsPeth7I/AAAAAAAAATQ/tT-rRVVgUoU/s320/Screenshot-6.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5172315662872053682" /&gt;&lt;/a&gt;&lt;br /&gt;And wait until download finish...&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R8fCJPeth8I/AAAAAAAAATY/tSxslTYcmv0/s1600-h/Screenshot-7.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R8fCJPeth8I/AAAAAAAAATY/tSxslTYcmv0/s320/Screenshot-7.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5172316161088260034" /&gt;&lt;/a&gt;&lt;br /&gt;When download is complete we have to confirm installation:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R8fCwPeth9I/AAAAAAAAATg/Bf0Jwu5-r2M/s1600-h/Screenshot-8.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R8fCwPeth9I/AAAAAAAAATg/Bf0Jwu5-r2M/s320/Screenshot-8.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5172316831103158226" /&gt;&lt;/a&gt;&lt;br /&gt;And when installation is complete ask for restart platform, so click Yes:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R8fC_feth-I/AAAAAAAAATo/sQohhl4uBxE/s1600-h/Screenshot-9.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R8fC_feth-I/AAAAAAAAATo/sQohhl4uBxE/s320/Screenshot-9.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5172317093096163298" /&gt;&lt;/a&gt;&lt;br /&gt;When Eclipse restart we can close it and open as normal user, using the Gnome menu, and work with CDT 4.0.3.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-5691322139608536171?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/5691322139608536171/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/02/cdt-403-is-available-for-download.html#comment-form' title='4 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5691322139608536171'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5691322139608536171'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/02/cdt-403-is-available-for-download.html' title='CDT 4.0.3 is available for download'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_sQJ1m4QDkME/R8e3I_eth2I/AAAAAAAAASo/6YyUyMMok0Y/s72-c/Screenshot-0-1.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-5059172428204616226</id><published>2008-02-24T08:48:00.017+01:00</published><updated>2008-12-11T09:43:59.780+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='xml'/><title type='text'>Working with XML on linux</title><content type='html'>If you want to add &lt;a href="http://www.w3.org/XML/"&gt;XML&lt;/a&gt; support for your c++ project on linux you have two choice (at least):&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://xmlsoft.org/"&gt;libxml2&lt;/a&gt; the XML C parser and toolkit of Gnome&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://xerces.apache.org/xerces-c/"&gt;Xerces-C++&lt;/a&gt; the Apache XML project for C++&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;When I start to write my ggredit project I do not know the existence of Xerces and I start to use libxml2. I see many open souce projects use libxml2 (&lt;a href="http://www.inkscape.org/"&gt;inkscape&lt;/a&gt;, &lt;a href="http://www.gnome.org/projects/dia/"&gt;dia&lt;/a&gt; and also &lt;a href="http://uml.sourceforge.net/index.php"&gt;umbrello&lt;/a&gt; based on QT) so I think this is the right way. But from when I discover Xerces I am not so sure...&lt;br /&gt;On libxml2 homepage you can find a link to &lt;a href="http://libxmlplusplus.sourceforge.net/"&gt;C++ bindings&lt;/a&gt;, I have only a quick look at the &lt;a href="http://libxmlplusplus.sourceforge.net/docs/reference/stable/html/hierarchy.html"&gt;documentation&lt;/a&gt;  but I can not see XSD schema management or an XML writer so I start write a tiny light C++ wrapper for libxml2 to use on my project, if you want you can download it from &lt;a href="http://www.box.net/shared/ph1sog2yog"&gt;here&lt;/a&gt;. This is not a complete wrapper, I implement only functionality required for my project so: a DOM document parser, the XSD schema validator, XPath management, an XML text writer.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Add libxml2 reference&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;First we need to configure our project for use libxml2. So we need to add the include directory to the compiler and add the library to the linker.&lt;br /&gt;If you use Eclipse you can add the include directory &lt;span style="font-weight:bold;"&gt;/usr/src/include/libxml2&lt;/span&gt; using the project properties dialog:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R8EzQIerVqI/AAAAAAAAAR4/QiRvOvaO_Ns/s1600-h/Schermata-Properties+for+ggredit+-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R8EzQIerVqI/AAAAAAAAAR4/QiRvOvaO_Ns/s320/Schermata-Properties+for+ggredit+-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5170470199445116578" /&gt;&lt;/a&gt;&lt;br /&gt;And the &lt;span style="font-weight:bold;"&gt;xml2&lt;/span&gt; library to the linker:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R8EzhoerVrI/AAAAAAAAASA/y34O895TG00/s1600-h/Schermata-Properties+for+ggredit+.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R8EzhoerVrI/AAAAAAAAASA/y34O895TG00/s320/Schermata-Properties+for+ggredit+.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5170470500092827314" /&gt;&lt;/a&gt;&lt;br /&gt;If you do not use Eclipse you can add the include directory on the &lt;span style="font-weight:bold;"&gt;-I&lt;/span&gt; option of gcc and the linker library on the &lt;span style="font-weight:bold;"&gt;-l&lt;/span&gt; option.&lt;br/&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;The DOM document parser&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;On libxml2 a document is managed by the &lt;a href="http://xmlsoft.org/html/libxml-tree.html#xmlDoc"&gt;xmlDoc&lt;/a&gt; structure, all API's for parse xml data return a pointer to this structure: &lt;a href="http://xmlsoft.org/html/libxml-tree.html#xmlDocPtr"&gt;xmlDocPtr&lt;/a&gt;. &lt;br /&gt;This pointer is allocated when we load the xml files using &lt;a href="http://xmlsoft.org/html/libxml-parser.html#xmlParseFile"&gt;xmlParseFile&lt;/a&gt;, we need to free allocated resources using &lt;a href="http://xmlsoft.org/html/libxml-tree.html#xmlFreeDoc"&gt;xmlFreeDoc&lt;/a&gt;. We can write the first class.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R8JvaIerVsI/AAAAAAAAASI/xPQXvK54ymI/s1600-h/XmlDocument.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R8JvaIerVsI/AAAAAAAAASI/xPQXvK54ymI/s320/XmlDocument.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5170817816918185666" /&gt;&lt;/a&gt;&lt;br /&gt;Elements on the DOM document tree are stored on &lt;a href="http://xmlsoft.org/html/libxml-tree.html#xmlNode"&gt;xmlNode&lt;/a&gt; structure. All this objects are allocated during parsing, we have to work with raw pointers &lt;a href="http://xmlsoft.org/html/libxml-tree.html#xmlNodePtr"&gt;xmlNodePtr&lt;/a&gt;. We do not need to free this structure, the document is the owner for all nodes. So we can get the node name, the node text...but...wait...libxml2 store string as &lt;a href="http://xmlsoft.org/html/libxml-xmlstring.html#xmlChar"&gt;xmlChar*&lt;/a&gt;, but we use &lt;a href="http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/classGlib_1_1ustring.html"&gt;Glib::ustring&lt;/a&gt; in our gtkmm application. The Glib::ustring character encoding is &lt;a href="http://en.wikipedia.org/wiki/UTF-8"&gt;UTF-8&lt;/a&gt; and also xmlChar string use the same encoding, so I think we can use reinterpret_cast, also libxml2 define the &lt;a href="http://xmlsoft.org/html/libxml-xmlstring.html#BAD_CAST"&gt;BAD_CAST&lt;/a&gt; macro for cast a char* to an xmlChar* .&lt;br /&gt;For get the node name as Glib::ustring I use:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Glib::ustring DomNode::getName() const &lt;br /&gt;{ &lt;br /&gt;    if (node_ptr_-&amp;gt;name != NULL)&lt;br /&gt;        return reinterpret_cast&amp;lt;const char*&amp;gt;(node_ptr_-&amp;gt;name);&lt;br /&gt;    else&lt;br /&gt;        throw NodeError( &amp;quot;Invalid node pointer&amp;quot; );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For read an attribute value we need to use &lt;a href="http://xmlsoft.org/html/libxml-tree.html#xmlGetProp"&gt;xmlGetProp&lt;/a&gt; function. This function return an xmlChar and let us the ownership of free memory using xmlFree.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Glib::ustring DomNode::getAttributeValue(const Glib::ustring&amp;amp; name) const&lt;br /&gt;{&lt;br /&gt;    xmlChar* value = xmlGetProp(node_ptr_, BAD_CAST name.c_str());&lt;br /&gt;    &lt;br /&gt;    if (value == NULL)&lt;br /&gt;    {&lt;br /&gt;        throw NodeError( &amp;quot;Attribute not found '&amp;quot; + name + &amp;quot;'&amp;quot; );&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        Glib::ustring ret_value( reinterpret_cast&amp;lt;const char*&amp;gt;(value) );&lt;br /&gt;        xmlFree (value);&lt;br /&gt;        return ret_value;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For get node text we have to use &lt;a href="http://xmlsoft.org/html/libxml-tree.html#xmlNodeListGetString"&gt;xmlNodeListGetString&lt;/a&gt; function. This function return all text from given node.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Glib::ustring DomNode::getString() const&lt;br /&gt;{&lt;br /&gt;    xmlChar* value = xmlNodeListGetString(node_ptr_-&amp;gt;doc, node_ptr_-&amp;gt;xmlChildrenNode, 1);&lt;br /&gt;&lt;br /&gt;    if (value == NULL)&lt;br /&gt;    {&lt;br /&gt;        return &amp;quot;&amp;quot;;&lt;br /&gt;    }&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        Glib::ustring ret_value( reinterpret_cast&amp;lt;const char*&amp;gt;(value) );&lt;br /&gt;        xmlFree (value);&lt;br /&gt;        return ret_value;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For navigate the tree we have to use the &lt;span style="font-weight:bold;"&gt;next &lt;/span&gt;and &lt;span style="font-weight:bold;"&gt;children&lt;/span&gt; members of xmlNodePtr.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;DomNode DomNode::getNext()&lt;br /&gt;{&lt;br /&gt;    return node_ptr_-&amp;gt;next;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;DomNode DomNode::getChild()&lt;br /&gt;{&lt;br /&gt;    return node_ptr_-&amp;gt;children;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;I prefer &lt;a href="http://libxmlplusplus.sourceforge.net/"&gt;libxml++&lt;/a&gt; implementation for iterate the document tree, using container like standard library.&lt;br /&gt;&lt;br /&gt;For read elements on the DOM document first we need the root element, the function &lt;a href="http://xmlsoft.org/html/libxml-tree.html#xmlDocGetRootElement"&gt;xmlDocGetRootElement&lt;/a&gt; return this.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;DomNode XmlDocument::getRootNode()&lt;br /&gt;{&lt;br /&gt;    if (doc_ptr_ == 0)&lt;br /&gt;        throw DocumentError(&amp;quot;Can not read root-node, document is NULL&amp;quot;);&lt;br /&gt;    &lt;br /&gt;    xmlNodePtr root_node_ptr = xmlDocGetRootElement(doc_ptr_);&lt;br /&gt;    &lt;br /&gt;    if (root_node_ptr == 0)&lt;br /&gt;        throw DocumentError(&amp;quot;Error reading root element&amp;quot;);&lt;br /&gt;    &lt;br /&gt;    return root_node_ptr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally we have this architecture:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R8KWPIerVuI/AAAAAAAAASY/7u1VTItq-UQ/s1600-h/XmlDocument-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R8KWPIerVuI/AAAAAAAAASY/7u1VTItq-UQ/s320/XmlDocument-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5170860508893107938" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;The XSD schema validator&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;If you go on libxml2 homepage and search for validation you can find only &lt;a href="http://xmlsoft.org/xmldtd.html"&gt;DTD validation&lt;/a&gt;. If you search for &lt;a href="http://www.w3.org/XML/Schema"&gt;schema&lt;/a&gt; you can find this &lt;a href="http://xmlsoft.org/html/libxml-xmlschemas.html"&gt;page&lt;/a&gt; on the API documentation, the first row say:&lt;br /&gt;&lt;blockquote&gt;interface to the XML Schemas handling and schema validity checking, it is incomplete right now.&lt;/blockquote&gt;&lt;br /&gt;when I read this message I think I made the wrong choice.&lt;br /&gt;Searching on Google i find this &lt;a href="http://www.collada.org/mediawiki/index.php/Schema_validation"&gt;page&lt;/a&gt;, of the &lt;a href="http://www.collada.org/mediawiki/index.php/COLLADA"&gt;Collada&lt;/a&gt; project. I never hear this project but here you can find the code for validate an xml document using an xsd schema.&lt;br /&gt;First we need to create a parser for the schema file: &lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Schema::Schema(const Glib::ustring&amp;amp; schema_uri) :&lt;br /&gt;    schema_parser_ptr_( NULL ),&lt;br /&gt;    schema_ptr_( NULL )&lt;br /&gt;{&lt;br /&gt;    schema_parser_ptr_ = xmlSchemaNewParserCtxt (schema_uri.c_str());&lt;br /&gt;    if (schema_parser_ptr_ == NULL)&lt;br /&gt;    {&lt;br /&gt;        throw SchemaError ( &amp;quot;Unable to create schema parser for &amp;quot; + schema_uri );&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    schema_ptr_ = xmlSchemaParse (schema_parser_ptr_);&lt;br /&gt;    if (schema_ptr_ == NULL)&lt;br /&gt;    {&lt;br /&gt;        throw SchemaError ( &amp;quot;Unable to create schema for &amp;quot; + schema_uri );&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then we can validate xml documents using the schema parsed above:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;bool Schema::validate(const Glib::ustring&amp;amp; filename)&lt;br /&gt;{&lt;br /&gt;    bool result = false;&lt;br /&gt;    &lt;br /&gt;    if (xmlSchemaValidCtxtPtr validity_context_ptr = xmlSchemaNewValidCtxt (schema_ptr_)) &lt;br /&gt;    {&lt;br /&gt;      result = xmlSchemaValidateFile (validity_context_ptr, filename.c_str(), 0) == 0;&lt;br /&gt;      xmlSchemaFreeValidCtxt (validity_context_ptr);&lt;br /&gt;    }    &lt;br /&gt;    &lt;br /&gt;    return result;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When we finish to use the schema we need to free resources:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;Schema::~Schema()&lt;br /&gt;{&lt;br /&gt;    if (schema_ptr_ != NULL)&lt;br /&gt;    {&lt;br /&gt;        xmlSchemaFree (schema_ptr_);;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    if (schema_parser_ptr_ != NULL)&lt;br /&gt;    {&lt;br /&gt;        xmlSchemaFreeParserCtxt (schema_parser_ptr_);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;XPath management&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;For access elements sometimes is better to use &lt;a href="http://www.w3.org/TR/xpath"&gt;xpath&lt;/a&gt;. We can use xpath only for a document already parsed. For use xpath we have to create an &lt;a href="http://xmlsoft.org/html/libxml-xpath.html#xmlXPathContextPtr"&gt;xmlXPathContext&lt;/a&gt; instance:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void XPath::createContext()&lt;br /&gt;{&lt;br /&gt;    // Create xpath evaluation context&lt;br /&gt;    xpath_ctx_ptr_ = xmlXPathNewContext (doc_ptr_);&lt;br /&gt;    if (xpath_ctx_ptr_ == NULL) &lt;br /&gt;    {&lt;br /&gt;        throw XPathError( &amp;quot;Unable to create new XPath context&amp;quot; );&lt;br /&gt;    }    &lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And when we finish to work with this object we need to free resources:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void XPath::freeContext()&lt;br /&gt;{&lt;br /&gt;    // Cleanup&lt;br /&gt;    if (xpath_ctx_ptr_ != NULL)&lt;br /&gt;    {&lt;br /&gt;        xmlXPathFreeContext (xpath_ctx_ptr_);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;If you use namespaces in your xml you need to register this namespaces on the xpath object, we have to use &lt;a href="http://xmlsoft.org/html/libxml-xpathInternals.html#xmlXPathRegisterNs"&gt;xmlXPathRegisterNs&lt;/a&gt; function:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void XPath::registerNamespace(const Glib::ustring&amp;amp; prefix, const Glib::ustring&amp;amp; href)&lt;br /&gt;{&lt;br /&gt;    // do register namespace&lt;br /&gt;    if(xmlXPathRegisterNs (xpath_ctx_ptr_, BAD_CAST prefix.c_str(), BAD_CAST href.c_str()) != 0) &lt;br /&gt;    {&lt;br /&gt;        throw XPathError( &amp;quot;Unable to register NS with prefix=&amp;quot; + prefix + &amp;quot; and href=&amp;quot; + href);&lt;br /&gt;    }    &lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For evaluate an &lt;a href="http://www.w3schools.com/xpath/xpath_syntax.asp"&gt;xpath expression&lt;/a&gt; we have to use &lt;a href="http://xmlsoft.org/html/libxml-xpath.html#xmlXPathEvalExpression"&gt;xmlXPathEvalExpression&lt;/a&gt; function, the result of an xpath expression is an &lt;a href="http://xmlsoft.org/html/libxml-xpath.html#xmlXPathObject"&gt;xmlXPathObject&lt;/a&gt; containing an array of nodes on the &lt;span style="font-weight:bold;"&gt;nodesetval&lt;/span&gt; member, if the expression return more than one nodes, the type of the array is &lt;a href="http://xmlsoft.org/html/libxml-xpath.html#xmlNodeSet"&gt;xmlNodeSet&lt;/a&gt;.&lt;br /&gt;I create a class for the array of node management:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;namespace xml&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;DomNodeSet::DomNodeSet(xmlNodeSetPtr node_set_ptr) :&lt;br /&gt;    node_set_ptr_( node_set_ptr )&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;DomNodeSet::~DomNodeSet()&lt;br /&gt;{&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int DomNodeSet::getNodeSize() const&lt;br /&gt;{&lt;br /&gt;    return node_set_ptr_-&amp;gt;nodeNr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;DomNode DomNodeSet::getNode(int index) const&lt;br /&gt;{&lt;br /&gt;    if (index &amp;gt;= node_set_ptr_-&amp;gt;nodeNr)&lt;br /&gt;    {&lt;br /&gt;        throw DomNodeSetError( &amp;quot;Node index out of bound&amp;quot; );&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    return DomNode( node_set_ptr_-&amp;gt;nodeTab[index] );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A class for store XPath result, this simply return the DomNodeSet and free resources on destructor using &lt;a href="http://xmlsoft.org/html/libxml-xpath.html#xmlXPathFreeObject"&gt;xmlXPathFreeObject&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;/**&lt;br /&gt; * @brief Result of XPath query&lt;br /&gt; */&lt;br /&gt;class XPathResult&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    /**&lt;br /&gt;     * @brief Constructor&lt;br /&gt;     * &lt;br /&gt;     * @param xpath_obj_ptr xmlXPathObjectPtr returned from libxml2&lt;br /&gt;     */&lt;br /&gt;    XPathResult(xmlXPathObjectPtr xpath_obj_ptr) :&lt;br /&gt;        xpath_obj_ptr_( xpath_obj_ptr )&lt;br /&gt;    {&lt;br /&gt;    };&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * @brief Destructor&lt;br /&gt;     * &lt;br /&gt;     * Free xmlXPathObjectPtr&lt;br /&gt;     */&lt;br /&gt;    virtual ~XPathResult()&lt;br /&gt;    {&lt;br /&gt;        if (xpath_obj_ptr_ != NULL)&lt;br /&gt;        {&lt;br /&gt;            xmlXPathFreeObject (xpath_obj_ptr_);&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * @brief Test for nodes array existence&lt;br /&gt;     * &lt;br /&gt;     * @return true if the nodes array is not null&lt;br /&gt;     */&lt;br /&gt;    bool hasNodeSet() const&lt;br /&gt;    {&lt;br /&gt;        return xpath_obj_ptr_-&amp;gt;nodesetval != NULL;&lt;br /&gt;    };&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * @brief Nodes array&lt;br /&gt;     * &lt;br /&gt;     * @return the nodes array&lt;br /&gt;     */&lt;br /&gt;    DomNodeSet getNodeSet()&lt;br /&gt;    {&lt;br /&gt;        return xpath_obj_ptr_-&amp;gt;nodesetval;&lt;br /&gt;    };&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    xmlXPathObjectPtr xpath_obj_ptr_;&lt;br /&gt;};&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Finally we can evaluate the xpath expression:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;XPathResult XPath::evalExpression(const Glib::ustring&amp;amp; expr)&lt;br /&gt;{&lt;br /&gt;    // Evaluate xpath expression&lt;br /&gt;    xmlXPathObjectPtr xpath_obj_ptr = xmlXPathEvalExpression (BAD_CAST expr.c_str(), xpath_ctx_ptr_);&lt;br /&gt;    if(xpath_obj_ptr == NULL) &lt;br /&gt;    {&lt;br /&gt;        throw XPathError( &amp;quot;Unable to evaluate xpath expression &amp;quot; + expr);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return XPathResult( xpath_obj_ptr );    &lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So we have this architecture:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R8O-ZYerVvI/AAAAAAAAASg/OyG4yLtxwRM/s1600-h/XmlXPath.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R8O-ZYerVvI/AAAAAAAAASg/OyG4yLtxwRM/s320/XmlXPath.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5171186140428588786" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;The XML text writer&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;For write an xml document we have to use the &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html"&gt;text writing API&lt;/a&gt;, you can store an entire tree or sequentially open and close elements, I use the last one.&lt;br /&gt;First we need to create the new text writer object using &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html#xmlNewTextWriterFilename"&gt;xmlNewTextWriterFilename&lt;/a&gt;, we have to give the file name and the compression flag, if this flag is zero the file was human readable and you can open it using your preferred text editor, if you enable compression the file size decrease but you can not read the file normally. I do not enable compression for xml files.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void TextWriter::open(const Glib::ustring&amp;amp; file_name, bool compression/* =false */)&lt;br /&gt;{&lt;br /&gt;    writer_ = xmlNewTextWriterFilename(file_name.c_str(), compression ? 1 : 0);&lt;br /&gt;    &lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;(libxml) Error creating the xml writer&amp;quot; );&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;When we finish to use text writer as usual we have to free resources:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void TextWriter::free()&lt;br /&gt;{&lt;br /&gt;    if (writer_ != NULL)&lt;br /&gt;    {&lt;br /&gt;        xmlFreeTextWriter(writer_);&lt;br /&gt;        writer_ = NULL;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;If you write elements on this writer the output will be unformatted on a single line, and this is not ok. For enable formatting we have to use the &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html#xmlTextWriterSetIndent"&gt;xmlTextWriterSetIndent&lt;/a&gt; function.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void TextWriter::setIndent(bool value)&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterSetIndent (writer_, value ? 1 : 0);&lt;br /&gt;&lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;        throw WriterError( &amp;quot;(libxml) Error at setIndent&amp;quot; );&lt;br /&gt;&lt;br /&gt;    indent_ = true;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Now we can use all &lt;span style="font-weight:bold;"&gt;xmlTextWriterStartXYZ&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;xmlTextWriterEndXYZ&lt;/span&gt; API. First we have to open the document, writing the main xml element:&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;ISO-8859-1&amp;quot;?&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We have to use the &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html#xmlTextWriterStartDocument"&gt;xmlTextWriterStartDocument&lt;/a&gt; function, giving the xml version "1.0" and the econding (for this I use "UTF-8"). When we finish to write all elements we have to call the &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html#xmlTextWriterEndDocument"&gt;xmlTextWriterEndDocument&lt;/a&gt; function.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void TextWriter::startDocument(const Glib::ustring&amp;amp; version, const Glib::ustring&amp;amp; encoding)&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterStartDocument(writer_, version.c_str(), encoding.c_str(), NULL);&lt;br /&gt;&lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;        throw WriterError( &amp;quot;(libxml) Error at startDocument&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    encoding_ = encoding;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void TextWriter::endDocument()&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterEndDocument(writer_);&lt;br /&gt;    &lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;         throw WriterError( &amp;quot;(libxml) Error at endDocument&amp;quot; );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;When the document is started we can add elements using &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html#xmlTextWriterStartElement"&gt;xmlTextWriterStartElement&lt;/a&gt;, for close the element we have to use &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html#xmlTextWriterEndElement"&gt;xmlTextWriterEndElement&lt;/a&gt;. So we can create nested elements using &lt;span style="font-weight:bold;"&gt;start &lt;/span&gt;and &lt;span style="font-weight:bold;"&gt;end&lt;/span&gt;, this is similar to write an xml document by hand. Probably you want to add elements using namespace so you have to use  &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html#xmlTextWriterStartElementNS"&gt;xmlTextWriterStartElementNS&lt;/a&gt;.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void TextWriter::startElement(const Glib::ustring&amp;amp; name)&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterStartElement (writer_, BAD_CAST name.c_str());&lt;br /&gt;    &lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;         throw WriterError( &amp;quot;(libxml) Error at startElement&amp;quot; );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void TextWriter::startElement(const Glib::ustring&amp;amp; name, const Glib::ustring&amp;amp; prefix)&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterStartElementNS (writer_, &lt;br /&gt;                                        BAD_CAST prefix.c_str(), &lt;br /&gt;                                        BAD_CAST name.c_str(), &lt;br /&gt;                                        NULL);&lt;br /&gt;    &lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;         throw WriterError( &amp;quot;(libxml) Error at startElement&amp;quot; );    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void TextWriter::startElement(const Glib::ustring&amp;amp; name, const Glib::ustring&amp;amp; prefix, const Glib::ustring&amp;amp; namespaceURI)&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterStartElementNS (writer_, &lt;br /&gt;                                        BAD_CAST prefix.c_str(), &lt;br /&gt;                                        BAD_CAST name.c_str(), &lt;br /&gt;                                        BAD_CAST namespaceURI.c_str());&lt;br /&gt;    &lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;         throw WriterError( &amp;quot;(libxml) Error at startElement&amp;quot; );    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void TextWriter::endElement()&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterEndElement (writer_);&lt;br /&gt;    &lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;         throw WriterError( &amp;quot;(libxml) Error at endElement&amp;quot; );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;For add attributes to an element we can use &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html#xmlTextWriterWriteAttribute"&gt;xmlTextWriterWriteAttribute&lt;/a&gt; giving attribute name and value. This function must be called only after startElement.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void TextWriter::writeAttribute(const Glib::ustring&amp;amp; name, const Glib::ustring&amp;amp; value)&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterWriteAttribute (writer_, &lt;br /&gt;                                        BAD_CAST name.c_str(),&lt;br /&gt;                                        BAD_CAST value.c_str());&lt;br /&gt;    &lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;         throw WriterError( &amp;quot;(libxml) Error at endElement&amp;quot; );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void TextWriter::writeAttribute(const Glib::ustring&amp;amp; name, const Glib::ustring&amp;amp; value, const Glib::ustring&amp;amp; prefix)&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterWriteAttributeNS (writer_,&lt;br /&gt;                                            BAD_CAST prefix.c_str(),&lt;br /&gt;                                            BAD_CAST name.c_str(),&lt;br /&gt;                                            NULL,&lt;br /&gt;                                            BAD_CAST value.c_str());&lt;br /&gt;    &lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;         throw WriterError( &amp;quot;(libxml) Error at endElement&amp;quot; );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void TextWriter::writeAttribute(const Glib::ustring&amp;amp; name, const Glib::ustring&amp;amp; value, const Glib::ustring&amp;amp; prefix, const Glib::ustring&amp;amp; namespaceURI)&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterWriteAttributeNS (writer_,&lt;br /&gt;                                            BAD_CAST prefix.c_str(),&lt;br /&gt;                                            BAD_CAST name.c_str(),&lt;br /&gt;                                            BAD_CAST namespaceURI.c_str(),&lt;br /&gt;                                            BAD_CAST value.c_str());&lt;br /&gt;    &lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;         throw WriterError( &amp;quot;(libxml) Error at endElement&amp;quot; );&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;We can add text to an element using &lt;a href="http://xmlsoft.org/html/libxml-xmlwriter.html#xmlTextWriterWriteString"&gt;xmlTextWriterWriteString &lt;/a&gt;after startElement.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;void TextWriter::writeString(const Glib::ustring&amp;amp; text)&lt;br /&gt;{&lt;br /&gt;    if (writer_ == NULL) &lt;br /&gt;        throw WriterError( &amp;quot;Invalid writer&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    int rc = xmlTextWriterWriteString(writer_, BAD_CAST text.c_str());&lt;br /&gt;    &lt;br /&gt;    if (rc &amp;lt; 0) &lt;br /&gt;         throw WriterError( &amp;quot;(libxml) Error at writeString&amp;quot; );    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-5059172428204616226?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/5059172428204616226/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/02/working-with-xml-on-linux.html#comment-form' title='6 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5059172428204616226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5059172428204616226'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/02/working-with-xml-on-linux.html' title='Working with XML on linux'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_sQJ1m4QDkME/R8EzQIerVqI/AAAAAAAAAR4/QiRvOvaO_Ns/s72-c/Schermata-Properties+for+ggredit+-1.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-7154598722063120195</id><published>2008-02-22T08:00:00.005+01:00</published><updated>2008-12-11T09:44:00.152+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ggredit'/><title type='text'>ggredit breaking news</title><content type='html'>We interrupt the normal programming for a shoking news: I complete the save and load functionality on ggredit.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R76HVYerVoI/AAAAAAAAARo/5R-YShhRGTY/s1600-h/breaking-news.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R76HVYerVoI/AAAAAAAAARo/5R-YShhRGTY/s320/breaking-news.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5169718223686030978" /&gt;&lt;/a&gt;&lt;br /&gt;Now ggredit store data on a well formed xml validated using schema. For this I write a light &lt;a href="http://xmlsoft.org/"&gt;libxml2&lt;/a&gt; c++ wrapper.&lt;br /&gt;I start also to implement the first UML object: the start-point of activity diagram...a black filled ellipse.&lt;br /&gt;Now is possible to draw the first diagram using ggredit:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R76IwoerVpI/AAAAAAAAARw/MojB0tort80/s1600-h/Screenshot-GraphicEditor-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R76IwoerVpI/AAAAAAAAARw/MojB0tort80/s320/Screenshot-GraphicEditor-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5169719791349094034" /&gt;&lt;/a&gt;&lt;br /&gt;This is the penis diagram and describe the life essence.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-7154598722063120195?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/7154598722063120195/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/02/ggredit-breaking-news.html#comment-form' title='1 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7154598722063120195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7154598722063120195'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/02/ggredit-breaking-news.html' title='ggredit breaking news'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/R76HVYerVoI/AAAAAAAAARo/5R-YShhRGTY/s72-c/breaking-news.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-3304771578076997426</id><published>2008-02-14T07:54:00.014+01:00</published><updated>2008-12-11T09:44:01.032+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mime'/><category scheme='http://www.blogger.com/atom/ns#' term='freedesktop'/><category scheme='http://www.blogger.com/atom/ns#' term='gnome'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Register your own MIME type on a free desktop</title><content type='html'>If someone is interested on ggredit status, be quiete the patient is still alive. &lt;br /&gt;But today I want to continue with the MIME type registration.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R7mR04erVnI/AAAAAAAAARg/XumueXuEDfs/s1600-h/Pantomime-Pablo2.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R7mR04erVnI/AAAAAAAAARg/XumueXuEDfs/s320/Pantomime-Pablo2.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5168322385084634738" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I start reading &lt;a href="http://docs.sun.com/app/docs/doc/817-5310/6mkpbn3tu?a=view"&gt;this article&lt;/a&gt;, here you can find explanation about how Gnome identify the type of a file. On Gnome the file manage &lt;a href="http://www.gnome.org/projects/nautilus/"&gt;Nautilus&lt;/a&gt; use &lt;a href="http://library.gnome.org/devel/gnome-vfs-2.0/unstable/"&gt;GnomeVFS&lt;/a&gt; for work with MIME types.&lt;br /&gt;Gnome can identify the MIME type in two way: searching for a particular pattern on the file content or matching the file name.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R7PwBIerVjI/AAAAAAAAARA/Pt3rOQGMXdo/s1600-h/mime1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R7PwBIerVjI/AAAAAAAAARA/Pt3rOQGMXdo/s320/mime1.png" alt="" id="BLOGGER_PHOTO_ID_5166737099770779186" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;The first way is the most cool, when I switch to Ubuntu from Windows this was the first difference I notice. Recognized patterns are stored on &lt;span style="font-weight: bold;"&gt;/etc/gnome-vfs-mime-magic&lt;/span&gt; setting file.&lt;br /&gt;The second way is the common method for recognize the type using extension. Recognized extensions are stored on the &lt;span style="font-weight: bold;"&gt;/usr/share/mime-info&lt;/span&gt; directory. When the system identify a MIME type can run the default application registered on the directory &lt;span style="font-weight:bold;"&gt;/usr/share/application-registry&lt;/span&gt; in the file &lt;span style="font-weight:bold;"&gt;gnome-vfs.applications&lt;/span&gt;.&lt;br /&gt;If you want to go into more depth on files structure you can read the linked article. We do not need to manually update these files, when we need to update the MIME database we can use &lt;a href="http://portland.freedesktop.org/xdg-utils-1.0/xdg-mime.html"&gt;xdg-mime&lt;/a&gt; and &lt;a href="http://portland.freedesktop.org/xdg-utils-1.0/xdg-icon-resource.html"&gt;xdg-icon-resource&lt;/a&gt; commands, from package &lt;a href="http://portland.freedesktop.org/xdg-utils-1.0/"&gt;xdg-utils&lt;/a&gt; included in Gnome. We have to add this command on the &lt;span style="font-weight: bold;"&gt;make install&lt;/span&gt; target for configure the desired MIME type during installation.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Use xdg-icon-resource&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;First we need to register the icon for our MIME type. We can accomplish this task using the xdg-icon-resource command. First you need to create a &lt;a href="http://kapo-cpp.blogspot.com/2008/02/ggredit-mime-icon.html"&gt;good icon&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo xdg-icon-resource install --context mimetypes --size 48 /home/user/Pictures/ggredit/48x48/ggredit-file-type.png x-application-ggr-diagram&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We have to give the file name (the png file) and an arbitrary icon name (x-application-ggr-diagram), we will use this name next.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Use xdg-mime&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;For register the MIME type on the MIME-info Database we have to use xdg-mime but first we have to write a configuration file, using an XML file that follow the &lt;a href="http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html#id2447399"&gt;freedesktop spec&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&lt;br /&gt;&amp;lt;mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'&amp;gt;&lt;br /&gt;  &amp;lt;mime-type type=&amp;quot;application/x-ggr-diagram&amp;quot;&amp;gt;&lt;br /&gt;  &lt;br /&gt;    &amp;lt;comment&amp;gt;GGR diagram&amp;lt;/comment&amp;gt;&lt;br /&gt;    &amp;lt;comment xml:lang=&amp;quot;it&amp;quot;&amp;gt;Diagramma GGR&amp;lt;/comment&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;sub-class-of type=&amp;quot;application/xml&amp;quot;/&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;magic priority=&amp;quot;80&amp;quot;&amp;gt;&lt;br /&gt;      &amp;lt;match type=&amp;quot;string&amp;quot; offset=&amp;quot;0:100&amp;quot; value=&amp;quot;&amp;amp;lt;ggr:document&amp;quot;/&amp;gt;&lt;br /&gt;    &amp;lt;/magic&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;glob pattern=&amp;quot;*.ggr&amp;quot;/&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;/mime-type&amp;gt;&lt;br /&gt;&amp;lt;/mime-info&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;The new MIME type is specified using the &lt;span style="font-weight:bold;"&gt;mime-type&lt;/span&gt; element, my MIME type is &lt;span style="font-weight:bold;"&gt;application/x-ggr-diagram&lt;/span&gt;, this name is the same of the icon we register above. The naming convention for MIME type is &lt;span style="font-style:italic;"&gt;content type/x-subtype&lt;/span&gt;, I don't find any document about this naming convention but this is the normal practice.&lt;br /&gt;&lt;br /&gt;Using the &lt;span style="font-weight:bold;"&gt;magic &lt;/span&gt;element we can specify the pattern match. I use &lt;span style="font-weight:bold;"&gt;priority &lt;/span&gt;set to 80, the default is 50 but since my MIME type is based on xml, and xml is itself a MIME type, I prefered an higher value. Using the match element we can specify the pattern, I use the root element of the xml generated from ggredit: "&lt;span style="font-weight:bold;"&gt;&amp;lt;ggr:document&lt;/span&gt;". GnomeVFS search on the range 0 to 100 for this string and if found a match then this is the MIME type.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-weight:bold;"&gt;glob &lt;/span&gt;element instead specify the file-name match, I use the ggredit file extension &lt;span style="font-weight:bold;"&gt;*.ggr&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Now we can register the MIME type using:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo xdg-mime install ggredit-mime.xml&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Test on Nautilus&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;Before register the MIME type Nautilus treat ggredit files as xml files.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R7ljcoerVkI/AAAAAAAAARI/XBIhornSDkU/s1600-h/Screenshot-test-mime-Before.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R7ljcoerVkI/AAAAAAAAARI/XBIhornSDkU/s320/Screenshot-test-mime-Before.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5168271390937929282" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;After register the MIME type Nautilus recognize ggredit files by extension and by content.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R7lkaoerVlI/AAAAAAAAARQ/sLf_LD2H52g/s1600-h/Screenshot-test-mime.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R7lkaoerVlI/AAAAAAAAARQ/sLf_LD2H52g/s320/Screenshot-test-mime.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5168272456089818706" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Test on gtkmm&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;We can use the new MIME type on the gtkmm &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/sec-dialogs-filechooserdialog.html"&gt;FileChooserDialog.&lt;/a&gt; We simply need to add a new &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1FileFilter.html"&gt;Gtk::FileFilter&lt;/a&gt; object using the new MIME type.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    Gtk::FileChooserDialog dialog(_(&amp;quot;Choose file&amp;quot;),&lt;br /&gt;        Gtk::FILE_CHOOSER_ACTION_OPEN);&lt;br /&gt;    &lt;br /&gt;    dialog.set_transient_for(*this);&lt;br /&gt;&lt;br /&gt;    //Add response buttons the the dialog:&lt;br /&gt;    dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);&lt;br /&gt;    dialog.add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);&lt;br /&gt;&lt;br /&gt;    //Add filters, so that only certain file types can be selected:&lt;br /&gt;&lt;br /&gt;    Gtk::FileFilter filter_text;&lt;br /&gt;    filter_text.set_name(&amp;quot;GGR Diagram&amp;quot;);&lt;br /&gt;    filter_text.add_mime_type(&amp;quot;application/x-ggr-diagram&amp;quot;);&lt;br /&gt;    dialog.add_filter(filter_text);&lt;br /&gt;&lt;br /&gt;    Gtk::FileFilter filter_any;&lt;br /&gt;    filter_any.set_name(&amp;quot;Any files&amp;quot;);&lt;br /&gt;    filter_any.add_pattern(&amp;quot;*&amp;quot;);&lt;br /&gt;    dialog.add_filter(filter_any);&lt;br /&gt;&lt;br /&gt;    //Show the dialog and wait for a user response:&lt;br /&gt;    int result = dialog.run();&lt;br /&gt;&lt;br /&gt;    //Handle the response:&lt;br /&gt;    switch(result)&lt;br /&gt;    {&lt;br /&gt;        case(Gtk::RESPONSE_OK):&lt;br /&gt;        {&lt;br /&gt;            std::string filename = dialog.get_filename();&lt;br /&gt;            &lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                // Load document...&lt;br /&gt;            }&lt;br /&gt;            catch (std::exception&amp;amp; e)&lt;br /&gt;            {&lt;br /&gt;                std::cerr &amp;lt;&amp;lt; &amp;quot;Exception loading file: &amp;quot; &amp;lt;&amp;lt; e.what() &amp;lt;&amp;lt; std::endl;&lt;br /&gt;            }&lt;br /&gt;            break;&lt;br /&gt;        }&lt;br /&gt;        case(Gtk::RESPONSE_CANCEL):&lt;br /&gt;        {&lt;br /&gt;            break;&lt;br /&gt;        }&lt;br /&gt;        default:&lt;br /&gt;        {&lt;br /&gt;            break;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this way we can display the file chooser dialog for ggredit using the new MIME type as filter.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R7ltlYerVmI/AAAAAAAAARY/eVSEzpZZhVI/s1600-h/Screenshot-test-mime-Choose+file.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R7ltlYerVmI/AAAAAAAAARY/eVSEzpZZhVI/s320/Screenshot-test-mime-Choose+file.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5168282536378062434" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;The future&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;You know GomeVFS will be &lt;a href="http://live.gnome.org/GioPort"&gt;replaced by GVFS&lt;/a&gt; of GIO? But since we use freedesktop guidelines we do not have to warry about this.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;References&lt;/font&gt;&lt;br/&gt;&lt;br /&gt;GNOME Documentation Library - &lt;a href="http://library.gnome.org/admin/system-admin-guide/stable/mimetypes-modifying.html.en"&gt;Modifying MIME types&lt;/a&gt; &lt;br /&gt;Sun Microsystems Documentation - &lt;a href="http://docs.sun.com/app/docs/doc/817-5310/6mkpbn3tu?a=view"&gt;Chapter 4 MIME Types&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-3304771578076997426?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/3304771578076997426/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/02/register-your-own-mime-type-on-free.html#comment-form' title='2 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/3304771578076997426'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/3304771578076997426'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/02/register-your-own-mime-type-on-free.html' title='Register your own MIME type on a free desktop'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_sQJ1m4QDkME/R7mR04erVnI/AAAAAAAAARg/XumueXuEDfs/s72-c/Pantomime-Pablo2.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-5597312655913518407</id><published>2008-02-13T07:27:00.013+01:00</published><updated>2008-12-11T09:44:01.582+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ggredit'/><title type='text'>ggredit MIME icon</title><content type='html'>I have a large number of critical bugs on my &lt;a href="http://sourceforge.net/projects/ggredit/"&gt;ggredit&lt;/a&gt; project...I add the Layer concept on my framework so I need to move all operations from the Page to the new Layer class...I have some unhandled exception that crash the application...the patient's serious risk...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R7KTEoerVbI/AAAAAAAAAQA/3LEJ0TyNPvc/s1600-h/402px-Surgeon_operating,_Fitzsimons_Army_Medical_Center,_circa_1990.JPEG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R7KTEoerVbI/AAAAAAAAAQA/3LEJ0TyNPvc/s320/402px-Surgeon_operating,_Fitzsimons_Army_Medical_Center,_circa_1990.JPEG" border="0" alt=""id="BLOGGER_PHOTO_ID_5166353430342227378" /&gt;&lt;/a&gt;&lt;br /&gt;Ok...good time for draw some icon...the doctor leave the operating room, the patient can wait....&lt;br /&gt;&lt;br /&gt;I think for long time how to express the concept of diagram on 48x48 pixels, is not easy as it seems. For example look &lt;a href="http://uml.sourceforge.net/index.php"&gt;Umbrello&lt;/a&gt; icon:&lt;br /&gt;&lt;table bgcolor="Gainsboro" border = "0" width = "100%"&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R7Kc2IerVeI/AAAAAAAAAQY/Dcq-sJe708U/s1600-h/Umbrello-icon2.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R7Kc2IerVeI/AAAAAAAAAQY/Dcq-sJe708U/s200/Umbrello-icon2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5166364176350402018" /&gt;&lt;/a&gt;[flame begin] How a man can use this icon? For me umbrello is good, but I can not click on this icon, I don't want to touch it! [flame end]&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;And look at &lt;a href="http://live.gnome.org/Dia"&gt;DIA&lt;/a&gt; icon:&lt;br /&gt;&lt;table bgcolor="Gainsboro" border = "0" width = "100%"&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R7KdMoerVfI/AAAAAAAAAQg/T9LEckCj5JA/s1600-h/dia_gnome_icon.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R7KdMoerVfI/AAAAAAAAAQg/T9LEckCj5JA/s200/dia_gnome_icon.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5166364562897458674" /&gt;&lt;/a&gt;[flame begin] Ok you can draw arrow... but this is an improper use! Ok DIA start with D but why use a letter in the icon? [flame end]&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;For my ggredit I want something integrated on the Gnome environment, may be following the &lt;a href="http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines"&gt;tango icon theme guidelines&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;This is the result of my work:&lt;br /&gt;&lt;table bgcolor="Gainsboro" border = "0" width = "100%"&gt;&lt;br /&gt;&lt;tr&gt;&lt;br /&gt;&lt;td&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R7PgV4erViI/AAAAAAAAAQ4/r1UdVIS8Fwc/s1600-h/ggredit-file-type.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R7PgV4erViI/AAAAAAAAAQ4/r1UdVIS8Fwc/s200/ggredit-file-type.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5166719864067020322" /&gt;&lt;/a&gt;Oh yeah baby!&lt;/td&gt;&lt;br /&gt;&lt;/tr&gt;&lt;br /&gt;&lt;/table&gt;&lt;br /&gt;Somebody told me I forget some color...&lt;br /&gt;&lt;br /&gt;The diagram inside the page was drawn using DIA, then I use &lt;a href="http://www.inkscape.org/"&gt;Inkscape&lt;/a&gt; for edit the diagram, finally I create the page and put all together using &lt;a href="http://www.gimp.org/"&gt;Gimp&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Please post some suggestion I don't want to use bad-looking icons!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-5597312655913518407?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/5597312655913518407/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/02/ggredit-mime-icon.html#comment-form' title='4 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5597312655913518407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5597312655913518407'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/02/ggredit-mime-icon.html' title='ggredit MIME icon'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_sQJ1m4QDkME/R7KTEoerVbI/AAAAAAAAAQA/3LEJ0TyNPvc/s72-c/402px-Surgeon_operating,_Fitzsimons_Army_Medical_Center,_circa_1990.JPEG' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-5015102637844686108</id><published>2008-01-31T07:39:00.000+01:00</published><updated>2008-12-11T09:44:02.789+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='cairomm'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Perspective effect using cairo</title><content type='html'>For my graphic editor I would like to use some nice effect for the page selector, something like the Album browser of the &lt;span style="font-style:italic;"&gt;iPod&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R6GwH7PwAgI/AAAAAAAAAPg/PLuPDkwAK44/s1600-h/Page-Leaf-Through.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R6GwH7PwAgI/AAAAAAAAAPg/PLuPDkwAK44/s320/Page-Leaf-Through.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5161600298152624642" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;The perspective&lt;/font&gt;&lt;/br&gt;&lt;br /&gt;For transform the source image and give the 3d effect I find two way:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;use &lt;a href="http://en.wikipedia.org/wiki/Opengl"&gt;OpenGL&lt;/a&gt;, this allow to obtain a better final result, as show on &lt;a href="http://macslow.thepimp.net/?p=152"&gt;MacSlow blog&lt;/a&gt;, but we have to add extra dependencies, and may be is too much only for select a page&lt;/li&gt;&lt;br /&gt;&lt;li&gt;use transformation matrix, the final result has some restriction but we does not need to add extra dependencies&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;For use transformation matrix on &lt;a href="http://cairographics.org/documentation/cairomm/reference/"&gt;cairomm&lt;/a&gt; we have to use the &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html#c520512061fa271fff3b1f922f94c9cb"&gt;transform&lt;/a&gt; method of the &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html"&gt;Cairo::Context&lt;/a&gt; class. We have to provide the transformation matrix, &lt;a href="http://cairographics.org/documentation/cairomm/reference/namespaceCairo.html#c3996d56b5f6dc03d1ea7b030aaa557b"&gt;Cairo::Matrix&lt;/a&gt; is only a new name for the type &lt;a href="http://cairographics.org/documentation/cairomm/reference/namespaceCairo.html#c3996d56b5f6dc03d1ea7b030aaa557b"&gt;cairo_matrix_t&lt;/a&gt;.&lt;br /&gt;I read this page &lt;a href="http://cairographics.org/matrix_transform/"&gt;about matrix transformations&lt;/a&gt; on the cairo documentation, but I don't understand this strange language. After some test I understand that the meanings of the matrix values are:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    Cairo::Matrix matrix_perspective;&lt;br /&gt;    cairo_matrix_init (&amp;amp;matrix_perspective,&lt;br /&gt;        scale_x, rotate_y,&lt;br /&gt;        rotate_x, scale_y,&lt;br /&gt;        translate_x, translate_y);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So for create the perspective effect I use:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Set matrix for perspective&lt;br /&gt;    Cairo::Matrix matrix_perspective;&lt;br /&gt;    cairo_matrix_init (&amp;amp;matrix_perspective,&lt;br /&gt;        0.5, 0.25,&lt;br /&gt;        0.0, 1.0,&lt;br /&gt;        0.0, 0.0);&lt;br /&gt;    context-&amp;gt;transform (matrix_perspective);&lt;br /&gt;    &lt;br /&gt;    // Draw the source image&lt;br /&gt;    context-&amp;gt;set_source (image_surface_ptr_, 0.0, 0.0);&lt;br /&gt;    context-&amp;gt;rectangle (0.0, 0.0, image_ptr_-&amp;gt;get_width(), image_ptr_-&amp;gt;get_height());&lt;br /&gt;    context-&amp;gt;fill();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I use scale on x (0.5) and the rotation only on y (0.25), the result is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R6Hnq7PwAhI/AAAAAAAAAPo/Vm0LXqHdR_M/s1600-h/Screenshot-Page3d-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R6Hnq7PwAhI/AAAAAAAAAPo/Vm0LXqHdR_M/s320/Screenshot-Page3d-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5161661372587573778" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For information about how to draw images on cairo see my &lt;a href="http://kapo-cpp.blogspot.com/2008/01/drawing-pixbuf-to-cairo-context-2.html"&gt;previous post&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;The reflex&lt;/font&gt;&lt;/br&gt;&lt;br /&gt;For draw the reflex effect we have to draw the image with &lt;span style="font-style:italic;"&gt;flip y&lt;/span&gt;. I use this matrix transformation:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Set matrix for reflection&lt;br /&gt;    Cairo::Matrix matrix_reflex;&lt;br /&gt;    cairo_matrix_init (&amp;amp;matrix_reflex,&lt;br /&gt;        0.5, 0.25,&lt;br /&gt;        0.0, -1.0,&lt;br /&gt;        0.0, image_ptr_-&amp;gt;get_height() * 2);    &lt;br /&gt;    context-&amp;gt;transform (matrix_reflex);&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-weight:bold;"&gt;-1.0&lt;/span&gt; value flip y and we need also to translate y because the draw now start from the bottom, I multiply image height for two because the reflex must be drawed on the bottom of the first image. The result is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R6HvkrPwAiI/AAAAAAAAAPw/dlh1rl6R09Y/s1600-h/Page3d-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R6HvkrPwAiI/AAAAAAAAAPw/dlh1rl6R09Y/s320/Page3d-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5161670061306413602" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;But the reflex is to be draw with transparency, for this we have to use the &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html#2ad3ea59afb6bb4fa04d000f5e9c3cf2"&gt;mask&lt;/a&gt; method. This method draw the current source using the alpha channel of a pattern or of a second surface. So if we use mask with a gradient we can reach the reflex effect.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Set matrix for reflection&lt;br /&gt;    Cairo::Matrix matrix_reflex;&lt;br /&gt;    cairo_matrix_init (&amp;amp;matrix_reflex,&lt;br /&gt;        0.5, 0.25,&lt;br /&gt;        0.0, -1.0,&lt;br /&gt;        0.0, image_ptr_-&amp;gt;get_height() * 2);    &lt;br /&gt;    context-&amp;gt;transform (matrix_reflex);&lt;br /&gt;    &lt;br /&gt;    // Prepare mask&lt;br /&gt;    Gdk::Color shadow_color( &amp;quot;black&amp;quot; );&lt;br /&gt;&lt;br /&gt;    Cairo::RefPtr&amp;lt; Cairo::LinearGradient &amp;gt; mask_gradient_ptr = Cairo::LinearGradient::create (&lt;br /&gt;        image_ptr_-&amp;gt;get_width() / 2, image_ptr_-&amp;gt;get_height() / 2, &lt;br /&gt;        image_ptr_-&amp;gt;get_width() / 2, image_ptr_-&amp;gt;get_height());&lt;br /&gt;&lt;br /&gt;    mask_gradient_ptr-&amp;gt;add_color_stop_rgba (0, &lt;br /&gt;            shadow_color.get_red_p(), shadow_color.get_green_p(), shadow_color.get_blue_p(), 0.0);&lt;br /&gt;    &lt;br /&gt;    mask_gradient_ptr-&amp;gt;add_color_stop_rgba (1, &lt;br /&gt;            shadow_color.get_red_p(), shadow_color.get_green_p(), shadow_color.get_blue_p(), 0.5);&lt;br /&gt;&lt;br /&gt;    // Draw the reflex&lt;br /&gt;    context-&amp;gt;set_source (image_surface_ptr_, 0.0, 0.0);&lt;br /&gt;    context-&amp;gt;mask (mask_gradient_ptr);&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I create a LinearGradient (see my &lt;a href="http://kapo-cpp.blogspot.com/2008/01/gradients-in-cairo.html"&gt;previou post on gradients&lt;/a&gt;) with the direction perpendicular to the perspective plane, and with a gradient on the alpha channel from half transparency (0.5) to completely transparent (0.0).&lt;br /&gt;&lt;br /&gt;And the final result is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R6HxI7PwAjI/AAAAAAAAAP4/TLokden-ZGs/s1600-h/Page3d-3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R6HxI7PwAjI/AAAAAAAAAP4/TLokden-ZGs/s320/Page3d-3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5161671783588299314" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then we can add a shadow for complete the effect...later...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-5015102637844686108?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/5015102637844686108/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/perspective-effect-using-cairo.html#comment-form' title='4 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5015102637844686108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/5015102637844686108'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/perspective-effect-using-cairo.html' title='Perspective effect using cairo'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_sQJ1m4QDkME/R6GwH7PwAgI/AAAAAAAAAPg/PLuPDkwAK44/s72-c/Page-Leaf-Through.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-2229364417780751365</id><published>2008-01-30T15:10:00.000+01:00</published><updated>2008-12-11T09:44:03.028+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ggredit'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><title type='text'>GGredit on SourceForge</title><content type='html'>I am very pleased to announce that GGredit (my graphic editor for uml diagrams) is hosted by SourceForge, here is the link to my &lt;a href="http://sourceforge.net/projects/ggredit/"&gt;project page&lt;/a&gt;.&lt;br /&gt;I configure Eclipse for work with the CVS repository on SourceForge, this IDE is very complete.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R6Cr8bPwAfI/AAAAAAAAAPY/VA_fUomoiN0/s1600-h/Eclipse-CVS.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R6Cr8bPwAfI/AAAAAAAAAPY/VA_fUomoiN0/s320/Eclipse-CVS.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5161314227560907250" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;In the project explorer is visible the version and the modified status of each file. We can invoke all CVS commands in a graphical way using the &lt;span style="font-style:italic;"&gt;Team&lt;/span&gt; menu.&lt;br /&gt;&lt;br /&gt;Now I have to complete the first phase of my project, the first implemented diagrams will be the &lt;span style="font-style:italic;"&gt;use case&lt;/span&gt;, the simpler. I will update you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-2229364417780751365?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/2229364417780751365/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/ggredit-on-sourceforge.html#comment-form' title='0 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/2229364417780751365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/2229364417780751365'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/ggredit-on-sourceforge.html' title='GGredit on SourceForge'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_sQJ1m4QDkME/R6Cr8bPwAfI/AAAAAAAAAPY/VA_fUomoiN0/s72-c/Eclipse-CVS.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-7569831653268555577</id><published>2008-01-21T07:49:00.000+01:00</published><updated>2008-12-11T09:44:03.685+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='cairomm'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Draw a Mac-Ball using Cairo</title><content type='html'>On my &lt;a href="http://kapo-cpp.blogspot.com/2008/01/gradients-in-cairo.html"&gt;previous post&lt;/a&gt; I introduce how to use gradients on Cairo. Now I will use gradients and transpacency for create a Macball, with shadow and highlight. For draw the Macball I follow this &lt;a href="http://poing.t35.com/go.php?page=macball"&gt;tutorial for gimp&lt;/a&gt;. The result should be this:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R5RiSooRfFI/AAAAAAAAAO4/3OVyn1BBjt8/s1600-h/Macball.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R5RiSooRfFI/AAAAAAAAAO4/3OVyn1BBjt8/s320/Macball.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5157855545529564242" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Step 1&lt;/font&gt;&lt;/br&gt;&lt;br /&gt;The first step is to create the ball background, drawing an ellipse filled by a vertical linear gradient. For draw an ellipse using cairo we have to use the &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html#aa96080beea581244f0a3838fb7c9ee6"&gt;arc&lt;/a&gt; method, but since this method draw a circle we have to use also the &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html#45543fb03fb740fe4c013492f348e084"&gt;scale&lt;/a&gt; method and change the current transformation matrix for achieve an elliptical arc. For draw an ellipse on a box given by &lt;span style="font-style:italic;"&gt;x, y, width, height&lt;/span&gt; I use:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    context-&amp;gt;save();&lt;br /&gt;&lt;br /&gt;    context-&amp;gt;translate (x + (width / 2.0), y + (height / 2.0));&lt;br /&gt;    context-&amp;gt;scale (width / 2.0, height / 2.0);    &lt;br /&gt;&lt;br /&gt;    context-&amp;gt;arc(0.0, 0.0, 1.0, 0.0, 2 * M_PI);&lt;br /&gt;&lt;br /&gt;    context-&amp;gt;restore&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;The translate is different of the one you can found on cairomm documentation, for me the code on the cairomm documentation does not work properly.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;For create the gradient I use a &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1LinearGradient.html"&gt;LinearGradient&lt;/a&gt; with two different tone of blue.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    double width = x1 - x0;&lt;br /&gt;    double height = y1 - y0;&lt;br /&gt;    &lt;br /&gt;    Gdk::Color bk_start_color( &amp;quot;blue&amp;quot; );&lt;br /&gt;    Gdk::Color bk_end_color( &amp;quot;midnight blue&amp;quot; );&lt;br /&gt;    Gdk::Color dark_shadow_color( &amp;quot;black&amp;quot; );&lt;br /&gt;    Gdk::Color light_color( &amp;quot;white&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    // Store context&lt;br /&gt;    context-&amp;gt;save();&lt;br /&gt;&lt;br /&gt;    // Update transformation matrix for draw an ellipse in the box&lt;br /&gt;    context-&amp;gt;translate (x0 + (width / 2.0), y0 + (height / 2.0));&lt;br /&gt;    context-&amp;gt;scale (width / 2.0, height / 2.0);&lt;br /&gt;    &lt;br /&gt;    // Ball background&lt;br /&gt;    Cairo::RefPtr&amp;lt; Cairo::LinearGradient &amp;gt; bk_gradient_ptr = Cairo::LinearGradient::create (&lt;br /&gt;        0.0, -1.0, 0.0, 1.0);&lt;br /&gt;&lt;br /&gt;    bk_gradient_ptr-&amp;gt;add_color_stop_rgb (0, &lt;br /&gt;            bk_start_color.get_red_p(), bk_start_color.get_green_p(), bk_start_color.get_blue_p());&lt;br /&gt;    &lt;br /&gt;    bk_gradient_ptr-&amp;gt;add_color_stop_rgb (1, &lt;br /&gt;            bk_end_color.get_red_p(), bk_end_color.get_green_p(), bk_end_color.get_blue_p());&lt;br /&gt;            &lt;br /&gt;    context-&amp;gt;set_source (bk_gradient_ptr);&lt;br /&gt;    context-&amp;gt;arc(0.0, 0.0, 1.0, 0.0, 2 * M_PI);&lt;br /&gt;    context-&amp;gt;fill();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And the result is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R5WYYYoRfGI/AAAAAAAAAPA/borUUvSNey4/s1600-h/Macball-Step1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R5WYYYoRfGI/AAAAAAAAAPA/borUUvSNey4/s320/Macball-Step1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5158196492918422626" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Step 2&lt;/font&gt;&lt;/br&gt;&lt;br /&gt;Now we can draw the shadow. The shadow must make dark the border. I use a &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1RadialGradient.html"&gt;RadialGradient&lt;/a&gt; with black color and the gradient on alpha value (from 60% to 100% of transparency).&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Dark shadow&lt;br /&gt;    Cairo::RefPtr&amp;lt; Cairo::RadialGradient &amp;gt; shadow_gradient_ptr = Cairo::RadialGradient::create (&lt;br /&gt;            0.0, 0.0, .6,  0.0, 0.0, 1.0);    &lt;br /&gt;    &lt;br /&gt;    shadow_gradient_ptr-&amp;gt;add_color_stop_rgba (0, &lt;br /&gt;            dark_shadow_color.get_red_p(), dark_shadow_color.get_green_p(), dark_shadow_color.get_blue_p(), 0);&lt;br /&gt;    &lt;br /&gt;    shadow_gradient_ptr-&amp;gt;add_color_stop_rgba (1, &lt;br /&gt;            dark_shadow_color.get_red_p(), dark_shadow_color.get_green_p(), dark_shadow_color.get_blue_p(), .5);&lt;br /&gt;            &lt;br /&gt;    context-&amp;gt;set_source (shadow_gradient_ptr);&lt;br /&gt;    &lt;br /&gt;    context-&amp;gt;arc (0.0, 0.0, 1.0, 0.0, 2 * M_PI);&lt;br /&gt;    &lt;br /&gt;    context-&amp;gt;fill();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And the result is:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R5WgcooRfHI/AAAAAAAAAPI/hGAhvmJ9TqA/s1600-h/Macball-Step2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R5WgcooRfHI/AAAAAAAAAPI/hGAhvmJ9TqA/s320/Macball-Step2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5158205362025888882" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Step 3&lt;/font&gt;&lt;/br&gt;&lt;br /&gt;Finally we have to draw the reflex. The reflex is a smaller ellipse inside the ball with a linear gradient of white, always using transparency. I use a gradient with three color_stop (using &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Gradient.html#688da07943fa37f8ccbe33c379544d9f"&gt;add_color_stop_rgba&lt;/a&gt;) because the first part (20%) must be strong-white, the second part instead fade to transparent.&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Light&lt;br /&gt;    context-&amp;gt;save();&lt;br /&gt;    context-&amp;gt;translate (0.0, -0.4);&lt;br /&gt;    context-&amp;gt;scale (0.6, 0.4);&lt;br /&gt;    &lt;br /&gt;    Cairo::RefPtr&amp;lt; Cairo::LinearGradient &amp;gt; light_gradient_ptr = Cairo::LinearGradient::create (&lt;br /&gt;        0.0, -1, 0.0, 0.5);&lt;br /&gt;    &lt;br /&gt;    light_gradient_ptr-&amp;gt;add_color_stop_rgba (0, &lt;br /&gt;            light_color.get_red_p(), light_color.get_green_p(), light_color.get_blue_p(), 0.9);&lt;br /&gt;&lt;br /&gt;    light_gradient_ptr-&amp;gt;add_color_stop_rgba (0.2, &lt;br /&gt;            light_color.get_red_p(), light_color.get_green_p(), light_color.get_blue_p(), 0.4);&lt;br /&gt;    &lt;br /&gt;    light_gradient_ptr-&amp;gt;add_color_stop_rgba (1, &lt;br /&gt;            light_color.get_red_p(), light_color.get_green_p(), light_color.get_blue_p(), 0.0);&lt;br /&gt;            &lt;br /&gt;    context-&amp;gt;set_source (light_gradient_ptr);&lt;br /&gt;    &lt;br /&gt;    context-&amp;gt;arc(0.0, 0.0, 1.0, 0.0, 2 * M_PI);&lt;br /&gt;    &lt;br /&gt;    context-&amp;gt;fill();&lt;br /&gt;&lt;br /&gt;    context-&amp;gt;restore();&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And this is the final result:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R5XEnIoRfII/AAAAAAAAAPQ/hANXdE0N3ZY/s1600-h/Macball-Step3.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R5XEnIoRfII/AAAAAAAAAPQ/hANXdE0N3ZY/s320/Macball-Step3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5158245124833115266" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is not exactly the result of the Gimp tutorial but is, for me, a good demonstration of Cairo capability.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #e2ebf8;font-size: 12px;border: 1px;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;You can download the complete Eclipse project with sources &lt;a href="http://www.box.net/shared/b65son7msw"&gt;here&lt;/a&gt;.&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-7569831653268555577?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/7569831653268555577/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/draw-mac-ball-using-cairo.html#comment-form' title='3 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7569831653268555577'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/7569831653268555577'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/draw-mac-ball-using-cairo.html' title='Draw a Mac-Ball using Cairo'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_sQJ1m4QDkME/R5RiSooRfFI/AAAAAAAAAO4/3OVyn1BBjt8/s72-c/Macball.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-591831524547602059</id><published>2008-01-16T08:44:00.000+01:00</published><updated>2008-12-11T09:44:04.011+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='cairomm'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Gradients in cairo</title><content type='html'>Ok the Web 2.0 force us to use different tone of colors for reach a good looking application. So we have to use &lt;a href="http://en.wikipedia.org/wiki/Gradient"&gt;gradients&lt;/a&gt; evrywere.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4795ooRfEI/AAAAAAAAAOw/r_oiEtQOahY/s1600-h/Cairo_by_night_3.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4795ooRfEI/AAAAAAAAAOw/r_oiEtQOahY/s320/Cairo_by_night_3.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5156337789986503746" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The base class for use gradients in cairomm is &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Gradient.html"&gt;Cairo::Gradient&lt;/a&gt;, but we do not need to use this cas directly, instead we have to use the inherited classes &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1LinearGradient.html"&gt;Cairo::LinearGradient&lt;/a&gt; and &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1RadialGradient.html"&gt;Cairo::RadialGradient&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;For create a LinearGradient object we need to use the static method &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1LinearGradient.html#da4b398d3c60dec6f650e940b2117f71"&gt;create&lt;/a&gt;, and we have to pass the points x0, y0 and x1, y1 that define the linear gradient orientation.&lt;br /&gt;&lt;br /&gt;Next we have to define the start color and the end color for gradient, we can accomplish this task using the &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Gradient.html#fe5e5167dd48fc684c7e88ea07340a6c"&gt;add_color_stop_rgb&lt;/a&gt; (or the variant &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Gradient.html#688da07943fa37f8ccbe33c379544d9f"&gt;add_color_stop_rgba&lt;/a&gt; for transparent colors) method. Surprise...we can define a gradient with more than two colors...oh I like Cairo. In fact when we call the add_color_stop_rgb we have to pass an offset value, 0 is the start of the linear gradient, 1 is the end of the linear gradient, a double value from 0 to 1 is a percent position in the linear gradient (in example 0.5 is in the middle).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R43pAooRfDI/AAAAAAAAAOo/PeJg46IU0us/s1600-h/linear_gradient.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R43pAooRfDI/AAAAAAAAAOo/PeJg46IU0us/s320/linear_gradient.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5156033345524694066" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Finally we have to assign the gradient to the &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html"&gt;Cairo::Context&lt;/a&gt; (using &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html#534d571d5aa4b500782036202a3e2aea"&gt;set_source&lt;/a&gt;) and use it to fill a path.&lt;br /&gt;&lt;br /&gt;This example draw a rectangle filled with a diagonal gradient (I put this code on the on_expose_event, read &lt;a href="http://kapo-cpp.blogspot.com/2008/01/drawing-pixbuf-to-cairo-context-2.html"&gt;this post&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;    // Create the context for the widget&lt;br /&gt;    Cairo::RefPtr&amp;lt;Cairo::Context&amp;gt; context = get_window()-&amp;gt;create_cairo_context();&lt;br /&gt;&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    // Rectangle&lt;br /&gt;    double x0 = 0.0;&lt;br /&gt;    double y0 = 0.0;&lt;br /&gt;    double x1 = 100.0;&lt;br /&gt;    double y1 = 100.0;&lt;br /&gt;&lt;br /&gt;    // Colors&lt;br /&gt;    Gdk::Color start_color( &amp;quot;blue&amp;quot; );&lt;br /&gt;    Gdk::Color end_color( &amp;quot;midnight blue&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    // Create the linear gradient diagonal&lt;br /&gt;    Cairo::RefPtr&amp;lt; Cairo::LinearGradient &amp;gt; background_gradient_ptr = Cairo::LinearGradient::create (&lt;br /&gt;        x0, y0, x1, y1);&lt;br /&gt;    &lt;br /&gt;    // Set grandient colors&lt;br /&gt;    background_gradient_ptr-&amp;gt;add_color_stop_rgb (0, &lt;br /&gt;            start_color.get_red_p(), start_color.get_green_p(), start_color.get_blue_p());&lt;br /&gt;    &lt;br /&gt;    background_gradient_ptr-&amp;gt;add_color_stop_rgb (1, &lt;br /&gt;            end_color.get_red_p(), end_color.get_green_p(), end_color.get_blue_p());&lt;br /&gt;&lt;br /&gt;    // Draw a rectangle and fill with gradient&lt;br /&gt;    context-&amp;gt;set_source (background_gradient_ptr);&lt;br /&gt;    &lt;br /&gt;    context-&amp;gt;rectangle (x0, y0, x1, y1);&lt;br /&gt;    &lt;br /&gt;    context-&amp;gt;fill();&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can use also use transparent colors, and the result can be gorgeous. The use of transparent colors is perfect for draw shadow.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-591831524547602059?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/591831524547602059/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/gradients-in-cairo.html#comment-form' title='4 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/591831524547602059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/591831524547602059'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/gradients-in-cairo.html' title='Gradients in cairo'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_sQJ1m4QDkME/R4795ooRfEI/AAAAAAAAAOw/r_oiEtQOahY/s72-c/Cairo_by_night_3.jpg' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-6904996131366280319</id><published>2008-01-15T08:47:00.000+01:00</published><updated>2008-12-11T09:44:05.967+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='doxygen'/><title type='text'>Documenting the code (using Doxygen)</title><content type='html'>During an application development writing documentation is a tedious work. In effect when you are writing the code all is clear, at this moment the code seems to document itself. But time pass, and one day you open an ancient project, look the code, ant the self documenting code now is cripted.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4xa8YoRe5I/AAAAAAAAANY/WhqTU_3Tlg0/s1600-h/Manoscritto.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4xa8YoRe5I/AAAAAAAAANY/WhqTU_3Tlg0/s320/Manoscritto.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5155595666882395026" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For documenting the code I use &lt;a href="http://www.stack.nl/%7Edimitri/doxygen/"&gt;doxygen&lt;/a&gt;. Using this tool I am forced to write good documentation, and "at the same price" I can get documentation in HTML format.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Writing comments&lt;/font&gt;&lt;/br&gt;&lt;br /&gt;&lt;br /&gt;For documenting the code just need to use the correct syntax in the comment block, like:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;font style="color: rgb(0, 102, 0);" face="courier new"&gt;/**&lt;br /&gt; * This is the documentation&lt;br /&gt; */&lt;/font&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you use &lt;font style="font-style: italic;"&gt;Eclipse &lt;/font&gt;with &lt;font style="font-style: italic;"&gt;CDT  &lt;/font&gt;the editor  recognize you  are writing documentation after the first "&lt;font style="font-weight: bold;"&gt;/**&lt;/font&gt;" line and  automatically  add "&lt;font style="font-weight: bold;"&gt;*&lt;/font&gt;" when you add a new line...nice.&lt;br /&gt;&lt;br /&gt;Usually the documentation of a class member can include:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;font style="color: rgb(0, 102, 0);" face="courier new"&gt;/**&lt;br /&gt; * @brief One line documentation &lt;br /&gt; *&lt;br /&gt; * A more detailed documentation&lt;br /&gt; *&lt;br /&gt; * @param arg1 the first function argument&lt;br /&gt; * @param arg2 the second function argument&lt;br /&gt; *&lt;br /&gt; * @return descrition for the function return value&lt;br /&gt; */&lt;/font&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Word preceded by "&lt;font style="font-weight: bold;"&gt;@&lt;/font&gt;" are command interpreted by doxygen (in effect doxygen can understand different syntax, but I prefer this).&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;font style="font-weight: bold;"&gt;@brief&lt;/font&gt; is the one line documentation, this is visible in the summary&lt;/li&gt;&lt;li&gt;after one blank line you can type the detailed function description&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;font style="font-weight: bold;"&gt;@param&lt;/font&gt; are the function arguments. After param you must specify the parameter name and then the descpription&lt;/li&gt;&lt;li&gt;&lt;font style="font-weight: bold;"&gt;@return&lt;/font&gt; is the description of the return value&lt;/li&gt;&lt;/ul&gt;So if you simply precede your function declaration with this comment block you can obtain the HTML documentation. The same syntax may be applied to class and namespace, doxygen look at the code and recognize what you want to document.&lt;br /&gt;&lt;br /&gt;We can use this syntax for documenting namespaces, classes or methods, just put this comment before the declarations.&lt;br /&gt;&lt;br /&gt;For a more detailed description look at the Doxygen &lt;a href="http://www.stack.nl/%7Edimitri/doxygen/docblocks.html"&gt;manual&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Grouping&lt;/font&gt;&lt;/br&gt;&lt;br /&gt;&lt;br /&gt;I use also the grouping function when declaring a set of signals, in this way the HTML output display a separated "Signals" chapter. A group start with the &lt;span style="font-weight:bold;"&gt;/*\@{*/&lt;/span&gt; comment and end with &lt;span style="font-weight:bold;"&gt;/*\@}*/&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;font style="color: rgb(0, 102, 0);" face="courier new"&gt;/** Signals */&lt;br /&gt;/*\@{*/&lt;br /&gt;&lt;font style="color: rgb(32, 64, 160);"&gt;signal_update_cursor_t&lt;/font&gt; &lt;font style="color: rgb(32, 64, 160);"&gt;signalUpdateCursor&lt;/font&gt;&lt;font style="color: rgb(68, 68, 255);"&gt;(&lt;/font&gt;&lt;font style="color: rgb(68, 68, 255);"&gt;);&lt;br /&gt;&lt;/font&gt;&lt;font face="courier new" style="color: rgb(0, 102, 0);"&gt;/*\@}*/&lt;/font&gt;&lt;/font&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;See also&lt;/font&gt;&lt;/br&gt;&lt;br /&gt;&lt;br /&gt;If we want to put a link to a different class or method (or a generic url) we have to use the &lt;span style="font-weight:bold;"&gt;@see&lt;/span&gt; tag.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;&lt;font style="color: rgb(0, 102, 0);" face="courier new"&gt;/* @see MyClass::myMethod&lt;br /&gt;/* @see http://kapo-cpp.blogspot.com/&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this way doxygen add a "see also" section containing the links.&lt;br /&gt;&lt;br /&gt;&lt;font style="font-weight: bold; color: rgb(51, 51, 255);" size="4"&gt;Generate HTML documentation&lt;/font&gt;&lt;br /&gt;For generate the HTML documentation I use &lt;a href="http://www.stack.nl/%7Edimitri/doxygen/doxywizard_usage.html"&gt;doxywizard&lt;/a&gt;, a gui for easily run doxygen, unfortunately developped using &lt;font style="font-style: italic;"&gt;QT&lt;/font&gt; libraries.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R4xjn4oRe6I/AAAAAAAAANg/ucb1tN2Hmmg/s1600-h/Doxygen-01.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R4xjn4oRe6I/AAAAAAAAANg/ucb1tN2Hmmg/s320/Doxygen-01.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155605210299726754" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This application help us to write the &lt;a href="http://www.stack.nl/~dimitri/doxygen/config.html"&gt;Doxyfile&lt;/a&gt;, this is the configuration file for doxygen.&lt;br /&gt;&lt;br /&gt;In the &lt;span style="font-weight:bold;"&gt;Step 1&lt;/span&gt; click on &lt;span style="font-weight:bold;"&gt;Wizard&lt;/span&gt; button, and a new dialog was displayed. On the first tab &lt;span style="font-weight:bold;"&gt;Project&lt;/span&gt; we have to write:&lt;br /&gt;&lt;br /&gt;&lt;UL&gt;&lt;br /&gt;&lt;LI&gt;the project name&lt;br /&gt;&lt;LI&gt;the project version&lt;br /&gt;&lt;LI&gt;the directory containing the project source code (ensure to select "scan recursively")&lt;br /&gt;&lt;LI&gt;the output directory, where doxygen put generated files&lt;br /&gt;&lt;/UL&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R4xmU4oRe7I/AAAAAAAAANo/2rMiDPsXr_4/s1600-h/Doxygen-02.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R4xmU4oRe7I/AAAAAAAAANo/2rMiDPsXr_4/s320/Doxygen-02.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155608182417095602" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On the tab &lt;span style="font-weight:bold;"&gt;Mode&lt;/span&gt; I usually do not change nothing.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R4xm_4oRe8I/AAAAAAAAANw/daH0VxzZLmU/s1600-h/Doxygen-03.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R4xm_4oRe8I/AAAAAAAAANw/daH0VxzZLmU/s320/Doxygen-03.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155608921151470530" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On the tab &lt;span style="font-weight:bold;"&gt;Output&lt;/span&gt; we can select wich kind of documentation to generate. By default HTML and LaTeX are selected, but we can remove LaTeX generation.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R4xn5ooRe9I/AAAAAAAAAN4/GYr1_kmnMvI/s1600-h/Doxygen-04.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R4xn5ooRe9I/AAAAAAAAAN4/GYr1_kmnMvI/s320/Doxygen-04.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155609913288915922" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On the tab diagrams we can choos if we want diagrams in the documentation. For use this option we need the package &lt;span style="font-weight:bold;"&gt;GraphViz &lt;/span&gt;installed.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4xoaYoRe-I/AAAAAAAAAOA/ZsGaaYocumQ/s1600-h/Doxygen-05.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4xoaYoRe-I/AAAAAAAAAOA/ZsGaaYocumQ/s320/Doxygen-05.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155610475929631714" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now we can click &lt;span style="font-weight:bold;"&gt;Ok&lt;/span&gt; button. And then we can &lt;span style="font-weight:bold;"&gt;Step 2&lt;/span&gt; save the Doxyfile, click on &lt;span style="font-weight:bold;"&gt;Save&lt;/span&gt; button. I usually save the Doxyfile on the same directory of the Output.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R4xppooRe_I/AAAAAAAAAOI/iMUG9Sc-4u0/s1600-h/Doxygen-06.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R4xppooRe_I/AAAAAAAAAOI/iMUG9Sc-4u0/s320/Doxygen-06.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155611837434264562" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This file can be used for all next times we have to run doxygen for this project. So nect time we can select &lt;span style="font-weight:bold;"&gt;Load &lt;/span&gt;on the &lt;span style="font-weight:bold;"&gt;Step 1&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;At last we must set the directory from wich to run doxygen, you can select any directory, usually I use the same directory containing the source.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R4xvHooRfAI/AAAAAAAAAOQ/3j4xtZicMcw/s1600-h/Doxygen-07.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R4xvHooRfAI/AAAAAAAAAOQ/3j4xtZicMcw/s320/Doxygen-07.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155617850388478978" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We need to select this directory also after load an existing Doxyfile.&lt;br /&gt;&lt;br /&gt;And now we can run doxygen, click the &lt;span style="font-weight:bold;"&gt;Start&lt;/span&gt; button.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R4xvsooRfBI/AAAAAAAAAOY/1NMlvAVL-Lw/s1600-h/Doxygen-08.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R4xvsooRfBI/AAAAAAAAAOY/1NMlvAVL-Lw/s320/Doxygen-08.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155618486043638802" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On the output directory we find the &lt;span style="font-weight:bold;"&gt;html&lt;/span&gt; directory. We can open the &lt;span style="font-weight:bold;"&gt;index.html&lt;/span&gt; using firefox for read the documentation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-6904996131366280319?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/6904996131366280319/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2007/10/documenting-code-using-doxygen.html#comment-form' title='5 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/6904996131366280319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/6904996131366280319'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2007/10/documenting-code-using-doxygen.html' title='Documenting the code (using Doxygen)'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/R4xa8YoRe5I/AAAAAAAAANY/WhqTU_3Tlg0/s72-c/Manoscritto.jpg' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-3644169101508648148</id><published>2008-01-11T09:51:00.000+01:00</published><updated>2008-12-11T09:44:09.065+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Using Eclipse for your gtkmm project (new version)</title><content type='html'>On this blog I already write about this topic, first &lt;a href="http://kapo-cpp.blogspot.com/2007/02/gtkmm-and-eclipse.html"&gt;here&lt;/a&gt; and then &lt;a href="http://kapo-cpp.blogspot.com/2007/12/let-eclipsecdt-autocomplete-your-gtkmm.html"&gt;here&lt;/a&gt;. So why I write the same post once again? Cause I prefer to put togheter this two post and provide some tips (and the CDT current version is different of the previous one).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:130%;" &gt;Install Eclipse with CDT&lt;/span&gt;&lt;/br&gt;&lt;br /&gt;First of all install the Sun Java, on Ubuntu 7.10 simply install the package &lt;span style="font-style:italic;"&gt;sun-java6-jre&lt;/span&gt; using Synaptic. The default Java (gcj) is too slow and when you hit ctrl+space for invoke autocompletition you risk to  fall asleep.&lt;br /&gt;Download Eclipse from the &lt;a href="http://www.eclipse.org/downloads/"&gt;Eclipse site&lt;/a&gt; is better than use the Eclipse version of the official Ubuntu repositories (the repository version is not updated). From the Eclipse site you can download the package for C++ developers, this already include CDT.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4sHqooReyI/AAAAAAAAAMg/_BTlbimSHT8/s1600-h/Firefox-Download-Eclipse-Hi.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4sHqooReyI/AAAAAAAAAMg/_BTlbimSHT8/s320/Firefox-Download-Eclipse-Hi.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5155222627497900834" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now we have the tar.gz archive. For install Eclipse I follow this &lt;a href="http://flurdy.com/docs/eclipse/install.html"&gt;howto&lt;/a&gt; (only the section Eclipse). First extract and move to opt directory:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;tar xzf eclipse-cpp-europa-fall2-linux-gtk.tar.gz&lt;br /&gt;sudo mv eclipse /opt/eclipse&lt;br /&gt;cd /opt/&lt;br /&gt;sudo chown -R root:root eclipse&lt;br /&gt;sudo chmod -R +r eclipse&lt;br /&gt;sudo chmod +x `sudo find eclipse -type d`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Create the executable on the bin directory:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo touch /usr/bin/eclipse&lt;br /&gt;sudo chmod 755 /usr/bin/eclipse&lt;br /&gt;sudo gedit /usr/bin/eclipse &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and paste this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#!/bin/sh&lt;br /&gt;#export MOZILLA_FIVE_HOME=&amp;quot;/usr/lib/mozilla/&amp;quot;&lt;br /&gt;export ECLIPSE_HOME=&amp;quot;/opt/eclipse&amp;quot;&lt;br /&gt;&lt;br /&gt;$ECLIPSE_HOME/eclipse $*&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Finally create the gnome menu item:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;sudo gedit /usr/share/applications/eclipse.desktop&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and paste this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;[Desktop Entry]&lt;br /&gt;Encoding=UTF-8&lt;br /&gt;Name=Eclipse&lt;br /&gt;Comment=Eclipse IDE&lt;br /&gt;Exec=eclipse&lt;br /&gt;Icon=/opt/eclipse/icon.xpm&lt;br /&gt;Terminal=false&lt;br /&gt;Type=Application&lt;br /&gt;Categories=GNOME;Application;Development;&lt;br /&gt;StartupNotify=true&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we can run Eclipse from the Gnome menu.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:130%;" &gt;Create the gtkmm project&lt;/span&gt;&lt;/br&gt;&lt;br /&gt;Create a new C++ project using the menu option &lt;span style="font-weight:bold;"&gt;File-&gt;New-&gt;C++ Project&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4eMlYoRerI/AAAAAAAAALo/mKJ8jbexXhc/s1600-h/Eclipse-Project-01.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4eMlYoRerI/AAAAAAAAALo/mKJ8jbexXhc/s320/Eclipse-Project-01.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5154242872443239090" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On the dialog we need to enter a project name(GtkmmDemo), and the project type (Executable-&gt;Hello World C++ Project).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4eNnooResI/AAAAAAAAALw/mocuNW9F0-A/s1600-h/Eclipse-Project-02.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4eNnooResI/AAAAAAAAALw/mocuNW9F0-A/s320/Eclipse-Project-02.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5154244010609572546" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Click Next button and set template arguments: author, copyright, ...&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R4eOAIoRetI/AAAAAAAAAL4/krpO3RfZof4/s1600-h/Eclipse-Project-03.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R4eOAIoRetI/AAAAAAAAAL4/krpO3RfZof4/s320/Eclipse-Project-03.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5154244431516367570" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Click Next button, we can manage project configurations, but for now we do not change anything.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_sQJ1m4QDkME/R4eUJ4oReuI/AAAAAAAAAMA/d4lfkF6My-E/s1600-h/Eclipse-Project-04.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_sQJ1m4QDkME/R4eUJ4oReuI/AAAAAAAAAMA/d4lfkF6My-E/s320/Eclipse-Project-04.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5154251196089858786" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Finally we can click finish. Now we have a new C++ project. On the &lt;span style="font-style:italic;"&gt;src&lt;/span&gt; directory there is a file with the same name of the project and the code for display the "Hello World" string.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4eU_YoRevI/AAAAAAAAAMI/OlY9JDrB2rM/s1600-h/Eclipse-Project-05-Main.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4eU_YoRevI/AAAAAAAAAMI/OlY9JDrB2rM/s320/Eclipse-Project-05-Main.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5154252115212860146" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:130%;" &gt;Configure builder&lt;/span&gt;&lt;/br&gt;&lt;br /&gt;&lt;br /&gt;First replace the Hello World code with the gtkmm code:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#include &amp;lt;gtkmm.h&amp;gt;&lt;br /&gt;#include &amp;lt;iostream&amp;gt;&lt;br /&gt;&lt;br /&gt;void button_clicked()&lt;br /&gt;{&lt;br /&gt;    std::cout &amp;lt;&amp;lt; &amp;quot;Hello World!&amp;quot; &amp;lt;&amp;lt; std::endl;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(int argc, char *argv[])&lt;br /&gt;{&lt;br /&gt;    Gtk::Main kit(argc, argv);&lt;br /&gt;    &lt;br /&gt;    Gtk::Window main_window;&lt;br /&gt;    &lt;br /&gt;    Gtk::Button button( &amp;quot;Click here&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    main_window.set_title( &amp;quot;Eclipse/GTKmm Demo&amp;quot; );&lt;br /&gt;    &lt;br /&gt;    main_window.set_border_width( 4 );&lt;br /&gt;    main_window.set_default_size( 200, 50 );&lt;br /&gt;    &lt;br /&gt;    main_window.add( button );&lt;br /&gt;    button.show();&lt;br /&gt;    &lt;br /&gt;    button.signal_clicked().connect( sigc::ptr_fun(button_clicked) );&lt;br /&gt;    &lt;br /&gt;    Gtk::Main::run( main_window );&lt;br /&gt;    &lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Save the file (&lt;span style="font-style:italic;"&gt;ctrl+S&lt;/span&gt;) and build (&lt;span style="font-style:italic;"&gt;ctrl+B&lt;/span&gt;), if the &lt;span style="font-weight:bold;"&gt;Project-&gt;Build Automatically&lt;/span&gt; menu option is enabled the build start automatically after save, but since I save often I prefer to work with this option turned off.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4eXjYoRewI/AAAAAAAAAMQ/ztGyrklh3oI/s1600-h/Eclipse-Project-06.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4eXjYoRewI/AAAAAAAAAMQ/ztGyrklh3oI/s320/Eclipse-Project-06.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5154254932711406338" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When build is complete we get many many errors, we need to configure the builder. On my previous post I use &lt;span style="font-style:italic;"&gt;pkg-config&lt;/span&gt; for configure include directories and linker libraries, but for use all Eclipse functions is better to add manually all include directories. Type &lt;span style="font-weight:bold;"&gt;pkg-config --cflags gtkmm-2.4&lt;/span&gt; on a terminal.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4eZSYoRexI/AAAAAAAAAMY/hQuyGKxlzsU/s1600-h/Terminal-PkgConfig-CFlags.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4eZSYoRexI/AAAAAAAAAMY/hQuyGKxlzsU/s320/Terminal-PkgConfig-CFlags.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5154256839676885778" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We have to add all this directories. On Eclipse select the &lt;span style="font-weight:bold;"&gt;Project-&gt;Properties&lt;/span&gt; menu option. Select &lt;span style="font-weight:bold;"&gt;C/C++ Build-&gt;Settings&lt;/span&gt; property page and &lt;span style="font-weight:bold;"&gt;GNU C++ Compiler-&gt;Directories&lt;/span&gt; from the &lt;span style="font-weight:bold;"&gt;Tool Settings&lt;/span&gt; tab. Now we have to add all directories.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4sOFYoRezI/AAAAAAAAAMo/zltsLt72MEE/s1600-h/Eclipse-Compiler-Settings-02.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4sOFYoRezI/AAAAAAAAAMo/zltsLt72MEE/s320/Eclipse-Compiler-Settings-02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5155229684129168178" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This is a tedious work but is the better way to use Eclipse.&lt;br /&gt;&lt;br /&gt;When we finish to add all directories we have to configure the linker, for this we can use pkg-config. Select &lt;span style="font-weight:bold;"&gt;GCC C++ Linker-&gt;Miscellaneus&lt;/span&gt; in the &lt;span style="font-weight:bold;"&gt;Linker flags&lt;/span&gt; field type:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;`pkg-config --libs gtkmm-2.4`&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4sRgooRe0I/AAAAAAAAAMw/yBjVcblbW30/s1600-h/Eclipse-Linker-Settings-02.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4sRgooRe0I/AAAAAAAAAMw/yBjVcblbW30/s320/Eclipse-Linker-Settings-02.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5155233450815486786" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now we can click &lt;span style="font-weight:bold;"&gt;Ok&lt;/span&gt; and close the dialog. Now we can build the project (&lt;span style="font-style:italic;"&gt;ctrl+B&lt;/span&gt;) without errors. So we can run the application &lt;span style="font-style:italic;"&gt;ctrl+F11&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4sSuooRe1I/AAAAAAAAAM4/bVGRf-E-HK0/s1600-h/GTKmm-Demo-Running.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4sSuooRe1I/AAAAAAAAAM4/bVGRf-E-HK0/s320/GTKmm-Demo-Running.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155234790845283154" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:130%;" &gt;CDT in action&lt;/span&gt;&lt;/br&gt;&lt;br /&gt;&lt;br /&gt;Now we can build our gtkmm application, but we can also explore CDT features. First we have to rebuild index. On the &lt;span style="font-weight:bold;"&gt;Project explorer&lt;/span&gt; right-click on the project and select &lt;span style="font-weight:bold;"&gt;Index-&gt;Rebuild&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4sUYYoRe2I/AAAAAAAAANA/2-6-sHDRbhg/s1600-h/Eclipse-Rebuild-Index.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/_sQJ1m4QDkME/R4sUYYoRe2I/AAAAAAAAANA/2-6-sHDRbhg/s320/Eclipse-Rebuild-Index.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155236607616449378" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When Eclipse finish to rebuild index we can se our code change color. If we move on a gtkmm class definition a tooltip was displayed, the tooltip display the class definition and the class documentation.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R4sVxIoRe3I/AAAAAAAAANI/vX-bxXVyo8k/s1600-h/New-Eclipse-Tooltip.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_sQJ1m4QDkME/R4sVxIoRe3I/AAAAAAAAANI/vX-bxXVyo8k/s320/New-Eclipse-Tooltip.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155238132329839474" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We can also use autocompletition pressing &lt;span style="font-style:italic;"&gt;ctrl+space&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4seUooRe4I/AAAAAAAAANQ/R1TPwMf910s/s1600-h/New-Eclipse-Autocomplete.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R4seUooRe4I/AAAAAAAAANQ/R1TPwMf910s/s320/New-Eclipse-Autocomplete.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5155247538308217730" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:130%;" &gt;The future&lt;/span&gt;&lt;/br&gt;&lt;br /&gt;&lt;br /&gt;I am waiting the &lt;a href="http://wiki.eclipse.org/CDT/planning/5.0"&gt;CDT 5.0&lt;/a&gt; for the &lt;a href="http://sourceware.org/eclipse/autotools/"&gt;autotools integration&lt;/a&gt;, now this is a plugin (on top of CDT) developed by Jeff Johnston, and the &lt;a href="http://r2.ifs.hsr.ch/cdtrefactoring"&gt;refactoring&lt;/a&gt; plugin, that give more options compared to the default (only rename).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-3644169101508648148?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/3644169101508648148/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/using-eclipse-for-your-gtkmm-project.html#comment-form' title='43 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/3644169101508648148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/3644169101508648148'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/using-eclipse-for-your-gtkmm-project.html' title='Using Eclipse for your gtkmm project (new version)'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/R4sHqooReyI/AAAAAAAAAMg/_BTlbimSHT8/s72-c/Firefox-Download-Eclipse-Hi.jpg' height='72' width='72'/><thr:total>43</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-6846681828296818544</id><published>2008-01-03T08:01:00.000+01:00</published><updated>2008-12-11T09:44:09.625+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><category scheme='http://www.blogger.com/atom/ns#' term='cairomm'/><category scheme='http://www.blogger.com/atom/ns#' term='gtkmm'/><title type='text'>Drawing pixbuf to Cairo context (2)</title><content type='html'>On my &lt;a href="http://kapo-cpp.blogspot.com/2007/11/drawing-images-to-cairo-context.html"&gt;previous post&lt;/a&gt; a told about how to render a &lt;a href="http://en.wikipedia.org/wiki/Portable_Network_Graphics"&gt;png&lt;/a&gt; image file to a Cairo context. But allow the user to select only png image file on my GraphicEditor is a very big restriction and does not satisfy me.&lt;br /&gt;The problem is the integration of Cairo on Gtk+, how say this &lt;a href="http://live.gnome.org/GtkCairoIntegration"&gt;page&lt;/a&gt; on live.gnome. But on this page there is also the Python pizza-code for render pixbuf to Cairo context.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R3yRvYoRemI/AAAAAAAAAKY/N41_XN12itc/s1600-h/pizza.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R3yRvYoRemI/AAAAAAAAAKY/N41_XN12itc/s320/pizza.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5151152317056252514" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;On gtkmm we have a set of API for work with Cairo context, the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/namespaceGdk_1_1Cairo.html"&gt;Cairo namespace&lt;/a&gt;, the c++ wrapper for the &lt;a href="http://library.gnome.org/devel/gdk/unstable/gdk-Cairo-Interaction.html"&gt;gdk cairo interaction functions&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#include &amp;lt;gdkmm/general.h&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The function we have to use is the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/namespaceGdk_1_1Cairo.html#1b5c10bf608143eddefadd46091d4a3d"&gt;set_source_pixbuf&lt;/a&gt;, since loading images in this way is slower we first create a new &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1Context.html"&gt;Cairo::Context&lt;/a&gt; containing the pixbuf and on the on_expose_event of the gtkmm widget we simply copy the image.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:130%;" &gt;Write the new widget&lt;/span&gt;&lt;br /&gt;For a demo we can write a widget that inherits from &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGtk_1_1DrawingArea.html"&gt;DrawingArea&lt;/a&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;#ifndef IMAGEAREA_H_&lt;br /&gt;#define IMAGEAREA_H_&lt;br /&gt;&lt;br /&gt;#include &amp;lt;gtkmm/drawingarea.h&amp;gt;&lt;br /&gt;&lt;br /&gt;#include &amp;lt;gdkmm/pixbuf.h&amp;gt;&lt;br /&gt;#include &amp;lt;glibmm/refptr.h&amp;gt;&lt;br /&gt;#include &amp;lt;cairomm/surface.h&amp;gt;&lt;br /&gt;&lt;br /&gt;class ImageArea : public Gtk::DrawingArea&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;    ImageArea();&lt;br /&gt;    virtual ~ImageArea();&lt;br /&gt;    &lt;br /&gt;    bool loadFile(const Glib::ustring&amp;amp; file_name);&lt;br /&gt;    &lt;br /&gt;protected:&lt;br /&gt;    Cairo::RefPtr&amp;lt; Cairo::Context &amp;gt; image_context_ptr_;&lt;br /&gt;    Cairo::RefPtr&amp;lt; Cairo::ImageSurface &amp;gt; image_surface_ptr_;&lt;br /&gt;    Glib::RefPtr&amp;lt; Gdk::Pixbuf &amp;gt; image_ptr_;&lt;br /&gt;    bool loaded_;&lt;br /&gt;    &lt;br /&gt;    //Override default signal handler:&lt;br /&gt;    virtual bool on_expose_event(GdkEventExpose* event);    &lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;#endif /*IMAGEAREA_H_*/&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:130%;" &gt;Load the image file&lt;/span&gt;&lt;br /&gt;We can implement the loadFile methods in this way:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;bool ImageArea::loadFile(const Glib::ustring&amp;amp; file_name)&lt;br /&gt;{&lt;br /&gt;    // Load pixbuf&lt;br /&gt;    image_ptr_ = Gdk::Pixbuf::create_from_file (file_name);&lt;br /&gt;    &lt;br /&gt;    // Detect transparent colors for loaded image&lt;br /&gt;    Cairo::Format format = Cairo::FORMAT_RGB24;&lt;br /&gt;    if (image_ptr_-&amp;gt;get_has_alpha())&lt;br /&gt;    {&lt;br /&gt;        format = Cairo::FORMAT_ARGB32;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    // Create a new ImageSurface&lt;br /&gt;    image_surface_ptr_ = Cairo::ImageSurface::create  (format, image_ptr_-&amp;gt;get_width(), image_ptr_-&amp;gt;get_height());&lt;br /&gt;    &lt;br /&gt;    // Create the new Context for the ImageSurface&lt;br /&gt;    image_context_ptr_ = Cairo::Context::create (image_surface_ptr_);&lt;br /&gt;    &lt;br /&gt;    // Draw the image on the new Context&lt;br /&gt;    Gdk::Cairo::set_source_pixbuf (image_context_ptr_, image_ptr_, 0.0, 0.0);&lt;br /&gt;    image_context_ptr_-&amp;gt;paint();&lt;br /&gt;    &lt;br /&gt;    loaded_ = true;&lt;br /&gt;    &lt;br /&gt;    return true;&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The function load the image file using the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html"&gt;pixbuf&lt;/a&gt; class, the &lt;a href="http://www.gtkmm.org/docs/gtkmm-2.4/docs/reference/html/classGdk_1_1Pixbuf.html#5000775e43142f3e764ba64236c95d47"&gt;create_from_file&lt;/a&gt; static method throw an exception if the file does not exist.&lt;br /&gt;After create the pixbuf we can create the Cairo::Context, but we have to detect if the image has transparent color, for use the correct &lt;a href="http://cairographics.org/documentation/cairomm/reference/namespaceCairo.html#d3f86970e1bd354b263303c9b8759166"&gt;Cairo::Context format&lt;/a&gt;. We create a new &lt;a href="http://cairographics.org/documentation/cairomm/reference/classCairo_1_1ImageSurface.html"&gt;Cairo::ImageSurface&lt;/a&gt; and bind this to a new Cairo::Context. Now we have a new context and we can paint the loaded image using the set_source_pixbuf.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:130%;" &gt;Draw the image on the Widget Context&lt;/span&gt;&lt;br /&gt;We can override the on_expose_event in this way:&lt;br /&gt;&lt;br /&gt;&lt;pre style="font-family: Andale Mono, Lucida Console, Monaco, fixed, monospace; color: #000000; background-color: #eee;font-size: 12px;border: 1px dashed #999999;line-height: 14px;padding: 5px; overflow: auto; width: 100%"&gt;&lt;code&gt;bool ImageArea::on_expose_event(GdkEventExpose* event)&lt;br /&gt;{&lt;br /&gt;    if (!loaded_)&lt;br /&gt;        return true;&lt;br /&gt;&lt;br /&gt;    // Create the context for the widget&lt;br /&gt;    Cairo::RefPtr&amp;lt;Cairo::Context&amp;gt; context = get_window()-&amp;gt;create_cairo_context();&lt;br /&gt;    &lt;br /&gt;    // Select the clipping rectangle&lt;br /&gt;    context-&amp;gt;rectangle(event-&amp;gt;area.x, event-&amp;gt;area.y,&lt;br /&gt;        event-&amp;gt;area.width, event-&amp;gt;area.height);&lt;br /&gt;    &lt;br /&gt;    context-&amp;gt;clip();&lt;br /&gt;    &lt;br /&gt;    // Store context&lt;br /&gt;    context-&amp;gt;save();&lt;br /&gt;    &lt;br /&gt;    // Draw the source image on the widget context&lt;br /&gt;    context-&amp;gt;set_source (image_surface_ptr_, 0.0, 0.0);&lt;br /&gt;    context-&amp;gt;rectangle (0.0, 0.0, image_ptr_-&amp;gt;get_width(), image_ptr_-&amp;gt;get_height());&lt;br /&gt;    context-&amp;gt;clip();&lt;br /&gt;    context-&amp;gt;paint();&lt;br /&gt;    &lt;br /&gt;    // Restore context&lt;br /&gt;    context-&amp;gt;restore();&lt;br /&gt;    &lt;br /&gt;    return true;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We create the Cairo::Context for the widget, and then we can paint the ImageSurface for loaded image to the widget using the &lt;a href="http://cairographics.org/FAQ/#paint_from_a_surface"&gt;usual way&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Finally a screenshot of my GraphicEditor showing a jpeg image file.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_sQJ1m4QDkME/R336hIoRenI/AAAAAAAAAKg/nbYObQS_fII/s1600-h/Screenshot-GraphicEditor+sample-1.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_sQJ1m4QDkME/R336hIoRenI/AAAAAAAAAKg/nbYObQS_fII/s320/Screenshot-GraphicEditor+sample-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5151548995940743794" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3099599922593802324-6846681828296818544?l=kapo-cpp.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kapo-cpp.blogspot.com/feeds/6846681828296818544/comments/default' title='Commenti sul post'/><link rel='replies' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/drawing-pixbuf-to-cairo-context-2.html#comment-form' title='11 Commenti'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/6846681828296818544'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3099599922593802324/posts/default/6846681828296818544'/><link rel='alternate' type='text/html' href='http://kapo-cpp.blogspot.com/2008/01/drawing-pixbuf-to-cairo-context-2.html' title='Drawing pixbuf to Cairo context (2)'/><author><name>kapo</name><uri>http://www.blogger.com/profile/14637510199591729752</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='28' src='http://bp3.blogger.com/_sQJ1m4QDkME/RyAz2IsNlsI/AAAAAAAAAII/Q0NNjGgvj6M/s320/kapo1.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_sQJ1m4QDkME/R3yRvYoRemI/AAAAAAAAAKY/N41_XN12itc/s72-c/pizza.jpg' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3099599922593802324.post-4790067804429565888</id><published>2007-12-10T08:10:00.000+01:00</published><updated>2008-12-11T09:44:09.907+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c++'/><title type='text'>Distance for developers</title><content type='html'>Developing my GraphicEditor I need to compute distance between two points and between the mouse pointer and a line. I search on google but almost the pages are written by mathematics and I find very difficult to decript all the strange magic formulas.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_sQJ1m4QDkME/R1zt0_w5CCI/AAAAAAA
