Transform to CMake project.
This commit is contained in:
201
special/BaseGridPicker.cpp
Normal file
201
special/BaseGridPicker.cpp
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* File: BaseGridPicker.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 7, 2019, 9:40 PM
|
||||
*/
|
||||
|
||||
#include "BaseGridPicker.h"
|
||||
|
||||
IMPLEMENT_CLASS(BaseGridPicker, BasePicker)
|
||||
|
||||
BaseGridPicker::BaseGridPicker(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize,
|
||||
const wxString& text,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size,
|
||||
long style,
|
||||
const wxValidator& validator,
|
||||
const wxString& name)
|
||||
: BasePicker(parent, id, popupSize, text, pos, size, style, validator, name)
|
||||
{
|
||||
m_grid = NULL;
|
||||
m_stringTable = NULL;
|
||||
m_editable = true;
|
||||
m_intentLabel = _T("Intent");
|
||||
m_nbInsertRows = 3;
|
||||
m_colTypeChoices = types;
|
||||
wxButton * btn = static_cast<wxButton*> (GetPickerCtrl());
|
||||
btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &BaseGridPicker::ShowPopup, this);
|
||||
}
|
||||
|
||||
BaseGridPicker::~BaseGridPicker()
|
||||
{
|
||||
delete m_grid;
|
||||
}
|
||||
|
||||
void BaseGridPicker::UpdatePickerFromTextCtrl()
|
||||
{
|
||||
// Gets called when TextCtrl is changed
|
||||
}
|
||||
|
||||
void BaseGridPicker::UpdateTextCtrlFromPicker()
|
||||
{
|
||||
// Gets called when TextCtrl loses focus
|
||||
}
|
||||
|
||||
void BaseGridPicker::CreateGrid()
|
||||
{
|
||||
wxDELETE(m_grid);
|
||||
BasePicker::CreatePopup();
|
||||
m_grid = new wxGrid(m_popup, wxID_ANY);
|
||||
m_popup->GetSizer()->Add(m_grid, 1, wxGROW | wxALL, 0);
|
||||
m_grid->SetSize(m_popup->GetSize());
|
||||
m_grid->SetDefaultCellAlignment(wxALIGN_LEFT, wxALIGN_CENTRE);
|
||||
m_stringTable = new wxGridStringTable();
|
||||
m_stringTable->CanHaveAttributes();
|
||||
m_grid->HideRowLabels();
|
||||
m_grid->SetUseNativeColLabels();
|
||||
m_grid->SetTable(m_stringTable);
|
||||
m_grid->SetSelectionMode(wxGrid::wxGridSelectionModes::wxGridSelectRows);
|
||||
|
||||
PrepareGrid();
|
||||
FillGrid();
|
||||
}
|
||||
|
||||
void BaseGridPicker::SetIntentLabel(const wxString& intent)
|
||||
{
|
||||
m_intentLabel = intent;
|
||||
wxASSERT_MSG(m_stringTable != NULL, _("m_stringTable IS NULL"));
|
||||
m_stringTable->SetColLabelValue(0, m_intentLabel);
|
||||
}
|
||||
|
||||
wxString BaseGridPicker::GetIntent() const
|
||||
{
|
||||
wxASSERT_MSG(m_stringTable != NULL, _("m_stringTable IS NULL"));
|
||||
for (uint row = 0; row < m_stringTable->GetRowsCount(); row++)
|
||||
{
|
||||
if (m_stringTable->GetValue(row, 2) != _T("0")
|
||||
&& !m_stringTable->GetValue(row, 2).IsEmpty()
|
||||
&& !m_stringTable->GetValue(row, 0).IsEmpty())
|
||||
{
|
||||
return m_stringTable->GetValue(row, 0);
|
||||
}
|
||||
}
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
void BaseGridPicker::EnableEditing(bool editable)
|
||||
{
|
||||
m_editable = editable;
|
||||
m_nbInsertRows = editable ? 3 : 0;
|
||||
}
|
||||
|
||||
void BaseGridPicker::OnPopupHidden(wxShowEvent& evt)
|
||||
{
|
||||
if (evt.IsShown())
|
||||
{
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
m_grid->SaveEditControlValue();
|
||||
/*
|
||||
* Workaround an unexpected behavior :
|
||||
* If cell is edited to empty, SaveEditControlValue() above does not
|
||||
* save the empty string in the string table.
|
||||
* It still contains the old non-empty value.
|
||||
* GoToCell() below effectively ends editing.
|
||||
* But this does not happen if cell is edited from empty to any non-empty
|
||||
* value.
|
||||
*/
|
||||
m_grid->GoToCell(m_grid->GetGridCursorRow(), m_grid->GetGridCursorCol());
|
||||
DumpGrid();
|
||||
for (uint row = 0; row < m_stringTable->GetRowsCount(); row++)
|
||||
{
|
||||
if (m_stringTable->GetValue(row, 2) != _T("0")
|
||||
&& !m_stringTable->GetValue(row, 2).IsEmpty())
|
||||
{
|
||||
const wxString intent = m_stringTable->GetValue(row, 0);
|
||||
if (!intent.IsEmpty())
|
||||
{
|
||||
GetTextCtrl()->SetValue(intent);
|
||||
}
|
||||
else
|
||||
{
|
||||
GetTextCtrl()->SetValue(INVALID_INTENT);
|
||||
}
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
}
|
||||
GetTextCtrl()->SetValue(INVALID_INTENT);
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void BaseGridPicker::PreparePreferredCol()
|
||||
{
|
||||
wxASSERT_MSG(m_stringTable != NULL, _("m_stringTable IS NULL"));
|
||||
wxGridCellAttr * colAtt = m_stringTable->GetAttr(m_grid->GetGridCursorRow(), 2, wxGridCellAttr::Col);
|
||||
if (colAtt == NULL) colAtt = new wxGridCellAttr();
|
||||
wxGridCellBoolEditor * ed = new wxGridCellBoolEditor();
|
||||
colAtt->SetEditor(ed);
|
||||
wxGridCellBoolRenderer * rn = new wxGridCellBoolRenderer();
|
||||
colAtt->SetRenderer(rn);
|
||||
colAtt->SetAlignment(wxALIGN_CENTER, wxALIGN_CENTRE);
|
||||
m_stringTable->SetColAttr(colAtt, 2);
|
||||
}
|
||||
|
||||
void BaseGridPicker::PrepareTypeCol()
|
||||
{
|
||||
wxASSERT_MSG(m_stringTable != NULL, _("m_stringTable IS NULL"));
|
||||
wxGridCellAttr * colAtt = m_stringTable->GetAttr(m_grid->GetGridCursorRow(), 1, wxGridCellAttr::Col);
|
||||
if (colAtt == NULL) colAtt = new wxGridCellAttr();
|
||||
wxGridCellChoiceEditor* ed = new wxGridCellChoiceEditor(m_colTypeChoices);
|
||||
colAtt->SetEditor(ed);
|
||||
m_stringTable->SetColAttr(colAtt, 1);
|
||||
}
|
||||
|
||||
void BaseGridPicker::PrepareGrid()
|
||||
{
|
||||
wxASSERT_MSG(m_grid != NULL, _("m_grid IS NULL"));
|
||||
wxASSERT_MSG(m_stringTable != NULL, _("m_stringTable IS NULL"));
|
||||
m_grid->AppendCols(4);
|
||||
m_grid->AppendRows(m_nbInsertRows);
|
||||
PreparePreferredCol();
|
||||
PrepareTypeCol();
|
||||
m_grid->SetColSize(0, 170);
|
||||
m_grid->SetColSize(1, 100);
|
||||
m_grid->SetColSize(3, 200);
|
||||
m_stringTable->SetColLabelValue(0, m_intentLabel);
|
||||
m_stringTable->SetColLabelValue(1, _T("Type"));
|
||||
m_stringTable->SetColLabelValue(2, _T("Preferred"));
|
||||
m_stringTable->SetColLabelValue(3, _T("Notes"));
|
||||
m_grid->Bind(wxEVT_GRID_CELL_CHANGED, &BaseGridPicker::OnPrefCellChanged, this);
|
||||
}
|
||||
|
||||
void BaseGridPicker::OnPrefCellChanged(wxGridEvent& evt)
|
||||
{
|
||||
if (evt.GetCol() == 2
|
||||
&& m_stringTable->GetValue(evt.GetRow(), evt.GetCol()) == _T("1"))
|
||||
{
|
||||
for (uint row = 0; row < m_stringTable->GetRowsCount(); row++)
|
||||
{
|
||||
if (row != evt.GetRow())
|
||||
{
|
||||
m_stringTable->SetValue(row, evt.GetCol(), _T("0"));
|
||||
}
|
||||
}
|
||||
m_grid->ForceRefresh();
|
||||
}
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void BaseGridPicker::ShowPopup(wxCommandEvent& evt)
|
||||
{
|
||||
BasePicker::DoShowPopup();
|
||||
evt.Skip();
|
||||
}
|
||||
172
special/BaseGridPicker.h
Normal file
172
special/BaseGridPicker.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* File: BaseGridPicker.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 7, 2019, 9:40 PM
|
||||
*/
|
||||
|
||||
#ifndef BASEGRIDPICKER_H
|
||||
#define BASEGRIDPICKER_H
|
||||
|
||||
#include "BasePicker.h"
|
||||
#include <wx/grid.h>
|
||||
|
||||
#define INVALID_INTENT _("[Invalid]")
|
||||
|
||||
/**
|
||||
* Abstract class adding a wxGrid to BasePicker.
|
||||
* <br/>The grid is contained in the popup. It has 4 columns :
|
||||
* <br/><br/> Column 0 : The intent : phone, email..., in single line
|
||||
* <br/> Column 1 : Type : Home, Work...
|
||||
* <br/> Column 2 : Preferred : one entry should be preferred
|
||||
* <br/> Column 3 : Short notes in single line
|
||||
* <br/><br/>
|
||||
* The label of the Intent column can be changed by an application. The other
|
||||
* columns have fixed labels.
|
||||
* <br/>
|
||||
* The Type column is edited with a combobox. Its values are set by
|
||||
* SetColTypeChoices().
|
||||
* <br/>
|
||||
* The Preferred column allows selecting one single entry as preferred. If none
|
||||
* is selected, the dataset persists but considered invalid.
|
||||
* <br/>
|
||||
* Selection mode is wxGridSelectRows. Row labels are hidden.
|
||||
* <br/>
|
||||
* Three empty rows are available for quick multiple inputs.
|
||||
* @return
|
||||
*/
|
||||
class BaseGridPicker : public BasePicker
|
||||
{
|
||||
DECLARE_CLASS(BaseGridPicker)
|
||||
public:
|
||||
BaseGridPicker(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize = wxDefaultSize,
|
||||
const wxString& text = wxEmptyString,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxPB_USE_TEXTCTRL,
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxButtonNameStr);
|
||||
virtual ~BaseGridPicker();
|
||||
/**
|
||||
* Unused, empty implementation.
|
||||
*/
|
||||
virtual void UpdatePickerFromTextCtrl();
|
||||
/**
|
||||
* Unused, empty implementation.
|
||||
*/
|
||||
virtual void UpdateTextCtrlFromPicker();
|
||||
|
||||
virtual void SetValue(const wxString& value) = 0;
|
||||
|
||||
virtual wxString GetValue() = 0;
|
||||
|
||||
/**
|
||||
* Sets the values of the Type column in a combobox.
|
||||
* @param choices
|
||||
*/
|
||||
void SetColTypeChoices(const wxArrayString& choices)
|
||||
{
|
||||
m_colTypeChoices = choices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the values of the Type column.
|
||||
* @return
|
||||
*/
|
||||
wxArrayString GetColTypeChoices() const
|
||||
{
|
||||
return m_colTypeChoices;
|
||||
}
|
||||
/**
|
||||
* Sets the label of the Intent column.
|
||||
* @param intent
|
||||
*/
|
||||
void SetIntentLabel(const wxString& intent);
|
||||
|
||||
/**
|
||||
* Gets the label of the Intent column.
|
||||
* @return
|
||||
*/
|
||||
wxString GetIntentLabel() const
|
||||
{
|
||||
return m_intentLabel;
|
||||
}
|
||||
/**
|
||||
* Gets the Intent value, the one that is marked as preferred.
|
||||
* It may return an empty string if no item is preferred.
|
||||
* @return
|
||||
*/
|
||||
wxString GetIntent() const;
|
||||
|
||||
/**
|
||||
* Can we modify data ?
|
||||
* @return
|
||||
*/
|
||||
bool IsEditable() const
|
||||
{
|
||||
return m_editable;
|
||||
}
|
||||
/**
|
||||
* Grid data may be editable or not. In the latter case, no empty rows are
|
||||
* shown.
|
||||
* @param editable
|
||||
*/
|
||||
void EnableEditing(bool editable);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Saves the grid's content internally and updates the wxTextCtrl's value.
|
||||
* @param evt
|
||||
*/
|
||||
virtual void OnPopupHidden(wxShowEvent& evt);
|
||||
virtual void FillGrid() = 0;
|
||||
virtual void DumpGrid() = 0;
|
||||
/**
|
||||
* Creates, configures and fills the grid by calling FillGrid(). A previous
|
||||
* grid is deleted.
|
||||
*/
|
||||
void CreateGrid();
|
||||
wxGrid * m_grid;
|
||||
wxGridStringTable * m_stringTable;
|
||||
bool m_editable;
|
||||
private:
|
||||
wxArrayString m_colTypeChoices;
|
||||
wxString m_intentLabel;
|
||||
uint m_nbInsertRows;
|
||||
/**
|
||||
* Configures the Preferred column for editing and rendering using a
|
||||
* checkbox.
|
||||
*/
|
||||
void PreparePreferredCol();
|
||||
/**
|
||||
* Configures the Type column for editing using a combobox.
|
||||
*/
|
||||
void PrepareTypeCol();
|
||||
/**
|
||||
* Adds rows and columns, configures the columns, further setting sizes
|
||||
* and labels.
|
||||
* <br/>
|
||||
* Binds the grid to editor creation and hidden events.
|
||||
*/
|
||||
void PrepareGrid();
|
||||
/**
|
||||
* Concerns the Preferred column only. When the editor is checked, ensures
|
||||
* the other rows are unchecked.
|
||||
* @param evt
|
||||
*/
|
||||
void OnPrefCellChanged(wxGridEvent& evt);
|
||||
/**
|
||||
* Just calls BasePicker::DoShowPopup().
|
||||
* @param evt
|
||||
*/
|
||||
virtual void ShowPopup(wxCommandEvent& evt);
|
||||
|
||||
};
|
||||
|
||||
#endif /* BASEGRIDPICKER_H */
|
||||
|
||||
75
special/BasePicker.cpp
Normal file
75
special/BasePicker.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* File: BasePicker.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 7, 2019, 9:24 PM
|
||||
*/
|
||||
|
||||
#include "BasePicker.h"
|
||||
|
||||
IMPLEMENT_CLASS(BasePicker, wxPickerBase)
|
||||
|
||||
BasePicker::BasePicker(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
wxSize popupSize,
|
||||
const wxString& text,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size,
|
||||
long style,
|
||||
const wxValidator& validator,
|
||||
const wxString& name)
|
||||
: wxPickerBase()
|
||||
{
|
||||
m_popup = NULL;
|
||||
m_popupSize = popupSize;
|
||||
wxPickerBase::CreateBase(parent, id, text, pos, size, style, validator, name);
|
||||
wxButton * btn = new wxButton(this, wxID_ANY, _T("↓"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
SetPickerCtrl(btn);
|
||||
wxPickerBase::PostCreation();
|
||||
GetTextCtrl()->SetEditable(false);
|
||||
GetTextCtrl()->SetMaxLength(0);
|
||||
SetTextCtrlGrowable(true);
|
||||
SetPickerCtrlGrowable(true);
|
||||
}
|
||||
|
||||
BasePicker::~BasePicker()
|
||||
{
|
||||
delete m_popup;
|
||||
}
|
||||
|
||||
void BasePicker::CreatePopup()
|
||||
{
|
||||
wxDELETE(m_popup);
|
||||
m_popup = new wxPopupTransientWindow(this);
|
||||
wxBoxSizer * sz = new wxBoxSizer(wxVERTICAL);
|
||||
m_popup->SetSizer(sz);
|
||||
|
||||
m_popup->Bind(wxEVT_SHOW, &BasePicker::OnPopupHidden, this);
|
||||
}
|
||||
|
||||
void BasePicker::DoShowPopup()
|
||||
{
|
||||
if (m_popupSize.GetWidth() < 0)
|
||||
m_popupSize.SetWidth(GetClientSize().GetWidth());
|
||||
if (m_popupSize.GetHeight() < 0)
|
||||
m_popupSize.SetHeight(300);
|
||||
m_popup->SetClientSize(m_popupSize);
|
||||
m_popup->GetSizer()->Layout();
|
||||
|
||||
wxScreenDC dc;
|
||||
const int screenWidth = dc.GetSize().GetWidth();
|
||||
const int screenHeight = dc.GetSize().GetHeight();
|
||||
const wxPoint oriPos = GetScreenPosition() + GetClientRect().GetBottomLeft();
|
||||
wxPoint dest(oriPos.x, oriPos.y);
|
||||
if (oriPos.x > (screenWidth - m_popupSize.GetWidth())) dest.x = (screenWidth - m_popupSize.GetWidth());
|
||||
if (oriPos.x < 0) dest.x = 0;
|
||||
if (oriPos.y > (screenHeight - m_popupSize.GetHeight())) dest.y = (screenHeight - m_popupSize.GetHeight());
|
||||
if (oriPos.y < 0) dest.y = 0;
|
||||
if (m_popupSize.GetWidth() > screenWidth) dest.x = 0;
|
||||
if (m_popupSize.GetHeight() > screenHeight) dest.y = 0;
|
||||
m_popup->SetPosition(dest);
|
||||
|
||||
m_popup->Popup();
|
||||
}
|
||||
63
special/BasePicker.h
Normal file
63
special/BasePicker.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* File: BasePicker.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 7, 2019, 9:24 PM
|
||||
*/
|
||||
|
||||
#ifndef BASEPICKER_H
|
||||
#define BASEPICKER_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/pickerbase.h>
|
||||
#include <wx/popupwin.h>
|
||||
|
||||
/**
|
||||
* Abstract class adding a popup to wxPickerBase styled with
|
||||
* a non-editable wxTextCtrl. It manages the popup's position and size also.
|
||||
* The picker control is a wxButton that shows the popup.
|
||||
*/
|
||||
class BasePicker : public wxPickerBase
|
||||
{
|
||||
DECLARE_CLASS(BasePicker)
|
||||
public:
|
||||
BasePicker(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
wxSize popupSize = wxDefaultSize,
|
||||
const wxString& text = wxEmptyString,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxPB_USE_TEXTCTRL,
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxButtonNameStr);
|
||||
virtual ~BasePicker();
|
||||
|
||||
virtual void UpdatePickerFromTextCtrl() = 0;
|
||||
virtual void UpdateTextCtrlFromPicker() = 0;
|
||||
|
||||
private:
|
||||
|
||||
protected:
|
||||
wxPopupTransientWindow * m_popup;
|
||||
wxSize m_popupSize;
|
||||
/**
|
||||
* A new popup is always created. Any previous popup is deleted.
|
||||
* It binds to OnPopupHidden().
|
||||
*/
|
||||
virtual void CreatePopup();
|
||||
/**
|
||||
* Shows the popup managing its position and size.
|
||||
* <br/><br/>
|
||||
* If m_popupSize.GetWidth() < 0, the popup's width is set to the control's
|
||||
* width.
|
||||
* <br/>
|
||||
* If m_popupSize.GetHeight() < 0, it defaults to 300.
|
||||
*/
|
||||
virtual void DoShowPopup();
|
||||
virtual void OnPopupHidden(wxShowEvent& evt) = 0;
|
||||
};
|
||||
|
||||
#endif /* BASEPICKER_H */
|
||||
|
||||
171
special/JsonGridPickerCtrl.cpp
Normal file
171
special/JsonGridPickerCtrl.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* File: JsonGridPickerCtrl.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 7, 2019, 10:01 PM
|
||||
*/
|
||||
|
||||
/*
|
||||
* [
|
||||
{
|
||||
"Intent" : "a@b.com",
|
||||
"Type" : "Home",
|
||||
"Preferred" : 0,
|
||||
"Notes" : "Do not use"
|
||||
},
|
||||
{
|
||||
"Intent" : "c@d.com",
|
||||
"Type" : "Work",
|
||||
"Preferred" : 1,
|
||||
"Notes" : "Neither"
|
||||
}
|
||||
]
|
||||
|
||||
*/
|
||||
#include "JsonGridPickerCtrl.h"
|
||||
#include <wx/jsonreader.h>
|
||||
#include <wx/jsonwriter.h>
|
||||
|
||||
IMPLEMENT_CLASS(JsonGridPickerCtrl, BaseGridPicker)
|
||||
|
||||
#define EMPTY_ARR _T("[]")
|
||||
|
||||
JsonGridPickerCtrl::JsonGridPickerCtrl(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize,
|
||||
const wxString& text,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size,
|
||||
long style,
|
||||
const wxValidator& validator,
|
||||
const wxString& name)
|
||||
: BaseGridPicker(parent, id, types, popupSize, text, pos, size, style, validator, name)
|
||||
{
|
||||
/*
|
||||
* Don't create the grid here. Let SetValue() do it, deleting the previous
|
||||
* one every time new data is fed in.
|
||||
*/
|
||||
SetValue(wxEmptyString);
|
||||
}
|
||||
|
||||
JsonGridPickerCtrl::~JsonGridPickerCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
void JsonGridPickerCtrl::SetValue(const wxString& value)
|
||||
{
|
||||
if (value.IsEmpty())
|
||||
{
|
||||
m_value = EMPTY_ARR;
|
||||
BaseGridPicker::CreateGrid(); // +++
|
||||
GetTextCtrl()->SetValue(INVALID_INTENT);
|
||||
return;
|
||||
}
|
||||
m_value = value;
|
||||
BaseGridPicker::CreateGrid(); // +++
|
||||
GetTextCtrl()->SetValue(INVALID_INTENT);
|
||||
|
||||
wxJSONReader reader(wxJSONREADER_STRICT);
|
||||
wxJSONValue root;
|
||||
uint nbErr = reader.Parse(m_value, &root);
|
||||
if (nbErr > 0)
|
||||
{
|
||||
const wxArrayString& errors = reader.GetErrors();
|
||||
for (int i = 0; i < nbErr; i++)
|
||||
{
|
||||
wxASSERT_MSG(nbErr == 0, errors[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!root.IsArray())
|
||||
{
|
||||
wxASSERT_MSG(root.IsArray(), _("JSON data is not an array"));
|
||||
return;
|
||||
}
|
||||
for (uint row = 0; row < root.Size(); row++)
|
||||
{
|
||||
if (root[row]["Preferred"].IsValid()
|
||||
&& !root[row]["Preferred"].AsString().IsEmpty()
|
||||
&& root[row]["Preferred"].AsInt() != 0)
|
||||
{
|
||||
GetTextCtrl()->SetValue(root[row]["Intent"].AsString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
GetTextCtrl()->SetValue(INVALID_INTENT);
|
||||
}
|
||||
|
||||
wxString JsonGridPickerCtrl::GetValue()
|
||||
{
|
||||
DumpGrid();
|
||||
/*
|
||||
* wxJSONWriter adds quotes and line breaks to EMPTY_ARR !
|
||||
* m_value is set in DumpGrid(). If there is no grid data, m_value is set
|
||||
* to \"[]\"\n
|
||||
*/
|
||||
wxJSONValue empty(EMPTY_ARR);
|
||||
wxJSONWriter writer;
|
||||
wxString sempty;
|
||||
writer.Write(empty, sempty);
|
||||
if (m_value == sempty)
|
||||
return wxEmptyString;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void JsonGridPickerCtrl::FillGrid()
|
||||
{
|
||||
wxASSERT_MSG(m_grid != NULL, _("m_grid IS NULL"));
|
||||
wxJSONReader reader(wxJSONREADER_STRICT);
|
||||
wxJSONValue root;
|
||||
uint nbErr = reader.Parse(m_value, &root);
|
||||
if (nbErr > 0)
|
||||
{
|
||||
const wxArrayString& errors = reader.GetErrors();
|
||||
for (int i = 0; i < nbErr; i++)
|
||||
{
|
||||
wxASSERT_MSG(nbErr == 0, errors[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!root.IsArray())
|
||||
{
|
||||
wxASSERT_MSG(root.IsArray(), _("JSON data is not an array"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint row = 0; row < root.Size(); row++)
|
||||
{
|
||||
m_grid->InsertRows(row);
|
||||
m_grid->SetCellValue(row, 0, root[row]["Intent"].AsString());
|
||||
m_grid->SetCellValue(row, 1, root[row]["Type"].AsString());
|
||||
m_grid->SetCellValue(row, 2, root[row]["Preferred"].AsString());
|
||||
m_grid->SetCellValue(row, 3, root[row]["Notes"].AsString());
|
||||
}
|
||||
}
|
||||
|
||||
void JsonGridPickerCtrl::DumpGrid()
|
||||
{
|
||||
wxASSERT_MSG(m_grid != NULL, _("m_grid IS NULL"));
|
||||
wxASSERT_MSG(m_stringTable != NULL, _("m_stringTable IS NULL"));
|
||||
if (!m_editable || !m_stringTable || !m_grid)
|
||||
return;
|
||||
wxJSONWriter writer;
|
||||
wxJSONValue root(EMPTY_ARR);
|
||||
uint row = 0;
|
||||
uint jrow = 0;
|
||||
for (row; row < m_stringTable->GetRowsCount(); row++)
|
||||
{
|
||||
if (m_stringTable->GetValue(row, 0).IsEmpty())
|
||||
continue;
|
||||
root[jrow]["Intent"] = m_stringTable->GetValue(row, 0);
|
||||
root[jrow]["Type"] = m_stringTable->GetValue(row, 1);
|
||||
root[jrow]["Preferred"] = (m_stringTable->GetValue(row, 2) == _T("0")
|
||||
|| m_stringTable->GetValue(row, 2).IsEmpty()) ? 0 : 1;
|
||||
root[jrow]["Notes"] = m_stringTable->GetValue(row, 3);
|
||||
jrow++;
|
||||
}
|
||||
writer.Write(root, m_value); // May be EMPTY_ARR
|
||||
}
|
||||
70
special/JsonGridPickerCtrl.h
Normal file
70
special/JsonGridPickerCtrl.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* File: JsonGridPickerCtrl.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 7, 2019, 10:01 PM
|
||||
*/
|
||||
|
||||
#ifndef JSONGRIDPICKERCTRL_H
|
||||
#define JSONGRIDPICKERCTRL_H
|
||||
|
||||
#include "BaseGridPicker.h"
|
||||
|
||||
/**
|
||||
* The grid content is stored in a JSON array.
|
||||
* @return
|
||||
*/
|
||||
class JsonGridPickerCtrl : public BaseGridPicker
|
||||
{
|
||||
DECLARE_CLASS(JsonGridPickerCtrl)
|
||||
public:
|
||||
JsonGridPickerCtrl(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize = wxDefaultSize,
|
||||
const wxString& text = wxEmptyString,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxPB_USE_TEXTCTRL,
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxButtonNameStr);
|
||||
virtual ~JsonGridPickerCtrl();
|
||||
|
||||
/**
|
||||
* Creates a new grid deleting the previous one and fills it with the JSON
|
||||
* data.
|
||||
* @param value
|
||||
*/
|
||||
virtual void SetValue(const wxString& value);
|
||||
|
||||
/**
|
||||
* Dumps the grid content and returns it as a JSON array. But returns empty
|
||||
* string if JSON array is empty.
|
||||
* @return
|
||||
*/
|
||||
virtual wxString GetValue();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Parses the JSON data and fills the grid. It should be pure JSON, without
|
||||
* any extension like comments.
|
||||
*/
|
||||
virtual void FillGrid();
|
||||
/**
|
||||
* Translates the grid content to a JSON array.
|
||||
* If the Intent column is empty, this row is ignored.
|
||||
*/
|
||||
virtual void DumpGrid();
|
||||
/**
|
||||
* Is the JSON array.
|
||||
*/
|
||||
wxString m_value;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif /* JSONGRIDPICKERCTRL_H */
|
||||
|
||||
53
special/JsonHelper.cpp
Normal file
53
special/JsonHelper.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* File: JsonHelper.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 16, 2019, 8:25 PM
|
||||
*/
|
||||
|
||||
#include "JsonHelper.h"
|
||||
#include <wx/jsonreader.h>
|
||||
|
||||
JsonHelper::JsonHelper()
|
||||
{
|
||||
}
|
||||
|
||||
JsonHelper::~JsonHelper()
|
||||
{
|
||||
}
|
||||
|
||||
wxString JsonHelper::GetIntent(const wxString& jsonData)
|
||||
{
|
||||
if (jsonData.IsEmpty())
|
||||
return wxEmptyString;
|
||||
|
||||
wxJSONReader reader(wxJSONREADER_STRICT);
|
||||
wxJSONValue root;
|
||||
uint nbErr = reader.Parse(jsonData, &root);
|
||||
if (nbErr > 0)
|
||||
{
|
||||
const wxArrayString& errors = reader.GetErrors();
|
||||
for (int i = 0; i < nbErr; i++)
|
||||
{
|
||||
wxASSERT_MSG(nbErr == 0, errors[i]);
|
||||
}
|
||||
return wxEmptyString;
|
||||
}
|
||||
if (!root.IsArray())
|
||||
{
|
||||
wxASSERT_MSG(root.IsArray(), _("JSON data is not an array"));
|
||||
return wxEmptyString;
|
||||
}
|
||||
for (uint row = 0; row < root.Size(); row++)
|
||||
{
|
||||
if (root[row]["Preferred"].IsValid()
|
||||
&& !root[row]["Preferred"].AsString().IsEmpty()
|
||||
&& root[row]["Preferred"].AsInt() != 0)
|
||||
{
|
||||
return root[row]["Intent"].AsString();
|
||||
}
|
||||
}
|
||||
return wxEmptyString;
|
||||
}
|
||||
36
special/JsonHelper.h
Normal file
36
special/JsonHelper.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* File: JsonHelper.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 16, 2019, 8:25 PM
|
||||
*/
|
||||
|
||||
#ifndef JSONHELPER_H
|
||||
#define JSONHELPER_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
/**
|
||||
* Application helper to quickly get the Intent value.
|
||||
* @param jsonData
|
||||
* @return
|
||||
*/
|
||||
class JsonHelper
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Returns a valid Intent value or an empty string.
|
||||
* @param jsonData
|
||||
* @return
|
||||
*/
|
||||
static wxString GetIntent(const wxString& jsonData);
|
||||
private:
|
||||
JsonHelper();
|
||||
virtual ~JsonHelper();
|
||||
};
|
||||
|
||||
#endif /* JSONHELPER_H */
|
||||
|
||||
113
special/LBoundJsonGridPicker.cpp
Normal file
113
special/LBoundJsonGridPicker.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* File: LBoundJsonGridPicker.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 8, 2019, 9:23 AM
|
||||
*/
|
||||
|
||||
#include "LBoundJsonGridPicker.h"
|
||||
#include <wx/jsonreader.h>
|
||||
|
||||
IMPLEMENT_CLASS(LBoundJsonGridPicker, JsonGridPickerCtrl)
|
||||
|
||||
LBoundJsonGridPicker::LBoundJsonGridPicker(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize,
|
||||
const wxString& text,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size,
|
||||
long style,
|
||||
const wxValidator& validator,
|
||||
const wxString& name)
|
||||
: JsonGridPickerCtrl(parent, id, types, popupSize, text, pos, size, style, validator, name)
|
||||
{
|
||||
m_sqlQuote = _T("'");
|
||||
}
|
||||
|
||||
LBoundJsonGridPicker::~LBoundJsonGridPicker()
|
||||
{
|
||||
if (m_rs) m_rs->UnRegisterControl(this);
|
||||
}
|
||||
|
||||
void LBoundJsonGridPicker::SetResultSet(LResultSet* newResultSet)
|
||||
{
|
||||
m_rs = newResultSet;
|
||||
if (m_rs == NULL) return;
|
||||
m_rs->RegisterControl(this);
|
||||
}
|
||||
|
||||
const wxAny LBoundJsonGridPicker::GetData()
|
||||
{
|
||||
// If m_value == EMPTY_ARR, GetValue() returns empty string
|
||||
if (GetValue().IsEmpty()) return L_SQLNULL;
|
||||
return GetValue();
|
||||
}
|
||||
|
||||
void LBoundJsonGridPicker::SetData(const wxAny& newData)
|
||||
{
|
||||
SetValue(newData.As<wxString>());
|
||||
}
|
||||
|
||||
void LBoundJsonGridPicker::SetNull()
|
||||
{
|
||||
// m_value is set to EMPTY_ARR
|
||||
SetValue(wxEmptyString);
|
||||
}
|
||||
|
||||
bool LBoundJsonGridPicker::IsDirty()
|
||||
{
|
||||
wxASSERT_MSG(m_rs != NULL, _("RS = NULL"));
|
||||
wxAny BEData = m_rs->GetData(m_columnName);
|
||||
const wxString ctrlValue = GetValue();
|
||||
/*
|
||||
* Make JSON objects from backend and control values, and compare them.
|
||||
* Postgresql : jsonb columns contain single line values. Can't compare strings.
|
||||
*/
|
||||
const wxString beValue = BEData.As<wxString>();
|
||||
if (ctrlValue.IsEmpty() || beValue.IsEmpty())
|
||||
return (ctrlValue != beValue);
|
||||
|
||||
wxJSONReader beReader(wxJSONREADER_STRICT);
|
||||
wxJSONValue beRoot;
|
||||
uint nbErr = beReader.Parse(beValue, &beRoot);
|
||||
if (nbErr > 0)
|
||||
{
|
||||
const wxArrayString& errors = beReader.GetErrors();
|
||||
for (int i = 0; i < nbErr; i++)
|
||||
{
|
||||
wxASSERT_MSG(nbErr == 0, errors[i]);
|
||||
}
|
||||
// Backend value is not what we expect. Declare dirty to overwrite it.
|
||||
return true;
|
||||
}
|
||||
if (!beRoot.IsArray())
|
||||
{
|
||||
wxASSERT_MSG(beRoot.IsArray(), _("Back end JSON data is not an array"));
|
||||
return true;
|
||||
}
|
||||
|
||||
wxJSONReader ctrlReader(wxJSONREADER_STRICT);
|
||||
wxJSONValue ctrlRoot;
|
||||
nbErr = beReader.Parse(ctrlValue, &ctrlRoot);
|
||||
// Should not happen as we wrote the data.
|
||||
if (nbErr > 0)
|
||||
{
|
||||
const wxArrayString& errors = ctrlReader.GetErrors();
|
||||
for (int i = 0; i < nbErr; i++)
|
||||
{
|
||||
wxASSERT_MSG(nbErr == 0, errors[i]);
|
||||
}
|
||||
// Control value is not what we expect. Don't overwrite in backend.
|
||||
return false;
|
||||
}
|
||||
if (!ctrlRoot.IsArray())
|
||||
{
|
||||
wxASSERT_MSG(ctrlRoot.IsArray(), _("Control JSON data is not an array"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return (!ctrlRoot.IsSameAs(beRoot));
|
||||
}
|
||||
81
special/LBoundJsonGridPicker.h
Normal file
81
special/LBoundJsonGridPicker.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* File: LBoundJsonGridPicker.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 8, 2019, 9:23 AM
|
||||
*/
|
||||
|
||||
#ifndef LBOUNDJSONGRIDPICKER_H
|
||||
#define LBOUNDJSONGRIDPICKER_H
|
||||
|
||||
#include "JsonGridPickerCtrl.h"
|
||||
#include "../LBoundControl.h"
|
||||
#include "../LResultSet.h"
|
||||
|
||||
/**
|
||||
* Saves a JSON array in database.
|
||||
* Data type of database column should be TEXT for sqlite, and can be TEXT or
|
||||
* JSONB for postgresql.
|
||||
* @return
|
||||
*/
|
||||
class LBoundJsonGridPicker : public JsonGridPickerCtrl, public LBoundControl
|
||||
{
|
||||
DECLARE_CLASS(LBoundJsonGridPicker)
|
||||
public:
|
||||
LBoundJsonGridPicker(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize = wxDefaultSize,
|
||||
const wxString& text = wxEmptyString,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxPB_USE_TEXTCTRL,
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxButtonNameStr);
|
||||
virtual ~LBoundJsonGridPicker();
|
||||
|
||||
/**
|
||||
* Sets the resultset member and registers the control in the resultset.
|
||||
* @param newResultSet
|
||||
*/
|
||||
void SetResultSet(LResultSet * newResultSet);
|
||||
/**
|
||||
*
|
||||
* @return If the control is empty, returns literal NULL.
|
||||
* Else, returns GetValue().
|
||||
*/
|
||||
const wxAny GetData();
|
||||
void SetData(const wxAny& newData);
|
||||
|
||||
bool IsNull()
|
||||
{
|
||||
return (GetData().As<wxString>() == L_SQLNULL);
|
||||
}
|
||||
void SetNull();
|
||||
/**
|
||||
* Is control data same as backend data?
|
||||
* <br/><br/>
|
||||
* If backend data cannot be parsed, will always return true, because
|
||||
* GetValue() returns empty control data.
|
||||
* @return
|
||||
*/
|
||||
bool IsDirty();
|
||||
|
||||
/**
|
||||
* Alias for GetValue().
|
||||
* Not really the displayed informative value in the picker's wxTextCtrl.
|
||||
* @return
|
||||
*/
|
||||
const wxString GetDisplayedData()
|
||||
{
|
||||
return GetValue();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif /* LBOUNDJSONGRIDPICKER_H */
|
||||
|
||||
72
special/LBoundXmlGridPicker.cpp
Normal file
72
special/LBoundXmlGridPicker.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* File: LBoundXmlGridPicker.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 14, 2019, 10:12 PM
|
||||
*/
|
||||
|
||||
#include "LBoundXmlGridPicker.h"
|
||||
|
||||
IMPLEMENT_CLASS(LBoundXmlGridPicker, XmlGridPickerCtrl)
|
||||
|
||||
LBoundXmlGridPicker::LBoundXmlGridPicker(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize,
|
||||
const wxString& text,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size,
|
||||
long style,
|
||||
const wxValidator& validator,
|
||||
const wxString& name)
|
||||
: XmlGridPickerCtrl(parent, id, types, popupSize, text, pos, size, style, validator, name)
|
||||
{
|
||||
m_sqlQuote = _T("'");
|
||||
}
|
||||
|
||||
LBoundXmlGridPicker::~LBoundXmlGridPicker()
|
||||
{
|
||||
if (m_rs) m_rs->UnRegisterControl(this);
|
||||
}
|
||||
|
||||
void LBoundXmlGridPicker::SetResultSet(LResultSet* newResultSet)
|
||||
{
|
||||
m_rs = newResultSet;
|
||||
if (m_rs == NULL) return;
|
||||
m_rs->RegisterControl(this);
|
||||
}
|
||||
|
||||
const wxAny LBoundXmlGridPicker::GetData()
|
||||
{
|
||||
// If m_value is EMPTY_DOC, GetValue() returns empty string
|
||||
if (GetValue().IsEmpty()) return L_SQLNULL;
|
||||
return GetValue();
|
||||
}
|
||||
|
||||
void LBoundXmlGridPicker::SetData(const wxAny& newData)
|
||||
{
|
||||
SetValue(newData.As<wxString>());
|
||||
}
|
||||
|
||||
void LBoundXmlGridPicker::SetNull()
|
||||
{
|
||||
// m_value is set to EMPTY_DOC
|
||||
SetValue(wxEmptyString);
|
||||
}
|
||||
|
||||
bool LBoundXmlGridPicker::IsDirty()
|
||||
{
|
||||
/*
|
||||
* String compare backend and control values.
|
||||
* Database column data type is TEXT, hence data is saved verbatim.
|
||||
* On the other hand, comparing XML documents is not trivial.
|
||||
* wxWidgets does not have this functionality, not does it write
|
||||
* canonical XML, AFAIK.
|
||||
* Linking to other libraries for this would be an overkill.
|
||||
*/
|
||||
wxASSERT_MSG(m_rs != NULL, _("RS = NULL"));
|
||||
wxAny BEData = m_rs->GetData(m_columnName);
|
||||
return (GetValue() != BEData.As<wxString>());
|
||||
}
|
||||
80
special/LBoundXmlGridPicker.h
Normal file
80
special/LBoundXmlGridPicker.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* File: LBoundXmlGridPicker.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 14, 2019, 10:12 PM
|
||||
*/
|
||||
|
||||
#ifndef LBOUNDXMLGRIDPICKER_H
|
||||
#define LBOUNDXMLGRIDPICKER_H
|
||||
|
||||
#include "XmlGridPickerCtrl.h"
|
||||
#include "../LBoundControl.h"
|
||||
#include "../LResultSet.h"
|
||||
|
||||
/**
|
||||
* Saves an XML document in database.
|
||||
* Data type of database column should be TEXT for both sqlite and postgresql.
|
||||
* @return
|
||||
*/
|
||||
class LBoundXmlGridPicker : public XmlGridPickerCtrl, public LBoundControl
|
||||
{
|
||||
DECLARE_CLASS(LBoundXmlGridPicker)
|
||||
public:
|
||||
LBoundXmlGridPicker(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize = wxDefaultSize,
|
||||
const wxString& text = wxEmptyString,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxPB_USE_TEXTCTRL,
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxButtonNameStr);
|
||||
virtual ~LBoundXmlGridPicker();
|
||||
|
||||
/**
|
||||
* Sets the resultset member and registers the control in the resultset.
|
||||
* @param newResultSet
|
||||
*/
|
||||
void SetResultSet(LResultSet * newResultSet);
|
||||
/**
|
||||
*
|
||||
* @return If the control is empty, returns literal NULL.
|
||||
* Else, returns GetValue().
|
||||
*/
|
||||
const wxAny GetData();
|
||||
void SetData(const wxAny& newData);
|
||||
|
||||
bool IsNull()
|
||||
{
|
||||
return (GetData().As<wxString>() == L_SQLNULL);
|
||||
}
|
||||
void SetNull();
|
||||
/**
|
||||
* Is control data same as backend data?
|
||||
* <br/><br/>
|
||||
* If backend data is cannot be parsed, will always return true, because
|
||||
* GetValue() returns empty control data.
|
||||
* @return
|
||||
*/
|
||||
bool IsDirty();
|
||||
|
||||
/**
|
||||
* Alias for GetValue().
|
||||
* Not really the displayed informative value in the picker'swxTextCtrl.
|
||||
* @return
|
||||
*/
|
||||
const wxString GetDisplayedData()
|
||||
{
|
||||
return GetValue();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif /* LBOUNDXMLGRIDPICKER_H */
|
||||
|
||||
150
special/LGridJsonCellEditor.cpp
Normal file
150
special/LGridJsonCellEditor.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* File: LGridJsonCellEditor.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
* Author: user
|
||||
*
|
||||
* Created on December 9, 2019, 10:36 AM
|
||||
*/
|
||||
|
||||
#include "LGridJsonCellEditor.h"
|
||||
#include "../LBoundGrid.h"
|
||||
|
||||
LGridJsonCellEditor::LGridJsonCellEditor(const wxString& newColName,
|
||||
const wxString& intentLabel,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize)
|
||||
: wxGridCellEditor(), LGridColEditor()
|
||||
{
|
||||
m_intentLabel = intentLabel;
|
||||
m_choices = types;
|
||||
m_popupSize = popupSize;
|
||||
m_colName = newColName;
|
||||
m_type = LGridColEditor::JSON_GRID;
|
||||
m_formEditor = NULL;
|
||||
m_BoundControl = NULL;
|
||||
m_BoundJsonGridPicker = NULL;
|
||||
m_editRow = wxNOT_FOUND;
|
||||
m_rsEVH = NULL;
|
||||
}
|
||||
|
||||
LGridJsonCellEditor::~LGridJsonCellEditor()
|
||||
{
|
||||
delete m_rsEVH;
|
||||
wxDELETE(m_control);
|
||||
}
|
||||
|
||||
void LGridJsonCellEditor::Create(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler)
|
||||
{
|
||||
m_control = new LBoundJsonGridPicker(parent, id, m_choices, m_popupSize);
|
||||
m_BoundJsonGridPicker = (static_cast<LBoundJsonGridPicker*> (m_control));
|
||||
m_BoundJsonGridPicker->SetColumnName(m_colName);
|
||||
if (!m_intentLabel.IsEmpty())
|
||||
m_BoundJsonGridPicker->SetIntentLabel(m_intentLabel);
|
||||
m_BoundControl = m_BoundJsonGridPicker;
|
||||
m_rsEVH = new JsonGridEditorRsEVH(this);
|
||||
m_control->Show(false);
|
||||
}
|
||||
|
||||
void LGridJsonCellEditor::BeginEdit(int row, int col, wxGrid *grid)
|
||||
{
|
||||
if (m_editRow != row)
|
||||
m_jsonBuffer.MakeNull();
|
||||
m_editRow = row;
|
||||
if (m_control == NULL)
|
||||
{
|
||||
Create(grid->GetGridWindow(), wxID_ANY, NULL);
|
||||
}
|
||||
|
||||
LResultSet * rs = ((LBoundGrid *) grid)->GetResultSet();
|
||||
m_rsEVH->SetResultSet(rs);
|
||||
rs->RegisterEventHandler(m_rsEVH);
|
||||
|
||||
m_BoundJsonGridPicker->SetResultSet(rs);
|
||||
if (m_jsonBuffer.IsNull() && row < rs->GetRowCount())
|
||||
m_jsonBuffer = rs->GetData(row, col);
|
||||
m_BoundJsonGridPicker->SetData(m_jsonBuffer);
|
||||
m_control->Show(true);
|
||||
}
|
||||
|
||||
wxGridCellEditor* LGridJsonCellEditor::Clone() const
|
||||
{
|
||||
return new LGridJsonCellEditor(m_colName, m_intentLabel, m_choices, m_popupSize);
|
||||
}
|
||||
|
||||
bool LGridJsonCellEditor::EndEdit(int row, int col, const wxGrid *grid, const wxString &oldval, wxString *newval)
|
||||
{
|
||||
// What do we do here ?
|
||||
return true;
|
||||
}
|
||||
|
||||
void LGridJsonCellEditor::ApplyEdit(int row, int col, wxGrid *grid)
|
||||
{
|
||||
m_jsonBuffer = m_BoundJsonGridPicker->GetValue();
|
||||
grid->GetTable()->SetValue(row, col, m_jsonBuffer.As<wxString>());
|
||||
}
|
||||
|
||||
void LGridJsonCellEditor::Reset()
|
||||
{
|
||||
delete m_rsEVH;
|
||||
m_rsEVH = NULL;
|
||||
wxDELETE(m_control);
|
||||
m_BoundControl = NULL;
|
||||
m_BoundJsonGridPicker = NULL;
|
||||
m_jsonBuffer.MakeNull();
|
||||
m_editRow = wxNOT_FOUND;
|
||||
}
|
||||
|
||||
wxString LGridJsonCellEditor::GetValue() const
|
||||
{
|
||||
return m_control == NULL ? wxString(wxEmptyString) : m_BoundControl->GetData().As<wxString>();
|
||||
}
|
||||
|
||||
wxControl* LGridJsonCellEditor::ProvideFormEditor(wxWindow * parent)
|
||||
{
|
||||
if (!m_formEditor) m_formEditor = new JsonGridPickerCtrl(parent, wxID_ANY, m_choices);
|
||||
m_formEditor->SetValue(GetValue());
|
||||
m_formEditor->SetName(m_BoundJsonGridPicker->GetName());
|
||||
m_formEditor->SetIntentLabel(m_BoundJsonGridPicker->GetIntentLabel());
|
||||
if (m_BoundJsonGridPicker->GetValidator()) m_formEditor->SetValidator(*(m_BoundJsonGridPicker->GetValidator()));
|
||||
return m_formEditor;
|
||||
}
|
||||
|
||||
void LGridJsonCellEditor::SyncBack(const int row, const int col, wxGrid * grid)
|
||||
{
|
||||
if (!m_formEditor) return;
|
||||
m_BoundJsonGridPicker->SetValue(m_formEditor->GetValue());
|
||||
ApplyEdit(row, col, grid);
|
||||
wxDELETE(m_formEditor);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
JsonGridEditorRsEVH::JsonGridEditorRsEVH(LGridJsonCellEditor * owner)
|
||||
: LResultSetEvent()
|
||||
{
|
||||
m_owner = owner;
|
||||
m_rs = NULL;
|
||||
}
|
||||
|
||||
JsonGridEditorRsEVH::~JsonGridEditorRsEVH()
|
||||
{
|
||||
if (m_rs)
|
||||
m_rs->UnRegisterEventHandler(this);
|
||||
}
|
||||
|
||||
void JsonGridEditorRsEVH::AfterAction(LResultSet * caller, ACTIONS action)
|
||||
{
|
||||
m_rs = caller;
|
||||
if (action == ACTIONS::ACTION_CANCEL)
|
||||
{
|
||||
m_owner->m_jsonBuffer.MakeNull();
|
||||
}
|
||||
}
|
||||
|
||||
void JsonGridEditorRsEVH::DataChanged(LResultSet* caller)
|
||||
{
|
||||
m_rs = caller;
|
||||
m_owner->m_jsonBuffer.MakeNull();
|
||||
}
|
||||
125
special/LGridJsonCellEditor.h
Normal file
125
special/LGridJsonCellEditor.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* File: LGridJsonCellEditor.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 9, 2019, 10:36 AM
|
||||
*/
|
||||
|
||||
#ifndef LGRIDJSONCELLEDITOR_H
|
||||
#define LGRIDJSONCELLEDITOR_H
|
||||
|
||||
#include "../LGridColEditor.h"
|
||||
#include "LBoundJsonGridPicker.h"
|
||||
|
||||
class JsonGridEditorRsEVH;
|
||||
class LGridJsonCellEditor;
|
||||
|
||||
/**
|
||||
* A grid cell editor using LBoundJsonGridPicker
|
||||
* @param newColName
|
||||
* @param intentLabel
|
||||
* @param types
|
||||
* @param popupSize
|
||||
*/
|
||||
class LGridJsonCellEditor : public wxGridCellEditor, public LGridColEditor
|
||||
{
|
||||
friend class JsonGridEditorRsEVH;
|
||||
public:
|
||||
LGridJsonCellEditor(const wxString& newColName,
|
||||
const wxString& intentLabel,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize = wxDefaultSize);
|
||||
virtual ~LGridJsonCellEditor();
|
||||
|
||||
/**
|
||||
* Creates m_control as LBoundJsonGridPicker.
|
||||
* @param parent
|
||||
* @param id
|
||||
* @param evtHandler
|
||||
*/
|
||||
void Create(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler);
|
||||
/**
|
||||
* Creates m_control if necessary. Registers the editor in the grid's resultset.
|
||||
* @param row
|
||||
* @param col
|
||||
* @param grid
|
||||
*/
|
||||
void BeginEdit(int row, int col, wxGrid *grid);
|
||||
wxGridCellEditor* Clone() const;
|
||||
bool EndEdit(int row, int col, const wxGrid *grid, const wxString &oldval, wxString *newval);
|
||||
/**
|
||||
* Applies the editor value as returned by GetValue() to the grid cell.
|
||||
* @param row
|
||||
* @param col
|
||||
* @param grid
|
||||
*/
|
||||
void ApplyEdit(int row, int col, wxGrid *grid);
|
||||
/**
|
||||
* Deletes the editor, all pointers to the editor are set to NULL.
|
||||
*/
|
||||
void Reset();
|
||||
/**
|
||||
*
|
||||
* @return GetData(), or wxEmptyString if the editor control has not been created.
|
||||
*/
|
||||
wxString GetValue() const;
|
||||
/**
|
||||
* Creates a wxTextCtrl to be used as editor in form view.
|
||||
*/
|
||||
wxControl* ProvideFormEditor(wxWindow * parent);
|
||||
|
||||
wxControl* GetFormEditor() const
|
||||
{
|
||||
return m_formEditor;
|
||||
}
|
||||
/**
|
||||
* Updates the grid cell and the editor. m_formEditor is deleted and set to NULL.
|
||||
* @param row
|
||||
* @param col
|
||||
* @param grid
|
||||
*/
|
||||
void SyncBack(const int row, const int col, wxGrid * grid);
|
||||
|
||||
private:
|
||||
wxString m_intentLabel;
|
||||
wxArrayString m_choices;
|
||||
wxSize m_popupSize;
|
||||
JsonGridPickerCtrl * m_formEditor;
|
||||
wxAny m_jsonBuffer;
|
||||
int m_editRow;
|
||||
/**
|
||||
* Fully typed alias to m_control.
|
||||
*/
|
||||
LBoundJsonGridPicker * m_BoundJsonGridPicker;
|
||||
wxWeakRef<JsonGridEditorRsEVH> m_rsEVH;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears LGridJsonGridEditor::m_jsonBuffer on LBoundGrid::Cancel.
|
||||
* Must be trackable. If it is deleted by an application, avoid crash in
|
||||
* destructor of LGridJsonGridEditor.
|
||||
*/
|
||||
class JsonGridEditorRsEVH : public LResultSetEvent, public wxTrackable
|
||||
{
|
||||
friend class LGridJsonCellEditor;
|
||||
public:
|
||||
|
||||
private:
|
||||
JsonGridEditorRsEVH(LGridJsonCellEditor * owner);
|
||||
virtual ~JsonGridEditorRsEVH();
|
||||
virtual void AfterAction(LResultSet * caller, ACTIONS action);
|
||||
virtual void DataChanged(LResultSet* caller);
|
||||
|
||||
void SetResultSet(LResultSet * caller)
|
||||
{
|
||||
m_rs = caller;
|
||||
}
|
||||
|
||||
LResultSet * m_rs;
|
||||
LGridJsonCellEditor * m_owner;
|
||||
};
|
||||
|
||||
#endif /* LGRIDJSONCELLEDITOR_H */
|
||||
|
||||
73
special/LGridJsonCellRenderer.cpp
Normal file
73
special/LGridJsonCellRenderer.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* File: LGridJsonCellRenderer.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 9, 2019, 1:55 PM
|
||||
*/
|
||||
|
||||
#include "LGridJsonCellRenderer.h"
|
||||
#include "BaseGridPicker.h"
|
||||
#include <wx/jsonreader.h>
|
||||
|
||||
LGridJsonCellRenderer::LGridJsonCellRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
LGridJsonCellRenderer::~LGridJsonCellRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
void LGridJsonCellRenderer::Draw(wxGrid & grid,
|
||||
wxGridCellAttr & attr,
|
||||
wxDC & dc,
|
||||
const wxRect & rect,
|
||||
int row,
|
||||
int col,
|
||||
bool isSelected)
|
||||
{
|
||||
const wxString intent = ProcessJsonValue(grid.GetCellValue(row, col));
|
||||
grid.SetCellValue(row, col, intent);
|
||||
|
||||
wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
|
||||
}
|
||||
|
||||
const wxString LGridJsonCellRenderer::ProcessJsonValue(const wxString& cellValue)
|
||||
{
|
||||
if (cellValue.IsEmpty())
|
||||
return INVALID_INTENT;
|
||||
|
||||
wxJSONReader reader(wxJSONREADER_STRICT);
|
||||
wxJSONValue root;
|
||||
uint nbErr = reader.Parse(cellValue, &root);
|
||||
if (nbErr > 0)
|
||||
{
|
||||
const wxArrayString& errors = reader.GetErrors();
|
||||
for (int i = 0; i < nbErr; i++)
|
||||
{
|
||||
wxASSERT_MSG(nbErr == 0, errors[i]);
|
||||
}
|
||||
// Show raw data.
|
||||
return cellValue;
|
||||
}
|
||||
if (!root.IsArray())
|
||||
{
|
||||
wxASSERT_MSG(root.IsArray(), _("JSON data is not an array"));
|
||||
return cellValue;
|
||||
}
|
||||
for (uint row = 0; row < root.Size(); row++)
|
||||
{
|
||||
if (root[row]["Preferred"].IsValid()
|
||||
&& !root[row]["Preferred"].AsString().IsEmpty()
|
||||
&& root[row]["Preferred"].AsInt() != 0)
|
||||
{
|
||||
return root[row]["Intent"].AsString();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Don't show raw data if there's no preferred item.
|
||||
* The data will still be in the editor and saved.
|
||||
*/
|
||||
return INVALID_INTENT;
|
||||
}
|
||||
38
special/LGridJsonCellRenderer.h
Normal file
38
special/LGridJsonCellRenderer.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* File: LGridJsonCellRenderer.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 9, 2019, 1:55 PM
|
||||
*/
|
||||
|
||||
#ifndef LGRIDJSONCELLRENDERER_H
|
||||
#define LGRIDJSONCELLRENDERER_H
|
||||
|
||||
#include "wx/grid.h"
|
||||
|
||||
/**
|
||||
* A grid cell renderer for json stored data.
|
||||
* It show the selected Intent value, or INVALID_INTENT.
|
||||
*/
|
||||
class LGridJsonCellRenderer : public wxGridCellStringRenderer
|
||||
{
|
||||
public:
|
||||
LGridJsonCellRenderer();
|
||||
virtual ~LGridJsonCellRenderer();
|
||||
|
||||
void Draw(wxGrid & grid,
|
||||
wxGridCellAttr & attr,
|
||||
wxDC & dc,
|
||||
const wxRect & rect,
|
||||
int row,
|
||||
int col,
|
||||
bool isSelected);
|
||||
private:
|
||||
|
||||
const wxString ProcessJsonValue(const wxString& cellValue);
|
||||
};
|
||||
|
||||
#endif /* LGRIDJSONCELLRENDERER_H */
|
||||
|
||||
149
special/LGridXmlCellEditor.cpp
Normal file
149
special/LGridXmlCellEditor.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* File: LGridXmlCellEditor.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 15, 2019, 6:32 PM
|
||||
*/
|
||||
|
||||
#include "LGridXmlCellEditor.h"
|
||||
#include "../LBoundGrid.h"
|
||||
|
||||
LGridXmlCellEditor::LGridXmlCellEditor(const wxString& newColName,
|
||||
const wxString& intentLabel,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize)
|
||||
: wxGridCellEditor(), LGridColEditor()
|
||||
{
|
||||
m_intentLabel = intentLabel;
|
||||
m_choices = types;
|
||||
m_popupSize = popupSize;
|
||||
m_colName = newColName;
|
||||
m_type = LGridColEditor::XML_GRID;
|
||||
m_formEditor = NULL;
|
||||
m_BoundControl = NULL;
|
||||
m_BoundXmlGridPicker = NULL;
|
||||
m_editRow = wxNOT_FOUND;
|
||||
m_rsEVH = NULL;
|
||||
}
|
||||
|
||||
LGridXmlCellEditor::~LGridXmlCellEditor()
|
||||
{
|
||||
delete m_rsEVH;
|
||||
wxDELETE(m_control);
|
||||
}
|
||||
|
||||
void LGridXmlCellEditor::Create(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler)
|
||||
{
|
||||
m_control = new LBoundXmlGridPicker(parent, id, m_choices, m_popupSize);
|
||||
m_BoundXmlGridPicker = (static_cast<LBoundXmlGridPicker*> (m_control));
|
||||
m_BoundXmlGridPicker->SetColumnName(m_colName);
|
||||
if (!m_intentLabel.IsEmpty())
|
||||
m_BoundXmlGridPicker->SetIntentLabel(m_intentLabel);
|
||||
m_BoundControl = m_BoundXmlGridPicker;
|
||||
m_rsEVH = new XmlGridEditorRsEVH(this);
|
||||
m_control->Show(false);
|
||||
}
|
||||
|
||||
void LGridXmlCellEditor::BeginEdit(int row, int col, wxGrid *grid)
|
||||
{
|
||||
if (m_editRow != row)
|
||||
m_xmlBuffer.MakeNull();
|
||||
m_editRow = row;
|
||||
if (m_control == NULL)
|
||||
{
|
||||
Create(grid->GetGridWindow(), wxID_ANY, NULL);
|
||||
}
|
||||
|
||||
LResultSet * rs = ((LBoundGrid *) grid)->GetResultSet();
|
||||
m_rsEVH->SetResultSet(rs);
|
||||
rs->RegisterEventHandler(m_rsEVH);
|
||||
|
||||
m_BoundXmlGridPicker->SetResultSet(rs);
|
||||
if (m_xmlBuffer.IsNull() && row < rs->GetRowCount())
|
||||
m_xmlBuffer = rs->GetData(row, col);
|
||||
m_BoundXmlGridPicker->SetData(m_xmlBuffer);
|
||||
m_control->Show(true);
|
||||
}
|
||||
|
||||
wxGridCellEditor* LGridXmlCellEditor::Clone() const
|
||||
{
|
||||
return new LGridXmlCellEditor(m_colName, m_intentLabel, m_choices, m_popupSize);
|
||||
}
|
||||
|
||||
bool LGridXmlCellEditor::EndEdit(int row, int col, const wxGrid *grid, const wxString &oldval, wxString *newval)
|
||||
{
|
||||
// What do we do here ?
|
||||
return true;
|
||||
}
|
||||
|
||||
void LGridXmlCellEditor::ApplyEdit(int row, int col, wxGrid *grid)
|
||||
{
|
||||
m_xmlBuffer = m_BoundXmlGridPicker->GetValue();
|
||||
grid->GetTable()->SetValue(row, col, m_xmlBuffer.As<wxString>());
|
||||
}
|
||||
|
||||
void LGridXmlCellEditor::Reset()
|
||||
{
|
||||
delete m_rsEVH;
|
||||
m_rsEVH = NULL;
|
||||
wxDELETE(m_control);
|
||||
m_BoundControl = NULL;
|
||||
m_BoundXmlGridPicker = NULL;
|
||||
m_xmlBuffer.MakeNull();
|
||||
m_editRow = wxNOT_FOUND;
|
||||
}
|
||||
|
||||
wxString LGridXmlCellEditor::GetValue() const
|
||||
{
|
||||
return m_control == NULL ? wxString(wxEmptyString) : m_BoundControl->GetData().As<wxString>();
|
||||
}
|
||||
|
||||
wxControl* LGridXmlCellEditor::ProvideFormEditor(wxWindow * parent)
|
||||
{
|
||||
if (!m_formEditor) m_formEditor = new XmlGridPickerCtrl(parent, wxID_ANY, m_choices);
|
||||
m_formEditor->SetValue(GetValue());
|
||||
m_formEditor->SetName(m_BoundXmlGridPicker->GetName());
|
||||
m_formEditor->SetIntentLabel(m_BoundXmlGridPicker->GetIntentLabel());
|
||||
if (m_BoundXmlGridPicker->GetValidator()) m_formEditor->SetValidator(*(m_BoundXmlGridPicker->GetValidator()));
|
||||
return m_formEditor;
|
||||
}
|
||||
|
||||
void LGridXmlCellEditor::SyncBack(const int row, const int col, wxGrid * grid)
|
||||
{
|
||||
if (!m_formEditor) return;
|
||||
m_BoundXmlGridPicker->SetValue(m_formEditor->GetValue());
|
||||
ApplyEdit(row, col, grid);
|
||||
wxDELETE(m_formEditor);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
XmlGridEditorRsEVH::XmlGridEditorRsEVH(LGridXmlCellEditor * owner)
|
||||
: LResultSetEvent()
|
||||
{
|
||||
m_owner = owner;
|
||||
m_rs = NULL;
|
||||
}
|
||||
|
||||
XmlGridEditorRsEVH::~XmlGridEditorRsEVH()
|
||||
{
|
||||
if (m_rs)
|
||||
m_rs->UnRegisterEventHandler(this);
|
||||
}
|
||||
|
||||
void XmlGridEditorRsEVH::AfterAction(LResultSet * caller, ACTIONS action)
|
||||
{
|
||||
m_rs = caller;
|
||||
if (action == ACTIONS::ACTION_CANCEL)
|
||||
{
|
||||
m_owner->m_xmlBuffer.MakeNull();
|
||||
}
|
||||
}
|
||||
|
||||
void XmlGridEditorRsEVH::DataChanged(LResultSet* caller)
|
||||
{
|
||||
m_rs = caller;
|
||||
m_owner->m_xmlBuffer.MakeNull();
|
||||
}
|
||||
124
special/LGridXmlCellEditor.h
Normal file
124
special/LGridXmlCellEditor.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* File: LGridXmlCellEditor.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 15, 2019, 6:32 PM
|
||||
*/
|
||||
|
||||
#ifndef LGRIDXMLCELLEDITOR_H
|
||||
#define LGRIDXMLCELLEDITOR_H
|
||||
|
||||
#include "../LGridColEditor.h"
|
||||
#include "LBoundXmlGridPicker.h"
|
||||
|
||||
class XmlGridEditorRsEVH;
|
||||
class LGridXmlCellEditor;
|
||||
|
||||
/**
|
||||
* A grid cell editor using LBoundXmlGridPicker
|
||||
* @param newColName
|
||||
* @param intentLabel
|
||||
* @param types
|
||||
* @param popupSize
|
||||
*/
|
||||
class LGridXmlCellEditor : public wxGridCellEditor, public LGridColEditor
|
||||
{
|
||||
friend class XmlGridEditorRsEVH;
|
||||
public:
|
||||
LGridXmlCellEditor(const wxString& newColName,
|
||||
const wxString& intentLabel,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize = wxDefaultSize);
|
||||
virtual ~LGridXmlCellEditor();
|
||||
/**
|
||||
* Creates m_control as LBoundJsonGridPicker.
|
||||
* @param parent
|
||||
* @param id
|
||||
* @param evtHandler
|
||||
*/
|
||||
void Create(wxWindow *parent, wxWindowID id, wxEvtHandler *evtHandler);
|
||||
/**
|
||||
* Creates m_control if necessary. Registers the editor in the grid's resultset.
|
||||
* @param row
|
||||
* @param col
|
||||
* @param grid
|
||||
*/
|
||||
void BeginEdit(int row, int col, wxGrid *grid);
|
||||
wxGridCellEditor* Clone() const;
|
||||
bool EndEdit(int row, int col, const wxGrid *grid, const wxString &oldval, wxString *newval);
|
||||
/**
|
||||
* Applies the editor value as returned by GetValue() to the grid cell.
|
||||
* @param row
|
||||
* @param col
|
||||
* @param grid
|
||||
*/
|
||||
void ApplyEdit(int row, int col, wxGrid *grid);
|
||||
/**
|
||||
* Deletes the editor, all pointers to the editor are set to NULL.
|
||||
*/
|
||||
void Reset();
|
||||
/**
|
||||
*
|
||||
* @return GetData(), or wxEmptyString if the editor control has not been created.
|
||||
*/
|
||||
wxString GetValue() const;
|
||||
/**
|
||||
* Creates a wxTextCtrl to be used as editor in form view.
|
||||
*/
|
||||
wxControl* ProvideFormEditor(wxWindow * parent);
|
||||
|
||||
wxControl* GetFormEditor() const
|
||||
{
|
||||
return m_formEditor;
|
||||
}
|
||||
/**
|
||||
* Updates the grid cell and the editor. m_formEditor is deleted and set to NULL.
|
||||
* @param row
|
||||
* @param col
|
||||
* @param grid
|
||||
*/
|
||||
void SyncBack(const int row, const int col, wxGrid * grid);
|
||||
|
||||
private:
|
||||
wxString m_intentLabel;
|
||||
wxArrayString m_choices;
|
||||
wxSize m_popupSize;
|
||||
XmlGridPickerCtrl * m_formEditor;
|
||||
wxAny m_xmlBuffer;
|
||||
int m_editRow;
|
||||
/**
|
||||
* Fully typed alias to m_control.
|
||||
*/
|
||||
LBoundXmlGridPicker * m_BoundXmlGridPicker;
|
||||
wxWeakRef<XmlGridEditorRsEVH> m_rsEVH;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears LGridXmlGridEditor::m_jsonBuffer on LBoundGrid::Cancel.
|
||||
* Must be trackable. If it is deleted by an application, avoid crash in
|
||||
* destructor of LGridXmlGridEditor.
|
||||
*/
|
||||
class XmlGridEditorRsEVH : public LResultSetEvent, public wxTrackable
|
||||
{
|
||||
friend class LGridXmlCellEditor;
|
||||
public:
|
||||
|
||||
private:
|
||||
XmlGridEditorRsEVH(LGridXmlCellEditor * owner);
|
||||
virtual ~XmlGridEditorRsEVH();
|
||||
virtual void AfterAction(LResultSet * caller, ACTIONS action);
|
||||
virtual void DataChanged(LResultSet* caller);
|
||||
|
||||
void SetResultSet(LResultSet * caller)
|
||||
{
|
||||
m_rs = caller;
|
||||
}
|
||||
|
||||
LResultSet * m_rs;
|
||||
LGridXmlCellEditor * m_owner;
|
||||
};
|
||||
|
||||
#endif /* LGRIDXMLCELLEDITOR_H */
|
||||
|
||||
58
special/LGridXmlCellRenderer.cpp
Normal file
58
special/LGridXmlCellRenderer.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* File: LGridXmlCellRenderer.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 15, 2019, 6:18 PM
|
||||
*/
|
||||
|
||||
#include "LGridXmlCellRenderer.h"
|
||||
#include "XmlHelper.h"
|
||||
#include "BaseGridPicker.h"
|
||||
|
||||
LGridXmlCellRenderer::LGridXmlCellRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
LGridXmlCellRenderer::~LGridXmlCellRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
void LGridXmlCellRenderer::Draw(wxGrid & grid,
|
||||
wxGridCellAttr & attr,
|
||||
wxDC & dc,
|
||||
const wxRect & rect,
|
||||
int row,
|
||||
int col,
|
||||
bool isSelected)
|
||||
{
|
||||
const wxString intent = ProcessXmlValue(grid.GetCellValue(row, col));
|
||||
grid.SetCellValue(row, col, intent);
|
||||
|
||||
wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
|
||||
}
|
||||
|
||||
const wxString LGridXmlCellRenderer::ProcessXmlValue(const wxString& cellValue)
|
||||
{
|
||||
if (cellValue.IsEmpty())
|
||||
return INVALID_INTENT;
|
||||
wxXmlDocument doc;
|
||||
wxXmlNode * root = XmlHelper::ValidateXmlValue(doc, cellValue);
|
||||
if (root == NULL)
|
||||
// Show raw data.
|
||||
return cellValue;
|
||||
wxXmlNode * row = root->GetChildren();
|
||||
while (row)
|
||||
{
|
||||
const wxString pref = row->GetAttribute(XML_ATTR_PREF);
|
||||
if (!pref.IsEmpty() && pref != _T("0"))
|
||||
return row->GetNodeContent();
|
||||
row = row->GetNext();
|
||||
}
|
||||
/*
|
||||
* Don't show raw data if there's no preferred item.
|
||||
* The data will still be in the editor and saved.
|
||||
*/
|
||||
return INVALID_INTENT;
|
||||
}
|
||||
39
special/LGridXmlCellRenderer.h
Normal file
39
special/LGridXmlCellRenderer.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* File: LGridXmlCellRenderer.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 15, 2019, 6:18 PM
|
||||
*/
|
||||
|
||||
#ifndef LGRIDXMLCELLRENDERER_H
|
||||
#define LGRIDXMLCELLRENDERER_H
|
||||
|
||||
#include "wx/grid.h"
|
||||
|
||||
/**
|
||||
* A grid cell renderer for xml stored data.
|
||||
* It show the selected Intent value, or INVALID_INTENT.
|
||||
*/
|
||||
class LGridXmlCellRenderer : public wxGridCellStringRenderer
|
||||
{
|
||||
public:
|
||||
LGridXmlCellRenderer();
|
||||
virtual ~LGridXmlCellRenderer();
|
||||
|
||||
void Draw(wxGrid & grid,
|
||||
wxGridCellAttr & attr,
|
||||
wxDC & dc,
|
||||
const wxRect & rect,
|
||||
int row,
|
||||
int col,
|
||||
bool isSelected);
|
||||
private:
|
||||
|
||||
const wxString ProcessXmlValue(const wxString& cellValue);
|
||||
|
||||
};
|
||||
|
||||
#endif /* LGRIDXMLCELLRENDERER_H */
|
||||
|
||||
167
special/XmlGridPickerCtrl.cpp
Normal file
167
special/XmlGridPickerCtrl.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* File: XmlGridPickerCtrl.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 14, 2019, 3:28 PM
|
||||
*/
|
||||
|
||||
#include "XmlGridPickerCtrl.h"
|
||||
#include <wx/sstream.h>
|
||||
#include "XmlHelper.h"
|
||||
|
||||
/*
|
||||
* <?xml version="1.0" encoding="UTF-8"?>
|
||||
<TABLE>
|
||||
<ROW Type="Work" Preferred="1" Notes="Do not use">+33 1 23 45 67 89</ROW>
|
||||
<ROW Type="Home" Preferred="0" Notes="Neither">+33 9 87 65 43 21</ROW>
|
||||
</TABLE>
|
||||
*/
|
||||
|
||||
IMPLEMENT_CLASS(XmlGridPickerCtrl, BaseGridPicker)
|
||||
|
||||
XmlGridPickerCtrl::XmlGridPickerCtrl(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize,
|
||||
const wxString& text,
|
||||
const wxPoint& pos,
|
||||
const wxSize& size,
|
||||
long style,
|
||||
const wxValidator& validator,
|
||||
const wxString& name)
|
||||
: BaseGridPicker(parent, id, types, popupSize, text, pos, size, style, validator, name)
|
||||
{
|
||||
/*
|
||||
* Don't create the grid here. Let SetValue() do it, deleting the previous
|
||||
* one every time new data is fed in.
|
||||
*/
|
||||
SetValue(wxEmptyString);
|
||||
}
|
||||
|
||||
XmlGridPickerCtrl::~XmlGridPickerCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
void XmlGridPickerCtrl::SetValue(const wxString& value)
|
||||
{
|
||||
if (value.IsEmpty())
|
||||
{
|
||||
m_value = EMPTY_DOC;
|
||||
BaseGridPicker::CreateGrid(); // +++
|
||||
GetTextCtrl()->SetValue(INVALID_INTENT);
|
||||
return;
|
||||
}
|
||||
m_value = value;
|
||||
BaseGridPicker::CreateGrid(); // +++
|
||||
GetTextCtrl()->SetValue(INVALID_INTENT);
|
||||
wxXmlDocument doc;
|
||||
wxXmlNode * root = XmlHelper::ValidateXmlValue(doc, m_value);
|
||||
if (root == NULL)
|
||||
{
|
||||
GetTextCtrl()->SetValue(INVALID_INTENT);
|
||||
return;
|
||||
}
|
||||
// Look for preferred
|
||||
wxXmlNode * row = root->GetChildren();
|
||||
while (row)
|
||||
{
|
||||
const wxString pref = row->GetAttribute(XML_ATTR_PREF);
|
||||
if (!pref.IsEmpty()
|
||||
&& pref != _T("0"))
|
||||
{
|
||||
GetTextCtrl()->SetValue(row->GetNodeContent());
|
||||
return;
|
||||
}
|
||||
row = row->GetNext();
|
||||
}
|
||||
GetTextCtrl()->SetValue(INVALID_INTENT);
|
||||
}
|
||||
|
||||
wxString XmlGridPickerCtrl::GetValue()
|
||||
{
|
||||
DumpGrid();
|
||||
|
||||
wxXmlDocument doc;
|
||||
wxXmlNode * root = new wxXmlNode(wxXML_ELEMENT_NODE, XML_ROOT_NAME);
|
||||
doc.SetRoot(root);
|
||||
wxString emptyXmlData;
|
||||
wxStringOutputStream sos(&emptyXmlData);
|
||||
doc.Save(sos);
|
||||
|
||||
if (m_value == emptyXmlData)
|
||||
return wxEmptyString;
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void XmlGridPickerCtrl::FillGrid()
|
||||
{
|
||||
wxASSERT_MSG(m_grid != NULL, _("m_grid IS NULL"));
|
||||
wxXmlDocument doc;
|
||||
wxXmlNode * root = XmlHelper::ValidateXmlValue(doc, m_value);
|
||||
if (root == NULL)
|
||||
{
|
||||
GetTextCtrl()->SetValue(INVALID_INTENT);
|
||||
return;
|
||||
}
|
||||
wxXmlNode * row = root->GetChildren();
|
||||
int idx = 0;
|
||||
while (row)
|
||||
{
|
||||
m_grid->InsertRows(idx);
|
||||
m_grid->SetCellValue(idx, 0, row->GetNodeContent());
|
||||
m_grid->SetCellValue(idx, 1, row->GetAttribute(XML_ATTR_TYPE));
|
||||
m_grid->SetCellValue(idx, 2, row->GetAttribute(XML_ATTR_PREF));
|
||||
m_grid->SetCellValue(idx, 3, row->GetAttribute(XML_ATTR_NOTES));
|
||||
idx++;
|
||||
row = row->GetNext();
|
||||
}
|
||||
}
|
||||
|
||||
void XmlGridPickerCtrl::DumpGrid()
|
||||
{
|
||||
wxASSERT_MSG(m_grid != NULL, _("m_grid IS NULL"));
|
||||
wxASSERT_MSG(m_stringTable != NULL, _("m_stringTable IS NULL"));
|
||||
if (!m_editable || !m_stringTable || !m_grid)
|
||||
return;
|
||||
wxXmlDocument doc;
|
||||
// This is EMPTY_DOC
|
||||
wxXmlNode * root = new wxXmlNode(wxXML_ELEMENT_NODE, XML_ROOT_NAME);
|
||||
doc.SetRoot(root);
|
||||
for (uint grow = 0; grow < m_stringTable->GetRowsCount(); grow++)
|
||||
{
|
||||
if (m_stringTable->GetValue(grow, 0).IsEmpty())
|
||||
continue;
|
||||
/*
|
||||
* Don't use the other constructor :
|
||||
* wxXmlNode(wxXmlNode *parent, wxXmlNodeType type ...
|
||||
* The row order will be reversed each time.
|
||||
* Explicitly add independent nodes to root.
|
||||
*/
|
||||
wxXmlNode * row = new wxXmlNode(wxXML_ELEMENT_NODE, XML_ROW_NAME);
|
||||
wxXmlAttribute * attr = new wxXmlAttribute(XML_ATTR_TYPE, m_stringTable->GetValue(grow, 1));
|
||||
row->AddAttribute(attr);
|
||||
attr = new wxXmlAttribute(XML_ATTR_PREF, (m_stringTable->GetValue(grow, 2) == _T("0")
|
||||
|| m_stringTable->GetValue(grow, 2).IsEmpty()) ? _T("0") : _T("1"));
|
||||
row->AddAttribute(attr);
|
||||
attr = new wxXmlAttribute(XML_ATTR_NOTES, m_stringTable->GetValue(grow, 3));
|
||||
row->AddAttribute(attr);
|
||||
new wxXmlNode(row, wxXML_TEXT_NODE, _T("irrelevant_name"), m_stringTable->GetValue(grow, 0));
|
||||
root->AddChild(row);
|
||||
}
|
||||
wxString xmlData;
|
||||
wxStringOutputStream sos(&xmlData);
|
||||
bool res = doc.Save(sos);
|
||||
if (!res)
|
||||
{
|
||||
wxASSERT_MSG(res, _T("Error dumping to XML"));
|
||||
// Let's not empty m_value.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_value = xmlData; // May be empty XML with XML_ROOT_NAME tag only
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
66
special/XmlGridPickerCtrl.h
Normal file
66
special/XmlGridPickerCtrl.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* File: XmlGridPickerCtrl.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 14, 2019, 3:28 PM
|
||||
*/
|
||||
|
||||
#ifndef XMLGRIDPICKERCTRL_H
|
||||
#define XMLGRIDPICKERCTRL_H
|
||||
|
||||
#include "BaseGridPicker.h"
|
||||
#include <wx/xml/xml.h>
|
||||
|
||||
/**
|
||||
* The grid content is stored in an XML document.
|
||||
* @return
|
||||
*/
|
||||
class XmlGridPickerCtrl : public BaseGridPicker
|
||||
{
|
||||
DECLARE_CLASS(XmlGridPickerCtrl)
|
||||
public:
|
||||
XmlGridPickerCtrl(wxWindow *parent,
|
||||
wxWindowID id,
|
||||
const wxArrayString& types,
|
||||
wxSize popupSize = wxDefaultSize,
|
||||
const wxString& text = wxEmptyString,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxPB_USE_TEXTCTRL,
|
||||
const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxButtonNameStr);
|
||||
virtual ~XmlGridPickerCtrl();
|
||||
|
||||
/**
|
||||
* Creates a new grid deleting the previous one and fills it with the XML
|
||||
* data.
|
||||
* @param value
|
||||
*/
|
||||
virtual void SetValue(const wxString& value);
|
||||
|
||||
/**
|
||||
* Dumps the grid content and returns it as an XML document. But returns
|
||||
* empty string if XML document is empty.
|
||||
* @return
|
||||
*/
|
||||
virtual wxString GetValue();
|
||||
private:
|
||||
/**
|
||||
* Parses the XML document and fills the grid.
|
||||
*/
|
||||
virtual void FillGrid();
|
||||
/**
|
||||
* Translates the grid content to an XML document.
|
||||
* If the Intent column is empty, this row is ignored.
|
||||
*/
|
||||
virtual void DumpGrid();
|
||||
/**
|
||||
* Is the XML document.
|
||||
*/
|
||||
wxString m_value;
|
||||
};
|
||||
|
||||
#endif /* XMLGRIDPICKERCTRL_H */
|
||||
|
||||
75
special/XmlHelper.cpp
Normal file
75
special/XmlHelper.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* File: XmlHelper.cpp
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 15, 2019, 4:13 PM
|
||||
*/
|
||||
|
||||
#include "XmlHelper.h"
|
||||
#include <wx/sstream.h>
|
||||
|
||||
XmlHelper::XmlHelper()
|
||||
{
|
||||
}
|
||||
|
||||
XmlHelper::~XmlHelper()
|
||||
{
|
||||
}
|
||||
|
||||
// if doc is declared with local scope, root elements are empty in caller
|
||||
|
||||
wxXmlNode* XmlHelper::ValidateXmlValue(wxXmlDocument& doc, const wxString& value)
|
||||
{
|
||||
// Avoid 'XML parsing error' message box.
|
||||
wxLogNull lognull;
|
||||
wxStringInputStream sis(value);
|
||||
bool res = doc.Load(sis);
|
||||
if (!res)
|
||||
{
|
||||
wxASSERT_MSG(res == true, _T("Can't load XML data.\n") + value);
|
||||
return NULL;
|
||||
}
|
||||
wxXmlNode * root = doc.GetRoot();
|
||||
if (root->GetName() != XML_ROOT_NAME)
|
||||
{
|
||||
wxASSERT_MSG(root->GetName() != XML_ROOT_NAME, _T("Bad XML data.\n") + value);
|
||||
return NULL;
|
||||
}
|
||||
// Check all rows and attributes
|
||||
wxXmlNode * row = root->GetChildren();
|
||||
while (row)
|
||||
{
|
||||
if (row->GetName() != XML_ROW_NAME
|
||||
|| !row->HasAttribute(XML_ATTR_TYPE)
|
||||
|| !row->HasAttribute(XML_ATTR_PREF)
|
||||
|| !row->HasAttribute(XML_ATTR_NOTES)
|
||||
|| row->GetNodeContent().IsEmpty())
|
||||
{
|
||||
wxASSERT_MSG(root->GetName() != XML_ROOT_NAME, _T("Unexpected XML data.\n") + value);
|
||||
return NULL;
|
||||
}
|
||||
row = row->GetNext();
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
wxString XmlHelper::GetIntent(const wxString& xmlData)
|
||||
{
|
||||
if (xmlData.IsEmpty())
|
||||
return wxEmptyString;
|
||||
wxXmlDocument doc;
|
||||
wxXmlNode * root = ValidateXmlValue(doc, xmlData);
|
||||
if (root == NULL)
|
||||
return wxEmptyString;
|
||||
wxXmlNode * row = root->GetChildren();
|
||||
while (row)
|
||||
{
|
||||
const wxString pref = row->GetAttribute(XML_ATTR_PREF);
|
||||
if (!pref.IsEmpty() && pref != _T("0"))
|
||||
return row->GetNodeContent();
|
||||
row = row->GetNext();
|
||||
}
|
||||
return wxEmptyString;
|
||||
}
|
||||
54
special/XmlHelper.h
Normal file
54
special/XmlHelper.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* File: XmlHelper.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : LGPL version 2.1
|
||||
* Copyright SET, M. D. - © 2014
|
||||
*
|
||||
* Created on December 15, 2019, 4:13 PM
|
||||
*/
|
||||
|
||||
#ifndef XMLHELPER_H
|
||||
#define XMLHELPER_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/xml/xml.h>
|
||||
|
||||
#define XML_ROOT_NAME _T("TABLE")
|
||||
#define XML_ROW_NAME _T("ROW")
|
||||
#define XML_ATTR_TYPE _T("Type")
|
||||
#define XML_ATTR_PREF _T("Preferred")
|
||||
#define XML_ATTR_NOTES _T("Notes")
|
||||
#define EMPTY_DOC _T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<TABLE/>")
|
||||
|
||||
/**
|
||||
* Application helper to quickly get the Intent value.
|
||||
* @param doc
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
class XmlHelper
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Parses value which is XML data and returns the XML root node, while
|
||||
* loading the XML data in doc.
|
||||
* If value does not have the expected tags defined above, returns NULL.
|
||||
* @param doc
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
static wxXmlNode * ValidateXmlValue(wxXmlDocument& doc, const wxString& value);
|
||||
/**
|
||||
* Returns a valid Intent value or an empty string.
|
||||
* @param xmlData
|
||||
* @return
|
||||
*/
|
||||
static wxString GetIntent(const wxString& xmlData);
|
||||
private:
|
||||
XmlHelper();
|
||||
virtual ~XmlHelper();
|
||||
};
|
||||
|
||||
#endif /* XMLHELPER_H */
|
||||
|
||||
Reference in New Issue
Block a user