2010年7月14日 星期三

[PHP] 取得指定目錄下的檔案清單

由於有些 open source 把 Javascript Code 分成很多個目錄,然後我又懶的一個個加入使用,所以,又偷懶寫了個小程式,用來取得指定目錄裡頭的檔案,搭配 Regular Expression 來決定哪些檔名要紀錄,哪些 file path 要捨棄。


程式碼:


<?php
function getFileList( $file_path , $filename_regexp_pattern , $skip_filepath_regexp_pattern )
{
        $_file_list = array();
        if( !file_exists( $file_path ) || !is_dir( $file_path ) )
                return $_file_list;
        if ( $handle = opendir( $file_path ) )
        {
                while (false !== ($file = readdir($handle)))
                {
                        if( $file == '.' || $file == '..' )
                                continue;
                        $target = $file_path . DIRECTORY_SEPARATOR . $file;
                        if( is_dir( $target ) )
                                foreach( getFileList( $target , $filename_regexp_pattern , $skip_filepath_regexp_pattern ) as $k => $v )
                                        $_file_list[ $v ] = $v;
                        if( !empty( $skip_filepath_regexp_pattern ) && preg_match( $skip_filepath_regexp_pattern , $target ) )
                                continue;
                        if( empty( $filename_regexp_pattern ) || preg_match( $filename_regexp_pattern , $file ) )
                                $_file_list[ $target ] = $target;
                }
                closedir($handle);
        }
        return $_file_list;
}

//print_r( getFileList( '.' , '/\.js$/is' , '/test/is' ) );
foreach( getFileList( '.' , '/\.js$/is' , '/test/is' ) as $js_file )
        echo '<script src="'.$js_file.'" type="text/javascript"></script>'."\n";
?>


[PHP] 替已壓縮 Javascript Code 稍稍排版

有時後會需要看別人寫的 Javascript Code,很多情況該程式碼已經被壓縮或最佳化,然後程式碼就被擠成一列而已,然而,那一些展開後可能是數百數千列的程式碼。


為此,就簡單寫隻 PHP 程式碼,把 Javascript Code 稍稍地排版,例如碰到 { 和 } 要縮排等,我記得以前用 Visual C++ 時,可全選程式碼後按 shtif + F8 就可以排版好了,這已經是七年前的印象,不過手邊沒這種環境,目前只愛用 vim 啦,就簡單寫一下 PHP 來處理。在自行更改 input 跟 output 吧。


程式碼(僅適合觀看,不適合轉完又拿來用喔,因為有些像 regular expression 應該因為此排版而出錯):


<?php
        $raw = file_get_contents( 'bundle.js' );

        $level = 0;
        for( $i=0 ; $i<strlen( $raw ) ; ++$i )
        {   
                if( $level > 0 && $raw[$i] == "\n" )
                {   
                        $sp = '';
                        for( $j=0 ; $j<$level; ++$j )
                                $sp .= "\t";

                        $prev_part = substr( $raw , 0 , $i );
                        $next_part = substr( $raw , $i + 1 );
                        $raw = $prev_part . $raw[ $i ] . $sp . $next_part ;

                        $i += $level;
                }   
                else if( $raw[ $i ] == ';' )
                {   
                        $prev_part = substr( $raw , 0 , $i );
                        $next_part = substr( $raw , $i + 1 );
                        $raw = $prev_part . $raw[ $i ] . "\n" . $next_part ;
                }   
                else if( $raw[ $i ] == '{' )
                {   
                        $prev_part = substr( $raw , 0 , $i );
                        $next_part = substr( $raw , $i + 1 );
                        $raw = $prev_part . $raw[ $i ] . "\n" . $next_part ;

                        ++$level;
                }   
                else if( $level > 0 && $raw[ $i ] == '}' )
                {   
                        --$level;
                        $sp = '';
                        for( $j=0 ; $j<$level; ++$j )
                                $sp .= "\t";

                        $prev_part = substr( $raw , 0 , $i );
                        $next_part = substr( $raw , $i + 1 );
                        $raw = $prev_part . "\n" . $sp . $raw[ $i ] . "\n" . $next_part ;

                        $i += $level + 1 ;      // 1 for first newline
                }   
                echo "$level\n";
        }
        file_put_contents( 'bundle.js.new' , $raw );
?>



2010年7月12日 星期一

使用 Django 架設 Bookworm @ Ubuntu 10.04

Bookworm 是一套採用 New BSD License 的 Open Source,細節請參考 http://code.google.com/p/threepress/ ,也可以直接使用線上版:



