sábado, 31 de diciembre de 2011

TUTORIAL: Desarrollo de aplicaciones para bada (y XXIV)

Form Manager: Cómo crear una aplicación con varias páginas

En este artículo voy a mostrar como crear una aplicación bada en C++ que contenga varias páginas (de ahora en adelante Forms) y que permita pasar de un Form al siguiente mediante un par de botones "Anterior" y "Siguiente" que añadiremos a cada uno.

NOTA: El proyecto del ejemplo está disponible aquí, de todas maneras puedes seguir el tutorial y crearlo tú mismo si te apetece.

Antes de nada crea un proyecto bada C++ de tipo "bada Form based Application" al que puedes llamar "FormManager".

1. Crea 3 nuevos Forms llamados "FormA", "FormB" y "FormC", por ejemplo.

Para crear un nuevo Form, en la pestaña "Resource:FormManager", haz clic derecho en "Forms" y selecciona "New Form...":


Luego introduce el nombre deseado, y selecciona "ScreenSize-Normal". Finalmente, haz clic en "Finish":



2. Modifica el método "FormManager::OnAppInitializing()" para que se inicie con "FormA" (en vez de con el Form creado por defecto):


bool
FormManager::OnAppInitializing(AppRegistry& appRegistry)
{
  result r = E_SUCCESS;
  FormMgr *pFormMgr = new FormMgr();
  if(pFormMgr->Initialize())
  {
   r = Application::GetInstance()->GetAppFrame()
                     ->GetFrame()->AddControl(*pFormMgr);
     TryCatch(r == E_SUCCESS, , GetErrorMessage(r));
     pFormMgr->SetStarterForm(FormMgr::REQUEST_FORMA, null);
  }

  return true;

  CATCH:
    SetLastResult(r);
    return false;
}
 
 
3. Crea los ficheros FormMgr.cpp y FormMgr.h.

Sustituye el código por defecto por el siguiente:

FormMgr.h

#ifndef _FORMMGR_H_
#define _FORMMGR_H_

#include >FApp.h> // cambiar el primer > (culpa del editor del blog) 
#include >FUiControls.h> // cambiar el primer > (culpa del editor del blog)
#include "FormA.h"
#include "FormB.h"
#include "FormC.h"


class FormMgr :
 public Osp::Ui::Controls::Form //derived from Form;
 {
     public:
      FormMgr(void);
      virtual ~FormMgr(void);

     public:
      bool Initialize(void);
      bool SetStarterForm(RequestId requestId, Osp::Base::Collection::IList* pArgs);
      static const RequestId REQUEST_FORMA = 101;
      static const RequestId REQUEST_FORMB = 102;
      static const RequestId REQUEST_FORMC = 103;

     protected:
      void SwitchToForm(RequestId requestId,
        Osp::Base::Collection::IList* pArgs);
      Osp::Ui::Controls::Form *__pPreviousForm;
      FormA *__pFormA;
      FormB *__pFormB;
      FormC *__pFormC;

     public:
      virtual void OnUserEventReceivedN(RequestId requestId,
        Osp::Base::Collection::IList* pArgs);
   };

#endif
 

FormMgr.cpp

#include "FormMgr.h"

using namespace Osp::App;
using namespace Osp::Base;
using namespace Osp::Ui;
using namespace Osp::Ui::Controls;

FormMgr::FormMgr(void)
{
 __pPreviousForm = null;
 __pFormA = null;
 __pFormB = null;
 __pFormC = null;
}

FormMgr::~FormMgr(void)
{
}

bool
FormMgr::Initialize(void)
{
 result r = E_SUCCESS;
 // FormMgr debe ser construido...
 r = Form::Construct(FORM_STYLE_NORMAL);
 if (r != E_SUCCESS)
 {
  SetLastResult(r);
 }
 else
 {
  // y debes darle un nombre!
  SetName(L"FormMgr");
 }
 return r == E_SUCCESS;
}


bool FormMgr::SetStarterForm(RequestId requestId,
Osp::Base::Collection::IList* pArgs)
{
 Form *pCurrentForm = Application::GetInstance()->GetAppFrame()
                      ->GetFrame()->GetCurrentForm();

 if (pCurrentForm == this)
  SwitchToForm(requestId, pArgs);
 else
  return false;

 return true;
}

void FormMgr::OnUserEventReceivedN(RequestId requestId,
  Osp::Base::Collection::IList* pArgs)
{
 SwitchToForm(requestId, pArgs);
}

void FormMgr::SwitchToForm(RequestId requestId,
  Osp::Base::Collection::IList* pArgs)
{
 result r = E_SUCCESS;
 Frame *pFrame = Application::GetInstance()->GetAppFrame()->GetFrame();

 switch (requestId)
 {
  // FORM A
  case REQUEST_FORMA:
  {
   __pFormA = new FormA(); // crear Form

   if(!__pFormA->Initialize()) { // iniciar Form
      TryCatch(false, , GetErrorMessage(r));
   }

   r = pFrame->AddControl(*__pFormA); //añadir al frame
   TryCatch(r == E_SUCCESS, , GetErrorMessage(r));

   // establecer como form actual
                        r = pFrame->SetCurrentForm(*__pFormA); 
   TryCatch(r == E_SUCCESS, , GetErrorMessage(r));

   __pFormA->RequestRedraw(true); //solicitar que se muestre
   if (__pPreviousForm != null)
    if (__pPreviousForm != __pFormA)
     pFrame->RemoveControl(*__pPreviousForm);
   __pPreviousForm = __pFormA;
   break;
  }
  // FORM B
  case REQUEST_FORMB:
  {
   __pFormB = new FormB();

   if(!__pFormB->Initialize()) {
    TryCatch(false, , GetErrorMessage(r));
   }

   r = pFrame->AddControl(*__pFormB);
   TryCatch(r == E_SUCCESS, , GetErrorMessage(r));

   r = pFrame->SetCurrentForm(*__pFormB);
   TryCatch(r == E_SUCCESS, , GetErrorMessage(r));

   __pFormB->RequestRedraw(true);
   if (__pPreviousForm != null)
    if (__pPreviousForm != __pFormB)
     pFrame->RemoveControl(*__pPreviousForm);
   __pPreviousForm = __pFormB;
   break;
  }
  // FORM C
  case REQUEST_FORMC:
  {
   __pFormC = new FormC();

   if(!__pFormC->Initialize()) {
    TryCatch(false, , GetErrorMessage(r));
   }

   r = pFrame->AddControl(*__pFormC);
   TryCatch(r == E_SUCCESS, , GetErrorMessage(r));

   r = pFrame->SetCurrentForm(*__pFormC);
   TryCatch(r == E_SUCCESS, , GetErrorMessage(r));

   __pFormC->RequestRedraw(true);
   if (__pPreviousForm != null)
    if (__pPreviousForm != __pFormC)
     pFrame->RemoveControl(*__pPreviousForm);
   __pPreviousForm = __pFormC;
   break;
  }
  default:
   break;
 }

 return;

 CATCH:
    // Evitar Memory Leak
      SetLastResult(r);
      if(__pFormA)
      {
       delete __pFormA;
       __pFormA = null;
      }
      if(__pFormB)
      {
       delete __pFormB;
       __pFormB = null;
      }
      if(__pFormC)
      {
       delete __pFormC;
       __pFormC = null;
      }
}


Fíjate en los comentarios marcados en letra azul del método SwitchToForm(), que es el encargado de cambiar de un Form a otro.


4. Enlaza el FormMgr con los nuevos Form.

Ahora que sabemos como el FormMgr gestiona el paso de un Form a otro, vamos a crear las clases para cada uno de los Forms que hemos creado en el paso 1 (FormA, FormB y FormC).

Para editar un Form, en la pestaña "Resource:FormManager", haz doble clic en uno de ellos, por ejemplo en "FormA". Se abrirá una nueva pestaña en la que verás el GUI Editor.
Bien, ahora selecciona la pestaña "Properties" y modifica los valores de las propiedades "Show Softkey0", "Show softkey1" a "true", para de este modo hacer visibles los botones inferiores en el form.
Modifica también las propiedades "Softkey 0 Text" y "Softkey 1 Text" con los valores "Anterior" y "Siguiente", respectivamente. Debe quedarte así:


Ahora añade una etiqueta ("Label") al formulario, seleccionando "Label" en el ToolBox de la derecha, y arrastrándolo y soltándolo en el Form. Luego modifica el valor de la propiedad "Text" por "FORM A":


Una vez tengamos el form con el diseño que nos guste, procederemos a crear su clase correspondiente.
Para ello, haz clic derecho en el form y selecciona "Add class":


Introduce el nombre de la clase, por ejemplo "FormA" y haz clic en "Finish":


Ahora tenemos creado el "FormA" y su clase correspondiente, pero los botones "Anterior" y "Siguiente" de momento no hacen nada. Tenemos que añadir un gestor de eventos para que se produzca una reacción cuando pulsemos esos botones.

Haz clic derecho en el form y selecciona "Add event handler". Selecciona "IActionEventListener". Luego, introduce un identificador para cada botón en los campos "Softkey0 Action ID" y "Softkey1 Action ID", por ejemplo "201" y "202". Pueden ser los que quieras, mientras sean diferentes entre si, ya que serviran al gestor de eventos para identificar qué elemento del form ha producido el evento.


Haz clic en "Finish".

Por último, vamos a rellenar el método FormA::OnActionPerformed(), que es el que se ejecutará cuando se pulse uno de los botones del form.
Introduce el siguiente código en el método :

void
FormA::OnActionPerformed(const Osp::Ui::Control &source, int actionId)
{
 Frame *pFrame = NULL;
 FormMgr *pFormMgr = NULL;
 if (!pFrame) pFrame = Application::GetInstance()->GetAppFrame()->GetFrame();
 if (!pFormMgr) pFormMgr = static_cast(pFrame->GetControl("FormMgr"));

 switch(actionId)
 {
  case 201: // se ha pulsado el boton "Anterior"
  {
   if (pFormMgr) pFormMgr->SendUserEvent(FormMgr::REQUEST_FORMC, null); // solicitamos mostrar FORM anterior
  }
  break;
  case 202: // se ha pulsado el boton "Siguiente"
  {
   if (pFormMgr) pFormMgr->SendUserEvent(FormMgr::REQUEST_FORMB, null); // solicitamos mostrar FORM siguiente
  }
  break;
  default:
  break;
 }
}
Como puedes observar en los comentarios marcados en azul, simplemente se hace una llamada a FormMgr para que muestre uno u otro Form, dependiendo del botón que hayamos pulsado.

Por cierto, no olvides comprobar que has incluído todas las librerías y dependencias que necesites:



#include "FormA.h"
#include "FormMgr.h"

using namespace Osp::App;
using namespace Osp::Base;
using namespace Osp::Ui;
using namespace Osp::Ui::Controls;


Repite todo el proceso para "FormB" y "FormC". 
En amarillo he marcado el código que variará según estemos en "FormA.cpp", "FormB.cpp" o "FormC.cpp".


5. Compila el proyecto y ejecútalo en el emulador. 

Deberías ver algo parecido a esto:

3 comentarios:

El Spector de Takeshi dijo...

muchísimas gracias!! se te agradece un monton!!

El Spector de Takeshi dijo...

Hola, estoy intentando meter imagenes en las páginas y no se como, pongo una "galería" y no deja poner nada, tampoco lo de copiar y pegar... aunque sea en un comentario (si es sencillo...)

Byron dijo...

Hola, prueba con este ejemplo:

http://www.badadev.com/bada-tutorial-displaying-a-transparent-image-on-a-form/

Publicar un comentario