GWT layout #1 - HtmlPanel, RootPanel, FlowPanel, FormPanel, PopupPanel

Próbálok egy posztsorozatot készíteni az alap GWT-s panelekről, widgetekről, layoutról. Mivel munkám során hosszabban csak a SmartGWT-seket és Vaadin-osokat használtam (melyek semmilyen átfedésben nincsenek a natúr GWT-sekkel), ezért részletesen én is menet közben ismerem meg őket. Az egész posztsorozatban a következő html template-et használom, semmi extra nincs benne, a Google Eclipse Plugin által generálttól csak annyiban különbözik, hogy a RootPanel megismerésének érdekében feltettem egy mainPanel id-s div-et. Tehát a template html (GwtLayout.html nálam épp a neve):



<body>

<!-- OPTIONAL: include this if you want history support -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>

<!-- RECOMMENDED if your web app will not function without JavaScript enabled -->
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled
in order for this application to display correctly.
</div>
</noscript>
<div id="mainPanel"></div>
</body>





HtmlPanel


A HtmlPanelt fogom használni az összes többi panel/widget/layout bemutatásához, ezért most külön rá nem mutatok példát.
A felületre pakolt HtmlPanel egy div-et fog képezni a js által felépített domfában, és a div tartalma az, amit a HtmlPanel konstruktorában String-ként definiálunk.






RootPanel


A RootPanel kilóg a többi panel közül, nem generálódik hozzá semmilyen tag, hanem egyszerűen csak a statikus get() függvénnyel el tud kérni a template html-től id alapján tag-et vagy ha nem adunk meg id-t argumentumként, akkor a template html body tag-jét.


Első RootPanel példa:


Figyeljünk oda, hogy a "rootPanel" jelen esetben a body lesz, ezért a template-be bedefiniált "mainPanel" id-jú div MELLÉ kerül az aPanel és a bPanel kód.


Kód:

public void onModuleLoad() {
// gray background
RootPanel rootPanel = RootPanel.get();
rootPanel.setStyleName("rootPanel");

// blue background
HTMLPanel aPanel = new HTMLPanel("aPanel");
aPanel.setStyleName("aPanel");
rootPanel.add(aPanel);

// green background
HTMLPanel bPanel = new HTMLPanel("bPanel");
bPanel.setStyleName("bPanel");
rootPanel.add(bPanel);
}

Css:

.rootPanel {
background-color: gray;
}
.aPanel {
background-color: blue;
}
.bPanel {
background-color: green;
}
.aPanel, .bPanel {
color: white;
text-align: center;
}

Látvány:


A generált js kód alapján futásidőben felépített dom-fa:

<body class="rootPanel">
...
<div id="mainPanel"></div>
...
<div class="aPanel">aPanel</div>
<div class="bPanel">bPanel</div>
</body>



Második RootPanel példa:


Egyetlen különbség van az előzőhöz képest az általam írt kódban, mégpedig az, hogy a RootPanel.get("mainPanel")-t hívtam a RootPanel.get() helyett. Látszik, hogy ekkor a template html-be rakott "mainPanel" id-s div lesz a "rootPanel", ő kapja meg a rootPanel css style-t is (szürke háttér), de mivel ő nem teljes képernyős div, ezért a body háttere érvényesül, ami mindenfél felüldefiniálás nélküli, tehát fehér. Ezenkívül látszik, hogy most a "mainPanel" id-s div alá kerül be az "aPanel" és a "bPanel".


Kód:

public void onModuleLoad() {
// gray background
RootPanel rootPanel = RootPanel.get("mainPanel");
rootPanel.setStyleName("rootPanel");

// blue background
HTMLPanel aPanel = new HTMLPanel("aPanel");
aPanel.setStyleName("aPanel");
rootPanel.add(aPanel);

// green background
HTMLPanel bPanel = new HTMLPanel("bPanel");
bPanel.setStyleName("bPanel");
rootPanel.add(bPanel);
}

Css:

.rootPanel {
background-color: gray;
}
.aPanel {
background-color: blue;
}
.bPanel {
background-color: green;
}
.aPanel, .bPanel {
color: white;
text-align: center;
}

Látvány:


A generált js kód alapján futásidőben felépített dom-fa:

<body>
...
<div id="mainPanel" class="rootPanel">
<div class="aPanel">aPanel</div>
<div class="bPanel">bPanel</div>
</div>
...
</body>






FlowPanel


Sima div-et generál. Figyelem, visszatértem arra, hogy a rootPanel a body, valamint raktam a flowPanel-nek egy kis paddingot, hogy a pink-sége előbukkanjon a képen is.


Kód:

