Code::Blocks Forums

Developer forums (C::B DEVELOPMENT STRICTLY!) => Development => Topic started by: frithjofh on May 31, 2012, 01:21:22 pm

Title: cbEvents
Post by: frithjofh on May 31, 2012, 01:21:22 pm
Hi everyone,

I know there are already a lot of topics regarding this, but I think it would really be time to address this theme.

I think the devs should reorganize some events and when they are posted. Especially the EVT_PROJECT_CLOSE and EVT_PROJECT_OPEN. Right now these events are not very clear in my humble opinion, and their behavior still less.

The  EVT_PROJECT_CLOSE gets sent  on closing a project. After that all editors of this project are closed and send their EVT_EDITOR_CLOSE event. When this happens, it seems, that the project is gone already, or what? But there is no EVT_PROJECT_CLOSED event. So a project does cease to exist before its editors?? Pardon me, I am no programmer with a degree or anything, but this just sounds like crap. After project close then, I cannot get the projects name for instance, using an editor to get at it? But I still have an editor for a file in a closed project?

The same applies to EVT_PROJECT_OPEN. First it opens all editors of the "project" (but there really still is no project), so I can't get to any project related information using one of these editors. Then, when all its editors are open, then the project begins to exist? After its own content? Very strange, and by the way, making work difficult without need for anyone developing something in or for c::b.

Well, just my little opinion, but searching the forum, I'm not the only one it seems.

So what can I do? Add the two missing events EVT_PROJECT_CLOSED and EVT_PROJECT_OPENED? I'm not sure if I'm able do change the way c::b opens and closes projects (for my pity faculties). I am also aware that making changes there can and will break a lot of stuff, topmost the plugins. But I do think this should be changed, it is really a messy heritage to carry around.

Regards

frithjofh
Title: Re: cbEvents
Post by: MortenMacFly on May 31, 2012, 01:48:05 pm
Well the reason here is the same as for the others:
These events are there to intercept them, so there is no point in sending them when its too late.
On the other hand, the CLOSED/OPENED events where simply not needed until now, so they don't exists. I also don't know why you would want to know, when a project has been destroyed, because you could no longer access any information of it, even a pointer to the project would be NULL. So you would have an event "PROJECT_CLOSED" with a NULL pointer attached, thus, all you get to know is "some project has gone". What would be the use-case here?

As for the editors: As long as the SDK methods to obtain an editors' projects do not return NULL, the project is present, of course. You can safely rely on that.
Title: Re: cbEvents
Post by: frithjofh on May 31, 2012, 05:13:44 pm
Well, I did expect that answer  ;)

But I'm still not convinced totally. If I look over the code in c::b that has to deal with this issue (and associated) I see that it really shines on checking if editor is cbEditor, if it is buildt-in, if it is VisibleToTree(), if it is NULL, and so on and so forth. I enjoy reading code, but this all seems like those examples in books where they tell you what not to do. But picking on you guys for all the work done is a bit unfair ... I know that.

So if your alright with the way these things work, I'll just go along. Maybe I am a little bit annoyed by the fact that the project is not given to the manager directly and be done with it, but that its editors are given to the manager one by one, and then the project is declared open. And the same the other way around when a project is closed. But surly there are reasons for the way things are done, and if the reason were that it was done so at some remote beginning and that is just why, it is fine with me too.

But look, I really think there is much friction introduced by these kind of things, friction in the work progress. I'm sure that all the guys which have hacked on c::b for years just have these things internalized and just don't notice anymore. But for the others out there some design decisions seem rather hard to understand. Every project has its style I guess and one has to adapt.

In the end: I'm not really criticizing anyone. In the end I just have to admit that c::b is fun and a great tool to work with, so just don't mind too much about my complaint.

By the way: is there some, one, place where all those events are really explained, as to when they fire, and what was the idea behind their implementation, and so ...

And for that thing which is the idea behind the EditorBase, and the cbEditor, and what more implications lurk there?