紀錄一下在從無到有的安裝過程:



  1. 安裝 Virutalbox 

  2. 安裝 Ubuntu 10.04 32-bit

  3. 基本環境安裝

    • $ sudo apt-get install vim subversion



  4. 取得 Django 並安裝

    • $ wget http://www.djangoproject.com/download/1.0.4/tarball/
      $ tar xzvf Django-1.0.4.tar.gz
      $ cd Django-1.0.4
      $ sudo python setup.py install



  5. 取得 bookworm 程式碼

    • svn checkout http://threepress.googlecode.com/svn/trunk/ threepress-read-only



  6. 安裝相關環境

    • $ sudo apt-get install patch mysql-server mysql-query-browser python-mysqldb python-lxml python-cssutils python-beautifulsoup python-twill python-openid

    • $ cd threepress-read-only/bookworm/gdata ; sudo python setup.py install;

    • 讓 mysql 使用 utf8 (此部份是從網路上隨意找到的資料,不保證正確性)

      • $ sudo vim /etc/mysql/my.cnf

        • [client]

          • default-character-set = utf8



        • [mysqld]

          • character-set-server = utf8
            collation-server = utf8_unicode_ci
            init_connect = 'set collation_connection = utf8_unicode_ci;'





      • 重新開機( 我用 $ sudo /etc/init.d/mysql restart 好像沒啥用,最後重開機才解決)





  7. 建立 bookworm 資料庫、threepress 帳號,記得要設定好權限,避免錯誤可以先把 bookworm 的所有權限都打開

  8. 初始化與執行

    • $ cd threepress-read-only/bookworm/ ;
      $ mkdir log ; touch log/bookworm.log ;  chmod -R 777 log/ library/storage
      $ python manage.py syncdb
      $ mysql -u threepress -p
      mysql> use bookworm;
      mysql> create
      fulltext index epubtext on library_htmlfile (words);
      mysql> quit;
      $ python manage.py runserver




啟動後,連上 http://localhost:8000 就可以看到登入介面囉!只是一堆 css 似乎都不存在(請查看 urls.py ),所以版面有點亂。後來我把一本三國演義的 EPUB 電子書丟進去給他處理,看來沒啥問題。


2010年7月8日 星期四

UITableViewController 之 didSelectRowAtIndexPath 無反應的問題

想說寫個簡單的 UITableViewController 來了解一些流程細節,結果每當我按下某個項目時,卻遲遲沒有動作?確認後,發現 didSelectRowAtIndexPath 函式完全沒進入。找了一些文章,也看不出個所以然,畢竟完完全全是最簡單的 UITableViewController ,新增後只修改 numberOfSectionsInTableView 和 numberOfRowsInSection 回傳的數字而已。


經過幾番確認,最後發現是我自己呼叫的流程問題:


錯誤的程式碼:


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    UINavigationController *n = [[UINavigationController alloc] init];
    
    MyUITableViewController *t = [[MyUITableViewController alloc] initWithStyle:UITableViewStylePlain];
    [n pushViewController:t animated:YES];
    t.title = @"MyTable";

    [window addSubview:n.view];
    [t release];
    [n release];
    // Override point for customization after application launch.
    
    [window makeKeyAndVisible];
    
    return YES;
}


錯誤的地方就只是把 UINavigationController 給 release 掉,然後他又會 release 掉 MyUITableViewController,因此關於 MyUITableViewController 物件就等於被回收掉。需留意 [window addSubview:n.view] 也只是會對那個 view 做 retain 而已,所以整個 table 還是看的到,但 controller 的事件卻無反應。


在此僅小小測試用的解法,就是不要去做 [n release] 。若是真正要跑的程式,應該是擺在 dealloc 函式中去處理,而 UINavigationController 要拉到 Interface 裡頭宣告。果真一個禮拜沒寫 iPhone 就會快忘光了!這個簡單的東西花了十來分鐘才發現。


而回到原本的測試是單純想要了解,從一個 UITableViewController 初始化、被切換到另一個 View 時,再被切回來時會呼叫哪些函數。測試的程式就只是在 MyUITableViewController 的 didSelectRowAtIndexPath 裡頭,宣告一個新的 MyUITableViewController 並 push 到 self.navigationController 裡頭,接著再 back 回來。從一開始的執行到結束所印出的訊息:


