Hello Andrzej !

     > I decided to stay with XAWindow for usage with TabListener, but I
     > implemented XWindowListener inside my class. It looks like putting a
     > TabListener to the same class will make it a bit crowded with
    methods of
     > similar names...

    OK ... at least it's a design decision made by you. As I've already
    mentioned ... why not ! .-)


I was thinking it over and over and hasitating between the option of adding a new interface or implementing an existing one, but I thought that things are a bit clearer this way. Maybe there is some third alternative that would satisfy both needs, I don't know :/

It works - so let it .-)
There is not realy a "best way" to implement it.
So your implementation is usable in the same way, then the other ones.

<snip>

     > Done. The createSingleFactory fix came out really helpful.
     > Test basic now looks like this :
     > Sub Main
     >
     >         taskcreator = createUnoService("foo.AWindow")
     >         msgbox taskcreator.dbg_supportedInterfaces
     >
     >         frame = taskcreator.createInstance()
     >         msgbox frame.dbg_supportedInterfaces
     >
     >         frame.getContainerWindow().setVisible(TRUE)
     >
     >         frame1 = taskcreator.createInstance()
     >         frame1.getContainerWindow ().setVisible(TRUE)
     > End Sub
     >

    Works now. But you retrieve the ParentWindow everytimes a new frame
    should be created. That's not neccessary. You can cache it. It's the
    same TabControl providing the same TabParentWindow everytimes you are
    asking for it.

 OK

    And further you register yourself as ResizeListener more
    then ones on this ParentWindow. That's not needed (and by the way
    dangerous) too. Why ?


mess++ I guess ;)

Yes .-)


    Your reference exists inside such listener
    container more then once (if call addListener() more then once). And
    you
    will be called back more then once .-)
    Means: N times disposing() ... N times activate() ... and so on .-)


    There is little mistake. Now you dont create two child windows ... but
you create two frames ... why ?

mess++ and also a little confusion from my part I think. I was trying to figure out at which point the main window gets created - I understood later that it's being created somehow by the TabControl, not by me. That said, I don't really remember why hasn't it been thrown out yet ;-)

It's not created by you ... but you need it to be able to create child windows. So you have to cache it.

<snip>

    Further there is no need to create more then one ResizeListener.
    This listener must forward resize events from 1 ParentWindow to X
    ChildWindows. There is no need to forward resizes from the ChildWindows
    back to e.g. the ParentWindow.


this is done to see if the children are switched properly, as you can see the children have a different implementation of XWindowListener, the only thing it does is broadcast a message
that an event has been trigerred on the child.

OK - I've overlooked that. Nice "debug feature" .-)

<snip>

    I miss the menu handling and closing the frames ...


I'm working on it :-)

Fine.

But this version is nearly the "Finish" of our last non optional step !

wow, I didn't think it would be *that* simple :-)

As I've already said: UNO can make things simple ...
If the programmer understand the designs behind ...
That's the big part .-)

OK ... there are might some small problems left.
E.g. we know that we will have some trouble with focus handling.
But I thing it's not part of this project to solve these problems.
It seams that WE (means the OOo developers) have to make some further changes - so it works as aspected.

I have some more remarks on my code, I'm not sure about a couple of things.

* What's the policy for exceptions ? I'd say that if I throw any exceptions inside my class, which are not related to sam interface implementation directly, I mean they're not mandatory, but added by me, those exceptions should be caught by my class too, so there are no unhandle ones, right?

Policy for exceptions ?
There are no rules defined, which are not defined in other projects too .-) I'm personaly follow these rules:

1)
Never catch a RuntimeException (and exceptions derived from RuntimeException). Every interface method is compiled with support for RuntimeExceptions. Normaly such exceptions will kill the office process ... but we hope that the user send the ErrorReport back to us, so we can find the reason for this error. Of course our AutoRecovery tool should make sure that all opened documents should be saved.

2)
All other exceptions should be catched and handled. Throwing it out can
kill the office. E.g. on solaris such exceptions passing due to an interface, which does not declare it, will be handled as an "unexpected one".

3)
Only declared and realy helpfull exceptions should be thrown away.
E.f. NoSuchElementExceptions on a container interface.

* About the mutex locks. I don't think that I understand this properly, and I like to clean this thing up. You said that whenever I call any outside services I should unlock, and I should use only copies of ref counted objects to do so. This pretty much means, that I should lock only when doing something with a class member, like, say, m_xActiveID = 5; right ?

Yes ... if the class member is not another UNO Service .-)
You should hold the lock alive to:
- read/write simple members (int, string, stl lists)
- and getting copies of more complex (may be UNO service based) objects (e.g. listener)

Example:

        member:
                int m_nInt;
                ::rtl::OUString m_sText;
                Reference< XInterface > m_xListener;

        // open safe scope
        ::osl::ResettableMutexGuard aLock(m_aLock);
                // allowed
                m_nInt   = 0;
                m_sText += "Test";
                Reference< XInterface > xCopy = m_xListener;

                // not allowed
                m_xListener->callSomething();
        aLock.clear();
        // safe scope closed

        // allowed
        xCopy->callSomething();

        // not allowed
        if (m_nInt == 0)
                doSomething();
        m_sText += "Test2";
        m_xListener->callSomething();

* Further, you said that I should use UNO_QUERY_THROW when querying for interfaces. Is that a general rule or does it apply only to vital stuff? But then again - most, if not all, interfaces I query for are vital to the application :/

UNO_QUERY_THROW should be used if you know that a service MUST(!) implement this interface (otherwise the service does not full fill it's own IDL definition) .. and you cant work without that interface. Then this value force throwing of a RuntimeException, in case the interface is not available at this service implementation.

You cant use this if a service has defined an optional interface !
Then you have to use UNO_QUERY and check for the return value.

It's a question about coding styles. It's not good to check everything wich is possible. On the other side its not good to check nothing and let it crash. But throwing an exception in case an expected interface does not exists (but is important for your code) can be handled and must not result into a crash ... but mostly it will .-)


Question: Which of the following code blocks seams to be more understandable and(!) make the job right ?

void BLOCK_1()
{
        Reference< XDesktop > xDesktop(
                xSMGR->createInstance("com.sun.star.frame.Desktop"),
                UNO_QUERY);

        if ( xDesktop.is() )
                xDesktop->addTerminateListener(this);
}

void BLOCK_2()
{
        Reference< XDesktop > xDesktop(
                xSMGR->createInstance("com.sun.star.frame.Desktop"),
                UNO_QUERY_THROW);
        
        xDesktop->addTerminateListener(this);
}

I preferr BLOCK_2(). It's clear that the desktop service has to implement the interface XDesktop. You dont need the check for a valid reference. And you can be sure that you are registered as listener ...
or the office dies by an unexpected (meanly programming!) error.

You dont need two days to find the problem, why you never will be called back from the desktop instance .-)

* Finally, I'm not sure about the childWindows parent, I mean the one setup in the windowDescriptor (wDesc) specifically, is it OK to put the TabControlParentWindow there ?

Yes. You should move the code, where you get the TabParentWindow from the TabControl to your lateInit() methd ... cache this parent window as a member ... and use it everytimes for creating new child windows inside the mentioned WindowDescriptor.

Regards
Andreas

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to