///////////////////////////////////////////////////////////////////////////// // 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 #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 #endif #include #include #include #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); }