Segue mais um exemplo do uso de MVC, aos poucos iremos postar exemplos desde os mais simples ao mais complexo em MVC. Baseando-se no primeiro exemplo postado em Meu primeiro fonte MVC , iremos mostrar como montar uma tela onde iremos separar os campos por grupos e incluiremos um novo botão em "Ações relacionadas". Montaremos uma tabela simples, com 6 campos, sendo 1 do tipo virtual
Ordem | Campo | Tipo | Tam | Contexto | Propriedade | Titulo | F3 | Inic.Padrao | Inic.Browse |
1 | ZZ8_FILIAL | C | 2 | R | V | Filial | |||
2 | ZZ8_CODIGO | C | 6 | R | A | Codigo | GETSX8NUM("ZZ8","ZZ8_CODIGO") | ||
3 | ZZ8_DESCR | C | 30 | R | A | Descrição | |||
4 | ZZ8_USER | C | 6 | R | A | Usuário | SRA | ||
5 | ZZ8_NOME | C | 30 | V | V | Nome | IF(INCLUI,' ',POSICIONE( 'SRA', 1, XFILIAL('SRA') + ZZ8->ZZ8_USER, 'RA_NOME')) | POSICIONE( 'SRA', 1, xFilial('SRA') + ZZ8->ZZ8_USER, 'RA_NOME') | |
6 | ZZ8_BLQ | C | 1 | R | A | Bloqueado? | "2" |
//Criando grupos oStr1:AddGroup( 'GRUPO01', 'Descrição' , '', 1 ) oStr1:AddGroup( 'GRUPO02', 'Funcionário' , '', 2 ) oStr1:AddGroup( 'GRUPO03', 'Outros' , '', 3 )Agora iremos informar para o objeto onde os campos ficarão. Para colocar todos os campos num único grupo você pode utilizar o asterisco (*)
// Colocando todos os campos para um agrupamento' oStr1:SetProperty( '*' , MVC_VIEW_GROUP_NUMBER, 'GRUPO01' )ou
// Colocando alguns campos por agrupamentos' oStr1:SetProperty( 'ZZ8_CODIGO' , MVC_VIEW_GROUP_NUMBER, 'GRUPO01' ) oStr1:SetProperty( 'ZZ8_DESCR' , MVC_VIEW_GROUP_NUMBER, 'GRUPO01' ) oStr1:SetProperty( 'ZZ8_USER' , MVC_VIEW_GROUP_NUMBER, 'GRUPO02' ) oStr1:SetProperty( 'ZZ8_NOME' , MVC_VIEW_GROUP_NUMBER, 'GRUPO02' ) oStr1:SetProperty( 'ZZ8_BLQ', MVC_VIEW_GROUP_NUMBER, 'GRUPO03' )Agora iremos inserir um novo botão em "Ações relacionadas" Para a criação de botões adicionais na barra de botões da interface utilizamos o método AddUserButton
//Criando um botão oView:AddUserButton( 'Novo botão', 'NOTE', {|oView| alert("Você clicou aqui")} )Onde o "Novo botão", é o texto que será apresentado no botão, "NOTE" é o nome da imagem do RPO (apesar de não exibir, é um parametro que faz parte) que será usada para o botão e o 3º parâmetro é o bloco de código que será executado ao acionar o botão. Para ficar melhor, segue o código fonte, copie e compile em seu projeto para vê-lo funcionado.
/*Importar as bibliotecas*/ #INCLUDE "PROTHEUS.CH" #INCLUDE "FWMBROWSE.CH" #INCLUDE "FWMVCDEF.CH" /*Iniciando sua função*/ User Function fEXPMVC1() /*Declarando as variáveis que serão utilizadas*/ Local lRet := .T. Local aArea := ZZ8->(GetArea()) Private oBrowse Private cChaveAux := "" //Iniciamos a construção básica de um Browse. oBrowse := FWMBrowse():New() //Definimos a tabela que será exibida na Browse utilizando o método SetAlias oBrowse:SetAlias("ZZ8") //Definimos o título que será exibido como método SetDescription oBrowse:SetDescription("DESCRIÇÃO") //Adiciona um filtro ao browse oBrowse:SetFilterDefault( "" ) //Ativamos a classe oBrowse:Activate() RestArea(aArea) Return
//------------------------------------------------------------------- // Montar o menu Funcional //------------------------------------------------------------------- Static Function MenuDef() Local aRotina := {} ADD OPTION aRotina TITLE "Pesquisar" ACTION 'PesqBrw' OPERATION 1 ACCESS 0 ADD OPTION aRotina TITLE "Visualizar" ACTION "VIEWDEF.fEXPMVC1" OPERATION 2 ACCESS 0 ADD OPTION aRotina TITLE "Incluir" ACTION "VIEWDEF.fEXPMVC1" OPERATION 3 ACCESS 0 ADD OPTION aRotina TITLE "Alterar" ACTION "VIEWDEF.fEXPMVC1" OPERATION 4 ACCESS 0 ADD OPTION aRotina TITLE "Excluir" ACTION "VIEWDEF.fEXPMVC1" OPERATION 5 ACCESS 0 ADD OPTION aRotina TITLE "Imprimir" ACTION "VIEWDEF.fEXPMVC1" OPERATION 8 ACCESS 0 ADD OPTION aRotina TITLE "Copiar" ACTION "VIEWDEF.fEXPMVC1" OPERATION 9 ACCESS 0 Return aRotina
Static Function ViewDef() Local oView Local oModel := ModelDef() Local bAvalCampo := {|cCampo| AllTrim(cCampo)+"|" $ "ZZ8_CODIGO|ZZ8_DESCR|ZZ8_NOME|"} Local oStr1 := NIL Local nOperation := oModel:GetOperation() oStr1 := FWFormStruct(2, 'ZZ8') // Cria o objeto de View oView := FWFormView():New() oView:Refresh() // Define qual o Modelo de dados será utilizado oView:SetModel(oModel) //Adiciona no nosso View um controle do tipo FormFields(antiga enchoice) oView:AddField('Formulario' , oStr1,'CamposZZ8' ) //Remove os campos que não irão aparecer //oStr1:RemoveField( 'ZZ8_BLQ' ) // Criar um "box" horizontal para receber algum elemento da view oView:CreateHorizontalBox( 'PAI', 100) // Relaciona o ID da View com o "box" para exibicao oView:SetOwnerView('Formulario','PAI') oView:EnableTitleView('Formulario' , 'Descricao' ) oView:SetViewProperty('Formulario' , 'SETCOLUMNSEPARATOR', {10}) //Criando grupos oStr1:AddGroup( 'GRUPO01', 'Descrição' , '', 1 ) oStr1:AddGroup( 'GRUPO02', 'Funcionário' , '', 2 ) oStr1:AddGroup( 'GRUPO03', 'Outros' , '', 3 ) // Colocando alguns campos por agrupamentos' oStr1:SetProperty( 'ZZ8_CODIGO' , MVC_VIEW_GROUP_NUMBER, 'GRUPO01' ) oStr1:SetProperty( 'ZZ8_DESCR' , MVC_VIEW_GROUP_NUMBER, 'GRUPO01' ) oStr1:SetProperty( 'ZZ8_USER' , MVC_VIEW_GROUP_NUMBER, 'GRUPO02' ) oStr1:SetProperty( 'ZZ8_NOME' , MVC_VIEW_GROUP_NUMBER, 'GRUPO02' ) oStr1:SetProperty( 'ZZ8_BLQ', MVC_VIEW_GROUP_NUMBER, 'GRUPO03' ) //Criando um botão oView:AddUserButton( 'Novo botão', 'CLIPS', {|oView| alert("Você clicou aqui")} ) //Força o fechamento da janela na confirmação oView:SetCloseOnOk({||.T.}) Return oView
Static Function ModelDef() Local oModel Local oStr1:= FWFormStruct( 1, 'ZZ8', /*bAvalCampo*/,/*lViewUsado*/ ) // Construção de uma estrutura de dados //Cria o objeto do Modelo de Dados //Irie usar uma função fEXPMVC1V que será acionada quando eu clicar no botão "Confirmar" oModel := MPFormModel():New('Descricao', /*bPreValidacao*/, { | oModel | fEXPMVC1V( oModel ) } , /*{ | oMdl | fEXPMVC1C( oMdl ) }*/ ,, /*bCancel*/ ) oModel:SetDescription('Descrição') //Abaixo irei iniciar o campo X5_TABELA com o conteudo da sub-tabela oStr1:SetProperty('ZZ8_CODIGO' , MODEL_FIELD_INIT,{|| GetSXENum("ZZ8","ZZ8_CODIGO")} ) //Abaixo irei bloquear/liberar os campos para edição oStr1:SetProperty('ZZ8_CODIGO' , MODEL_FIELD_WHEN,{|| .F. }) oStr1:SetProperty('ZZ8_NOME' , MODEL_FIELD_WHEN,{|| .F. }) // Adiciona ao modelo uma estrutura de formulário de edição por campo oModel:addFields('CamposZZ8',,oStr1,{|oModel|fEXPMVC1T(oModel)},,) //Define a chave primaria utilizada pelo modelo oModel:SetPrimaryKey({'ZZ8_CODIGO', 'ZZ8_DESCR', 'ZZ8_USER' }) // Adiciona a descricao do Componente do Modelo de Dados oModel:getModel('CamposZZ8'):SetDescription('TabelaZZ8') Return oModel
//Esta função será executada no inicio do carregamento da tela, neste exemplo irei //apenas armazenar numa variável o conteudo de um campo Static Function fEXPMVC1T( oModel ) Local lRet := .T. Local oModelZZ8 := oModel:GetModel( 'CamposZZ8' ) cChaveAux := ZZ8->ZZ8_CODIGO Return(lRet)
//------------------------------------------------------------------- // Validações ao salvar registro // Input: Model // Retorno: Se erros foram gerados ou não //------------------------------------------------------------------- Static Function fEXPMVC1V( oModel ) Local lRet := .T. Local oModelZZ8 := oModel:GetModel( 'CamposZZ8' ) Local nOpc := oModel:GetOperation() Local aArea := GetArea() //Capturar o conteudo dos campos Local cChave := oModelZZ8:GetValue('ZZ8_CODIGO') Local cTabela := oModelZZ8:GetValue('ZZ8_DESCR') Local cDescri := oModelZZ8:GetValue('ZZ8_USER') Local cBlq := oModelZZ8:GetValue('ZZ8_BLQ') Begin Transaction if nOpc == 3 .or. nOpc == 4 dbSelectArea("ZZ8") ZZ8->(dbSetOrder(1)) ZZ8->(dbGoTop()) If(ZZ8->(dbSeek(xFilial("ZZ8")+cChave))) if cChaveAux != cChave SFCMsgErro("A chave "+Alltrim(cChave)+" ja foi informada!","fEXPMVC1") lRet := .F. Endif Endif if Empty(cChave) SFCMsgErro("O campo chave é obrigatório!","fEXPMVC1") lRet := .F. Endif if Empty(cDescri) SFCMsgErro("O campo descrição é obrigatório!","fEXPMVC1") lRet := .F. Endif Endif if !lRet DisarmTransaction() Endif End Transaction RestArea(aArea) FwModelActive( oModel, .T. ) Return lRet