# The MIT License (MIT)
#
# Copyright (C) 2026 Scott Duensing
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

.section Widgets
.topic widget.datactrl
.title DataCtrl
.toc 0 Data Widgets
.toc 0 DataCtrl
.index DataCtrl
.index wgtDataCtrl
.index Database Binding
.index Master-Detail

.h2 DataCtrl

A VB3-style Data control for database binding. Displays a visible navigation bar (|< < > >|) that connects to a SQLite database via dvxSql* functions. Reads all rows from the RecordSource query into an in-memory cache for bidirectional navigation. Fires a Reposition event each time the current row changes so bound controls can update. Supports master-detail linking between Data controls (via MasterSource / MasterField / DetailField), INSERT via AddNew, and DELETE via Delete. UPDATEs use the KeyColumn to identify the row.

The widget depends on the "dvxsql" library DXE; the navigation logic caches the full result set so there is no round-trip for MoveNext/MovePrev.

Header: widgets/dataCtrl.h

.h3 Creation

.code
WidgetT *data = wgtDataCtrl(parent);
.endcode

Set properties (DatabaseName, RecordSource, KeyColumn, etc.) and then call dataCtrlRefresh to populate.

.h3 API Functions

.index dataCtrlRefresh
.index dataCtrlMoveFirst
.index dataCtrlMoveNext
.index dataCtrlGetField
.index dataCtrlSetField
.index dataCtrlUpdate
.index dataCtrlAddNew
.index dataCtrlDelete

.table
  Function                                                   Description
  --------                                                   -----------
  WidgetT *dataCtrlCreate(parent)                            Create a Data control. Exposed as create in the API struct.
  void dataCtrlRefresh(w)                                    Re-execute the RecordSource query and rebuild the row cache.
  void dataCtrlMoveFirst(w)                                  Move the cursor to the first row.
  void dataCtrlMovePrev(w)                                   Move the cursor to the previous row.
  void dataCtrlMoveNext(w)                                   Move the cursor to the next row.
  void dataCtrlMoveLast(w)                                   Move the cursor to the last row.
  const char *dataCtrlGetField(w, colName)                   Get the value of a column in the current row (case-insensitive).
  void dataCtrlSetField(w, colName, value)                   Set the value of a column in the current row. Marks the row dirty.
  void dataCtrlUpdate(w)                                     Flush pending changes (INSERT or UPDATE) to the database.
  void dataCtrlUpdateRow(w)                                  Legacy wrapper around dataCtrlUpdate.
  void dataCtrlAddNew(w)                                     Append a blank row and move the cursor to it. The row is dirty and new until Update is called.
  void dataCtrlDelete(w)                                     Delete the current row from the cache and the database.
  void dataCtrlSetMasterValue(w, val)                        Set the master-detail filter value. Normally managed by the form runtime.
  int32_t dataCtrlGetRowCount(w)                             Get the total number of cached rows.
  int32_t dataCtrlGetColCount(w)                             Get the number of columns in the result set.
  const char *dataCtrlGetColName(w, col)                     Get the name of a column by index.
  const char *dataCtrlGetCellText(w, row, col)               Get the text of a specific cell.
  void dataCtrlSetCurrentRow(w, row)                         Set the current row by index. Auto-saves the previous row if dirty.
.endtable

.h3 API Struct (wgtRegisterApi "data")

.table
  Slot                 Function
  ----                 --------
  create               dataCtrlCreate
  refresh              dataCtrlRefresh
  moveFirst            dataCtrlMoveFirst
  movePrev             dataCtrlMovePrev
  moveNext             dataCtrlMoveNext
  moveLast             dataCtrlMoveLast
  getField             dataCtrlGetField
  setField             dataCtrlSetField
  updateRow            dataCtrlUpdateRow
  update               dataCtrlUpdate
  addNew               dataCtrlAddNew
  delete               dataCtrlDelete
  setMasterValue       dataCtrlSetMasterValue
  getRowCount          dataCtrlGetRowCount
  getColCount          dataCtrlGetColCount
  getColName           dataCtrlGetColName
  getCellText          dataCtrlGetCellText
  setCurrentRow        dataCtrlSetCurrentRow
.endtable

.h3 Properties (BASIC Interface)

.table
  Property       Type       Access       Description
  --------       ----       ------       -----------
  DatabaseName   String     Read/Write   Path to the SQLite database file.
  RecordSource   String     Read/Write   SQL query or table name for the result set.
  KeyColumn      String     Read/Write   Primary key column name (used for UPDATE/DELETE).
  MasterSource   String     Read/Write   Name of the master Data control for master-detail linking.
  MasterField    String     Read/Write   Column in the master control to read for the filter value.
  DetailField    String     Read/Write   Column in this table to filter by the master value.
  Caption        String     Read/Write   Text displayed on the navigator bar.
  BOF            Boolean    Read-only    True when the cursor is at the first row (or no rows).
  EOF            Boolean    Read-only    True when the cursor is past the last row (or no rows).
.endtable

.h3 Methods (BASIC Interface)

.table
  Method         Description
  ------         -----------
  AddNew         Append a blank row and move to it.
  Delete         Delete the current row.
  MoveFirst      Move the cursor to the first row.
  MoveLast       Move the cursor to the last row.
  MoveNext       Move the cursor to the next row.
  MovePrevious   Move the cursor to the previous row.
  Refresh        Re-execute the query and rebuild the cache.
  Update         Write pending changes to the database.
.endtable

.h3 Events

.table
  Event          Description
  -----          -----------
  Reposition     Fires when the current row changes. Default event.
  Validate       Fires before writing. Return false to cancel the write.
.endtable
