Community
    • Login

    plugin template, docking feature, and c++ core guidelines

    Scheduled Pinned Locked Moved Notepad++ & Plugin Development
    7 Posts 3 Posters 670 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ThosRTannerT
      ThosRTanner
      last edited by ThosRTanner

      I’ve been footling around with an existing plugin and I thought I’d try applying the c++ core guideline document (as MSVC has support for them) to the project

      It produced a bimcj of warnings for dockingfeature code from the plugin template (https://github.com/npp-plugins/plugintemplate) for methods not being noexcept.

      Having had a look at them, I’m a little confused, as there’s no documentation explaining this.

      In no particular order:

      There’s a lot of virtual functions in Window.h where it seems odd for them to be virtual. (getWindowRect for instance).

      It also ends up with the slightly odd situation that getHeight returns 0 if the window isn’t visible, but it doesn’t use the isVisible method (leading to code-nearly-duplication) - presumably because that is a virtual method and might have a different idea as to whether or not the window is visible to what windows does.

      Additionally two of the functions are commented as ‘should NEVER be const’ without any explanation as to why, because they look pretty const.

      Adding noexcept to a virtual function is generally a bit risky, as you don’t know how clients are going to override it, but I’m not sure I can see the point of overriding (e.g.) getHeight.

      Also (in passing) the getFocus method should probably be called setFocus.

      I suppose I should also point out that the init() method looks like a constructor, and why isn’t it one? At least in the plugin I’m working on, by the time it needs to create the docked window, it already knows enough to call the init method from the constructor for the class controlling the docked window.

      So I guess what I’m asking is ‘why?’, and what versions of C++ are used by plugins, and whether anyone either does or should rely on some of these methods being virtual.

      CoisesC 1 Reply Last reply Reply Quote 2
      • CoisesC
        Coises @ThosRTanner
        last edited by

        @ThosRTanner

        I haven’t written a plugin that uses the docking interface, but as far as I can tell, the only mandatory part of the DockingFeature folder is Docking.h, which is required by the NPPM_DMMREGASDCKDLG method.

        The rest appears to form a C++ wrapper around a Windows dialog. It looks as if it is taken from Notepad++ source (Window.h, StaticDialog and DockingWnd); so my guess is that the GoToLineDlg example in the template was built up as quickly as possible based on structures and logic already available and familiar to Notepad++ authors.

        My point being that most of that code was written for Notepad++. My guess is that it was carried over intact as a quick way to build an example, not built from scratch in such a way that everything in it would make sense in the context of a typical plugin. Trying to “rationalize” it from that perspective is probably not possible.

        As I wrote above, I haven’t attempted to write a dockable dialog. If I were to do so, I would begin by taking only the Docking.h file as normative, and look to the rest only as a resource for discovering what a docking dialog is expected to do. Of course, actually trying that might change my mind…

        ThosRTannerT 1 Reply Last reply Reply Quote 3
        • ThosRTannerT
          ThosRTanner @Coises
          last edited by

          Hmmm. I’ve tried debugging this and found that the DMN_DOCK message is sent to the plugin, from https://github.com/notepad-plus-plus/notepad-plus-plus/blob/07041f456545b8339323d2b0441007923bec7571/PowerEditor/src/WinControls/DockingWnd/DockingManager.cpp#L691

          Which sort of implies that it is (or was) possible to have undocked dialogues - not that I can find out how to make that happen.

          So that header is also required.

          CoisesC 1 Reply Last reply Reply Quote 1
          • CoisesC
            Coises @ThosRTanner
            last edited by

            @ThosRTanner said in plugin template, docking feature, and c++ core guidelines:

            DMN_DOCK message is sent to the plugin

            I see. It does look like a number of messages and notifications are defined in dockingResource.h — and not listed in the Plugin Communication section of the help.

            undocked dialogues - not that I can find out how to make that happen

            The user can drag the dialog into or out of the dock. Aside from that, I’d guess one sends the DMM_FLOAT message from dockingResource.h… which, on examination, leads me to retract most of what I said earlier in this thread.

            My presumption — that the interface for docking dialogs would be a C interface, like everything else for plugins — appears to have been mistaken. I’m seeing that the DMM_FLOAT message in Notepad++ expects LPARAM to be a pointer to a DockingCont, which is based on a StaticDialog, which is very much a C++ structure, not a C structure.

            So perhaps it is necessary to copy the entire set of C++ declarations: it looks like Notepad++ expects to see a very specific structure surrounding a docking dialog. That would also mean the compiler for a plugin that implements a docking dialog must be ABI compatible with the one used to compile Notepad++.

            All of which points back to the concerns in your original post being valid.

            rdipardoR 1 Reply Last reply Reply Quote 1
            • rdipardoR
              rdipardo @Coises
              last edited by rdipardo

              I’m seeing that the DMM_FLOAT message in Notepad++ expects LPARAM to be a pointer to a DockingCont, which is based on a StaticDialog . . .

              To be precise, the LPARAM is converted to a DockingCont pointer by means of reinterpret_cast. The plugin only needs to provide the equivalent of an opaque pointer. It’s the job of N++ to (re-)interpret that pointer as something it can use.

              It follows that any compiled language capable of addressing objects via pointers can use the plugin API. See, for example, the many re-implementations of the plugin template in C#, Object Pascal (and derivatives like Modula-2 — e.g., the WebEdit plugin), V, etc.


              CoisesC 1 Reply Last reply Reply Quote 0
              • CoisesC
                Coises @rdipardo
                last edited by

                @rdipardo said in plugin template, docking feature, and c++ core guidelines:

                To be precise, the LPARAM is converted to a DockingCont pointer by means of reinterpret_cast . The plugin only needs to provide the equivalent of an opaque pointer. It’s the job of N++ to (re-)interpret that pointer as something it can use.

                Thank you for that clarification. I think I see, somewhat. The only reference to DockingCont in the plugin template is in a comment. So your point, I take it, is that the pointer to DockingCont is opaque to the plugin; the address is something that would come from Notepad++. In the absence of documentation, though, it is not obvious — to me, anyway — how this pointer would be obtained. But then, it could be that the messages that use it (like DMM_FLOAT) are meant for Notepad++ internal use, and they’re only in the plugin demo code because they’re in the same file as the DMN_* notifications, which are apparently sent to the dialog procedure for the dockable dialog and must be meant for use by plugins.

                So, are we back to what I speculated earlier (and then doubted): that it is a C interface, and the DockingDlgInterface based on StaticDialog based on Window classes are just part of an example, not structures that need to be present as such in a plugin that implements a dockable dialog?

                1 Reply Last reply Reply Quote 0
                • rdipardoR
                  rdipardo
                  last edited by

                  The essential point to remember is that the every facet of the API surface is C-compatible, just like the Win32 API, which underlies all of N++'s internal functions. The details of how N++ dispatches plugin messages naturally involves a few C++ semantics, because it’s a C++ application. Plugins can implement their own C++ types, too, but nothing in the API says they have to. If you just want to display a free-floating form, you can use whatever functions your plugin natively supports, from ::CreateDialogParam to System.Windows.Forms.Form.ShowDialog.

                  The (poorly documented) purpose of the docking API is to register a form with the Docking Manager. In practice, that means preserving the form’s position and geometry in config.xml, so that N++ can optionally reload it when the application starts. To do that, a plugin sends NPPM_DMMREGASDCKDLG with a pointer to a C-like structure filled with some basic parameters, as shown in the developers’ manual.

                  The form’s creation is entirely up to the plugin. N++ simply invokes the function that creates the form by calling through a function pointer. No plugin is required to instantiate a DockingCont or any other object derived from a C++ class. Examples of plugins that do this anyway are special cases, not illustrations of how the docking API works.

                  1 Reply Last reply Reply Quote 3
                  • First post
                    Last post
                  The Community of users of the Notepad++ text editor.
                  Powered by NodeBB | Contributors