tabletest[1706:207] viewDidLoad:First
tabletest[1706:207] viewWillAppear:First
tabletest[1706:207] viewDidAppearFirst
tabletest[1706:207] >>>>In didSelectRowAtIndexPath<<<<
tabletest[1706:207] viewDidLoad:Second
tabletest[1706:207] viewWillDisappear:First
tabletest[1706:207] viewWillAppear:Second
tabletest[1706:207] viewDidDisappear:First
tabletest[1706:207] viewDidAppearSecond
tabletest[1706:207] viewWillDisappear:Second
tabletest[1706:207] viewWillAppear:First
tabletest[1706:207] viewDidDisappear:Second
tabletest[1706:207] viewDidAppearFirst


2010年7月3日 星期六

iOS 開發教學 - 使用 UIScrollView 顯示照片清單

UIScrollView

筆記之前透過 UIScorllView 呈現跟 iPhone 內建的照片瀏覽程式的類似效果

關鍵程式碼:

-
(void)viewWillAppear:(BOOL)animated

{
   [super viewWillAppear:animated];
   CGRect currFrame =
[[UIScreen mainScreen] bounds];

   
   [scroll setDelegate:self];
   [scroll
setBackgroundColor:[UIColor blackColor]];

   [scroll
setScrollEnabled:YES];

   [scroll setPagingEnabled:YES];

   CGSize photoView =
CGSizeMake(100, 100);

   
   int photo_cnt = 10;
   
   int col_cnt =
currFrame.size.width / photoView.width;

   int row_cnt =
photo_cnt / col_cnt + ( ( photo_cnt % col_cnt ) ? 1 : 0 );

   float pandding =
(currFrame.size.width - photoView.width * col_cnt ) / ( col_cnt + 1 );

   
   [scroll
setContentOffset:CGPointMake(0, 0)];

   [scroll
setContentSize:CGSizeMake(currFrame.size.width, (photoView.height +
pandding )* row_cnt + pandding )];


   [scroll setFrame:currFrame];
   [[self view]
addSubview:scroll];



   NSLog(@"row,col,pandding:(%d,%d,%f)", row_cnt ,col_cnt,pandding);

   
   for( int i=0 ;
i<photo_cnt ; i++ )

   {
       int x = i % col_cnt;
       int y = i /
col_cnt;


       


       UIImage *thumbnail = [UIImage imageNamed:[NSString
stringWithFormat: ( i+1 < 10 ? @"0%d.jpg" : @"%d.jpg" ), i+1]];


       UIButton *b =
[[UIButton alloc] init];

       [b setBackgroundImage:thumbnail
forState:UIControlStateNormal];

       [thumbnail release];
       
       [b
setShowsTouchWhenHighlighted:YES];

       [b
setUserInteractionEnabled:YES];

       [b setFrame:CGRectMake( x * (
photoView.width + pandding ) + pandding , y * ( photoView.height +
pandding ) + pandding , photoView.width , photoView.height )];

       [scroll
addSubview:b];

       [b release];
   }
}

使用上宣告一個 UIViewController 並且使用 UIScrollViewDelegate protocol,並且修改其 viewWillAppear 函式,除此之外,請自備 10 張圖,依序為 01.jpg, 02.jpg, ..., 10.jpg。程式碼中的 scroll 為 UIScrollView 物件。

程式流程:


  • 取得當前設備的解析度

  • 設定 scroll 物件的控制與回應、背景設成黑色等

  • 假設一張圖將使用 75x75 的大小,計算一列可擺幾張圖,以及圖與圖之間要留多少空間,以及最後有幾列,透過這些資訊決定 scroll 物件的內容大小

  • 接著使用 UIButton 來呈現圖片,並且依照圖片的順序決定顯示的位置

  • 收工!

使用 UIScrollView 算是可以很輕鬆地達到 iPhone 內建軟體的照片呈現效果,但有個很致命的缺點,那就是上述的過程是直接用原圖呈現的,所以圖片看起來會有失真,並且因為是使用原圖大小,將導致記憶體使用吃緊,並隨著圖片很多張時,問題會越來越嚴重!其他細節,可以參考 UITableViewCotrller ,其架構不錯,特別是在 Cell 的重複使用上,巧妙地控制好記憶體的使用。

因此,其實也是可以用 UITableViewController 來這個效果,只需要把 Cell 做一些手腳處理就行,如 [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 和 [self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone]; 等。在此感謝同事的提醒,不然我還沒留意 UITableViewController 是繼承 UIScrollViewController 的!

此篇主要記錄照片座標等計算的部分,雖然使用 UITableViewController 後座標計算又不一樣並且更加簡單,但還是留念一下囉。至於縮圖方面,可以參考此篇文章:UIImage: Resize, then Crop