Many thanks for the extensive commentary.
Though, our original post was in two parts, and clearly the second part had overcome the vast majority of issues that were raised in the first part. As such, and while we appreciate your time, we are not sure why you had taken time to comment on so many items, and only, in the first part, that had been clearly resolved in the second part, and prior to your response (e.g. all the non declared bits, just for example).
Regarding some of your queries:
1) The code is produced in CB with wxSmith as a wxWidget project, and amongst other things:
a) It creates the code automatically.
b) Much of that code can't be changed in any manageable way, since every time wxSmith has a go at it, it deletes/re-writes large chunks of code, so any edits we had made in those parts vanish. That is decidedly not how a pure wxWidgets programme seems to work, and clearly it is what contributed the some of the issues in part 1 of the original post, but which was overcome by the second part of the original post.
c) The structure of the code produced automatically by wxSmith seems to be different is subtle, and perhaps important ways, compared to what we have seen in our research of "pure" wx code. We are too new at this to be able to comment on the implications of that.
d) Thank you for the link (http://docs.wxwidgets.org/3.0.0/classwx_text_entry.html#a90f876b2dd83ba5c97ba0c193b386e9f), but it is of little help, as clearly we had been using that already (as in the code example in our original post). The issue is that wxSmith declares the widgets as Private, so there is no direct way to use/change them from outside of the core code.
Indeed, as the second part of our post demonstrates, wx doesn't like its bits being changed from the "outside" (such as from OnInit()), and that is why, when we found on the wxWidget forum (as stated in the post prior to your response), we used
void CB_SRList_wxFrame::SetValue_of_FileName_TextCtrl1(wxString t)
{
this->FileName_TextCtrl1->SetValue(t);
}
which (as must be clear from the post) we managed to make a "member" and we managed to "declare", once we figured out that wxSmith kept deleting our edits, and so we required a different approach, and which apparently worked (wrt to creating a member "manually", as we could not figure a way to do it from wxSmith directly, which seemed to would make this a CB question for that reason alone).
e) As such, and given this is essentially our first proper wxWidget/wsSmith project, we could not be sure how much of the difficulties were a CB issue or a wx issue, or possibly some combination of both.
... and thus it seemed reasonably to ask the question on the CB forum also, though clearly, the attention is on the SECOND part of the original post.
... as it happens we also asked the question on the wxWidget forum, as yet there has not been a response ... I hope they don't tell us that it's a CB matter, go back to CB.
Any way, for the record, and I am not sure how much of this you want (as in the past we've been told not to create long posts), but here is the code (the crucial line is in CB_SRList_wxApp.cpp, further down, and I have commented it ... if a line has something like //DrO in it, then it is one of ours), :
CB_SRList_wxMain.cpp:
/***************************************************************
* Name: CB_SRList_wxMain.cpp
* Purpose: Navigation Tool/Plug-In for Fortran procedures, etc
* Author: ()
* Created: 2016-04-15
* Copyright: ()
* License:
**************************************************************/
#include "wx_pch.h"
#include "CB_SRList_wxMain.h"
#include <wx/msgdlg.h>
//!#include <wx/event.h> //! DrO
#include <iostream> //! DrO
//(*InternalHeaders(CB_SRList_wxFrame)
#include <wx/intl.h>
#include <wx/string.h>
//*)
//helper functions
enum wxbuildinfoformat {
short_f, long_f };
wxString wxbuildinfo(wxbuildinfoformat format)
{
wxString wxbuild(wxVERSION_STRING);
if (format == long_f )
{
#if defined(__WXMSW__)
wxbuild << _T("-Windows");
#elif defined(__UNIX__)
wxbuild << _T("-Linux");
#endif
#if wxUSE_UNICODE
wxbuild << _T("-Unicode build");
#else
wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
}
return wxbuild;
}
//(*IdInit(CB_SRList_wxFrame)
const long CB_SRList_wxFrame::ID_STATICTEXT1 = wxNewId();
const long CB_SRList_wxFrame::ID_CHOICE1 = wxNewId();
const long CB_SRList_wxFrame::ID_GRID1 = wxNewId();
const long CB_SRList_wxFrame::ID_TEXTCTRL1 = wxNewId();
const long CB_SRList_wxFrame::ID_BUTTON1 = wxNewId();
const long CB_SRList_wxFrame::ID_PANEL1 = wxNewId();
const long CB_SRList_wxFrame::ID_MENUITEM1 = wxNewId();
const long CB_SRList_wxFrame::idMenuQuit = wxNewId();
const long CB_SRList_wxFrame::ID_MENUITEM2 = wxNewId();
const long CB_SRList_wxFrame::idMenuAbout = wxNewId();
const long CB_SRList_wxFrame::ID_STATUSBAR1 = wxNewId();
//*)
BEGIN_EVENT_TABLE(CB_SRList_wxFrame,wxFrame)
//(*EventTable(CB_SRList_wxFrame)
//*)
END_EVENT_TABLE()
CB_SRList_wxFrame::CB_SRList_wxFrame(wxWindow* parent,wxWindowID id)
{
void SetValue_of_FileName_TextCtrl1( wxString t); // DrO
//(*Initialize(CB_SRList_wxFrame)
wxMenuItem* MenuItem2;
wxMenuItem* MenuItem1;
wxMenu* Menu1;
wxMenuBar* MenuBar1;
wxMenu* Menu2;
Create(parent, id, _("Fortran Navigation"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
SetClientSize(wxSize(459,592));
Move(wxPoint(900,39));
Panel1 = new wxPanel(this, ID_PANEL1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("ID_PANEL1"));
StaticText1 = new wxStaticText(Panel1, ID_STATICTEXT1, _("Sort by: "), wxPoint(216,8), wxSize(72,24), wxALIGN_RIGHT, _T("ID_STATICTEXT1"));
Choice1 = new wxChoice(Panel1, ID_CHOICE1, wxPoint(296,8), wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("ID_CHOICE1"));
Grid1 = new wxGrid(Panel1, ID_GRID1, wxPoint(0,104), wxSize(447,436), 0, _T("ID_GRID1"));
Grid1->CreateGrid(30,5);
Grid1->EnableEditing(true);
Grid1->EnableGridLines(true);
Grid1->SetRowLabelSize(25);
Grid1->SetDefaultColSize(70, true);
Grid1->SetColLabelValue(0, _("Line"));
Grid1->SetColLabelValue(1, _("Type"));
Grid1->SetColLabelValue(2, _("Procedure"));
Grid1->SetColLabelValue(3, _("Kind"));
Grid1->SetColLabelValue(4, _("References"));
Grid1->SetDefaultCellFont( Grid1->GetFont() );
Grid1->SetDefaultCellTextColour( Grid1->GetForegroundColour() );
FileName_TextCtrl1 = new wxTextCtrl(Panel1, ID_TEXTCTRL1, _("FileName"), wxPoint(8,56), wxSize(432,21), 0, wxDefaultValidator, _T("ID_TEXTCTRL1"));
ReCalcButton = new wxButton(Panel1, ID_BUTTON1, _("ReCalc"), wxPoint(32,16), wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
MenuBar1 = new wxMenuBar();
Menu1 = new wxMenu();
MenuItem3 = new wxMenuItem(Menu1, ID_MENUITEM1, _("Open"), wxEmptyString, wxITEM_NORMAL);
Menu1->Append(MenuItem3);
Menu1->AppendSeparator();
MenuItem1 = new wxMenuItem(Menu1, idMenuQuit, _("Quit\tAlt-F4"), _("Quit the application"), wxITEM_NORMAL);
Menu1->Append(MenuItem1);
MenuBar1->Append(Menu1, _("&File"));
Menu3 = new wxMenu();
MenuItem4 = new wxMenuItem(Menu3, ID_MENUITEM2, _("ReCalc"), wxEmptyString, wxITEM_NORMAL);
Menu3->Append(MenuItem4);
MenuBar1->Append(Menu3, _("Action"));
Menu2 = new wxMenu();
MenuItem2 = new wxMenuItem(Menu2, idMenuAbout, _("About\tF1"), _("Show info about this application"), wxITEM_NORMAL);
Menu2->Append(MenuItem2);
MenuBar1->Append(Menu2, _("Help"));
SetMenuBar(MenuBar1);
StatusBar1 = new wxStatusBar(this, ID_STATUSBAR1, 0, _T("ID_STATUSBAR1"));
int __wxStatusBarWidths_1[1] = { -1 };
int __wxStatusBarStyles_1[1] = { wxSB_NORMAL };
StatusBar1->SetFieldsCount(1,__wxStatusBarWidths_1);
StatusBar1->SetStatusStyles(1,__wxStatusBarStyles_1);
SetStatusBar(StatusBar1);
Connect(idMenuQuit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&CB_SRList_wxFrame::OnQuit);
Connect(idMenuAbout,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&CB_SRList_wxFrame::OnAbout);
//*)
}
CB_SRList_wxFrame::~CB_SRList_wxFrame()
{
//(*Destroy(CB_SRList_wxFrame)
//*)
}
void CB_SRList_wxFrame::OnQuit(wxCommandEvent& event)
{
Close();
}
void CB_SRList_wxFrame::OnAbout(wxCommandEvent& event)
{
wxString msg = wxbuildinfo(long_f);
wxMessageBox(msg, _("Welcome to..."));
}
void CB_SRList_wxFrame::SetValue_of_FileName_TextCtrl1(wxString t) // DrO
{
this->FileName_TextCtrl1->SetValue(t);
}
CB_SRList_wxMain.h
/***************************************************************
* Name: CB_SRList_wxMain.h
* Purpose: Defines Application Frame
* Author: ()
* Created: 2016-04-15
* Copyright: ()
* License:
**************************************************************/
#ifndef CB_SRLIST_WXMAIN_H
#define CB_SRLIST_WXMAIN_H
//(*Headers(CB_SRList_wxFrame)
#include <wx/stattext.h>
#include <wx/menu.h>
#include <wx/textctrl.h>
#include <wx/panel.h>
#include <wx/grid.h>
#include <wx/choice.h>
#include <wx/button.h>
#include <wx/frame.h>
#include <wx/statusbr.h>
//*)
class CB_SRList_wxFrame: public wxFrame
{
public:
CB_SRList_wxFrame(wxWindow* parent,wxWindowID id = -1);
virtual ~CB_SRList_wxFrame();
void SetValue_of_FileName_TextCtrl1( wxString t); // DrO
private:
//(*Handlers(CB_SRList_wxFrame)
void OnQuit(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
void OnSetFocus(wxFocusEvent& event);
void OnPaint(wxPaintEvent& event);
void OnFileName_TextCtrl1TextEnter(wxCommandEvent& event);
//*)
//(*Identifiers(CB_SRList_wxFrame)
static const long ID_STATICTEXT1;
static const long ID_CHOICE1;
static const long ID_GRID1;
static const long ID_TEXTCTRL1;
static const long ID_BUTTON1;
static const long ID_PANEL1;
static const long ID_MENUITEM1;
static const long idMenuQuit;
static const long ID_MENUITEM2;
static const long idMenuAbout;
static const long ID_STATUSBAR1;
//*)
//(*Declarations(CB_SRList_wxFrame)
wxTextCtrl* FileName_TextCtrl1;
wxMenu* Menu3;
wxMenuItem* MenuItem4;
wxPanel* Panel1;
wxStaticText* StaticText1;
wxGrid* Grid1;
wxButton* ReCalcButton;
wxMenuItem* MenuItem3;
wxStatusBar* StatusBar1;
wxChoice* Choice1;
//*)
DECLARE_EVENT_TABLE()
};
#endif // CB_SRLIST_WXMAIN_H
CB_SRList_wxApp.cpp, I have put a comment at the line where we the difficulties in
/***************************************************************
* Name: CB_SRList_wxApp.cpp
* Purpose: Code for Application Class
* Author: ()
* Created: 2016-04-15
* Copyright: ()
* License:
**************************************************************/
#include "wx_pch.h"
#include "CB_SRList_wxApp.h"
#include <iostream> //! DrO
//(*AppHeaders
#include "CB_SRList_wxMain.h"
#include <wx/image.h>
//*)
IMPLEMENT_APP(CB_SRList_wxApp);
static wxString InitialFileName_wxs; // DrO
bool lInitialFileName_wxs; // DrO
bool CB_SRList_wxApp::OnInit()
{
//(*AppInitialize
bool wxsOK = true;
wxInitAllImageHandlers();
if ( wxsOK )
{
CB_SRList_wxFrame* Frame = new CB_SRList_wxFrame(0);
Frame->Show();
SetTopWindow(Frame);
}
//*)
int CmdArgC = wxApp::argc; //! DrO
wxChar ** CmdArgV = wxApp::argv; //! DrO
lInitialFileName_wxs = FALSE; // DrO
//! also create count, for latter "full Char(Len=n)" assignment
if( CmdArgC != 2) // DrO
{
return wxsOK;
};
int CmdArgIndex = 1; // DrO
int CharCount = 0; // DrO
for (int j = 0; CmdArgV[CmdArgIndex][j] != '\0'; ++j) // DrO
{
CharCount = CharCount + 1;
}
if( CharCount < 1 ) // DrO
{
return wxsOK;
};
char ArgVCharFull[CharCount+1] = {'\0'}; // DrO
//! CONVERT TO Char(Len=CharCount)
//! ------------------------------
//! Start at 1 to skip the program name, since
- just give prog name
//! -----------------------------------
for ( int j = 0; j<CharCount ; ++j) // DrO
{
ArgVCharFull[j] = CmdArgV[CmdArgIndex][j];
}
lInitialFileName_wxs = TRUE; // DrO
InitialFileName_wxs = wxString::FromUTF8(ArgVCharFull); // DrO
CB_SRList_wxFrame::SetValue_of_FileName_TextCtrl1( InitialFileName_wxs); // DrO// <<<<<<<<<<<<<< This is where the problems are
return wxsOK;
}
/***************************************************************
* Name: CB_SRList_wxApp.h
* Purpose: Defines Application Class
* Author: ()
* Created: 2016-04-15
* Copyright: ()
* License:
**************************************************************/
#ifndef CB_SRLIST_WXAPP_H
#define CB_SRLIST_WXAPP_H
#include <wx/app.h>
class CB_SRList_wxApp : public wxApp
{
public:
virtual bool OnInit();
};
#endif // CB_SRLIST_WXAPP_H
1) please use code tags if you post code (The # symbol in the new post editor: Press it and insert your code between the two tags)
2) Sry, i didn't read anywhere that you used wxSmith... It could be possible that i have forgotten it after reading all thix text. Young people have only a attention span of a few lines text...
3) Yes wxSmith removes code if you put it in the wrong places. This behaviour is normal for all code generators i have worked until now (mostly for embedded things). To avoid this simply don't put your code between the
//(* //*)
parts. wxSmith will ignore all code outside this tags and overwrite all things inside it
4) wxSmith does not generate different code. wxWdigets is a huge library, and c++ is a huge language. There are many ways to do things, but all roads lead to Rome...
Thank you for the code, now i am able to help you. But as i see this are all c++ errors and this post will probably get locked because c++ questions are not allowed here...
I will try to help you anyway and point you in some directions...
CB_SRList_wxFrame::CB_SRList_wxFrame(wxWindow* parent,wxWindowID id)
{
void SetValue_of_FileName_TextCtrl1( wxString t); // DrO
not valid c++ code
int CmdArgC = wxApp::argc; //! DrO
wxChar ** CmdArgV = wxApp::argv; //! DrO
i am not sure if this is the correct way to access these variables (it has something to do with base class and derived class)... you can use only argc and argv , without wxApp... http://docs.wxwidgets.org/trunk/overview_app.html
//! CONVERT TO Char(Len=CharCount)
//! ------------------------------
//! Start at 1 to skip the program name, since
just give prog name
//! -----------------------------------
Not a valid comment, wont compile
CB_SRList_wxFrame::SetValue_of_FileName_TextCtrl1( InitialFileName_wxs); // DrO// <<<<<<<<<<<<<< This is where the problems are
Of course this won't work... You access a member function of a class without instance. This works only for static member functions... This is a big misunderstanding of c++ so i recommend you to read a bit about c++.
But to defend your point, there is some "problem" with the code from wxSmith. You can't access the
CB_SRList_wxFrame* Frame = new CB_SRList_wxFrame(0);
variable within the wxApp code.
@devx: How is the right way to solve this issue? Normally there would be a "Is memeber" in the resource editor, to make the frame a member of the App class. but this option is missing...
i will try to create a workaround. Give me some time..
greetings
To solve your problem i would recommend to make the App object accessible in the wxFrame code. You can use
http://docs.wxwidgets.org/trunk/group__group__funcmacro__rtti.html#ga1523a2d553dea288d66cd35e8a0ffd5c
in the CB_SRList_wxApp.h file
This will look like this:
#ifndef CB_SRLIST_WXAPP_H
#define CB_SRLIST_WXAPP_H
#include <wx/app.h>
class CB_SRList_wxApp : public wxApp
{
private:
wxString m_cmd_line;
public:
virtual bool OnInit();
wxString GetCmdLine() {return m_cmd_line;};
};
DECLARE_APP(CB_SRList_wxApp);
#endif // CB_SRLIST_WXAPP_H
NOTE: If you are using wx2.8 you HAVE to use DECLARE_APP() and not wxDECLARE_APP()
in the application file:
bool CB_SRList_wxApp::OnInit()
{
// Do your command line parsing here and safe it in m_cmd_line, for example:
if(argc > 1)
m_cmd_line = wxString(argv[1]);
//(*AppInitialize
bool wxsOK = true;
wxInitAllImageHandlers();
if ( wxsOK )
{
CB_SRList_wxFrame* Frame = new CB_SRList_wxFrame(0);
Frame->Show();
SetTopWindow(Frame);
}
//*)
}
Now in your frame code:
#incldue "CB_SRList_wxApp.h"
CB_SRList_wxFrame::CB_SRList_wxFrame(wxWindow* parent,wxWindowID id)
{
void SetValue_of_FileName_TextCtrl1( wxString t); // DrO
//(*Initialize(CB_SRList_wxFrame)
// wxSmith bla bla
//*)
FileName_TextCtrl1->SetValue(wxGetApp().GetCmdLine());
}
i know it is not 100% what you want, but this works with wxSmith and encapsulates parsing of data and showing data nicely (parsing in the app class, but showing in the frame (Doc/View model ;) ) )
And no, this is not a wrong way, its the way of wxSmith. As i said before: all roads lead to Rome, but sometimes one road is longer than the other...
[EDIT:] NOTE: i don't have compiled explicitly this code, so there are possibly a view syntax errors... But the approach is tested and works...
Many thanks for the thoughtful and detailed response.
First, an apology: In providing the code in my previous response, I erred. Notably, our code is actually very much longer as it includes a vast number of comments and "experimental" sections. I had stripped all the non-essential bits for clarity ... but clearly I messed up, resulting with a couple of spurious bits in the posting.
... this caused you to be distracted, and to waste time ... my bad! FYI, I have had to put some considerable monies into our "swear jar" :-(
Also, some bits included demonstrate desperation. For example, we know enough about CPP that the line should be:
CB_SRList_wxFrame.SetValue_of_FileName_TextCtrl1( InitialFileName_wxs);
not
CB_SRList_wxFrame::SetValue_of_FileName_TextCtrl1( InitialFileName_wxs);
... but had erroneously left the "wrong experiment" in the submitted code ... again, my bad!
Finally, sorry about my ignorance regarding "code display" in the forum, I'll try in this post to see if I've sussed it.
Now for some GOOD news, we think.
We have obtained an alternate solution from wxWidgets, and which is massively simpler/more elegant, but which may have some risks in the context of CB's Wizard/scripts.
In particular, their solution is simply to change the original CB_SRList_wxApp.cpp code from:
//(*AppInitialize
bool wxsOK = true;
wxInitAllImageHandlers();
if ( wxsOK )
{
CB_SRList_wxFrame* Frame = new CB_SRList_wxFrame(0);
SetTopWindow(Frame);
}
//*)
to
//(*AppInitialize
bool wxsOK = true;
wxInitAllImageHandlers();
if ( wxsOK )
{
CB_SRList_wxFrame* Frame = new CB_SRList_wxFrame(0);
Frame->SetValue_of_FileName_TextCtrl1( InitialFileName_wxs ); //! DrO
Frame->Show(); //! DrO
SetTopWindow(Frame);
}
//*)
This works beautifully ... though, of course, it is between //("...//") markers, and so may lead to "CB/script risk". We don't really understand the "CB/script risk" since in some places (especially in the "main", CB is utterly narcissistic regarding these blocks, while ... so far ... this bit of code in "Apps" has not been "molested" by CB, even after several specific tests altering the gui, to see if we would loose the (extra) code. Presumably, there may be certain actions in CB that would then also "molest" the App code, but perhaps we have not as yet happened across them.
Of course, we have taken note of your statement that we should not place things inside those CB markers ... but given the elegance and simplicity of wxWidget's solution, we were wondering if you would still recommend against the type of approach here (we would like to avoid your solution on the grounds that we are neophytes and don't fully grasp all the bits yet, and it is much more expensive ... particularly for what is coming next).
Moreover, getting a bit of text to a gui text field is just the first and "easy" bit. Next, we need to link the App to a DLL, which returns the array that fills the grid on the gui. That requires a lot of code. So if there is risk of loosing a lot of code due to "CB/script risk", we would like to know more about it.
... if you feel the risk is too great, then we will take the plunge and the extra expense, but obviously would wish to avoid that if practical.
Please advise.
P.S. Thanks for the tip Re the FileName_TextCtrl1->SetValue(wxGetApp().GetCmdLine()); approach. In the event, as the filename must be passed to a DLL written in Fortran, which does the "actual calculation/processing", and which is via "bind(c)", our meagre skills only know enough to rely on a char variable that we know how to pass to the DLL. As such, with our limited c/wx knowledge, we are obliged to use the approach taken to retrieve the command line to char**, and convert to wxString only for the txtctrl, but really requiring the char** for the DLL.
ooops ... dreadfully sorry, and please disregard much of the earlier post.
In the event, we had already previously implemented a process that equates to your solution. Unfortunately, and I suppose due to the many permutations we were testing (and as had reported earlier), with an approach like yours, we had the cmd line arg evaluated in OnInit(), but it was evaluated after the " //("...//") " bits. Indeed, we had commented that we did not understand why that was not working as we expected the OnInit() to be completed in totality before it returned to "main" (e.g. we were cout'ing at every stage, and did not understand why the setvalue in main was null, given that the var was assigned in OnInit() ... or so we thought).
... it seems, if now we have it correct, that " //("...//") " block has set frame (Frame->Show) directive, and that is, it seems, the "end" of the OnInit() processing.
As soon as we moved the cmd arg eval prior to the " //("...//") " in the OnInit, and removed the setvalue from OnInit, the setvalue we had already in the "main" worked correctly.
Incidentally, on further exchange with the wxWidget chaps, they also suggested moving the setvalue from the OnInit to the "main" (frame constructor), as you have suggested (and we already had, but with the messed up arg assignment in OnInit())
... to make a long story short, we have actually implemented your solution already before your solution was posted, but had messed up on the order of operations in OnInit() ... as it did not occur to us that it would stop processing prior to the end of OnInit().
In any case ... SOLVED ... whoo hoo ... many thanks for all the effort.
I know it's been a year since this was discussed, but for those who, like I, did a search for 'wxsmith argc' this is where you'll probably end up.
I would have liked to a see a simple way to access the command line arguments from the Frame area of a wxSmith project but no luck from what I've read above - so what I did is.
Pass argc and argv to the Frame constructor - in the wxApp::OnInit() function
change new projectFrame(0);
to new projectFrame(0, 0, argc, argv);
add ' ,int c = 0, char** v = NULL ' to the constructor arguments in the projectMain.cpp and projectMain.h files.
add int argc and char** argv to the public area of the Frame class,
add argc = c; and argv = v; to the constructor method.
Now you can access all the command line arguments you want in any projectFrame member or event routine.
Hope it helps.