Hello Andrzej !
Hello all !
I'm just into finishing my *very* productive and exciting evening with
the tab browse component :-)
Here's what I did over the last 4,5 hours :
Good job !
The first draft goes to the right directiony.
Of course it has some smaller problems .-)
But that's normal for a draft version.
Please have a look onto my comments below.
* Added lateInit from Andreas, although have some questions here (please
see below)
Will be answered below too.
* Defined a couple of methods in the XAWindow interface
* And implemented the XAWindow interface in the component, this involved
adding a couple of methods for compliance with XTypeProvider
Here some hints:
a)
Dont derive your class directly from an interface if you use the
template cppu::WeakImplHelperX<>. Please adapt the list of interface
already used within this template.
E.g.
class YourClass : public ::cppu::WeakImplHelper1< XInterface1 >
class YourClass : public ::cppu::WeakImplHelper2< XInterface1,
XInterface2 > and so on.
And further dont implement the methods of XInterface/XTypeProvider
directly on your class, if you use WeakImplHelper! Because this template
does it already for you. And it's not a good idea to have two ref count
variables at the same object.
b)
You use a special interface XAWindow to forward resizes of the parent
window to the child tab windows. Why not .-) But there is an easier way.
You can add yourself (means your cMyWindow instance) as listener on the
parent window. Then you have to implement the XWindowListener interface
directly. So XAWindow is an indirection ...
* After that I was able to get a new
TabListenerImpl(Reference<XInterface> xThis) working from the lateInit.
* In TabListener I queried xThis for a XAWindow interface and called
showChildWindow, hideChildWindow
* Similar thing done in ResizeListener's (of the main window) resized()
method.
So what I've got is :
* a main window showing two unaligned simple children windows inside,
and a tab control with 2 tabs
Question: Why do you create two tabs everytime ?
It's not needed. You should create only one tab per
createInstanceWithContext() request.
Further you should use a singleton mechanism to create the tab control
itself one times only. Otherwhise you get n TabControls with 1 document.
But we need 1 TabControl with n documents inside. How can it be reached?
You can implement a OneInstance service instance of a MultiService.
Patch your component_getFactory() method. Instead of using the cppu
helper method cppu::createSingleFactory() ... you should use
cppu::createOneInstanceFactory().
Some further hints:
a)
Please initialize every new created frame with the right window. The
parent window of the tab control isnt the right one.
E.g.
XWindow xNewChild = xToolkit->create(...xParentWindow...);
XFrame xNewFrame = xSMGR->createInstance("css.frame.Frame");
xNewFrame->initialize(xNewChild);
b)
Every new created (and intialized) frame must be added to the desktop
container. Otherwhise our search mechanism for frames inside the office
will be damaged. And it's needed e.g. to locate already loaded documents
instead of opening it twice.
E.g.
XFramesSupplier xSupp(xDesktop, UNO_QUERY);
XFrames xContainer = xSupp->getFrames();
xContainer->append(xNewFrame);
xNewFrame->setCreator(xDesktop);
c)
Every new created child window should get the right size initialy.
Means: instead of using a default, you should use the actual size of the
parent window. Otherwhise you open "small documents" inside big windows.
And only the first move or resize of the parent window will bring the
right size to the tab window.
* clicking the tabs results in hiding / showing of the appropriate child
window.
* resigin the main window results in resizing the active child window
(to the same size as the parent's)
There is a small bug inside your code .-)
Your member m_activeID should be actualized everytime it's needed.
E.g. initialiazing it inside ctor; actualizing if new tabs was created
And you should check the return value of findChildWindow() before you
use it ... or it will crash sometimes .-)
Question regarding lateInit :
I observed that if I don't pass the reference of xThis anywhere outside
of the component the object gets destroyed anyway. Is that ok, or did I
copy&paste somethin wrong ;-) ? I might of.
I'm getting pretty tired ;-)
Your service will be hold alive by reference.
ParentWindowOfTabControl -> YourResizseListener -> (XAWindow)cMyWindow
If the parent window will be closed it removes your resize listener from
it's container ... the listener dies and removes your cMyWindow
reference (clearing it's member). So you cMyWindow instance will die too.
Anyway, the code is in here :
http://iapart.net/dav/soc/window_1st_working_RC1/
because the SF project has not yet been registered (SF staff complained
about poor project description and rejected the registration. I already
filed a patch).
I really like when things go as expected. Well, at least most of the
time they did ;-)
Now you should implement the cosmetic changes I've mentioned above and
start the next steps:
a) refresh menus on tab activate/deactivate
b) closing all frames (documents) if the tab window is closed
How ?
a)
You must know every created frame (according to the right tab ID).
Here the basic code to get the menu bar of a document.
rem Ask for the LayoutManager of the frame.
rem Use it to retrieve the menubar UIElement from it.
rem Note: If a frame was initialized with a window not
rem supporting the interface XTopWindow
rem a menu bar was not created! That's needed e.g. for the
rem beamer window, which uses child windows ..
rem but replaces the menubar of the outside application window
rem (where it's embedded).
rem In such case you have to create a menu bar UIElement hardly.
xFrameProps = xFrame
xLM = xFrameProps.getPropertyValue("LayoutManager")
xMenuUIElem = xLM.getElement("private:resource/menubar/menubar")
if isNull(xMenuUIElem) then
xLM.createElement("private:resource/menubar/menubar")
xMenuUIElem = xLM.getElement("private:resource/menubar/menubar")
endif
if isNull(xMenuUIElem) then
msgbox "Error: no menu"
exit sub
endif
rem Ask the menu bar UIElement for it's XMenubar interface.
rem and set it on you TabParentWindow
xMenuProps = xMenuUIElem
xMenuBar = xMenuProps.getPropertyValue("XMenuBar")
rem xTopWindow = xTabParentWindow
rem xTopWindow.setMenuBar(xMenuBar)
b)
Add a XTopWindowListener on the TabParentWindow. You will be notified it
the parent window is closed. The you should step over the list of all
open frames and try to close it. But dont do it by calling
XComponent->dispose() or XCloseable->close() ! We need a different APi
here ... we must close it by dispatching an URL ".uno:CloseFrame" to
every frame.
Why ?
If you close all frames by using the API it will not terminate the
office. You have to do it explicitly. But if you use the dispatch API
... the office will be terminated atomaticly if the last frame was
closed. You can use the office dispatch helper service to dispatch such
URL very easy: (Here a basic script ...)
DispatchHelper = createUnoService("com.sun.star.frame.DispatchHelper")
dim NoArgs() as new com.sun.star.beans.PropertyValue
DispatchHelper.executeDispatch(xFrame, ".uno:CloseFrame", "", 0, NoArgs())
Cheers,
Andrzej
It's nice to see the progress of this project .-)
And it's further nice to see, how easy it can be to adopt the behaviour
of OOo by implementing an external(!) UNO component, which can be
registered as AddOn on Ooo .-))
Regards
Andreas
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]