App-Entwicklung für bada – ein Beispiel

Seite 3: 2. Formular

Inhaltsverzeichnis

Zum Ändern und Hinzufügen von Items benötigt man ein zweites Formular. Erfreulicherweise ist es einfach, eine bada-Applikation in diese Richtung zu erweitern. Dazu muss der Entwickler die Ressourcendatei IDF_FORM1.xml öffnen, um die IDE in den Ressourcen-Editiermodus zu versetzen. Am unteren linken Teil des Bildschirms erscheint ein Ressourcenfenster. Nach dem Klick mit der rechten Maustaste auf den Ordner ScreenSize-Normal und im darauf erscheinenden Pop-up-Menü auf New Form reagiert die IDE darauf mit dem in Abbildung 3 gezeigten Formular-Wizard, der das Erstellen der neuen Ressourcendatei erledigt.

Die bada IDE erstellt Formulare automatisch (Abb. 3).

Die Bedienung des Dialogs ist einfach. Man markiert ScreenSize-Normal und gibt einen Formularnamen ein. Nach dem Klick auf Finish erscheint im Ressourcenfenster das neue Formular (s. Abb. 4).

Die Erstellung des Formulars ist so gut wie abgeschlossen (Abb. 4).

Um das Formular endgültig anzulegen, muss man auf den mit dem Stern markierten Eintrag klicken. Wenn das neue Formular im Ressourceneditor geladen ist, klickt man auf das Speichern-Icon in der Toolbar. Daraufhin legt die IDE eine weitere XML-Datei im Ordner /res/ScreenSize-Normal an.

Zum Erstellen der Formularklassen gibt es einen kleinen Shortcut. Dafür muss man das Formular-Wurzelelement (IDF_FORM_*) in der Outline des Ressourceneditors rechts anklicken und im danach erscheinenden Menü die Option Add Class anwählen. Nach der Bestätigung des Dialogs erstellt die bada-IDE die Klasse samt dazugehörendem Header automatisch.

Im nächsten Schritt ist das Formular mit Steuerelementen zu befüllen. Diesmal sind sie aber nicht von Hand anzuordnen, diese Arbeit wird an die in bada integrierten Layout-Manager ausgelagert. Als Erstes muss der Entwickler dem System mitteilen, dass automatische Layout-Unterstützung benötigt wird. Dazu setzt er die Formulareigenschaft "Layout Style" auf LAYOUT_VERTICAL_BOX, um die Steuerelemente übereinander anzuordnen. Im nächsten Schritt bevölkert er das Formular, indem er nacheinander ein Label, ein EditField und zwei Buttons aus der Toolbar in den Formularkorpus zieht. Der Layoutmanager ordnet die Steuerelemente automatisch untereinander an, es ist nur noch die Breite anzupassen. Am Ende sollte das Formular ungefähr wie in Abbildung 5 aussehen.

Dieses Formular wird vom Layoutsystem verwaltet (Abb. 5).

Primitive Anwendungen verwalten ihre Formulare in der Applikationsklasse. Ergänzt sei die Klasse HeiseBada1 deshalb um einen Pointer auf Form_edit und um eine Referenz auf Form1:

