<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DUMFRn4_fyp7ImA9WhRUEU4.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462</id><updated>2012-01-21T17:16:57.047+08:00</updated><category term="flash" /><category term="postgresql" /><category term="gnome3" /><category term="news" /><category term="當兵" /><category term="development" /><category term="apt-get" /><category term="AppCentre" /><category term="asus" /><category term="community" /><category term="adobe" /><category term="rss reader" /><category term="linkedin" /><category term="logitech" /><category term="chrome" /><category term="openstreetmap" /><category term="picasa" /><category term="urmap" /><category term="mouse" /><category term="TDD" /><category term="beryl" /><category term="hard disk" /><category term="video" /><category term="xsplash" /><category term="中文" /><category term="愚人節" /><category term="seed" /><category term="openoffice.org" /><category term="tab" /><category term="IBM" /><category term="ubuntu 8.04" /><category term="jaiku" /><category term="geany" /><category term="dual-monitor" /><category term="java" /><category term="arch" /><category term="電池" /><category term="拼音" /><category term="restful" /><category term="lazybuntu" /><category term="mac os" /><category term="music player" /><category term="ubuntu studio" /><category term="apt" /><category term="xmlrpc" /><category term="ubuntu 9.10" /><category term="album" /><category term="pdf" /><category term="wordpress" /><category term="fast boot" /><category term="centrino" /><category term="about:config" /><category term="jamei" /><category term="desktop" /><category term="G1" /><category term="lively" /><category term="glib" /><category term="palm" /><category term="compiz fusion" /><category term="ubuntu" /><category term="touchpad" /><category term="anti-virus" /><category term=".NET" /><category term="google" /><category term="ruby" /><category term="Pull Down Refresh" /><category term="yahoo pipes" /><category term="MS Windows" /><category term="eee-pc" /><category term="google video" /><category term="Xserver" /><category term="gtkorphan" /><category term="osdc" /><category term="acpi" /><category term="pidgin" /><category term="xul" /><category term="mplayer" /><category term="f-spot" /><category term="logo" /><category term="輸入法" /><category term="Hacking Thursday" /><category term="gi" /><category term="irc" /><category term="高雄" /><category term="squeeze" /><category term="subtitle" /><category term="hardware" /><category term="硬體" /><category term="ListView" /><category term="gesture" /><category term="zenity" /><category term="artwork" /><category term="other" /><category term="ibus-pinyin-bopomofo" /><category term="p2p" /><category term="gdb" /><category term="eog" /><category term="foxconn" /><category term="gtk" /><category term="ssh" /><category term="music" /><category term="tero" /><category term="deb" /><category term="WLOT" /><category term="ie" /><category term="kkbox" /><category term="ruby on rails" /><category term="sources.list" /><category term="google earth" /><category term="server" /><category term="ThinkPad" /><category term="gnome.asia" /><category term="vpn" /><category term="qt" /><category term="ibus-pinyin" /><category term="gmail" /><category term="tosres" /><category term="ibus" /><category term="calendar" /><category term="gobject" /><category term="xinput" /><category term="RTM" /><category term="jsmodem" /><category term="kalug" /><category term="lenny" /><category term="remember the milk" /><category term="openca" /><category term="open source" /><category term="Vanilla Journal" /><category term="筆記" /><category term="presentation" /><category term="lazyscripts" /><category term="zonble" /><category term="google docs" /><category term="firefox" /><category term="sshfs" /><category term="google profile" /><category term="css" /><category term="icos" /><category term="ati" /><category term="gaim" /><category term="symbian" /><category term="nintendo" /><category term="sun" /><category term="todo" /><category term="vim" /><category term="eclipse" /><category term="windows mobile" /><category term="droid" /><category term="laptop" /><category term="libgtkembedmoz" /><category term="virtualbox" /><category term="google maps" /><category term="Sony" /><category term="dcraw" /><category term="lftp" /><category term="gnome-taiwan" /><category term="bloglines" /><category term="注音" /><category term="sound card" /><category term="callback" /><category term="smartphone" /><category term="blogg" /><category term="jslinux" /><category term="deborphan" /><category term="google chrome os" /><category term="radeon" /><category term="editor" /><category term="intel" /><category term="Software Store" /><category term="software" /><category term="gnome-panel" /><category term="html" /><category term="Lenovo" /><category term="remix" /><category term="screenshot" /><category term="beagle" /><category term="web design" /><category term="node.js" /><category term="sharp" /><category term="FireGestures" /><category term="app store" /><category term="orzlab" /><category term="javascript" /><category term="xandros" /><category term="gobject-introspection" /><category term="seedkit" /><category term="jenkins" /><category term="gjs" /><category term="google talk" /><category term="gnome-shell" /><category term="jserv" /><category term="map" /><category term="linux Taiwan" /><category term="lazyeeepc" /><category term="lucid" /><category term="fedora" /><category term="graphviz" /><category term="hardy" /><category term="rpm" /><category term="evolution" /><category term="qunit" /><category term="tossug" /><category term="GNOME" /><category term="富士康" /><category term="osdc.tw" /><category term="C++" /><category term="DRBL" /><category term="topic" /><category term="downthemall" /><category term="plymouth" /><category term="unit test" /><category term="python" /><category term="browser" /><category term="debian" /><category term="hotkey" /><category term="windows" /><category term="coscup" /><category term="compiz" /><category term="mint" /><category term="Android" /><category term="google calendar" /><category term="app centre" /><category term="linux" /><category term="google analytics" /><category term="translation" /><category term="ajax" /><category term="google code search" /><category term="moblin" /><category term="modem" /><category term="GAE" /><category term="wii" /><category term="irssi" /><category term="google presentations" /><category term="font" /><category term="blog" /><category term="MX510" /><category term="canonical" /><category term="nikon d200" /><category term="blogger" /><category term="elantech" /><category term="opcion" /><category term="tunnel" /><category term="xfce" /><category term="X-Window" /><category term="google reader" /><category term="google desktop" /><category term="TrackPoint" /><title>Yuren's Info Area</title><subtitle type="html">語言本身無所不能，設計師的表達能力是唯一的極限</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://yurinfore.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>536</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/YurensInfoArea" /><feedburner:info uri="yurensinfoarea" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;DUMFRn48fCp7ImA9WhRUEU4.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-7917524744885596398</id><published>2012-01-21T17:16:00.000+08:00</published><updated>2012-01-21T17:16:57.074+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-21T17:16:57.074+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="gnome3" /><category scheme="http://www.blogger.com/atom/ns#" term="fedora" /><title>Fedora 16 下換 GNOME3 Theme</title><content type="html">一時無聊看到 &lt;a href="http://tiheum.deviantart.com/art/Gnome-Shell-Ice-Crean-Sandwich-280076980"&gt;ICS GNOME3&lt;/a&gt; 的 Theme 覺得很有趣想換一下，沒想到還有點麻煩。主要在於 Fedora 上面的 GNOME3 Theme Selector extension 有相容性問題沒辦法安裝。&lt;br /&gt;
&lt;br /&gt;
解決的方法是只安裝 GNOME3 User Theme extension，然後再用 command line 修改 theme。&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;下載 GNOME3 的 Theme，並且放到 .themes 裡面，如果沒這個目錄就創建一個&lt;/li&gt;
&lt;li&gt;安裝 user theme extension:&lt;br /&gt;# yum install&amp;nbsp;gnome-shell-extension-user-theme.noarch&lt;/li&gt;
&lt;li&gt;重開 gnome-shell，按下 alt + F2 輸入 r 按 enter&lt;/li&gt;
&lt;li&gt;使用指令指定要使用的 theme:&lt;br /&gt;$ gsettings set org.gnome.shell.extensions.user-theme name "Ice Cream Sandwich"&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
這樣就可以切換到所指定的 theme 了。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-LslnZCfSZMI/TxqBU-dO_8I/AAAAAAAAMZY/_q-rIR1FfqM/s1600/%25E8%259E%25A2%25E5%25B9%2595%25E6%2588%25AA%25E5%259C%2596%25E5%25AD%2598%25E7%2582%25BA+2012-01-21+17%253A00%253A47.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="480" src="http://2.bp.blogspot.com/-LslnZCfSZMI/TxqBU-dO_8I/AAAAAAAAMZY/_q-rIR1FfqM/s640/%25E8%259E%25A2%25E5%25B9%2595%25E6%2588%25AA%25E5%259C%2596%25E5%25AD%2598%25E7%2582%25BA+2012-01-21+17%253A00%253A47.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
這樣跟我的手機剛好搭成一套 :)&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-eb4ygT4OC5o/TxqCRnqaYZI/AAAAAAAAMZg/TUpY-jzwWYc/s1600/Screenshot_2012-01-21-17-03-07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://4.bp.blogspot.com/-eb4ygT4OC5o/TxqCRnqaYZI/AAAAAAAAMZg/TUpY-jzwWYc/s640/Screenshot_2012-01-21-17-03-07.png" width="360" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&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/7050224734475821462-7917524744885596398?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/jTWe_xJVE9M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/7917524744885596398/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2012/01/fedora-16-gnome3-theme.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/7917524744885596398?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/7917524744885596398?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/jTWe_xJVE9M/fedora-16-gnome3-theme.html" title="Fedora 16 下換 GNOME3 Theme" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-LslnZCfSZMI/TxqBU-dO_8I/AAAAAAAAMZY/_q-rIR1FfqM/s72-c/%25E8%259E%25A2%25E5%25B9%2595%25E6%2588%25AA%25E5%259C%2596%25E5%25AD%2598%25E7%2582%25BA+2012-01-21+17%253A00%253A47.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2012/01/fedora-16-gnome3-theme.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ICRnc8cCp7ImA9WhRWEk8.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-4373321512100095815</id><published>2011-12-30T15:18:00.000+08:00</published><updated>2011-12-30T15:19:27.978+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-30T15:19:27.978+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ListView" /><category scheme="http://www.blogger.com/atom/ns#" term="Pull Down Refresh" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><title>客製化 ListView 產生 ScrollRunnable 互搶的問題解法</title><content type="html">最近用了一個朋友寫的客製化的 ListView，主要的用途是作類似 iOS 上可以作 Pull down refresh 的功能。&lt;br /&gt;
&lt;br /&gt;
但遇到了一個小問題困擾我很久。&lt;br /&gt;
&lt;br /&gt;
因為 pull down 的 scrolling back to first item 的工作是由一個 ScrollRunnable 搭配 Scroller 實作的，這東西基本上平常運作都沒有問題，但是如果在 Scroll Fling 到最頂端的時候就會有 scroll 亂跳的問題。&lt;br /&gt;
&lt;br /&gt;
深究 ListView/AbsListView 之後，發現其實 AbsListView 內有一個 mFlingRunnable 負責控制 Fling 動作發生時的捲動動作，而當使用另外一個 &amp;nbsp;ScrollRunnable 去控制捲動的時候，會跟原本的 mFlingRunnable 的捲動互搶，造成捲動亂跳的問題。&lt;br /&gt;
&lt;br /&gt;
知道原因了，要解決就很簡單吧？&lt;br /&gt;
&lt;br /&gt;
錯了。&lt;br /&gt;
&lt;br /&gt;
AbsListView 並沒有預留讓開發者存取 mFlingRunnable 的介面，拿不到 Runnable 就無法取消它。難道我要把整個 AbsListView, ListView 搬出來嗎 XDD&lt;br /&gt;
&lt;br /&gt;
還好找到了一個不太好的 workaround。但是鑑於要把整個 AbsListView 移出來的成本太大，就將就著用了。答案是當使用 smoothScrollBy 系列的 method 的時候，AbsListView 將會自己移除 mFlingRunnable 的操作：&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: java"&gt;    public void smoothScrollBy(int distance, int duration) {
        if (mFlingRunnable == null) {
            mFlingRunnable = new FlingRunnable();
        } else {
            mFlingRunnable.endFling();
        }
        mFlingRunnable.startScroll(distance, duration);
    }