Regards and thank you for the answer

frithjof
Title: Re: cbEvents
Post by: oBFusCATed on May 31, 2012, 06:05:26 pm
Too much words you're using and the noise/signal ratio is too big.
Can you provide code snippet or snippets, where the current events fail to serve their purpose?
This way it will be a bit clear what are the problems or you can be given exact solutions or guides.

EditorBase is some base editor, which must be derived by the real editors. See the wxSmith plugin if you want to see a working editor implementation.
cbEditor is the text editor, also know as the buildin editor.
Title: Re: cbEvents
Post by: frithjofh on May 31, 2012, 08:13:17 pm
OK:

I'm making a plugin right now. It adds all open and opened files to a list. In the list the file name and the project name of the file are displayed.

When the plugin is enabled and I open a project, the entries in the list show up fine with their file name correctly set, but with their project name empty. I believe this is due to the project not existing at the moment the files are opened. When a file gets opened, the plugin queries for its name and the name of the project. This is triggered by the EVT_EDITOR_OPEN. As the project does not exist at this time, the project name is retrieved as empty. Then the project comes to life, it has a name, and I would be forced to scan the open files to set the project name accordingly.

When the plugin is disabled, and I have a project open, and then enable the plugin the project name is displayed correctly.

I am able to make this work in my plugin, it just does not feel very straight forward.

Also having to query each time for this :
Code
    if ( !an_editor || !an_editor->VisibleToTree() || !an_editor->IsBuiltinEditor() )
        return;
is quite ugly. I still accept the !an_editor part to check against NULL, but the other two are rather awkward, don't you think?

Regards

frithjofh
Title: Re: cbEvents
Post by: oBFusCATed on May 31, 2012, 11:01:51 pm
Have you look at how openfilelist plugin is done?

Also having to query each time for this :
Code
    if ( !an_editor || !an_editor->VisibleToTree() || !an_editor->IsBuiltinEditor() )
        return;
is quite ugly. I still accept the !an_editor part to check against NULL, but the other two are rather awkward, don't you think?
Why do you care for the VisibleToTree? I don't think it is needed...
The second check is if you want to show only text editors. If you want to show all editors you don't need this check, too.
I see no problem here. Keep in mind that there can be non-text kind of editors, like the GUI editors in the wxSmith plugin.
So, I doubt you know a way to make the IsBuiltinEditor check disappear, if you know I'm all ears. :)

p.s. please try to keep your code/text ratio larger (e.g. post more code and less text) :)
p.p.s. can you post the whole snippet that is having the missing project problem or the whole plugin's source?
Title: Re: cbEvents
Post by: frithjofh on June 01, 2012, 12:26:31 pm
Yes, I looked how it is done in the openfilelist plugin. I copied from there. My code:
Code
Entry::Entry(const EditorBase* editor) :
    m_pEditor(editor),          // no ownership
    m_pAttribute(nullptr),      // no ownership
    m_AgeIndex(-1),
    m_ImageIndex(0),                                           // ascii
    m_ShortName(m_pEditor->GetShortName()),
    m_FileName(m_pEditor->GetFilename()),
    m_ProjectName(wxEmptyString)
{
    if (m_pEditor->GetModified())       m_ImageIndex =  1;     // modified
    else if (m_pEditor->IsReadOnly())   m_ImageIndex =  2;     // read only

    ProjectFile* prjf((static_cast<const cbEditor*>(m_pEditor))->GetProjectFile());
    if(prjf)
    {
        cbProject* prj = prjf->GetParentProject();
        if(prj)
            m_ProjectName = prj->GetTitle();
    }
}
Obviously this class is a sort of wrapper for the files information, some retrieved from c::b, other set by my plugin. Resulting behavior as to the moment is: when the plugin is active and I open a project, the projects name does not get caught. If I have the project already open and then enable the plugin the project name does get caught. Construction of Entry is triggered by EVT_EDITOR_OPEN.

