Code: Select all
// FiveWin PIM (personal information manager)
#include "FiveWin.ch"
#include "Splitter.ch"
#include "xbrowse.ch"
static oWnd, oBtnSave, oImageList, oMruRCs
//----------------------------------------------------------------------------//
function Main()
local oBar, oMenuNew
local oBmpTiled
DEFINE BITMAP oBmpTiled RESOURCE "background"
DEFINE WINDOW oWnd FROM 3, 6 TO 20, 70 ;
TITLE FWVERSION + " PIM" ;
MENU BuildMenu() MDI
DEFINE BUTTONBAR oBar SIZE 70, 70 OF oWnd 2010
DEFINE BUTTON OF oBar PROMPT "New" ;
TOOLTIP "New" NOBORDER RESOURCE "New" ;
ACTION NewDataFile()
DEFINE BUTTON OF oBar PROMPT "Open" ;
TOOLTIP "Open" NOBORDER RESOURCE "Open" ;
ACTION OpenDataFile()
DEFINE BUTTON oBtnSave OF oBar PROMPT "Save" ;
TOOLTIP "Save" NOBORDER RESOURCE "Save" ACTION Save()
oBtnSave:Disable()
DEFINE BUTTON OF oBar GROUP PROMPT "Exit" ;
TOOLTIP "Exit" NOBORDER RESOURCE "Exit" ACTION oWnd:End()
oImageList = TImageList():New()
oImageList:Add( TBitmap():Define( "folder",, oWnd ),;
TBitmap():Define( "fldmask",, oWnd ) )
oImageList:Add( TBitmap():Define( "dialog",, oWnd ),;
TBitmap():Define( "dlgmask",, oWnd ) )
oImageList:Add( TBitmap():Define( "icon",, oWnd ),;
TBitmap():Define( "icomask",, oWnd ) )
oImageList:Add( TBitmap():Define( "bitmap",, oWnd ),;
TBitmap():Define( "bmpmask",, oWnd ) )
oImageList:Add( TBitmap():Define( "includes",, oWnd ),;
TBitmap():Define( "incmask",, oWnd ) )
DEFINE MSGBAR OF oWnd PROMPT "Personal Information Manager (c) FiveTech Software 2020" DATE KEYBOARD 2010
ACTIVATE WINDOW oWnd MAXIMIZED ;
ON PAINT DrawTiled( hDC, oWnd, oBmpTiled )
// VALID MsgYesNo( "Want to end ?" )
oBmpTiled:End()
oImageList:End()
return nil
//----------------------------------------------------------------------------//
function BuildMenu()
local oMenu
MENU oMenu 2007
MENUITEM "&File"
MENU
MENUITEM "&New" RESOURCE "new2"
MENUITEM "&Open" RESOURCE "Open2" ;
ACTION OpenDataFile()
MENUITEM "&Save as..."
SEPARATOR
MENUITEM "Recent files"
MENU
MRU oMruRCs ;
FILENAME ".\re.ini" ; // .INI to manipulate. '\.' for local
SECTION "Recent RC files" ; // The name of the INI section
ACTION OpenDataFile( cMruItem ) ; // cMruItem is automatically provided
MESSAGE "Open this file" ; // The message for all of them
SIZE 10
ENDMENU
SEPARATOR
MENUITEM "&Exit..." ACTION oWnd:End() RESOURCE "Exit2"
ENDMENU
MENUITEM "&Edit"
oMenu:AddMDI()
oMenu:AddHelp( "FiveWin Resources Editor", "FiveTech 1993-2018" )
ENDMENU
return oMenu
//----------------------------------------------------------------------------//
function Save()
local oTreeView := oWnd:oWndActive:aControls[ 1 ]
local cText := "", cFileName := oWnd:oWndActive:GetText()
oTreeView:Scan( { | oItem, nItem | BuildXML( oItem, @cText, nItem ) } )
if File( cFileName )
if MsgYesNo( "Do you want to overwrite " + cFileName + " ?",;
cFileName + " already exists" )
hb_MemoWrit( cFileName, cText, .F. )
MsgInfo( cText )
endif
else
hb_MemoWrit( cFileName, cText,.F. )
endif
oBtnSave:Disable()
return nil
//----------------------------------------------------------------------------//
function BuildXML( oItem, cText, nItem )
if oItem:oParent != nil
cText += CRLF
endif
if oItem:oParent == nil .and. nItem == 1
if oItem:cPrompt != "xml"
oItem:Cargo = oItem:cPrompt
oItem:cPrompt = "xml"
cText += "<" + oItem:Cargo + ">"
endif
endif
if " " $ oItem:cPrompt
oItem:cPrompt = StrTran( oItem:cPrompt, " ", "_" )
endif
cText += "<" + If( ! Empty( oItem:cPrompt ), oItem:cPrompt, "" ) + ">"
if ! Empty( oItem:Cargo )
cText += oItem:Cargo
endif
if Len( oItem:aItems ) == 0
cText += "</" + If( ! Empty( oItem:cPrompt ), oItem:cPrompt, "" ) + ">"
endif
if oItem:oParent != nil .and. oItem:cPrompt != "xml"
if oItem == ATail( oItem:oParent:aItems )
cText += CRLF + "</" + oItem:oParent:cPrompt + ">"
endif
endif
return .F. // so it iterates the entire tree
//----------------------------------------------------------------------------//
function NewDataFile( cFileName )
local oWndData, oTree, oMemo, cItemText, oSplit
DEFAULT cFileName := cNewFileName( "new", "xml" )
DEFINE WINDOW oWndData TITLE cFileName MDICHILD
oTree = TTreeView():New( 2, 0, oWndData )
oTree:bChanged = { | oItem | oItem := oTree:GetSelected(),;
If( oItem != nil, oMemo:SetText( If( ! Empty( oItem:Cargo ), oItem:Cargo, "" ) ),) }
// oTree:bLDblClick = { || ShowItem( oTree:GetSelected() ) }
oTree:bRClicked = { | nRow, nCol | EditTree( nRow, nCol, oWndData, oTree ) }
oTree:SetImageList( oImageList )
oTree:nWidth += 48
if ! File( cFileName )
hb_MemoWrit( cFileName, '<xml>version="1.0"<new></new></xml>', .F. )
OpenXml( cFileName, oTree )
endif
@ 0, 25.7 GET oMemo VAR cItemText MEMO OF oWndData SIZE 300, 100 ;
ON CHANGE ( oBtnSave:Enable(), oMemo:Cargo := .T.,;
oTree:GetSelected():Cargo := cItemText )
oMemo:Cargo = .F. // it has not changed
@ 0, 200 SPLITTER oSplit ;
VERTICAL ;
PREVIOUS CONTROLS oTree ;
HINDS CONTROLS oMemo ;
SIZE 4, 200 PIXEL ;
OF oWndData
oSplit:AdjClient()
ACTIVATE WINDOW oWndData ;
ON RESIZE oSplit:AdjClient()
oWndData:bGotFocus = { || If( oMemo:Cargo, oBtnSave:Enable(), oBtnSave:Disable() ) }
return nil
//----------------------------------------------------------------------------//
function OpenDataFile( cFileName )
local cTxtFile, oTree
DEFAULT cFileName := cGetFile( "XML files (*.xml) |*.xml| JSON files (*.json)", "Select a data file" )
if Empty( cFileName )
return nil
endif
oMruRCs:Save( cFileName )
oBtnSave:Disable()
NewDataFile( cFileName )
oTree = oWnd:oWndActive:aControls[ 1 ]
if ! Empty( cFileName )
do case
case Upper( cFileExt( cFileName ) ) == "XML"
OpenXML( cFileName, oTree )
case Upper( cFileExt( cFileName ) ) == "JSON"
OpenJSON( cFileName, oTree )
endcase
endif
return nil
//----------------------------------------------------------------------------//
function OpenXML( cFileName, oTree )
local aRoots := {}, hFile, oXmlDoc, oXmlIter, oTagLast, oTagActual
hFile = FOpen( cFileName )
oXmlDoc = TXmlDocument():New( hFile )
oXmlIter = TXmlIterator():New( oXmlDoc:oRoot )
AAdd( aRoots, oTree )
while ( oTagActual := oXmlIter:Next() ) != nil
if oTagLast != nil
if oTagLast:Depth() < oTagActual:Depth()
ASize( aRoots, Len( aRoots ) + 1 )
aRoots[ oTagActual:Depth() + 1 ] = aRoots[ oTagActual:Depth() ]:Add( oTagActual:cName )
aRoots[ oTagActual:Depth() + 1 ]:Cargo = oTagActual:cData
endif
if oTagLast:Depth() > oTagActual:Depth()
aRoots[ oTagActual:depth() + 1 ] = aRoots[ oTagActual:Depth() ]:Add( oTagActual:cName )
aRoots[ oTagActual:depth() + 1 ]:Cargo = oTagActual:cData
endif
if oTagLast:Depth() == oTagActual:Depth()
aRoots[ Max( oTagLast:Depth(), 1 ) ]:Add( oTagActual:cName ):Cargo = oTagActual:cData
endif
else
AAdd( aRoots, oTree:Add( oTagActual:cName ) )
ATail( aRoots ):Cargo = oTagActual:cData
endif
oTagLast = oTagActual
end
FClose( hFile )
return nil
//----------------------------------------------------------------------------//
function OpenJSON( cFileName )
return nil
//----------------------------------------------------------------------------//
function ShowImage( cBmp )
local oDlg, oBmp
DEFINE DIALOG oDlg TITLE cBmp
if Lower( Right( cBmp, 3 ) ) == "bmp"
@ 0, 0 BITMAP oBmp FILENAME cBmp OF oDlg NOBORDER
elseif Lower( Right( cBmp, 3 ) ) == "ico"
@ 0, 0 ICON oBmp FILENAME cBmp OF oDlg
endif
ACTIVATE DIALOG oDlg CENTERED ;
ON INIT ( oDlg:SetSize( Max( 300, oBmp:nWidth + 20 ),;
Max( 300, oBmp:nHeight + 20 ) ),;
oBmp:Center( oDlg ), oDlg:Center() )
return nil
//----------------------------------------------------------------------------//
function EditTree( nRow, nCol, oWndData, oTree )
local oPopup, cPrompt
MENU oPopup POPUP
MENUITEM "Add" ACTION If( oTree:GetSelected() != nil,;
( oTree:GetSelected():oParent:Add( "new" ), oTree:Refresh() ),;
( oTree:Add( "new" ), oTree:Refresh(), oBtnSave:Enable() ) )
MENUITEM "Add child" ACTION If( oTree:GetSelected() != nil,;
( oTree:GetSelected():Add( "new" ), oTree:Refresh(), oBtnSave:Enable() ),)
MENUITEM "Edit" ACTION ( cPrompt := PadR( oTree:GetSelected():cPrompt, 30 ),;
If( MsgGet( "Edit", "item prompt", @cPrompt ),;
( oTree:GetSelected():cPrompt := AllTrim( cPrompt ), oBtnSave:Enable() ),) )
MENUITEM "Delete" ACTION If( oTree:GetSelected() != nil,;
( oTree:GetSelected():End(), oTree:Refresh(), oBtnSave:Enable() ),)
ENDMENU
ACTIVATE POPUP oPopup WINDOW oWndData AT nRow, nCol
return nil
//----------------------------------------------------------------------------//
static function GenDblClickBlock( oCtrl )
return { || MsgInfo( oCtrl:nId ) }
//----------------------------------------------------------------------------//