15 de septiembre de 2017

Guardar y restaurar configuraciones en aplicaciones VFP

Artículo original: Saving and restoring settings in VFP applications
http://www.sweetpotatosoftware.com/SPSBlog/PermaLink,guid,e5d49608-9752-42a5-b7f7-867df325a780.aspx
Autor: Craig Boyd
Traducido por: Ana María Bisbé York


El problema

Muchas veces, los desarrolladores Visual FoxPro van a encontrarse a si mismo guardando estados previos de alguna configuración para restaurarlo una vez que está ejecutando el código. Los más usuales son:

  • comandos SET (tales como SET SAFETY, SET DELETED, etc.)
  • comandos ON (ON ERROR, ON ESCAPE, etc.)
  • posición del puntero de registro
  • área de trabajo actual

La solución

En lugar de escribir las mismas líneas de código una y otra vez en sus programas, podríamos crear una clase que lo controle. Esto hace la siguiente clase SettingHandler, que he escrito y he preparado unos ejemplos de cómo utilizarla. Notará que cuando instancio la clase envío el comando que estoy por ejecutar (tales como SET SAFETY OFF) como un parámetro tipo cadena. La clase va a guardar la configuración actual del parámetro Safety y luego lo iguala a OFF. Cuando deseo restablecer la configuración anterior, libero la instancia de SettingHandler y la clase restablece el valor de Safety a lo que hubiera antes de que yo lo hubiera cambiado.

Inconvenientes y ventajas

El único inconveniente que encuentro en este proceder es que no trabaja IntelliSense cuando escribo el comando como parámetro de cadena. Y sobre las mejoras, puedo pensar en más de una, por ejemplo, operaciones sobre tablas. Se podría agregar que permita guardar la sesión actual de datos y que luego la restablezca (habrá probablemente otros parámetros que también se podrían proporcionar Captions, ForeColor, BackColor, Tag, etc) Además, se podría agregar alguna lógica para controlar si un desarrollador cambia las áreas de trabajo; pero no especifica un área de trabajo en el comando GOTO.

He aquí un ejemplo listo para correr y la definición de clase (copie y pegue el código que aparece a continuación en un prg y ejecútelo)

*************************
*!* EJEMPLO DE USO
*************************
CLEAR
LOCAL loSetting
? "SET COMMANDS:"
SET SAFETY ON
? SET("SAFETY")
**  Guarda y cambia el valor de Safety 
loSetting = CREATEOBJECT("SettingHandler", "SET SAFETY OFF")
? SET("SAFETY")
** Restaura el valor previo de Safety 
RELEASE loSetting 
? SET("SAFETY")
?
? "ON COMMANDS:"
ON ERROR ? "Controlador de error previo "
? ON("ERROR")
** Guarda y cambia el valor del controlador de error
loSetting = CREATEOBJECT("SettingHandler", "ON ERROR ?'New Error Handler'") 
? ON("ERROR")
** Restaura el valor previo del controlador de error
RELEASE loSetting 
? ON("ERROR")
?
? "RECORD NUMBER:"
IF !USED("customers")
  USE (HOME(2) + "northwind\customers.dbf") IN 0 SHARED
ENDIF
GOTO 5 IN "customers"
? RECNO("customers")
** Guarda y cambia el valor de la posición del puntero de registro
loSetting = CREATEOBJECT("SettingHandler", "GO 12 in [customers]") 
? RECNO("customers")
** Restaura el valor previo de la posición del puntero de registro
RELEASE loSetting 
? RECNO("customers")
?
? "SELECT:"
IF !USED("orders")
  USE (HOME(2) + "northwind\orders.dbf") IN 0 SHARED
ENDIF
SELECT "Orders"
? ALIAS()
** Guarda y cambia el valor del Alias actual
loSetting = CREATEOBJECT("SettingHandler", "Select Customers") 
? ALIAS()
** Restaura el valor previo del Alias actual
RELEASE loSetting 
? ALIAS()
USE IN SELECT("Customers")
USE IN SELECT("Orders")
*
******* Final de los ejemplos ******
*
************************************
*!* DEFINICIÓN DE CLASE
************************************
DEFINE CLASS SettingHandler as custom
  PROTECTED PreviousValue
  PreviousValue = .NULL.
  PROTECTED SettingCommand
  SettingCommand = ""
  PROTECTED SettingType && 0 = SET/ON, 1 = RECNO
  SettingType = -1
  #DEFINE SETTINGDELIMITERS [('" ] + "[])"

  PROCEDURE Init (tcCommand)
    This.Setup(tcCommand)
  ENDPROC

  PROTECTED PROCEDURE Destroy
    This.RevertSetting()
  ENDPROC

  PROCEDURE Setup (tcCommand)
    This.SettingCommand = ALLTRIM(tcCommand)
    This.SaveSetting()
    This.UpdateSetting()
  ENDPROC

  PROTECTED PROCEDURE SaveSetting
    LOCAL lcFirstPart, lcSecondPart, lnSecondPosition, lcCommand
    lcFirstPart = UPPER(ALLTRIM(GETWORDNUM(this.SettingCommand, ;
      1, SETTINGDELIMITERS)))
    DO CASE
      CASE INLIST(lcFirstPart, "SET", "ON")
        lcSecondPart = UPPER(ALLTRIM(GETWORDNUM(this.SettingCommand, ;
          2, SETTINGDELIMITERS)))
        lcCommand = lcFirstPart + [("] + lcSecondPart + [")]
        This.SettingType = 0
      CASE INLIST(lcFirstPart, "GOTO", "GO")
        lnSecondPosition = ATC(" IN ", this.SettingCommand)
        IF lnSecondPosition > 0
          lcSecondPart = SUBSTR(this.settingcommand, lnSecondPosition + 4)
        ELSE
          lcSecondPart = ""
        ENDIF
        lcCommand = [RECNO(] + lcSecondPart + [)]
        This.SettingType = 1
      CASE lcFirstPart = "SELECT"
        lcSecondPart = UPPER(ALLTRIM(GETWORDNUM(this.SettingCommand, ;
          2, SETTINGDELIMITERS)))
        lcCommand = [ALIAS()]
        This.SettingType = 2
    ENDCASE
    IF !EMPTY(lcCommand)
      This.PreviousValue = EVALUATE(lcCommand)
    ENDIF
  ENDPROC

  PROTECTED PROCEDURE UpdateSetting
    EXECSCRIPT(This.SettingCommand) && Cambia los valores
  ENDPROC

  PROTECTED PROCEDURE RevertSetting
    LOCAL lcCommand, lnStuffPosition, lnStuffLength, lcAliasWas
    DO CASE
      CASE This.SettingType = 0 && SET/ON
        lnStuffPosition = AT(" ", this.Settingcommand, 2) + 1
        lnStuffLength = LEN(this.settingcommand) - lnStuffPosition + 1
      CASE This.SettingType = 1 && GOTO/GO
        lnStuffPosition = AT(" RECORD ", UPPER(this.Settingcommand), 1) + 8
        IF lnStuffPosition < 9
          lnStuffPosition = AT(" ", this.Settingcommand, 1) + 1
          lnStuffLength = AT(" ", this.Settingcommand, 2)
          IF lnStuffLength > 0
            lnStuffLength = lnStuffLength - lnStuffPosition + 1
          ELSE
            lnStuffLength = LEN(this.settingcommand) - lnStuffPosition + 1
          ENDIF
        ELSE
          lnStuffLength = LEN(this.settingcommand) - lnStuffPosition + 1
        ENDIF
      CASE This.SettingType = 2 && SELECT
        lnStuffPosition = AT(" ", this.Settingcommand, 1) + 1
        lnStuffLength = LEN(this.settingcommand) - lnStuffPosition + 1
    ENDCASE
    IF !EMPTY(lnStuffPosition)
      lcCommand = STUFF(This.SettingCommand, lnStuffPosition, ;
        lnStuffLength, TRANSFORM(this.PreviousValue))
      ** Restablece el estado inicial antes de que fueran cambiado
      EXECSCRIPT(lcCommand) 
    ENDIF
  ENDPROC
ENDDEFINE

No hay comentarios. :

Publicar un comentario

Los comentarios son moderados, por lo que pueden demorar varias horas para su publicación.