class HeiseBada1 :
public Osp::App::Application,
public Osp::System::IScreenEventListener
{
public:
Form1 *pForm1;
Form_edit *pEditForm;

Die automatisch erstellte "temporäre Referenz" in OnAppInitializing wird durch einen Verweis auf die Member-Variable ersetzt. Ebenda wird auch das neue Formular initialisiert:

bool
HeiseBada1::OnAppInitializing(AppRegistry& appRegistry)
{
pForm1 = new Form1();
pForm1->Initialize();
pEditForm=new Form_edit();
pEditForm->Initialize();

Frame *pFrame = GetAppFrame()->GetFrame();
pFrame->AddControl(*pForm1);
pFrame->AddControl(*pEditForm);

pFrame->SetCurrentForm(*pForm1);

pForm1->Draw();
pForm1->Show();

return true;
}

Wichtig ist, dass alle bada-Formulare im Frame der Anwendung leben. Deshalb muss der Entwickler alle Formularinstanzen erstellen und danach ihre Initialize()-Methoden aufrufen, um die Konstruktoren auszuführen. Danach schreibt er die Formulare in den Frame. Zu guter Letzt aktiviert er das erste Formular und gibt es zum Zeichnen frei. Die Aktivierung des Editor-Formulars erfolgt in den Handlern der Add- und Edit-Buttons von Form1:

case ID_FOOTER_ADD:
{//Compiler whines re reuse
HeiseBada1 *anApp;
anApp=static_cast<HeiseBada1*>
(Osp::App::Application::GetInstance());
Frame *pFrame;
pFrame = anApp->GetAppFrame()->GetFrame();
pFrame->SetCurrentForm(*(anApp->pEditForm));
anApp->pEditForm->SetIDAndMode(true,0, this);
anApp->pEditForm->RequestRedraw(true);
}
case ID_FOOTER_EDIT:
{
bool isFormulaFound=false;
int i;
for(i=0;i<myList->GetItemCount();i++)
{
if(myList->IsItemChecked(i))
{
isFormulaFound=true;
break;
}
}
if(isFormulaFound)
{
HeiseBada1 *anApp;
anApp=static_cast<HeiseBada1*>(Osp::App::Application::GetInstance());
Frame *pFrame;
pFrame = anApp->GetAppFrame()->GetFrame();
pFrame->SetCurrentForm(*(anApp->pEditForm));
anApp->pEditForm->SetIDAndMode(false,i, this);
anApp->pEditForm->RequestRedraw(true);
}
}
break;

Auch zum Wechseln des aktiven Formulars benötigt der Entwickler den Frame. Die Referenz auf ihn bekommt er über die Singleton-Mutterklasse der Anwendung. Die erste Aufgabe besteht deshalb darin, einen Zeiger auf das Singleton zu erhalten. Danach setzt man das aktuelle Formular, schreibt die Eigenschaften und ruft RequestRedraw auf, um ein Neuzeichnen der geänderten Steuerelemente zu erzwingen.

Die Edit-Methode unterscheidet sich von Add nur insofern, dass sie statt eines leeren Elements den Index des selektierten Elements an den Editor weiterreicht. Dort wartet die Methode SetIDAndMode, die das Editorformular neu initialisiert:

void Form_edit::SetIDAndMode(bool _createNew, int _id, Form1* context)
{
myCreateFlag=_createNew;
myContext=context;
myID=_id;
EditField* TxtField = static_cast<EditField *>
(GetControl(L"IDC_EDITFIELD1"));
if(myCreateFlag)
{
TxtField->SetText("");

}
else
{
TxtField->SetText(myContext->item[myID]);
}
}

Die übergebenen Parameter werden ins Formular gespeichert, die TextBox bekommt den zutreffenden Text durch Aufruf der Methode SetText zugewiesen. Es muss nur noch der Editor geschlossen werden:

case ID_BUTTON_CANCEL:
{
HeiseBada1 *anApp;
anApp=static_cast<HeiseBada1*>
(Osp::App::Application::GetInstance());
Frame *pFrame;
pFrame = anApp->GetAppFrame()->GetFrame();
pFrame->SetCurrentForm(*(anApp->pForm1));
anApp->pForm1->RequestRedraw(true);
}
break;
case ID_BUTTON_OK:
{
HeiseBada1 *anApp;
anApp=static_cast<HeiseBada1*>
(Osp::App::Application::GetInstance());
Frame *pFrame;
pFrame = anApp->GetAppFrame()->GetFrame();
pFrame->RemoveControl(*(anApp->pForm1));
//Update base stack
if(myCreateFlag==true)
{
EditField* TxtField = static_cast<EditField
*>(GetControl(L"IDC_EDITFIELD1"));
myContext->item[myContext->itemCount]=TxtField->GetText();
myContext->itemCount++;
}
else
{
EditField* TxtField = static_cast<EditField
*>(GetControl(L"IDC_EDITFIELD1"));
myContext->item[myID]=TxtField->GetText();
}

Osp::Base::String item[8];
int itemCount = myContext->itemCount;
for(int i=0;i<8;i++)
item[i]=myContext->item[i];

//Redo form stack
anApp->pForm1=new Form1();
anApp->pForm1->Initialize();

//Restore data
anApp->pForm1->itemCount = itemCount;
for(int i=0;i<8;i++)
anApp->pForm1->item[i]=item[i];

pFrame->AddControl(*(anApp->pForm1));
pFrame->SetCurrentForm(*(anApp->pForm1));



anApp->pForm1->RequestRedraw(true);
}
break;

Sofern der Benutzer auf Cancel klickt, hat das Programm keine Arbeit. Es schickt den Editor wieder in den Hintergrund und zeigt stattdessen Form1 an. Bei einem Klick auf Ok werden Änderungen an der Liste erforderlich, was eine etwas komplexere Vorgehensweise erfordert.

Die von Samsung vorgesehene Methode des Anpassens von Formularen besteht darin, die Liste über die diversen Methoden über das Einpflegen und Ändern von Items zu informieren. In der Praxis ist es oft einfacher, das Formular komplett neu zu erstellen. Im Beispiel nutzt der Autor diesen Shortcut und erstellt eine neue Formularinstanz. Da die Item-Liste im Formular liegt, ist sie zwischenzuspeichern – in der Praxis würde man sie in die Applikations-Mutterklasse oder ein anderes globales Objekt auslagern.

Die Zuweisung der Event-Handler für die Buttons erfolgt in OnInitializing:

result
Form_edit::OnInitializing(void)
{
result r = E_SUCCESS;

// TODO: Add your initialization code here

CmdOk = static_cast<Button *>(GetControl(L"IDC_BUTTONOK"));
if (CmdOk != null)
{
CmdOk->SetActionId(ID_BUTTON_OK);
CmdOk->AddActionEventListener(*this);
}

CmdCancel = static_cast<Button *>(GetControl(L"IDC_BUTTONCANCEL"));
if (CmdCancel != null)
{
CmdCancel->SetActionId(ID_BUTTON_CANCEL);
CmdCancel->AddActionEventListener(*this);
}


return r;
}

Der Unterschied zu den vorher besprochenen Buttons im Footer besteht darin, dass die Buttons die Zuweisung der Event-ID zur Laufzeit erwarten. Bevor sich die Anwendung testen lässt, muss der Entwickler noch die Initialisierung des Arrays in OnInitializing entfernen, danach ist die Liste editierbar.

Zu beachten ist, dass die bada-Runtime nicht mehr als 30 Formulare gleichzeitig verwalten kann. Bei komplexen Programmen ist es deshalb sinnvoll, eine Art Formularmanager zu realisieren und die Formularklassen nach Bedarf zu erstellen und abzutragen – Beispiele dafür finden sich im
Internet.