public void onModuleLoad() {
// gray background
RootPanel rootPanel = RootPanel.get();
rootPanel.setStyleName("rootPanel");

// pink background
FlowPanel flowPanel = new FlowPanel();
flowPanel.setStyleName("flowPanel");
rootPanel.add(flowPanel);

// blue background
HTMLPanel aPanel = new HTMLPanel("aPanel");
aPanel.setStyleName("aPanel");
flowPanel.add(aPanel);

// green background
HTMLPanel bPanel = new HTMLPanel("bPanel");
bPanel.setStyleName("bPanel");
flowPanel.add(bPanel);
}

Css:

.rootPanel {
background-color: gray;
}

.flowPanel {
background-color: pink;
padding: 10px;
}

.aPanel {
background-color: blue;
}

.bPanel {
background-color: green;
}

.aPanel, .bPanel, .flowPanel {
color: white;
text-align: center;
}

Látvány:


A generált js kód alapján futásidőben felépített dom-fa:

<body class="rootPanel">
...
<div id="mainPanel"></div>
<div class="flowPanel">
<div class="aPanel">aPanel</div>
<div class="bPanel">bPanel</div>
</div>
</body>






FormPanel


A FormPanel a SimplePanel leszármazottja, ez meg azt jelenti, hogy csak egy gyerekpanelt lehet hozzáadni, a második panel/widget hozzáadásakor IllegalStateException-t kapunk. A FormPanel-t nyilvánvalóan nem is arra találták ki, hogy még panel-eket pakoljunk hozzá, helyette inkább formelemeket, viszont ezeket be kell csomagolni egy layoutba/panelba és úgy rárakni a FormPanel-re. Itt a példa terjedelmesebb lesz, de megnézzük, hogy mivé fordulnak az egyes formelemek. Látható, hogy a RadioButton és a CheckBox span-be kerülnek, és kapnak label-t, míg a Simple verziójuk (SimpleRadioButton és SimpleCheckbox) simán csak az adott tag-gé fordul.


Kód:

public void onModuleLoad() {
// gray background
RootPanel rootPanel = RootPanel.get();
rootPanel.setStyleName("rootPanel");

// yellow background
FormPanel formPanel = new FormPanel();
formPanel.setStyleName("formPanel");
rootPanel.add(formPanel);

// pink background
FlowPanel flowPanel = new FlowPanel();
flowPanel.setStyleName("flowPanel");
formPanel.add(flowPanel);

TextBox textBox = new TextBox();
textBox.setText("textBox");
textBox.setStyleName("formElement");
flowPanel.add(textBox);

PasswordTextBox passwordTextBox = new PasswordTextBox();
passwordTextBox.setText("passwordTextBox");
passwordTextBox.setStyleName("formElement");
flowPanel.add(passwordTextBox);

RadioButton radioButton = new RadioButton("radioButton", "radioLabel");
radioButton.setStyleName("formElement");
flowPanel.add(radioButton);

SimpleRadioButton simpleRadioButton = new SimpleRadioButton("simpleRadioButton");
simpleRadioButton.setStyleName("formElement");
flowPanel.add(simpleRadioButton);

CheckBox checkBox = new CheckBox("checkBoxLabel");
checkBox.setStyleName("formElement");
flowPanel.add(checkBox);

SimpleCheckBox simpleCheckBox = new SimpleCheckBox();
simpleCheckBox.setStyleName("formElement");
flowPanel.add(simpleCheckBox);

TextArea textArea = new TextArea();
textArea.setText("textArea textArea textArea textArea textArea textArea");
textArea.setStyleName("formElement");
flowPanel.add(textArea);

ListBox listBox = new ListBox();
listBox.addItem("item1", "value1");
listBox.addItem("item2", "value2");
listBox.setStyleName("formElement");
flowPanel.add(listBox);

ListBox listBoxMultipleSelect = new ListBox(true);
listBoxMultipleSelect.addItem("item1", "value1");
listBoxMultipleSelect.addItem("item2", "value2");
listBoxMultipleSelect.setStyleName("formElement");
flowPanel.add(listBoxMultipleSelect);

FileUpload fileUpload = new FileUpload();
fileUpload.setStyleName("formElement");
flowPanel.add(fileUpload);

Hidden hidden = new Hidden();
hidden.setStyleName("formElement");
flowPanel.add(hidden);

DateBox dateBox = new DateBox();
dateBox.setStyleName("formElement");
dateBox.setValue(new Date());
flowPanel.add(dateBox);
}

Css (paddingot adok mind a flowPanel-nek, mind a formPanel-nek, hogy látszódjon belőlük valami, plusz a formelemeket display:block -kal látom el, hogy ne egy sorba kerüljenek):