&lt;/pre&gt;
所以當你要操作自己的 ScrollRunnable 的時候，先執行 smoothScrollBy(0, 0) 就行了。因為參數都是 0 所以基本上 Fling 的動作就會取消了。&lt;br /&gt;
&lt;br /&gt;
如果哪位看官有更好的解法請務必跟我說 :D&lt;br /&gt;
&lt;br /&gt;
特別感謝 &lt;a href="https://www.facebook.com/wuman"&gt;David Wu&lt;/a&gt; 跟我一起看了這個問題！&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-4373321512100095815?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/i27ppbUm5R0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/4373321512100095815/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/12/listview-scrollrunnable.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/4373321512100095815?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/4373321512100095815?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/i27ppbUm5R0/listview-scrollrunnable.html" title="客製化 ListView 產生 ScrollRunnable 互搶的問題解法" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/12/listview-scrollrunnable.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYGSHY4cSp7ImA9WhRQGEs.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-8595734810157958242</id><published>2011-12-14T19:28:00.000+08:00</published><updated>2011-12-14T19:28:49.839+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-14T19:28:49.839+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><title>Android 自製元件 - PrismFlipper</title><content type="html">這幾天公司的 app 要作訂製的 notification bar，花了一點時間做出來，把他整理出來成一個小 view widget，這個 widget 主要是一個客製化的 notification bar，主要是想模擬三角稜柱翻動的樣子。跑起來大概像下面這樣：&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;iframe width="640" height="480" src="http://www.youtube.com/embed/Ra37YQMtJ5E?hd=1" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
使用方法也很簡單，用 flipper.showNext(text, reverse) 就可以使用了，下面附上比較完整的範例&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: java"&gt;final PrismFlipper flipper = (PrismFlipper)findViewById(R.id.viewFlipper1);
final String[] texts = new String[] { "Refresh", "go to last read position", "last read post" };
flipper.setFrontText(texts[0]);
flipper.setBackground(new ColorDrawable(0xff3465a4));
flipper.setTextColor(Color.WHITE);
Button btn = (Button)findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener() {
   
 @Override
 public void onClick(View arg0) {
  flipper.showNext(texts[mPosition], false);
  mPosition = (mPosition + 1) % texts.length;
 }
});
        
btn = (Button)findViewById(R.id.button2);
btn.setOnClickListener(new OnClickListener() {
   
 @Override
 public void onClick(View arg0) {
  flipper.showNext(texts[mPosition], true);
  mPosition = (mPosition + 1) % texts.length;
 }
});
&lt;/pre&gt;
&lt;br /&gt;
完整的範例可以在 &lt;a href="https://github.com/yurenju/PrismFlipper"&gt;github&lt;/a&gt; 上找到，授權是 BSD license。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-8595734810157958242?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/VNKKvZwIDKY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/8595734810157958242/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/12/android-prismflipper.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/8595734810157958242?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/8595734810157958242?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/VNKKvZwIDKY/android-prismflipper.html" title="Android 自製元件 - PrismFlipper" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/Ra37YQMtJ5E/default.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/12/android-prismflipper.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcDRX0-fyp7ImA9WhdbGEk.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-352004716209235790</id><published>2011-10-17T17:34:00.000+08:00</published><updated>2011-10-17T17:34:34.357+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-17T17:34:34.357+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><title>Android 小技巧：找出未用的 Resource</title><content type="html">記得好像有其他 Android 內建的方法可以哪些 resource 沒有被使用。一時找不到，Google 一下發現另外一套：&lt;a href="http://code.google.com/p/androidresourcetracker/"&gt;Android Resource Tracker&lt;/a&gt;。&lt;br /&gt;
&lt;br /&gt;
使用方法也很簡單，在 project 目錄底下執行：&lt;br /&gt;
&lt;pre class="brush: text"&gt;$ java -jar &amp;lt;PATH_TO_JAR&amp;gt;/AndroidUnusedResources1.4.jar
&lt;/pre&gt;
&lt;br /&gt;
接著就會列出未被使用的資源：&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: text"&gt;Running in: /Users/yurenju/git/YOUR_PROJECT
242 resources found

44 unused resources were found:
array     : upload_photo_options
    /Users/yurenju/git/YOUR_PROJECT/res/values/arrays.xml
...
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-352004716209235790?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/9AA0Tvoge30" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/352004716209235790/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/10/android-resource.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/352004716209235790?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/352004716209235790?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/9AA0Tvoge30/android-resource.html" title="Android 小技巧：找出未用的 Resource" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/10/android-resource.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAFRXY_eip7ImA9WhdbE0w.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-8475258418402599225</id><published>2011-10-11T15:05:00.000+08:00</published><updated>2011-10-11T15:05:14.842+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-11T15:05:14.842+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="eclipse" /><title>Eclipse 小技巧 - 同時設定多個 method breakpoint</title><content type="html">有時候正在除錯剛寫好的 class 時，會需要針對 class 底下的所有 method 設定中斷點。不過一個一個設定實在太麻煩了，Eclipse 提供一個很貼心的功能，可以直接將多個 method 設定中斷點。&lt;br /&gt;
&lt;br /&gt;
打開 Eclipse 找到列出所有 Method 的 Outline，用 Ctrl/Cmd 多選 Method 後，按右鍵選取 Toggle Method Breakpoint 即可。&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-mpDU5N24xrA/TpPpTARkALI/AAAAAAAALA4/wEFhAkOqNmU/s1600/eclipse.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" id=":current_picnik_image" src="http://4.bp.blogspot.com/-mpDU5N24xrA/TpPpTARkALI/AAAAAAAALA4/wEFhAkOqNmU/s1600/eclipse.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-8475258418402599225?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/iTTe7khnmJM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/8475258418402599225/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/10/eclipse-method-breakpoint.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/8475258418402599225?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/8475258418402599225?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/iTTe7khnmJM/eclipse-method-breakpoint.html" title="Eclipse 小技巧 - 同時設定多個 method breakpoint" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-mpDU5N24xrA/TpPpTARkALI/AAAAAAAALA4/wEFhAkOqNmU/s72-c/eclipse.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/10/eclipse-method-breakpoint.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QEQ3g8eyp7ImA9WhdVF04.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-5899414564584042070</id><published>2011-09-22T23:58:00.001+08:00</published><updated>2011-09-23T06:41:42.673+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-23T06:41:42.673+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="qunit" /><category scheme="http://www.blogger.com/atom/ns#" term="unit test" /><category scheme="http://www.blogger.com/atom/ns#" term="TDD" /><title>Javascript client library 之 TDD</title><content type="html">最近因緣際會在寫 web service 的 javascript client library，就趁著這個機會試試看 &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD (Test-Driven Development)&lt;/a&gt; 的方式來開發看看。&lt;br /&gt;
&lt;br /&gt;
這次撰寫的 client library 因為是 javascript，所以就利用了 Javascript 常見的 event driven 的呼叫方式。原本打算用 &lt;a href="http://www.jsunit.net/"&gt;jsunit&lt;/a&gt; 作為 unit test 的框架，但因為沒看到可以測試 callback 的 method，最後改用了 jquery 所使用的 &lt;a href="http://docs.jquery.com/Qunit"&gt;qunit&lt;/a&gt;。&lt;br /&gt;
&lt;br /&gt;
qunit 在測試 callback 的方式大略如下：&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: js"&gt;test(
  'Login success test',

  function() {
    expect(1);
    stop();

    var service = new WebService();
    service.login(
      {
        username: 'user1@example.com',
        password: 'password'
      },
      function(res) {
        equal(res.response.status, "OK", 'expected login success');
        start();
      }
    );
  }
);
&lt;/pre&gt;
qunit 可以利用 stop() 停止整個 unit test 的進行，等到呼叫 start() 的時候再繼續執行。在這個測試中，qunit 會在 stop() 之後開始等待，等到呼叫到 callback method 裡面的 start() 之後才會繼續執行，這個時候就可以擷取到 equal() 所測試的結果。另外 expect() 可以指定預期會跑到的 assert 總共有幾個，在這個例子裡面只跑了一次 equal()，所以是 expect(1)。

當所有 test case 完成後，跑 qunit 的結果大略如下：

&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-UnVkxRZy3Qw/TntZF-CR0NI/AAAAAAAAK2Q/vjP71KeYDe0/s1600/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-09-22+%25E4%25B8%258B%25E5%258D%258811.39.44.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/-UnVkxRZy3Qw/TntZF-CR0NI/AAAAAAAAK2Q/vjP71KeYDe0/s640/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-09-22+%25E4%25B8%258B%25E5%258D%258811.39.44.png" width="534" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
因為根本就還沒開始寫 client library，當然所有測試結果都是 failed。但在這個時候就已經得知 javascript client library 要如何使用以及有哪些回傳值了。這樣其實可以在早期的時候就可以看到整個 client library 的面貌。&lt;br /&gt;
&lt;br /&gt;
而且看著 test case 一個一個的通過心中真是有莫名的快感阿。寫完之後就變成這樣：&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-XTi2HJPnlQ0/TntaRtp6VJI/AAAAAAAAK2U/SZy3v8RPb2E/s1600/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-09-22+%25E4%25B8%258B%25E5%258D%258811.53.21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://2.bp.blogspot.com/-XTi2HJPnlQ0/TntaRtp6VJI/AAAAAAAAK2U/SZy3v8RPb2E/s640/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-09-22+%25E4%25B8%258B%25E5%258D%258811.53.21.png" width="530" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
使用 TDD 方法開發確實讓整個開發的過程踏實不少。不過這種開發方式還是比較適合實作函式庫，如果撰寫 UI 的話就沒有那麼適合了。&lt;br /&gt;
&lt;br /&gt;
不過大家還是可以玩一下，蠻有收穫的 :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-5899414564584042070?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/xI7jGusW2Gc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/5899414564584042070/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/09/javascript-client-library-tdd.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/5899414564584042070?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/5899414564584042070?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/xI7jGusW2Gc/javascript-client-library-tdd.html" title="Javascript client library 之 TDD" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-UnVkxRZy3Qw/TntZF-CR0NI/AAAAAAAAK2Q/vjP71KeYDe0/s72-c/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-09-22+%25E4%25B8%258B%25E5%258D%258811.39.44.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/09/javascript-client-library-tdd.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ANRn08cSp7ImA9WhdWFks.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-1778197328301009815</id><published>2011-09-10T12:12:00.000+08:00</published><updated>2011-09-10T21:36:37.379+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-10T21:36:37.379+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="jenkins" /><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><title>Jenkins 系列 (1): 在終端機下設定 Android 模擬器</title><content type="html">命題的有點怪，不過基本上這是篇為了在&amp;nbsp;Jenkins&amp;nbsp;進行 unit test 以及 daily build 的前置動作。當在建立 Continuous Integration 的測試系統時，我希望可以在一台獨立的機器進行測試。而在遠端的伺服器不一定有 X Window 的狀況，這個時候就會需要在終端機上設定 Android Eumlator 環境。&lt;br /&gt;
&lt;br /&gt;
首先是下載並且解壓縮 Android SDK&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: text"&gt;
$&amp;nbsp;wget http://dl.google.com/android/android-sdk_r12-linux_x86.tgz
$ tar zxvf android-sdk_r12-linux_x86.tgz&lt;/pre&gt;
&lt;br /&gt;
切換到&amp;nbsp;android-sdk-linux_x86/tools，並且用 --no-ui 選項來安裝 Android 3.2/2.3 或其他平台相關的 Platform SDK&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: text"&gt;
$ cd android-sdk-linux_x86/tool
$ ./android update sdk --no-ui
&lt;/pre&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
這個時候會從最新的平台（如 Android 3.2）開始下載安裝，一路從最新的下載到最舊的 SDK。我是在下載完 Android 2.2 的 Platform SDK 就按 Ctrl + C 終止安裝。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
編輯家目錄的 ~/.bash_profile，加入執行路徑：&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class="brush: text"&gt;PATH="$PATH:~/android-sdk-linux_x86/tools:~/android-sdk-linux_x86/platform-tools&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
安裝完 platform SDK 之後，可以利用下面的指令看到安裝了哪些 platform SDK:&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class="brush: text"&gt;$&amp;nbsp;android list target&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
輸出大略如下：&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: text"&gt;id: 4 or "android-8"
     Name: Android 2.2
     Type: Platform
     API level: 8
     Revision: 3
     Skins: QVGA, WVGA854, WQVGA432, HVGA, WVGA800 (default), WQVGA400
