#include "fivewin.ch"
#include "constant.ch"
#define DLG_nColorDlg RGB(245,245,235)
#define DLG_nColortitle1 RGB(219,230,244)
#define DLG_nColortitle2 RGB(207,221,239)
#define DLG_nColorBar1 RGB(250,250,245)
#define DLG_nColorBar2 RGB(245,245,235)
#define DLG_nColorBtn1 RGB(245,245,235)
#define DLG_nColorBtn2 RGB(250,250,245)
#define DLG_nColorBtnB RGB(195,195,185)
REQUEST DBFCDX
static l2Box,l3Box,l4Box
static nBoxNumber
STATIC aCheckboxPanelMap
function Main()
local oDlg, oBrw, oFont, oBold
local nBottom := 32.4
local nRight := 95
local nHt := nBottom * DLG_CHARPIX_H
local nWd := Max(nRight * DLG_CHARPIX_W, 180)
local oBox := Array(4) // 3+1
local oDbf, oState
local nRow
local aState := {}
l2Box := .F.
l3Box := .F.
l4Box := .F.
aCheckboxPanelMap:=array(3)
oFont := TFont():New("TAHOMA", 0, 14)
oBold := TFont():New( "TAHOMA", 0, 14,,.t. )
oState := TDataBase():Open(nil, "STATES", "DBFCDX", .T.)
oState:gotop()
Do While !oState:eof()
AADD(aState, {oState:CODE, oState:NAME})
oState:skip()
enddo
oState:close()
oDbf := TDataBase():Open(nil, "CUSTOMER", "DBFCDX", .T.)
DEFINE DIALOG oDlg SIZE nWd, nHt PIXEL TRUEPIXEL;
FONT oFont COLOR CLR_BLACK, RGB(245,245,235);
STYLE nOR(DS_MODALFRAME, WS_POPUP, WS_CAPTION, WS_SYSMENU, WS_MINIMIZEBOX)
@ 40, 10 XBROWSE oBrw SIZE -10,-60 PIXEL OF oDlg;
DATASOURCE oDbf;
COLUMNS "ID", "CITY", "STATE", "MARRIED", "AGE";
CELL LINES NOBORDER UPDATE
WITH OBJECT oBrw
:nRowHeight := 25
:l2007 := .F.
:l2015 := .T.
:lRecordSelector := .F.
:nColDividerStyle := LINESTYLE_LIGHTGRAY
:nRowDividerStyle := LINESTYLE_LIGHTGRAY
:nStretchCol := STRETCHCOL_WIDEST
:nMarqueeStyle := MARQSTYLE_HIGHLROW
:SetChecks()
:lHScroll := .F.
:CreateFromCode()
END
nRow := 440
oBox[1] := PanelBox(nRow, 10, 30, oDlg:nWidth - 20, DLG_nColorBar1, DLG_nColorBar2,oDlg)
nRow -= 31
oBox[2] := PanelBox(nRow, 10, 30, oDlg:nWidth - 20, DLG_nColorBar1, DLG_nColorBar2,oDlg)
nRow -= 31
oBox[3] := PanelBox(nRow, 10, 30, oDlg:nWidth - 20, DLG_nColorBar1, DLG_nColorBar2,oDlg)
nRow -= 31
oBox[4] := PanelBox(nRow, 10, 30, oDlg:nWidth - 20,DLG_nColorBar1, DLG_nColorBar2,oDlg)
ACTIVATE DIALOG oDlg CENTERED;
ON INIT (oBox[2]:hide(), oBox[3]:hide(), oBox[4]:hide(),;
Form_Check(oBox, oDbf, oBrw, oDlg, aState))
return nil
//----------------------------------------------------------------//
Function Form_Check(oBox, oDbf, oBrw, oDlg, aState)
local cFilter := ""
local aFilters := { { .F., "AGE>20" }, { .F., "STATE='NY'" }, { .F., "MARRIED" } }
local aCheck[3], n
local nRow := 8
local nCol := 120
local oSay
@ 8, 40 SAY { || "FILTER : " + cFilter } SIZE 400, 25 PIXEL OF oDlg CENTER UPDATE TRANSPARENT
@ nRow, 5 SAY oSay PROMPT "Filter by" SIZE 80, 20 PIXEL OF oBox[1];
COLOR CLR_BLACK, Rgb(250,250,245)
oSay:lTransparent := .T.
for n := 1 to Len(aFilters)
aCheck[n] := CreateChk(nRow, nCol, oBox, aFilters, n, oDbf, @cFilter, oBrw, oDlg, aState)
aCheck[n]:lTransparent := .T.
aCheck[n]:setcolor(CLR_BLACK, rgb(210,210,205))
nCol += 160
if n == 3
EXIT
endif
next
return nil
//----------------------------------------------------------------//
static function CreateChk(nRow, nCol, oBox, aFilters, nIndex, oDbf, cFilter, oBrw, oDlg, aState)
local oChk
@ nRow, nCol CHECKBOX oChk VAR aFilters[nIndex, 1];
PROMPT aFilters[nIndex, 2] SIZE 150, 15 PIXEL OF oBox[1];
ON CHANGE (cFilter := ResetFilter(aFilters, oDbf, oBox, oBrw, aState, nIndex ), oDlg:Update())
return oChk
//----------------------------------------------------------------//
Function Refresh_Filter(oDbf, oBrw, cFilter, aFilters)
local af := {}
AEVAL(aFilters, { |a| If(a[1], AAdd(af, a[2]), nil) })
cFilter := FW_ArrayAsList(af, " .AND. ")
oDbf:SetFilter(cFilter)
oDbf:GoTop()
oBrw:Refresh()
return nil
//-----------------------------------------------------------------------------//
function PanelBox(nTop, nLeft, nBottom, nRight, nClrLite, nClrDark,oDlg)
local oPanel,oBrush
Local aGrad := { nClrLite,nClrDark}
DEFINE BRUSH oBrush GRADIENT aGrad
oPanel:=Tpanel():New( nTop, nLeft,nTop+nBottom, nRight, oDlg)
oPanel:SetBrush( oBrush )
* oPanel:bPainted := { || oPanel:Box( 1,1,oPanel:nHeight-1,oPanel:nWidth-1 ) }
return oPanel
//-----------------------------------------------------------------------------//
FUNCTION ActivateNextBox( oBox, l2Box, l3Box, l4Box, oDlgx )
local nPanel
IF l2Box
IF l3Box
IF l4Box
// All boxes are already active, do nothing
ELSE
oBox[4]:Show()
oDlgx := oBox[4]
l4Box := .T.
nPanel:= 4
ENDIF
ELSE
oBox[3]:Show()
oDlgx := oBox[3]
l3Box := .T.
nPanel:= 3
ENDIF
ELSE
oBox[2]:Show()
oDlgx := oBox[2]
l2Box := .T.
nPanel:= 2
ENDIF
RETURN nPanel
//--------------------------------------------------------------------------//
FUNCTION DeactivateBox( oBox, nIndex, l2Box, l3Box, l4Box, oDlgx )
DO CASE
CASE nIndex == 2
IF l2Box
oBox[2]:Hide()
l2Box := .F.
oDlgx := NIL
AdjustPanelPosition(oBox, 2)
ENDIF
CASE nIndex == 3
IF l3Box
oBox[3]:Hide()
l3Box := .F.
oDlgx := NIL
AdjustPanelPosition(oBox, 3)
ENDIF
CASE nIndex == 4
IF l4Box
oBox[4]:Hide()
l4Box := .F.
oDlgx := NIL
AdjustPanelPosition(oBox, 4)
ENDIF
ENDCASE
RETURN NIL
//--------------------------------------------------------------------------//
// When a checkbox activates a panel, we add the mapping to our array
FUNCTION ActivatePanel(nCheckboxIndex, nPanelIndex)
aCheckboxPanelMap[nCheckboxIndex] := nPanelIndex
RETURN NIL
//--------------------------------------------------------------------------//
// When we want to deactivate a panel, we use mapping to find the panel
FUNCTION DeactivatePanel(nCheckboxIndex, oBox,oBrw)
LOCAL nPanelIndex := aCheckboxPanelMap[nCheckboxIndex]
IF nPanelIndex != NIL
oBox[nPanelIndex]:Hide()
aCheckboxPanelMap[nCheckboxIndex] := NIL
// Spostiamo gli altri pannelli
AdjustPanelPosition(oBox,oBrw)
ENDIF
RETURN NIL
//--------------------------------------------------------------------------//
// Function to move the remaining panels when one is deactivated
FUNCTION AdjustPanelPosition(oBox, oBrw)
LOCAL nDesiredTop := 440
LOCAL nPanelHeight := 30 // Height of the single panel
LOCAL nCurrentTop := nDesiredTop
// Calculate the number of active panels
LOCAL nActivePanels := 0
FOR nIndex := 2 TO LEN(oBox)
IF !Empty(oBox[nIndex])
nActivePanels++
ENDIF
NEXT
// Calculate the new position of the active panels
IF nActivePanels > 0
nCurrentTop -= nPanelHeight * nActivePanels
ENDIF
FOR nIndex := 2 TO LEN(oBox)
IF !Empty(oBox[nIndex])
oBox[nIndex]:nTop := nCurrentTop
nCurrentTop += nPanelHeight
ENDIF
NEXT
RETURN NIL
//--------------------------------------------------------------------------//
STATIC FUNCTION ResetFilter(aFilters, oDbf, oBox, oBrw, aState, nIndex)
LOCAL cFilter := ""
LOCAL af := {}
LOCAL cState := SPACE(25)
LOCAL lMarried := .F.
LOCAL nAge := 0
LOCAL oCmb, nState := 1
LOCAL nRow := 8
LOCAL oSay, oRadio, nRadio := 1, cMarried := ""
LOCAL oDlgx, i
LOCAL aAge := {"20", "40", "60"}
LOCAL nBoxHeight := 30
LOCAL nVisibleBoxHeight := 0
LOCAL oCtrl
LOCAL nPanel
oDlgx := NIL
IF aFilters[nIndex, 1]
// We use ActivateNextBox to get the number of the activated panel
nPanel := ActivateNextBox(oBox, @l2Box, @l3Box, @l4Box, @oDlgx)
nVisibleBoxHeight := 30
// We hide the controls if they are there in oDlgx
IF !Empty(oDlgx:acontrols)
FOR EACH oCtrl IN oDlgx:acontrols
oCtrl:hide()
NEXT
ENDIF
// We activate the panel corresponding to the checkbox
ActivatePanel(nIndex, nPanel)
DO CASE
CASE nIndex == 1 // Age
@ nRow, 5 SAY oSay PROMPT "Age:" SIZE 80, 20 PIXEL OF oDlgx;
COLOR CLR_BLACK, Rgb(250,250,245)
oSay:lTransparent := .T.
@ 0.4, 10 COMBOBOX oCmb VAR nAge ITEMS aAge;
SIZE 600, 90 OF oDlgx;
ON CHANGE (cFilter := 'AGE<' + LTrim(Str(nAge)),;
aFilters[1, 2] := cFilter,;
Refresh_Filter(oDbf, oBrw, @cFilter, aFilters))
CASE nIndex == 2 // State
@ nRow, 5 SAY oSay PROMPT "State:" SIZE 80, 20 PIXEL OF oDlgx;
COLOR CLR_BLACK, Rgb(250,250,245)
oSay:lTransparent := .T.
@ 0.4, 10 COMBOBOX oCmb VAR nState ITEMS ArrTranspose(aState)[2];
SIZE 600, 90 OF oDlgx;
ON CHANGE (cState := aState[nState][1],;
cFilter := 'STATE=' + "'" + cState + "'",;
aFilters[2, 2] := cFilter,;
Refresh_Filter(oDbf, oBrw, @cFilter, aFilters))
CASE nIndex == 3 // Married
@ nRow, 5 SAY oSay PROMPT "Married:" SIZE 80, 20 PIXEL OF oDlgx;
COLOR CLR_BLACK, Rgb(250,250,245)
oSay:lTransparent := .T.
@ 1, 80 RADIO oRadio VAR nRadio OF oDlgx UPDATE SIZE 80, 25 PIXEL;
PROMPT "Married";
ON CHANGE (IF(nRadio == 1, cMarried := ".T.", cMarried := ".F."),;
cFilter := 'MARRIED=' + cMarried,;
aFilters[3, 2] := cFilter,;
Refresh_Filter(oDbf, oBrw, @cFilter, aFilters))
@ 1, 400 RADIOITEM "Not Married" RADIOMENU oRadio;
OF oDlgx PIXEL SIZE 80, 20
ENDCASE
ELSE
// We deactivate the panel corresponding to the checkbox
DeactivatePanel(nIndex, oBox,oBrw)
nVisibleBoxHeight -= 30 // Let's remove the height of the deactivated panel
ENDIF
// Let's update the smaller browser size
oBrw:nBottomMargin += nVisibleBoxHeight
// Let's update the filter and browser
AEVAL(aFilters, { |a| If(a[1], AAdd(af, a[2]), NIL) })
cFilter := FW_ArrayAsList(af, " .AND. ")
oDbf:SetFilter(cFilter)
oDbf:GoTop()
oBrw:Refresh()
RETURN cFilter
//--------------------------------------------------------------------------//