# buttonlb.4gl # Stuff to work with buttons, particularly enabling & disabling INCLUDE SYSTEM "ixapp.4gh" INCLUDE SYSTEM "ixwindow.4gh" INCLUDE SYSTEM "ixsuptbl.4gh" INCLUDE SYSTEM "ixvisobj.4gh" INCLUDE SYSTEM "ixviscon.4gh" INCLUDE SYSTEM "ixbutton.4gh" INCLUDE SYSTEM "ix4gl.4gh" #------------------------------------------------------------------------ FUNCTION activateBN(myVC ixVisualContainer, BNname CHAR(*)) RETURNING VOID # Input: VisualContainer of the button (SuperTable or Window) # Name of the button to activate # Assumes: Usually this is called from a menu item to duplicate # a button press. # Purpose: Activate the button in question # Returns: N/A #------------------------------------------------------------------------ VARIABLE myBN ixButton LET myBN = myVC.getContainedObjByName(BNname) IF myBN IS NOT NULL THEN CALL myBN.activate() END IF END FUNCTION # activateBN(myWN ixWindow, BNname CHAR(*)) #------------------------------------------------------------------------ FUNCTION ableBN(myVC ixVisualContainer, VOname CHAR(*), whatWay CHAR(*)) RETURNING VOID # Input: VisualContainer of the Object (SuperTable or Window) # Name of the Visual object to work on (Button or Menu) # "DIS"(able) or "EN"(able) # Assumes: Standard naming conventions. # See the quoted strings within the function. # Purpose: enable or disable the visual Object designated # Returns: N/A #------------------------------------------------------------------------ VARIABLE myVO ixVisualObject VARIABLE myST ixSuperTable VARIABLE MIname CHAR(*) VARIABLE lgth SMALLINT VARIABLE myWN ixWindow LET myVO = myVC.getContainedObjByName(VOname) IF myVO IS NOT NULL THEN IF whatWay = "DIS" THEN CALL myVO.disable() ELSE LET myST = myVC CAST ixSuperTable # enable non-buttons or non-movement buttons on request IF myVO.getClass() NOT MATCHES "*utton*" OR (VOname NOT MATCHES "*[Ff]irst*" AND VOname NOT MATCHES "*[Ll]ast*" AND VOname NOT MATCHES "*[Nn]ext*" AND VOname NOT MATCHES "*[Pp]rev*" AND VOname NOT MATCHES "*Delete*") THEN # enable the superFields # CALL ableSuperFields(myST, "EN") CALL myVO.enable() ELSE # enable movement buttons only where appropriate IF myST.getNumStoredRows(ixSuperTable::displayData) > 0 THEN CASE WHEN VOname MATCHES "*Delete*" LET whatWay = "EN" WHEN VOname MATCHES "*FirstRow*" OR VOname MATCHES "*PrevRow*" OR VOname MATCHES "*PrevPage*" IF (myST.getLayout() = ixSuperTable::freeForm AND myST.getCurrRowNum() <= 1) # for grid form, we'll turn off FirstRow & PrevPage # if the first row is on the screen OR (myST.getLayout() = ixSuperTable::gridForm AND myST.getCurrGridOffset() >= 0 AND (myST.getCurrRowNum() - myST.getCurrGridOffset()) <= 1) THEN # set up to disable instead LET whatWay = "DIS" END IF # (myST.getLayout() = ixSuperTable::freeForm ... WHEN VOname MATCHES "*LastRow*" OR VOname MATCHES "*NextRow*" OR VOname MATCHES "*NextPage*" IF (myST.getLayout() = ixSuperTable::freeForm AND myST.getCurrRowNum() = myST.getNumStoredRows(ixSuperTable::displayData)) OR (myST.getLayout() = ixSuperTable::gridForm AND myST.getNumDispRows() >= myST.getCurrGridOffset() AND myST.getCurrRowNum() + myST.getNumDispRows() - myST.getCurrGridOffset() > myST.getNumStoredRows(ixSuperTable::displayData)) THEN # set up to disable instead LET whatWay = "DIS" END IF # (myST.getLayout() = ixSuperTable::freeForm ... END CASE # VOname ... ELSE # myST.getNumStoredRows(ixSuperTable::displayData) = 0 # this happens if we delete the last row in our data set # all movement keys go off LET whatWay = "DIS" END IF # myST.getNumStoredRows(ixSuperTable::displayData) > 0 IF whatWay = "EN" THEN CALL myVO.enable() ELSE CALL myVO.disable() END IF # whatWay = "EN" END IF # myVO.getClass() NOT MATCHES "*utton*" ... END IF # whatWay = "DIS" # see if there's menu item(s) that need to be dis/enabled # get the menu item as well. # If it exists, it has the same prefix as the button, with a "MI" suffix LET lgth = LENGTH(VOname) - 2 LET MIname = VOname[1, lgth], "MI" # make sure our VisualContainer is a window LET myWN = myVC.getWindow() LET myVO = myWN.getContainedObjByName(MIname) IF myVO IS NOT NULL THEN IF whatWay = "EN" THEN CALL myVO.enable() ELSE CALL myVO.disable() END IF # whatWay = "EN" END IF # myVO IS NOT NULL THEN # if we're -abling a ??Next[Row|Page] or ??Prev[Row|Page] button, # there might be a Next/PrevJump menu item as well # In case they get added as buttons some time, they are named # [ff|gf][Next|Prev]JumpMI IF VOname MATCHES "*extRow*" OR VOname MATCHES "*revRow*" OR VOname MATCHES "*extPage*" OR VOname MATCHES "*revPage*" THEN LET MIname = VOname[1, 6], "JumpMI" LET myVO = myWN.getContainedObjByName(MIname) IF myVO IS NOT NULL THEN IF whatWay = "EN" THEN CALL myVO.enable() ELSE CALL myVO.disable() END IF # whatWay = "EN" END IF # myVO IS NOT NULL THEN END IF # VOname MATCHES "*extRow*" OR VOname MATCHES "*revRow*" END IF # myVO IS NOT NULL END FUNCTION # ableBN(myVC ixVisualContainer, VOname CHAR(*), whatWay CHAR(*)) #------------------------------------------------------------------------ FUNCTION ableMoveBNs(myST ixSuperTable, whatWay CHAR(*)) RETURNING VOID # Input: Visual Container (SuperTable only) # "DIS"(able) or "EN"(able) # Assumes: Buttons are contained by the SuperTable with which # they are supposed to work. # Standard control naming conventions (see the code). # Purpose: disable or enable buttons used to move from row to row # as the various flags and states dictate. #------------------------------------------------------------------------ DEFINE BNprefix CHAR(*) DEFINE BNname CHAR(*) IF myST.getLayout() = ixSuperTable::gridForm THEN # buttons begin with "gf" LET BNprefix = "gf" ELSE # myST.getLayout() = ixSuperTable::freeForm # buttons begin with "ff" LET BNprefix = "ff" END IF # myST.getLayout() = ixSuperTable::gridForm LET BNname = BNprefix CLIPPED, "FirstRowBN" CALL ableBN(myST,BNname,whatWay) LET BNname = BNprefix CLIPPED, "LastRowBN" CALL ableBN(myST,BNname,whatWay) IF BNprefix = "gf" THEN LET BNname = BNprefix CLIPPED, "PrevPageBN" CALL ableBN(myST,BNname,whatWay) LET BNname = BNprefix CLIPPED, "NextPageBN" CALL ableBN(myST,BNname,whatWay) ELSE LET BNname = BNprefix CLIPPED, "DeleteRowBN" CALL ableBN(myST,BNname,whatWay) LET BNname = BNprefix CLIPPED, "PrevRowBN" CALL ableBN(myST,BNname,whatWay) LET BNname = BNprefix CLIPPED, "NextRowBN" CALL ableBN(myST,BNname,whatWay) END IF # BNprefix = "gf" END FUNCTION # ableMoveBNs(myST ixSuperTable, whatWay CHAR(*)) #------------------------------------------------------------------------ FUNCTION ableBNs(myBN ixButton) RETURNING VOID # Input: Button just activated # Assumes: Standard Button naming conventions, as showd below. # Purpose: disable or enable buttons based on which button we just pushed # e.g. if apply is punched, apply & revert are disabled and # and the appropriate movement buttons are turned back on. # Returns: N/A #------------------------------------------------------------------------ VARIABLE BNname CHAR(*) VARIABLE BNprefix CHAR(*) VARIABLE myST ixSuperTable LET BNname = myBN.name.getValueStr() LET myST = myBN.getVisualContainer() IF myST.getLayout() = ixSuperTable::gridForm THEN # buttons begin with "gf" LET BNprefix = "gf" ELSE # myST.getLayout() = ixSuperTable::freeForm # buttons begin with "ff" LET BNprefix = "ff" END IF # myST.getLayout() = ixSuperTable::gridForm CASE WHEN BNprefix = "ff" AND (BNname = "queryBN" OR BNname MATCHES "*Insert*") CALL ableBN(myST,"queryBN","DIS") LET BNname = BNprefix CLIPPED, "InsertRowBN" CALL ableBN(myST,BNname,"DIS") # enable/disable DeleteRow, NextRow, ... etc in a group CALL ableMoveBNs(myST,"DIS") CALL ableBN(myST,"applyBN","EN") CALL ableBN(myST,"revertBN","EN") WHEN BNprefix = "gf" AND (BNname MATCHES "*DeleteRowBN" OR BNname MATCHES "*InsertRowBN" OR BNname MATCHES "*FillBN" ) CALL ableBN(myST,"applyBN","EN") CALL ableBN(myST,"revertBN","EN") WHEN BNname = "applyBN" OR BNname = "revertBN" OR (BNprefix = "ff" AND BNname MATCHES "*DeleteRowBN") CALL ableBN(myST,"queryBN","EN") LET BNname = BNprefix CLIPPED, "InsertRowBN" CALL ableBN(myST,BNname,"EN") # enable/disable ffDeleteRow, ffNextRow, ... etc in a group CALL ableMoveBNs(myST,"EN") CALL ableBN(myST,"applyBN","DIS") CALL ableBN(myST,"revertBN","DIS") END CASE # BNname END FUNCTION # ableBNs(myBN ixButton) RETURNING VOID #------------------------------------------------------------------------ FUNCTION disableEditBNs(myST ixSuperTable) RETURNING VOID # Input: superTable whose buttons we're working # Assumes: Standard Naming conventions. # Purpose: disable the edit buttons of the SuperTable in question # This function is called from cellKeyPress of the *other* SuperTable # (e.g. if myST is a Detail, the function was called when we set # the update keys of the Master ST and vice versa) # Returns: N/A #------------------------------------------------------------------------ VARIABLE BNname CHAR(*) VARIABLE BNprefix CHAR(*) VARIABLE myWN ixWindow IF myST.getLayout() = ixSuperTable::freeForm THEN LET BNprefix = "ff" ELSE LET BNprefix = "gf" END IF # myST.getLayout() = ixSuperTable::freeForm LET BNname = "queryBN" CALL ableBN(myST, BNname, "DIS") LET BNname = BNprefix CLIPPED, "InsertRowBN" CALL ableBN(myST, BNname, "DIS") LET BNname = BNprefix CLIPPED, "DeleteRowBN" CALL ableBN(myST, BNname, "DIS") LET BNname = BNprefix CLIPPED, "FillBN" CALL ableBN(myST, BNname, "DIS") IF BNprefix = "ff" THEN # display freeForm movement keys CALL ableMoveBNs(myST,"DIS") END IF LET myWN = myST.getWindow() LET BNname = "applyBN" CALL ableBN(myWN, BNname, "DIS") LET BNname = "revertBN" CALL ableBN(myWN, BNname, "DIS") # disable the superFields #CALL ableSuperFields(myST, "DIS") END FUNCTION # disableEditBNs(myST ixSuperTable) #------------------------------------------------------------------------ FUNCTION enableForUpdateBNs(mySF ixSuperField, otherST ixSuperTable) RETURNING VOID # Input: Visual Object we just made some change to. (SuperField), # The Master/Detail SuperTable we may need to check # Assumes: Standard Naming conventions. # Purpose: disable or enable buttons when we're in UPDATE mode. # This function is called from cellKeyPress for any cells that # are active for updating, and from the picker functions if # anything was picked. # Returns: N/A #------------------------------------------------------------------------ VARIABLE BNname CHAR(*) VARIABLE BNprefix CHAR(*) VARIABLE myBN ixButton VARIABLE myST ixSuperTable VARIABLE myWN ixWindow VARIABLE ok BOOLEAN # we only have to do this if we're in displayData mode and we haven't # done it already (which we can tell because if we haven't done it before, # the applyBN will be disabled). LET myST = mySF.getVisualContainer() LET myWN = mySF.getWindow() LET myBN = myWN.getContainedObjByName("applyBN") IF NOT myBN.isEnabled() AND myST.getDisplayMode() = ixSuperTable::displayData THEN IF myST.getLayout() = ixSuperTable::gridForm THEN # buttons begin with "gf" LET BNprefix = "gf" ELSE # myST.getLayout() = ixSuperTable::freeForm # buttons begin with "ff" LET BNprefix = "ff" END IF # myST.getLayout() = ixSuperTable::gridForm CALL ableBN(myST,"queryBN","DIS") # delete insert Row & movement for free form SuperTables IF BNprefix = "ff" THEN LET BNname = BNprefix CLIPPED, "InsertRowBN" CALL ableBN(myST,BNname,"DIS") # disable movement buttons CALL ableMoveBNs(myST,"DIS") END IF # BNprefix = "ff" CALL ableBN(myST,"applyBN","EN") CALL ableBN(myST,"revertBN","EN") # put up a message to tell them about the change # CALL TBMessage(myWN,"5",FALSE) # Make Changes as Required ... # disable the other superTable edit buttons IF otherST IS NOT NULL THEN CALL disableEditBNs(otherST) END IF # otherST IS NOT NULL THEN CALL mySF.focus() END IF # NOT myBN.isEnabled() AND myST.getDisplayMode() = ... END FUNCTION # enableForUpdateBNs(mySF ixSuperField, otherST ixSuperTable) #------------------------------------------------------------------------ FUNCTION nextRowActivate(myBN ixButton) RETURNING VOID # Input: Next Row Button # Assumes: Next Row Button is contained by the SuperTable with which it works. # Purpose: Fetch the next row in the set. # Returns: N/A #------------------------------------------------------------------------ VARIABLE ok BOOLEAN VARIABLE superTable ixSuperTable VARIABLE rowPosition INTEGER LET superTable = (myBN.getVisualContainer() CAST ixSuperTable) LET rowPosition = superTable.getCurrRowNum() + 1 # get the number of rows for the current displayMode IF rowPosition > superTable.getNumStoredRows(NULL) THEN LET rowPosition = ixSuperTable::lastRow END IF LET ok = superTable.setCurrentCell(rowPosition, ixSuperTable::currentColumn) END FUNCTION # nextRowActivate(myBN ixButton) RETURNING VOID #------------------------------------------------------------------------ FUNCTION prevRowActivate(myBN ixButton) RETURNING VOID # Input: Prev Row Button # Assumes: Prev Row Button is contained by the SuperTable with which it works. # Purpose: Fetch the prev row in the set. # Returns: N/A #------------------------------------------------------------------------ VARIABLE ok BOOLEAN VARIABLE superTable ixSuperTable VARIABLE rowPosition INTEGER LET superTable = (myBN.getVisualContainer() CAST ixSuperTable) LET rowPosition = superTable.getCurrRowNum() - 1 IF rowPosition < 1 THEN LET rowPosition = 1 END IF LET ok = superTable.setCurrentCell(rowPosition, ixSuperTable::currentColumn) END FUNCTION # prevRowActivate(myBN ixButton) #------------------------------------------------------------------------ FUNCTION firstRowActivate(myBN ixButton) RETURNING VOID # Input: First Row Button # Assumes: First Row Button is contained by the SuperTable with which it works. # Purpose: Fetch the First row in the set. # Returns: N/A #------------------------------------------------------------------------ VARIABLE ok BOOLEAN VARIABLE superTable ixSuperTable LET superTable = (myBN.getVisualContainer() CAST ixSuperTable) LET ok = superTable.setCurrentCell(1, ixSuperTable::currentColumn) END FUNCTION # firstRowActivate(myBN ixButton) #------------------------------------------------------------------------ FUNCTION lastRowActivate(myBN ixButton) RETURNING VOID # Input: Last Row Button # Assumes: Last Row Button is contained by the SuperTable with which it works. # Purpose: Fetch the Last row in the set. # Returns: N/A #------------------------------------------------------------------------ VARIABLE ok BOOLEAN VARIABLE superTable ixSuperTable LET superTable = (myBN.getVisualContainer() CAST ixSuperTable) LET ok = superTable.setCurrentCell(ixSuperTable::lastRow, ixSuperTable::currentColumn) END FUNCTION # lastRowActivate(myBN ixButton) #------------------------------------------------------------------------ FUNCTION nextPageActivate(myBN ixButton) RETURNING VOID # Input: Next page Button # Assumes: Next page Button is contained by the SuperTable with which it works. # Purpose: Fetch the Next page in the set. # Returns: N/A #------------------------------------------------------------------------ VARIABLE ok BOOLEAN VARIABLE superTable ixSuperTable LET superTable = (myBN.getVisualContainer() CAST ixSuperTable) LET ok = superTable.pageDown() END FUNCTION # nextPageActivate(myBN ixButton) #------------------------------------------------------------------------ FUNCTION prevPageActivate(myBN ixButton) RETURNING VOID # Input: Prev page Button # Assumes: Prev page Button is contained by the SuperTable with which it works. # Purpose: Fetch the Next page in the set. # Returns: N/A #------------------------------------------------------------------------ VARIABLE ok BOOLEAN VARIABLE superTable ixSuperTable LET superTable = (myBN.getVisualContainer() CAST ixSuperTable) LET ok = superTable.pageUp() END FUNCTION # prevPageActivate(myBN ixButton) #------------------------------------------------------------------------ FUNCTION applyActivate(myBN ixButton) RETURNING VOID # Input: Apply Button # Assumes: Apply Button is contained by the SuperTable with which it works. # Purpose: Do what the apply button is supposed to for various # situations # Returns: N/A #------------------------------------------------------------------------ VARIABLE myST ixSuperTable VARIABLE myWN ixWindow VARIABLE ok BOOLEAN LET myST = myBN.getVisualContainer() LET myWN = myST.getWindow() # if we're in displayData mode, # treat this button as the default apply Button IF myST.getDisplayMode() = ixSuperTable::displayData THEN IF myST.getLayout() = ixSuperTable::freeForm THEN LET ok = FALSE IF myST.acceptRow() THEN LET ok = myST.applyRowSQL (myST.getRowByNumber(displayMode: ixSuperTable:: displayData)) # put up a message # CALL TBMessage(myWN, "4", FALSE) # Row Applied # set the buttons CALL ableBNs(myBN) END IF # myST.acceptRow() ELSE # myST.getLayout() = ixSuperTable::gridForm THEN CALL myST.unHighlightRow(NULL) LET ok = myST.apply() END IF # myST.getLayout() = ixSuperTable::freeForm IF ok THEN # commit CALL (myST.getConnection()).transact(mode: ixSQLConnect::SQL_Commit) # put up a message # CALL TBMessage(myWN, "4", FALSE) # Row Applied # set the buttons CALL ableBNs(myBN) ELSE # roll back CALL (myST.getConnection()).transact(mode: ixSQLConnect::SQL_Rollback) END IF # ok ELSE # for displayQuery mode (freeForm only for now), # do what the Retrieve button usually does # CALL TBmessage(myWN,2,FALSE) # Searching ... IF ixApp::setCursor (ixApp::busyCur) THEN END IF LET ok = myST.retrieve( QBE: TRUE ) IF ixApp::setCursor (ixApp::standardCur) THEN END IF # set the buttons CALL ableBNs(myBN) END IF # myST.getDisplayMode() = ixSuperTable::displayData END FUNCTION # applyActivate(myBN ixButton) #------------------------------------------------------------------------ FUNCTION revertActivate(myBN ixButton) RETURNING VOID # Input: Revert Button # Assumes: Revert Button is contained by the SuperTable with which it works. # Purpose: Do what the Revert button is supposed to for various # situations # Returns: N/A #------------------------------------------------------------------------ VARIABLE myST ixSuperTable VARIABLE myWN ixWindow VARIABLE myRow ixRow VARIABLE ok BOOLEAN LET myST = myBN.getVisualContainer() LET myWN = myST.getWindow() CASE WHEN myST.getLayout() = ixSuperTable::gridForm # this is a revert of gridForm changes CALL myST.unHighlightRow(NULL) LET ok = myST.revert() WHEN myST.getDisplayMode() = ixSuperTable::displayQuery # this was a Query, reset any prior retrieve CALL myST.setDisplayMode(displayMode: ixSuperTable::displayData, clear: FALSE) WHEN myST.getChangeFlag(colNum:NULL) = ixSuperTable::isNew OR myST.getChangeFlag(colNum:NULL) = ixSuperTable::isNewModified # this was an insert LET myRow = myST.delete() OTHERWISE # this was an update LET ok = myST.revert() END CASE #CALL TBMessage(myWN, "3", FALSE) # Action Cancelled # set the buttons CALL ableBNs(myBN) END FUNCTION # revertActivate(myBN ixButton) #------------------------------------------------------------------------ FUNCTION insertRowActivate(myBN ixButton) RETURNING VOID # Input: Insert Row Button # Assumes: Insert Row Button is contained by the SuperTable with which it works. # Purpose: Insert a blank row into the dataset # Returns: N/A #------------------------------------------------------------------------ VARIABLE rowNum INTEGER VARIABLE superTable ixSuperTable LET superTable = (myBN.getVisualContainer() CAST ixSuperTable) LET rownum = superTable.insert() # set the buttons CALL ableBNs(myBN) END FUNCTION # insertRowActivate(myBN ixButton) #------------------------------------------------------------------------ FUNCTION deleteRowActivate(myBN ixButton) RETURNING VOID # Input: Delete Row Button # Assumes: Delete Row Button is contained by the SuperTable with which it works. # Cascading deletes take care for child tables. # Purpose: Delete the current row of the Dataset. # For freeForm SuperTables, prompt to confirm the # deletion and remove the row from the database. # Returns: N/A #------------------------------------------------------------------------ VARIABLE deletedRow ixRow VARIABLE superTable ixSuperTable VARIABLE ok BOOLEAN LET superTable = (myBN.getVisualContainer() CAST ixSuperTable) IF superTable.getLayout() = ixSuperTable::freeForm THEN # confirm the delete for Free From SuperTables # LET ok = okToDelete() ELSE # just assume ok for gridForm SuperTables LET ok = TRUE END IF # superTable.getLayout() = ixSuperTable::freeForm IF ok THEN #just use default rowNum = currentRow LET deletedRow = superTable.delete() IF superTable.getLayout() = ixSuperTable::freeForm THEN # lose it from the Database right away; # for gridForm we wait until apply() IF superTable.applyRowSQL(deletedRow) THEN CALL (superTable.getConnection()). transact(mode: ixSQLConnect::SQL_Commit) END IF END IF # set the buttons CALL ableBNs(myBN) END IF # ok END FUNCTION # deleteRowActivate(myBN ixButton) #------------------------------------------------------------------------ FUNCTION queryActivate(myBN ixButton) RETURNING VOID # Input: the Query Button # Assumes: Query Button contianed by its SuperTable # Purpose: Put the user into QBE. # Returns: N/A #------------------------------------------------------------------------ VARIABLE superTable ixSuperTable LET superTable = (myBN.getVisualContainer() CAST ixSuperTable) # set the buttons CALL superTable.setDisplayMode(displayMode: ixSuperTable::displayQuery, clear: FALSE) CALL ableBNs(myBN) END FUNCTION # queryActivate(myBN ixButton)