id: 5 or "android-9"
     Name: Android 2.3.1
     Type: Platform
     API level: 9
     Revision: 2
     Skins: QVGA, WVGA854, WQVGA432, HVGA, WVGA800 (default), WQVGA400
id: 6 or "android-10"
     Name: Android 2.3.3
     Type: Platform
     API level: 10
     Revision: 2
     Skins: QVGA, WVGA854, WQVGA432, HVGA, WVGA800 (default), WQVGA400
&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
用下面的指令就可以建立新的 Android 2.3.3 模擬器環境&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class="brush: text"&gt;$ android create avd --name android-2.3 --target android-10&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
這個時候就可以用不跑模擬器畫面的方式啟動 Android 模擬環境：&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class="brush: text"&gt;$ emulator-arm -avd android-2.3 -no-window&lt;/pre&gt;&lt;/div&gt;

想知道運行狀況，可以利用 adb logcat 瞭解。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-1778197328301009815?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/9GJs27HsPN4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/1778197328301009815/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/09/android.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/1778197328301009815?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/1778197328301009815?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/9GJs27HsPN4/android.html" title="Jenkins 系列 (1): 在終端機下設定 Android 模擬器" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/09/android.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0MFQXc8fSp7ImA9WhdXFE8.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-198191179269933868</id><published>2011-08-27T13:03:00.000+08:00</published><updated>2011-08-27T13:03:30.975+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-27T13:03:30.975+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="modem" /><category scheme="http://www.blogger.com/atom/ns#" term="linux" /><category scheme="http://www.blogger.com/atom/ns#" term="jsmodem" /><category scheme="http://www.blogger.com/atom/ns#" term="jslinux" /><title>jsmodem - 讓 jslinux 使用網路功能</title><content type="html">前陣子有個很有趣的 project - &lt;a href="http://bellard.org/jslinux/"&gt;jslinux&lt;/a&gt;，這個專案主要是在瀏覽器上面模擬 x86 電腦，再將 Linux 跑在瀏覽器上面。等於說這個專案簡單實作了 PC 模擬器，就如同 VMWare, VirtualBox 一樣，但是在瀏覽器上就可以跑模擬器上面的 OS 了。甚至在上面還包含了一個 C compiler，可以在上面編譯程式。&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/-3pRI2EPWnQM/TlhbpH3OP4I/AAAAAAAAKqQ/OERsG244474/s1600/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-08-27+%25E4%25B8%258A%25E5%258D%258810.48.02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="524" src="http://1.bp.blogspot.com/-3pRI2EPWnQM/TlhbpH3OP4I/AAAAAAAAKqQ/OERsG244474/s640/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-08-27+%25E4%25B8%258A%25E5%258D%258810.48.02.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
這個 project 非常的酷，不過看完之後也只是覺得有趣，沒繼續追之後的消息。而這個禮拜在 Hacking Thursday 遇到 &lt;a href="http://ben6.blogspot.com/"&gt;Ben&lt;/a&gt;, 他提到了這個專案的後續發展 - 有人利用 ppp 實作的 modem device，所以這個在瀏覽器上面運作的 Linux 現在可以上網了 XD&lt;br /&gt;
&lt;br /&gt;
這個延伸的專案是 &lt;a href="https://github.com/ewiger/jsmodem"&gt;jsmodem&lt;/a&gt;，主要的功能是在 jslinux 這個 javascript emulator 上加上一個 modem，讓瀏覽器裡面的 Linux 可以上網，我看了一下 source code，推敲的架構如下：&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-oja4BK5Mz9I/TlhtvhULWEI/AAAAAAAAKqY/zYk1ixRTo14/s1600/jsmodem.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://3.bp.blogspot.com/-oja4BK5Mz9I/TlhtvhULWEI/AAAAAAAAKqY/zYk1ixRTo14/s400/jsmodem.png" width="385" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
說是推敲的意思，其實我看了一下沒看到在 browser 怎麼從 ppp 轉到 websocket 的地方。如果有好心的朋友知道可以告訴我一聲 :p&lt;br /&gt;
&lt;br /&gt;
這個 linux 會利用 pppd 的方式開啟一個網路介面，並且接到 jsmodem。而 jsmodem 利用 websocket 的方式向 server 通訊。所以要讓 jslinux 可以上網，必須要在本機端跑一個 websocket server，並且用 iptable forward 封包。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;架設步驟&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
我測試的環境是 Ubuntu 11.04，理論上用什麼 Linux 作法應該都一樣。首先當然是下載 jsmodem&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: text"&gt;git clone https://github.com/ewiger/jsmodem.git&lt;/pre&gt;
&lt;br /&gt;
接著理論上進去 emulator 目錄，打 make all 就可以了。不過不知道為什麼&amp;nbsp;http://bellard.org/ 會檔掉 wget，就算我換 user-agent 也沒辦法。懶得處理，就把四個檔案&amp;nbsp;cpux86.js cpux86-ta.js jslinux.js term.js 載下來放在原本的目錄裡面，再打 make all 就行了。&lt;br /&gt;
&lt;br /&gt;
另外在 jslinux.js 裡面所指示的 binary 路徑是 vmlinux.bin, 而非 vmlinux26.bin，所以必須要將 vmlinux26.bin rename 成 vmlinux.bin



完成之後，就可以用以下指令開啟 websocket server，並且開啟一個 ppp interface 準備接收 websocket 封包。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: text"&gt;sudo ./serve.sh&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
這個時候用 Google Chrome 打開 0.0.0.0:2080，應該就可以看到 Linux 開機。用 root 登入後，打 ./ppp_up 這樣就可以建立 ppp 連線。&lt;br /&gt;
&lt;br /&gt;
這個時候回到本機端的 Linux 建立 package forward&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: text"&gt;#&amp;nbsp;echo 1 &amp;gt; /proc/sys/net/ipv4/ip_forward
#&amp;nbsp;/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE&lt;/pre&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
這樣就大功告成了 :)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-RE_44ykf9pE/Tlh6HcdqEaI/AAAAAAAAKqc/ijDIV_T7Gzg/s1600/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-08-27+%25E4%25B8%258B%25E5%258D%258812.57.06.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="280" src="http://2.bp.blogspot.com/-RE_44ykf9pE/Tlh6HcdqEaI/AAAAAAAAKqc/ijDIV_T7Gzg/s400/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-08-27+%25E4%25B8%258B%25E5%258D%258812.57.06.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-198191179269933868?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/FThTytnun-k" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/198191179269933868/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/08/jsmodem-jslinux.html#comment-form" title="2 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/198191179269933868?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/198191179269933868?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/FThTytnun-k/jsmodem-jslinux.html" title="jsmodem - 讓 jslinux 使用網路功能" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-3pRI2EPWnQM/TlhbpH3OP4I/AAAAAAAAKqQ/OERsG244474/s72-c/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-08-27+%25E4%25B8%258A%25E5%258D%258810.48.02.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/08/jsmodem-jslinux.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQHSXw9fip7ImA9WhdRFkw.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-1540406927511733182</id><published>2011-08-06T14:32:00.000+08:00</published><updated>2011-08-06T14:32:18.266+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-06T14:32:18.266+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="restful" /><category scheme="http://www.blogger.com/atom/ns#" term="node.js" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>Mocking Bird - node.js REST API simulation (1)</title><content type="html">當團隊決定開發一個使用 web service 的 mobile app 時，我們遇到了一個小問題：mobile app 跟 web service 是同時開發的，當 web service 還沒實作完畢前，mobile app developer 只能暫時先從規格中&amp;nbsp;implement 跟 web service 銜接的介面。&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
這聽起來有點瞎子摸象。&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
不過 Jamie Sa 提供了個有趣的點子：如果我們可以寫個模擬的 REST API service，並且透過 YAML 定義簡單的規格的話，我們就可以利用這個模擬 REST API 比較真實的跟 web service 銜接了 :)&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://1.bp.blogspot.com/-EKIHMifuE0A/TjyapToKkQI/AAAAAAAAKZU/w6lhDyKrcuQ/s1600/arch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-EKIHMifuE0A/TjyapToKkQI/AAAAAAAAKZU/w6lhDyKrcuQ/s1600/arch.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;a name='more'&gt;&lt;/a&gt;&lt;br /&gt;
正巧手邊大家正在研究 node.js，不免俗的我們就用了它來實作了初版的 API Simulator，Jamie 把它叫做 mockingBird。這個時候 YAML spec 看起來像這樣：&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: text"&gt;# APIs in V1
meta:
  version: draft
v1_articles:
  timestamp: '2011-07-19T08:54Z'
  is_end: true
  articles:
    - { article: 1 }
    - { article: 2 }
    - { article: 3 }
  article_count: 3
&lt;/pre&gt;
&lt;br /&gt;
而用瀏覽器開啟 http://127.0.0.1:8080/v1/articles 則會輸出以下結果：&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://3.bp.blogspot.com/-4aCXPkkIDaI/TjzLrnwngsI/AAAAAAAAKZY/W6jgCXrtGvc/s1600/v1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-4aCXPkkIDaI/TjzLrnwngsI/AAAAAAAAKZY/W6jgCXrtGvc/s1600/v1.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;br /&gt;
初版的時候我們用 underline "_" 來分割版本，並且將假資料直接放在 YAML 裡面。而當我們需要模擬取得多筆資料的時候還可以處理，但如果需要類似 http://HOST/&lt;host&gt;article/ARTICLE_ID&lt;id&gt;&amp;nbsp;這樣的 API 就無法模擬了，目前這樣的寫法也無法模擬 POST method。&lt;/id&gt;&lt;/host&gt;&lt;br /&gt;
&lt;br /&gt;
做了一連串的 hacking 後，終於完成了一個較有彈性的架構，不過當然還是沒辦法模擬太過於複雜的狀況 :P&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://2.bp.blogspot.com/-HGudaXyIgOE/TjzM8c5bpiI/AAAAAAAAKZc/RgmbNsQPnzs/s1600/arch-v2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-HGudaXyIgOE/TjzM8c5bpiI/AAAAAAAAKZc/RgmbNsQPnzs/s1600/arch-v2.png" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
MockingBird 會將 JSON 格式的假資料讀取進來，而可以在 YAML 裡面調用 dummy data 以及使用簡單的 Javascript 做計算。&lt;br /&gt;
&lt;br /&gt;
比如說我要模擬 Social network 的 API，&lt;br /&gt;
&lt;br /&gt;
首先要先產生 dummy.json 假資料檔，這邊我用一個 python script 產生 dummy.json。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: python"&gt;import uuid
import json
from random import randint, choice
from datetime import datetime, timedelta

firstnames = ['Ericka', 'Amie', 'Annabelle', 'Hugh', 'Carmella']
lastnames = ['Hilts', 'Kowalsky', 'Cincotta', 'Gerken', 'Stults']
devicenames = ['iPad', 'Android', 'Web']
basetime = datetime.today()
lipsum='Lorem ipsum dolor sit amet, consectetur adipiscing elit. In sollicitudin elementum tristique. Nullam gravida bibendum magna viverra gravida. Cras nec mi a est malesuada dictum.'

def gen_id():
    return uuid.uuid1().hex[:24]

def gen_users(num=10):
    users = []
    for i in range(num):
        user = {}
        user['id'] = gen_id()
        user['email'] = 'a%s@example.com' % randint(0,1000000)
        user['nickname'] = "%s %s" % \
                           (choice(firstnames), \
                           choice(lastnames))
        users.append(user)
    return users

def gen_comment(users, article_id, timestamp):
    c = {}
    c['id'] = gen_id()
    c['creator_id'] = choice(users)['id']
    c['creation_device_name'] = choice(devicenames)
    c['article_id'] = article_id
    c['timestamp'] = timestamp
    c['text'] = lipsum
    return c

