欄位輔助

使用者通常會在文字欄位或組合框之類的簡式欄位中提供文字資訊。 雖然移入這些欄位的應用程式碼通常比移入複式小組件(如表格或樹狀結構)的程式碼簡單,但這些「簡單」的欄位卻帶給使用者較大的負擔。 使用者必須識別哪些欄位需要內容、欄位是否包含有效內容,以及有哪些預期的選項。 JFace 欄位輔助支援提供了協助使用者處理輸入作業的類別。

org.eclipse.jface.fieldassist 套件以兩種方式來提供協助。 裝飾欄位支援可讓您併入影像裝飾來提示使用者特定欄位的狀態。 內容提議支援可讓您提供蹦現式內容輔助,以提供使用者的內容選項。

裝飾的欄位

裝飾的欄位可讓您將影像裝飾放在視窗或對話框所定義的欄位旁。 欄位有四個角,裝飾可以放在其中一個角旁。 裝飾的欄位很像檢視器,它用來將功能加到 SWT 控制項上,且仍能存取基礎控制項。 DecoratedField 的 API 可讓您新增、隱藏和顯示欄位旁的裝飾。 仍能存取基礎控制項,因此,您可以利用現有的 SWT API 來影響基礎控制項,例如,設定它的內容、顏色或字型。

建立裝飾欄位

從外部來看,裝飾欄位的行為類似單一控制項。 從內部來看,裝飾欄位利用複合控制項來管理欄位及其裝飾的版面。 在大多數情況下,這都應該與用戶端應用程式無關。 不過,這表示裝飾欄位必須實際建立控制項。 比方說,我們設想下面這個片段,應用程式建立一個文字控制項,這個控制項在它的一個對話框之中:

...
// 建立文字欄位
Text text = new Text(parent, SWT.BORDER);
text.setText("some text");
...

為了裝飾這個欄位,這個欄位會依這個方式來建立:

...
// 建立文字控制項的裝飾欄位
DecoratedField field = new DecoratedField(parent, SWT.BORDER, new TextControlCreator());
Text text = (Text)field.getControl();
text.setText("some text");
...

用來建立基本控制項的相同母項和樣式位元,也用來建立裝飾欄位。 主要的程式碼差異在於提供了 IControlCreator 實例,這個實例會建立欄位所需要的特定類型的控制項。 如果是文字欄位,您可以使用 TextControlCreator 類別來建立控制項。然而,您也可以靈活實作 IControlCreator,在欄位內建立任何其他類型的控制項,例如組合框或旋轉鈕。

使用裝飾

建立好裝飾欄位之後,便可以將裝飾加到其中的四個位置之一。 SWT 位置常數用來指定裝飾應該放在哪裡。 如果要新增裝飾,您必須指定 FieldDecoration,它用來定義裝飾影像及(選用)使用者將滑鼠停留在裝飾上時,所能顯示的說明文字。

...
// 建立一個欄位裝飾,將它加到欄位上
Image image = JFaceResources.getImage("myplugin.specialimage");
FieldDecoration mySpecialDecoration = new FieldDecoration(image, "This field is special");
field.addFieldDecoration(mySpecialDecoration, SWT.TOP | SWT.LEFT, false);
...

Boolean 參數用來指定是否只在控制項取得焦點時,才應顯示裝飾,或所有時間都應該顯示它。 在這個情況下,所有時間都會顯示裝飾。 不過,也可能會有其他應該隱藏或顯示裝飾的時間。 下列片段會隱藏已建立的裝飾。

...
// 發生狀況,我想有隱藏裝飾
field.hideDecoration(mySpecialDecoration);
...

如果更新裝飾的影像或說明,欄位應該收到通知,以便重新繪製裝飾。

...
// 一些情況使欄位成為非常特別
mySpecialDecoration.setDescription("This field is extra-special");
field.updateDecoration(mySpecialDecoration);
...

版面裝飾欄位和非裝飾欄位

