2018-04-25 20:43:41 +02:00
|
|
|
/*
|
|
|
|
|
* File: LBoundGrid.h
|
2022-11-19 16:05:44 +01:00
|
|
|
* Author: Saleem Edah-Tally - nmset@yandex.com
|
2018-04-25 20:43:41 +02:00
|
|
|
* License : LGPL version 2.1
|
2022-11-19 16:05:44 +01:00
|
|
|
* Copyright Saleem Edah-Tally, M. D. - © 2014
|
2018-04-25 20:43:41 +02:00
|
|
|
*
|
|
|
|
|
* Created on 9 juin 2014, 16:40
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef LBOUNDGRID_H
|
Added classes to manage simple tabular data of known structure using a
popup containing a wxGrid object.
BasePicker : Abstract class adding a popup to wxPickerBase styled with
a wxTextCtrl.
BaseGridPicker : Abstract class adding a wxGrid in the popup.
JsonGridPickerCtrl : UI control storing the tabular data in a JSON
array.
LBoundJsonGridPicker : connect JsonGridPicker to database.
LGridJsonCellEditor : use LBoundJsonGridPicker in other wxGrid objects.
LGridJsonCellRenderer : render cell JSON data.
XmlGridPickerCtrl : UI control storing the tabular data in as XML
document.
LBoundXmlGridPicker : connect XmlGridPicker to database.
LGridXmlCellEditor : grid editor for LBoundXmlGridPicker.
LGridXmlCellRenderer : grid renderer for LBoundXmlGridPicker.
JsonHelper and XmlHelper : for applications to quickly get intent value
from database data..
The structure of managed tabular data :
Column 1 : Intent - this is what we want to store/edit. This can be
telephone numbers, email addresses, instant messaging addresses...
any single line piece of information that can exist many times for one
entity (person, company...).
Column 2 : Type - A short description of the intent : 'Home, Work,
Mobile, Fax, Other...'. It is displayed in a non editable wxComboBox.
Column 3 : Preferred - One line of data can be selected as the preferred
one. It is not mandatory, but it must be a single choice.
Column 4 : Notes - single line notes.
Adjust sql scripts and L7.dox.
Applied ANSI formatting style to all files.
Other changes :
Work around a nasty misbehavior.
Grid columns edited by a translated combobox expect full string
data as cell values. LResultSet::BEData() will report these mapped strings,
instead of database real data. LBoundComboBox::IsDirty() will always be
true even if the editor is unchanged once created.
Simplest workaround : disconnect m_BoundComboBox if unchanged.
LGridTextEditor::ProvideFormEditor() : set the form editor's value
explicitely.; wxTextCtrl does not interpret data it receives
LBoundControl::SetNull must be void.
LBoundGrid : Unbind:: instructions should limit to the widget's id, like Bind::
LConnection::GetReturnedKeys should return NULL.
LConnection::SetData should return void.
Notes : wxJSON must be configured with the same prefix as wxWidgets,
here /usr/local/{wxWidgets,wxWidgets-Release}.
2019-12-22 16:35:16 +01:00
|
|
|
#define LBOUNDGRID_H
|
2018-04-25 20:43:41 +02:00
|
|
|
|
|
|
|
|
#include <wx/grid.h>
|
|
|
|
|
#include "LResultSet.h"
|
|
|
|
|
#include "LGridColEditor.h"
|
|
|
|
|
|
|
|
|
|
class LBoundGridFormEvent;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Displays and edits database tables with custom renderers and editors.
|
|
|
|
|
* A custom menu controls data editing.
|
|
|
|
|
* Can edit a row in form view; application can add widgets on the form dialog.
|
|
|
|
|
* Display on phones or tablets with high DPI is optimized.
|
|
|
|
|
*/
|
|
|
|
|
class LBoundGrid : public wxGrid
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
/**
|
|
|
|
|
* The constructor forces selection mode to wxGridSelectRows,
|
|
|
|
|
* this is a requirement, don't change it in your code.
|
|
|
|
|
*
|
|
|
|
|
* @param parent
|
|
|
|
|
* @param id
|
|
|
|
|
*/
|
|
|
|
|
LBoundGrid(wxWindow* parent, wxWindowID id = wxID_ANY);
|
|
|
|
|
/**
|
|
|
|
|
* Deletes the menu, the form client sizer and calls ClearGrid().
|
|
|
|
|
*/
|
|
|
|
|
virtual ~LBoundGrid();
|
|
|
|
|
|
|
|
|
|
void SetResultSet(LResultSet * newResultSet);
|
|
|
|
|
|
|
|
|
|
LResultSet* GetResultSet() const
|
|
|
|
|
{
|
|
|
|
|
return m_rs;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Is destructive. All rows and columns are deleted. Column editors get destroyed.
|
|
|
|
|
*/
|
|
|
|
|
void ClearGrid();
|
|
|
|
|
/**
|
|
|
|
|
* Deletes all rows, preserves columns, fills the underlying wxStringTable with raw database data.
|
|
|
|
|
*/
|
|
|
|
|
void FillGrid();
|
|
|
|
|
/**
|
|
|
|
|
* The specified column will be edited with LGridCheckEditor and rendered with LGridCheckRenderer.
|
|
|
|
|
* @param newColName database table column name
|
|
|
|
|
* @param newLabel grid header label
|
|
|
|
|
* @param width column width
|
|
|
|
|
* @param readOnly if true, editing is not allowed
|
|
|
|
|
* @param isDualstate edit/render as dual or tristate
|
|
|
|
|
* @param newNullLabel if the underlying check box is tristate with undetermined state, the cell displays this value
|
|
|
|
|
*/
|
|
|
|
|
void CreateCheckBoxColumn(const wxString& newColName,
|
|
|
|
|
const wxString& newLabel,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
bool readOnly = false,
|
|
|
|
|
bool isDualstate = false,
|
|
|
|
|
wxString newNullLabel = _T("?"));
|
|
|
|
|
/**
|
|
|
|
|
* The specified column will be edited with LGridComboEditor and rendered with LGridComboRenderer.
|
|
|
|
|
* @param newColName database table column name
|
|
|
|
|
* @param newLabel grid header label
|
|
|
|
|
* @param width column width
|
|
|
|
|
* @param readOnly if true, editing is not allowed
|
|
|
|
|
*/
|
|
|
|
|
void CreateComboBoxColumn(const wxString& newColName,
|
|
|
|
|
const wxString& newLabel,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
bool readOnly = false);
|
|
|
|
|
/**
|
|
|
|
|
* The specified column will be edited with LGridDateEditor and rendered with LGridDateRenderer.
|
|
|
|
|
* @param newColName database table column name
|
|
|
|
|
* @param newLabel grid header label
|
|
|
|
|
* @param width column width
|
|
|
|
|
* @param readOnly if true, editing is not allowed
|
|
|
|
|
*/
|
|
|
|
|
void CreateDateColumn(const wxString& newColName,
|
|
|
|
|
const wxString& newLabel,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
bool readOnly = false);
|
|
|
|
|
/**
|
|
|
|
|
* The specified column will be edited with LGridTextEditor and rendered with LGridTextRenderer.
|
|
|
|
|
* @param newColName database table column name
|
|
|
|
|
* @param newLabel grid header label
|
|
|
|
|
* @param width column width
|
|
|
|
|
* @param newMultiline use a single or multiline text editor
|
|
|
|
|
* @param readOnly if true, editing is not allowed
|
|
|
|
|
*/
|
|
|
|
|
void CreateTextColumn(const wxString& newColName,
|
|
|
|
|
const wxString& newLabel,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
bool newMultiline = false,
|
|
|
|
|
bool readOnly = false);
|
|
|
|
|
/**
|
|
|
|
|
* The specified column will be edited with LGridSpinEditor and rendered with LGridSpinRenderer.
|
|
|
|
|
* @param newColName database table column name
|
|
|
|
|
* @param newLabel grid header label
|
|
|
|
|
* @param width column width
|
|
|
|
|
* @param newMin minimal value of the editor
|
|
|
|
|
* @param newMax maximal value of the editor
|
|
|
|
|
* @param newInitial initial value of the editor
|
|
|
|
|
* @param readOnly if true, editing is not allowed
|
|
|
|
|
*/
|
|
|
|
|
void CreateSpinColumn(const wxString& newColName,
|
|
|
|
|
const wxString& newLabel,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
int newMin = 0,
|
|
|
|
|
int newMax = 100,
|
|
|
|
|
int newInitial = 0,
|
|
|
|
|
bool readOnly = false);
|
Added classes to manage simple tabular data of known structure using a
popup containing a wxGrid object.
BasePicker : Abstract class adding a popup to wxPickerBase styled with
a wxTextCtrl.
BaseGridPicker : Abstract class adding a wxGrid in the popup.
JsonGridPickerCtrl : UI control storing the tabular data in a JSON
array.
LBoundJsonGridPicker : connect JsonGridPicker to database.
LGridJsonCellEditor : use LBoundJsonGridPicker in other wxGrid objects.
LGridJsonCellRenderer : render cell JSON data.
XmlGridPickerCtrl : UI control storing the tabular data in as XML
document.
LBoundXmlGridPicker : connect XmlGridPicker to database.
LGridXmlCellEditor : grid editor for LBoundXmlGridPicker.
LGridXmlCellRenderer : grid renderer for LBoundXmlGridPicker.
JsonHelper and XmlHelper : for applications to quickly get intent value
from database data..
The structure of managed tabular data :
Column 1 : Intent - this is what we want to store/edit. This can be
telephone numbers, email addresses, instant messaging addresses...
any single line piece of information that can exist many times for one
entity (person, company...).
Column 2 : Type - A short description of the intent : 'Home, Work,
Mobile, Fax, Other...'. It is displayed in a non editable wxComboBox.
Column 3 : Preferred - One line of data can be selected as the preferred
one. It is not mandatory, but it must be a single choice.
Column 4 : Notes - single line notes.
Adjust sql scripts and L7.dox.
Applied ANSI formatting style to all files.
Other changes :
Work around a nasty misbehavior.
Grid columns edited by a translated combobox expect full string
data as cell values. LResultSet::BEData() will report these mapped strings,
instead of database real data. LBoundComboBox::IsDirty() will always be
true even if the editor is unchanged once created.
Simplest workaround : disconnect m_BoundComboBox if unchanged.
LGridTextEditor::ProvideFormEditor() : set the form editor's value
explicitely.; wxTextCtrl does not interpret data it receives
LBoundControl::SetNull must be void.
LBoundGrid : Unbind:: instructions should limit to the widget's id, like Bind::
LConnection::GetReturnedKeys should return NULL.
LConnection::SetData should return void.
Notes : wxJSON must be configured with the same prefix as wxWidgets,
here /usr/local/{wxWidgets,wxWidgets-Release}.
2019-12-22 16:35:16 +01:00
|
|
|
void CreateJsonGridColumn(const wxString& newColName,
|
|
|
|
|
const wxString& newLabel,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
const wxString& intentLabel,
|
|
|
|
|
const wxArrayString& types,
|
|
|
|
|
wxSize popupSize = wxDefaultSize,
|
|
|
|
|
bool readOnly = false);
|
|
|
|
|
void CreateXmlGridColumn(const wxString& newColName,
|
|
|
|
|
const wxString& newLabel,
|
|
|
|
|
unsigned int width,
|
|
|
|
|
const wxString& intentLabel,
|
|
|
|
|
const wxArrayString& types,
|
|
|
|
|
wxSize popupSize = wxDefaultSize,
|
|
|
|
|
bool readOnly = false);
|
2018-04-25 20:43:41 +02:00
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param col the grid column index
|
|
|
|
|
* @return the database table column name if above Create???Column has been called on that column, wxEmpyString otherwise.
|
|
|
|
|
*/
|
|
|
|
|
const wxString GetColName(const unsigned int col);
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param colName database table column name
|
|
|
|
|
* @return the grid column index of the first column defined with above Create???Column and whose
|
|
|
|
|
* columnName property equals colName. If no column is found, -1 is returned.
|
|
|
|
|
*/
|
|
|
|
|
int GetColIndex(const wxString& colName);
|
|
|
|
|
/**
|
|
|
|
|
* Has to call BeginEdit on the cell at row and col. This creates the editor if necessary,
|
|
|
|
|
* which in turn registers it in the underlying resultset.
|
|
|
|
|
* @param row
|
|
|
|
|
* @param col
|
|
|
|
|
* @param keepRegistered if true, does not unregister the editor in the underlying resultset
|
|
|
|
|
* @return The editor typed as LBoundControl* if found, NULL otherwise.
|
|
|
|
|
*/
|
|
|
|
|
LBoundControl* GetBoundControl(const unsigned int row,
|
|
|
|
|
const unsigned int col,
|
|
|
|
|
bool keepRegistered = true);
|
|
|
|
|
/**
|
|
|
|
|
* Has to call BeginEdit on the cell at row and colName. This creates the editor if necessary,
|
|
|
|
|
* which in turn registers it in the underlying resultset.
|
|
|
|
|
* @param row
|
|
|
|
|
* @param colName database table column name
|
|
|
|
|
* @param keepRegistered if true, does not unregister the editor in the underlying resultset
|
|
|
|
|
* @return The editor typed as LBoundControl* if found, NULL otherwise.
|
|
|
|
|
*/
|
|
|
|
|
LBoundControl* GetBoundControl(const unsigned int row,
|
|
|
|
|
const wxString& colName,
|
|
|
|
|
bool keepRegistered = true);
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param row
|
|
|
|
|
* @param col
|
|
|
|
|
* @return the cell editor at row and col as LGridColEditor* .
|
|
|
|
|
*/
|
|
|
|
|
LGridColEditor * GetColEditor(const unsigned int row, const unsigned int col) const;
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param col grid column index
|
|
|
|
|
* @return the form editor if in form view, NULL otherwise.
|
|
|
|
|
*/
|
|
|
|
|
wxControl* GetFormEditor(const unsigned int col) const;
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param colName database table column name
|
|
|
|
|
* @return the form editor if in form view, NULL otherwise.
|
|
|
|
|
*/
|
|
|
|
|
wxControl* GetFormEditor(const wxString& colName);
|
|
|
|
|
/**
|
|
|
|
|
* Calls BeginEdit on the cell at row and colName. This creates the editor if necessary,
|
|
|
|
|
* which in turn registers it in the underlying resultset.
|
|
|
|
|
* @param row
|
|
|
|
|
* @param col
|
|
|
|
|
* @param keepRegistered if true, does not unregister the editor in the underlying resultset
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
bool InitEditor(const unsigned int row,
|
|
|
|
|
const unsigned int col,
|
|
|
|
|
bool keepRegistered = true);
|
|
|
|
|
void InitAllEditors(const unsigned int row, bool keepRegistered = true);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* An application can register a single form event handler here.
|
|
|
|
|
* @param newEVH
|
|
|
|
|
*/
|
|
|
|
|
void SetGridFormEventHandler(LBoundGridFormEvent * newEVH)
|
|
|
|
|
{
|
|
|
|
|
m_gridFormEVH = newEVH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LBoundGridFormEvent* GetGridFormEventHandler()
|
|
|
|
|
{
|
|
|
|
|
return m_gridFormEVH;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AddMenuSeparator();
|
|
|
|
|
void AddMenuItem(wxMenuItem * newItem);
|
|
|
|
|
void AddSubMenu(wxMenu * newSubMenu, const wxString &label);
|
|
|
|
|
void RemoveMenuItem(const wxString& newItemLabelText);
|
|
|
|
|
void RemoveAllExternalMenuItems();
|
|
|
|
|
void EnableMenuItem(int id, bool enable = true);
|
|
|
|
|
|
|
|
|
|
wxMenu* GetMenu() const
|
|
|
|
|
{
|
|
|
|
|
return m_menu;
|
|
|
|
|
}
|
|
|
|
|
// Overrides to optimize display on phones and tablets with high DPI.
|
|
|
|
|
void SetDefaultRowSize(int height, bool resizeExistingRows = false);
|
|
|
|
|
void SetColMinimalAcceptableWidth(int width);
|
|
|
|
|
void SetColMinimalWidth(int col, int width);
|
|
|
|
|
void SetColSize(int col, int width);
|
|
|
|
|
void SetDefaultColSize(int width, bool resizeExistingCols = false);
|
|
|
|
|
void SetRowLabelSize(int width);
|
|
|
|
|
void SetRowMinimalAcceptableHeight(int height);
|
|
|
|
|
void SetRowMinimalHeight(int row, int height);
|
|
|
|
|
void SetRowSize(int row, int height);
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
enum mnuIDs
|
|
|
|
|
{
|
|
|
|
|
ID_MNU_SAVE = -50000, ID_MNU_DELETE, ID_MNU_CANCEL, ID_MNU_REFRESH, ID_MNU_FORMVIEW
|
|
|
|
|
};
|
|
|
|
|
wxWeakRef<LResultSet> m_rs;
|
|
|
|
|
/**
|
|
|
|
|
* For phones and tablets with high DPI.
|
|
|
|
|
*/
|
|
|
|
|
wxDouble m_scaleFactor;
|
|
|
|
|
/**
|
|
|
|
|
* All database table date is stored as string.
|
|
|
|
|
*/
|
|
|
|
|
wxGridStringTable * m_stringTable;
|
|
|
|
|
wxMenu * m_menu;
|
|
|
|
|
/**
|
|
|
|
|
* This wxBoxSizer is created on the wxDialog when the grid is in form view,
|
|
|
|
|
* and is passed to the application via an instance of LBoundGridFormEvent if set.
|
|
|
|
|
*/
|
|
|
|
|
wxBoxSizer * m_formClientSizer;
|
|
|
|
|
/**
|
|
|
|
|
* Client application can set a single instance of LBoundGridFormEvent to receive
|
|
|
|
|
* events in form view.
|
|
|
|
|
*/
|
|
|
|
|
LBoundGridFormEvent * m_gridFormEVH;
|
|
|
|
|
/**
|
|
|
|
|
* Only one single line must be selected.
|
|
|
|
|
* @param evt
|
|
|
|
|
*/
|
|
|
|
|
void ForceSingleLineRange(wxGridRangeSelectEvent& evt);
|
|
|
|
|
/**
|
|
|
|
|
* Synchronizes the grid and the resultset row positions.
|
|
|
|
|
* @param evt
|
|
|
|
|
*/
|
|
|
|
|
void CellSelected(wxGridEvent& evt);
|
|
|
|
|
/**
|
|
|
|
|
* Called in constructor.
|
|
|
|
|
*/
|
|
|
|
|
void CreateMenu();
|
|
|
|
|
/**
|
|
|
|
|
* On right click.
|
|
|
|
|
* @param evt
|
|
|
|
|
*/
|
|
|
|
|
void ShowMenu(wxGridEvent& evt);
|
|
|
|
|
/**
|
|
|
|
|
* Saves, cancels edits or deletes current row, or shows form view.
|
|
|
|
|
* @param evt
|
|
|
|
|
*/
|
|
|
|
|
void MenuAction(wxCommandEvent& evt);
|
|
|
|
|
/**
|
|
|
|
|
* Helper function to Save() and Delete(). Concerns the column declared as primary key.
|
|
|
|
|
* @param row
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
bool InitPKEditor(const int row);
|
|
|
|
|
/**
|
|
|
|
|
* Edits the current row in a wxDialog.
|
|
|
|
|
*/
|
|
|
|
|
void ShowFormView();
|
|
|
|
|
/**
|
|
|
|
|
* Unregisters all controls in the resultset and set them back to null.
|
|
|
|
|
*/
|
|
|
|
|
void RestoreEditorControls();
|
|
|
|
|
/**
|
|
|
|
|
* Calls Reset() on the LGridColEditor at col, i.e., deletes the editor control.
|
|
|
|
|
* @param col grid column index
|
|
|
|
|
*/
|
|
|
|
|
void ResetColEditor(const int col);
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class LBoundGridFormEvent
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
LBoundGridFormEvent();
|
|
|
|
|
virtual ~LBoundGridFormEvent();
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param origin
|
|
|
|
|
* @param clientSizer a wxBoxSizer at the bottom of the form window.
|
|
|
|
|
*/
|
|
|
|
|
virtual void BeforeFormShown(const LBoundGrid * origin, wxBoxSizer * clientSizer);
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param origin
|
|
|
|
|
* @param clientSizer a wxBoxSizer at the bottom of the form window.
|
|
|
|
|
*/
|
|
|
|
|
virtual void AfterFormHidden(const LBoundGrid * origin, wxBoxSizer * clientSizer);
|
|
|
|
|
virtual void AfterFormDestroyed(const LBoundGrid * origin);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
Added classes to manage simple tabular data of known structure using a
popup containing a wxGrid object.
BasePicker : Abstract class adding a popup to wxPickerBase styled with
a wxTextCtrl.
BaseGridPicker : Abstract class adding a wxGrid in the popup.
JsonGridPickerCtrl : UI control storing the tabular data in a JSON
array.
LBoundJsonGridPicker : connect JsonGridPicker to database.
LGridJsonCellEditor : use LBoundJsonGridPicker in other wxGrid objects.
LGridJsonCellRenderer : render cell JSON data.
XmlGridPickerCtrl : UI control storing the tabular data in as XML
document.
LBoundXmlGridPicker : connect XmlGridPicker to database.
LGridXmlCellEditor : grid editor for LBoundXmlGridPicker.
LGridXmlCellRenderer : grid renderer for LBoundXmlGridPicker.
JsonHelper and XmlHelper : for applications to quickly get intent value
from database data..
The structure of managed tabular data :
Column 1 : Intent - this is what we want to store/edit. This can be
telephone numbers, email addresses, instant messaging addresses...
any single line piece of information that can exist many times for one
entity (person, company...).
Column 2 : Type - A short description of the intent : 'Home, Work,
Mobile, Fax, Other...'. It is displayed in a non editable wxComboBox.
Column 3 : Preferred - One line of data can be selected as the preferred
one. It is not mandatory, but it must be a single choice.
Column 4 : Notes - single line notes.
Adjust sql scripts and L7.dox.
Applied ANSI formatting style to all files.
Other changes :
Work around a nasty misbehavior.
Grid columns edited by a translated combobox expect full string
data as cell values. LResultSet::BEData() will report these mapped strings,
instead of database real data. LBoundComboBox::IsDirty() will always be
true even if the editor is unchanged once created.
Simplest workaround : disconnect m_BoundComboBox if unchanged.
LGridTextEditor::ProvideFormEditor() : set the form editor's value
explicitely.; wxTextCtrl does not interpret data it receives
LBoundControl::SetNull must be void.
LBoundGrid : Unbind:: instructions should limit to the widget's id, like Bind::
LConnection::GetReturnedKeys should return NULL.
LConnection::SetData should return void.
Notes : wxJSON must be configured with the same prefix as wxWidgets,
here /usr/local/{wxWidgets,wxWidgets-Release}.
2019-12-22 16:35:16 +01:00
|
|
|
#endif /* LBOUNDGRID_H */
|
2018-04-25 20:43:41 +02:00
|
|
|
|