def gen_articles(users, num=20):
    articles = []
    for i in range(num):
        user = choice(users)
        timestamp = basetime+timedelta(0,i*10)
        article = {}
        article['id'] = gen_id()
        article['creator_id'] = user['id']
        article['creation_device_name'] = choice(devicenames)
        article['timestamp'] = timestamp.isoformat()
        article['text'] = lipsum
        article['comment_count'] = randint(0,5)
        article['comments'] = []
        for j in range(article['comment_count']):
            c = gen_comment(users, article['id'], \
                            (timestamp+timedelta(0,j*10)).isoformat())
            article['comments'].append(c)

        articles.append(article)
    return articles

if __name__ == '__main__':
    data = {}
    data['users'] = gen_users()
    data['articles'] = gen_articles(data['users'])
    print json.dumps(data, indent=2)

&lt;/pre&gt;
&lt;br /&gt;
&lt;br /&gt;
這個 dummy json 會 load 進去 node.js 的主程式裡面，可以由程式或者是 YAML 裡面使用。現在的 YAML 檔案則是長成這樣：&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: text"&gt;version: 0
api:
  articles:
    prefix: api
    url: "articles.*"
    http_method: GET
    response:
      timestamp: "timestamp"
      is_end: "true"
      article_count: "dummy['articles'].length"
      articles: "params['limit'] ? dummy['articles'].slice(0,params['limit']) : dummy['articles']"
  article:
    prefix: api
    url: "article/(\w+)$"
    http_method: GET
    response:
      article: "findById(dummy['articles'], match)"
  users:
    prefix: api
    url: "users"
    http_method: GET
    response:
      users: "dummy['users']"
  
  post_article:
    prefix: api
    url: article
    http_method: POST
    response:
      creator_id: "params.creator_id"
      creation_device_name: "params.creation_device_name"
      text: "params.text"
      timestamp: "timestamp"
      comment_count: "0"
      comments: "[]"
      id: "generateId()"
  
  post_comment:
    prefix: api
    url: comment
    http_method: POST
    response:
      creator_id: "params.creator_id"
      creation_device_name: "params.creation_device_name"
      article_id: "params.article_id"
      text: "params.text"
      id: "generateId()"
      
&lt;/pre&gt;
&lt;br /&gt;
裡面有些關鍵字解釋一下：&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;version&lt;/b&gt;: 最後 mockingBird 的網址會是 http://HOST&lt;host&gt;/PREFIX&lt;prefix&gt;/VERSION&lt;version&gt;/method，如 http://localhost/api/0/articles，用來區分 API 版本用的變數&lt;/version&gt;&lt;/prefix&gt;&lt;/host&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;prefix&lt;/b&gt;: 可以針對 API 的用途使用不同的 prefix，在這邊我們只用了 "api" 這個 prefix。&lt;/li&gt;
&lt;li&gt;&lt;b&gt;url&lt;/b&gt;: url 的 match pattern&lt;/li&gt;
&lt;li&gt;&lt;b&gt;http_method&lt;/b&gt;: 可以指定要用 POST 或是 GET 的 HTTP Method&lt;/li&gt;
&lt;li&gt;&lt;b&gt;response&lt;/b&gt;: 要回應的 JSON 訊息。&lt;/li&gt;
&lt;li&gt;&lt;b&gt;dummy&lt;/b&gt;: 在 YAML 裡面可以利用 dummy 取得假資料，比如說 dummy['articles'] 就是所有的 articles。&lt;/li&gt;
&lt;li&gt;&lt;b&gt;params&lt;/b&gt;: 使用 GET/POST 的時候丟進來的參數。比如下達了 http://localhost/api/0/articles?limit=2 時，YAML 可以使用參數 params.limit 取得這個 limit 數值，可以參考下面的片段&lt;/li&gt;
&lt;li&gt;&lt;b&gt;findById&lt;/b&gt;: 用 id 來搜尋物件的 method&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre class="brush: text; highlight: 9"&gt;articles:
    prefix: api
    url: "articles.*"
    http_method: GET
    response:
      timestamp: "timestamp"
      is_end: "true"
      article_count: "dummy['articles'].length"
      articles: "params['limit'] ? dummy['articles'].slice(0,params['limit']) : dummy['articles']"
&lt;/pre&gt;
&lt;/div&gt;
&lt;br /&gt;
當用瀏覽器開啟 http://localhost:8080/api/0/articles?limit=1 的時候，就可以獲得以下結果：&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;a href="http://4.bp.blogspot.com/-9B1ODBVlkeQ/TjzZzozlQiI/AAAAAAAAKZg/sjOpGjP8Vus/s1600/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-08-06+%25E4%25B8%258B%25E5%258D%25882.05.17.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://4.bp.blogspot.com/-9B1ODBVlkeQ/TjzZzozlQiI/AAAAAAAAKZg/sjOpGjP8Vus/s640/%25E8%259E%25A2%25E5%25B9%2595%25E5%25BF%25AB%25E7%2585%25A7+2011-08-06+%25E4%25B8%258B%25E5%258D%25882.05.17.png" width="578" /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
如此一來，你的 mobile app 就可以開幹了，而有了這個實體的 SPEC，web service 的 developer 也可以依此為目標，最終做成跟這個相同的 API。&lt;br /&gt;
&lt;br /&gt;
下一篇再來詳細講解怎麼使用這個工具還有 node.js 裡面是怎麼實作的。但重點是：有人有興趣嗎？出個聲吧 :P&lt;br /&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-1540406927511733182?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/ldC8V9KsZXI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/1540406927511733182/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/08/mocking-bird-nodejs-rest-api-simulation.html#comment-form" title="4 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/1540406927511733182?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/1540406927511733182?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/ldC8V9KsZXI/mocking-bird-nodejs-rest-api-simulation.html" title="Mocking Bird - node.js REST API simulation (1)" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-EKIHMifuE0A/TjyapToKkQI/AAAAAAAAKZU/w6lhDyKrcuQ/s72-c/arch.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/08/mocking-bird-nodejs-rest-api-simulation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQERHszfCp7ImA9WhZbGUQ.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-5258733581322714691</id><published>2011-06-25T17:31:00.000+08:00</published><updated>2011-06-25T17:31:45.584+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-25T17:31:45.584+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="gobject-introspection" /><category scheme="http://www.blogger.com/atom/ns#" term="gi" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>Python and GObject-Introspection 簡報</title><content type="html">2011/6/25 在 PycTW 2011 講了 Python and GObject-Introspection，主要講 GObject-Introspection 的原理還有簡單的介紹 python-gobject 如何實作 GObject-Introspection。投影片如下：&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style="width:595px" id="__ss_8419185"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/yurenju/python-and-gobject-introspection" title="Python and GObject Introspection"&gt;Python and GObject Introspection&lt;/a&gt;&lt;/strong&gt; &lt;object id="__sse8419185" width="595" height="497"&gt; &lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=python-gi-110625022017-phpapp01&amp;stripped_title=python-and-gobject-introspection&amp;userName=yurenju" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse8419185" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=python-gi-110625022017-phpapp01&amp;stripped_title=python-and-gobject-introspection&amp;userName=yurenju" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="595" height="497"&gt;&lt;/embed&gt; &lt;/object&gt; &lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/yurenju"&gt;Yuren Ju&lt;/a&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-5258733581322714691?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/gOFb0tALEpw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/5258733581322714691/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/06/python-and-gobject-introspection.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/5258733581322714691?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/5258733581322714691?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/gOFb0tALEpw/python-and-gobject-introspection.html" title="Python and GObject-Introspection 簡報" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/06/python-and-gobject-introspection.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUASXg4eip7ImA9WhZVGE4.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-3633340822326204948</id><published>2011-05-31T18:03:00.001+08:00</published><updated>2011-05-31T18:04:08.632+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-31T18:04:08.632+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Hacking Thursday" /><category scheme="http://www.blogger.com/atom/ns#" term="yahoo pipes" /><title>h4addicted - 聚會主題搜集器</title><content type="html">上次聚會的時候, Rex 講了一個小問題。通常我們在聚會之前，其實就會有一些覺得有趣的主題想要帶到 Hacking Thursday 討論。所以希望有一個地方可以搜集這些主題。不過大家都有各自用的服務如 plurk, twitter 或是 facebook，通常有不太想要只是因為要搜集主題就需要額外使用一個 service (如 friendfeed)。&lt;br /&gt;
&lt;br /&gt;
於是大家就討論想要寫一個 web app 來解決這個問題。基本上的概念就是希望在發言的時候如果加了 #h4 時，就會把這個發言丟到 web app 上，條件是至少要在 twitter 與 plurk 都可以使用 (Facebook 會比較麻煩，所以就先跳過了)。然後我們就在 David 的筆電上蓋看到 addicted 這個字，所以這個專案就叫做 h4addicted 啦。&lt;br /&gt;
&lt;br /&gt;
今天我研究了一下，發現這個服務很容易就可以使用 Yahoo Pipes 兜出來！基於懶惰的原則，我就沒有自己去寫程式了 :P&lt;br /&gt;
&lt;br /&gt;
Yahoo Pipe 基本上是一個可以從網路上撈資料進行後處理的 web app。所以我們要做的就是搜集大家的 feed，對各個 service 做一些後處理後產生新的 RSS/JSON 就完成了。你可以到下面這個網址：&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://pipes.yahoo.com/yurenju/h4addicted"&gt;http://pipes.yahoo.com/yurenju/h4addicted&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
功能其實是非常簡易的，原本製作也很簡單，只要把大家的 RSS feed 拉進來就結束了。不過事情沒有這麼簡單！我們把 twitter, plurk, facebook (對，後來 David 又透過 JSON 撈到了 Facebook 的資料，但是前提是你的 post 是公開的。)都弄出來之後發現有幾個問題要解決：&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Plurk 的 RSS link 欄位填寫的是相對網址，需要對字串作後處理&lt;/li&gt;
&lt;li&gt;Facebook 也有相同的問題，因為是從 JSON 轉過來的，所以也沒有 link 欄位。&lt;/li&gt;
&lt;li&gt;Facebook 因為根本沒有與 link 對應的欄位，所以要從 post id 那邊分析後取得 post id，然後再跟 user id 合併後產生 link 欄位&lt;/li&gt;
&lt;li&gt;Facebook 的 message 欄位沒有 author，所以要額外把 name 加入 message 欄位&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;所以比想象中的複雜一點，不過還是搞定了 XD&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;首先看概觀&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-7K_0DiFoHsA/TeS7JS3OO6I/AAAAAAAAJWA/HseEijAPK5g/s1600/Screenshot-Pipes%253A+editing+%2527h4addicted%2527+-+Google+Chrome.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="486" src="http://4.bp.blogspot.com/-7K_0DiFoHsA/TeS7JS3OO6I/AAAAAAAAJWA/HseEijAPK5g/s640/Screenshot-Pipes%253A+editing+%2527h4addicted%2527+-+Google+Chrome.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;Plurk 的部分其實就是把 link 拿出來加上 http://www.plurk.com/ 的前綴後再塞回去就完成了。右邊的 facebook 我則是把它獨立成另外一個模組處理。&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-J8VeaadaZy8/TeS7sXMloqI/AAAAAAAAJWE/UchS22dVYRo/s1600/Screenshot-Pipes%253A+editing+%2527facebook%2527+-+Google+Chrome.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="454" src="http://2.bp.blogspot.com/-J8VeaadaZy8/TeS7sXMloqI/AAAAAAAAJWE/UchS22dVYRo/s640/Screenshot-Pipes%253A+editing+%2527facebook%2527+-+Google+Chrome.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Rename 模組負責把 JSON 的格式改成與 RSS 類似，讓訊息可以正確的的解譯出來。&lt;/li&gt;
&lt;li&gt;Loop - String Builder 的部分是為了作讓 user name 加在 message 前面，才知道是誰的發言。&lt;/li&gt;
&lt;li&gt;Loop - String Regex 的部分則是用來把 item.id 裡面類似&amp;nbsp;724235041_10150262195320042 的結構取出後者（也就是 post-id）並且儲存&lt;/li&gt;
&lt;li&gt;取出 post-id 後再利用一次 String Builder 把 facebook 前綴、 user-id 與 post-id 連接在一起，就完成了。&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Yahoo Pipes 真是非常方便的工具，利用它其實可以做到非常多事情了 :)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;也歡迎 clone 拿去使用。&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-3633340822326204948?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/zTtKrBZCv-s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/3633340822326204948/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/05/h4addicted.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/3633340822326204948?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/3633340822326204948?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/zTtKrBZCv-s/h4addicted.html" title="h4addicted - 聚會主題搜集器" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-7K_0DiFoHsA/TeS7JS3OO6I/AAAAAAAAJWA/HseEijAPK5g/s72-c/Screenshot-Pipes%253A+editing+%2527h4addicted%2527+-+Google+Chrome.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/05/h4addicted.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUCSX49fCp7ImA9WhZVGE0.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-8610446264374335534</id><published>2011-05-30T16:21:00.018+08:00</published><updated>2011-05-31T10:01:08.064+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-31T10:01:08.064+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="gnome3" /><category scheme="http://www.blogger.com/atom/ns#" term="GNOME" /><category scheme="http://www.blogger.com/atom/ns#" term="gjs" /><title>GNOME3 延伸套件開發</title><content type="html">這幾天到 KaLUG 講了一場『GNOME3 延伸套件開發教學』，其實也幫我自己上了一堂課。在這邊寫下一些心得讓大家參考一下。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;3D 加速後的 GNOME3 桌面&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
在 GNOME3 裡面多了一個 gnome-shell 的軟體，主要負責提供 GNOME3 新一代的使用者體驗，包含更容易使用的 workspace，新的 application 管理機制等等。比如說下面的影片講解了 workspace 系統：&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="390" src="http://www.youtube.com/embed/bRHAio98n-g" width="640"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
而這些絢麗的使用者體驗歸功於新的 UI Toolkit - Clutter 以及 Shell-Toolkit (ST)。Clutter 是一套利用 OpenGL/OpenGL ES 加速的 UI Toolkit，可以簡單的創作出許多絢麗的特效。比如說我們要撰寫一個小程式，當使用者點擊圖像之後，做出淡出、放大並且位移的特效。若使用 GTK+ 或其他 UI Toolkit 亦然可撰寫出來，但採用 Clutter 撰寫時就會格外簡單許多。&lt;br /&gt;
&lt;br /&gt;
&lt;iframe allowfullscreen="" frameborder="0" height="390" src="http://www.youtube.com/embed/RzuTk8s24-0" width="480"&gt;&lt;/iframe&gt;&lt;br /&gt;
(因為使用桌面錄影的關係，感覺有些遲鈍，不過實際上跑的時候還蠻順暢的。)&lt;br /&gt;
&lt;br /&gt;
這個 Demo 程式源碼如下：&lt;br /&gt;
&lt;pre class="brush: js"&gt;const Clutter = imports.gi.Clutter;
const Tweener = imports.tweener.tweener;

function click(actor, ev) {
    let properties = {  time: 2.0,
                        x: texture.x+100,
                        y: texture.y+100,
                        scale_x: 1.5,
                        scale_y: 1.5,
                        opacity: 0
                    };
    Tweener.addTween(texture, properties);
    print('Clicked!');
    return true;
}

function quit(actor) {
    Clutter.main_quit();
}

Clutter.init(0, null);
let stage = new Clutter.Stage();
let texture = new Clutter.Texture({ filename: 'test.jpg',
                                    reactive: true });
texture.connect('button-press-event', click);
stage.connect('destroy', quit);
stage.add_actor(texture);
stage.show();

Clutter.main();
&lt;/pre&gt;&lt;br /&gt;
上面這個範例可以在 Debian 安裝 gir1.0-clutter-1.0, gjs 之後即可執行。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;GNOME3 extension 採用 Javascript 撰寫&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
其實在 gnome-shell 的 UI 部分幾乎都是採用 Javascript 撰寫而成。而理所當然的開發 extension 時當然也是採用 Javascript 開發。然而最好的地方在於開發 extension 的時候，就像是 firefox extension 一樣，你可以任意的存取原本 gnome-shell 的所有元件。比如說，你可以存取 panel 的日曆元件，並且加入或修改這些元件。&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Looking glass - 幾近作弊的 console&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
在 GNOME3 extension 開發的時候有個非常好用的工具叫做 Looking glass，這個東西就像是雷神之錘按下 "~" 就可以叫出來的 console (然後可以在裡面輸入作弊指令)。在 GNOME3 的環境下，按 alt + F2 並且輸入 lg 你就會看到這個 console 緩緩地從上面降下來。&lt;br /&gt;
&lt;br /&gt;
這東西有什麼用途呢？最好用的工具是左上角那隻筆。它的作用是可以拿來點 GNOME3 桌面元件的任何東西，接着你就可以取得那個元件，然後做些什麼事情。&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-Y1_0fS-BC_s/TeNN1fa-n9I/AAAAAAAAJVg/eVSNmw4caj8/s1600/Screenshot-gnome3-ext-tutorial.pdf.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="291" src="http://3.bp.blogspot.com/-Y1_0fS-BC_s/TeNN1fa-n9I/AAAAAAAAJVg/eVSNmw4caj8/s320/Screenshot-gnome3-ext-tutorial.pdf.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
選取元件之後會跳回 looking glass，這個時候系統就會給他一個存取他的變數 r(NUM)，接下來你可以在 console 使用這個代號調用它。&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Ma9DKiLNcIU/TeNOun-Oz8I/AAAAAAAAJVo/Z_AIjVA7Wsw/s1600/method.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Ma9DKiLNcIU/TeNOun-Oz8I/AAAAAAAAJVo/Z_AIjVA7Wsw/s1600/method.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
當你點擊這個物件的時候，他就會把這個物件的 method 全部列出來，馬上就可以知道有什麼 method 可以調用。然後！這個東西當然不是只有看的，你甚至可以在 looking glass 裡面使用 r(NUM).method() 直接在 runtime 執行特定 method。比如說我執行了 r(13).set_text("I don't care")&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-Uj9TgZvJqnE/TeNPkoSQ4yI/AAAAAAAAJVs/QNDV6CcJmok/s1600/idontcare.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="164" src="http://2.bp.blogspot.com/-Uj9TgZvJqnE/TeNPkoSQ4yI/AAAAAAAAJVs/QNDV6CcJmok/s640/idontcare.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
系統的日期馬上就任性了起來！當然你也可以做些旋轉或什麼之類的事情，而且由於 clutter 的特性，作了修改後的元件依然可以操作。&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-q_ILQQxM53Q/TeNTxGI-aNI/AAAAAAAAJV0/1nDf13O7W2M/s1600/rotation.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="306" src="http://4.bp.blogspot.com/-q_ILQQxM53Q/TeNTxGI-aNI/AAAAAAAAJV0/1nDf13O7W2M/s640/rotation.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
最後附上 Tutorial 簡報，請多多指教 :)&lt;br /&gt;
&lt;br /&gt;
&lt;div style="width:595px" id="__ss_8147152"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/yurenju/gnome3" title="GNOME3 延伸套件教學"&gt;GNOME3 延伸套件教學&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/8147152" width="595" height="497" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt; &lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/yurenju"&gt;Yuren Ju&lt;/a&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-8610446264374335534?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/IX6F0kw9gaU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/8610446264374335534/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/05/gnome3.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/8610446264374335534?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/8610446264374335534?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/IX6F0kw9gaU/gnome3.html" title="GNOME3 延伸套件開發" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/bRHAio98n-g/default.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/05/gnome3.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkcASXY9eip7ImA9WhZWFUg.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-3457344657662611163</id><published>2011-05-16T23:00:00.000+08:00</published><updated>2011-05-16T23:00:48.862+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-16T23:00:48.862+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="linkedin" /><title>Linkedin 連結</title><content type="html">Hi 各位讀者大家好，下面是小弟的 Linkedin 連結：&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://tw.linkedin.com/in/yurenju"&gt;http://tw.linkedin.com/in/yurenju&lt;/a&gt;&lt;br /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;歡迎寄信給我索取詳細資料 :)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div&gt;yurenju -AT- gmail -DOT- com&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-3457344657662611163?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/NGPfebzmmhE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/3457344657662611163/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/05/linkedin.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/3457344657662611163?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/3457344657662611163?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/NGPfebzmmhE/linkedin.html" title="Linkedin 連結" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/05/linkedin.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkYARnY_eip7ImA9WhZRGUs.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-6329974219834964083</id><published>2011-04-16T23:35:00.000+08:00</published><updated>2011-04-16T23:35:47.842+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-16T23:35:47.842+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="gnome3" /><category scheme="http://www.blogger.com/atom/ns#" term="GNOME" /><category scheme="http://www.blogger.com/atom/ns#" term="gnome-taiwan" /><category scheme="http://www.blogger.com/atom/ns#" term="gnome-shell" /><title>[簡報] 手把手教你寫 gnome-shell 擴充套件</title><content type="html">前幾週在 GNOME 3 Release Party 給了這個 Talk 『手把手教你寫 gnome-shell 擴充套件』，分享一下探索下一代 GNOME3 的桌面環境擴充套件，並且簡單的示範如何使用 Javascript 寫出下面這個 Screenshot 的擴充套件&lt;br /&gt;
&lt;br /&gt;
&lt;iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/epKssSQpfLQ" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
GNOME3 的桌面可是充滿著絢麗動畫的 framework 呢 :)&lt;br /&gt;
&lt;br /&gt;
簡報在下面，歡迎參觀。不過提醒一下 GNOME3 這次發佈並沒有提到 extension 系統的部份，想必是 API 目前也還沒有穩定。歡迎敢死隊現在就開始寫 gnome-shell extension!&lt;br /&gt;
&lt;br /&gt;
&lt;div style="width:595px" id="__ss_7581351"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/yurenju/step-by-step-to-write-a-gnomeshell-extension" title="step by step to write a gnome-shell extension "&gt;step by step to write a gnome-shell extension &lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/7581351" width="595" height="497" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt; &lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/yurenju"&gt;Yuren Ju&lt;/a&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-6329974219834964083?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/d9llwcQQpFA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/6329974219834964083/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/04/gnome-shell.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/6329974219834964083?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/6329974219834964083?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/d9llwcQQpFA/gnome-shell.html" title="[簡報] 手把手教你寫 gnome-shell 擴充套件" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/epKssSQpfLQ/default.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/04/gnome-shell.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkYAR309eyp7ImA9Wx9bFU4.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-7981807621508279227</id><published>2011-02-24T14:47:00.001+08:00</published><updated>2011-02-24T14:49:06.363+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-24T14:49:06.363+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="gtk" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><title>Python-GTK 簡報與勘誤</title><content type="html">感謝 Study-Area 與 GNOME Taiwan 的邀請，一月份下旬給了一份 talk，投影片在此。&lt;br /&gt;
&lt;br /&gt;
&lt;div style="width:595px" id="__ss_6739196"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/yurenju/python-gtk" title="Python-GTK"&gt;Python-GTK&lt;/a&gt;&lt;/strong&gt; &lt;object id="__sse6739196" width="595" height="497"&gt; &lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=python-gtk-110128180101-phpapp02&amp;stripped_title=python-gtk&amp;userName=yurenju" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse6739196" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=python-gtk-110128180101-phpapp02&amp;stripped_title=python-gtk&amp;userName=yurenju" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="595" height="497"&gt;&lt;/embed&gt; &lt;/object&gt; &lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/yurenju"&gt;Yuren Ju&lt;/a&gt; &lt;/div&gt;&lt;/div&gt;另外也感謝 &lt;a href="http://mosky.tw/"&gt;Mosky&lt;/a&gt; 以及 &lt;a href="http://hychen.wuweig.org/"&gt;Hychen&lt;/a&gt; 的指正，部分演講內容作出修改。&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;第 35 頁的奇技淫巧其中的回傳多個變數的能力，實際上內部是透過 tuple 實做，並不是真的可以回傳多個變數。&lt;/li&gt;
&lt;li&gt;__init__ 並不是建構子，而是物件的初始化 method&lt;/li&gt;
&lt;li&gt;範例裡面的 gtk-gtr2.py 使用了 except 但卻沒有指定例外種類，這也是不建議的寫法。&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-7981807621508279227?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/zprnGR6ZLGE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/7981807621508279227/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2011/02/python-gtk.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/7981807621508279227?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/7981807621508279227?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/zprnGR6ZLGE/python-gtk.html" title="Python-GTK 簡報與勘誤" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2011/02/python-gtk.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUBQn09fip7ImA9Wx5bEk4.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-1087187694643111423</id><published>2010-10-28T11:40:00.000+08:00</published><updated>2010-10-28T11:40:53.366+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-28T11:40:53.366+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ibus-pinyin-bopomofo" /><category scheme="http://www.blogger.com/atom/ns#" term="ibus" /><category scheme="http://www.blogger.com/atom/ns#" term="ibus-pinyin" /><title>ibus 無調注音支援空白鍵作為一聲</title><content type="html">最近都在修改 ibus 的注音輸入法，這次新增的功能是把原本空白鍵的導引鍵功能，改成支援陰平聲調（也就是注音聲調中的一聲）。之前的無調注音雖然好用，不過許多人還是習慣在輸入的時候鍵入聲調。而 ibus 注音輸入法遇到聲調目前會自動忽略，所以就算你輸入聲調也不會有什麼問題，不過令人困擾的是平常繁體中文使用者使用空白鍵作為聲調中的一聲，正巧跟 ibus 注音輸入法的導引鍵衝突。所以我花了一些時間加入空白鍵作為一聲的支援。&lt;br /&gt;
&lt;br /&gt;
相同的源碼我都放在 &lt;a href="http://github.com/yurenju/ibus-pinyin"&gt;github&lt;/a&gt; 上，現在要使用新增的功能都需要編譯源碼。晚點我測試的差不多後就會推到官方 ibus 的 repository 中。&lt;br /&gt;
&lt;br /&gt;
新的 ibus 注音輸入法在設定的地方會多一個空白鍵功能的選項。&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/_iOO0fC4NKLE/TMjvqu-2-ZI/AAAAAAAAI84/Cy-NNMXCphg/s1600/Screenshot-%E5%81%8F%E5%A5%BD%E8%A8%AD%E5%AE%9A-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_iOO0fC4NKLE/TMjvqu-2-ZI/AAAAAAAAI84/Cy-NNMXCphg/s1600/Screenshot-%E5%81%8F%E5%A5%BD%E8%A8%AD%E5%AE%9A-1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
現在預設會使用陰平聲調，所以新的使用者不需要調整。之前有使用 ibus 注音輸入法的使用者只需要切換這個選項就可以讓空白鍵變成陰平聲調。&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/_iOO0fC4NKLE/TMjwp_fa8sI/AAAAAAAAI88/dmtnBRKsLPM/s1600/chinese-input-method.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_iOO0fC4NKLE/TMjwp_fa8sI/AAAAAAAAI88/dmtnBRKsLPM/s1600/chinese-input-method.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-1087187694643111423?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/DHS3GVaMeuc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/1087187694643111423/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2010/10/ibus.html#comment-form" title="5 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/1087187694643111423?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/1087187694643111423?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/DHS3GVaMeuc/ibus.html" title="ibus 無調注音支援空白鍵作為一聲" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_iOO0fC4NKLE/TMjvqu-2-ZI/AAAAAAAAI84/Cy-NNMXCphg/s72-c/Screenshot-%E5%81%8F%E5%A5%BD%E8%A8%AD%E5%AE%9A-1.png" height="72" width="72" /><thr:total>5</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2010/10/ibus.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAGRXs5cSp7ImA9Wx5UFUo.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-44835227589853203</id><published>2010-10-20T19:12:00.001+08:00</published><updated>2010-10-20T19:22:04.529+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-20T19:22:04.529+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ibus-pinyin-bopomofo" /><category scheme="http://www.blogger.com/atom/ns#" term="ibus" /><category scheme="http://www.blogger.com/atom/ns#" term="ibus-pinyin" /><title>ibus-pinyin-bopomofo 無調注音輸入法新增 enter 直接輸出第一個候選字</title><content type="html">最近正在參與 ibus 中的無調注音輸入法 (pinyin-bopomofo) 的開發。希望能夠讓這個輸入法更好用，並且也同時考慮到對岸以及台灣使用者的使用習慣。&lt;br /&gt;
&lt;br /&gt;
這次修改的是加入 enter 鍵的功能選項。原本的輸入法按下 enter 後會輸出原本的英文字串。比如說輸入 yurenju 雖然剛開始會變成好像是亂打的字如下圖：&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/_iOO0fC4NKLE/TL7Mj9INuoI/AAAAAAAAI8w/76zQ1IsUEvA/s1600/enter_eng.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_iOO0fC4NKLE/TL7Mj9INuoI/AAAAAAAAI8w/76zQ1IsUEvA/s1600/enter_eng.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
不過當你按下 Enter 之後就會變成 yurenju。不過台灣的中文使用者有些比較習慣按下 Enter 後輸出的是第一個候選詞。所以小弟新增了一個小功能，讓使用者可以在設定裡面調整 Enter 鍵的功能。源碼在 &lt;a href="http://github.com/yurenju/ibus-pinyin"&gt;github&lt;/a&gt; 上，現在要使用必須直接編譯源碼。新的版本預設會讓按下 Enter 後輸出第一個候選字，不過也可以在設定裡面調整。&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/_iOO0fC4NKLE/TL7OHc03jWI/AAAAAAAAI80/WYMdIzFAOQc/s1600/Screenshot-%E5%81%8F%E5%A5%BD%E8%A8%AD%E5%AE%9A.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/_iOO0fC4NKLE/TL7OHc03jWI/AAAAAAAAI80/WYMdIzFAOQc/s400/Screenshot-%E5%81%8F%E5%A5%BD%E8%A8%AD%E5%AE%9A.png" width="295" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
另外在我 github 的版本也有把 shift + , 與 shift + . 重新 mapping 到全形的逗點跟句點了。接下來會看一些 issues 有哪些要幫忙解。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-44835227589853203?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/Axp0izLQceU" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/44835227589853203/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2010/10/ibus-pinyin-bopomofo-enter.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/44835227589853203?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/44835227589853203?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/Axp0izLQceU/ibus-pinyin-bopomofo-enter.html" title="ibus-pinyin-bopomofo 無調注音輸入法新增 enter 直接輸出第一個候選字" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_iOO0fC4NKLE/TL7Mj9INuoI/AAAAAAAAI8w/76zQ1IsUEvA/s72-c/enter_eng.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2010/10/ibus-pinyin-bopomofo-enter.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YEQ3s5eip7ImA9Wx5UFEo.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-7048784977427592765</id><published>2010-10-19T17:05:00.000+08:00</published><updated>2010-10-19T17:05:02.522+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-19T17:05:02.522+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="gdb" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><category scheme="http://www.blogger.com/atom/ns#" term="筆記" /><title>[筆記] gdb C++ 小技巧</title><content type="html">以前自己用 gdb 都是拿來 debug C 語言的程式，這次拿來對 C++ 除錯發現有些小地方要注意的。&lt;br /&gt;
&lt;br /&gt;
第一個是 &lt;b&gt;C++ 字串&lt;/b&gt;。平常印出 C 語言的字串只需要用 print str_var 就可以了，不過要印出 C++ 的字串則是要用 print str_var.c_str()。&lt;br /&gt;
&lt;br /&gt;
另外一個要注意的是 breakpoint 的設定方式。breakpoint 的設定可以用行號或者是 function name，不過如果在 C++ 除錯時如果有 namespace 必須要打出&lt;b&gt;完整的 name + class + method name&lt;/b&gt;。比如說 ibus 的 PYBopomofoEditor.cc 裡面有&amp;nbsp;BopomofoEditor::processBopomofo method，要設定中斷點就必須打&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;b PY::BopomofoEditor::processBopomofo(unsigned int, unsigned int, unsigned int)&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
我想你也會跟我一樣覺得打這串也太長了吧，不過 gdb 支援自動補齊，只要打 PY::Bo 之後按下 Tab 鍵就可以用自動補齊的方式快速的打完整串了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-7048784977427592765?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/P67JBCLpeNM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/7048784977427592765/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2010/10/gdb-c.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/7048784977427592765?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/7048784977427592765?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/P67JBCLpeNM/gdb-c.html" title="[筆記] gdb C++ 小技巧" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2010/10/gdb-c.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAGQH8-fSp7ImA9Wx5VGEo.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-1428751829090803830</id><published>2010-10-12T16:55:00.000+08:00</published><updated>2010-10-12T16:55:21.155+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-12T16:55:21.155+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="gdb" /><title>printf debug 大法？改用 gdb 取代 printf debug 方式</title><content type="html">這個東西 jserv 在好久以前的演講就提過，不過今天要用又找了一會才找到，筆記與此。&lt;br /&gt;
&lt;br /&gt;
很多時候在 debug 的時候只是要確定程式跑到那段時，大概有很大的機率會加入 printf 到程式碼裡面來進行這樣的 debug 動作。不過使用 printf 每次都要重新編譯源碼實在是有點麻煩，而使用 gdb print 資訊可以在不更動源碼也不會有每次都因為設定中斷點就停下來的問題。&lt;br /&gt;
&lt;br /&gt;
比如說有以下程式：&lt;br /&gt;
&lt;pre class="brush: c"&gt;switch (m_punct_mode) {
    case MODE_DISABLE:
        {
            g_assert (ch == IBUS_grave);
            ...
            update ();
        }
        break;
    case MODE_INIT:
        {
            m_text.clear ();
            ...
            m_cursor = 0;
        }
    case MODE_NORMAL:
        {
            m_text.insert (m_cursor, ch);
            ...
            update ();
        }
        break;
    default:
        g_assert_not_reached ();
    }