當在對話框或視窗內版面裝飾欄位時,您應該版面欄位的版面控制項,而不是基礎的簡式控制項。 請重新考量建立文字控制項的程式碼。 當版面文字控制項時,應用程式會設定控制項的版面資料。

...
// 建立文字欄位
Text text = new Text(parent, SWT.BORDER);
text.setText("some text");
// 設定版面資料
GridData data = new GridData(IDialogConstants.ENTRY_FIELD_WIDTH, SWT.DEFAULT);
text.setLayoutData(data);
...

當版面裝飾欄位時,應用程式應該讓版面資料在欄位的版面控制項上。 依所需要的版面而定,可能需要針對裝飾大小來調整欄位大小。

...
// 建立文字控制項的裝飾欄位
DecoratedField field = new DecoratedField(main, SWT.BORDER, new TextControlCreator());
Text text = (Text)field.getControl();
text.setText("some text");
// 設定版面資料
GridData data = new GridData(IDialogConstants.ENTRY_FIELD_WIDTH +
   FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(), SWT.DEFAULT);
field.getLayoutControl().setLayoutData(data);
...

欄位輔助支援不要求,也不假設您只在特定對話框或視窗內使用裝飾欄位。 不過,當裝飾欄位混合了簡式控制項時,視窗的版面可能會複雜一些。 為了對齊裝飾和非裝飾欄位,您必須將裝飾寬度所產生的內縮考慮在內。 裝飾的寬度只是它的影像寬度。 不過,如果您使用含有不同寬度的裝飾,情況會比較複雜。 若是如此,您可以在 FieldDecorationRegistry 中登錄您的所有裝飾,使情況簡化。

欄位裝飾登錄

欄位裝飾登錄可讓您利用字串 ID 來登錄和存取欄位裝飾。 這提供了一種便利方式,供您參照整個應用程式所用的裝飾。 如果您想讓其他外掛程式能夠使用您的裝飾 ID,您可以選擇定義顯現裝飾 ID 的 API。 請注意,登錄裝飾並不會管理影像在這些裝飾內的生命週期。 您的應用程式可以決定如何管理這些影像。 例如,JFace 影像登錄便可用來登錄和管理影像的生命週期。 另外,您的應用程式也可能想隨需應變來建立影像,當不再需要影像時,便刪除它。 FieldDecorationRegistry 中之登錄方法的 Javadoc 說明登錄裝飾時,可用來指定影像的不同方式。

另外,將裝飾登錄在欄位裝飾登錄中,也可以簡化混合裝飾(和非裝飾)欄位時的版面程序。 依預設,裝飾欄位會咨詢欄位裝飾登錄來判斷裝飾的寬度上限,以及確保所有裝飾都使用這個寬度。 這表示不論任何特定裝飾的寬度為何,都會適當對齊所有裝飾欄位。 如果要對齊非裝飾欄位,您可以利用 FieldDecorationRegistry 通訊協定來存取最大裝飾的寬度及建立必要的內縮。

...
// 建立文字欄位
Text text = new Text(parent, SWT.BORDER);
text.setText("some text");
// 設定版面資料
GridData data = new GridData();
data.horizontalAlignment = SWT.FILL;
data.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth();
text.setLayoutData(data);
...

雖然欄位輔助支援並不規定應該如何使用裝飾,但登錄也定義了應用程式可用來顯示欄位特定狀態的標準裝飾。 例如,下列片段便將標準裝飾用在必要欄位上:

...
// 建立含必要欄位裝飾的裝飾欄位。
DecoratedField field = new DecoratedField(main, SWT.BORDER, new TextControlCreator());
FieldDecoration requiredFieldIndicator = FieldDecorationRegistry.getDefault().
   getFieldDecoration(FieldDecorationRegistry.DEC_REQUIRED);
field.addDecoratedField(requiredFieldIndicator, SWT.BOTTOM | SWT.LEFT, false);
...

內容提議

除了用裝飾來註解欄位之外,應用程式也提供了啟動欄位蹦現提議內容提議輔助。 您可以將 ContentProposalAdapter 安裝在任意控制項上,以便提供這個行為。 下列片段會將內容提議配接器安裝在文字控制項上。 請注意,這個文字控制項可能是應用程式直接建立的控制項,也可能是從裝飾欄位取得的控制項。

