2010-11-07 14:00:59 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Name: objref.cpp
|
|
|
|
// Purpose: XML resources sample: Object references and ID ranges dialog
|
|
|
|
// Author: David Hart, Vaclav Slavik
|
|
|
|
// RCS-ID: $Id$
|
|
|
|
// Copyright: (c) Vaclav Slavik
|
|
|
|
// Licence: wxWindows licence
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Standard wxWidgets 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" wxWidgets headers)
|
|
|
|
#ifndef WX_PRECOMP
|
|
|
|
#include "wx/wx.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Header of this .cpp file
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "objrefdlg.h"
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2010-11-07 19:33:38 +00:00
|
|
|
// Needed wx headers,
|
2010-11-07 14:00:59 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#include "wx/xrc/xmlres.h" // XRC XML resouces
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Public members
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
ObjrefDialog::ObjrefDialog(wxWindow* parent)
|
|
|
|
{
|
|
|
|
wxXmlResource::Get()->LoadDialog(this, parent, wxT("objref_dialog"));
|
|
|
|
|
|
|
|
nb = XRCCTRL(*this, "objref_notebook", wxNotebook);
|
|
|
|
wxCHECK_RET(nb, "failed to find objref_notebook");
|
2010-11-07 19:33:30 +00:00
|
|
|
|
|
|
|
// Connect different event handlers.
|
|
|
|
nb->Connect(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
|
|
|
|
wxNotebookEventHandler(ObjrefDialog::OnNotebookPageChanged),
|
|
|
|
NULL, this);
|
|
|
|
|
|
|
|
// We want to direct UpdateUI events for the ID range 'first_row' to
|
|
|
|
// OnUpdateUIFirst(). We could achieve this using first_row[0] and
|
|
|
|
// first_row[2], but what if a fourth column were added? It's safer to use
|
|
|
|
// the 'typedefs' for the two ends of the range:
|
|
|
|
wxNotebookPage *page = nb->GetPage(icons_page);
|
|
|
|
page->Connect(XRCID("first_row[start]"), XRCID("first_row[end]"),
|
|
|
|
wxEVT_UPDATE_UI,
|
|
|
|
wxUpdateUIEventHandler(ObjrefDialog::OnUpdateUIFirst),
|
|
|
|
NULL, this);
|
|
|
|
page->Connect(XRCID("second_row[start]"), XRCID("second_row[end]"),
|
|
|
|
wxEVT_UPDATE_UI,
|
|
|
|
wxUpdateUIEventHandler(ObjrefDialog::OnUpdateUISecond),
|
|
|
|
NULL, this);
|
|
|
|
page->Connect(XRCID("third_row[start]"), XRCID("third_row[end]"),
|
|
|
|
wxEVT_UPDATE_UI,
|
|
|
|
wxUpdateUIEventHandler(ObjrefDialog::OnUpdateUIThird),
|
|
|
|
NULL, this);
|
|
|
|
|
|
|
|
// Connect the id ranges, using the [start] and [end] 'typedefs'
|
|
|
|
page = nb->GetPage(calc_page);
|
|
|
|
page->Connect(XRCID("digits[start]"), XRCID("digits[end]"),
|
|
|
|
wxEVT_COMMAND_BUTTON_CLICKED,
|
|
|
|
wxCommandEventHandler(ObjrefDialog::OnNumeralClick),
|
|
|
|
NULL, this);
|
|
|
|
page->Connect(XRCID("operators[start]"), XRCID("operators[end]"),
|
|
|
|
wxEVT_COMMAND_BUTTON_CLICKED,
|
|
|
|
wxCommandEventHandler(ObjrefDialog::OnOperatorClick),
|
|
|
|
NULL, this);
|
|
|
|
|
2010-11-07 14:00:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ObjrefDialog::~ObjrefDialog()
|
|
|
|
{
|
2010-11-07 19:33:38 +00:00
|
|
|
// Select page 0. Otherwise if the Calc page were selected, when it's
|
|
|
|
// removed the Icons page is selected and sets the log target again in idle
|
|
|
|
// time, *after* myframe restores the old one!
|
2010-11-07 14:00:59 +00:00
|
|
|
nb->ChangeSelection(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Private members (including the event handlers)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void ObjrefDialog::OnNotebookPageChanged( wxNotebookEvent &event )
|
|
|
|
{
|
|
|
|
switch(event.GetSelection())
|
|
|
|
{
|
|
|
|
case copy_page:
|
|
|
|
{
|
|
|
|
// This is a straight object reference to the first page
|
|
|
|
// so change the text programmatically
|
|
|
|
nb->SetPageText(copy_page, "Page 1 copy");
|
|
|
|
|
|
|
|
wxNotebookPage *page = nb->GetPage(copy_page);
|
2010-11-07 19:33:38 +00:00
|
|
|
wxTextCtrl *
|
|
|
|
text = XRCCTRL(*page, "description_text", wxTextCtrl);
|
2010-11-07 14:00:59 +00:00
|
|
|
text->ChangeValue(
|
2010-11-07 19:33:38 +00:00
|
|
|
"This is a duplicate of page 1, using an object reference. "
|
|
|
|
"It was created by this very simple xml:\n\n"
|
|
|
|
"<object class=\"notebookpage\">\n\t<object_ref ref=\"page1\"/>\n"
|
|
|
|
"\t<label>Page 1 copy</label>\n</object>"
|
|
|
|
"\n\n(Then I'm cheating by inserting this text programmatically.)"
|
2010-11-07 14:00:59 +00:00
|
|
|
);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case icons_page:
|
|
|
|
{
|
|
|
|
wxNotebookPage *page = nb->GetPage(icons_page);
|
|
|
|
text = XRCCTRL(*page, "log_text", wxTextCtrl);
|
|
|
|
if (text)
|
|
|
|
delete wxLog::SetActiveTarget(new wxLogTextCtrl(text));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case calc_page:
|
|
|
|
{
|
|
|
|
wxNotebookPage *page = nb->GetPage(calc_page);
|
|
|
|
result_txt = XRCCTRL(*page, "result", wxTextCtrl);
|
|
|
|
text = XRCCTRL(*page, "log_text", wxTextCtrl);
|
|
|
|
if (text)
|
|
|
|
delete wxLog::SetActiveTarget(new wxLogTextCtrl(text));
|
|
|
|
|
|
|
|
ClearCalculator();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default: return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-07 19:33:38 +00:00
|
|
|
// There are undoubtedly simpler ways of doing all this, but we're
|
|
|
|
// demonstrating the use of ID ranges
|
2010-11-07 14:00:59 +00:00
|
|
|
void ObjrefDialog::OnUpdateUIFirst(wxUpdateUIEvent& event)
|
|
|
|
{
|
|
|
|
// The checkbox with the XRCID 'check[0]' controls this row of icons
|
2010-11-07 19:33:38 +00:00
|
|
|
wxCheckBox *
|
|
|
|
chk = XRCCTRL(*(nb->GetPage(icons_page)), "check[0]", wxCheckBox);
|
2010-11-07 14:00:59 +00:00
|
|
|
if (chk)
|
|
|
|
event.Enable(chk->IsChecked());
|
|
|
|
|
|
|
|
// Let's create a log-window entry
|
|
|
|
static bool checked = true;
|
|
|
|
if (chk->IsChecked() != checked)
|
|
|
|
{
|
|
|
|
checked = chk->IsChecked();
|
2010-11-07 19:33:38 +00:00
|
|
|
wxLogMessage("Row one has been %s by check[0], XRCID = %i",
|
|
|
|
checked ? "enabled" : "disabled", XRCID("check[0]"));
|
|
|
|
wxLogMessage("XRCIDs: first_row[start] = %i, first_row[0] = %i, "
|
|
|
|
"first_row[1] = %i, first_row[2] = %i, "
|
|
|
|
"first_row[end] = %i",
|
|
|
|
XRCID("first_row[start]"), XRCID("first_row[0]"),
|
|
|
|
XRCID("first_row[1]"), XRCID("first_row[2]"),
|
|
|
|
XRCID("first_row[end]"));
|
2010-11-07 14:00:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjrefDialog::OnUpdateUISecond(wxUpdateUIEvent& event)
|
|
|
|
{
|
|
|
|
// The checkbox with the XRCID 'check[1]' controls this row of icons
|
2010-11-07 19:33:38 +00:00
|
|
|
wxCheckBox *
|
|
|
|
chk = XRCCTRL(*(nb->GetPage(icons_page)), "check[1]", wxCheckBox);
|
2010-11-07 14:00:59 +00:00
|
|
|
if (chk)
|
|
|
|
event.Enable(chk->IsChecked());
|
|
|
|
|
|
|
|
// Let's create a log-window entry
|
|
|
|
static bool checked = true;
|
|
|
|
if (chk->IsChecked() != checked)
|
|
|
|
{
|
|
|
|
checked = chk->IsChecked();
|
2010-11-07 19:33:38 +00:00
|
|
|
wxLogMessage("Row two has been %s by check[1], XRCID = %i",
|
|
|
|
checked ? "enabled" : "disabled", XRCID("check[1]"));
|
|
|
|
wxLogMessage("XRCIDs: second_row[start] = %i, second_row[0] = %i, "
|
|
|
|
"second_row[1] = %i, second_row[2] = %i, "
|
|
|
|
"second_row[end] = %i",
|
|
|
|
XRCID("second_row[start]"), XRCID("second_row[0]"),
|
|
|
|
XRCID("second_row[1]"), XRCID("second_row[2]"),
|
|
|
|
XRCID("second_row[end]"));
|
2010-11-07 14:00:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjrefDialog::OnUpdateUIThird(wxUpdateUIEvent& event)
|
|
|
|
{
|
|
|
|
// The checkbox with the XRCID 'check[2]' controls this row of icons
|
2010-11-07 19:33:38 +00:00
|
|
|
wxCheckBox *
|
|
|
|
chk = XRCCTRL(*(nb->GetPage(icons_page)), "check[2]", wxCheckBox);
|
2010-11-07 14:00:59 +00:00
|
|
|
if (chk)
|
|
|
|
event.Enable(chk->IsChecked());
|
|
|
|
|
|
|
|
// Let's create a log-window entry
|
|
|
|
static bool checked = true;
|
|
|
|
if (chk->IsChecked() != checked)
|
|
|
|
{
|
|
|
|
checked = chk->IsChecked();
|
2010-11-07 19:33:38 +00:00
|
|
|
wxLogMessage("Row three has been %s by check[2], XRCID = %i",
|
|
|
|
checked ? "enabled" : "disabled", XRCID("check[2]"));
|
|
|
|
wxLogMessage("XRCIDs: third_row[start] = %i, third_row[0] = %i, "
|
|
|
|
"third_row[1] = %i, third_row[2] = %i, "
|
|
|
|
"third_row[end] = %i",
|
|
|
|
XRCID("third_row[start]"), XRCID("third_row[0]"),
|
|
|
|
XRCID("third_row[1]"), XRCID("third_row[2]"),
|
|
|
|
XRCID("third_row[end]"));
|
2010-11-07 14:00:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjrefDialog::OnNumeralClick(wxCommandEvent& event)
|
|
|
|
{
|
|
|
|
// See how the id range simplifies determining which numeral was clicked
|
|
|
|
int digit = event.GetId() - XRCID("digits[start]");
|
|
|
|
|
|
|
|
char c = '0' + digit;
|
|
|
|
if (current==0 && previous==0)
|
|
|
|
{
|
|
|
|
// We're just starting a calculation, so get rid of the placeholder '0'
|
|
|
|
result_txt->Clear();
|
|
|
|
}
|
|
|
|
else if (operator_expected == true)
|
|
|
|
{
|
2010-11-07 19:33:38 +00:00
|
|
|
// If we've just finished one calculation, and now a digit is entered,
|
|
|
|
// clear
|
2010-11-07 14:00:59 +00:00
|
|
|
ClearCalculator();
|
|
|
|
result_txt->Clear();
|
|
|
|
}
|
|
|
|
(*result_txt) << c;
|
|
|
|
|
|
|
|
|
|
|
|
current = current*10 + digit;
|
|
|
|
|
|
|
|
wxLogMessage("You clicked digits[%c], XRCID %i", c, event.GetId());
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjrefDialog::OnOperatorClick(wxCommandEvent& event)
|
|
|
|
{
|
|
|
|
static const char symbols[] = "+-*/=";
|
|
|
|
|
|
|
|
operator_expected = false;
|
|
|
|
int ID = event.GetId() - XRCID("operators[start]");
|
|
|
|
|
|
|
|
// We carefully used "operators[end]" as the name of the Clear button
|
|
|
|
if (event.GetId() == XRCID("operators[end]"))
|
|
|
|
{
|
2010-11-07 19:33:38 +00:00
|
|
|
wxLogMessage("You clicked operators[%i], XRCID %d, 'Clear'",
|
|
|
|
ID, event.GetId());
|
2010-11-07 14:00:59 +00:00
|
|
|
return ClearCalculator();
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(ID)
|
|
|
|
{
|
|
|
|
case operator_plus:
|
|
|
|
case operator_minus:
|
|
|
|
case operator_multiply:
|
|
|
|
case operator_divide:
|
|
|
|
if (current!=0 || previous!=0)
|
|
|
|
{
|
2010-11-07 19:33:38 +00:00
|
|
|
// We're in the middle of a complex calculation, so do the
|
|
|
|
// first bit
|
2010-11-07 14:00:59 +00:00
|
|
|
Calculate();
|
|
|
|
}
|
|
|
|
curr_operator = (CalcOperator)ID;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case operator_equals:
|
|
|
|
Calculate();
|
2010-11-07 19:33:38 +00:00
|
|
|
wxLogMessage("You clicked operators[%i], XRCID %i, giving a '%c'",
|
|
|
|
ID, event.GetId(), symbols[ID]);
|
2010-11-07 14:00:59 +00:00
|
|
|
curr_operator = operator_equals;
|
|
|
|
// Flag that the next entry should be an operator, not a digit
|
|
|
|
operator_expected = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
(*result_txt) << ' ' << symbols[ID] << ' ';
|
|
|
|
|
2010-11-07 19:33:38 +00:00
|
|
|
wxLogMessage("You clicked operators[%i], XRCID %i, giving a '%c'",
|
|
|
|
ID, event.GetId(), symbols[ID]);
|
2010-11-07 14:00:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ObjrefDialog::Calculate()
|
|
|
|
{
|
|
|
|
switch(curr_operator)
|
|
|
|
{
|
|
|
|
case operator_plus:
|
|
|
|
previous += current; break;
|
|
|
|
case operator_minus:
|
|
|
|
previous -= current; break;
|
|
|
|
case operator_multiply:
|
|
|
|
previous *= current; break;
|
|
|
|
case operator_divide:
|
|
|
|
if (current!=0)
|
|
|
|
previous /= current;
|
|
|
|
break;
|
|
|
|
default: return;
|
|
|
|
}
|
|
|
|
|
|
|
|
curr_operator = operator_plus;
|
|
|
|
current = 0;
|
|
|
|
result_txt->Clear();
|
|
|
|
|
|
|
|
(*result_txt) << previous;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ObjrefDialog::ClearCalculator()
|
|
|
|
{
|
|
|
|
current = previous = 0;
|
|
|
|
curr_operator = operator_plus;
|
|
|
|
operator_expected = false;
|
|
|
|
result_txt->ChangeValue("0");
|
|
|
|
}
|