Page 1 of 1

Writing plugins -- Standard features for custom panels

Posted: Tue Aug 30, 2011 12:17 am
by GlenboLake
I'm writing a plugin that involves opening an editor window that is graphical instead of text-based. Because of this, it does not implement the IEditor interface. I suspect that this is the reason that several otherwise normal features aren't working.

Here are some problems I'm having:
  • When opening a file with one of these windows, the MainBook does not switch to it, even though m_mgr->SelectPage() returns true.
  • Saving is not enabled when an svPanel is selected
  • Undo/redo are not enabled when an svPanel is selected.
Here's my basic implementation.

svPanel.h:

Code: Select all

class svPanel : public wxScrolledWindow
{
private:
    svDocument *m_document; // created in svPanel constructor
    ...
public:
    svPanel(wxWindow* parent, wxFileName file);
    ...
};
svPanel.cpp:

Code: Select all

svPanel::svPanel(wxWindow* parent, wxFileName file) : wxScrolledWindow(parent)
{
    m_document = new svDocument(this, file);
    ...
}
swarmvis.cpp (main plugin file):

Code: Select all

// Open bool SwarmVis::DoOpenWithSwarmVis(wxFileName& file)
{
	if (file.GetExt() == wxT(SV_EXTENSION)) // SV_EXTENSION is a #define
	{
		svPanel *svp = new svPanel(m_mgr->GetTheApp()->GetTopWindow(), file);
		m_mgr->AddEditorPage(svp, file.GetFullName());
		m_mgr->SelectPage(svp); // This returns true, but doesn't actually select the page. Shouldn't AddEditorPage() select it anyway?

		return true;
	}
	return false;
}
Am I correct in thinking that I'm having these problems because I'm not implementing IEditor? If so, is there a way for me to fix any of these issues without implementing it?

Re: Writing plugins -- Standard features for custom panels

Posted: Tue Aug 30, 2011 12:25 am
by eranif
GlenboLake wrote:When opening a file with one of these windows, the MainBook does not switch to it, even though m_mgr->SelectPage() returns true.
I am not sure why this is happening, but it also happens for the database explorer plugin which opens an SQL editors instead of standard IEditor pages. I still need to investigate this, note that this is only happening under Linux (works fine under Windows / Mac)
GlenboLake wrote:Saving is not enabled when an svPanel is selected
You need to connect these events and handle it yourself, for example to enable copy/paste et al in the DB explorer plugin, I added this line:

Code: Select all

wxTheApp->Connect(wxID_COPY, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(SQLCommandPanel::OnEdit),   NULL, this);
To handle the SAVE command, you should handle the wxID_SAVE event (similar to what I wrote above)
Undo/redo are not enabled when an svPanel is selected.
See my previous comment.

For a good example, please have a look at:
DatabaseExplorer/SqlCommandPanel.cpp
EDIT:

Here is the list of event IDs you want to handle:

Code: Select all

XRCID("save_file")      => for handling 'save' command
XRCID("save_file_as") => save as
XRCID("save_all")       => save all files
wxID_COPY 
wxID_PASTE
wxID_CUT
wxID_UNDO
wxID_REDO
wxID_SELECTALL
Don't ask me why I used 'XRCID("save_file")' and not wxID_SAVE ;) I wrote it 3 or maybe 4 years ago :D

Eran

Re: Writing plugins -- Standard features for custom panels

Posted: Tue Aug 30, 2011 10:02 pm
by GlenboLake
Thanks! The connected event handlers for select all, undo/redo, and cut/copy/paste are working. However, the toolbar buttons and menu items for Save, Save As, and Reload File are still disabled. I tried putting this in the svPanel constructor in addition to the command event handler for save_file:

Code: Select all

wxTheApp->Connect(XRCID("save_file"), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(svPanel::OnUpdateUI));
The content of svPanel::OnUpdateUI is currently just some wxPuts commands, which never occur. I note that there is a wxUpdateUIEventHandler in SqlCommandPanel, but that it is never connected to anything. What am I still missing?

Re: Writing plugins -- Standard features for custom panels

