1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include "selectlabeldialog.hxx"
23 #include <strings.hrc>
24 #include <bitmaps.hlst>
25 #include "formbrowsertools.hxx"
26 #include "formstrings.hxx"
27 #include "modulepcr.hxx"
28 #include <com/sun/star/form/FormComponentType.hpp>
29 #include <com/sun/star/container/XChild.hpp>
30 #include <com/sun/star/container/XIndexAccess.hpp>
31 #include <com/sun/star/sdbc/XResultSet.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <comphelper/property.hxx>
35 #include <comphelper/types.hxx>
36 #include <sal/log.hxx>
37 #include <tools/debug.hxx>
44 using namespace ::com::sun::star::uno
;
45 using namespace ::com::sun::star::container
;
46 using namespace ::com::sun::star::beans
;
47 using namespace ::com::sun::star::form
;
48 using namespace ::com::sun::star::sdbc
;
49 using namespace ::com::sun::star::lang
;
53 OSelectLabelDialog::OSelectLabelDialog(weld::Window
* pParent
, Reference
< XPropertySet
> const & _xControlModel
)
54 : GenericDialogController(pParent
, u
"modules/spropctrlr/ui/labelselectiondialog.ui"_ustr
, u
"LabelSelectionDialog"_ustr
)
55 , m_xControlModel(_xControlModel
)
56 , m_bLastSelected(false)
57 , m_bHaveAssignableControl(false)
58 , m_xMainDesc(m_xBuilder
->weld_label(u
"label"_ustr
))
59 , m_xControlTree(m_xBuilder
->weld_tree_view(u
"control"_ustr
))
60 , m_xScratchIter(m_xControlTree
->make_iterator())
61 , m_xNoAssignment(m_xBuilder
->weld_check_button(u
"noassignment"_ustr
))
63 m_xControlTree
->connect_selection_changed(LINK(this, OSelectLabelDialog
, OnEntrySelected
));
64 m_xControlTree
->set_size_request(-1, m_xControlTree
->get_height_rows(8));
66 // fill the description
67 OUString sDescription
= m_xMainDesc
->get_label();
68 sal_Int16 nClassID
= FormComponentType::CONTROL
;
69 if (::comphelper::hasProperty(PROPERTY_CLASSID
, m_xControlModel
))
70 nClassID
= ::comphelper::getINT16(m_xControlModel
->getPropertyValue(PROPERTY_CLASSID
));
72 sDescription
= sDescription
.replaceAll("$controlclass$",
73 GetUIHeadlineName(nClassID
, Any(m_xControlModel
)));
74 OUString sName
= ::comphelper::getString(m_xControlModel
->getPropertyValue(PROPERTY_NAME
));
75 sDescription
= sDescription
.replaceAll("$controlname$", sName
);
76 m_xMainDesc
->set_label(sDescription
);
78 // search for the root of the form hierarchy
79 Reference
< XChild
> xCont(m_xControlModel
, UNO_QUERY
);
80 Reference
< XInterface
> xSearch( xCont
.is() ? xCont
->getParent() : Reference
< XInterface
> ());
81 Reference
< XResultSet
> xParentAsResultSet(xSearch
, UNO_QUERY
);
82 while (xParentAsResultSet
.is())
84 xCont
.set(xSearch
, UNO_QUERY
);
85 xSearch
= xCont
.is() ? xCont
->getParent() : Reference
< XInterface
> ();
86 xParentAsResultSet
.set(xSearch
, UNO_QUERY
);
89 // and insert all entries below this root into the listbox
92 // check which service the allowed components must support
93 sal_Int16 nClassId
= 0;
94 try { nClassId
= ::comphelper::getINT16(m_xControlModel
->getPropertyValue(PROPERTY_CLASSID
)); } catch(...) { }
95 m_sRequiredService
= (FormComponentType::RADIOBUTTON
== nClassId
) ? SERVICE_COMPONENT_GROUPBOX
: SERVICE_COMPONENT_FIXEDTEXT
;
96 m_aRequiredControlImage
= (FormComponentType::RADIOBUTTON
== nClassId
) ? RID_EXTBMP_GROUPBOX
: RID_EXTBMP_FIXEDTEXT
;
98 // calc the currently set label control (so InsertEntries can calc m_xInitialSelection)
99 Any
aCurrentLabelControl( m_xControlModel
->getPropertyValue(PROPERTY_CONTROLLABEL
) );
100 DBG_ASSERT((aCurrentLabelControl
.getValueTypeClass() == TypeClass_INTERFACE
) || !aCurrentLabelControl
.hasValue(),
102 "OSelectLabelDialog::OSelectLabelDialog : invalid ControlLabel property !");
103 if (aCurrentLabelControl
.hasValue())
104 aCurrentLabelControl
>>= m_xInitialLabelControl
;
107 OUString
sRootName(PcrRes(RID_STR_FORMS
));
108 m_xControlTree
->insert(nullptr, -1, &sRootName
, nullptr,
109 nullptr, nullptr, false, m_xScratchIter
.get());
110 m_xControlTree
->set_image(*m_xScratchIter
, RID_EXTBMP_FORMS
);
113 m_xInitialSelection
.reset();
114 m_bHaveAssignableControl
= false;
115 std::unique_ptr
<weld::TreeIter
> xRoot
= m_xControlTree
->make_iterator();
116 m_xControlTree
->get_iter_first(*xRoot
);
117 InsertEntries(xSearch
, *xRoot
);
118 m_xControlTree
->expand_row(*xRoot
);
121 if (m_xInitialSelection
)
123 m_xControlTree
->scroll_to_row(*m_xInitialSelection
);
124 m_xControlTree
->select(*m_xInitialSelection
);
128 m_xControlTree
->scroll_to_row(0);
129 m_xControlTree
->unselect_all();
130 m_xNoAssignment
->set_active(true);
133 if (!m_bHaveAssignableControl
)
134 { // no controls which can be assigned
135 m_xNoAssignment
->set_active(true);
136 m_xNoAssignment
->set_sensitive(false);
139 m_xLastSelected
= m_xControlTree
->make_iterator(nullptr);
141 m_xNoAssignment
->connect_toggled(LINK(this, OSelectLabelDialog
, OnNoAssignmentClicked
));
142 OnNoAssignmentClicked(*m_xNoAssignment
);
145 OSelectLabelDialog::~OSelectLabelDialog()
149 sal_Int32
OSelectLabelDialog::InsertEntries(const Reference
< XInterface
> & _xContainer
, const weld::TreeIter
& rContainerEntry
)
151 Reference
< XIndexAccess
> xContainer(_xContainer
, UNO_QUERY
);
152 if (!xContainer
.is())
155 sal_Int32 nChildren
= 0;
157 Reference
< XPropertySet
> xAsSet
;
158 for (sal_Int32 i
=0; i
<xContainer
->getCount(); ++i
)
160 xContainer
->getByIndex(i
) >>= xAsSet
;
163 SAL_INFO("extensions.propctrlr", "OSelectLabelDialog::InsertEntries : strange : a form component which isn't a property set !");
167 if (!::comphelper::hasProperty(PROPERTY_NAME
, xAsSet
))
168 // we need at least a name for displaying ...
170 sName
= ::comphelper::getString(xAsSet
->getPropertyValue(PROPERTY_NAME
));
172 // we need to check if the control model supports the required service
173 Reference
< XServiceInfo
> xInfo(xAsSet
, UNO_QUERY
);
177 if (!xInfo
->supportsService(m_sRequiredService
))
178 { // perhaps it is a container
179 Reference
< XIndexAccess
> xCont(xAsSet
, UNO_QUERY
);
180 if (xCont
.is() && xCont
->getCount())
181 { // yes -> step down
182 m_xControlTree
->insert(&rContainerEntry
, -1, &sName
, nullptr,
183 nullptr, nullptr, false, m_xScratchIter
.get());
184 m_xControlTree
->set_image(*m_xScratchIter
, RID_EXTBMP_FORM
);
185 auto xIter
= m_xControlTree
->make_iterator(&rContainerEntry
);
186 m_xControlTree
->iter_nth_child(*xIter
, nChildren
);
187 sal_Int32 nContChildren
= InsertEntries(xCont
, *xIter
);
190 m_xControlTree
->expand_row(*xIter
);
194 { // oops, no valid children -> remove the entry
195 m_xControlTree
->remove(*xIter
);
202 if (!::comphelper::hasProperty(PROPERTY_LABEL
, xAsSet
))
205 OUString sDisplayName
=
206 ::comphelper::getString(xAsSet
->getPropertyValue(PROPERTY_LABEL
)) +
209 // all requirements met -> insert
210 m_xUserData
.emplace_back(new Reference
<XPropertySet
>(xAsSet
));
211 OUString
sId(weld::toId(m_xUserData
.back().get()));
212 m_xControlTree
->insert(&rContainerEntry
, -1, &sDisplayName
, &sId
, nullptr, nullptr, false, m_xScratchIter
.get());
213 m_xControlTree
->set_image(*m_xScratchIter
, m_aRequiredControlImage
);
215 if (m_xInitialLabelControl
== xAsSet
)
217 m_xInitialSelection
= m_xControlTree
->make_iterator(&rContainerEntry
);
218 m_xControlTree
->iter_nth_child(*m_xInitialSelection
, nChildren
);
222 m_bHaveAssignableControl
= true;
228 IMPL_LINK(OSelectLabelDialog
, OnEntrySelected
, weld::TreeView
&, rLB
, void)
230 DBG_ASSERT(&rLB
== m_xControlTree
.get(), "OSelectLabelDialog::OnEntrySelected : where did this come from ?");
231 std::unique_ptr
<weld::TreeIter
> xIter
= m_xControlTree
->make_iterator();
232 bool bSelected
= m_xControlTree
->get_selected(xIter
.get());
233 OUString sData
= bSelected
? m_xControlTree
->get_id(*xIter
) : OUString();
234 if (!sData
.isEmpty())
235 m_xSelectedControl
.set(*weld::fromId
<Reference
<XPropertySet
>*>(sData
));
236 m_xNoAssignment
->set_active(sData
.isEmpty());
239 IMPL_LINK(OSelectLabelDialog
, OnNoAssignmentClicked
, weld::Toggleable
&, rButton
, void)
241 DBG_ASSERT(&rButton
== m_xNoAssignment
.get(), "OSelectLabelDialog::OnNoAssignmentClicked : where did this come from ?");
243 if (m_xNoAssignment
->get_active())
245 m_bLastSelected
= m_xControlTree
->get_selected(m_xLastSelected
.get());
249 DBG_ASSERT(m_bHaveAssignableControl
, "OSelectLabelDialog::OnNoAssignmentClicked");
250 // search the first assignable entry
251 auto xSearch
= m_xControlTree
->make_iterator(nullptr);
252 bool bSearch
= m_xControlTree
->get_iter_first(*xSearch
);
255 if (m_xControlTree
->get_id(*xSearch
).toInt64())
257 bSearch
= m_xControlTree
->iter_next(*xSearch
);
262 m_xControlTree
->copy_iterator(*xSearch
, *m_xLastSelected
);
263 m_xControlTree
->select(*m_xLastSelected
);
264 m_bLastSelected
= true;
270 if (!m_xNoAssignment
->get_active())
271 m_xControlTree
->select(*m_xLastSelected
);
273 m_xControlTree
->unselect(*m_xLastSelected
);
279 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */