The GNOME::container interface is rather simple:
module GNOME { interface ParseDisplayName : Unknown { exception SyntaxError {}; }; interface Container : ParseDisplayName { typedef sequence<Unknown> ObjectList; ObjectList enum_objects (); exception NotFound {}; Unknown get_object (in string item_name, in boolean only_if_exists) raises (SyntaxError, NotFound); }; }; |
This interface is mainly used to activate the embedded components when linking is used. Nothing really interesting.
The other interfaces, mainly GNOME::ClientSite and GNOME::ViewFrame are much more interesting. They are responsible for the real embedding of the components.
Here is the ClientSite idl ( bonobo/idl/gnome-client-site.idl )
module GNOME { interface ClientSite : GNOME::Unknown { Container get_container (); void show_window (in boolean shown); Persist::Status save_object (); }; }; |
The get_container function is used for linking. we'll see this later.
The show_window method is rather obvious: when the embedded component has been notified by the container that it must activate itself (ie: enter in edit mode) through the GNOME::View::activate, it will notify the container that it has shown its own editing window through this method if it does not support in-place activation. This will allow the container to show in the composed document that the component is being edited in another window by greying the component views. GNOME::ClientSite::show_window is similar to IOleClientSite::OnShowWindow.
The save_object method is used by the embedded component to ask the container to save itself with all its requested views. This will return a Persist::Status value which will tell the component whether the save succeeded or not. GNOME::ClientSite::save_object is similar to IOleClientSite::SaveObject.
Here is the GNOME::ViewFrame idl definition ( bonobo/idl/gnome-embeddable.idl ):
module GNOME { interface ViewFrame : GNOME::Unknown { typedef sequence<octet> pixbuf; ClientSite get_client_site (); UIHandler get_ui_handler (); void view_activated (in boolean state); void deactivate_and_undo (); void request_resize (in short new_width, in short new_height); void activate_uri (in string uri, in boolean relative); }; }; |
request_resize is a sink for the component: the component will call request_resize to ask the container for more or less space if its size changed. In turn, the container will call the GNOME::View::size_allocate function of the View connected to the GNOME::ViewFrame the request was sent to. The component's View will thus know what his size can be and will update the corresponding view accordingly.
view_activated is also a sink for the component: it must be called by the component to ensure the container that it accepts that its view is to be activated. Typically, this function should be called by the component implementation of GNOME::View::activate. The view_activated function is mainly used to grey the Views to show that they are being edited in a separate window.
get_ui_handler must return a reference to an object implementing the GNOME::UIHandler interface. This new interface is used for the merging of the component menus and toolbars with the container own menus and toolbars for in-place editing. We'll discuss this later.
deactivate_and_undo should be called by the View being edited if undo is called just after activation. This means that the user requested to exit the editing mode.
get_client_site is rather simple: must return an object reference to the GNOME::ViewFrame's GNOME::ClientSite interface
activate_uri ?? gloups ??
The complexity of the interfaces presented should not hide from you the fact that what happens is *REALLY* simple.
Let's imagine i ask the container to insert a component by the "insert from" menu. The container will first try to locate the desired component with the GOAD. The component's factory will be started if not already and an instance of the component will be build. The container will add to its internal list of components this component.
The container then creates a ClientSite for the new component and the designed ClientSite creates a ViewFrame. The ClientSite is passed to the component as well as the ViewFrame so that it may build the corresponding GNOME::embeddable and GNOME::View interfaces.
Once all the interfaces are build, the container intercepts all events on the non-activated component view. If a double-click occurs, the container notifies the component of this to allow the component to activate itself (ie: create a new window for editing or merge its toolbars/menus for in-place editing). The container waits for the component to tell him it is activated and then it greys the edited view to show the user it is being edited.
That's all ! The following section will show you how to implement such a set of interfaces and will show you how the different interfaces interact.