lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [5230] Prepare to embed InputSequenceEntry in wxDVC (VS)


From: Greg Chicares
Subject: [lmi-commits] [5230] Prepare to embed InputSequenceEntry in wxDVC (VS)
Date: Sun, 07 Aug 2011 12:02:42 +0000

Revision: 5230
          http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=5230
Author:   chicares
Date:     2011-08-07 12:02:42 +0000 (Sun, 07 Aug 2011)
Log Message:
-----------
Prepare to embed InputSequenceEntry in wxDVC (VS)

Modified Paths:
--------------
    lmi/trunk/input_sequence_entry.cpp
    lmi/trunk/input_sequence_entry.hpp

Modified: lmi/trunk/input_sequence_entry.cpp
===================================================================
--- lmi/trunk/input_sequence_entry.cpp  2011-08-05 00:28:32 UTC (rev 5229)
+++ lmi/trunk/input_sequence_entry.cpp  2011-08-07 12:02:42 UTC (rev 5230)
@@ -48,7 +48,7 @@
 #include <wx/textctrl.h>
 #include <wx/valtext.h>
 
-#include <algorithm>              // std::copy(), std::find()
+#include <algorithm>              // std::copy()
 #include <iterator>               // std::back_inserter
 #include <map>
 #include <vector>
@@ -191,9 +191,16 @@
         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);
@@ -289,6 +296,8 @@
     // 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)
@@ -1129,9 +1138,95 @@
 
     update_diagnostics();
 }
+
+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)
 {
 }
 
@@ -1140,6 +1235,7 @@
     ,wxWindowID         id
     ,wxString const&    name
     )
+    :input_(0)
 {
     Create(parent, id, name);
 }
@@ -1161,16 +1257,8 @@
 
     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));
@@ -1187,21 +1275,64 @@
     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 =
@@ -1216,11 +1347,11 @@
 
     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
         );
@@ -1238,10 +1369,8 @@
 
     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)

Modified: lmi/trunk/input_sequence_entry.hpp
===================================================================
--- lmi/trunk/input_sequence_entry.hpp  2011-08-05 00:28:32 UTC (rev 5229)
+++ lmi/trunk/input_sequence_entry.hpp  2011-08-07 12:02:42 UTC (rev 5230)
@@ -31,6 +31,9 @@
 #include <wx/panel.h>
 #include <wx/xrc/xmlres.h>
 
+#include <string>
+
+class Input;
 class WXDLLIMPEXP_FWD_CORE wxButton;
 class WXDLLIMPEXP_FWD_CORE wxTextCtrl;
 
@@ -42,6 +45,12 @@
     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 +58,9 @@
   private:
     void UponOpenEditor(wxCommandEvent&);
 
+    Input const* input_;
+    std::string field_name_;
+
     wxTextCtrl* text_;
     wxButton*   button_;
     wxString    title_;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]