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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
30 #include "optiongrouplayouter.hxx"
31 #include <tools/debug.hxx>
32 #include <tools/string.hxx>
33 #include <com/sun/star/awt/Size.hpp>
34 #include <com/sun/star/awt/Point.hpp>
35 #include <com/sun/star/container/XIndexAccess.hpp>
36 #include <com/sun/star/container/XNameAccess.hpp>
37 #include <com/sun/star/drawing/XShapes.hpp>
38 #include <com/sun/star/drawing/XShapeGrouper.hpp>
39 #include <com/sun/star/text/TextContentAnchorType.hpp>
40 #include <com/sun/star/view/XSelectionSupplier.hpp>
41 #include "controlwizard.hxx"
42 #include "groupboxwiz.hxx"
43 #include "dbptools.hxx"
44 
45 //.........................................................................
46 namespace dbp
47 {
48 //.........................................................................
49 
50 #define BUTTON_HEIGHT		300
51 #define TOP_HEIGHT			300
52 #define HEIGHT				450
53 #define OFFSET				300
54 #define MIN_WIDTH			600
55 
56 	using namespace ::com::sun::star::uno;
57 	using namespace ::com::sun::star::drawing;
58 	using namespace ::com::sun::star::beans;
59 	using namespace ::com::sun::star::awt;
60 	using namespace ::com::sun::star::container;
61 	using namespace ::com::sun::star::lang;
62 	using namespace ::com::sun::star::text;
63 	using namespace ::com::sun::star::view;
64 
65 	//=====================================================================
66 	//= OOptionGroupLayouter
67 	//=====================================================================
68 	//---------------------------------------------------------------------
69 	OOptionGroupLayouter::OOptionGroupLayouter(const Reference< XMultiServiceFactory >& _rxORB)
70 		:m_xORB(_rxORB)
71 	{
72 	}
73 
74 	//---------------------------------------------------------------------
75 	void OOptionGroupLayouter::doLayout(const OControlWizardContext& _rContext, const OOptionGroupSettings& _rSettings)
76 	{
77 		Reference< XShapes > xPageShapes(_rContext.xDrawPage, UNO_QUERY);
78 		if (!xPageShapes.is())
79 		{
80 			DBG_ERROR("OOptionGroupLayouter::OOptionGroupLayouter: missing the XShapes interface for the page!");
81 			return;
82 		}
83 
84 		Reference< XMultiServiceFactory > xDocFactory(_rContext.xDocumentModel, UNO_QUERY);
85 		if (!xDocFactory.is())
86 		{
87 			DBG_ERROR("OOptionGroupLayouter::OOptionGroupLayouter: no document service factory!");
88 			return;
89 		}
90 
91 		// no. of buttons to create
92 		sal_Int32 nRadioButtons = _rSettings.aLabels.size();
93 
94 		sal_Int32 nTopSpace = 0;
95 
96 		// the shape of the groupbox
97 		::com::sun::star::awt::Size aControlShapeSize = _rContext.xObjectShape->getSize();
98 		// maybe need to adjust the size if the control shapes
99 		sal_Int32 nMinShapeHeight = BUTTON_HEIGHT*(nRadioButtons+1) + BUTTON_HEIGHT + BUTTON_HEIGHT/4;
100 		if (aControlShapeSize.Height < nMinShapeHeight)
101 			aControlShapeSize.Height = nMinShapeHeight;
102 		if (aControlShapeSize.Width < MIN_WIDTH)
103 			aControlShapeSize.Width = MIN_WIDTH;
104 		_rContext.xObjectShape->setSize(aControlShapeSize);
105 
106 		// if we're working on a writer document, we need to anchor the shape
107 		implAnchorShape(Reference< XPropertySet >(_rContext.xObjectShape, UNO_QUERY));
108 
109 		// shape collection (for grouping the shapes)
110 		Reference< XShapes > xButtonCollection(m_xORB->createInstance(
111 				::rtl::OUString::createFromAscii("com.sun.star.drawing.ShapeCollection")),
112 			UNO_QUERY);
113 		// first member : the shape of the control
114 		xButtonCollection->add(_rContext.xObjectShape.get());
115 
116 		sal_Int32 nTempHeight = (aControlShapeSize.Height - BUTTON_HEIGHT/4) / (nRadioButtons + 1);
117 
118 		::com::sun::star::awt::Point aShapePosition = _rContext.xObjectShape->getPosition();
119 
120 		::com::sun::star::awt::Size aButtonSize(aControlShapeSize);
121 		aButtonSize.Width = aControlShapeSize.Width - OFFSET;
122 		aButtonSize.Height = HEIGHT;
123 		::com::sun::star::awt::Point aButtonPosition;
124 		aButtonPosition.X = aShapePosition.X + OFFSET;
125 
126 		::rtl::OUString sElementsName = ::rtl::OUString::createFromAscii("RadioGroup");
127 		disambiguateName(Reference< XNameAccess >(_rContext.xForm, UNO_QUERY), sElementsName);
128 
129 		StringArray::const_iterator aLabelIter = _rSettings.aLabels.begin();
130 		StringArray::const_iterator aValueIter = _rSettings.aValues.begin();
131 		for (sal_Int32 i=0; i<nRadioButtons; ++i, ++aLabelIter, ++aValueIter)
132 		{
133 			aButtonPosition.Y = aShapePosition.Y + (i+1) * nTempHeight + nTopSpace;
134 
135 			Reference< XPropertySet > xRadioModel(
136 					xDocFactory->createInstance(::rtl::OUString::createFromAscii("com.sun.star.form.component.RadioButton")),
137 				UNO_QUERY);
138 
139 			// the label
140 			xRadioModel->setPropertyValue(::rtl::OUString::createFromAscii("Label"), makeAny(rtl::OUString(*aLabelIter)));
141 			// the value
142 			xRadioModel->setPropertyValue(::rtl::OUString::createFromAscii("RefValue"), makeAny(rtl::OUString(*aValueIter)));
143 
144 			// default selection
145 			if (_rSettings.sDefaultField == *aLabelIter)
146 				xRadioModel->setPropertyValue(::rtl::OUString::createFromAscii("DefaultState"), makeAny(sal_Int16(1)));
147 
148 			// the connection to the database field
149 			if (0 != _rSettings.sDBField.Len())
150 				xRadioModel->setPropertyValue(::rtl::OUString::createFromAscii("DataField"), makeAny(::rtl::OUString(_rSettings.sDBField)));
151 
152 			// the name for the model
153 			xRadioModel->setPropertyValue(::rtl::OUString::createFromAscii("Name"), makeAny(sElementsName));
154 
155 			// create a shape for the radio button
156 			Reference< XControlShape > xRadioShape(
157 					xDocFactory->createInstance(::rtl::OUString::createFromAscii("com.sun.star.drawing.ControlShape")),
158 				UNO_QUERY);
159 			Reference< XPropertySet > xShapeProperties(xRadioShape, UNO_QUERY);
160 
161 			// if we're working on a writer document, we need to anchor the shape
162 			implAnchorShape(xShapeProperties);
163 
164 			// position it
165 			xRadioShape->setSize(aButtonSize);
166 			xRadioShape->setPosition(aButtonPosition);
167 			// knitting with the model
168 			xRadioShape->setControl(Reference< XControlModel >(xRadioModel, UNO_QUERY));
169 
170 			// the name of the shape
171 			if (xShapeProperties.is())
172 				xShapeProperties->setPropertyValue(::rtl::OUString::createFromAscii("Name"), makeAny(sElementsName));
173 
174 			// add to the page
175 			xPageShapes->add(xRadioShape.get());
176 			// add to the collection (for the later grouping)
177 			xButtonCollection->add(xRadioShape.get());
178 
179 			// set the GroupBox as "LabelControl" for the RadioButton
180 			// (_after_ having inserted the model into the page!)
181 			xRadioModel->setPropertyValue(::rtl::OUString::createFromAscii("LabelControl"), makeAny(_rContext.xObjectModel));
182 		}
183 
184 		// group the shapes
185 		try
186 		{
187 			Reference< XShapeGrouper > xGrouper(_rContext.xDrawPage, UNO_QUERY);
188 			if (xGrouper.is())
189 			{
190 				Reference< XShapeGroup > xGroupedOptions = xGrouper->group(xButtonCollection);
191 				Reference< XSelectionSupplier > xSelector(_rContext.xDocumentModel->getCurrentController(), UNO_QUERY);
192 				if (xSelector.is())
193 					xSelector->select(makeAny(xGroupedOptions));
194 			}
195 		}
196 		catch(Exception&)
197 		{
198 			DBG_ERROR("OOptionGroupLayouter::doLayout: caught an exception while grouping the shapes!");
199 		}
200 	}
201 
202 	//---------------------------------------------------------------------
203 	void OOptionGroupLayouter::implAnchorShape(const Reference< XPropertySet >& _rxShapeProps)
204 	{
205 		static const ::rtl::OUString s_sAnchorPropertyName = ::rtl::OUString::createFromAscii("AnchorType");
206 		Reference< XPropertySetInfo > xPropertyInfo;
207 		if (_rxShapeProps.is())
208 			xPropertyInfo = _rxShapeProps->getPropertySetInfo();
209 		if (xPropertyInfo.is() && xPropertyInfo->hasPropertyByName(s_sAnchorPropertyName))
210 			_rxShapeProps->setPropertyValue(s_sAnchorPropertyName, makeAny(TextContentAnchorType_AT_PAGE));
211 	}
212 
213 //.........................................................................
214 }	// namespace dbp
215 //.........................................................................
216 
217