I could listen for the EVT_PROJECT_OPEN and then set the project name to the Entries accordingly, that will work, but that seems very clumsy. This is first problem.

Second issue: no, I do not know right now how to avoid check IsBuiltinEditor(), but I think having to do this check raises the question if inheritance is used right here.

Third issue: I care for VisibleToTree() here (as does the openfilelist plugin) because of the presence of the start page.

regards and thank you for the attention  :)
Title: Re: cbEvents
Post by: oBFusCATed on June 01, 2012, 01:11:37 pm
1. Are you sure "m_ProjectName = prj->GetTitle();" is executed?
2. What are you using m_ProjectName(wxEmptyString), the default c-tor does a perfect job
3. Why have you posted the code out of it's context
4. Probably inheritance was not used correctly here, but I doubt it could be changed easily. You can volunteer to try to remedy the situation :)
Title: Re: cbEvents
Post by: frithjofh on June 01, 2012, 01:43:25 pm
1. Yes. just ran in debugger and yes, constructor is entered and GetTitle() is executed.
2. I know. I use wxEmptyString here as a more visible reminder to myself.
3. It is not out of context in the sense, that this is the only place in the plugin, where the m_ProjectName member is set.
4. I do. Don't know when. Probably somebody else will be quicker on it.  :-\
Title: Re: cbEvents
Post by: frithjofh on June 01, 2012, 01:56:44 pm
Thinking about it: I changed the code a bit to see what happens:

1. in the initializer list of Entry I set m_ProjectName to "wtf" (just some example string)
2. inside the constructor I set m_ProjectName to "some other strg"

result:
case a: plugin enabled and then loading project: just "wtf" shows up as project name. that is in this case there is no project yet and so it stays with the initialization from initializer list
case b: first load project, then enable plugin: "some other strg" shows up as project name. in this case the plugin gets the already open editors from the manager, so there the project exists.
Title: Re: cbEvents
Post by: oBFusCATed on June 01, 2012, 01:58:55 pm
3. It is not out of context in the sense, that this is the only place in the plugin, where the m_ProjectName member is set.
You see the context, but we do not, thus it is out of the context :)
Title: Re: cbEvents
Post by: frithjofh on June 01, 2012, 02:04:45 pm
 ;D well okay. Your more stubborn than I am. I admit it is out of context ;). Do you really need more code, then I'll send? Really the constructor is called without detours by functions taking only a cbEvent, so there is nothing there.

But anyway: what can you tell me about the issue? Any idea?
Title: Re: cbEvents
Post by: oBFusCATed on June 01, 2012, 02:21:13 pm
Looking at it looks normal, but I guess, the availability of the data depends on the events calling the code you've shown.
I doubt there is some secret part, so showing the full code is not a big problem for you. This will allow people to try it. Or to pin-point something.
I'm not proficient with the C::B events and when I have problems with them I use the debugger to see where is the place where they are sent
and what is the code/state around that place.

btw: Is this a part of the real code "ProjectFile* prjf((static_cast<const cbEditor*>(m_pEditor))->GetProjectFile());" (note the missing =)?
Title: Re: cbEvents
Post by: frithjofh on June 01, 2012, 02:31:19 pm
yes, this is the real code:
Code
ProjectFile* prjf((static_cast<const cbEditor*>(m_pEditor))->GetProjectFile());
I do this a lot (shame on me for readability), but its not an assignment, but a construction, actually.

I think the issue is that on opening a project cbEVT_EDITOR_OPEN events are sent before the project actually exists. I will use the trailing cbEVT_PROJECT_OPEN to set the name of those editors afterward. This is a bit ugly, and not very intuitive, but I recon nobody (not me for sure) will change the way these events are fired.

For the moment I stay put. When the plugin is in any presentable shape, I'll post it. Its function will combine the OpenFileList and the ClosedFileList in one and add a visual history of files. The most of it is working already, but I not satisfied yet.

