[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] [PATCH 1/2] Make InputSequenceEntry friendly to embedding in w
From: |
Vaclav Slavik |
Subject: |
Re: [lmi] [PATCH 1/2] Make InputSequenceEntry friendly to embedding in wxDVC. |
Date: |
Tue, 05 Jul 2011 15:11:23 +0200 |
User-agent: |
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.15) Gecko/20110303 Thunderbird/3.1.9 |
Hi,
On 2011-06-29 18:34, Vaclav Slavik wrote:
> this patch makes the InputSequenceEntry composite control behave more like a
> "normal" control with regard to focus changes and input events.
> wxDataViewCtrl wants
> to intercept these events so that it knows when to close an inline editor
> control
> and this change makes it handle InputSequenceEntry correctly.
Please replace this with an updated version:
commit 2806dea06f88c781fcf304beb6e22e6f1b752074
Author: Vaclav Slavik <address@hidden>
Date: Fri Apr 29 10:26:53 2011 +0200
Make InputSequenceEntry friendly to embedding in wxDVC.
diff --git a/input_sequence_entry.cpp b/input_sequence_entry.cpp
--- a/input_sequence_entry.cpp
+++ b/input_sequence_entry.cpp
@@ -190,9 +190,16 @@ class InputSequenceEditor
default_keyword_ = default_keyword;
}
+ void associate_text_ctrl(wxTextCtrl* t)
+ {
+ associated_text_ctrl_ = t;
+ }
+
void sequence(InputSequence const& s);
std::string sequence_string();
+ virtual void EndModal(int retCode);
+
private:
void add_row();
void insert_row(int row);
@@ -281,6 +288,8 @@ class InputSequenceEditor
// scalar absolute values for end durations; this is used to recompute
// duration number for certain duration modes
std::vector<int> duration_scalars_;
+
+ wxTextCtrl *associated_text_ctrl_;
};
InputSequenceEditor::InputSequenceEditor(wxWindow* parent, wxString const&
title, Input const& input)
@@ -1002,9 +1011,96 @@ void InputSequenceEditor::UponAddRow(wxCommandEvent&
event)
duration_num_field(new_row).SetFocus();
}
+
+void InputSequenceEditor::EndModal(int retCode)
+{
+ // We need to set the value as soon as possible -- when used in
wxDataViewCtrl, the value
+ // is read from editor control as soon as focus changes, which is before
ShowModal() returns.
+ if(associated_text_ctrl_ && retCode == wxID_OK)
+ associated_text_ctrl_->SetValue(sequence_string());
+
+ wxDialog::EndModal(retCode);
+}
+
+class InputSequenceTextCtrl
+ :public wxTextCtrl
+{
+ public:
+ InputSequenceTextCtrl(wxWindow* parent, wxWindowID id);
+
+ private:
+ void UponKillFocus(wxFocusEvent& event);
+ void UponChar(wxKeyEvent& event);
+};
+
+InputSequenceTextCtrl::InputSequenceTextCtrl(wxWindow* parent, wxWindowID id)
+ :wxTextCtrl(parent, id)
+{
+ ::Connect
+ (this
+ ,wxEVT_KILL_FOCUS
+ ,&InputSequenceTextCtrl::UponKillFocus
+ );
+ ::Connect
+ (this
+ ,wxEVT_CHAR
+ ,&InputSequenceTextCtrl::UponChar
+ );
+}
+
+void InputSequenceTextCtrl::UponKillFocus(wxFocusEvent& event)
+{
+ if(0 == event.GetWindow() || event.GetWindow()->GetParent() != GetParent())
+ GetParent()->ProcessWindowEvent(event);
+ event.Skip();
+}
+
+void InputSequenceTextCtrl::UponChar(wxKeyEvent& event)
+{
+ if(!GetParent()->ProcessWindowEvent(event))
+ event.Skip();
+}
+
+
+class InputSequenceButton
+ :public wxButton
+{
+ public:
+ InputSequenceButton(wxWindow* parent, wxWindowID id);
+
+ private:
+ void UponKillFocus(wxFocusEvent& event);
+};
+
+InputSequenceButton::InputSequenceButton(wxWindow* parent, wxWindowID id)
+ :wxButton(parent, id, "...", wxDefaultPosition, wxDefaultSize,
wxBU_EXACTFIT)
+{
+ ::Connect
+ (this
+ ,wxEVT_KILL_FOCUS
+ ,&InputSequenceButton::UponKillFocus
+ );
+
+ SetToolTip("Open sequence editor");
+}
+
+void InputSequenceButton::UponKillFocus(wxFocusEvent& event)
+{
+ // Don't notify the parent (and thus wxDataViewCtrl) of focus change if
its within this
+ // InputSequenceEntry composite control or a InputSequenceEditor window
opened from it.
+ if(0 == event.GetWindow() ||
+ (event.GetWindow()->GetParent() != GetParent() &&
+ wxGetTopLevelParent(event.GetWindow())->GetParent() != this))
+ {
+ GetParent()->ProcessWindowEvent(event);
+ }
+ event.Skip();
+}
+
} // Unnamed namespace.
InputSequenceEntry::InputSequenceEntry()
+ :input_(0)
{
}
@@ -1013,6 +1109,7 @@ InputSequenceEntry::InputSequenceEntry
,wxWindowID id
,wxString const& name
)
+ :input_(0)
{
Create(parent, id, name);
}
@@ -1034,16 +1131,8 @@ bool InputSequenceEntry::Create
wxSizer* sizer = new(wx) wxBoxSizer(wxHORIZONTAL);
- text_ = new(wx) wxTextCtrl(this, wxID_ANY);
- button_ = new(wx) wxButton
- (this
- ,wxID_ANY
- ,"..."
- ,wxDefaultPosition
- ,wxDefaultSize
- ,wxBU_EXACTFIT
- );
- button_->SetToolTip("Open sequence editor");
+ text_ = new(wx) InputSequenceTextCtrl(this, wxID_ANY);
+ button_ = new(wx) InputSequenceButton(this, wxID_ANY);
sizer->Add(text_, wxSizerFlags(1).Expand());
sizer->Add(button_, wxSizerFlags().Expand().Border(wxLEFT, 1));
@@ -1060,21 +1149,64 @@ bool InputSequenceEntry::Create
return true;
}
+void InputSequenceEntry::input(Input const& input)
+{
+ input_ = &input;
+}
+
+Input const& InputSequenceEntry::input() const
+{
+ if(input_)
+ {
+ return *input_;
+ }
+ else
+ {
+ // MvcController's design uses editor controls that only have local
+ // knowledge of the value they directly edit. This isn't an
+ // unreasonable assumption and e.g. wxDataViewCtrl does the same.
+ // Unfortunately, it doesn't fit InputSequenceEditor, which needs
+ // additional information about the Input instance the sequence is used
+ // in. Hence this hack -- it gets the Input from the parent
+ // MvcController if used inside one.
+ MvcController const* tlw = dynamic_cast<MvcController
const*>(wxGetTopLevelParent(const_cast<InputSequenceEntry*>(this)));
+ LMI_ASSERT(tlw);
+ Input const* input = dynamic_cast<Input const*>(&tlw->Model());
+ LMI_ASSERT(input);
+
+ return *input;
+ }
+}
+
+void InputSequenceEntry::field_name(std::string const& name)
+{
+ field_name_ = name;
+}
+
+std::string InputSequenceEntry::field_name() const
+{
+ if(!field_name_.empty())
+ {
+ return field_name_;
+ }
+ else
+ {
+ // see the explanation in input()
+ return std::string(GetName().c_str());
+ }
+}
+
void InputSequenceEntry::UponOpenEditor(wxCommandEvent&)
{
- MvcController const* tlw = dynamic_cast<MvcController
const*>(wxGetTopLevelParent(this));
- LMI_ASSERT(tlw);
- Input const* input = dynamic_cast<Input const*>(&tlw->Model());
- LMI_ASSERT(input);
+ Input const& in = input();
// Center the window on the [...] button for best locality -- it will be
// close to user's point of attention and the mouse cursor.
- InputSequenceEditor editor(button_, title_, *input);
+ InputSequenceEditor editor(button_, title_, in);
editor.CentreOnParent();
std::string sequence_string = std::string(text_->GetValue());
- std::string const name(GetName().c_str());
- datum_sequence const& ds =
*member_cast<datum_sequence>(input->operator[](name));
+ datum_sequence const& ds = *member_cast<datum_sequence>(in[field_name()]);
std::map<std::string,std::string> const kwmap = ds.allowed_keywords();
std::vector<std::string> const keywords =
@@ -1089,11 +1221,11 @@ void InputSequenceEntry::UponOpenEditor(wxCommandEvent&)
InputSequence sequence
(sequence_string
- ,input->years_to_maturity()
- ,input->issue_age ()
- ,input->retirement_age ()
- ,input->inforce_year ()
- ,input->effective_year ()
+ ,in.years_to_maturity()
+ ,in.issue_age ()
+ ,in.retirement_age ()
+ ,in.inforce_year ()
+ ,in.effective_year ()
,0
,keywords
);
@@ -1111,10 +1243,8 @@ void InputSequenceEntry::UponOpenEditor(wxCommandEvent&)
editor.sequence(sequence);
- if(wxID_OK == editor.ShowModal())
- {
- text_->SetValue(editor.sequence_string());
- }
+ editor.associate_text_ctrl(text_);
+ editor.ShowModal();
}
IMPLEMENT_DYNAMIC_CLASS(InputSequenceEntryXmlHandler, wxXmlResourceHandler)
diff --git a/input_sequence_entry.hpp b/input_sequence_entry.hpp
index c2f39cd..890619b 100644
--- a/input_sequence_entry.hpp
+++ b/input_sequence_entry.hpp
@@ -42,6 +42,12 @@ class InputSequenceEntry
InputSequenceEntry(wxWindow* parent, wxWindowID id, wxString const& name);
bool Create(wxWindow* parent, wxWindowID id, wxString const& name);
+ void input(Input const& input);
+ Input const& input() const;
+
+ void field_name(std::string const& name);
+ std::string field_name() const;
+
wxTextCtrl& text_ctrl() {return *text_;}
void set_popup_title(wxString const& title) {title_ = title;}
@@ -49,6 +55,9 @@ class InputSequenceEntry
private:
void UponOpenEditor(wxCommandEvent&);
+ Input const* input_;
+ std::string field_name_;
+
wxTextCtrl* text_;
wxButton* button_;
wxString title_;
- Re: [lmi] [PATCH 1/2] Make InputSequenceEntry friendly to embedding in wxDVC.,
Vaclav Slavik <=