/src/libreoffice/vcl/source/control/verticaltabctrl.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <ivctrl.hxx> |
21 | | #include <verticaltabctrl.hxx> |
22 | | |
23 | | #include <vcl/commandevent.hxx> |
24 | | #include <vcl/mnemonic.hxx> |
25 | | #include <vcl/tabctrl.hxx> |
26 | | #include <vcl/uitest/uiobject.hxx> |
27 | | #include <vcl/uitest/logger.hxx> |
28 | | #include <vcl/uitest/eventdescription.hxx> |
29 | | #include <vcl/vclevent.hxx> |
30 | | |
31 | | namespace |
32 | | { |
33 | | void collectUIInformation(const OUString& aID, const OUString& aPos) |
34 | 0 | { |
35 | 0 | EventDescription aDescription; |
36 | 0 | aDescription.aID = aID; |
37 | 0 | aDescription.aParameters = { { "POS", aPos } }; |
38 | 0 | aDescription.aAction = "SELECT"; |
39 | 0 | aDescription.aKeyWord = "VerticalTab"; |
40 | 0 | UITestLogger::getInstance().logEvent(aDescription); |
41 | 0 | } |
42 | | } |
43 | | |
44 | | struct VerticalTabPageData |
45 | | { |
46 | | OUString sId; |
47 | | SvxIconChoiceCtrlEntry* pEntry; |
48 | | VclPtr<vcl::Window> xPage; ///< the TabPage itself |
49 | | }; |
50 | | |
51 | | VerticalTabControl::VerticalTabControl(vcl::Window* pParent, bool bWithIcons) |
52 | 0 | : VclHBox(pParent) |
53 | 0 | , m_xChooser(VclPtr<SvtIconChoiceCtrl>::Create( |
54 | 0 | this, WB_3DLOOK | (bWithIcons ? WB_ICON : WB_SMALLICON) | |
55 | | #ifdef MACOSX |
56 | | WB_NOBORDER | |
57 | | #else |
58 | 0 | WB_BORDER | |
59 | 0 | #endif |
60 | 0 | WB_NOCOLUMNHEADER | WB_NODRAGSELECTION | WB_TABSTOP | WB_CLIPCHILDREN |
61 | 0 | | WB_NOHSCROLL)) |
62 | 0 | , m_xBox(VclPtr<VclVBox>::Create(this)) |
63 | 0 | { |
64 | 0 | SetStyle(GetStyle() | WB_DIALOGCONTROL); |
65 | 0 | SetType(WindowType::VERTICALTABCONTROL); |
66 | 0 | m_xChooser->SetClickHdl(LINK(this, VerticalTabControl, ChosePageHdl_Impl)); |
67 | 0 | m_xChooser->set_width_request(150); |
68 | 0 | m_xChooser->set_height_request(400); |
69 | 0 | m_xChooser->SetSizePixel(Size(150, 400)); |
70 | 0 | m_xBox->set_vexpand(true); |
71 | 0 | m_xBox->set_hexpand(true); |
72 | 0 | m_xBox->set_expand(true); |
73 | 0 | m_xBox->Show(); |
74 | 0 | m_xChooser->Show(); |
75 | 0 | } Unexecuted instantiation: VerticalTabControl::VerticalTabControl(vcl::Window*, bool) Unexecuted instantiation: VerticalTabControl::VerticalTabControl(vcl::Window*, bool) |
76 | | |
77 | 0 | VerticalTabControl::~VerticalTabControl() { disposeOnce(); } |
78 | | |
79 | | void VerticalTabControl::dispose() |
80 | 0 | { |
81 | 0 | m_xChooser.disposeAndClear(); |
82 | 0 | m_xBox.disposeAndClear(); |
83 | 0 | VclHBox::dispose(); |
84 | 0 | } |
85 | | |
86 | | IMPL_LINK_NOARG(VerticalTabControl, ChosePageHdl_Impl, SvtIconChoiceCtrl*, void) |
87 | 0 | { |
88 | 0 | SvxIconChoiceCtrlEntry* pEntry = m_xChooser->GetSelectedEntry(); |
89 | 0 | if (!pEntry) |
90 | 0 | pEntry = m_xChooser->GetCursor(); |
91 | |
|
92 | 0 | VerticalTabPageData* pData = GetPageData(pEntry); |
93 | |
|
94 | 0 | if (pData->sId != m_sCurrentPageId) |
95 | 0 | SetCurPageId(pData->sId); |
96 | 0 | } |
97 | | |
98 | | bool VerticalTabControl::EventNotify(NotifyEvent& rNEvt) |
99 | 0 | { |
100 | 0 | if (rNEvt.GetType() == NotifyEventType::KEYINPUT) |
101 | 0 | { |
102 | 0 | sal_uInt16 nCode = rNEvt.GetKeyEvent()->GetKeyCode().GetCode(); |
103 | 0 | if (nCode == KEY_PAGEUP || nCode == KEY_PAGEDOWN |
104 | 0 | || (nCode == KEY_TAB && rNEvt.GetKeyEvent()->GetKeyCode().IsMod1())) |
105 | 0 | { |
106 | 0 | m_xChooser->DoKeyInput(*(rNEvt.GetKeyEvent())); |
107 | 0 | m_xChooser->GrabFocus(); |
108 | 0 | return true; |
109 | 0 | } |
110 | 0 | } |
111 | 0 | return VclHBox::EventNotify(rNEvt); |
112 | 0 | } |
113 | | |
114 | 0 | void VerticalTabControl::ActivatePage() { m_aActivateHdl.Call(this); } |
115 | | |
116 | | bool VerticalTabControl::DeactivatePage() |
117 | 0 | { |
118 | 0 | return !m_aDeactivateHdl.IsSet() || m_aDeactivateHdl.Call(this); |
119 | 0 | } |
120 | | |
121 | | VerticalTabPageData* VerticalTabControl::GetPageData(const SvxIconChoiceCtrlEntry* pEntry) const |
122 | 0 | { |
123 | 0 | VerticalTabPageData* pRet = nullptr; |
124 | 0 | for (auto& pData : maPageList) |
125 | 0 | { |
126 | 0 | if (pData->pEntry == pEntry) |
127 | 0 | { |
128 | 0 | pRet = pData.get(); |
129 | 0 | break; |
130 | 0 | } |
131 | 0 | } |
132 | 0 | return pRet; |
133 | 0 | } |
134 | | |
135 | | VerticalTabPageData* VerticalTabControl::GetPageData(std::u16string_view rId) const |
136 | 0 | { |
137 | 0 | VerticalTabPageData* pRet = nullptr; |
138 | 0 | for (auto& pData : maPageList) |
139 | 0 | { |
140 | 0 | if (pData->sId == rId) |
141 | 0 | { |
142 | 0 | pRet = pData.get(); |
143 | 0 | break; |
144 | 0 | } |
145 | 0 | } |
146 | 0 | return pRet; |
147 | 0 | } |
148 | | |
149 | | void VerticalTabControl::SetCurPageId(const OUString& rId) |
150 | 0 | { |
151 | 0 | OUString sOldPageId = GetCurPageId(); |
152 | 0 | if (sOldPageId == rId) |
153 | 0 | return; |
154 | | |
155 | 0 | VerticalTabPageData* pOldData = GetPageData(sOldPageId); |
156 | 0 | if (pOldData && pOldData->xPage) |
157 | 0 | { |
158 | 0 | if (!DeactivatePage()) |
159 | 0 | return; |
160 | 0 | pOldData->xPage->Hide(); |
161 | 0 | } |
162 | | |
163 | 0 | m_sCurrentPageId = ""; |
164 | |
|
165 | 0 | VerticalTabPageData* pNewData = GetPageData(rId); |
166 | 0 | if (pNewData && pNewData->xPage) |
167 | 0 | { |
168 | 0 | m_sCurrentPageId = rId; |
169 | 0 | m_xChooser->SetCursor(pNewData->pEntry); |
170 | |
|
171 | 0 | ActivatePage(); |
172 | 0 | pNewData->xPage->Show(); |
173 | 0 | } |
174 | 0 | collectUIInformation(get_id(), m_sCurrentPageId); |
175 | 0 | } |
176 | | |
177 | | const OUString& VerticalTabControl::GetPageId(sal_uInt16 nIndex) const |
178 | 0 | { |
179 | 0 | return maPageList[nIndex]->sId; |
180 | 0 | } |
181 | | |
182 | | void VerticalTabControl::InsertPage(const rtl::OUString& rIdent, const rtl::OUString& rLabel, |
183 | | const Image& rImage, const rtl::OUString& rTooltip, |
184 | | VclPtr<vcl::Window> xPage, int nPos) |
185 | 0 | { |
186 | 0 | SvxIconChoiceCtrlEntry* pEntry = m_xChooser->InsertEntry(rLabel, rImage); |
187 | 0 | pEntry->SetQuickHelpText(rTooltip); |
188 | 0 | m_xChooser->ArrangeIcons(); |
189 | 0 | VerticalTabPageData* pNew; |
190 | 0 | if (nPos == -1) |
191 | 0 | { |
192 | 0 | maPageList.emplace_back(new VerticalTabPageData); |
193 | 0 | pNew = maPageList.back().get(); |
194 | 0 | } |
195 | 0 | else |
196 | 0 | { |
197 | 0 | maPageList.emplace(maPageList.begin() + nPos, new VerticalTabPageData); |
198 | 0 | pNew = maPageList[nPos].get(); |
199 | 0 | } |
200 | 0 | pNew->sId = rIdent; |
201 | 0 | pNew->pEntry = pEntry; |
202 | 0 | pNew->xPage = xPage; |
203 | 0 | Size aOrigPrefSize(m_xBox->get_preferred_size()); |
204 | 0 | Size aPagePrefSize(xPage->get_preferred_size()); |
205 | 0 | m_xBox->set_width_request(std::max(aOrigPrefSize.Width(), aPagePrefSize.Width())); |
206 | 0 | m_xBox->set_height_request(std::max(aOrigPrefSize.Height(), aPagePrefSize.Height())); |
207 | 0 | pNew->xPage->Hide(); |
208 | 0 | } |
209 | | |
210 | | void VerticalTabControl::RemovePage(std::u16string_view rPageId) |
211 | 0 | { |
212 | 0 | for (auto it = maPageList.begin(), end = maPageList.end(); it != end; ++it) |
213 | 0 | { |
214 | 0 | VerticalTabPageData* pData = it->get(); |
215 | 0 | if (pData->sId == rPageId) |
216 | 0 | { |
217 | 0 | sal_Int32 nEntryListPos = m_xChooser->GetEntryListPos(pData->pEntry); |
218 | 0 | assert(nEntryListPos >= 0); |
219 | 0 | m_xChooser->RemoveEntry(nEntryListPos); |
220 | 0 | m_xChooser->ArrangeIcons(); |
221 | 0 | maPageList.erase(it); |
222 | 0 | break; |
223 | 0 | } |
224 | 0 | } |
225 | 0 | } |
226 | | |
227 | | sal_uInt16 VerticalTabControl::GetPagePos(std::u16string_view rPageId) const |
228 | 0 | { |
229 | 0 | VerticalTabPageData* pData = GetPageData(rPageId); |
230 | 0 | if (!pData) |
231 | 0 | return TAB_PAGE_NOTFOUND; |
232 | 0 | return m_xChooser->GetEntryListPos(pData->pEntry); |
233 | 0 | } |
234 | | |
235 | | VclPtr<vcl::Window> VerticalTabControl::GetPage(std::u16string_view rPageId) const |
236 | 0 | { |
237 | 0 | VerticalTabPageData* pData = GetPageData(rPageId); |
238 | 0 | if (!pData) |
239 | 0 | return nullptr; |
240 | 0 | return pData->xPage; |
241 | 0 | } |
242 | | |
243 | | OUString VerticalTabControl::GetPageText(std::u16string_view rPageId) const |
244 | 0 | { |
245 | 0 | VerticalTabPageData* pData = GetPageData(rPageId); |
246 | 0 | if (!pData) |
247 | 0 | return OUString(); |
248 | 0 | return pData->pEntry->GetText(); |
249 | 0 | } |
250 | | |
251 | | void VerticalTabControl::SetPageText(std::u16string_view rPageId, const OUString& rText) |
252 | 0 | { |
253 | 0 | VerticalTabPageData* pData = GetPageData(rPageId); |
254 | 0 | if (!pData) |
255 | 0 | return; |
256 | 0 | pData->pEntry->SetText(rText); |
257 | 0 | } |
258 | | |
259 | | Size VerticalTabControl::GetOptimalSize() const |
260 | 0 | { |
261 | | // re-calculate size - we might have replaced dummy tab pages with |
262 | | // actual content |
263 | 0 | Size aOptimalPageSize(m_xBox->get_preferred_size()); |
264 | |
|
265 | 0 | for (auto const& item : maPageList) |
266 | 0 | { |
267 | 0 | Size aPagePrefSize(item->xPage->get_preferred_size()); |
268 | 0 | if (aPagePrefSize.Width() > aOptimalPageSize.Width()) |
269 | 0 | aOptimalPageSize.setWidth(aPagePrefSize.Width()); |
270 | 0 | if (aPagePrefSize.Height() > aOptimalPageSize.Height()) |
271 | 0 | aOptimalPageSize.setHeight(aPagePrefSize.Height()); |
272 | 0 | } |
273 | |
|
274 | 0 | Size aChooserSize(m_xChooser->get_preferred_size()); |
275 | 0 | return Size(aChooserSize.Width() + aOptimalPageSize.Width(), |
276 | 0 | std::max(aChooserSize.Height(), aOptimalPageSize.Height())); |
277 | 0 | } |
278 | | |
279 | | FactoryFunction VerticalTabControl::GetUITestFactory() const |
280 | 0 | { |
281 | 0 | return VerticalTabControlUIObject::create; |
282 | 0 | } |
283 | | |
284 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |