OInterfaceContainerHelper3 needs to be thread-safe
[LibreOffice.git] / vcl / jsdialog / executor.cxx
blobcddee247c5316428ff08ff257c306bf5bcd8c097
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
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/.
8 */
10 #include <jsdialog/jsdialogbuilder.hxx>
11 #include <vcl/weld.hxx>
12 #include <vcl/jsdialog/executor.hxx>
13 #include <sal/log.hxx>
14 #include <rtl/uri.hxx>
15 #include <boost/property_tree/json_parser.hpp>
17 namespace jsdialog
19 StringMap jsonToStringMap(const char* pJSON)
21 StringMap aArgs;
22 if (pJSON && pJSON[0] != '\0')
24 std::stringstream aStream(pJSON);
25 boost::property_tree::ptree aTree;
26 boost::property_tree::read_json(aStream, aTree);
28 for (const auto& rPair : aTree)
30 aArgs[OUString::fromUtf8(rPair.first.c_str())]
31 = OUString::fromUtf8(rPair.second.get_value<std::string>(".").c_str());
34 return aArgs;
37 void SendFullUpdate(const std::string& nWindowId, const OString& rWidget)
39 weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, rWidget);
41 if (pWidget != nullptr)
43 auto pJSWidget = dynamic_cast<BaseJSWidget*>(pWidget);
44 pJSWidget->sendFullUpdate();
48 bool ExecuteAction(const std::string& nWindowId, const OString& rWidget, StringMap& rData)
50 weld::Widget* pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, rWidget);
52 OUString sControlType = rData["type"];
53 OUString sAction = rData["cmd"];
55 if (sControlType == "responsebutton")
57 if (pWidget == nullptr)
59 // welded wrapper not found - use response code instead
60 pWidget = JSInstanceBuilder::FindWeldWidgetsMap(nWindowId, "__DIALOG__");
61 sControlType = "dialog";
62 sAction = "response";
64 else
66 // welded wrapper for button found - use it
67 sControlType = "pushbutton";
71 if (pWidget != nullptr)
73 if (sControlType == "tabcontrol")
75 auto pNotebook = dynamic_cast<weld::Notebook*>(pWidget);
76 if (pNotebook)
78 if (sAction == "selecttab")
80 OString pageId = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
81 int page = std::atoi(pageId.getStr());
83 pNotebook->set_current_page(page);
85 return true;
89 else if (sControlType == "combobox")
91 auto pCombobox = dynamic_cast<weld::ComboBox*>(pWidget);
92 if (pCombobox)
94 if (sAction == "selected")
96 int separatorPos = rData["data"].indexOf(';');
97 if (separatorPos > 0)
99 OUString entryPos = rData["data"].copy(0, separatorPos);
100 OString posString = OUStringToOString(entryPos, RTL_TEXTENCODING_ASCII_US);
101 int pos = std::atoi(posString.getStr());
102 pCombobox->set_active(pos);
103 LOKTrigger::trigger_changed(*pCombobox);
104 return true;
107 else if (sAction == "change")
109 pCombobox->set_entry_text(rData["data"]);
110 LOKTrigger::trigger_changed(*pCombobox);
111 return true;
115 else if (sControlType == "pushbutton")
117 auto pButton = dynamic_cast<weld::Button*>(pWidget);
118 if (pButton)
120 if (sAction == "click")
122 pButton->clicked();
123 return true;
127 else if (sControlType == "menubutton")
129 auto pButton = dynamic_cast<weld::MenuButton*>(pWidget);
130 if (pButton)
132 if (sAction == "toggle")
134 if (pButton->get_active())
135 pButton->set_active(false);
136 else
137 pButton->set_active(true);
139 BaseJSWidget* pMenuButton = dynamic_cast<BaseJSWidget*>(pButton);
140 if (pMenuButton)
141 pMenuButton->sendUpdate(true);
143 return true;
147 else if (sControlType == "checkbox")
149 auto pCheckButton = dynamic_cast<weld::CheckButton*>(pWidget);
150 if (pCheckButton)
152 if (sAction == "change")
154 bool bChecked = rData["data"] == "true";
155 pCheckButton->set_state(bChecked ? TRISTATE_TRUE : TRISTATE_FALSE);
156 LOKTrigger::trigger_clicked(*static_cast<weld::Button*>(pCheckButton));
157 LOKTrigger::trigger_toggled(*static_cast<weld::ToggleButton*>(pCheckButton));
158 return true;
162 else if (sControlType == "drawingarea")
164 auto pArea = dynamic_cast<weld::DrawingArea*>(pWidget);
165 if (pArea)
167 if (sAction == "click")
169 int separatorPos = rData["data"].indexOf(';');
170 if (separatorPos > 0)
172 // x;y
173 OString clickPosX = OUStringToOString(rData["data"].copy(0, separatorPos),
174 RTL_TEXTENCODING_ASCII_US);
175 OString clickPosY = OUStringToOString(rData["data"].copy(separatorPos + 1),
176 RTL_TEXTENCODING_ASCII_US);
177 if (!clickPosX.isEmpty() && !clickPosY.isEmpty())
179 double posX = std::atof(clickPosX.getStr());
180 double posY = std::atof(clickPosY.getStr());
181 OutputDevice& rRefDevice = pArea->get_ref_device();
182 // We send OutPutSize for the drawing area bitmap
183 // get_size_request is not necessarily updated
184 // therefore it may be incorrect.
185 Size size = rRefDevice.GetOutputSize();
186 posX = posX * size.Width();
187 posY = posY * size.Height();
188 LOKTrigger::trigger_click(*pArea, Point(posX, posY));
189 return true;
192 LOKTrigger::trigger_click(*pArea, Point(10, 10));
193 return true;
197 else if (sControlType == "spinfield")
199 auto pSpinField = dynamic_cast<weld::SpinButton*>(pWidget);
200 if (pSpinField)
202 if (sAction == "change" || sAction == "value")
204 if (rData["data"] == "undefined")
205 return true;
207 OString sValue = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
208 double nValue = std::atof(sValue.getStr());
209 pSpinField->set_value(nValue
210 * weld::SpinButton::Power10(pSpinField->get_digits()));
211 LOKTrigger::trigger_value_changed(*pSpinField);
212 return true;
214 if (sAction == "plus")
216 pSpinField->set_value(pSpinField->get_value() + 1);
217 LOKTrigger::trigger_value_changed(*pSpinField);
218 return true;
220 else if (sAction == "minus")
222 pSpinField->set_value(pSpinField->get_value() - 1);
223 LOKTrigger::trigger_value_changed(*pSpinField);
224 return true;
228 else if (sControlType == "toolbox")
230 auto pToolbar = dynamic_cast<weld::Toolbar*>(pWidget);
231 if (pToolbar)
233 if (sAction == "click")
235 LOKTrigger::trigger_clicked(
236 *pToolbar, OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US));
237 return true;
239 else if (sAction == "togglemenu")
241 pToolbar->set_menu_item_active(
242 OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US), true);
243 return true;
247 else if (sControlType == "edit")
249 auto pEdit = dynamic_cast<JSEntry*>(pWidget);
250 if (pEdit)
252 if (sAction == "change")
254 pEdit->set_text_without_notify(rData["data"]);
255 LOKTrigger::trigger_changed(*pEdit);
256 return true;
260 auto pTextView = dynamic_cast<weld::TextView*>(pWidget);
261 if (pTextView)
263 if (sAction == "change")
265 pTextView->set_text(rData["data"]);
266 LOKTrigger::trigger_changed(*pTextView);
267 return true;
271 else if (sControlType == "treeview")
273 auto pTreeView = dynamic_cast<JSTreeView*>(pWidget);
274 if (pTreeView)
276 if (sAction == "change")
278 OUString sDataJSON = rtl::Uri::decode(
279 rData["data"], rtl_UriDecodeMechanism::rtl_UriDecodeWithCharset,
280 RTL_TEXTENCODING_UTF8);
281 StringMap aMap(jsonToStringMap(
282 OUStringToOString(sDataJSON, RTL_TEXTENCODING_ASCII_US).getStr()));
284 OString nRowString = OUStringToOString(aMap["row"], RTL_TEXTENCODING_ASCII_US);
285 int nRow = std::atoi(nRowString.getStr());
286 bool bValue = aMap["value"] == "true";
288 pTreeView->set_toggle(nRow, bValue ? TRISTATE_TRUE : TRISTATE_FALSE);
290 return true;
292 else if (sAction == "select")
294 OString nRowString
295 = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
297 pTreeView->unselect_all();
299 int nAbsPos = std::atoi(nRowString.getStr());
301 std::unique_ptr<weld::TreeIter> itEntry(pTreeView->make_iterator());
302 pTreeView->get_iter_abs_pos(*itEntry, nAbsPos);
303 pTreeView->select(*itEntry);
304 pTreeView->set_cursor(*itEntry);
305 LOKTrigger::trigger_changed(*pTreeView);
306 return true;
308 else if (sAction == "activate")
310 OString nRowString
311 = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
312 int nRow = std::atoi(nRowString.getStr());
314 pTreeView->unselect_all();
315 pTreeView->select(nRow);
316 pTreeView->set_cursor(nRow);
317 LOKTrigger::trigger_changed(*pTreeView);
318 LOKTrigger::trigger_row_activated(*pTreeView);
319 return true;
321 else if (sAction == "expand")
323 OString nRowString
324 = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
325 int nAbsPos = std::atoi(nRowString.getStr());
326 std::unique_ptr<weld::TreeIter> itEntry(pTreeView->make_iterator());
327 pTreeView->get_iter_abs_pos(*itEntry, nAbsPos);
328 pTreeView->expand_row(*itEntry);
329 return true;
331 else if (sAction == "dragstart")
333 OString nRowString
334 = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
335 int nRow = std::atoi(nRowString.getStr());
337 pTreeView->select(nRow);
338 pTreeView->drag_start();
340 return true;
342 else if (sAction == "dragend")
344 pTreeView->drag_end();
345 return true;
349 else if (sControlType == "iconview")
351 auto pIconView = dynamic_cast<weld::IconView*>(pWidget);
352 if (pIconView)
354 if (sAction == "select")
356 OString nPosString
357 = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
358 int nPos = std::atoi(nPosString.getStr());
360 pIconView->select(nPos);
361 LOKTrigger::trigger_changed(*pIconView);
363 return true;
365 else if (sAction == "activate")
367 OString nPosString
368 = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
369 int nPos = std::atoi(nPosString.getStr());
371 pIconView->select(nPos);
372 LOKTrigger::trigger_changed(*pIconView);
373 LOKTrigger::trigger_item_activated(*pIconView);
375 return true;
379 else if (sControlType == "expander")
381 auto pExpander = dynamic_cast<weld::Expander*>(pWidget);
382 if (pExpander)
384 if (sAction == "toggle")
386 pExpander->set_expanded(!pExpander->get_expanded());
387 return true;
391 else if (sControlType == "dialog")
393 auto pDialog = dynamic_cast<weld::Dialog*>(pWidget);
394 if (pDialog)
396 if (sAction == "close")
398 pDialog->response(RET_CANCEL);
399 return true;
401 else if (sAction == "response")
403 OString nResponseString
404 = OUStringToOString(rData["data"], RTL_TEXTENCODING_ASCII_US);
405 int nResponse = std::atoi(nResponseString.getStr());
406 pDialog->response(nResponse);
407 return true;
411 else if (sControlType == "popover")
413 auto pPopover = dynamic_cast<weld::Popover*>(pWidget);
414 if (pPopover)
416 if (sAction == "close")
418 LOKTrigger::trigger_closed(*pPopover);
419 return true;
423 else if (sControlType == "radiobutton")
425 auto pRadioButton = dynamic_cast<weld::RadioButton*>(pWidget);
426 if (pRadioButton)
428 if (sAction == "change")
430 bool bChecked = rData["data"] == "true";
431 pRadioButton->set_state(bChecked ? TRISTATE_TRUE : TRISTATE_FALSE);
432 LOKTrigger::trigger_clicked(*static_cast<weld::Button*>(pRadioButton));
433 LOKTrigger::trigger_toggled(*static_cast<weld::ToggleButton*>(pRadioButton));
434 return true;
440 return false;
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */