2008年11月9日 星期日

Ubuntu 8.10 at Thinkpad T61

前幾天把 Ubuntu 8.10 Desktop Edition 64Bit 版本昇級.
昇級方法可以參考官方的這篇說明: http://www.ubuntu.com/getubuntu/upgrading

基本上所有 T61 上的硬體都能正確抓到, 包含先前提到的 Intel 4965AGN wireless LED 也一併改善解決.

然而 nvidia driver 由於 restricted driver 內建是 177.80 , 所以踩到了一個雷.


無法登出或 Ctrl+Alt+Backspace:

[G86GL] Latest NVIDIA drivers: X hangs with blank screen after logout.
阿土伯採用的是延長 GDM 等待 nvidia driver 回應的時間.
也就是請修改 /etc/gdm/gdm.conf 中的 GdmXserverTimeout 將它加大到 30 以上, 阿土伯目前使用 40.
沒有太大問題再發生.


2D performance 太慢:
nvidia driver 在 linux 上 2D 效能一直不怎麼樣, 當然官方也一直在改進, 由於 8.10 直接跳到了 177.80 版, 所以可以
使用一些新的設定, 可以參考:  http://www.nvnews.net/vbulletin/showthread.php?t=115916 討論串.
或直接在 /etc/X11/xorg.conf 加入
Option "PixmapCacheSize" "1000000"
Option "AllowSHMPixmaps" "0"

並在 ~/.gnomerc 加入
nvidia-settings -a InitialPixmapPlacement=2 -a GlyphCache=1

可以獲得很大的改善.
可以利用 firefox 打開 addons 管理視窗, 然後利用 mouse wheel scroll 看看差別有多大...




2008年9月16日 星期二

iGoogle Tab RSS 小工具 Bug Fixed

感謝幾位網友的提醒, 阿土伯忘了現在 iGoogle 已不建議並(禁用?) html-inline 的 content 了..
所以造成了幾個小工具已不能使用.. 已修復完異.. 謝謝大家愛用..

什麼是 Tab RSS 請見下圖及參考說明:


使用說明及介紹:
iGoogle Tab RSS 小工具


2008年9月1日 星期一

李斯諫逐客書

學生時唸到的古文, 沒想到在現在會這麼有感覺.
本土/外來/挺誰/嗆誰/反誰/護誰 一再操作這樣議題昇高人民對立是否得宜...
政治也是一種專業, 程式設計亦然.
當批評別人的設計有問題時, 能謙虛的自省自己的專業, 是否也出現了相同的問題, 並容納多元的意見以及不同團隊間的合作...
共勉之~

##CONTINUE##

李斯諫逐客書    李 斯
  秦宗室大臣皆言秦王曰:「諸侯人來事秦者,祇為其主遊間秦耳,請一切逐客。」李斯
議亦在逐中。斯乃上書曰:「臣聞吏議逐客,竊以為過矣。」
  「昔穆公求士,西取由余於戎,東得百里奚於宛,迎蹇叔於宋,求丕豹,公孫支於晉。
此五子者,不產於秦,而穆公用之,井國二十,遂霸西戎。孝公用商鞅之法,移風易俗,民
以殷盛,國以富彊,百姓樂用,諸侯親服獲楚,魏之師,舉地千里,至今治強。惠王用張儀
之計,拔三川之地,西井巴蜀,北收上郡,南取漢中。包九夷,制鄢郢,東據成皋之險,割
膏腴之壤,遂散六國之從,使之西面事秦,功施到今。昭王得范雎,廢穰侯,逐華陽,強公
室,杜私門,蠶食諸侯,使秦成帝業。此四君者,皆以客之功。由此觀之,客何負於秦哉!
向使四君卻客而不內,疏士而不與,是使國無富利之實,而秦無強大之名也。」
  「今陛下致昆山之玉,有隨和之寶,垂明月之珠,服太阿之劍,乘纖離之馬,建翠鳳之
