Skip to content

Examples🔗

Real-world implementation examples of the Taboga Interactive Filter Library.

🎯 Basic Customer Browse🔗

📊 Simple Implementation🔗

! Basic customer browse with filtering
Customers PROCEDURE 

BRW1::View:Browse    VIEW(Customers)
                       PROJECT(CUS:Company)
                       PROJECT(CUS:FirstName)
                       PROJECT(CUS:LastName)
                       PROJECT(CUS:City)
                       PROJECT(CUS:State)
                       PROJECT(CUS:ZipCode)
                     END

Queue:Browse:1       QUEUE
CUS:Company            LIKE(CUS:Company)
CUS:FirstName          LIKE(CUS:FirstName)
CUS:LastName           LIKE(CUS:LastName)
CUS:City               LIKE(CUS:City)
CUS:State              LIKE(CUS:State)
CUS:ZipCode            LIKE(CUS:ZipCode)
CUS:CustNumber         LIKE(CUS:CustNumber)
Mark                   BYTE
ViewPosition           STRING(1024)
                     END

! Interactive Filter class
TIF2                 CLASS(TInteractiveFilterClass)
BrowseResetSort        PROCEDURE(BYTE Force),DERIVED
BrowseSetFilter        PROCEDURE(STRING Filter,STRING Id),DERIVED
InitComponents         PROCEDURE(),BYTE,PROC,DERIVED
                     END

QuickWindow          WINDOW('Browse Customers'),AT(,,447,197),RESIZE,CENTER
  LIST,AT(8,30,434,124),USE(?Browse:1),FROM(Queue:Browse:1)
  BUTTON,AT(5,158,14,14),USE(?TFilterFor),ICON('tint_FilterFor.ico'),FLAT
  CHECK,AT(19,158,14,14),USE(?TFilterToggle),ICON('tint_FilterToggle.ico'),FLAT
  BUTTON('Close'),AT(399,180,49,14),USE(?Close)
END

  CODE
  GlobalResponse = ThisWindow.Run()

ThisWindow.Init PROCEDURE
ReturnValue          BYTE,AUTO
  CODE
  ReturnValue = PARENT.Init()
  IF ReturnValue THEN RETURN ReturnValue.

  ! Initialize Interactive Filter
  TIF2.InitComponents
  ?TFilterToggle{PROP:Use} = TIF2.isInteractiveFilterOn
  TIF2.InteractiveFilterToggleControl = ?TFilterToggle
  DISABLE(?TFilterToggle)

  TIF2.UpdateQuery(0)        ! Auto-populate from browse
  TIF2.InitPopup            ! Setup context menus
  TIF2.CaseSensitivity = 0  ! Case insensitive

  RETURN ReturnValue

TIF2.InitComponents PROCEDURE
ReturnValue          BYTE,AUTO
  CODE
  ReturnValue = PARENT.InitComponents()

  SELF.myWindow           &= QuickWindow
  SELF.CollectionName = 'Customers'
  SELF.AllowFreeFormQuery = FALSE
  SELF.BrowseControl    = ?Browse:1
  SELF.BrowseView      &= BRW1::View:Browse
  SELF.BrowseQueueRef  &= Queue:Browse:1
  SELF.AllowQueryPersistance = TRUE
  SELF.LoadFilterEvent   = 4070
  SELF.SaveFilterEvent   = 4071
  SELF.OperatorInterface = 0

  RETURN ReturnValue

🎨 Advanced Product Browse🔗

📋 List Interface with Filter Display🔗

Products PROCEDURE 

! Enhanced configuration with visual feedback
TIF11                CLASS(TInteractiveFilterClass)
BrowseResetSort        PROCEDURE(BYTE Force),DERIVED
BrowseSetFilter        PROCEDURE(STRING Filter,STRING Id),DERIVED
InitComponents         PROCEDURE(),BYTE,PROC,DERIVED
                     END

