- 博物館驚魂夜Night at the Museum(IMDB、Wikipedia),就是很適合小朋友看的電影,整個重點還是在於博物館晚上所發生的怪事。
- 3:10 to Yuma(IMDB、Wikipedia),中譯:決戰310。在台灣好像不賣座?Yahoo!電影居然查不到,或許根本沒上片也不一定。不過這部西部片很好看,由一個江洋大盜與一個瘸腿父親所交織出來的故事,最後的轉折出人意表之外。
How to monorail by Generator tool(2)
接下來,就參考這篇有名的 Four Days on Rails 來試試看吧~
首先呢,由於隔了這麼久才寫這篇,所以 Generator 改位置了,你得從這裡:http://svn.castleproject.org:8080/svn/castle/trunk/Experiments/Generator/ Checkout,其他大致都跟上篇一樣。
- 先利用 monorail ToDo,建立專案,接著依照上篇文章作必要的設定,同時我們使用 rc2,不使用最新的版本(也就是你不用更動 default.build),設定的部份就不再贅述。
- 建立資料庫,這邊我是用MySQL,建立的資料庫名稱是 ToDoDev,不過這只有跟修改連線字串有關係。
- 修改資料庫的連線字串,連線字串是放在 config/databases/ 下的 ActiveRecord 設定檔裡面,你可以看到這邊有兩個設定檔,他很貼心的把開發用與測試用的資料庫分開:development.xml、test.xml,事實上,你還可以增加一個 Production (或是其他名字)的 ActiveRecord 設定檔,表示這是正式上線用的資料庫。切換的時候,可以更動 config/boot.cs 以決定使用哪個 ActiveRecord 設定檔,預設是 development。
- 建立 Model,首先先產生”Category”,Category 的欄位如下:
id int autoincrement
name varchar(255)
created_on datetime
updated_on datetime,在專案的目錄下輸入:script\generate model Categories name created_on updated_on,這邊要注意的是,不需要特別寫 id,因為慣例至上,Generator會自動幫你增加 Id 這個欄位。Generator 會幫你作三件事情:產生 Category 這個類別、產生測試 Category 的 Unit test 類別以及建立資料表格的程式,你可以從指令的輸出結果很清楚的看到。
exists app\models
create app\models\Categories.cs
exists test\models
create test\models\CategoriesTest.cs
create db\migrations
create db\migrations01_AddCategoriesTable.cs - 接下來,要去修改 Categories 類別的屬性型態,Generator 預設都是把型態設為字串,db\migrations 那邊則都是建立 varchar(50)。所以除了 app\models\Categories.cs 要修改型態之外,db\migrations01_AddCategoriesTable.cs 下也要改!這邊把 Name 改為 255 個字元,created_on與updated_on 則改為 DateTime。
- 都修改完畢之後,就可以執行 nant migrate,這個步驟會幫你去實體資料庫作必要的事情。為甚麼要這樣子作?我想是因為一般資料庫的 script 是沒有作管理的,因此,才刻意把這些要去資料庫建立表格、修改欄位等的動作都放到 db\migrations 下,以便把這些程式也都納入版本控制。
- 執行 script\generate scaffold Category,這個步驟會一口氣幫你把 CRUD 的頁面都弄出來。
- 那麼,就編譯吧,直接執行 nant,只是卻出現了…
[csc] app\controllers\CategoriesController.cs(36,72): error CS0246: 找不到型別或命名空間名稱 ‘Category’ (您是否遺漏 using 指示詞或組件參考?)
[csc] app\controllers\CategoriesController.cs(56,45): error CS0246: 找不到型別或命名空間名稱 ‘Category’ (您是否遺漏 using 指示詞或組件參考?)這個,得去修改 CategoriesController.cs,把 Category 都改為 Categories,這看來是 Generator 的問題。接著又再出現
error CS1501: 方法 ‘CreatePagination’ 沒有任何多載使用 ‘2’ 個引數
,唉~這個錯誤訊息實在是太黯然又太銷魂…你必須再次修改 CategoriesController.cs,添加這兩行:
using System.Collections; using System.Collections.Generic;
然後把
PropertyBag["categories"] = PaginationHelper.CreatePagination( Categories.FindAll(), 10);
改為
PropertyBag["categories"] = PaginationHelper.CreatePagination( (IList)Categories.FindAll(), 10);
,接下來應該就沒問題了。
- 先試試看到目前為止的成果吧,輸入script\server,然後打開你的瀏覽器,在位址列輸入:http://localhost:8080/categories/list.aspx,就能看到結果了。
plugin_syntaxhighlighter
在 blogger 使用 dp.syntaxhighlighter 的話,你會發現根本無法生效,主要是因為 blogger 把換行符號都替換成 <br/> 了,而且還沒有設定可以決定是否要替換。
很幸運地,有人已經提出解決方法:yehyeh: Blogger dp.SyntaxHighlighter斷行問題解決方法
只是,我已經套用blogger-ext2了,於是想說,是不是可以寫一個blogger-ext2的 plugin 來解決這個問題。
非常感謝jQuery的強大功能,不到半天就完成了,最重要的是,不用像上面解決方法一樣,寫了一堆 code。
// Register dp.SyntaxHighLighter
// Dependency:
// jQuery-1.2.1
// blogger-ext2-core (最新版,0.7.x 的樣子)
// dp.syntaxhighlighter-1.5.1
BloggerExt.SH = function() {
// Plugin 會由此開始
if( dp!='undefined' ) {
// 找到 pre, textarea 下所有 br,然後替換成換行符號,收工。
jQuery("pre > br").each( function() { jQuery(this).replaceWith( "\n" ); } );
jQuery("textarea > br").each( function() { jQuery(this).replaceWith( "\n" ); } );
dp.SyntaxHighlighter.ClipboardSwf = 'http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');
}
};
BloggerExt.SH.user_pref = function() {
var prefs = [];
return prefs;
};
BloggerExt.SH.update_pref = function(prefs) {
};
BloggerExt.register('SH', { SH: true} );
使用範例:
<script type="text/javascript" src="jquery-1.2.1.pack.js"></script> <script src="blogger_ext2.js" type="text/javascript"></script> <script type="text/javascript" src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shCore.js'></script> <script type="text/javascript" src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushCSharp.js'></script> <script type="text/javascript" src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushVb.js'></script> <script type="text/javascript" src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushPhp.js'></script> <script type="text/javascript" src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushJScript.js'></script> <script type="text/javascript" src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushSql.js'></script> <script type="text/javascript" src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushXml.js'></script> <script type="text/javascript" src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushPython.js'></script> <script type="text/javascript" src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushCss.js'></script> <script type="text/javascript" src='http://syntaxhighlighter.googlecode.com/svn/tags/1.5.1/Scripts/shBrushCpp.js'></script> <!--假設你已經把上面代碼存為 plugin_syntaxhighlighter.js 了 --> <script type="text/javascript" src='plugin_syntaxhighlighter.js'></script>
Postfix log 出現 Database files are not up-to-date 的解法
Google it!! 請參照:[CentOS] Postfix /etc/aliases problem
postconf -e “alias_maps = hash:/etc/aliases”
postconf -e “alias_database = hash:/etc/aliases”
Then run ‘newaliases’ to rebuild the aliases.db file from the text file.
Gtk# UI設計隨便聊
前一陣子用MonoDevelop來寫 Gtk# 應用程式玩,發現真的是很簡單。
幾乎可以跟 SharpDevelop 或 Visual Studio.Net 設計 Windows form 應用程式一樣了,同樣也是拖拉放,就可以完成。
對於初入門的人來說,最痛苦的可能還是對於 Gtk# 的物件模型不熟悉,因為不熟悉,所以也就不知道該去處理哪些屬性與事件。
好在Mono官方網站有提供入門文件:
用力唸一唸這些文件跟自己去嘗試,大致上應該是夠了。但這些文件大部分都是自己去寫 Layout code。
如果你正在使用目前版本的 MonoDevelop 在 Layout 的話,你會發現世界全然不同,因為MonoDevelop引進了 Stetic。
現在使用 MonoDevelop 拉出來的 Form,實際上都會被存放在專案目錄下的 gtk-gui 目錄下的某個 xml 檔案,在每次 build 之前,MonoDevelop 會先把 xml 轉換為一個存放於 gtk-gui 目錄下的 partial 類別(.cs),然後 build 的時候,再 build 到一起。而在專案目錄下所看到的代碼,只會有一行 Build()。
這真的是方便很多,開發者只需要專注於如何處理程式邏輯就可以,而不需要去管 UI 代碼的生成。
在 MonoDevelop 加入 Stetic 之前,大部分的 Gtk# 應用程式還是用手動加代碼或是用 Glade# 來設計介面(詳細的 Glade# 用法,可以參考 Your First Glade# Application 的說明)。
Glade# 其實也是把整個 UI 存成一個 xml 檔案,所以你得先使用 Glade 應用程式設計出 UI,得到 .glade 檔案,然後在程式裡面:
- 載入 .glade 檔案
- 為控制項(Widget)加上 Attribute
- 撰寫事件處理並繫結
。
這當然是比手動寫代碼方便許多,但比起 Stetic,還是要多作事,往往用 Glade 修改 UI 後,可能會忘記加必要的 Widget 宣告,或是對應的事件繫結。
Gtk.TreeView(3)
在 Linux 裡面,所謂的”事件”,多半是用 Signal 來表示,所以你看到 Signal 時,可以概略地當作”事件”來看。
而這些事件跟 Windows Form 的事件命名法差異相當大。
以下這些是TreeView比較常用到的:
protected virtual void OnTreeview1RowActivated (object o, Gtk.RowActivatedArgs args)
{
// double click
Console.WriteLine( String.Format("[{0}]: {1}", o.GetType().ToString(), "row activated") );
}
protected virtual void OnTreeview1RowCollapsed (object o, Gtk.RowCollapsedArgs args)
{
// collapse
Console.WriteLine( String.Format("[{0}]: {1}", o.GetType().ToString(), "row collapsed") );
}
protected virtual void OnTreeview1RowExpanded (object o, Gtk.RowExpandedArgs args)
{
// expand
Console.WriteLine( String.Format("[{0}]: {1}", o.GetType().ToString(), "row expanded") );
}
protected virtual void OnTreeview1CursorChanged (object sender, System.EventArgs e)
{
// click
Console.WriteLine( String.Format("[{0}]: {1}", sender.GetType().ToString(), "Cursor changed") );
}
我是怎麼查到的呢?
坦白說,我是用笨方法,看到那些 Console.WriteLine 了沒?
我先試著在可能的事件裡面放置這些 Console.WriteLine,接著執行程式,試著去 Click、Expand,然後看 Console 輸出就知道了…
電影流水帳(2007/11/29~2007/12/13)
只看了兩部片。不知道今年我到底看了多少片子?到年底的時候來算算看。
- Transformer(Wikipedia,IMDB),中譯:變形金剛,受到台灣很多人喜愛的片子,特效炫,故事緊湊,女主角也很正,完全符合好萊塢作風,也難怪會賣座。個人唯一覺得不好的地方就是,金剛們的金屬味很重,沒有卡通裡面那種色彩強烈的感覺。
- Silent Hill(Wikipedia,IMDB),中譯:沉默之丘。第一次挑戰英文字幕,除了很多單字以外,其實看來不會很吃力。整個裡面的氣氛鋪陳的很好,片中等於有兩個世界,兩個世界交錯地發生事情,不會讓人有搞不懂的情況。總之,我覺得拍的不錯。不過片尾並沒有所謂的結局,看來應該是有打算要拍續集,希望可以看到最後這兩個世界是怎麼再次接軌起來。(謎之聲:世界末日與冷酷異境書末最後兩個世界也沒接起來啊,你要期待什麼?)
Gtk.TreeView (2)
根據昨天的程式,稍作改良,就可以把整個目錄樹丟進去顯示了…
下面就是利用 Recursive 來把資料塞到 TreeStore 裡面去。
public void _buildTreeStore( TreeStore store, DirectoryInfo di, TreeIter parent )
{
foreach( DirectoryInfo iter in di.GetDirectories() )
{
TreeIter ti = store.AppendValues( parent, iter.FullName, iter.Name, "" );
_buildTreeStore( store, iter, ti, true );
}
// add files in tree
foreach( FileInfo fi in di.GetFiles() )
store.AppendValues( parent, fi.FullName, fi.Name, fi.Length.ToString() );
}
public TreeStore buildTreeStore( string path )
{
// 0: fullpath 1: name 2: filesize
TreeStore store = new TreeStore( typeof(string), typeof(string), typeof(string) );
DirectoryInfo di = new DirectoryInfo( path );
TreeIter root = store.AppendValues( path, di.Name, "" );
_buildTreeStore( store, di, root );
return store;
}
public ExplorerSharp(): base(Gtk.WindowType.Toplevel)
{
Build();
TreeStore store = buildTreeStore( "./" );
// 設定資料來源
treeview1.Model = store;
// 不顯示表頭
treeview1.HeadersVisible = false;
// 設定要顯示的欄位
treeview1.AppendColumn("Name", new CellRendererText(), "Name", 1 );
treeview1.AppendColumn("Size", new CellRendererText(), "FileSize", 2 );
// 一次只能選定一列或一個節點
treeview1.Selection.Mode = Gtk.SelectionMode.Single;
}
Gtk.TreeView (1)
使用 TreeView 的基本,首先就是添加列與設定要顯示的欄。
呈現的方式,取決於你給 TreeView.Model 屬性的資料是什麼,如果是 TreeStore,就會顯示 Tree,如果是 ListStore,就會顯示 Grid。
// 如果你把 TreeStore 改為 ListStore,就能得到類似 Grid 的效果。
TreeStore store = new TreeStore();
for( int i=0; i<10; i++ )
{
TreeIter iter = store.AppendValues( "Demo " + i.ToString(), "" );
// 添加子節點,你可以把這兩行註解掉試試看,這樣就沒有子節點了。
for( int j=0; j<10; j++ )
store.AppendValues( iter, "", "Child " + j.ToString() );
}
// 設定資料來源
treeview1.Model = store;
// 不顯示表頭
treeview1.HeadersVisible = false;
// 設定要顯示的欄位
treeview1.AppendColumn("Name", new CellRendererText(), "i", 0 );
treeview1.AppendColumn("Size", new CellRendererText(), "j", 1 );
// 一次只能選定一列或一個節點
treeview1.Selection.Mode = Gtk.SelectionMode.Single;

