/////////////////////////////////////////////////////////////////////////////
// Name: dbobject.cpp
// Purpose: Database Objects
// Author: Daniel Horak
// Modified by:
// RCS-ID: $Id: dbobject.cc,v 1.5 2004/01/04 18:32:16 horakdan Exp $
// Copyright: (c) Daniel Horak
// Licence: GPL
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include <wx/wxprec.h>
#ifdef __BORLANDC__
#pragma hdrstop
#endif
// for all others, include the necessary headers (this file is usually all you
// need because it includes almost all "standard" wxWindows headers
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/notebook.h>
#include <wx/ogl/ogl.h>
#include <wx/listimpl.cpp>
#include "config.h"
#include "xml.h"
#include "dbobject.h"
#include "schema.h"
#define ID_LIST 100
DBObject::DBObject(DBObjectType type, const wxString& typestr, DataDesignerProject *project, DataDesignerContainer *container)
: m_type(type), m_typestr(typestr), m_project(project), m_container(container), m_appended(FALSE), m_shape(NULL)
{
}
DBObject::~DBObject()
{
DataDesignerSchema *schema;
if (m_appended) {
m_project->Delete(m_treeitemid);
}
if (m_shape) {
m_shape->Show(FALSE);
schema = m_project->GetSchema();
if (schema)
schema->RemoveShape(m_shape);
}
}
wxTreeItemId DBObject::AppendItem()
{
if (! m_appended) {
m_treeitemid = m_project->AppendItem(m_container->GetTreeItemId(), m_name, -1, -1, new DataDesignerItemData(this));
m_appended = TRUE;
}
return m_treeitemid;
}
wxTreeItemId DBObject::InsertItem(const wxTreeItemId& prev)
{
m_treeitemid = m_project->InsertItem(m_container->GetTreeItemId(), prev, m_name, -1, -1, new DataDesignerItemData(this));
m_appended = TRUE;
return m_treeitemid;
}
void DBObject::LoadXmlNode(wxXmlNode *node)
{
wxXmlNode *child;
m_name = node->GetPropVal("name", wxEmptyString);
m_pname = node->GetPropVal("pname", wxEmptyString);
child = node->GetChildren();
while (child) {
if (child->GetName() == "remark") {
LoadTextNode(child, "remark", m_remark);
} else if (child->GetName() == "description") {
LoadTextNode(child, "description", m_desc);
}
child = child->GetNext();
}
m_project->SetItemText(m_treeitemid, m_name);
}
wxXmlNode* DBObject::GetXmlNode()
{
wxXmlNode *node;
node = new wxXmlNode(wxXML_ELEMENT_NODE, m_typestr);
node->AddProperty("name", m_name);
node->AddProperty("pname", m_pname);
node->AddChild(GetTextNode("description", m_desc));
node->AddChild(GetTextNode("remark", m_remark));
return node;
}
void DBObject::LoadTextNode(wxXmlNode *node, const wxString& name, wxString& value)
{
wxXmlNode *elem;
if (! value.IsEmpty()) {
wxLogMessage("parameter '%s' has been already set to %s", name.c_str(), value.c_str());
return;
}
elem = node->GetChildren();
if (elem) {
if (elem->GetType() == wxXML_TEXT_NODE) {
value = elem->GetContent();
} else {
wxLogMessage("child of '%s' node must text node", name.c_str());
}
} else {
wxLogMessage("no child of '%s' node", name.c_str());
value = wxEmptyString;
}
}
wxXmlNode *DBObject::GetTextNode(const wxString& name, const wxString& value)
{
wxXmlNode *elem, *txt;
if (value == wxEmptyString)
return NULL;
txt = new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString, value);
elem = new wxXmlNode(wxXML_ELEMENT_NODE, name);
elem->AddChild(txt);
return elem;
}
void DBObject::LoadBoolNode(wxXmlNode *node, const wxString& name, bool& value, bool defval)
{
wxXmlNode *elem;
wxString boolval;
elem = node->GetChildren();
if (elem) {
if (elem->GetType() == wxXML_TEXT_NODE) {
boolval = elem->GetContent();
if (boolval == "true")
value = TRUE;
else if (boolval == "false")
value = FALSE;
else {
wxLogMessage("wrong '%s' specification '%s'", name.c_str(), boolval.c_str());
value = defval;
}
} else {
wxLogMessage("child of '%s' node must text node", name.c_str());
}
} else {
wxLogMessage("no child of '%s' node", name.c_str());
value = defval;
}
}
wxXmlNode *DBObject::GetBoolNode(const wxString& name, const bool& value)
{
wxXmlNode *elem, *val;
val = new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString, value ? "true" : "false");
elem = new wxXmlNode(wxXML_ELEMENT_NODE, name);
elem->AddChild(val);
return elem;
}
void DBObject::LoadBoolProperty(wxXmlNode *node, const wxString& name, bool& value, bool defval)
{
wxString boolval;
boolval = node->GetPropVal(name, wxEmptyString);
if ((boolval == "Y") || (boolval == "y") || (boolval == "T") || (boolval =="t"))
value = TRUE;
else if ((boolval == "N") || (boolval == "n") || (boolval == "F") || (boolval =="f"))
value = FALSE;
else {
if (boolval != wxEmptyString)
wxLogMessage("wrong '%s' specification '%s'", name.c_str(), boolval.c_str());
value = defval;
}
}
wxXmlProperty *DBObject::GetBoolProperty(const wxString& name, const bool& value)
{
wxXmlProperty *prop;
prop = new wxXmlProperty();
prop->SetName(name);
prop->SetValue(value ? "Y" : "N");
return prop;
}
void DBObject::CreateShape()
{
}
void DBObject::CreatePName()
{
m_pname = m_name;
m_pname.MakeLower();
m_pname.Replace(" ", "_");
}
void DBObject::CreateNextName()
{
if (m_container)
m_name.Printf("%s%d", m_typestr.c_str(), m_container->GetNextId());
else
m_name.Printf("%s", m_typestr.c_str());
}
WX_DEFINE_LIST(DBObjectList);
/*
* Editor
*/
BEGIN_EVENT_TABLE(DBObjectEditor, wxDialog)
EVT_BUTTON (ID_BUTTON_COPYNAME, DBObjectEditor::OnCopyName)
END_EVENT_TABLE()
DBObjectEditor::DBObjectEditor(const wxString& title, const wxSize& size, DBObject *object, bool edit)
: wxDialog(NULL, -1, title, wxDefaultPosition, size, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
m_object(object), m_button_x(10), m_edit(edit)
{
m_notebook = new wxNotebook(this, -1);
m_panel_button = new wxPanel(this);
wxLayoutConstraints *c = new wxLayoutConstraints;
c->top.SameAs (this, wxTop);
c->left.SameAs (this, wxLeft);
c->right.SameAs (this, wxRight);
c->bottom.SameAs(m_panel_button, wxTop);
m_notebook->SetConstraints(c);
c = new wxLayoutConstraints;
c->height.Absolute(40);
c->left.SameAs (this, wxLeft);
c->right.SameAs (this, wxRight);
c->bottom.SameAs(this, wxBottom);
m_panel_button->SetConstraints(c);
m_page_general = new wxPanel(m_notebook);
m_page_remark = new wxPanel(m_notebook);
// info on main
new wxStaticText(m_page_general, -1, _("Logical Name"), wxPoint(10,10), wxSize(80,-1), wxALIGN_RIGHT);
it1 = new wxTextCtrl(m_page_general, -1, wxEmptyString, wxPoint(100,10), wxSize(100,-1));
if (m_edit)
it1->Disable();
m_button_copyname = new wxButton(m_page_general, ID_BUTTON_COPYNAME, ">>", wxPoint(220,10), wxSize(30,-1));
new wxStaticText(m_page_general, -1, _("Physical Name"), wxPoint(260,10), wxSize(100,-1), wxALIGN_RIGHT);
it4 = new wxTextCtrl(m_page_general, -1, wxEmptyString, wxPoint(370,10), wxSize(100,-1));
new wxStaticText(m_page_general, -1, _("Description"), wxPoint(10,35), wxSize(80,-1), wxALIGN_RIGHT);
it2 = new wxTextCtrl(m_page_general, -1, wxEmptyString, wxPoint(100,35), wxSize(370,-1));
// remark
it3 = new wxTextCtrl(m_page_remark, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxTE_PROCESS_TAB);
c = new wxLayoutConstraints;
c->top.SameAs (m_page_remark, wxTop);
c->left.SameAs (m_page_remark, wxLeft);
c->right.SameAs (m_page_remark, wxRight);
c->bottom.SameAs(m_page_remark, wxBottom);
it3->SetConstraints(c);
m_page_general->SetAutoLayout(TRUE);
m_page_remark->SetAutoLayout(TRUE);
m_notebook->AddPage(m_page_general, _("General"));
m_notebook->AddPage(m_page_remark, _("Remark"));
SetAutoLayout(TRUE);
m_button_ok = AddButton(wxID_OK, _("OK"), wxSize(60,-1));
m_button_cancel = AddButton(wxID_CANCEL, _("Cancel"), wxSize(60,-1));
m_button_ok->SetDefault();
if (m_edit)
it2->SetFocus();
else
it1->SetFocus();
Center();
Layout(); // needed in WXMSW to use layout constraints
}
wxButton *DBObjectEditor::AddButton(wxWindowID id, const wxString& label, const wxSize& size)
{
wxButton *button;
button = new wxButton(m_panel_button, id, label, wxPoint(m_button_x, 10), size);
m_button_x += size.x + 20;
return button;
}
bool DBObjectEditor::TransferDataFromWindow()
{
DBObject *object = GetObject();
if (it1->IsModified())
object->m_name = it1->GetValue();
object->m_desc = it2->GetValue();
object->m_remark = it3->GetValue();
object->m_pname = it4->GetValue();
if (object->m_pname.IsEmpty())
object->CreatePName();
/* we must also set that the project is modified */
object->GetProject()->GetSplitter()->GetView()->GetDocument()->Modify(TRUE);
/* refresh schema, should be optimized, so the schema is refreshed only when some visible change is made */
if (object->GetProject()->GetSchema())
object->GetProject()->GetSchema()->Refresh();
return TRUE;
}
bool DBObjectEditor::TransferDataToWindow()
{
DBObject *object = GetObject();
if (object->m_name.IsEmpty())
object->CreateNextName();
it1->SetValue(object->m_name);
it2->SetValue(object->m_desc);
it3->SetValue(object->m_remark);
it4->SetValue(object->m_pname);
return TRUE;
}
bool DBObjectEditor::Validate()
{
if (m_edit == FALSE) {
// check only when creating a new object, during editing it is not possible to change object's name
if (it1->GetValue().IsEmpty()) {
wxMessageBox(_("Cannot create object without a name"), _("Error"), wxOK | wxICON_ERROR);
return FALSE;
}
if (GetObject()->GetContainer()->GetObjectByName(it1->GetValue())) {
wxMessageBox(_("Object with the same name already exists"), _("Error"), wxOK | wxICON_ERROR);
return FALSE;
}
}
return TRUE;
}
void DBObjectEditor::OnCopyName(wxCommandEvent& event)
{
if (! it1->GetValue().IsEmpty()) {
DBObject *object = GetObject();
object->CreatePName();
it4->SetValue(object->m_pname);
}
}
/*
* ObjectList Control
*/
BEGIN_EVENT_TABLE(DBObjectListCtrl, wxPanel)
EVT_LIST_ITEM_ACTIVATED (ID_LIST, DBObjectListCtrl::OnActivated)
EVT_LIST_ITEM_SELECTED (ID_LIST, DBObjectListCtrl::OnSelected)
EVT_BUTTON (ID_BUTTON_ADD, DBObjectListCtrl::OnAdd)
EVT_BUTTON (ID_BUTTON_EDIT, DBObjectListCtrl::OnEdit)
EVT_BUTTON (ID_BUTTON_DELETE, DBObjectListCtrl::OnDelete)
EVT_BUTTON (ID_BUTTON_MOVEUP, DBObjectListCtrl::OnMoveUp)
EVT_BUTTON (ID_BUTTON_MOVEDOWN, DBObjectListCtrl::OnMoveDown)
END_EVENT_TABLE()
DBObjectListCtrl::DBObjectListCtrl(wxWindow *parent, DataDesignerContainer *container)
: wxPanel(parent), m_current(-1), m_container(container)
{
m_list = new wxListCtrl(this, ID_LIST);
m_list->SetWindowStyleFlag(wxLC_REPORT | wxSUNKEN_BORDER | wxLC_SINGLE_SEL);
m_list->InsertColumn(0, _("Name"));
m_bpanel = new wxPanel(this);
wxLayoutConstraints *c = new wxLayoutConstraints;
c->top.SameAs(this, wxTop);
c->left.SameAs(this, wxLeft);
c->right.SameAs(this, wxRight);
c->bottom.SameAs(m_bpanel, wxTop);
m_list->SetConstraints(c);
c = new wxLayoutConstraints;
c->height.Absolute(40);
c->left.SameAs(this, wxLeft);
c->right.SameAs(this, wxRight);
c->bottom.SameAs(this, wxBottom);
m_bpanel->SetConstraints(c);
m_button_add = new wxButton(m_bpanel, ID_BUTTON_ADD, _("Add"), wxPoint(10,10), wxSize(60,-1));
m_button_edit = new wxButton(m_bpanel, ID_BUTTON_EDIT, _("Edit"), wxPoint(80,10), wxSize(60,-1));
m_button_delete = new wxButton(m_bpanel, ID_BUTTON_DELETE, _("Delete"), wxPoint(150,10), wxSize(60,-1));
m_button_moveup = new wxButton(m_bpanel, ID_BUTTON_MOVEUP, _("Up"), wxPoint(220,10), wxSize(40,-1));
m_button_movedown = new wxButton(m_bpanel, ID_BUTTON_MOVEDOWN, _("Down"), wxPoint(270,10), wxSize(40,-1));
SetAutoLayout(TRUE);
}
DBObjectListCtrl::~DBObjectListCtrl()
{
}
long DBObjectListCtrl::InsertColumn(long index, const wxString& heading)
{
return m_list->InsertColumn(index, heading);
}
long DBObjectListCtrl::InsertItem(long index, const wxString& label)
{
return m_list->InsertItem(index, label);
}
bool DBObjectListCtrl::SetColumnWidth(int col, int width)
{
return m_list->SetColumnWidth(col, width);
}
bool DBObjectListCtrl::SetColumnTitle(int col, const wxString& title)
{
wxListItem item;
item.m_mask = wxLIST_MASK_TEXT;
item.m_text = title;
return m_list->SetColumn(col, item);
}
bool DBObjectListCtrl::SetItemData(long item, long data)
{
return m_list->SetItemData(item, data);
}
long DBObjectListCtrl::SetItem(long item, long col, const wxString& label)
{
return m_list->SetItem(item, col, label);
}
void DBObjectListCtrl::AddObject(long item, DBObject *object)
{
InsertItem(item, object->m_name);
SetItemData(item, (long)object);
SetObject(item, object);
}
void DBObjectListCtrl::OnActivated(wxListEvent& event)
{
m_current = event.GetIndex();
#ifdef ENABLE_DEBUG
wxLogMessage("OnActivated - m_current=%ld", m_current);
#endif
OnEditCommon();
}
void DBObjectListCtrl::OnSelected(wxListEvent& event)
{
m_current = event.GetIndex();
#ifdef ENABLE_DEBUG
wxLogMessage("OnSelected - m_current=%ld", m_current);
#endif
if (m_current == 0)
m_button_moveup->Disable();
else
m_button_moveup->Enable();
if (m_current == m_list->GetItemCount() - 1)
m_button_movedown->Disable();
else
m_button_movedown->Enable();
}
void DBObjectListCtrl::OnAdd(wxCommandEvent& event)
{
DBObject *object;
wxDialog *editor;
object = m_container->CreateObject();
if (object == NULL) {
wxLogMessage("OnAdd - object == NULL");
return;
}
editor = object->Editor(FALSE);
if (editor) {
if (editor->ShowModal() == wxID_OK) {
object->AppendItem();
AddObject(m_list->GetItemCount(), object);
} else {
delete object;
}
editor->Destroy();
}
}
void DBObjectListCtrl::OnEdit(wxCommandEvent& event)
{
OnEditCommon();
}
void DBObjectListCtrl::OnEditCommon()
{
DBObject *object;
wxDialog *editor;
int res;
if (m_current == -1)
return;
object = (DBObject *)(m_list->GetItemData(m_current));
if (object == NULL) {
wxLogMessage("OnEditCommon - object == NULL");
return;
}
editor = object->Editor(TRUE);
if (editor) {
if ((res = editor->ShowModal()) == wxID_OK) {
SetObject(m_current, object);
m_list->SetItemState(m_current, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
m_list->EnsureVisible(m_current);
}
editor->Destroy();
}
}
void DBObjectListCtrl::OnDelete(wxCommandEvent& event)
{
DBObject *object;
DataDesignerProject *project;
#ifdef ENABLE_DEBUG
wxLogMessage("OnDelete - m_current=%ld", m_current);
#endif
if (m_current == -1)
return;
object = (DBObject *)(m_list->GetItemData(m_current));
if (object == NULL) {
wxLogMessage("OnDelete - object == NULL");
return;
}
m_list->DeleteItem(m_current);
delete object;
}
void DBObjectListCtrl::OnMoveUp(wxCommandEvent& event)
{
DBObject *selobj,
*prevobj;
DataDesignerProject *project;
// if no item selected or first item selected, then return
if ((m_current == -1) || (m_current == 0))
return;
selobj = (DBObject *)(m_list->GetItemData(m_current));
prevobj = (DBObject *)(m_list->GetItemData(m_current - 1));
project = selobj->GetProject();
project->GetSplitter()->GetView()->GetDocument()->Modify(TRUE);
// move in list
SwapItems(m_current, m_current - 1);
// move in tree
project->SwapItems(selobj->GetTreeItemId(), prevobj->GetTreeItemId());
}
void DBObjectListCtrl::OnMoveDown(wxCommandEvent& event)
{
DBObject *selobj,
*nextobj;
DataDesignerProject *project;
// if no item selected or last item selected, then return
if ((m_current == -1) || (m_current == (m_list->GetItemCount() - 1)))
return;
selobj = (DBObject *)(m_list->GetItemData(m_current));
nextobj = (DBObject *)(m_list->GetItemData(m_current + 1));
project = selobj->GetProject();
project->GetSplitter()->GetView()->GetDocument()->Modify(TRUE);
// move in list
SwapItems(m_current, m_current + 1);
// move in tree
project->SwapItems(selobj->GetTreeItemId(), nextobj->GetTreeItemId());
}
void DBObjectListCtrl::SwapItems(long item1, long item2)
{
DBObject *object1 = (DBObject *)(m_list->GetItemData(item1));
DBObject *object2 = (DBObject *)(m_list->GetItemData(item2));
m_list->SetItemData(item1, (long)object2);
m_list->SetItemData(item2, (long)object1);
m_list->SetItem(item1, 0, object2->m_name);
m_list->SetItem(item2, 0, object1->m_name);
SetObject(item1, object2);
SetObject(item2, object1);
m_current == -1;
m_list->SetItemState(item2, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
}
syntax highlighted by Code2HTML, v. 0.9.1