Thanks for all the attention and greetings from Asturias  :)
Title: Re: cbEvents
Post by: oBFusCATed on June 01, 2012, 02:36:38 pm
Then can you show the callstack for the non-working case a?
Title: Re: cbEvents
Post by: frithjofh on June 01, 2012, 04:24:18 pm
I'll try my best. The call stack I used only inside the debugger till now.

On other thing: in the code I posted the constructor takes a EditorBase pointer as argument. For the case a this pointer I get directly from the event object. Could it be for some reason, that this event object carries a pointer to EditorBase which is not completely initialized? For the case b if retrieve the pointers from the editormanager, these are complete.
Title: Re: cbEvents
Post by: oBFusCATed on June 01, 2012, 04:46:26 pm
What is the event for caseA?
Title: Re: cbEvents
Post by: frithjofh on June 01, 2012, 04:49:26 pm
cbEVT_EDITOR_OPEN. case b works without event: the plugin on attaching retrieves from editormanager whatever editors are open.

just ran a test: after receiving the event, I don't use the editor from the event object, but retrieve the editor by filename (from the editor in the event object) directly from editormanager. same result.

Opening some arbitrary file also does not show the project name. as till now I think the project name is set on the editors only after cbEVT_PROJECT_OPEN.
Title: Re: cbEvents
Post by: frithjofh on June 01, 2012, 05:18:50 pm
Made another test. Tried to retrieve the project name from an Entry which was constructed from an editor retrieved from an cbEVT_EDITOR_CLOSE event object. This does work as expected.

So: cbEVT_EDITOR_CLOSE and cbEVT_EDITOR_OPEN are not symmetric.
Title: Re: cbEvents
Post by: oBFusCATed on June 01, 2012, 05:45:20 pm
Looking at the code:
1. In EditorManager::New there is not mentioning of a project, probably it has not created here or it is just an omission. No time to dig if the project can be made available in this method.
2. There are some project events like cbEVT_PROJECT_BEGIN_ADD_FILES, cbEVT_PROJECT_FILE_ADDED have you tried to capture them? When do they happen? Before or after the EDITOR_OPEN event?
Title: Re: cbEvents
Post by: frithjofh on June 01, 2012, 05:53:12 pm
I thought these events were meant only if files were added or removed from a project, not when a file belonging to a project was opened??

For my issue: even if the plugin is attached and a project is open already, every file I then open (a file belonging to a project) does not show its projects name. I think the problem really is what you found: the cbEVT_EDITOR_OPEN does not contemplate the project the file belongs to.
Title: Re: cbEvents
Post by: MortenMacFly on June 01, 2012, 06:13:29 pm
In the end: I'm not really criticizing anyone. In the end I just have to admit that c::b is fun and a great tool to work with, so just don't mind too much about my complaint.
Don't worry, we listen and we like discussions. Again, just try to implement it in a way it fits your needs by introducing additional events to the core and provide us with patches. In the end if your plugin works fine and requires them we have no other choice than to apply those, aren't we?! ;-)

By the way: is there some, one, place where all those events are really explained, as to when they fire, and what was the idea behind their implementation, and so ...
I'm afraid only in the heads of us for the moment. I recall a WiKi article on that topic but it seems gone, or at least a quick search didn't reveal it for me.

And for that thing which is the idea behind the EditorBase, and the cbEditor, and what more implications lurk there?
Sure: Have a look at wxSmith and ByoGames, also HexEditor and the NassiShneiderman plugin for example: They all use not a classical cbEditor which means editing text (source code), but an EditorBase. EditorBase it intended to be the minimal set of function relevant to all basically "notebooks" C::b will handle. However, "specialisations" for source code, which is the #1 use case are done in cbEditor. You can also see EditorBase as an interface class, if you want to.