.rootPanel {
background-color: gray;
}
.flowPanel {
background-color: pink;
padding: 10px;
}
.formPanel {
background-color: yellow;
padding: 10px;
display: block;
}
.formElement {
display:block;
}

Látvány:


A generált js kód alapján futásidőben felépített dom-fa:

<body class="rootPanel">
...
<form target="FormPanel_1" class="formPanel">
<div class="flowPanel">
<input type="text" tabindex="0" class="formElement">
<input type="password" tabindex="0" class="formElement">
<span class="formElement">
<input type="radio" name="radioButton" id="gwt-uid-1" tabindex="0">
<label for="gwt-uid-1">radioLabel</label>
</span>
<input type="radio" name="simpleRadioButton" tabindex="0" class="formElement">
<span class="formElement">
<input type="checkbox" id="gwt-uid-2" tabindex="0">
<label for="gwt-uid-2">checkBoxLabel</label>
</span>
<input type="checkbox" tabindex="0" class="formElement">
<textarea tabindex="0" class="formElement"></textarea>
<select tabindex="0" class="formElement">
<option value="value1">item1</option>
<option value="value2">item2</option>
</select>
<select multiple="" tabindex="0" class="formElement">
<option value="value1">item1</option>
<option value="value2">item2</option>
</select>
<input type="file" class="formElement">
<input type="hidden" class="formElement">
<input type="text" tabindex="0" class="formElement">
</div>
</form>
...
</body>






PopupPanel


PopupPanel-t nem kell hozzáadni semmilyen panelhez, a show metódusát hívva jelenik meg a többi panel/widget előtt. Ő maga a SimplePanel leszármazottja, ami (mint már tudjuk) azt jelenti, hogy csak egy widget-e / gyerekpanelja lehet. Tehát magyarul először rá kell tennünk pl. egy FlowPanel-t, és arra pakolni a gombokat, feliratokat. Amennyiben a popupPanel.setGlassEnabled(true)-t is meghívjuk, akkor felrak a popupPanel és a többi oldalelem közé még egy panelt, ami teljes brózer méretű, és egyrészt elszürkíti a hátteret (a default stílusbeállításokkal), valamint kiiktatja azok kattinthatóságát. A generált js kód által felépített dom-fában ez egy div-ként jelenik meg, mely a hierarchiában egy szintre kerül a popupPanel divjével.


Kód:

public void onModuleLoad() {
RootPanel rootPanel = RootPanel.get();
rootPanel.setStyleName("rootPanel");

// black
final PopupPanel popupPanel = new PopupPanel();
popupPanel.setPopupPosition(100, 100);
popupPanel.setWidth("400px");
popupPanel.setHeight("200px");
popupPanel.setStyleName("popupPanel");
popupPanel.setGlassEnabled(true);

// yellow
FlowPanel flowPanel = new FlowPanel();
flowPanel.setStyleName("flowPanel");
popupPanel.add(flowPanel);

Label label = new Label("Some text!");
flowPanel.add(label);

Button closeButton = new Button();
closeButton.setText("Close");
closeButton.addClickHandler(new ClickHandler() {

@Override
public void onClick(ClickEvent event) {
popupPanel.hide();
}
});
flowPanel.add(closeButton);

Button button = new Button();
button.setText("Push me!");
button.addClickHandler(new ClickHandler() {

@Override
public void onClick(ClickEvent event) {
popupPanel.show();
}
});
rootPanel.add(button);
}

Css:

.rootPanel {
background-color: white;
}
.popupPanel {
background-color: black;
padding: 10px;
}
.flowPanel {
background-color: yellow;
padding: 10px;
}

Látvány a gomb megnyomása előtt:



Látvány a gomb megnyomása után:


A generált js kód alapján futásidőben felépített dom-fa a gomb megnyomása előtt:

<body class="rootPanel">
...
<button type="button" tabindex="0" class="gwt-Button">Push me!</button>
</body>

A gomb megnyomása után:

<body class="rootPanel">
...
<button type="button" tabindex="0" class="gwt-Button">Push me!</button>
<div class="gwt-PopupPanelGlass" style="position: absolute; left: 0px; top: 0px; width: 1680px; height: 957px; display: block; "></div>
<div style="position: absolute; left: 100px; top: 100px; overflow-x: visible; overflow-y: visible; " class="popupPanel">
<div class="popupContent">
<div class="flowPanel" style="height: 200px; width: 400px; ">
<div class="gwt-Label">Some text!</div>
<button type="button" tabindex="0" class="gwt-Button">Close</button>
</div>
</div>
</div>
</body>






Folytatás következik...
top