Andrzej Wytyczak-Partyka wrote:
Hi Andreas !
I'm fighting with those damn listeners right now, this is really hard.
I have some remarks on this.
1. When I close a document inside the Tab, the tab is not removed.
That could be fixed by keeping the FrameActionListener on the
child frame and listening on COMPONENT_DETACHING events.
This way whenever user closes a document opened inside a tab
the tab itself closes too. I think that would also work with the File->
mechanism.
COMPONENT_DETACHING is definetly wrong. It does not describe closing of
the frame. After such COMPONENT_DETACHING a COMPONENT_ATTACHING can
follow. That can happen incase the same is reused for loading another
component (document).
You have to listen as XCloseListener on every frame you created for a
callback notifyClosing(). Only here you can be sure, that a frame will
be closed. And only here you should remove your tab.
Question: How do you close the document inside the tab ?
2. Whenever a Component is disposed it calls the disposing() method
of listeners attached to it. Those listeners should then clear all the
references to this component, but there's no need to call
removeEventListener()
because that will be done inside the component itself. So, I added an
event listener to the frame component, to check if it's being disposed.
If you are registered as e.g. XCloseListener on a frame, there is no
need to register yourself as XEventListener too. Because XCloseListener
is derived from XEventListener. And after XCloseListenr::notifyClosing()
a XEventListener::disposing() will be called automaticly.
OK - I see. For your purpose it's enough to react on disposing() call's
sent by the frame. Because there is not realy a different between
notifyClosing() and disposing(). In both cases the frame will die ...
and you have to veto against that.
It would be different in case your tabbed environment wishes to stop
closing of frames. But I dont see any reason here doing so.
=> forget the XCloseListener .. listen for disposing() events on frames only
3. When the TopWindow's close button is hit the TopWindow listener - me
- is notified
with disposing(), so I go through the list of frames and issue the
dispatch command
.uno:FrameClose. But ! I don't get the notifyClosing from any frame,
nor is the disposing
method of the EventListener listinening on the frames called ! So I
think there's
something wrong with my dispatch. It looks like this :
Reference< ::css::frame::XDispatchHelper > xDispatch(
m_xServiceManager->createInstance(
::rtl::OUString::createFromAscii(
"com.sun.star.frame.DispatchHelper")),
UNO_QUERY_THROW);
Reference< XDispatchProvider > xDP((*childListIter).m_cFrame,
UNO_QUERY_THROW);
xDispatch->executeDispatch(xDP,
::rtl::OUString::createFromAscii(".uno:CloseFrame"),
::rtl::OUString::createFromAscii(""), 0,
Sequence<
::css::beans::PropertyValue >()
);
For me the dispatch code looks fine. For debugging purposes you can try
to close frames direct using the XCloseable API ...
You must get a notifyClosing() and disposing() event !
4. When the File->Exit is hit the notifyClosing() is called properly, I
have some other
problems here, but I'm still woking on it.
So you get this event on closing frames. Here my question again:
How do you clos your frames for testing ... using menu/toolbar ...?
5. I have some problems with m_refCount, after cleaning everything up
it's still up to 3,
and that's even if I force the child frames to dispose :-/
I can't find the reason for this yet.
That can be reasoned by your listener registrations.
If e.g. all frames was closed manually (e.g. by using File->Close inside
every open frame) nobody will be responsible to close the TabControl and
it's windows. So your object will be registered e.g. as
XTopWindowListener and XWindowListener there.
You hold the TabControl alive ... and the TabControl holds you.
Such ring-references can be killed by dispose() e.g. the TabControl
explicitly.
OK ... here the set of listener interfaces and callbacks, which should
be implemented by your component:
a)
m_xTabParentWindow => XWindowListener::windowResized()
to resize all child windows if the parent window was changed by the user.
b)
every cFrame instance =>
XFrameActionListener::frameAction(COMPONENT_ATTACHED)
to retrieve a XMenuBar object there and cache it.
c)
every cFrame instance =>
XFrameActionListener::frameAction(COMPONENT_REATTACHED)
to update a cached XMenuBar in case a new document was loaded into the
same frame
d)
every cFrame instance =>
XFrameActionListener::frameAction(COMPONENT_DETTACHED)
to forget the cached XMenuBar (nothing more!)
e)
every cFrame instance =>
XEventListener::disposing()
Note: Because you are already XFrameActionListener on every frame, there
is no need to register yourself as XEventListener there again.
Inside the disposing() callback youhas to locate the tab and your
internal tab-info structure. Release it only - dont call dispose() there.
f)
m_xTopWindow => XEventListener::disposing()
to know that the user will close the application.
Here you do the following:
You call XDesktop::terminate() on the m_xDesktop instance (instead of
try to close all frames manually using the dispatch .-)
That will close all open documents (means frames).
Every closed frame will call you with disposing(xFrame).
(see e) what you has to do then ...)
If terminate() returns TRUE, you call dispose() on your m_xTabControl
member. That will call you back within XEventListener::disposing() for
- you registration on m_xTopWindow
- and your registration on m_xTabParentWindow
Forget these member references then.
Normaly then all listener registrations should be gone.
all frames/documents should be closed ...
and the office itself should start it's real termination.
Regards,
Andrzej
Have fun .-)
Andreas
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]