Posted: Tue Aug 30, 2011 10:28 pm
by eranif

Code: Select all

wxTheApp->Connect(XRCID("save_file"), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(svPanel::OnUpdateUI));
This is incorrect. Try this instead:

Code: Select all

wxTheApp->Connect(XRCID("save_file"), wxUpdateUIEventHandler(svPanel::OnUpdateUI), NULL, this);
The 2 arguments: 'NULL' and 'this' are very important when connecting events from one control to another

Eran

Re: Writing plugins -- Standard features for custom panels

Posted: Wed Aug 31, 2011 12:00 am
by GlenboLake
I added the NULL and this to the Connect command (apparently I already had them on the disconnect and all the other Connects except that one...), but unfortunately that didn't fix the problem. It seems like the events themselves aren't even getting to the panel. For the sake of experimentation, I tried intercepting all update events to see what I was getting:

Code: Select all

svPanel::svPanel()
{
    ...
// Uncommenting the next three lines, with or without the wxEVT_UPDATE_UI argument, does not alter output in any way.
//  wxTheApp->Connect(XRCID("save_file"),    wxEVT_UPDATE_UI, wxUpdateUIEventHandler(svPanel::OnUpdateUI), NULL, this);
//  wxTheApp->Connect(XRCID("save_file_as"), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(svPanel::OnUpdateUI), NULL, this);
//  wxTheApp->Connect(XRCID("refresh_file"), wxEVT_UPDATE_UI, wxUpdateUIEventHandler(svPanel::OnUpdateUI), NULL, this);
    wxTheApp->Connect(wxEVT_UPDATE_UI, wxUpdateUIEventHandler(svPanel::OnUpdateUI), NULL, this);
}

void svPanel::OnUpdateUI(wxUpdateUIEvent& event)
{
    if (event.GetId() == XRCID("save_file"))
        wxPuts(wxT("save_file"));
    else if (event.GetId() == XRCID("save_file_as"))
        wxPuts(wxT("save_file_as"));
    else if (event.GetId() == XRCID("reload_file"))
        wxPuts(wxT("reload_file"));
    else
    {
        if (wxDynamicCast(event.GetEventObject(), svPanel)==NULL)
        {
            event.Skip();
            return;
        }
        wxPrintf(wxT("svPanel::OnUpdateUI (%d)\n"), event.GetId());
    }
}
The output, upon opening one of my panels, is this:

Code: Select all

svPanel::OnUpdateUI (-539)
svPanel::OnUpdateUI (-343)
svPanel::OnUpdateUI (-480)
svPanel::OnUpdateUI (-539)
svPanel::OnUpdateUI (-343)
svPanel::OnUpdateUI (-480)
svPanel::OnUpdateUI (-539)
svPanel::OnUpdateUI (-343)
svPanel::OnUpdateUI (-480)
It's always three numbers repeating, but they're not always the same (something from XRCID, I assume). More importantly, the panel isn't getting any save_file, save_file_as, or reload_file update events.

Re: Writing plugins -- Standard features for custom panels

Posted: Wed Aug 31, 2011 1:03 am
by eranif
Hi,

Code: Select all

wxTheApp->Connect(wxID_COPY,    wxEVT_UPDATE_UI, wxUpdateUIEventHandler(svPanel::OnUpdateUI), NULL, this);
Is the correct way to write it (with wxVET_UPDATE_UI)

I digged into the code a bit and it seems that you won't be able to handle these events since those events (unlike the wxID_COPY/PAST/CUT/UNDO/REDO/SELECTALL) will never be propogated by codelite if the active editor is not of type IEditor

codelite's main frame handles them like this:

Code: Select all

void clMainFrame::OnFileExistUpdateUI(wxUpdateUIEvent &event)
{
	CHECK_SHUTDOWN();

	LEditor* editor = GetMainBook()->GetActiveEditor();
	if ( !editor ) {
		event.Enable(false);
	} else {
		event.Enable(true);
	}
}
So you will need to create your own toolbar which have the 'save' / 'save as' et al buttons and don't rely on the common buttons for this

Eran