旗,樹靈鼉之鼓:此數寶者,秦不生一焉,而陛下說之,何也?必秦國之所生然後可,則是
夜光之璧,不飾朝廷;犀象之器,不為玩好;鄭衛之女,不充後官;而駿馬駃騠,不實外廄
;江南金錫不為用;西蜀丹青不為采。所以飾後官,充下陳,娛心意,說耳目者,必出於秦
然後可,則是宛珠之簪,傅璣之珥,阿縞之衣?錦繡之飾,不進於前;而隨俗雅化,佳冶窈
窕,趙女不立於側也。夫擊甕叩缶,彈箏搏髀,而歌呼嗚嗚快耳者,真秦之聲也;鄭衛桑間
,韶虞武象者,異國之樂也。今棄擊甕而就鄭衛,退彈箏而取韶虞,若是者何也?快意當前
,適觀而已矣。今取人則不然,不問可否,不論曲直,非秦者去,為客者逐,然則是所重者
在乎笆樂珠玉,而所輕者在乎人民也。此非所以跨海內,致諸侯之術也。」
  「臣聞地廣者粟多,國大者人眾,兵強者士勇。是以泰山不讓士壤,故能成其大;河海
不擇細流,故能就其深;王者不卻眾庶,故能明其德。是以地無四,方民無異國,四時充美
,鬼神降福
。此五帝,三王之所以無敵也。今乃棄黔首以資敵國,卻賓客以業諸侯,使天下
之士退而不敢西向,裹足不入秦,此所謂『藉寇兵而齎盜糧』者也。」
  「夫物不產於秦,可寶者多;士不產於秦,而願忠者眾。今逐客以資敵國,損民以益讎
,內自虛而外樹怨於諸侯,求國無危,不可得也
。」
  秦王乃除逐客之令,復李斯官。
大意:
   (一)自「秦宗室大臣皆言秦王曰」至「竊以為過矣」
     說明逐客為過。
   (二)自「昔穆公求士」至「而秦無強大之名也」
     (舉繆公、孝公、惠王、昭王例)說明客有功於秦(暗示逐客為不智)。
   (三)自「今陛下致昆山之玉」至「致諸侯之術也」
     說明逐其民人而取其色樂珠玉,非王霸者之所為(以色樂珠玉之取襯客之去為不
     合理)。
   (四)自「臣聞地廣者粟多」至「此所謂藉寇兵而齎盜糧者也」
     說明卻客而為他國所用,非秦之福(以逐客資敵業諸侯說明爭取人才的重要性)
     。
   (五)自「夫物不產於秦」至「不可得也」
     說明逐客則國危。
   (六)自「秦王乃除逐客之令」至「復李斯官」
     記敘李斯復官。

2008年8月18日 星期一

GREUtils 1.1 in trunk

GREUtils 1.1 已經 update 到 http://greutils.googlecode.com/svn/trunk 中, 有興趣參考 Source Code 或使用, 請利用 svn checkout .