(Now I'll continue to read the other million posts in this thread... ;D).
Title: Re: cbEvents
Post by: MortenMacFly on June 01, 2012, 06:24:11 pm
Looking at the code:
1. In EditorManager::New there is not mentioning of a project, probably it has not created here or it is just an omission. No time to dig if the project can be made available in this method.
Sure it is not, because an editor does not require a project. However, the IDE will ask in the case you create a new file (editor) if you want to attach this to a project. In that case, you'll see it in the project changed event (or similarly called). In fact, if an editor is created there should not be a ned fr a project to keep it decoupled. Again, think about specific editors like ByoGames... there will never be a project nor should be.
Title: Re: cbEvents
Post by: MortenMacFly on June 01, 2012, 06:25:03 pm
For my issue: even if the plugin is attached and a project is open already, every file I then open (a file belonging to a project) does not show its projects name. I think the problem really is what you found: the cbEVT_EDITOR_OPEN does not contemplate the project the file belongs to.
For all these test cases, can you do me a favour and disable the CC plugin to check if that changes things?
Title: Re: cbEvents
Post by: frithjofh on June 01, 2012, 06:37:00 pm
disabling the code completion plugin does not change the behavior.
Title: Re: cbEvents
Post by: frithjofh on June 02, 2012, 06:22:20 pm
Just a thought: how about having more different events to signal that an editor opens? Every specific editor inheriting from EditorBase could have his specific event to be fired when opening. This would concentrate all the decision making at the point where these events are produced. All the plugins could then only listen to those specific events they are interested in. If other new editor types are introduced, this would not affect any code already existing, every new editor type would bring along its own events.
Title: Re: cbEvents
Post by: MortenMacFly on June 02, 2012, 06:28:49 pm
Every specific editor inheriting from EditorBase could have his specific event to be fired when opening.
This is not possible, because internally often EditorBase is used all the time, even if it is a text editor. So you never know if it is a special editor, therefore "just" EditorBase or an internal. And that is by design and good as it is, because that's the only way how you can use common functionality w/o knowing the details for each editor. For most tasks you don want and don't need to know the specialisation of the editor.
Title: Re: cbEvents
Post by: frithjofh on June 02, 2012, 06:32:29 pm
Then how about putting the information inside the event object. It could have besides the generic GetEditor() function others that retrieve a specific editor, like GetBuiltinEditor() or so, returning NULL when it is not a built in and the editor if it is?
Title: Re: cbEvents
Post by: MortenMacFly on June 02, 2012, 06:53:32 pm
Then how about putting the information inside the event object. It could have besides the generic GetEditor() function others that retrieve a specific editor, like GetBuiltinEditor() or so, returning NULL when it is not a built in and the editor if it is?
Well the SDK does not know special editors and should not know it (it e.g. knows nothing about wxSmith). So the SDK cannot return a special editor like that except if we integrate all special editors into the SDK which is simply impossible and also makes no sense.

Having another method GetBuiltinEditor() besides GetEditor() turns this:
if (event.GetEditor() && event.GetEditor()->IsBuiltIn())
...into:
if (event.GetBuiltInEditor())
Well - we can do this, but it means that in 90% of the cases you pass this overhead (each event object grows) but don't need it for what benefit?

In the end, if the SDK provides this method it also checks for both (event.GetEditor() && event.GetEditor()->IsBuiltIn()), so you could do yourself in your plugin a (static) method that does this, like (pseudo-code):
Code
cbEditor * GetBuiltInEditor(cbEvent* evt)
{
  if (evt && evt.GetEditor() && evt.GetEditor()->IsBuiltIn())
    return static_cast<cbEditor>(evt.GetEditor());
  return 0L;
}
Then you can use it easily as desired. In the end you as plugin developer (this applies to all) plugin developers) will always have special needs. If we put all this into the SDK it will sooner or later be bloated. This is why I am always asking, show me a use case where it makes really sense.
Title: Re: cbEvents
Post by: ollydbg on June 10, 2012, 04:21:36 pm
It looks like there is only one wiki page I can find talking about cb event, it is Code::Blocks SDK events - CodeBlocks (http://wiki.codeblocks.org/index.php?title=Code::Blocks_SDK_events).

But this article is quite simple and does not have detailed information about each event.