QuickWindow          WINDOW('Browse Products'),AT(,,493,262),CENTER
  PROMPT('Current filter will be displayed below:'),AT(6,2,478,10)
  LIST,AT(8,65,475,115),USE(?Browse:1),FROM(Queue:Browse:1)

  ! Filter controls
  BUTTON,AT(4,204,14,14),USE(?TFilterFor),ICON('tint_FilterFor.ico'),FLAT
  CHECK,AT(18,204,14,14),USE(?TFilterToggle),ICON('tint_FilterToggle.ico'),FLAT

  ! Filter display
  PROMPT('Filter'),AT(5,223,349,36),USE(?TFilter)

  BUTTON('Close'),AT(441,206,49,14),USE(?Close)
END

TIF11.InitComponents PROCEDURE
ReturnValue          BYTE,AUTO
  CODE
  ReturnValue = PARENT.InitComponents()

  SELF.myWindow           &= QuickWindow
  SELF.CollectionName = 'Products'
  SELF.AllowFreeFormQuery = FALSE
  SELF.BrowseControl    = ?Browse:1
  SELF.BrowseView      &= BRW1::View:Browse
  SELF.BrowseQueueRef  &= Queue:Browse:1

  ! Use list interface for operators
  SELF.OperatorInterface = 1

  ! Display current filter
  SELF.InteractiveFilterResultFEQ = ?TFilter

  SELF.AllowQueryPersistance = TRUE
  SELF.LoadFilterEvent   = 4070
  SELF.SaveFilterEvent   = 4071

  RETURN ReturnValue

📅 Date/Numeric Filtering🔗

🕐 Inventory History Browse🔗

InvHist PROCEDURE 

! Specialized for date and numeric data
TIF7                 CLASS(TInteractiveFilterClass)
BrowseResetSort        PROCEDURE(BYTE Force),DERIVED
BrowseSetFilter        PROCEDURE(STRING Filter,STRING Id),DERIVED
InitComponents         PROCEDURE(),BYTE,PROC,DERIVED
                     END

BRW1::View:Browse    VIEW(InvHist)
                       PROJECT(INV:Date)
                       PROJECT(INV:TransType)
                       PROJECT(INV:ProductNumber)
                       PROJECT(INV:Quantity)
                       PROJECT(INV:VendorNumber)
                       PROJECT(INV:Cost)
                       PROJECT(INV:Notes)
                       JOIN(VEN:KeyVendorNumber,INV:VendorNumber)
                         PROJECT(VEN:VendorName)
                       END
                       JOIN(PRO:KeyProductNumber,INV:ProductNumber)
                         PROJECT(PRO:Description)
                       END
                     END

TIF7.InitComponents PROCEDURE
ReturnValue          BYTE,AUTO
  CODE
  ReturnValue = PARENT.InitComponents()

  SELF.myWindow           &= QuickWindow
  SELF.CollectionName = 'InvHist'
  SELF.AllowFreeFormQuery = FALSE
  SELF.BrowseControl    = ?Browse:1
  SELF.BrowseView      &= BRW1::View:Browse
  SELF.BrowseQueueRef  &= Queue:Browse:1
  SELF.AllowQueryPersistance = TRUE
  SELF.LoadFilterEvent   = 4070
  SELF.SaveFilterEvent   = 4071
  SELF.OperatorInterface = 0

  RETURN ReturnValue

! Event handling for date/numeric context
ThisWindow.TakeFieldEvent PROCEDURE
ReturnValue          BYTE,AUTO
  CODE
  ReturnValue = PARENT.TakeFieldEvent()

  CASE FIELD()
  OF ?Browse:1
    CASE EVENT()
    ELSE
       ! Enhanced context-sensitive filtering
       CASE EVENT()
       OF 4068  ! Contains/Less than or equal
          CASE(TIF7.CurrentType)
          OF 1     ! String
             TIF7.FilterOnOperator(e_tint_Contains)
          OF 2     ! Numeric  
             TIF7.FilterOnOperator(e_tint_LessOrEqualThan)
          OF 3     ! Date
             TIF7.FilterOnOperator(e_tint_LessOrEqualThan)
          OF 4     ! Time
             TIF7.FilterOnOperator(e_tint_LessOrEqualThan)
          END

       OF 4069  ! Not contains/Greater than or equal
          CASE(TIF7.CurrentType)
          OF 1     ! String
             TIF7.FilterOnOperator(e_tint_NotContains)
          OF 2     ! Numeric
             TIF7.FilterOnOperator(e_tint_LargerOrEqualThan)
          OF 3     ! Date
             TIF7.FilterOnOperator(e_tint_LargerOrEqualThan)
          OF 4     ! Time
             TIF7.FilterOnOperator(e_tint_LargerOrEqualThan)
          END
       END
    END
  END

  RETURN ReturnValue

