2016年1月10日 星期日

[JUCE] Image Viewer Development Log 6 - Add File Tree View

這次要為 Image Viewer 增加一個 File Tree View

想要的功能有以下

(1) 可以用 View 工具列去決定是否顯示 File Tree View

(2) 會隨著 File Open 這個功能去改變當下的 File Tree

(3) 可以調整 File Tree View 和 Image 的相對大小

以下是重點部份的講解

1. 首先在 MainComponent.h 增加所需要的 variables、functions,以及需要多繼承的 class

   繼承 FileBrowserListener 這個 class,是在 File Tree View 有 event 發生時要有相對應動作


   而繼承了 FileBrowserListener 就必須實做以下這些 functions

   這邊主要會去實做 selectionChanged(),其餘的就用 empty function


   以下是新增的 member variables,說明一些重點的 variables

   StretchableLayoutManager : 就是用來調整 file tree view 和 image 的相對大小

   StretchableLayoutResizerBar : 顧名思義就是 resizer bar

   TimeSliceThread : DirectoryContentsList 用來在背景掃描 file structure 用的 thread

   WildcardFileFilter : 即 file filter

   DirectoryContentsList : FileTreeComponent 所要展示的內容

   FileTreeComponent : 即本次要的 file tree
 

2. 接下來看 MainComponent.cpp

   首先在 constructor 對 member variable 做初始化

   利用 setOpaque() 將 component 設成非透明,可以做一些優化


   依然在 constructor

   [1] : 利用 StretchableLayoutManager::setItemLayout() 來設定 file tree view 和 image 該要

         有的大小以及 resizer bar 的大小

         因為 file tree view 預設是沒有顯示的,所以只有image

         StretchableLayoutManager::setItemLayout() 的第一個參數是 index,之後會將 component

         用 array 的形式傳給 StretchableLayoutManager,StretchableLayoutManager 就會根據

         index 去 layout 在該 index 的 component,在這邊規劃的順序是 0 = FileTreeComponent、

         1 = StretchableLayoutResizerBar、2 = ImageComponent

   [2] : 將預設的起始 folder 設在當下工作目錄

   [3] : 啟動 background thread

   [4] : 將 FileBrowserListener 加到 FileTreeComponent


3. 增加一個 View 在 menu bar,此部分就不在說明,之前已經說明過

4. 在 resize() 來指定好各 component 所該要的位置

   可以看到 comps[] 這個 array 裡面的 component 是按照在 constructor 所規劃的順序放進去的

   最後在用 StretchableLayoutManager::layOutComponents() 來 layout 各 component


5. 在 openImageFile(),因為開啟圖檔有可能會造成所在 path 改變,所以必須去對

   DirectoryContentsList 做相對應的設定

   當新的所在目錄和之前的不相同的時候,用 DirectoryContentsList::setDirectory() 去設定新

   的 root directory,並且等 DirectoryContentsList 掃描完新的 path 後,refresh

   FileTreeComponent 的內容  


    這邊必須要特別說明最後三行做的事

    (1) 每次選擇了一個新的圖檔,會去用 FileTreeComponent::setSelectedFile() 來指定檔案

        而指定了這個檔案,會造成一次選擇的 event 以及一次 repaint

        後面兩個變數的設定,即 mOpenedFile 和 mNeedRepaint,是為了同時有多個 repaint

        發生時必須做一些處理而增加的,這個部分等會說明,先說明選擇 event 的部分

        因為會有一次選擇的 event 發生,所以 selectionChanged() 這個 callback function 會被

        呼叫,所以就在這邊將指定的檔案給 ImageComponent 去顯示

        而同時間也利用 DocumentWindow::setName() 將開啟檔案的檔名顯示在視窗的 title


    (2) 接著說明剛剛提到的 repaint。在同一個目錄,用menu bar 的 file open 功能開啟不同檔

        案,file tree view 都能正常重畫 selected raw 到選擇的檔案上

        但若是目錄也變了,會使用 DirectoryContentsList::setDirectory() 來改變 root directory

        此時,也會造成一次 repaint (因為不同的目錄有不同的 files & directories),而造成的結

        果就是後面呼叫 FileTreeComponent::setSelectedFile() 所產生的 repaint

        (重畫 selected raw)會被吃掉

        所以在這邊使用 mOpenedFile 和 mNeedRepaint 來記錄此現象,並在 paint()

        這個 function 去補畫 selected raw

        重畫的方式很簡單,就是再呼叫一次 FileTreeComponent::setSelectedFile() 這樣就可以了

        因為這只是當所在目錄也換的時候才會有的特殊現象,所以用 mNeedRepaint 來決定是

        否要做這個動作


6. 接著看到 perform()

   這邊說明一下如何動態去決定 File Tree View 是否顯示。方法就是改變

   StretchableLayoutManager 的設定值,根據 mFileTreeVisible 的值去設定相對應的

   StretchableLayoutManager::setItemLayout(),然後再用

   StretchableLayoutManager::layOutComponents 去 relayout 就可以了
 

7. 成果如下


沒有留言:

張貼留言