Linux multi-monitor fullscreen support
[ryzomcore.git] / ryzom / client / src / interface_v3 / group_quick_help.cpp
blob567926e0685f5d80e30d5b596ccd729c51510613
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2021 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2019-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "stdpch.h"
28 #include "group_quick_help.h"
29 #include "nel/gui/group_list.h"
30 #include "nel/gui/group_paragraph.h"
31 #include "nel/gui/libwww.h"
32 #include "nel/gui/html_element.h"
33 #include "interface_manager.h"
34 #include "nel/gui/action_handler.h"
35 #include "nel/misc/xml_auto_ptr.h"
36 #include "../actions.h"
37 #include "../client_cfg.h"
39 using namespace std;
40 using namespace NLMISC;
42 // ***************************************************************************
43 NLMISC_REGISTER_OBJECT(CViewBase, CGroupQuickHelp, std::string, "quick_help");
45 CGroupQuickHelp::CGroupQuickHelp(const TCtorParam &param)
46 : CGroupHTML(param)
48 _IsQuickHelp = false;
49 initParameters();
50 _UpdateParagraphNextUpdateCoords = true;
53 // ***************************************************************************
55 CGroupQuickHelp::~CGroupQuickHelp()
59 // ***************************************************************************
61 bool CGroupQuickHelp::submitEvent (const char *event)
63 if(_IsQuickHelp==false)
64 return false;
66 if (_CurrentStep<_Steps.size())
68 const CStep &step = _Steps[_CurrentStep];
69 if (step.EventToComplete.find (event) != step.EventToComplete.end())
71 // Next step
72 _CurrentStep++;
74 activateCurrentStep ();
76 // Update the text
77 updateParagraph ();
80 return false;
83 // ***************************************************************************
85 void CGroupQuickHelp::updateParagraph ()
87 // Get the group list of CGroupScrollText
88 CGroupList *groupList = getList ();
89 if (groupList && groupList->getNumChildren())
91 // Get the adaptator
92 CViewBase *viewBase = groupList->getChild(0);
93 if (viewBase)
95 CInterfaceGroup *adaptor = dynamic_cast<CInterfaceGroup*>(viewBase);
96 if (adaptor)
98 // Get the groups
99 const vector<CInterfaceGroup*> &groups = adaptor->getGroups();
101 // For each paragraph
102 uint i;
103 for (i=0; i<groups.size(); i++)
105 if (groups[i])
107 // Get a paragraph
108 CGroupParagraph *paragraph = dynamic_cast<CGroupParagraph*> (groups[i]);
109 if (paragraph)
111 // Set the text size
112 if (i==_CurrentStep)
113 setGroupTextSize (paragraph, true);
114 else
115 setGroupTextSize (paragraph, false);
125 // ***************************************************************************
127 bool CGroupQuickHelp::parse (xmlNodePtr cur, CInterfaceGroup *parentGroup)
129 // Reset parameters
130 initParameters ();
132 CXMLAutoPtr ptr;
134 ptr = xmlGetProp (cur, (xmlChar*)"non_selected_color");
135 if (ptr)
136 _NonSelectedColor = convertColor(ptr);
137 ptr = xmlGetProp (cur, (xmlChar*)"non_selected_link_color");
138 if (ptr)
139 _NonSelectedLinkColor = convertColor(ptr);
140 ptr = xmlGetProp (cur, (xmlChar*)"non_selected_global_color");
141 if (ptr)
142 _NonSelectedGlobalColor = convertBool(ptr);
143 ptr = xmlGetProp (cur, (xmlChar*)"non_selected_font_size");
144 if (ptr)
145 fromString((const char*)ptr, _NonSelectedSize);
148 if (!CGroupHTML::parse (cur, parentGroup))
149 return false;
151 return true;
154 // ***************************************************************************
156 void CGroupQuickHelp::initParameters()
158 _CurrentStep = 0;
159 _NonSelectedSize = 10;
160 _NonSelectedColor = CRGBA(128,128,128);
161 _NonSelectedLinkColor = CRGBA(0,0,128);
162 _NonSelectedGlobalColor = true;
165 // ***************************************************************************
167 void CGroupQuickHelp::setGroupTextSize (CInterfaceGroup *group, bool selected)
169 bool globalColor = selected ? TextColorGlobalColor : _NonSelectedGlobalColor;
170 bool linkGlobalColor = selected ? LinkColorGlobalColor : _NonSelectedGlobalColor;
171 uint fontSize = selected ? _BrowserStyle.Current.FontSize : _NonSelectedSize;
172 NLMISC::CRGBA color = selected ? _BrowserStyle.Current.TextColor : _NonSelectedColor;
173 NLMISC::CRGBA linkColor = selected ? LinkColor : _NonSelectedLinkColor;
175 // Look for text in this group
176 const vector<CViewBase*> &views = group->getViews();
177 uint i;
178 for (i=0; i<views.size(); i++)
180 // View text ?
181 CViewLink *viewText = dynamic_cast<CViewLink *>(views[i]);
182 if (viewText)
184 bool link = !(viewText->getText().empty()) && viewText->getUnderlined ();
186 // Set text attributes
187 viewText->setFontSize(fontSize);
188 viewText->setColor(link ? linkColor : color);
189 viewText->setModulateGlobalColor(link ? linkGlobalColor : globalColor);
193 // Active / desactive link ctrl
194 const vector<CCtrlBase*> &ctrls = group->getControls();
195 for (i=0; i<ctrls.size(); i++)
197 CCtrlLink *ctrlLink = dynamic_cast<CCtrlLink*>(ctrls[i]);
198 if (ctrlLink)
200 ctrlLink->setActive(selected);
204 // Look into subgroups
205 const vector<CInterfaceGroup*> &groups = group->getGroups();
206 for (i=0; i<groups.size(); i++)
208 if (groups[i])
210 setGroupTextSize (groups[i], selected);
213 CGroupParagraph *p = dynamic_cast<CGroupParagraph*>(group);
214 if (p)
215 p->setTopSpace(0);
216 group->setActive(selected);
219 // ***************************************************************************
221 extern CActionsContext ActionsContext;
223 void CGroupQuickHelp::beginElement(CHtmlElement &elm)
225 CGroupHTML::beginElement (elm);
227 // Paragraph ?
228 switch(elm.ID)
230 case HTML_A:
231 // Quick help
232 if (_TrustedDomain && elm.hasNonEmptyAttribute("z_action_shortcut"))
234 // Get the action category
235 string category = elm.getAttribute("z_action_category");
237 // Get the action params
238 string params = elm.getAttribute("z_action_params");
240 // Get the action descriptor
241 CActionsManager *actionManager = ActionsContext.getActionsManager (category);
242 if (actionManager)
244 const CActionsManager::TActionComboMap &actionCombo = actionManager->getActionComboMap ();
245 CActionsManager::TActionComboMap::const_iterator ite = actionCombo.find (CAction::CName (elm.getAttribute("z_action_shortcut").c_str(), params.c_str()));
246 if (ite != actionCombo.end())
248 addString (ite->second.toString());
252 break;
254 case HTML_P:
255 // Get the action name
256 if (elm.hasAttribute("quick_help_events"))
258 // This page is a quick help
259 _IsQuickHelp = true;
260 // Add a step
261 _Steps.push_back (CStep());
262 CStep &step = _Steps.back();
264 // Get the event names
265 string events = elm.getAttribute("quick_help_events");
266 if (!events.empty())
268 uint first = 0;
269 while (first < events.size())
271 // String end
272 string::size_type last = events.find_first_of(" ", first);
273 if (last == string::npos)
274 last = events.size();
276 // Extract the string
277 step.EventToComplete.insert (events.substr (first, last-first));
278 first = (uint)last+1;
282 // Get the condition
283 step.Condition = elm.getAttribute("quick_help_condition");
285 // Get the action handlers to run
286 step.URL = elm.getAttribute("quick_help_link");
288 break;
292 // ***************************************************************************
293 std::string CGroupQuickHelp::getLanguageUrl(const std::string &href, std::string lang) const
295 std::string uri = href;
297 if (uri.size() < 5 || uri.substr(0, 5) == "http://" || uri.substr(0, 6) == "https://")
299 return uri;
302 // modify uri such that '_??.html' ending contains current user language
303 if (uri.substr(uri.size()-5) == ".html")
305 if (uri.rfind("_") == uri.size() - 8)
307 uri = uri.substr(0, uri.size() - 8);
309 else
311 uri = uri.substr(0, uri.size() - 5);
313 uri += "_" + lang + ".html";
315 // files inside bnp (file:/gamedev.bnp@help_en.html) will always match with CPath::lookup()
316 std::string fname;
317 size_t pos = uri.find("@");
318 if (pos != std::string::npos)
320 fname = uri.substr(pos+1);
322 else
324 fname = uri;
326 if (CPath::lookup(fname, false) == "" && lang != "en")
328 uri = getLanguageUrl(href, "en");
332 return uri;
335 // ***************************************************************************
337 void CGroupQuickHelp::browse (const char *url)
339 // Reset the data
340 _Steps.clear ();
341 _CurrentStep = 0;
343 _IsQuickHelp = false;
345 string completeURL = getLanguageUrl(url, ClientCfg.getHtmlLanguageCode());
347 CGroupHTML::browse (completeURL.c_str());
350 // ***************************************************************************
352 std::string CGroupQuickHelp::home() const
354 string completeURL = getLanguageUrl(Home, ClientCfg.getHtmlLanguageCode());
356 return completeURL;
359 // ***************************************************************************
361 void CGroupQuickHelp::endBuild ()
363 CGroupHTML::endBuild ();
365 if(_IsQuickHelp==false)
366 return;
368 // First step must run an action handler ?
369 activateCurrentStep ();
370 _UpdateParagraphNextUpdateCoords = true;
373 // ***************************************************************************
375 void CGroupQuickHelp::activateCurrentStep ()
377 CInterfaceManager *pIM = CInterfaceManager::getInstance();
378 for(;;)
380 if (_CurrentStep < _Steps.size())
382 // Current step
383 CStep &step = _Steps[_CurrentStep];
385 // A link to follow ?
386 if (!step.URL.empty())
387 CAHManager::getInstance()->runActionHandler("browse", NULL, "url="+step.URL);
389 // Test a skip condition
390 if (!step.Condition.empty() && evalExpression (step.Condition))
392 // Next action handler
393 _CurrentStep++;
394 continue;
397 break;
401 // ***************************************************************************
403 bool CGroupQuickHelp::evalExpression (const std::string &condition)
405 // Add your conditions here :
407 if (condition == "always")
408 return true;
410 return false;
413 // ***************************************************************************
414 /** Submit a quick help action
416 class CHandlerSubmitQuickHelp : public IActionHandler
418 void execute (CCtrlBase * /* pCaller */, const std::string &sParams)
420 CInterfaceElement *element = CWidgetManager::getInstance()->getElementFromId("ui:interface:quick_help:content:html");
421 if (element)
423 // Group HTML ?
424 CGroupQuickHelp *groupQH = dynamic_cast<CGroupQuickHelp*>(element);
425 if (groupQH)
427 // Submit the form the url
428 groupQH->submitEvent (sParams.c_str());
431 element = CWidgetManager::getInstance()->getElementFromId("ui:interface:help_browser:content:html");
432 if (element)
434 // Group HTML ?
435 CGroupQuickHelp *groupQH = dynamic_cast<CGroupQuickHelp*>(element);
436 if (groupQH)
438 // Submit the form the url
439 groupQH->submitEvent (sParams.c_str());
445 REGISTER_ACTION_HANDLER( CHandlerSubmitQuickHelp, "submit_quick_help");
447 // ***************************************************************************
448 /** Run a quick help
450 class CHandlerRunQuickHelp : public IActionHandler
452 void execute (CCtrlBase * /* pCaller */, const std::string &sParams)
454 CInterfaceManager *pIM = CInterfaceManager::getInstance();
456 // Get the quick help radio buttons base id
457 string buttonId = CWidgetManager::getInstance()->getParser()->getDefine("quick_help_buttons");
458 if (!buttonId.empty())
460 // Get the button id
461 CInterfaceElement *element = CWidgetManager::getInstance()->getElementFromId(buttonId+":"+sParams);
462 if (element)
464 // Button Ctrl ?
465 CCtrlBaseButton *button = dynamic_cast<CCtrlBaseButton*>(element);
466 if (button)
468 // Push the button
469 button->setPushed(true);
471 // Run the left click action handler
472 CAHManager::getInstance()->runActionHandler(button->getActionOnLeftClick(), button, button->getParamsOnLeftClick());
478 REGISTER_ACTION_HANDLER( CHandlerRunQuickHelp, "run_quick_help");
480 // ***************************************************************************
482 void CGroupQuickHelp::updateCoords()
484 CGroupHTML::updateCoords();
485 if(_IsQuickHelp==false)
486 return;
487 if (_UpdateParagraphNextUpdateCoords)
489 _UpdateParagraphNextUpdateCoords = false;
490 updateParagraph ();
494 // ***************************************************************************