💾 Custom Save/Load Implementation🔗

🔧 Enhanced Filter Persistence🔗

! Custom save procedure with additional validation
MyCustomSaveFilter PROCEDURE(* TInteractiveFilterClass pIFObj, <STRING pFilterName>)
xSavedFilterName     LIKE(_TF:SavedFilterName)
xFilterCount         LONG
Window WINDOW('Save Filter'),AT(,,300,80),GRAY,CENTER,MODAL
  PROMPT('Filter Name:'),AT(10,10)
  ENTRY(@s80),AT(10,25,200,12),USE(xSavedFilterName)
  STRING(@n3),AT(220,25),USE(xFilterCount)
  BUTTON('&Save'),AT(155,50,45,14),USE(?Save),DEFAULT
  BUTTON('&Cancel'),AT(205,50,45,14),USE(?Cancel)
END

  CODE
  ! Get current filter count
  xFilterCount = RECORDS(pIFObj.FilterRows)

  ! Validate filter exists
  IF NOT xFilterCount
     MESSAGE('No filter criteria to save!','Save Filter',ICON:Exclamation)
     RETURN TRUE
  END

  ! Get filter name from user
  IF NOT OMITTED(2)
     xSavedFilterName = CLIP(pFilterName)
  ELSE
     OPEN(Window)
     ACCEPT
        CASE FIELD()
        OF ?Save
           IF NOT xSavedFilterName
              MESSAGE('Please enter a filter name!','Save Filter',ICON:Exclamation)
              SELECT(?xSavedFilterName)
              CYCLE
           END
           POST(EVENT:CloseWindow)
        OF ?Cancel
           xSavedFilterName = ''
           POST(EVENT:CloseWindow)
        END
     END
     CLOSE(Window)
  END

  IF NOT xSavedFilterName
     RETURN TRUE  ! User cancelled
  END

  ! Save with timestamp
  CLEAR(_TFilters)
  _TF:FilterCollectionName = pIFObj.CollectionName
  _TF:SavedFilterName = xSavedFilterName & ' [' & FORMAT(TODAY(),@d6) & ']'

  ! Continue with standard save logic...
  ! (Implementation details as in tutorial)

  MESSAGE('Filter "' & xSavedFilterName & '" saved successfully!','Save Filter',ICON:Asterisk)
  RETURN FALSE

! Custom load with preview
MyCustomLoadFilter PROCEDURE(* TInteractiveFilterClass pIFObj)
xPreviewFilter       STRING(1000)
xAppendMode          STRING(10)

! Enhanced load dialog with preview
LoadWindow WINDOW('Load Saved Filter'),AT(,,400,250),GRAY,CENTER,MODAL
  LIST,AT(10,20,200,150),USE(?FilterList),FROM(FilterQueue)
  PROMPT('Preview:'),AT(220,20)
  TEXT,AT(220,35,170,100),USE(xPreviewFilter),READONLY
  OPTION('Load Mode'),AT(220,140,170,40),USE(xAppendMode),BOXED
    RADIO('Replace Current'),VALUE('REPLACE')
    RADIO('Add with AND'),VALUE('AND')
    RADIO('Add with OR'),VALUE('OR')
  END
  BUTTON('&Load'),AT(270,200,50,14),USE(?Load)
  BUTTON('&Cancel'),AT(330,200,50,14),USE(?Cancel)
END

  CODE
  ! Build filter list with preview
  ! Show enhanced load dialog
  ! Apply selected filter with chosen mode

  RETURN

🎯 Field Override Examples🔗

📝 Selective Field Configuration🔗