&lt;/pre&gt;&lt;br /&gt;
我們想在程式運行時知道到底跑到那個 switch case, 就可以用 gdb 來 print。其中的原理是利用中斷之後執行一小段 gdb 命令來達成。gdb 有個指令叫做 commands 可以在中斷後自動執行一小段 gdb 指令，所以如果我們使用 command 指令再配合 print 以及 continue 就可以做出類似 printf 的除錯功能。比如說第一個中斷點的設定方式則為：&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: bash"&gt;b editor.cc:4
commands
print "MODE_DISABLE"
continue
end
&lt;/pre&gt;&lt;br /&gt;
這樣執行時就可以讓 gdb 印出資訊達到 printf 的效果，但卻不用重新編譯源碼。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-1428751829090803830?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/mIAIMm5rIq0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/1428751829090803830/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2010/10/printf-debug-gdb-printf-debug.html#comment-form" title="3 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/1428751829090803830?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/1428751829090803830?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/mIAIMm5rIq0/printf-debug-gdb-printf-debug.html" title="printf debug 大法？改用 gdb 取代 printf debug 方式" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>3</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2010/10/printf-debug-gdb-printf-debug.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QNRXg-fCp7ImA9Wx5VE0k.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-1257253689889836005</id><published>2010-10-06T15:04:00.002+08:00</published><updated>2010-10-06T15:16:34.654+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-10-06T15:16:34.654+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ibus-pinyin-bopomofo" /><category scheme="http://www.blogger.com/atom/ns#" term="輸入法" /><category scheme="http://www.blogger.com/atom/ns#" term="注音" /><category scheme="http://www.blogger.com/atom/ns#" term="ibus" /><category scheme="http://www.blogger.com/atom/ns#" term="ibus-pinyin" /><category scheme="http://www.blogger.com/atom/ns#" term="拼音" /><title>Linux 無調注音輸入法 - ibus-pinyin-bopomofo</title><content type="html">前幾天，&lt;a href="http://pingyeh.blogspot.com/"&gt;Pingooo&lt;/a&gt;、&lt;a href="http://hychen.wuweig.org/"&gt;Hychen&lt;/a&gt;&amp;nbsp;在 TOSSUG 討論最近 Ubuntu 10.04 的 ibus 輸入法有很多 issues，然後又聊到對岸的拼音輸入法比起注音輸入法少打了聲調速度好像快很多之後，我們三個就想說是不是自己來修一下 ibus 的問題，順便看有沒有可能寫出無調的注音輸入法。&lt;br /&gt;
&lt;br /&gt;
無調注音輸入法的概念也很簡單，基本上跟使用新酷音用法差不多，但是不需要輸入一二三四聲，所以才稱爲無調注音。基本上拼音輸入法原本就不需要輸入聲調，理論上我們可以基於拼音輸入法把英文拼音轉換成注音這樣的基礎原理來創造無調注音輸入法。&lt;br /&gt;
&lt;br /&gt;
沒想到前幾天 hychen 丟出了一個對岸同胞作出以&lt;a href="http://www.byvoid.com/blog/ibus-bopomofo-1-3-9-features/"&gt;拼音爲基礎的注音輸入法&lt;/a&gt;，正巧是我們想要的無調注音輸入法！&lt;br /&gt;
&lt;br /&gt;
這個注音輸入法是基於 ibus-pinyin 所作的注音輸入法，雖然說目前正在研發還不是很穩定，不過基本上方向是與我們心目中的無調注音輸入法是相同的。要在 Ubuntu 10.04 安裝也是相當容易，輸入以下指令即可安裝：&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: bash"&gt;sudo add-apt-repository ppa:shawn-p-huang/ppa
sudo apt-get update
sudo apt-get install ibus-gtk ibus-qt ibus-pinyin ibus-pinyin-db-open-phrase
　
&lt;/pre&gt;&lt;br /&gt;
這兩天試用了一下發現有些問題先筆記起來，或許有機會可以提交到原作者的『&lt;a href="https://docs.google.com/document/edit?id=1x3JDrt4BuoupbK1p1jwyB1zSsu7eJcNxHnYlQO8hucU&amp;amp;hl=zh_TW#"&gt;注音模式用戶交互設計方案&lt;/a&gt;』，這些發現是基於一個新酷音使用者的意見回饋，或許拼音輸入法的使用者有更好的使用方式，只是我只試用兩天還沒發現罷了&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;輸入完畢後，如果輸入法候選字都正確時，不能直接按下 enter 鍵直接輸出，需要先按空白鍵再選擇第一組正確的候選字組纔可以輸入（或者是連按兩下空白鍵）。&lt;/li&gt;
&lt;li&gt;輸入完畢後直接按 enter 會直接出現剛剛敲過的所有按鍵，看起來像這樣：d0fux9vu;5ku;。這個似乎不是使用者預期的輸出&lt;/li&gt;
&lt;li&gt;以上兩點如果將 enter 鍵改成直接輸出正確的候選字會比較快速。&lt;/li&gt;
&lt;li&gt;按着 shift + , 或者 shift + . 出現的並不是全形的逗號以及句號，而是『《』以及『》』，感覺不符合使用者預期&lt;/li&gt;
&lt;li&gt;使用 ` 鍵叫出符號表的時候，如果已經設定選字鍵爲 asdfghjkl;，但是符號表的選字鍵依然是 1234567890&lt;/li&gt;
&lt;li&gt;輸入了一個句子後，可以用左右鍵移動到注音符號的任意位置，但不清除功能爲何。看起來似乎可以用來決定切字點，但是移到要切字的位置後按下空白選字，接下來的字會變成注音符號。例如要輸入：十全路十五號，需要切字在『十五』之間。如果移到十五中間按下空白鍵選字，整串字會變成『十全路十ㄨㄏㄠ』&lt;/li&gt;
&lt;li&gt;按下空白鍵選字後，必須要按下 page up/down 跳頁選字。此時方向鍵之中的上下鍵並沒有功能，建議可以用來取代&amp;nbsp;page up/down&lt;/li&gt;
&lt;li&gt;如果第一次選詞的時候沒有正確選擇，下次就算正確選詞也沒辦法更正。比如說我第一次選擇注音輸入法的時候選錯成『註音』，接下來就算我多選幾次注音也沒辦法讓註音慢慢消失。&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt;接下來希望可以跟開發者有些聯絡，來協助改善這個無調注音輸入法 :-)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-1257253689889836005?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/DgvxW5hYld4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/1257253689889836005/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2010/10/linux-ibus-pinyin-bopomofo.html#comment-form" title="4 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/1257253689889836005?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/1257253689889836005?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/DgvxW5hYld4/linux-ibus-pinyin-bopomofo.html" title="Linux 無調注音輸入法 - ibus-pinyin-bopomofo" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>4</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2010/10/linux-ibus-pinyin-bopomofo.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QGQ3k-fip7ImA9Wx5WFkg.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-3759779004728799695</id><published>2010-09-28T15:35:00.000+08:00</published><updated>2010-09-28T15:35:22.756+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-28T15:35:22.756+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Android" /><title>[筆記] android WebView 遇到網頁重導後開新視窗的問題</title><content type="html">塞個 WebViewClient 給他。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: java"&gt;WebView web = (WebView)findViewById(R.id.WebPages);
web.setWebViewClient(new WebViewClient());
&lt;/pre&gt;&lt;br /&gt;
最近會筆記些零碎的 android 問題。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-3759779004728799695?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/YeSiQS1Uxec" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/3759779004728799695/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2010/09/android-webview.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/3759779004728799695?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/3759779004728799695?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/YeSiQS1Uxec/android-webview.html" title="[筆記] android WebView 遇到網頁重導後開新視窗的問題" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2010/09/android-webview.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0IEQ3w4fCp7ImA9Wx5XGEg.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-910424818290128814</id><published>2010-09-19T07:42:00.003+08:00</published><updated>2010-09-19T08:18:22.234+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-19T08:18:22.234+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="GNOME" /><category scheme="http://www.blogger.com/atom/ns#" term="icos" /><category scheme="http://www.blogger.com/atom/ns#" term="gnome-shell" /><title>吃了蘑菇的 gnome-shell</title><content type="html">&lt;iframe class="youtube-player" frameborder="0" height="450" src="http://www.youtube.com/embed/33iNA9tS6-I" type="text/html" width="580"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&lt;b&gt;會變大～ &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
上面這個影片主要是 demo 目前 gnome-shell 的 extension 可以控制 gnome-shell 裡面的任意元件，所以才可以做出讓 calendar 放大的外掛。有興趣可以看一下&lt;a href="http://gist.github.com/586175"&gt;源碼&lt;/a&gt;。&lt;br /&gt;
&lt;br /&gt;
這是在 ICOS 的講題 Javascript in Linux Desktop，雖然跟 COSCUP 講的題目一樣，不過經過了一個月當然是要升級一下啦。&lt;br /&gt;
&lt;br /&gt;
這次不一樣的地方還有加入了 seedkit 的部份。不過瞄準的是略有開發經驗的聽眾，所以技術細節其實並沒有提很多。這次 seedkit 的範例用了 seedkit 原本就內附的 dbus, libnotify 範例外，也加了使用 wnck, 用 javascript 控制視窗的範例。&lt;br /&gt;
&lt;br /&gt;
下面這個影片依據 demo 用 dbus 控制 Ubuntu music player - rhythmbox 的上下首變更、libnotify 跳出通知訊息、以及用 wnck 取得視窗標題以及最後的操作所有視窗最小化。&lt;br /&gt;
&lt;br /&gt;
&lt;iframe class="youtube-player" frameborder="0" height="450" src="http://www.youtube.com/embed/cL_JPbVvFuk" type="text/html" width="580"&gt;&lt;/iframe&gt;&lt;br /&gt;
&lt;br /&gt;
而操作這些動作的全部都是使用 html 與 javascript, 範例源碼如下：&lt;br /&gt;
HTML 部份&lt;br /&gt;
&lt;pre class="brush: html"&gt;&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
    &amp;lt;link rel="stylesheet" href="./ui.css" type="text/css" media="all" /&amp;gt;
    &amp;lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="./ui.js"&amp;gt;&amp;lt;/script&amp;gt;

    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
    &amp;lt;div class="demo"&amp;gt;
        &amp;lt;img id="cover-art"&amp;gt;&amp;lt;/img&amp;gt;
        &amp;lt;div id="prev-button" class="button"&amp;gt;Prev&amp;lt;/div&amp;gt;
        &amp;lt;div id="next-button" class="button"&amp;gt;Next&amp;lt;/div&amp;gt;
        &amp;lt;div id="notify-button" class="button"&amp;gt;notify&amp;lt;/div&amp;gt;
        &amp;lt;div id="wins-button" class="button"&amp;gt;get wins&amp;lt;/div&amp;gt;
        &amp;lt;div id="min-button" class="button"&amp;gt;minimize&amp;lt;/div&amp;gt;
        &amp;lt;div id="file-uri"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;ul id="windows-list"&amp;gt;&amp;lt;/ul&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
Javascript 部份：&lt;br /&gt;
&lt;pre class="brush: js"&gt;Seed.include("./dbus-rhythmbox.js");

function sendNotification(summary, body, timeOut) {
 var notification = new Notify.Notification({summary:summary, body:body});
 notification.set_timeout(timeOut);
 notification.show();
}

function getWindows () {
        Wnck = imports.gi.Wnck;
        Gtk = imports.gi.Gtk
        Gtk.init(Seed.argv);

        var screen = Wnck.Screen.get_default();
        while (Gtk.events_pending())
            Gtk.main_iteration();
        return screen.get_windows();
}

$(document).ready(function(){
 var shell = new RhythmboxShell();
 var player = new RhythmboxPlayer();

 Notify = imports.gi.Notify;

 $("#wins-button").click( function() {
        var wins = getWindows();
        Seed.print (wins.length);
        for (var i = 0; i &amp;lt; wins.length; i++) {
            Seed.print (wins[i].get_name());
            $("#windows-list").append("&amp;lt;li&amp;gt;" + wins[i].get_name() + "&amp;lt;/li&amp;gt;");
        }
    });

 $("#min-button").click( function() {
        var wins = getWindows();
        for (var i = 0; i &amp;lt; wins.length; i++) {
            wins[i].minimize();
        }
    });
 
    Notify.init("Webview");
 $("#notify-button").click( function() {
  sendNotification("Raised from a WebView","Raised from a WebView", 500); 
  Seed.print("clicked");
 });

 //playeplayer.getVolumeRemote(function (volume) {print("oi")});
 $("#next-button").click(function(){
  player.nextRemote();
 });

 $("#prev-button").click(function(){
  player.previousRemote();
 });

 player.connect("playingUriChanged", 
         function(emitter, uri){
   //var song = shell.getSongPropertiesRemoteSync(uri);
   //print(song); 
         });

 player.connect("playingSongPropertyChanged", 
         function(emitter, title, property_name, old_value, new_value){
   if (property_name == "rb:coverArt-uri")
    $("#cover-art").attr('src', new_value);
 });
});
&lt;/pre&gt;&lt;br /&gt;
dbus 的操作一樣的是比較複雜，你可以參考&lt;a href="http://yurinfore.blogspot.com/2010/09/seedkit-web-technology-desktop.html"&gt;上一篇&lt;/a&gt;。不過相對起來 wnck, libnotify 就簡單許多。而這整個操作，全部都可以使用 jquery 的方式操作，撰寫起桌面應用程式就跟網頁一樣。&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
最後是 slide。謝謝昨天大家的聆聽 &lt;img border="0" height="25" src="http://1.bp.blogspot.com/_iOO0fC4NKLE/TJVVlWDrMQI/AAAAAAAAI54/pwJiW_STygc/s200/mario_mushroom.png" width="25" /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div id="__ss_5230896" style="width: 425px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/yurenju/javascript-in-linux-desktop-icos-ver" title="Javascript in linux desktop (ICOS ver.)"&gt;Javascript in linux desktop (ICOS ver.)&lt;/a&gt;&lt;/strong&gt;&lt;object height="355" id="__sse5230896" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=javascript-in-linux-desktop-100918181247-phpapp01&amp;stripped_title=javascript-in-linux-desktop-icos-ver&amp;userName=yurenju" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse5230896" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=javascript-in-linux-desktop-100918181247-phpapp01&amp;stripped_title=javascript-in-linux-desktop-icos-ver&amp;userName=yurenju" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
&lt;div style="padding: 5px 0 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/yurenju"&gt;yurenju&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-910424818290128814?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/8NV99LkTOrk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/910424818290128814/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2010/09/gnome-shell.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/910424818290128814?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/910424818290128814?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/8NV99LkTOrk/gnome-shell.html" title="吃了蘑菇的 gnome-shell" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/33iNA9tS6-I/default.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2010/09/gnome-shell.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUIHR3Y-cSp7ImA9Wx5QGEk.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-5033158754041178333</id><published>2010-09-07T15:12:00.000+08:00</published><updated>2010-09-07T15:12:16.859+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-09-07T15:12:16.859+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="seed" /><category scheme="http://www.blogger.com/atom/ns#" term="GNOME" /><category scheme="http://www.blogger.com/atom/ns#" term="seedkit" /><title>seedkit - 用 web technology 撰寫 desktop application</title><content type="html">繼上次 COSCUP 講了 Javascript in linux desktop 後，最近又在看之前 penk 跟我介紹的 seedkit，還有會後 sleepnova 跟我提到一些 java 上有些 javascript implementation 的實做，去慶功宴的時候阿修又提了好幾個 javascript 寫 desktop application 的 framework，才知道這個部份已經蠻多人在做了。&lt;br /&gt;
&lt;br /&gt;
不過這次會議也有另外一個感想，就是 web developer 還是比較希望維持原有的開發模式，而不僅只是使用 javascript 語言來撰寫程式。翻開 seed/gjs 寫的 javascript 源碼，開發的思維其實跟 python 差不多，幾乎都可以從 python 無痛轉換了。&lt;br /&gt;
&lt;br /&gt;
而 seedkit 就是打算維持原本 web application 的開發模式而設計的工具。在 seedkit-viewer 的 example 裡面提供了一些有趣的範例。比如說 dbus-rhythmbox &amp;nbsp;這個範例，他透過 dbus 的方式控制歌曲的上、下首切換。&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://4.bp.blogspot.com/_iOO0fC4NKLE/TIXZkQXlvbI/AAAAAAAAI4I/0CMSwat9XlU/s1600/Screenshot+(1).png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="372" src="http://4.bp.blogspot.com/_iOO0fC4NKLE/TIXZkQXlvbI/AAAAAAAAI4I/0CMSwat9XlU/s640/Screenshot+(1).png" width="640" /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
右邊的 seedkit-viewer 視窗裡面的 next/previous 可以操作 rhythmbox 上、下首。這個程式與 rhythmbox 是兩個獨立的程式，而不是 rhythmbox 的外掛。&lt;br /&gt;
&lt;br /&gt;
這個功能可以在各種語言用 dbus 實做出來。不過在 Seedkit 的實做方式則是比較近乎 web application 的開發方式。首先我們看源碼中的 ui.html （沒錯是 HTML 檔案）。&lt;br /&gt;
&lt;br /&gt;
&lt;pre class="brush: html"&gt;&amp;lt;html&amp;gt;
    &amp;lt;head&amp;gt;
    &amp;lt;link rel="stylesheet" href="./ui.css" type="text/css" media="all" /&amp;gt;
    &amp;lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="./ui.js"&amp;gt;&amp;lt;/script&amp;gt;

    &amp;lt;/head&amp;gt;
    &amp;lt;body&amp;gt;
    &amp;lt;div class="demo"&amp;gt;
        &amp;lt;img id="cover-art"&amp;gt;&amp;lt;/img&amp;gt;
        &amp;lt;div id="prev-button" class="button"&amp;gt;Prev&amp;lt;/div&amp;gt;
        &amp;lt;div id="next-button" class="button"&amp;gt;Next&amp;lt;/div&amp;gt;
        &amp;lt;div id="file-uri"&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
基本上就是使用 jquery 函式庫，並引入了 ui.js 這個 javascript。接下來是 ui.js。&lt;br /&gt;
&lt;pre class="brush: js"&gt;Seed.include("./dbus-rhythmbox.js");

$(document).ready(function(){

var shell = new RhythmboxShell();
var player = new RhythmboxPlayer();

//playeplayer.getVolumeRemote(function (volume) {print("oi")});

$("#next-button").click(function(){
 player.nextRemote();
});

$("#prev-button").click(function(){
 player.previousRemote();
});


player.connect("playingUriChanged", 
        function(emitter, uri){
  //var song = shell.getSongPropertiesRemoteSync(uri);
  //print(song); 
        });

player.connect("playingSongPropertyChanged", 
        function(emitter, title, property_name, old_value, new_value){
  if (property_name == "rb:coverArt-uri")
   $("#cover-art").attr('src', new_value);
});

});
&lt;/pre&gt;&lt;br /&gt;
這段也相當簡單，就是按下 next 或 previous 之後去呼叫 player.nextRemote/previousRemote，並且使用了 jquery 的語法。至於 player 則定義於 &lt;a href="http://gitorious.org/~scaroo/seedkit/seedkit-viewer/blobs/master/examples/dbus/rhythmbox/dbus-rhythmbox.js"&gt;dbus-rhythmbox.js&lt;/a&gt; 裡面。&lt;br /&gt;
&lt;br /&gt;
另外，這個範例為了方便的操作 dbus，所以做了一個 wrapper 在 &lt;a href="http://gitorious.org/~scaroo/seedkit/seedkit-viewer/blobs/master/examples/dbus/rhythmbox/lang-local.js"&gt;dbus-local.js&lt;/a&gt;，有興趣的話可以翻一下，特別是把 next mapping 到 nextRemote 可以翻一下&amp;nbsp;proxifyPrototype 這個函式。&lt;br /&gt;
&lt;br /&gt;
基本上 seedkit 讓開發桌面程式的方式盡可能的接近網頁應用程式，並且還是可以使用系統的 API 去作檔案 IO、網路存取、dbus、notification 之類的系統 API，感覺起來是 GTK 裡面比較完整的解決方案。&lt;br /&gt;
&lt;br /&gt;
而更棒的是 seedkit 也可以當作一個 Gtk Widget，你可以將這些程式片段嵌入在 UI 的一部分，這也保持了開發彈性，開發者還是可以選用其他的 UI 函式庫如 Clutter 或是 GTK，而不是只能使用 Web Application 的 View。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-5033158754041178333?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/YyUmZKDRwO4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/5033158754041178333/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2010/09/seedkit-web-technology-desktop.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/5033158754041178333?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/5033158754041178333?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/YyUmZKDRwO4/seedkit-web-technology-desktop.html" title="seedkit - 用 web technology 撰寫 desktop application" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_iOO0fC4NKLE/TIXZkQXlvbI/AAAAAAAAI4I/0CMSwat9XlU/s72-c/Screenshot+(1).png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2010/09/seedkit-web-technology-desktop.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEADQHw4cCp7ImA9Wx5SGU4.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-8472893992849584159</id><published>2010-08-16T13:32:00.000+08:00</published><updated>2010-08-16T13:32:51.238+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-16T13:32:51.238+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="gnome.asia" /><category scheme="http://www.blogger.com/atom/ns#" term="coscup" /><title>Javascript in Linux Desktop 簡報</title><content type="html">COSCUP 結束了，感謝各位支持！簡報檔在此，授權為 &lt;a href="http://creativecommons.org/licenses/by/3.0/deed.zh_TW"&gt;CC 姓名標示 3.0 Unported&lt;/a&gt;。&lt;br /&gt;
&lt;br /&gt;
&lt;div id="__ss_4977528" style="width: 425px;"&gt;&lt;strong style="display: block; margin: 12px 0 4px;"&gt;&lt;a href="http://www.slideshare.net/yurenju/javascript-in-linux-desktop" title="Javascript in Linux Desktop"&gt;Javascript in Linux Desktop&lt;/a&gt;&lt;/strong&gt;&lt;object height="355" id="__sse4977528" width="425"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=javascript-in-linux-desktop-100816002531-phpapp01&amp;stripped_title=javascript-in-linux-desktop" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed name="__sse4977528" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=javascript-in-linux-desktop-100816002531-phpapp01&amp;stripped_title=javascript-in-linux-desktop" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
&lt;div style="padding: 5px 0 12px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/yurenju"&gt;yurenju&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;
範例檔在此：&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href="http://gist.github.com/484314"&gt;js-gallery&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gist.github.com/526476"&gt;gnome-shell extension&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-8472893992849584159?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/SDk4PWYSZCk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/8472893992849584159/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2010/08/javascript-in-linux-desktop.html#comment-form" title="5 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/8472893992849584159?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/8472893992849584159?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/SDk4PWYSZCk/javascript-in-linux-desktop.html" title="Javascript in Linux Desktop 簡報" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><thr:total>5</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2010/08/javascript-in-linux-desktop.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CE8ERH06eSp7ImA9Wx5TGE0.&quot;"><id>tag:blogger.com,1999:blog-7050224734475821462.post-2623478852263575754</id><published>2010-08-03T10:33:00.000+08:00</published><updated>2010-08-03T10:33:25.311+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-03T10:33:25.311+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="javascript" /><category scheme="http://www.blogger.com/atom/ns#" term="GNOME" /><category scheme="http://www.blogger.com/atom/ns#" term="coscup" /><title>[talk] Javascript in Linux Desktop</title><content type="html">最近在這邊發了幾篇 Javascript 跟 GNOME Desktop 相關的文章，其實是為了 COSCUP 的分享『&lt;a href="http://coscup.org/2010/zh-tw/program/abstracts#javascript-in-linux-desktop"&gt;Javascript in Linux Desktop&lt;/a&gt;』作準備。如果你也對 Javascript 撰寫桌面應用程式有興趣，歡迎在 COSCUP 第二天 (8/15) 下午 4:00-4:30 到第二會議室來聽我的分享。(喔，我知道同一個時段也有很精彩的 Jserv 演講啦 XD)&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_iOO0fC4NKLE/TFd_s1rD2fI/AAAAAAAAI1w/yRcnBX5qthw/s1600/Screenshot-javascript-in-linux-desktop.odp+-+OpenOffice.org+Impress.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="313" src="http://2.bp.blogspot.com/_iOO0fC4NKLE/TFd_s1rD2fI/AAAAAAAAI1w/yRcnBX5qthw/s400/Screenshot-javascript-in-linux-desktop.odp+-+OpenOffice.org+Impress.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7050224734475821462-2623478852263575754?l=yurinfore.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/YurensInfoArea/~4/0Q7eo4WImQ8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://yurinfore.blogspot.com/feeds/2623478852263575754/comments/default" title="張貼意見" /><link rel="replies" type="text/html" href="http://yurinfore.blogspot.com/2010/08/talk-javascript-in-linux-desktop.html#comment-form" title="0 個意見" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/2623478852263575754?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7050224734475821462/posts/default/2623478852263575754?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/YurensInfoArea/~3/0Q7eo4WImQ8/talk-javascript-in-linux-desktop.html" title="[talk] Javascript in Linux Desktop" /><author><name>Yuren Ju</name><uri>https://profiles.google.com/118313872024612853681</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-oIq_w7efYt8/AAAAAAAAAAI/AAAAAAAAJv4/6l3I6WTGzR4/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_iOO0fC4NKLE/TFd_s1rD2fI/AAAAAAAAI1w/yRcnBX5qthw/s72-c/Screenshot-javascript-in-linux-desktop.odp+-+OpenOffice.org+Impress.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://yurinfore.blogspot.com/2010/08/talk-javascript-in-linux-desktop.html</feedburner:origLink></entry></feed>

