• 沒有找到結果。

Chapter 4 PGML / PUML

4.3 PUML – Pervasive User-interface Markup Language

4.3.4 PUML 範例

其實撰寫 PUML 文件相當容易。PUML 的程式設計師只要有公佈欄的抽象 概念,然後只要想著要在公佈欄上張貼什麼訊息即可。也就是說,若要在公 佈欄上貼圖片的話,就只要在<board>的 element content 中加上<picture>即 可,想要在公佈欄上貼上標籤的話,就只要在<board>的 element content 中 加上<label>即可,其他以此類推。若想使用邏輯運算來完成某些特定的事情 的話,就只要在<board>的 element content 中加上<logic-objects>,然後在

<logic-objects>的 element content 中,使用<object>來指定要使用哪個邏輯物 件(logic object,也就是 PGML 文件)即可。若想要觸發事件以進行邏輯運算 的話,在<board>的 element content 中加上<action>,然後在<action>的 element content 中,根據你想執行的順序,分別加上<use-object>、<change>、

<nextboard>即可,相當直覺。

也就是說,在PUML 中,使用者介面容器(UI container)就是<board> element,

在<board> 的 element content 中 可 以 放 入 <label> 、 <textnote> 、 <logic -objects>、<action>……等等的 elements。PUML 的程式設計師在設計使用 者介面時,便以board 為基本單位,來設計行動應用程式中所有可能出現的 使用者介面。

再來,簡單介紹一下PUML 文件結構的骨架。

PUML 的 root element(document element)為<user-interface>,<user-interface>

包含三種 child element,分別為<layout>、<logic-objects>和<board>。在

<user-interface> 的 element content 中 最 多 只 能 有 一 個 <layout> , 而

<logic-objects>最多也只能有一個,另外<board>則最少要有一個。<board>

包含了六種child element,分別為<picture>、<label>、<textnote>、<listpaper>,

以 及 <logic-objects> 和 <action> , 而 在 <board> 中 最 多 只 能 有 一 個

<logic-objects>。<listpaper>的 child element 為<item>,<logic-objects>的 child element 為<object>,<action>的 child element 為<use-object>、<change>或

<nextboard>。每種 elements 的詳細用法及說明,請參考表 4-3 和本論文中的 範例。

以下為PUML 文件結構的示意圖(圖 4-7):

<?xml version="1.0"?>

<user-interface name=“…l" version="1.2"

xmlns="http://dcsw3.cis.nctu.edu.tw/Project/Pervasive/PUML/">

<layout>…</layout>

<logic-objects>

<object name=“…” source=“…”/>

</logic-objects>

<board name=“…" title=“…" seqNO=“…">

<picture/>

<action name=“…" showText=“…">

<use-object name=“…” method=“…”>

<param/>

..

</use-object>

<change container=“…" component=“…" update=“…">

<user-interface name="LoginInput" version="1.2"

xmlns="http://dcsw3.cis.nctu.edu.tw/Project/Pervasive/PUML/">

<logic-objects>

<object name="login" source="Login.pgml"/>

</logic-objects>

<board name="loginBoard" title="login page" seqNO="0">

<label name="showMsg1" showText="input your name: "/>

<textnote type="text" name="UserName"/>

<label name="showMsg2" showText="select your sex: "/>

<listpaper iname="isex" mode="single">

<item showText="Boy"/>

<item showText="Girl"/>

</listpaper>

<action name="enter" showText="ENTER">

<use-object name="login" method="verify">

<param select="UserName"/>

<param select="isex"/>

<param type="String" value="Location-NCTU"/>

</use-object>

<nextboard goto="mainBoard"/>

</action>

</board>

<board name="mainBoard" title="main page">

<!--content-->

</board>

</user-interface>

[圖 4-8 PUML 簡單範例]

這個例子是描述一個登入的使用者介面。在這個所描述的使用者介面中,會 要求使用者輸入姓名以及性別,然後在事件觸發後(按下 button 或 command 之後),會將使用者在使用者介面上輸入的資料,送給後端的邏輯運算部份

做運算,運算完之後會將畫面切換到另一個描述的使用者介面。

相對應的J2ME 程式碼如下(圖 4-9、圖 4-10、圖 4-11):

(共產生三個 class:BMngr_LoginInput、B_loginBoard、B_mainBoard)

import javax.microedition.midlet.*; import javax.microedition.lcdui.*;

interface BMngr_Interface {

public void changeBoard(String boardName);

public Displayable getBoard(String boardName);

}

public class BMngr_LoginInput extends MIDlet implements BMngr_Interface{

public static BMngr_LoginInput instance; private Display display;

/*global logic objects*/

public Login lgObj_login = new Login();

/*all displayables corresponding to boards' declaration*/

private B_loginBoard loginBoard = new B_loginBoard(); private B_mainBoard mainBoard = new B_mainBoard();

/*Constructor*/

public BMngr_LoginInput(){ instance = this; } /*Main method*/

public void startApp(){ display = Display.getDisplay(this); display.setCurrent(loginBoard); } /*Handle pausing the MIDlet*/

public void pauseApp(){ } /*Handle destroying the MIDlet*/

public void destroyApp(boolean unconditional){ } /*Quit the MIDlet*/

public static void quitApp(){ instance.destroyApp(true); instance.notifyDestroyed(); instance = null; } /*change UI presentation*/

public void changeBoard(String boardName){

if(boardName.compareTo("loginBoard") == 0){ display.setCurrent(loginBoard); } if(boardName.compareTo("mainBoard") == 0){ display.setCurrent(mainBoard); } }

/*get particular UI container*/

public Displayable getBoard(String boardName){

Displayable displayable = null;

if(boardName.compareTo("loginBoard") == 0){ displayable = loginBoard; } if(boardName.compareTo("mainBoard") == 0){ displayable = mainBoard; } return displayable;

} }

[圖 4-9 class:BMngr_LoginInput]

class B_loginBoard extends Form implements CommandListener { /*local logic objects*/

/*UI components*/

public StringItem showMsg1; public TextField UserName; public StringItem showMsg2; public ChoiceGroup isex;

/*commands*/

private Command enter = new Command("ENTER", Command.SCREEN, 1);

/*Constructor*/

public B_loginBoard() {

/* initialize UI component */

super("login page"); showMsg1 = new StringItem("input your name: ", "");

UserName = new TextField("", "", 50, TextField.ANY);

showMsg2 = new StringItem("select your sex: ", "");

isex = new ChoiceGroup("", ChoiceGroup.EXCLUSIVE);

isex.append("Boy", null); isex.append("Girl", null);

/* set up listeners */

this.setCommandListener(this);

/* append UI component */

this.append(showMsg1); this.append(UserName); this.append(showMsg2); this.append(isex);

/* add commands */

this.addCommand(enter);

}

/*Handle command events*/

public void commandAction(Command command, Displayable displayable){

String selectedStr = null; String oldPath = null; String newPath = null; String align = null;

if(command == enter){

BMngr_LoginInput.instance.lgObj_login.

verify(UserName.getString(), isex.getSelectedIndex()+1, "Location-NCTU");

BMngr_LoginInput.instance.changeBoard("mainBoard");

} } }

[圖 4-10 class:B_loginBoard]

class B_mainBoard extends Form implements CommandListener { /*local logic objects*/

/*UI components*/

/*commands*/

/*Constructor*/

public B_mainBoard() {

/* initialize UI component */

super("main page");

/* set up listeners */

this.setCommandListener(this);

/* append UI component */

/* add commands */

}

/*Handle command events*/

public void commandAction(Command command, Displayable displayable){

String selectedStr = null; String oldPath = null; String newPath = null; String align = null;

} }

[圖 4-11 class:B_mainBoard]

C.

複雜的範例

使用PUML 做一個比較複雜的使用者介面描述。在這個例子中, 使用四個

<board>來描述四個使用者介面,而整個例子主要的用意是,展示所有在 PUML 中可以描述出來的使用者介面元件。

第一個<board>主要展示 PUML 可以描述圖片、標籤以及輸入欄位等使用者 介面元件,並且可以將使用者輸入的資料送到後端邏輯部份去處理,處理完 之後,使用者將可以在第二個<board>所描述的使用者介面中看到所輸入的 資料。

第二個<board>主要展示在 PUML 所描述出來的使用者介面中,可以隨時反 應出使用者介面元件的變化,例如:將使用者在第一個使用者介面中所輸入 的資料,透過更新使用者介面元件顯示的方式,將所輸入的資料顯示在第二 個所描述的使用者介面上。另外,在這個使用者介面中,可以透過事件驅動 的方式(按下 button 或 command),選擇要進入第三個或第四個使用者介面。

第三個<board>主要展示 PUML 也可以描述單選模式的選單(single-selection choice group 或 single-selection choice list),並可以將使用者的選擇結果顯示 在同一個使用者介面上。

第四個<board>主要展示 PUML 也可以描述多選模式的選單(multi-selection choice group 或 multi-selection choice list),並可以將使用者的選擇結果顯示 在同一個使用者介面上。

因為篇幅排版的關係,這個範例的 PUML 原始文件檔,以及經過 XSLT 轉 換機制,所轉換出來的J2ME 程式碼和 WML 程式碼,均放在 appendix 中。

另外,本範例也會在 7.2 節中的 Example1 出現,將提供本範例所描述出來 的使用者介面在執行時期的面貌。