! Manual field configuration with overrides
TIF2.InitComponents PROCEDURE
ReturnValue          BYTE,AUTO
  CODE
  ReturnValue = PARENT.InitComponents()

  ! Standard configuration
  SELF.myWindow           &= QuickWindow
  SELF.CollectionName = 'CustomersAdvanced'
  SELF.BrowseControl    = ?Browse:1
  SELF.BrowseView      &= BRW1::View:Browse
  SELF.BrowseQueueRef  &= Queue:Browse:1

  ! Field overrides (applied before UpdateQuery)
  SELF.AddItemOverride('CUS:CustNumber','',TRUE)           ! Skip internal ID
  SELF.AddItemOverride('CUS:Company','Company Name',FALSE) ! Override title
  SELF.AddItemOverride('CUS:State','State/Province',FALSE) ! Localized title

  ! Auto-populate with overrides applied
  SELF.UpdateQuery(0)

  ! Manual additions for special fields
  SELF.AddItem('CUS:LastModified','Last Updated','@d6',e_tint_CaseSensitive)
  SELF.AddItem('CUS:CreditLimit','Credit Limit','@n$10.2',e_tint_CaseSensitive)

  RETURN ReturnValue

🔧 Legacy Clarion Implementation🔗

🏛️ Non-ABC Application🔗

! Legacy Clarion implementation
Customers PROCEDURE 

! Legacy popup handling variables
ItemName             CSTRING(101)
IconName             CSTRING(255)
ItemText             CSTRING(101)
TPopupText           CSTRING(1000)
PopupText            CSTRING(1000)

TIF2                 CLASS(TInteractiveFilterClass)
BrowseResetSort        PROCEDURE(BYTE Force),DERIVED
BrowseSetFilter        PROCEDURE(STRING Filter,STRING Id),DERIVED
InitComponents         PROCEDURE(),BYTE,PROC,DERIVED
TakeNewSelection       PROCEDURE(),DERIVED
                     END

Window WINDOW('Browse Customers'),AT(,,400,200)
  LIST,AT(10,30,380,130),USE(?Browse:1),FROM(BrowseQueue)
  BUTTON,AT(10,170,14,14),USE(?TFilterFor),ICON('tint_FilterFor.ico'),FLAT
  CHECK,AT(30,170,14,14),USE(?TFilterToggle),ICON('tint_FilterToggle.ico'),FLAT
  BUTTON('Close'),AT(350,170,40,14),USE(?Close)
END

  CODE
  OPEN(Window)

  ! Initialize filter
  TIF2.InitComponents
  ?TFilterToggle{PROP:Use} = TIF2.isInteractiveFilterOn
  TIF2.InteractiveFilterToggleControl = ?TFilterToggle
  DISABLE(?TFilterToggle)

  TIF2.UpdateQuery(0)
  TIF2.InitPopup
  TIF2.CaseSensitivity = 0

  ! Legacy accept loop
  ACCEPT
    CASE FIELD()
    OF ?Browse:1
      CASE EVENT()
      OF EVENT:NewSelection
        DO TakeNewSelection
      ELSE
        ! Filter event handling
        CASE EVENT()
        OF 4064
          TIF2.FilterOnOperator(e_tint_equals)
        OF 4065
          TIF2.FilterOnOperator(e_tint_NotEquals)
        OF 4067
          TIF2.FilterRemove
        END
      END

    OF ?TFilterFor
      IF EVENT() = EVENT:Accepted
         x# = TIF2.FilterFor()
      END

    OF ?TFilterToggle
      IF EVENT() = EVENT:Accepted
         IF TIF2.isInteractiveFilterOn AND TIF2.GetFilter()
            TIF2.ApplyFilter()
         ELSE
            TIF2.DisableFilter()
         END
      END

    OF ?Close
      IF EVENT() = EVENT:Accepted
         POST(EVENT:CloseWindow)
      END
    END
  END

  CLOSE(Window)

TIF2.InitComponents PROCEDURE
ReturnValue          BYTE,AUTO
  CODE
  ReturnValue = PARENT.InitComponents()

  SELF.myWindow           &= Window
  SELF.CollectionName = 'CustomersLegacy'
  SELF.BrowseControl    = ?Browse:1
  SELF.BrowseQueuePrefix = 'BRW1:'
  SELF.AllowQueryPersistance = FALSE  ! Simplified for legacy
  SELF.OperatorInterface = 0

  RETURN ReturnValue