...
autoActivationCharacters = new char[] { '#', '(' };
keyStroke = KeyStroke.getInstance("Ctrl+Space");
// 假設已利用某種方式建立了 myTextControl
ContentProposalAdapter adapter = new ContentProposalAdapter(
	myTextControl, new TextContentAdapter(),
	new SimpleContentProposalProvider(new String [] {"ProposalOne", "ProposalTwo", "ProposalThree"}),
	keyStroke, autoActivationCharacters);

為了在使用者選擇蹦現畫面中的某項提議時,能夠取得和設定控制項的內容,您必須提供 IControlContentAdapter 實例給配接器,以便擷取和設定特定控制項類型的內容。 如果是文字欄位,您可以使用 TextContentAdapter 類別。 不過,您也可以靈活實作 IControlContentAdapter 來搭配任何其他類型的控制項使用內容提議配接器。

當建立內容提議配接器時,您也必須指定一個 IContentProposalProvider 實例,以便從其中擷取提議本身。 這個提供者負責傳回內容提議陣列。 提議本身是指定成 IContentProposal 的實例,從這些實例中,可以取得提議的標籤和內容及其他資訊(如提議的詳細說明)。

上述範例使用 SimpleContentProposalProvider。 這個提供者的定義方式是將簡單的 String 陣列指定成內容提議。 這個簡式提供者實作必要的通訊協定來將每個字串對映至預期的 IContentProposal 中。 IContentProposalProvider 很靈活,可讓您實作含有進階特性的提議提供者,例如,根據控制項內容來過濾提議,在蹦現畫面中提供說明性的標籤來取代將插入的實際內容,以及指定插入提議之後的預期游標位置。 請參閱欄位輔助範例,以及搜尋 IContentProposalProvider 的實作者,以瞭解進階用法。

配置內容提議配接器

我們已看到內容提議配接器的基本定義包括提供的提議所適用的控制項、用來變更控制項內容的內容配接器,以及定義蹦現畫面中之提議清單的提議提供者。 除了這些基本項目之外,您還可以利用許多方式來配置內容提議配接器:

欄位輔助範例可讓您在範例喜好設定中配置各種這些選項,以及嘗試不同的組合。 例如,配接器可以配置成用某個按鍵來明確呼叫,以及將提議內容插入控制項中,使它的行為比較類似於文字編輯器內容輔助。 它也可以配置成不含任何明確的按鍵、自動啟動字元以及內容的取代,因此,它的行為比較類似 Web 瀏覽器 URL 或搜尋欄位所用的預先輸入樣式。 請參閱 Javadoc,以取得每個這些方法及其互動方式的其他詳細資料。

工作台欄位輔助

JFace 層次的欄位輔助支援為應用程式提供了非常大的彈性空間,應用程式可以靈活決定如何裝飾欄位以及顯示欄位輔助的提議。 對於獨立式 JFace 應用程式或獨立式 Rich Client 應用程式而言,這很好。 不過,如果您的應用程式預定會整合其他外掛程式,如 Eclipse SDK 或協力廠商外掛程式,您可能會想依照與其他外掛程式一致的方式來使用欄位輔助支援。 工作台會定義一些將欄位輔助用在特定互動類型的公用程式類別。

例如,ContentAssistField 類別就會建立含有燈泡裝飾的欄位,以提示使用者可以使用內容輔助。 另外,它也會配置內容輔助樣式插入項的內容提議配接器。 最後,它會提供工作台層次內容輔助指令的處理常式,因此,當使用者呼叫工作台按鍵連結所指定的按鍵或觸發序列時,會開啟內容提議蹦現畫面。 請參閱 org.eclipse.ui.fieldassist 套件,以取得這些公用程式類別的詳細資料。

這個套件預期會發展成工作台,欄位輔助的使用會擴大,且會將某些欄位狀態所用的裝飾同步化。