1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "box.hxx"
29 
30 #include <tools/debug.hxx>
31 #include <sal/macros.h>
32 
33 #include <com/sun/star/awt/XWindow2.hpp>
34 
35 // fixed point precision for distributing error
36 #define FIXED_PT 16
37 
38 namespace layoutimpl
39 {
40 
41 using namespace css;
42 
43 Box_Base::ChildData::ChildData( uno::Reference< awt::XLayoutConstrains > const& xChild )
44     : mxChild( xChild )
45     , mxProps()
46     , maRequisition()
47 {
48 }
49 
50 static bool isVisible( uno::Reference< awt::XLayoutConstrains > xWidget )
51 {
52     if ( !xWidget.is() )
53     {
54         DBG_ERROR( "FIXME: invalid child !" );
55         return true;
56     }
57 
58     uno::Reference< awt::XWindow2 > xWindow( xWidget, uno::UNO_QUERY );
59     if ( xWindow.is() && !xWindow->isVisible() )
60         return false;
61 
62     uno::Reference< awt::XLayoutContainer > xContainer( xWidget, uno::UNO_QUERY );
63     if ( xContainer.is() )
64     {
65         uno::Sequence< uno::Reference< awt::XLayoutConstrains > > aChildren
66             = xContainer->getChildren();
67 
68         if (!aChildren.getLength ())
69             if (Container *c = dynamic_cast <Container*> (xWidget.get ()))
70                 return c->emptyVisible ();
71 
72         for ( int i = 0; i < aChildren.getLength(); i++ )
73             if ( isVisible( aChildren[i] ) )
74                 return true;
75         return false; // this would kill flow without workaround above
76     }
77 
78     return true;
79 }
80 
81 bool Box_Base::ChildData::isVisible()
82 {
83     // FIXME: call the 'isVisible' method on it ?
84     return layoutimpl::isVisible( mxChild );
85 }
86 
87 void
88 Box_Base::AddChild (uno::Reference <awt::XLayoutConstrains> const& xChild)
89 {
90     ChildData *pData = createChild (xChild);
91     maChildren.push_back (pData);
92     queueResize ();
93 }
94 
95 void SAL_CALL
96 Box_Base::addChild (uno::Reference <awt::XLayoutConstrains> const& xChild)
97     throw (uno::RuntimeException, awt::MaxChildrenException)
98 {
99     if (xChild.is ())
100     {
101         AddChild (xChild);
102         setChildParent (xChild);
103     }
104 }
105 
106 Box_Base::ChildData*
107 Box_Base::removeChildData( std::list< ChildData* >& lst, css::uno::Reference< css::awt::XLayoutConstrains > const& xChild )
108 {
109     for ( std::list< ChildData* >::iterator it = lst.begin();
110           it != lst.end(); it++ )
111     {
112         if ( (*it)->mxChild == xChild )
113         {
114             ChildData* pRet = *it;
115             lst.erase( it );
116             return pRet;
117         }
118     }
119     return 0;
120 }
121 
122 void SAL_CALL
123 Box_Base::removeChild( const uno::Reference< awt::XLayoutConstrains >& xChild )
124     throw (uno::RuntimeException)
125 {
126     if ( ChildData* p = removeChildData( maChildren, xChild ) )
127     {
128         delete p;
129         unsetChildParent( xChild );
130         queueResize();
131     }
132     else
133     {
134         DBG_ERROR( "Box_Base: removeChild: no such child" );
135     }
136 }
137 
138 uno::Sequence< uno::Reference < awt::XLayoutConstrains > > SAL_CALL
139 Box_Base::getChildren()
140     throw (uno::RuntimeException)
141 {
142     uno::Sequence< uno::Reference< awt::XLayoutConstrains > > children( maChildren.size() );
143     unsigned int index = 0;
144     for ( std::list< ChildData* >::iterator it = maChildren.begin();
145           it != maChildren.end(); it++, index++ )
146         children[index] = ( *it )->mxChild;
147 
148     return children;
149 }
150 
151 uno::Reference< beans::XPropertySet > SAL_CALL
152 Box_Base::getChildProperties( const uno::Reference< awt::XLayoutConstrains >& xChild )
153     throw (uno::RuntimeException)
154 {
155 
156     for ( std::list< ChildData * >::iterator it = maChildren.begin();
157           it != maChildren.end(); it++)
158     {
159         if ( ( *it )->mxChild == xChild )
160         {
161             if ( !( *it )->mxProps.is() )
162             {
163                 PropHelper *pProps = createChildProps( *it );
164                 pProps->setChangeListener( this );
165                 ( *it )->mxProps = pProps;
166             }
167             return (*it)->mxProps;
168         }
169     }
170     return uno::Reference< beans::XPropertySet >();
171 }
172 
173 } // namespace layoutimpl
174