TakeNewSelection ROUTINE
  ! Legacy popup menu building
  TIF2.TakeNewSelection
  PopupText = TPopupText
  ! Handle popup selection...

🎨 Multi-DLL Configuration🔗

🔧 DLL with Exported Classes🔗

! In main DLL application
APPLICATION('FilterLibrary'),DLL

! Extension configuration
[T] Enables "InteractiveFilter" functionality
  ☑ Export TInteractiveFilterClass
  ☑ Export ABC PopupClass

! Compilation symbols generated:
! _TIntFilterLinkMode_=>1;_TIntFilterDllMode_=>0

! In client application
APPLICATION('ClientApp'),EXE

! Extension configuration  
[T] Enables "InteractiveFilter" functionality
  ☑ Generate TInteractiveFilterClass as EXTERNAL
    External Source: Dynamic Link Library (DLL)

! Compilation symbols generated:
! _TIntFilterLinkMode_=>0;_TIntFilterDllMode_=>1

📊 Performance Optimization🔗

⚡ High-Performance Configuration🔗

! Optimized for large datasets
TIF2.InitComponents PROCEDURE
ReturnValue          BYTE,AUTO
  CODE
  ReturnValue = PARENT.InitComponents()

  ! Standard configuration
  SELF.myWindow           &= QuickWindow
  SELF.CollectionName = 'LargeDataset'
  SELF.BrowseControl    = ?Browse:1
  SELF.BrowseView      &= BRW1::View:Browse
  SELF.BrowseQueueRef  &= Queue:Browse:1

  ! Performance optimizations
  SELF.CaseSensitivity = 1                     ! Case sensitive for SQL
  SELF.AllowFreeFormQuery = FALSE              ! Disable complex queries
  SELF.OperatorInterface = 0                   ! Faster button interface

  ! Only add indexed fields
  SELF.AddItem('CUS:State','State','@s2',e_tint_CaseSensitive)      ! Indexed
  SELF.AddItem('CUS:ZipCode','Zip','@s10',e_tint_CaseSensitive)     ! Indexed
  SELF.AddItem('CUS:Company','Company','@s20',e_tint_CaseSensitive) ! Indexed

  ! Skip non-indexed fields to prevent slow queries

  RETURN ReturnValue

🎯 Integration Examples🔗

🔗 With Query-by-Example🔗

! Combining with existing QBE functionality
BRW1.SetAlerts PROCEDURE
  CODE
  ! Add QBE integration
  IF QBEActive
     SELF.Popup.AddItem('Switch to QBE','SwitchQBE')
  END

  ! Standard filter popup items
  SELF.Popup.AddItem(TIF2.FilterBySelectionText,'TFilterSelection')
  SELF.Popup.AddItemEvent('TFilterSelection',4064,?Browse:1)
  SELF.Popup.SetIcon('TFilterSelection','tint_FilterBySelection.ico')

  PARENT.SetAlerts

🎨 Custom Event Handling🔗

! Custom event numbers to avoid conflicts
TIF2.InitComponents PROCEDURE
ReturnValue          BYTE,AUTO
  CODE
  ReturnValue = PARENT.InitComponents()

  ! Custom event numbers
  SELF.LoadFilterEvent   = 5000  ! Instead of 4070
  SELF.SaveFilterEvent   = 5001  ! Instead of 4071

  ! Rest of configuration...
  RETURN ReturnValue

! Corresponding event handling
ThisWindow.TakeFieldEvent PROCEDURE
  CODE
  ! Handle custom events
  CASE EVENT()
  OF 5000  ! Custom load event
     MyCustomLoadFilter(TIF2)
  OF 5001  ! Custom save event
     MyCustomSaveFilter(TIF2)
  END

  RETURN PARENT.TakeFieldEvent()

These examples demonstrate the flexibility and power of the Taboga Interactive Filter Library across different scenarios and configurations.