[ Lit Window Library at SourceForge ] [ Lit Window Productions Homepage ] [ wxWidgets Tips&Tricks ] [ wxVisualSetup ]
| Normal C++ code | C++ with Lit Window Library |
|---|---|
void ReadSettings(wxConfigBase &cfg, Settings &s) { long l; cfg.Read("/settings/m_nextRefresh", &l); s.m_nextRefresh=wxDateTime(l); cfg.Read("/settings/m_refreshAfter", &l); s.m_refreshAfter=wxTimeSpan(l); // read channels vector cfg.Read("/settings/m_channels/size", &l); size_t i; s.m_channels.clear(); for (i=0; i<l; ++i) { Channel newChannel; cfg.SetPath(wxString::Format("/settings/m_channels/E%08d", i)); ReadChannel(cfg, newChannel); s.m_channels.push_back(newChannel); } } void ReadChannel(wxConfigBase &cfg, Channel &newChannel) { long l; cfg.Read("m_webAddress", &newChannel.m_newWebAddress); cfg.Read("m_title", &newChannel.m_title); cfg.Read("m_cacheExpires", &l); newChannel.m_cacheExpires=wxTimeSpan(l); cfg.Read("m_lastRead", &l); newChannel.m_lastRead=wxDateTime(l); cfg.Read("m_headlines/size", &l); newChannel.m_headlines.clear(); size_t i; for (i=0; i<l; ++i) { cfg.SetPath(wxString::Format("E%08d", i)); Headline newHeadline; cfg.Read("m_title", &newHeadline.m_title); cfg.Read("m_body", &newHeadline.m_body); long publishedTime; cfg.Read("m_published", &publishedTime); newHeadline.m_published=wxDateTime(publishedTime); cfg.Read("m_url", &newHeadline.m_url); newChannel.m_headlines.push_back(newHeadline); cfg.SetPath(".."); } } | void ReadSettings(wxConfigBase &cfg, Settings &s) { cfg >> setpath("/settings") >> s; } |
void WriteSettings(wxConfigBase &cfg, Settings &s) { cfg << setpath("/settings") << s; }
Headline. Assume you have to add this: wxString m_notes; // some user notes
| Normal C++ code | C++ with Lit Window Library |
|---|---|
|
|
| Normal C++ code | C++ with Lit Window Library |
|---|---|
void MyDialog::TransferData(Channel &s, bool saveData) { if (saveData) { // copy values from widgets to data s.m_title=m_title.GetValue(); s.m_webaddress=m_webaddress.GetValue(); s.m_cacheExpires=m_cacheExpires.GetValue(); } else { m_title.SetValue(s.m_title); m_webaddress.SetValue(s.m_webaddress); m_cacheExpires.SetValue(s.m_cacheExpires); } } void MyDialog::CreateControls() { m_webaddress=wxDynamicCast(FindWindow(XRCID(ID_WEBADDRESS)), wxTextCtrl); m_title=wxDynamicCast(FindWindow(XRCID(ID_TITLE)), wxTextCtrl); // or any other initialisation code to // init the member variables representing the widgets } void ShowDialog() { Channel channel; MyDialog dlg; dlg.TransferData(channel, false); if (dlg.ShowModal()==IDYES) { dlg.TransferData(channel, true); } } | void ShowDialog() { Channel channel; if (litwindow::ShowModalDialog(make_accessor(channel), "ID_CHANNEL_DIALOG")==IDYES) { // do something } } |
The RapidUI mechanism automatically transfers the value of all member variables from the 'channel' struct to their widgets and back.
The Lit Window Library listbox widget adds the following properties: _ container of 'things'
The important point is that 'thing' can be any data structure you define, as long as you also provide a data adapter. Here is how it works:
| Normal C++ code | C++ with Lit Window Library |
|---|---|
void FillChannelsListbox(wxListBox *lb, Settings &s) { lb->Clear(); size_t i; for (i=0; i<s.m_channels.size(); ++i) { lb->AppendString(s.m_channels.at(i).m_title); } } | BEGIN_RULES() "channelsListbox.Items=s.m_channels" "channelsListbox.Column=\"m_title\"" END_RULES() |
This example assigns a member variable m_channels to the Items property of a listbox channelsListbox. The Items property accepts any container. The Column property of the listbox contains the name of the member you want to display. If you wanted to show m_webaddress instead, you would simply change the Column property.
The same mechanism works for comboboxes, listcontrols, radioboxes, editcontrols etc...
| Normal C++ code | C++ with Lit Window Library |
|---|---|
void SomeDialog::OnUpdateEditcontrol(wxUpdateEvent &evt)
{
evt.SetEnabled(checkboxA->GetValue()!=1);
}
| editControlB.Enabled = !checkboxA.Checked |
| Normal C++ code | C++ with Lit Window Library |
|---|---|
BEGIN_EVENT_TABLE() EVT_LISTBOX(ID_CHANNEL_LISTBOX, OnSelectChannel) END_EVENT_TABLE() void SomeDialog::OnSelectChannel(wxCommandEvent &evt) { int selectedChannelIdx=channelsListbox->GetSelected(); if (selectedChannelIdx>=0) FillHeadlinesListbox( g_settings.m_channels.at(selectedChannelIdx).m_headlines); else FillHeadlinesListbox(vector<Headline>()); } void SomeDialog::FillHeadlinesListbox(vector<Headline> &headlines) { headlinesListbox->Clear(); size_t i; for (i=0; i<headlines.size(); ++i) { headlinesListbox->AppendString(headlines.at(i).m_title); } } | BEGIN_RULES() headlinesListbox.Column = "m_title" headlinesListbox.Items = channelsListbox.Current.m_headlines END_RULES() |
m_title as the element that is shown in the listbox. The last rule does the work. It ensures that the Items property (the list of elements shown) of the headlinesListbox is always 'in sync' with the m_headlines member variable of the currently selected (property Current) element of the channelsListbox.Let me explain a bit more slowly.
Items property of a listbox accepts any container.Current property of a listbox returns the 'thing' that is currently selected.Items.channelsListbox.Items has been assigned a vector<Channel>.channelsListbox.Current returns the currently selected element, which is of the type Channel.channelsListbox.Current.m_headlines is the m_headlines member variable of the currently selected Channel element.Items property of the headlinesListbox.
And RapidUI does the rest. It ensures that whenever the user changes the channelsListbox selection, all rules depending on channelsListbox are reevaluated. As a result, the headlinesListbox is updated every time the user changes the selection.
The Lit Window Library works differently. You define any data structures you like. To be able to use them, the library needs an adapter for every one of your data structures. This requires some initial work, but not very much.
If this is your data structure
struct Headline { wxString m_title; // the headline title wxString m_body; // the news in html wxDateTime m_published; // date/time when this headline was published string m_url; // an associated URL }; struct Channel { string m_webAddress; // url of the channel wxString m_title; // the title of this channel wxTimeSpan m_cacheExpires; // timespan between two refreshes vector<Headline> m_headlines; // the list of headlines wxDateTime m_lastRead; // date/time when this channel was last read }; struct RssReaderData { vector<Channel> m_channels; // store all channels wxTimeSpan m_refreshAfter; // timespan between two refreshes wxDateTime m_nextRefresh; // time of next refresh }; extern RssReaderData g_data;
the data adapter definition will look like this
BEGIN_ADAPTER(Headline)
PROP(m_title)
PROP(m_body)
PROP(m_published)
PROP(m_url)
END_ADAPTER()
BEGIN_ADAPTER(Channel)
PROP(m_webAddress)
PROP(m_title)
PROP(m_cacheExpires)
PROP(m_headlines)
PROP(m_lastRead)
END_ADAPTER()
BEGIN_ADAPTER(RssReaderData)
PROP(m_channels)
PROP(m_refreshAfter)
PROP(m_nextRefresh)
END_ADAPTER()
Let me point out several important things about the data adapter mechanism.
The data adapter definition above is the investment you have to make to use the Lit Window Library.
Copyright 2004, Hajo Kirchhoff, Lit Window Productions