From cea70820ee29767cef720c052399bda47f1cb8f5 Mon Sep 17 00:00:00 2001 From: Pritpal Bedi Date: Fri, 19 Aug 2011 10:10:58 +0000 Subject: [PATCH] 2011-08-19 02:58 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com) * contrib/hbcuied/cu_object.prg + Implemented: two-way saving/loading of screens from PRG sources. Alt+S - Save / Alt+L - Load, keys are defined. At startup, if hbCuiEd is invoked with a .prg file name as first and only parameter, then all screens embedded in the source are presented for selection, and selected screen is brought in the designer. On save the actual indent of the loaded screen is preserved which means screens can be designed in real-time. If there is a need screens can be edited in the PRG ( assumed, it follows the protocols laid down by the designer ). Screens can be saved with new name. In this case a new function as "hbcui_" + screen name will be appended to the source which later can be edited and placed anywhere in the PRG. Will write a test program to demonstrate its two-way capabilities in a couple of days. --- harbour/ChangeLog | 19 ++ harbour/contrib/hbcuied/cu_object.prg | 352 +++++++++++++++++++++++--- 2 files changed, 333 insertions(+), 38 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index bec7d0cd0b..74c4b30478 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -16,6 +16,25 @@ The license applies to all entries newer than 2009-04-28. */ +2011-08-19 02:58 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com) + * contrib/hbcuied/cu_object.prg + + Implemented: two-way saving/loading of screens from PRG sources. + Alt+S - Save / Alt+L - Load, keys are defined. + At startup, if hbCuiEd is invoked with a .prg file name + as first and only parameter, then all screens embedded + in the source are presented for selection, and selected + screen is brought in the designer. On save the actual + indent of the loaded screen is preserved which means + screens can be designed in real-time. If there is a need + screens can be edited in the PRG ( assumed, it follows the + protocols laid down by the designer ). Screens can be + saved with new name. In this case a new function as + "hbcui_" + screen name will be appended to the source + which later can be edited and placed anywhere in the PRG. + + Will write a test program to demonstrate its two-way + capabilities in a couple of days. + 2011-08-18 08:28 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com) * contrib/hbcuied/cu_object.prg * Changed: saves screen at the previous location in a PRG diff --git a/harbour/contrib/hbcuied/cu_object.prg b/harbour/contrib/hbcuied/cu_object.prg index e1f204d58d..f83184c558 100644 --- a/harbour/contrib/hbcuied/cu_object.prg +++ b/harbour/contrib/hbcuied/cu_object.prg @@ -77,7 +77,6 @@ CLASS hbCUIEditor DATA cSource INIT "" DATA cScreen INIT "" - DATA nIndent INIT 3 DATA lEdited INIT .f. DATA obj_ INIT {} @@ -199,7 +198,10 @@ CLASS hbCUIEditor METHOD scrVrbHeaders( nType ) METHOD scrGetProperty( nObj ) - METHOD scrUpdateSource( s ) + METHOD scrUpdateSource( prg_ ) + METHOD scrBuildSource( prg_, nIndent ) + METHOD scrBuildFunction( prg_ ) + METHOD scrBuildFromBuffer( cBuffer, cScreen ) ENDCLASS @@ -239,12 +241,39 @@ METHOD hbCUIEditor:destroy() /*----------------------------------------------------------------------*/ METHOD hbCUIEditor:scrLoad( cSource, cScreen ) - + LOCAL cBuffer, n, n1, nSel, aMatches, aMatch + LOCAL scr_:={} + IF empty( cSource ) .OR. ! hb_fileExists( cSource ) aadd( ::obj_, ::scrObjBlank() ) RETURN SELF ENDIF + IF empty( cScreen ) + // Pull out all screens embedded IN the source + cBuffer := hb_memoread( cSource ) + aMatches := hb_regExAll( "HB_SCREEN_BEGINS", cBuffer, .f., .f., 0, 1, .f. ) + IF ! empty( aMatches ) + FOR EACH aMatch IN aMatches + IF ( n := hb_at( "<", cBuffer, aMatch[ 2 ] ) ) > 0 + IF ( n1 := hb_at( ">", cBuffer, aMatch[ 2 ] ) ) > 0 + aadd( scr_, substr( cBuffer, n + 1, n1 - n - 1 ) ) + ENDIF + ENDIF + NEXT + ENDIF + IF ! empty( scr_ ) + B_MSG "Select a Screen" CHOOSE scr_ RESTORE SHADOW CENTER INTO nSel + IF nSel > 0 + cScreen := scr_[ nSel ] + ENDIF + ENDIF + ENDIF + + IF ! empty( cScreen ) + ::scrBuildFromBuffer( cBuffer, cScreen ) + ENDIF + ::cSource := cSource ::cScreen := iif( empty( cScreen ), 'Untitled', cScreen ) ::cFile := ::cScreen @@ -255,8 +284,222 @@ METHOD hbCUIEditor:scrLoad( cSource, cScreen ) //----------------------------------------------------------------------// +METHOD hbCUIEditor:scrBuildFromBuffer( cBuffer, cScreen ) + LOCAL cTokenB := "/* HB_SCREEN_BEGINS <" + cScreen + "> */" + LOCAL cTokenE := "/* HB_SCREEN_ENDS <" + cScreen + "> */" + LOCAL cCode, aCode, cLine, aAttr, aMatch, aMatches, nStart, nEnd, nLen, s, n, o_, a_ + + IF ( nStart := at( cTokenB, cBuffer ) ) > 0 + IF ( nEnd := at( cTokenE, cBuffer ) ) > 0 + cCode := substr( cBuffer, nStart + len( cTokenB ), nEnd - nStart - 1 - len( cTokenB ) ) + aCode := hb_aTokens( strtran( cCode, chr( 13 ), chr( 10 ) ), chr( 10 ) ) + IF ! empty( aCode ) + aAttr := {} + FOR EACH cLine IN aCode + cLine := alltrim( cLine ) + IF ! empty( cLine ) + IF left( cLine, 3 ) == "///" + aAttr := hb_aTokens( substr( cLine, 5 ), " " ) + aAttr[ 1 ] := val( aAttr[ 1 ] ) + aAttr[ 2 ] := val( aAttr[ 2 ] ) + aAttr[ 4 ] := val( aAttr[ 4 ] ) + aAttr[ 5 ] := val( aAttr[ 5 ] ) + + ELSE + SWITCH aAttr[ 2 ] + + CASE OBJ_O_BOX + aMatches := hb_regExAll( "^@|\bBOX\b|\bCOLOR\b", cLine, .f., .f., 0, 1, .f. ) + IF ! empty( nLen := len( aMatches ) ) + o_:= ::scrObjBlank() + // + o_[ OBJ_TYPE ] := OBJ_O_BOX + o_[ OBJ_ID ] := "Frame" + o_[ OBJ_F_LEN ] := 9 + o_[ OBJ_MDL_F_TYPE ] := 62 + + FOR EACH aMatch IN aMatches + SWITCH alltrim( upper( aMatch[ 1 ] ) ) + CASE "@" + n := aMatches[ aMatch:__enumIndex() + 1, 2 ] + s := alltrim( substr( cLine, aMatch[ 3 ] + 1, n - 1 - aMatch[ 3 ] ) ) + s := strtran( s, " ,", "," ) + s := strtran( s, ", ", "," ) + a_:= hb_aTokens( s, "," ) + + o_[ OBJ_ROW ] := val( alltrim( a_[ 1 ] ) ) + 1 + o_[ OBJ_COL ] := val( alltrim( a_[ 2 ] ) ) + 1 + o_[ OBJ_TO_ROW ] := val( alltrim( a_[ 3 ] ) ) + 1 + o_[ OBJ_TO_COL ] := val( alltrim( a_[ 4 ] ) ) + 1 + + EXIT + CASE "BOX" + IF nLen > 2 + n := aMatches[ aMatch:__enumIndex() + 1, 2 ] + s := alltrim( substr( cLine, aMatch[ 3 ] + 1, n - 1 - aMatch[ 3 ] ) ) + ELSE + s := substr( cLine, aMatch[ 3 ] + 1 ) + ENDIF + s := alltrim( s ) + s := strtran( s, '"', "" ) + o_[ OBJ_BOX_SHAPE ] := substr( s, 1, 8 ) + o_[ OBJ_PATTERN ] := iif( len( s ) == 9, "FILLED", "CLEAR" ) + + EXIT + CASE "COLOR" + o_[ OBJ_COLOR ] := alltrim( substr( cLine, aMatch[ 3 ] + 1 ) ) + + EXIT + ENDSWITCH + NEXT + aadd( ::obj_, o_ ) + ENDIF + EXIT + + CASE OBJ_O_TEXT + aMatches := hb_regExAll( "^@|\bSAY\b|\bCOLOR\b", cLine, .f., .f., 0, 1, .f. ) + IF ! empty( nLen := len( aMatches ) ) + o_:= ::scrObjBlank() + // + o_[ OBJ_TYPE ] := OBJ_O_TEXT + o_[ OBJ_ID ] := "Text" + + FOR EACH aMatch IN aMatches + SWITCH alltrim( upper( aMatch[ 1 ] ) ) + CASE "@" + n := aMatches[ aMatch:__enumIndex() + 1, 2 ] + s := alltrim( substr( cLine, aMatch[ 3 ] + 1, n - 1 - aMatch[ 3 ] ) ) + s := strtran( s, ", ", "," ) + a_:= hb_aTokens( s, "," ) + + o_[ OBJ_ROW ] := val( alltrim( a_[ 1 ] ) ) + 1 + o_[ OBJ_COL ] := val( alltrim( a_[ 2 ] ) ) + 1 + + EXIT + CASE "SAY" + IF nLen > 2 + n := aMatches[ aMatch:__enumIndex() + 1, 2 ] + s := alltrim( substr( cLine, aMatch[ 3 ] + 1, n - 1 - aMatch[ 3 ] ) ) + ELSE + s := substr( cLine, aMatch[ 3 ] + 1 ) + ENDIF + s := alltrim( s ) + s := substr( s, 2, len( s ) - 2 ) + + o_[ OBJ_EQN ] := s + o_[ OBJ_TO_ROW ] := o_[ OBJ_ROW ] + o_[ OBJ_TO_COL ] := o_[ OBJ_COL ] + len( s ) + o_[ OBJ_F_TYPE ] := "C" + o_[ OBJ_F_LEN ] := len( s ) + + EXIT + CASE "COLOR" + o_[ OBJ_COLOR ] := alltrim( substr( cLine, aMatch[ 3 ] + 1 ) ) + + ENDSWITCH + NEXT + + aadd( ::obj_, o_ ) + ENDIF + EXIT + + CASE OBJ_O_FIELD + aMatches := hb_regExAll( "^@|\bGET\b|\bPICTURE\b|\bCOLOR\b|\bWHEN\b|\bVALID\b", cLine, .f., .f., 0, 1, .f. ) + IF ! empty( nLen := len( aMatches ) ) + o_:= ::scrObjBlank() + // + o_[ OBJ_TYPE ] := OBJ_O_FIELD + + FOR EACH aMatch IN aMatches + SWITCH alltrim( upper( aMatch[ 1 ] ) ) + + CASE "@" + n := aMatches[ aMatch:__enumIndex() + 1, 2 ] + s := alltrim( substr( cLine, aMatch[ 3 ] + 1, n - 1 - aMatch[ 3 ] ) ) + s := strtran( s, ", ", "," ) + a_:= hb_aTokens( s, "," ) + + o_[ OBJ_ROW ] := val( alltrim( a_[ 1 ] ) ) + 1 + o_[ OBJ_COL ] := val( alltrim( a_[ 2 ] ) ) + 1 + o_[ OBJ_TO_ROW ] := o_[ OBJ_ROW ] + o_[ OBJ_TO_COL ] := o_[ OBJ_COL ] + aAttr[ 4 ] + o_[ OBJ_F_TYPE ] := aAttr[ 3 ] + o_[ OBJ_F_LEN ] := aAttr[ 4 ] + o_[ OBJ_F_DEC ] := aAttr[ 5 ] + + EXIT + + CASE "GET" + IF nLen > 2 + n := aMatches[ aMatch:__enumIndex() + 1, 2 ] + s := alltrim( substr( cLine, aMatch[ 3 ] + 1, n - 1 - aMatch[ 3 ] ) ) + ELSE + s := substr( cLine, aMatch[ 3 ] + 1 ) + ENDIF + s := alltrim( s ) + o_[ OBJ_ID ] := s + o_[ OBJ_EQN ] := padc( s, aAttr[ 4 ] ) + EXIT + + CASE "PICTURE" + IF aMatch:__enumIndex() < len( aMatches ) + n := aMatches[ aMatch:__enumIndex() + 1, 2 ] + o_[ OBJ_F_PIC ] := alltrim( substr( cLine, aMatch[ 3 ] + 1, n - 1 - aMatch[ 3 ] ) ) + ELSE + o_[ OBJ_F_PIC ] := alltrim( substr( cLine, aMatch[ 3 ] + 1 ) ) + ENDIF + EXIT + + CASE "COLOR" + IF aMatch:__enumIndex() < len( aMatches ) + n := aMatches[ aMatch:__enumIndex() + 1, 2 ] + o_[ OBJ_COLOR ] := alltrim( substr( cLine, aMatch[ 3 ] + 1, n - 1 - aMatch[ 3 ] ) ) + ELSE + o_[ OBJ_COLOR ] := alltrim( substr( cLine, aMatch[ 3 ] + 1 ) ) + ENDIF + EXIT + + CASE "WHEN" + IF aMatch:__enumIndex() < len( aMatches ) + n := aMatches[ aMatch:__enumIndex() + 1, 2 ] + o_[ OBJ_WHEN ] := alltrim( substr( cLine, aMatch[ 3 ] + 1, n - 1 - aMatch[ 3 ] ) ) + ELSE + o_[ OBJ_WHEN ] := alltrim( substr( cLine, aMatch[ 3 ] + 1 ) ) + ENDIF + EXIT + + CASE "VALID" + IF aMatch:__enumIndex() < len( aMatches ) + n := aMatches[ aMatch:__enumIndex() + 1, 2 ] + o_[ OBJ_VALID ] := alltrim( substr( cLine, aMatch[ 3 ] + 1, n - 1 - aMatch[ 3 ] ) ) + ELSE + o_[ OBJ_VALID ] := alltrim( substr( cLine, aMatch[ 3 ] + 1 ) ) + ENDIF + EXIT + + ENDSWITCH + + NEXT + + aadd( ::obj_, o_ ) + ENDIF + EXIT + + ENDSWITCH + aAttr := {} + ENDIF + ENDIF + NEXT + ENDIF + ENDIF + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + METHOD hbCUIEditor:scrSave( lAsk ) - LOCAL s, cP, o_, cSource, cScreen + LOCAL s, o_, cSource, cScreen local prg_:={} DEFAULT lAsk TO .f. @@ -283,10 +526,12 @@ METHOD hbCUIEditor:scrSave( lAsk ) aadd( prg_, "/* HB_SCREEN_BEGINS <" + ::cScreen + "> */" ) aadd( prg_, " " ) FOR EACH o_ IN ::obj_ - IF !empty( o_[ OBJ_TYPE ] ) - aadd( prg_, "/// " + iif( empty( o_[ OBJ_F_TYPE ] ), ".", o_[ OBJ_F_TYPE ] ) + " " + hb_ntos( o_[ OBJ_F_LEN ] ) + " " + hb_ntos( o_[ OBJ_F_DEC ] ) ) + IF ! empty( o_[ OBJ_TYPE ] ) + + aadd( prg_, "/// " + hb_ntos( o_:__enumIndex() ) + " " + hb_ntos( o_[ OBJ_TYPE ] ) + " " + ; + o_[ OBJ_F_TYPE ] + " " + hb_ntos( o_[ OBJ_F_LEN ] ) + " " + hb_ntos( o_[ OBJ_F_DEC ] ) ) - s := "@ " + hb_ntos( o_[ OBJ_ROW ] ) + ", " + hb_ntos( o_[ OBJ_COL ] ) + " " + s := "@ " + hb_ntos( o_[ OBJ_ROW ] - 1 ) + ", " + hb_ntos( o_[ OBJ_COL ] - 1 ) + " " SWITCH o_[ OBJ_TYPE ] @@ -296,18 +541,18 @@ METHOD hbCUIEditor:scrSave( lAsk ) s += "PICTURE " + o_[ OBJ_F_PIC ] + " " ENDIF IF !empty( o_[ OBJ_COLOR ] ) - s += "COLOR " + o_[ OBJ_COLOR ] + " " + s += "COLOR " + o_[ OBJ_COLOR ] + " " ENDIF IF !empty( o_[ OBJ_WHEN ] ) - s += "WHEN " + o_[ OBJ_WHEN ] + " " + s += "WHEN " + o_[ OBJ_WHEN ] + " " ENDIF IF !empty( o_[ OBJ_VALID ] ) - s += "VALID " + o_[ OBJ_VALID ] + " " + s += "VALID " + o_[ OBJ_VALID ] + " " ENDIF EXIT CASE OBJ_O_BOX - s += ", " + hb_ntos( o_[ OBJ_TO_ROW ] ) + ", " + hb_ntos( o_[ OBJ_TO_COL ] ) + " BOX " + ; + s += ", " + hb_ntos( o_[ OBJ_TO_ROW ] - 1 ) + ", " + hb_ntos( o_[ OBJ_TO_COL ] - 1 ) + " BOX " + ; '"' + o_[ OBJ_BOX_SHAPE ] + iif( o_[ OBJ_PATTERN ] == "CLEAR", "", " " ) + '"' + " " IF ! empty( o_[ OBJ_COLOR ] ) s += "COLOR " + o_[ OBJ_COLOR ] @@ -330,22 +575,41 @@ METHOD hbCUIEditor:scrSave( lAsk ) aadd( prg_, "/* HB_SCREEN_ENDS <" + ::cScreen + "> */" ) IF !empty( prg_ ) - s := "" - cP := space( ::nIndent ) - - aeval( prg_, {|e| s += cP + e + chr( 13 ) + chr( 10 ) } ) - - s := substr( s, 1, len( s ) - 2 ) - - ::scrUpdateSource( s ) + ::scrUpdateSource( prg_ ) ENDIF RETURN Self //----------------------------------------------------------------------// -METHOD hbCUIEditor:scrUpdateSource( s ) - LOCAL cBuffer, cTokenB, cTokenE, nStart, nEnd +METHOD hbCUIEditor:scrBuildFunction( prg_ ) + LOCAL s + + s := hb_eol() + s += "FUNCTION hbcui_" + lower( strtran( ::cScreen, " ", "_" ) ) + "()" + hb_eol() + s += hb_eol() + s += ::scrBuildSource( prg_, 3 ) + hb_eol() + s += hb_eol() + s += " RETURN NIL" + s += hb_eol() + + RETURN s + +/*----------------------------------------------------------------------*/ + +METHOD hbCUIEditor:scrBuildSource( prg_, nIndent ) + LOCAL cP, s := "" + + cP := space( nIndent ) + aeval( prg_, {|e| s += cP + e + hb_eol() } ) + s := substr( s, 1, len( s ) - len( hb_eol() ) ) + + RETURN s + +/*----------------------------------------------------------------------*/ + +METHOD hbCUIEditor:scrUpdateSource( prg_ ) + LOCAL cBuffer, cTokenB, cTokenE, nStart, nEnd, s, nIndent, cTmp IF hb_fileExists( ::cSource ) cBuffer := hb_memoread( ::cSource ) @@ -353,22 +617,33 @@ METHOD hbCUIEditor:scrUpdateSource( s ) cTokenE := "/* HB_SCREEN_ENDS <" + ::cScreen + "> */" IF ( nStart := at( cTokenB, cBuffer ) ) > 0 - IF ( nEnd := at( cTokenE, cBuffer ) ) > 0 - cBuffer := substr( cBuffer, 1, nStart - ::nIndent - 1 ) + s + substr( cBuffer, nEnd + len( cTokenE ) ) - hb_memowrit( ::cSource, cBuffer ) - alert( "Screen is saved in " + ::cSource ) - ::lEdited := .f. - ENDIF + nEnd := at( cTokenE, cBuffer ) + IF nEnd == 0 + nEnd := nStart + len( cTokenB ) + ELSE + nEnd += len( cTokenE ) + ENDIF + cTmp := substr( cBuffer, 1, nStart - 1 ) + nIndent := nStart - hb_rat( hb_eol(), cTmp ) - len( hb_eol() ) + + s := ::scrBuildSource( prg_, nIndent ) + s := substr( cBuffer, 1, nStart - nIndent - 1 ) + s + substr( cBuffer, nEnd ) + ELSE - // What TO DO ? + s := ::scrBuildFunction( prg_ ) + s := cBuffer + hb_eol() + s + ENDIF ELSE - hb_memowrit( ::cSource, s ) - alert( "Screen is saved in " + ::cSource ) - ::lEdited := .f. + s := ::scrBuildFunction( prg_) + ENDIF + hb_memowrit( ::cSource, s ) + alert( "Screen is saved in " + ::cSource ) + ::lEdited := .f. + RETURN Self /*----------------------------------------------------------------------*/ @@ -524,19 +799,21 @@ METHOD hbCUIEditor:operate() CASE ::nLastKey == K_ESC IF alert( "Do you want to exit ?", { "Yes","No" } ) == 1 IF ::lEdited - ::scrSave() + IF alert( "Screen has been edited, do you want to save ?", { "Yes","No" } ) == 1 + ::scrSave() + ENDIF ENDIF EXIT ENDIF CASE ::nLastKey == K_CTRL_ENTER - IF alert( "Do you want TO save screen ?", { "Yes","No" } ) == 1 + IF ::lEdited ::scrSave() ENDIF EXIT CASE ::nLastKey == K_ALT_L - ::scrLoad() + ::scrLoad( ::cSource, "" ) CASE ::nLastKey == K_ALT_S - ::scrSave() + ::scrSave( .t. ) CASE ::nLastKey == K_RIGHT ::scrMovRgt() @@ -580,7 +857,7 @@ METHOD hbCUIEditor:operate() ::nColsMax := max( ::nColsMax, ::obj_[ ::nObjSelected, OBJ_TO_COL ] + 1 ) ::nMode := OBJ_MODE_IDLE ::xRefresh := OBJ_REFRESH_LINE - ::nObjSelected := 0 + ::nObjSelected := 0 ::scrMsg() ENDIF @@ -2044,7 +2321,6 @@ METHOD hbCUIEditor:scrAddTxt( nMode ) txt_[ n1, OBJ_COL ] := ::nColRep+1 txt_[ n1, OBJ_EQN ] := s2 txt_[ n1, OBJ_ID ] := 'Text' - txt_[ n1, OBJ_SECTION ] := 1 txt_[ n1, OBJ_TO_ROW ] := ::nRowRep txt_[ n1, OBJ_TO_COL ] := txt_[ n1, OBJ_COL ] + len( s2 ) - 1 ENDIF @@ -2173,7 +2449,7 @@ METHOD hbCUIEditor:scrObjBlank() o_[ OBJ_TO_ROW ] := 0 o_[ OBJ_TO_COL ] := 0 o_[ OBJ_TEXT ] := "" - o_[ OBJ_F_TYPE ] := "" + o_[ OBJ_F_TYPE ] := "." o_[ OBJ_F_LEN ] := 0 o_[ OBJ_F_DEC ] := 0 o_[ OBJ_F_PIC ] := ""