Chromium的菜單實現考慮到跨平台的要求,使用了一層抽象模型(SimpleMenuModel),所有菜單模型都繼承自這個類,各平台實現時需要根據提供的模型構造對應的菜單。這個工具菜單模型是WrenchMenuModel類,也繼承自SimpleMenuModel。Chromium在Linux平台使用了GTK+來建立介面,也就由MenuGtk類負責菜單模型的解釋和構造。所有的菜單都要經過**MenuModel到GtkMenuItem的過程,如果要添加或刪除功能表項目可以直接修改對應的MenuModel,再由MenuGtk類自動產生相應菜單。
Chromium在菜單上添加了按鈕,而GTK沒有提供相應的控制項,所以Chromium自己編寫了一個自訂功能表項目類,繼承自GTK+的功能表項目類。縮放功能表項目的結構如下:
其中的全屏按鈕是最複雜的一個按鈕,因為其他所有按鈕上只有一個label,而這個全屏按鈕上添加了一個表徵圖,而且這個表徵圖還會根據不同的狀態改變樣式,難怪它這麼複雜。這個按鈕在構建模型時很正常,和其他按鈕一樣,只是多了個icon_idr,這是用來表示表徵圖資源ID的,其他按鈕都是預設的-1,而它是IDR_FULLSChromiumEEN_MENU_BUTTON。在MenuGtk類根據模型構建菜單時,才真正開始:
在MenuGtk::BuildSubmenuFromModel中構建菜單時,處理TYPE_BUTTON_ITEM類型的功能表項目時調用了BuildButtonMenuItem函數,在BuildButtonMenuItem中如果從功能表項目模型中擷取到了有效圖片ID(現在就是IDR_FULLSChromiumEEN_MENU_BUTTON)就會調用SetupImageIcon函數為功能表項目設定表徵圖,而SetupImageIcon函數中只是給該功能表項目串連了”show”訊號由OnSubmenuShowButtonImage函數處理,也就是說當該功能表項目需要顯示時便會調用這個函數,在這個函數中才真正地調用GetIconSetForId擷取表徵圖資源,然後設定給了該功能表項目。沒完呢,在GetIconSetForId中有這麼一條語句:”if
(id == IDR_FULLSChromiumEEN_MENU_BUTTON) return fullsChromiumeen_icon_set_; returnNULL;”這是巧合麼!這個被返回的fullsChromiumeen_icon_set在函數GtkThemeService::RebuildMenuIconSets中被初始化,當然這個函數也只處理了這個一表徵圖,Chromium這麼麻煩的目的只有一個:讓全屏按鈕的行為看起來更像系統控制項。因為帶有標籤的按鈕在啟用時背景高亮且文字反色,但是系統不會處理帶有映像的按鈕,Chromium就自己搞了。如果想在菜單中添加更多的表徵圖按鈕,可以跳過Chromium這麼麻煩的處理過程直接添加映像到按鈕上,這樣就不會有那麼“像系統”的行為了,也可以在GtkThemeService類中添加更多的GtkIconSet來達到Chromium這樣的效果。
Chromium的菜單實現考慮到跨平台的要求,使用了一層抽象模型(SimpleMenuModel),所有菜單模型都繼承自這個類,各平台實現時需要根據提供的模型構造對應的菜單。這個工具菜單模型是WrenchMenuModel類,也繼承自SimpleMenuModel。Chromium在Linux平台使用了GTK+來建立介面,也就由MenuGtk類負責菜單模型的解釋和構造。所有的菜單都要經過**MenuModel到GtkMenuItem的過程,如果要添加或刪除功能表項目可以直接修改對應的MenuModel,再由MenuGtk類自動產生相應菜單。
Chromium在菜單上添加了按鈕,而GTK沒有提供相應的控制項,所以Chromium自己編寫了一個自訂功能表項目類,繼承自GTK+的功能表項目類。縮放功能表項目的結構如下:
其中的全屏按鈕是最複雜的一個按鈕,因為其他所有按鈕上只有一個label,而這個全屏按鈕上添加了一個表徵圖,而且這個表徵圖還會根據不同的狀態改變樣式,難怪它這麼複雜。這個按鈕在構建模型時很正常,和其他按鈕一樣,只是多了個icon_idr,這是用來表示表徵圖資源ID的,其他按鈕都是預設的-1,而它是IDR_FULLSChromiumEEN_MENU_BUTTON。在MenuGtk類根據模型構建菜單時,才真正開始:
在MenuGtk::BuildSubmenuFromModel中構建菜單時,處理TYPE_BUTTON_ITEM類型的功能表項目時調用了BuildButtonMenuItem函數,在BuildButtonMenuItem中如果從功能表項目模型中擷取到了有效圖片ID(現在就是IDR_FULLSChromiumEEN_MENU_BUTTON)就會調用SetupImageIcon函數為功能表項目設定表徵圖,而SetupImageIcon函數中只是給該功能表項目串連了”show”訊號由OnSubmenuShowButtonImage函數處理,也就是說當該功能表項目需要顯示時便會調用這個函數,在這個函數中才真正地調用GetIconSetForId擷取表徵圖資源,然後設定給了該功能表項目。沒完呢,在GetIconSetForId中有這麼一條語句:”if
(id == IDR_FULLSChromiumEEN_MENU_BUTTON) return fullsChromiumeen_icon_set_; returnNULL;”這是巧合麼!這個被返回的fullsChromiumeen_icon_set在函數GtkThemeService::RebuildMenuIconSets中被初始化,當然這個函數也只處理了這個一表徵圖,Chromium這麼麻煩的目的只有一個:讓全屏按鈕的行為看起來更像系統控制項。因為帶有標籤的按鈕在啟用時背景高亮且文字反色,但是系統不會處理帶有映像的按鈕,Chromium就自己搞了。如果想在菜單中添加更多的表徵圖按鈕,可以跳過Chromium這麼麻煩的處理過程直接添加映像到按鈕上,這樣就不會有那麼“像系統”的行為了,也可以在GtkThemeService類中添加更多的GtkIconSet來達到Chromium這樣的效果。