GREUtils 是一個 XULRunner / Firefox extensions Javascript Utilities Libraries.
1.0 到 1.1 基本上是全面改寫, GREUtils 1.1 提供以下功能:
  • Object extend function
  • include / include_once specified URL script.
  • XPCOM utilities
  • Charset Convert
  • Preferences Services
  • File IO
  • Dialog utilities (all XPCOM implemented, can use in javascript code modules)
  • Controller and CommandDispatcher? Helper
  • Cryphto Hash Utilities – md5 / sha1 /sha256
  • JSON encode / decode use XPCOM implemented (VERY FASTer then json.org's javascript version)
  • Threading – Native Multi-Threading support
  • JavaScript code modules support

其它改變:
  • GREUtils 1.1 全部改寫了 1.0 的 inline document , 由 ScriptDoc 改成了 jsdoc 格式, 以方便產生出 API Reference.
  • Makefile for linux user , 以方便產生 minified / packed / jsmodues / jsdoc 等 distribution files.
  • singleton support
  • inherits / namespace support (many idea and source from goog javascript libraries).
Project URL: http://code.google.com/p/greutils/

API References: http://greutils.googlecode.com/svn/trunk/jsdoc/index.html

2008年7月4日 星期五

Threading in Firefox 3

Firefox 3 (Gecko 1.9) 新增了許多特色 (詳見 ), 其中一項重要的特色, 便是導入了 Thread Manager 機制.

##CONTINUE##

在 Firefox 3 以前, 我們要讓 Javascript 程式在背景執行, 最簡單的方式便是利用 setTimeout / setInterval 方式:


function backgroundTask() {
// Perform a small amount of work

window.setTimeout(arguments.callee, 100);
}

window.setTimeout(backgroundTask, 100);

以上的方式雖然可以把程式丟到背景執行, 然而, 它依然只是在主執行緒(mainThread)中, 以非同步的方式執行.

Firefox 3 後, 導入了 Thread Manager , 讓我們可以撰寫平台相關的真正多執行緒程式.

要實作多執行緒 Javascript 程式,本身必須是 XPCOM Object, 且實作 nsIRunnable 介面(和 Java Thread 很像不是嗎?).
詳細範例可參考 Thread Manager nsIThreadManager .

Thread Utils:
雖然 Firefox 3 已經大大簡化了多執行緒程式的寫作方式(且很有 Java 風格), 但就 Javascript 來說, 就顯的有些麻煩, 我們要為每一個要執行的程式, 一一實作成 XPCOM Object 也是一件很煩人的事..
阿土伯在 GREUtils Rewriting 計劃中, 為 Threading 做了一些封裝, 讓您可以比較容易且直覺的使用 Firefox 3 所帶來的 Multi-Threading 這份大禮.

有關 Thread 部份的 Code 如下, 已修改過可以獨立運作於 GREUtils 整個專案之外:

/**
* Thread - is simple and easy use Thread Manager APIs libraries for GRE (Gecko Runtime Environment).
* ONLY Work with Firefox 3 or XULRunner 1.9
*
* @public
* @name GREUtils.Thread
* @namespace GREUtils.Thread
*/
var GREUtils = GREUtils || {};

GREUtils.Thread = {

_threadManager: Components.classes["@mozilla.org/thread-manager;1"]
.getService(Components.interfaces.nsIThreadManager),

_mainThread: null,

_workerThread: null,

reportError: function(err){
Components.utils.reportError(err);
}
};


/**
* getThreadManager
*
* @public
* @static
* @function
* @return {Object} nsIThreadManager
*/
GREUtils.Thread.getThreadManager = function(){
return this._threadManager;
};


/**
* getMainThread
*
* @public
* @static
* @function
* @return {Object} nsIThread main thread
*/
GREUtils.Thread.getMainThread = function(){
if (this._mainThread == null) {
this._mainThread = GREUtils.Thread.getThreadManager().mainThread;

// extends magical method to worker thread
// this._workerThread.dispatchMainThread = GREUtils.Thread.dispatchMainThread;
}
return this._mainThread;
};


/**
* dispatchMainThread
*
* @public
* @static
* @function
* @return {Object} nsIThreadManager
* @param {Object} aRunnable
* @param {Object} aType
*/
GREUtils.Thread.dispatchMainThread = function(aRunnable, aType) {
var mainThread = GREUtils.Thread.getMainThread();
var aType = aType || mainThread.DISPATCH_NORMAL;
try {
mainThread.dispatch(aRunnable, aType);
}catch (err) {
GREUtils.Thread.reportError(err);
}
};


/**
* dispatchWorkerThread
*
* @public
* @static
* @function
* @return {Object} nsIThreadManager
* @param {Object} workerThread
* @param {Object} aRunnable
* @param {Object} aType
*/
GREUtils.Thread.dispatchWorkerThread = function(workerThread, aRunnable, aType) {
var aType = aType || workerThread.DISPATCH_NORMAL;
try {
workerThread.dispatch(aRunnable, aType);
}catch (err) {
GREUtils.Thread.reportError(err);
}
};

/**
* getWorkerThread in pool
*
* @public
* @static
* @function
* @return {Object} nsIThread worker thread
*/
GREUtils.Thread.getWorkerThread = function(){
// get presist work thread
// will not create new worker thread
if (this._workerThread == null) {
this._workerThread = GREUtils.Thread.getThreadManager().newThread(0);

// extends magical method to worker thread
// this._workerThread.dispatchMainThread = GREUtils.Thread.dispatchMainThread;
}
return this._workerThread;
};


/**
* createWorkerThread - create new worker thread.
*
* @public
* @static
* @function
* @return {Object} nsIThread worker thread
*/
GREUtils.Thread.createWorkerThread = function(){
// create new worker thread
var worker = GREUtils.Thread.getThreadManager().newThread(0);

// extends magical method to worker thread
//worker.dispatchMainThread = GREUtils.Thread.dispatchMainThread;

return worker;
};


/**
* CallbackRunnableAdapter
*
* @public
* @class
* @param {Object} func
* @param {Object} data
*/
GREUtils.Thread.CallbackRunnableAdapter = function(func, data) {
this._func = func;
this._data = data;
};

GREUtils.Thread.CallbackRunnableAdapter.prototype = {

get func() {
return this._func;
},

set func(func){
this._func = func || null;
},

get data() {
return this._data;
},

set data(data){
this._data = data || null;
},

run: function() {
try {
if (this.func) {
if(this.data) this.func(this.data);
else this.func();
}
} catch (err) {
Components.utils.reportError(err);
}
},

QueryInterface: function(iid) {
if (iid.equals(Components.Interfaces.nsIRunnable) || iid.equals(Components.Interfaces.nsISupports)) {
return this;
}
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};


/**
* WorkerRunnableAdapter
*
* @public
* @class
* @param {Object} func
* @param {Object} callback
* @param {Object} data
*/
GREUtils.Thread.WorkerRunnableAdapter = function(func, callback, data) {
this._func = func;
this._callback = callback;
this._data = data;

if(arguments.length == 2 ) {
this._data = callback;
this._callback = null;
}
};

GREUtils.Thread.WorkerRunnableAdapter.prototype = {

get func() {
return this._func;
},

set func(func){
this._func = func || null;
},

get callback() {
return this._callback;
},

set callback(callback){
this._callback = callback || null;
},

get data() {
return this._data;
},

set data(data){
this._data = data || null;
},

run: function() {
try {
var result = null;
if (this.func) {
if(this.data) result = this.func(this.data);
else result = this.func();
}

if (this.callback) {
GREUtils.Thread.dispatchMainThread(new GREUtils.Thread.CallbackRunnableAdapter(this.callback, result));
}
} catch (err) {
Components.utils.reportError(err);
}

},

QueryInterface: function(iid) {
if (iid.equals(Components.Interfaces.nsIRunnable) || iid.equals(Components.Interfaces.nsISupports)) {
return this;
}
throw Components.results.NS_ERROR_NO_INTERFACE;
}
};


/**
* createWorkerThreadAdapter
*
* @public
* @static
* @function
* @param {Object} workerFunc
* @param {Object} callbackFunc
* @param {Object} data
*/
GREUtils.Thread.createWorkerThreadAdapter = function(workerFunc, callbackFunc, data) {

return new GREUtils.Thread.WorkerRunnableAdapter(workerFunc, callbackFunc, data);
};


使用方式:
利用 GREUtils.Thread.getMainThread() 可以取得主執行緒.
利用 GREUtils.Thread.createWorkerThread() 產生一個新的執行緒.

WorkerThreadAdapter:
則是用以簡化自行撰寫 worker / callback 二個 XPCOM Object, 取而代之的是二個 Function handle 以及要傳入 worker thread 的資料.


var worker = GREUtils.Thread.createWorkerThread();
var execute = GREUtils.Thread.createWorkerThreadAdapter(
/* worker function */
function(data) {
var result = 0;
var i = 0;

while(i <= data) {
result += i;
i++;
}
return result;
},
/* callback function */
function(result) {
alert('sum = ' + result);
},
/* data to worker function */
10000
);

GREUtils.Thread.dispatchWorkerThread(worker, execute);



註1:
Firefox3 的 Thread 由於是以 XPCOM 實作, 所以您只能用於 extension addons 寫作或是 XULRunner 專案中, 如果您需要在一般 Web Application 中使用多執行緒, 可以參考 Google Gears 的 WorkerPool 實作.

註2:
請特別注意 The Thread Manager 那篇的這句重要的警告.
Note: The DOM is not thread safe. You must not access the DOM or user interface from background threads. Doing so will likely crash.
其中要再注意的是, alert() 也是 DOM global scope 哦, 如果您在 background threads 用了 alert(), Firefox 3 也是會當給你看地.


忙裡偷閒寫下本篇, 內容有點雜亂簡單, 但還是希望對大家有幫助.

2008年5月11日 星期日

Processing.js

Processing.js. jQuery 作者 John Resig’s 將 processing.org Java implementation's Processing Language port to JavaScript and Canvas.

而且實測, 在 Firefox 3 執行的很完美, 真是有夠強.

有興趣的可以玩玩 Processing.js 的 Basic Demo.
和 processing.org java 版的 Basic Demo.
只能說..太酷了..

其中有幾樣和 Processing Language 無關的 javascript 實作, 也很值得研究.

  • Types and type casting
  • Classes
  • Method overloading and multiple constructors
  • Inheritance

2008年5月2日 星期五

Nimbus Theme on Ubuntu 8.04


Nimbus ( 各組件詳細 Nimbus SPEC ) 是 Sun Solaris Desktop 預設的就相當有質感的 Theme . 在未來的 JDK 6u10 中也將加入 Nimbus LookAndFeel.
所以利用這次重裝 Ubuntu 8.04 之餘, 順便把 Nimbus GTK2 engine 以及 Icons-theme 加入 Ubuntu 8.04 中.

阿土伯目前的 Ubuntu ScreenShot:


Compile and Install:
首先請先確認您有安裝打包 dpkg 相關的開發環境

sudo apt-get install fakeroot dpkg-dev devscripts icon-naming-utils

接下來就是下載 Nimbus 最新的 0.0.9 Source, 以及 deb 的 patch 包.

wget -c http://dlc.sun.com/osol/jds/downloads/extras/nimbus-0.0.9.tar.bz2
wget -c http://zap.tartarus.org/~ds/debian/dists/sid/main/source/nimbus_0.0.6-1.diff.gz


Compile:

tar xf nimbus-0.0.9.tar.bz2
cd nimbus-0.0.9
zcat ../nimbus_0.0.6-1.diff.gz | patch -p1
chmod +x debian/rules
debchange -v 0.0.9-1
sudo apt-get build-dep
fakeroot dpkg-buildpackage -us -uc

在一陣等待後, 您應該會在您的家目錄得到二個deb, (gtk2-engines-nimbus_0.0.6-1_i386.deb / nimbus-icon-theme_0.0.6-1_all.deb )

安裝 Nimbus dpkg:

sudo dpkg -i nimbus-icon-theme_0.0.6-1_all.deb
sudo dpkg -i gtk2-engines-nimbus_0.0.6-1_i386.deb

您應該可以在外觀設定看到 Nimbus 嘍.

懶人包:
OK!OK! 阿土伯了解大家的痛苦, 懶人包在此, 請直接下載這二個 deb , 然後依照安裝方式安裝即可.
gtk2-engines-nimbus_0.0.6-1_i386.deb(45K)
nimbus-icon-theme_0.0.6-1_all.deb(9M)

2008年4月29日 星期二

安裝 Ubuntu 8.04 於 Thinkpad T61 雜記

前幾天把 Ubuntu 8.04 Desktop Edition 版本裝在 lenovo Thinkpad T61 上面.
安裝上算是例來版本最順暢的版本, 不用調整 acpi / sata 設定, 一路安裝到底就可以完成安裝嘍.
基本上所有 T61 上的硬體都能正確抓到, 而 nvidia driver 也只需透過 restricted driver 確認的動作便完成了.
當然, 尚許多美中不足的地方需要調效,本篇並不是安裝教學,請參考官方或網路上為數眾多之教學文件.

Wireless LED 不會亮:
雖說 Intel 4965AGN 的 wireless driver 正確掛上, 且亦可以正確使用, 但是主機上那個 wireless led 不會亮, 就是那麼讓人爽度下降.
所以我們需要自己更新 intel compat wireless driver. (當然, 除了 T61 其它品牌 notebook 亦可照作).
首先先到 http://linuxwireless.org/ 下載最新的 driver, link here.
解壓後, 請修改 config.mk 加入 LED 的 options.

CONFIG_IWL3945_LEDS=y
CONFIG_IWLWIFI_LEDS=y

然後 sudo make install 即可完成更新,由於網路 module 使用中, 通常需要重開.
您就會看到您主機上的 wireless LED 開始可愛的一閃一閃了.

Trackpoint 中間鍵
加入以下幾行在 /etc/X11/xorg.conf 的 mouse 設定中:

Option "Device" "/dev/input/mice"
Option "Protocol" "ImPS/2"
Option "ZAxisMapping" "4 5"
Option "Emulate3Buttons" "true"
Option "EmulateWheel" "true"
Option "EmulateWheelButton" "2"


中文輸入法的更換:
雖然我對 SCIM 沒有好惡問題, 但是經過半天的使用, 發現 pidgin 在輸入字時,
會始整個視窗 hang 住一下, 然後久久才取得 focus .
一開始以為是 compiz 特效問題, 後來發現是 scim 怪怪的, 沒有去深究為什麼, 換成 gcin 試試.
於是改裝套件庫中的 gcin gcin-qt3-immodule, pidgin 果然不會卡卡的.
但是另一個問題接著而來, 那就是部份程式在結束時會有 segment fault 問題發生, Firefox / MySQL Query Browser 都會.
所以,又要展開昇級的動作, 由於 hardy 套件庫內的版本只到 1.3.7 版本. 新的穩定版是 1.3.9 可以解決這個問題.
於是我們使用 debian etch 套件庫來更新, 請參考 http://www.calno.com/moto/gcin/

deb http://www.calno.com etch-backports main

加入您 Synaptic 第三方套件列表中->更新套件.
即可完成 1.3.9 版本的安裝, 現在 firefox / MySQL Query Browser 可以正常使用了.

中文字體 AA 小字不好看:
由於 Ubuntu 8.04 內建已經使用文泉驛正黑體, 由於 wqy-zenhei 內建含了點陣的明體,所以小字會使用到點陣字.
所以我們需要關掉它. (詳見官網).
請下載官網中的 [44-wqy-zenhei.conf] , 並換掉系統中的 /etc/fonts/conf.d/44-wqy-zenhei.conf .
在此, 由於官網的 match 只用了 "WenQuanYi Zen Hei" 如果在選字時用了 "文泉驛正黑" 的中文 family name 將不會生效, 建議您將
44-wqy-zenhei.conf test 部份改成如下:

<test qual="any" name="family">
<string>WenQuanYi Zen Hei</string>
<string>文泉驿正黑</string>
<string>文泉驛正黑</string>
</test>


CPU 時脈調整
預設的 CPU freq 模式是 Ondemand, 會自動依 CPU 使用情況調整 CPU 時脈, 但是常常會造成程式 delay 或切換過慢的問題. 所以我們需要讓 cpufreq-selector 可以調整時脈.

sudo dpkg-reconfigure gnome-applets

回答 YES , 讓 cpufreq-selector 擁有 SUID root 權限. 將 cpufreq-selector 加入面版,現在可以很容易依需要調整 CPU 時脈.


Suspend / Hibernate Support
讓 fn+f4 suspend 以及 fn+f12 能正常作業.
修改 /etc/default/acpi-support

ACPI_SLEEP=true
ACPI_HIBERNATE=true
ACPI_SLEEP_MODE=mem
MODULES="e1000 iwl4965 nvidia"
HIBERNATE_MODE=platform

其中的 modules 則是 "removed before suspend and reloaded on resume" 所以可以有效解決 resume 畫面一片白/無線網路不能連等問題(至少阿土伯電腦沒再出現過了).

讓 Ubuntu 更好用:
當然, 不能忘了 lazybuntu 最新的 0.1.5 版也支援 hardy 了.

以上, 是目前阿土伯安裝的心得, 陸續調適, 再行增加整理.

2008年3月10日 星期一

另人遺憾的 Google AuthSub API 有感

身為一個 Google Fans 及 Programmer, 對於參與開發的 Web Application , 總是極力希望能直接整合 Google Services. 甚而連 User Singup 都不用了, 直接使用 Google Account 或 OpenID 進行 Authenticate , 然後直接使用我們的服務..

然而 Google Account API 中的 AuthSub API 似乎不能把它拿來當 Account Identification 用. 因為它無法傳回 UID (username / hash or anythings).

如果我們要拿來識別自己的 local user, 看來只能使用 ClientLogin, 要使用者填入 username (gmail) / password ,.....
這...是怎樣, 在現在釣魚網站這麼多, 而又是一個新創網站而言, 要使用者填入它的 Google username / password 是幾乎不可能的吧...


建議不用改變太多, 至少擴充一下 AuthSubTokenInfo 多傳一行 user_hash or UID 應該沒有安全性上考量吧.. 查了一下 Groups , 很多開發者有和阿土伯相同的困擾, 就差最後一點功夫, 很遺憾的, Google 缺少了它....

現在我們的 Service 放棄了 Google Login 的功能, 阿土伯身為 GFans , 好不甘心呀~~~~

建議:
一. 不改變現有任何 API , 但對於同一個 Username 對於同一個 next 同一個 scope 操作, 回傳同一個
session token , 因為目前 session token 並不會失效, 所以我們可以 "暫時" 拿來當同一個使用者的識別之用.

二. 只改變 AuthSubTokenInfo , 目前有的三行資訊, 多加入一行 user_hash or anything 可以反映相同使用者的資訊都可...

Google Groups: http://tinyurl.com/2yr8hx

2008年2月26日 星期二

GRE 開發三: Step by Step 桌面程式快速開發

XULRunner + jQuery + GREUtils = Quick Application Platform.

本篇將利用範例的方式, 一步一步展示如何快速撰寫一個 Windows / Linux / MacOS 上的桌面應用程式, 您會發現利用 XULRunner (Gecko) 寫 Application 是那麼的容易. 這也是前二篇阿土伯專案中選用 XULRunner 而暫時排處 JavaFX 的原因.
基本上和設計 FireFox Extensions 差不多, 但本篇著重在撰寫 standalone application.
##CONTINUE##
XULRunner 安裝:
XULRunner 的官方網址在 http://developer.mozilla.org/en/docs/XULRunner , 而各個 build 好的
binary 可在此 FTP 下載 http://releases.mozilla.org/pub/mozilla.org/xulrunner/releases/1.8.1.3/contrib/
在這邊我們下載 xulrunner-1.8.1.3.en-US.win32-20080128.zip , 然後 解壓到 C:\

下載 GREUtils 範例:
請到 http://code.google.com/p/greutils/ , 下載 helloworld 範例 http://greutils.googlecode.com/files/greutil-helloworld.zip
然後一樣解壓到 C:\

執行 GREUtils 範例:
請開啟 Command Prompt (執行->cmd.exe), 然後鍵入

c:\xulrunner\xulrunner.exe c:\greutil-helloworld\application.ini


執行畫面:
OK~ 您應該可以看到如下的畫面. Linux / MacOS 執行方式及結果應該亦是相同.
應為跨平台亦是 Gecko 的特色之一, 且由於使用 XUL/XHTML/CSS 所以各平台執行結果及承現是一致的.


開發環境:
XULRunner + jQuery + GREUtils 為此範例的主要環境.
XULRunner 開發細節在此不多作解釋, 請見官網文件. 您可以把它想像成 JavaRuntime 之類的環境, Firefox / ThunderBird 便是架構在 XULRunner 之上.

jQuery 我們的老朋友嘍, 所有 javascript 和 XUL/XHTML 的互動, 都是利用它來實現, 也就是您原來在 Web 中所使用的技巧(Ajax/DOM/XHR), 都可以搬到 Application 來用嘍.
這樣您有沒有信心大增, 即使您熟悉的是 Web Programming, 現在不用學 Java / VB / VC .... VX 就可以寫一些(簡單?)的應用程式嘍.

GREUtils 它是阿土伯封裝的一個簡易框架, 讓您可以容易的開發 XULRunner 應用程式.


application.js:
application.js 負責配製 Preferences , Initialize , 期望您在此僅撰寫這二件事, 相關的程式, 請將它寫到 Controller 中.
以下為 initialize 片斷

// init controller
GREUtils.include_once('appController.js', window);
GREUtils.include_once('mainController.js', window);
GREUtils.include_once('charsetController.js', window);
GREUtils.ControllerHelper.appendController(AppController, this);
GREUtils.ControllerHelper.appendController(MainController, this);
GREUtils.ControllerHelper.appendController(CharsetController, this);


xxxController.js:
Controller 提供相關的 action 實作. 由於 GREUtils 封裝了 CommandDispatcher , 所以您只要擴展
GREUtils.ControllerAdapter , 您可以僅實作您的 action commands , 它會自動處理 supportsCommand / isCommandEnabled / doCommand / onEvent 等相關細節.
其中 init 為 Controller initialize function , 它會傳入 Application, 讓您可以在您的 Controller 中處理 Preferences 以及 Application wide function.

jQuery:
您可以在 Controller , 利用 jQuery 處理畫面上的任何元素, 所以相當容易直覺, 就如同您在設計 Web.

charsetCmdConvert1: function() {
jQuery("#charsetList1").each(function(i) {
var cs = this.selectedItem.label;
var input_text = jQuery("#utf8MsgBoxInput").val();
var out = GREUtils.Charset.convertCharset(input_text, 'UTF-8', cs);
jQuery("#utf8MsgBoxoutput").val(out);
});
}


Append DOM Object:
如果您發現您直接利用 jQuery.append 等相關的 DOM 操作, 和您想的不一樣, 別感到驚訝.
因為在 XULRunner 中, XUL 和 HTML 的 Namespace 是不同的.
所以您可以利用 GREUtils.domXULString / GREUtils.domHTMLString 來處理.
如 明確的指定您要加入一個 XUL 的 Label Object:

jQuery("#testContainer").append( GREUtils.domXULString("<label value='test'/>" ));


Debug:
程式執行起來, 會為您 Popup Error Console 供您 Debug, 當然, 您也可以在 AppController.js
中拿掉它... 您更可以自行安裝 FireBug 為您的 Debuger.

其它..:
有關利用 3rd extensions 和提供您的 application add-ons 在下次有機會阿土伯再行解說.
歡迎大家來信/留言討論, 一同成長.

2008年2月25日 星期一

GREUtils 1.0 Release

GREUtils 是一個輔助您在設計 Firefox extensions 或設計 XULRunner 程式的一個工具程式.

  • 封裝了幾個常用的 XPCOM 功能, 讓您可以更方便更直覺的叫用它們.
  • 封裝了 Dialog / Preferences / Sound 等常用 XPCOM.
  • 封裝了 Charset Convert , 您可以利用 Function 進行 charset convert, 如同 php .
  • 亦加入了如同 PHP 的 include / include_once 的特色, 讓您的程式可以更 MVC , 只有在需要的時侯, 引入適當的 javascript 及模組.
  • 封裝了 Controller 和 CommandDispatch , 讓您的程式有一個良好易於寫作的MVC 架構.

今年比較忙, 一直沒有更新 Blog, 包含之前希望提供給大家的 Gecko 開發工具包, 也一直沒有時間整理(阿土伯很早 2007/09 就投到 google code 開放出來了).

還是沒有時間為大家寫完完整的說明及 Sample code, 怕一拖下去沒完沒了,
先放出來讓大家使用, 或請大家幫我寫一下 Sample Code 吧~~ :D

已補上 hello world 的 xulrunne rsample application, 利用了所有 GREUtils 的特性.
您可以把 helloworld application 當成您專案的 blank application 來用.


大家先看 Source code 或 javadoc 理解一下. 希望對您在撰寫 extension / xulrunner 上有幫助.

專案位址: http://code.google.com/p/greutils/

##CONTINUE##

GREUtils is simple and easy use APIs libraries for GRE (Gecko Runtime Environment).

It provides:

  • Object extend function
  • include / include_once specified URL script.
  • XPCOM utilities
  • Charset Convert
  • Preferences Services
  • File IO
  • Dialog utilities
  • Controller and CommandDispatcher? Helper