Commit 6adae34a authored by Nimetu's avatar Nimetu

Merge with develop

parents ad8724ff fded57d3
......@@ -206,12 +206,6 @@ namespace NLGUI
invalidateContent();
}
// Set the HTML group used for links
void setBrowseGroup (CInterfaceElement *group)
{
_BrowseGroup = group;
}
/// \from CInterfaceElement
void onInvalidateContent();
sint32 getMaxUsedW() const;
......@@ -293,9 +287,6 @@ namespace NLGUI
// The links
std::vector<CLink> _Links;
// The HTML group used
CInterfaceElement *_BrowseGroup;
private:
std::string _HardText;
uint32 _TextId;
......
......@@ -50,10 +50,21 @@ namespace NLGUI
void setHTMLView( CGroupHTML *html);
bool getMouseOverShape(std::string &texName, uint8 &rot, NLMISC::CRGBA &col);
void setActionOnLeftClick(const std::string &actionHandler) { _AHOnLeftClick = actionHandler; };
void setParamsOnLeftClick(const std::string &actionParams) { _AHOnLeftClickParams = actionParams; };
const std::string &getActionOnLeftClick() const { return _AHOnLeftClick; }
const std::string &getParamsOnLeftClick() const { return _AHOnLeftClickParams; }
protected:
// The main HTML group
CGroupHTML *HTML;
// Left mouse click action
// Don't use CStringShared as URLs change past values would be permanently remembered.
std::string _AHOnLeftClick;
std::string _AHOnLeftClickParams;
};
}
......
......@@ -23,6 +23,7 @@
#include "nel/gui/db_manager.h"
#include "nel/gui/interface_link.h"
#include "nel/gui/widget_manager.h"
#include "nel/gui/view_renderer.h"
using namespace std;
using namespace NLMISC;
......@@ -742,4 +743,14 @@ namespace NLGUI
};
REGISTER_ACTION_HANDLER (CAHUnlockAllContainer, "unlock_all_container");
}
\ No newline at end of file
// ------------------------------------------------------------------------------------------------
class CAHCopyToClipboard : public IActionHandler
{
virtual void execute (CCtrlBase *pCaller, const std::string &params)
{
if (!CViewRenderer::getInstance()->getDriver()->copyTextToClipboard(params))
nlwarning("Copy to clipboard failed: '%s'", params.c_str());
}
};
REGISTER_ACTION_HANDLER(CAHCopyToClipboard, "copy_to_clipboard");
}
......@@ -497,7 +497,11 @@ namespace NLGUI
if (res != CURLE_OK)
{
browseError(string("Connection failed with curl error " + string(curl_easy_strerror(res))).c_str());
std::string err;
err = "Connection failed with cURL error: ";
err += curl_easy_strerror(res);
err += "\nURL '" + _CurlWWW->Url + "'";
browseError(err.c_str());
}
else
if ((code >= 301 && code <= 303) || code == 307 || code == 308)
......@@ -541,7 +545,7 @@ namespace NLGUI
if ( (code < 200 || code >= 300) )
{
browseError(string("Connection failed (curl code " + toString((sint32)res) + "), http code " + toString((sint32)code) + ") : " + _CurlWWW->Url).c_str());
browseError(string("Connection failed (curl code " + toString((sint32)res) + ")\nhttp code " + toString((sint32)code) + ")\nURL '" + _CurlWWW->Url + "'").c_str());
}
else
{
......@@ -3769,7 +3773,6 @@ namespace NLGUI
CGroupParagraph *newParagraph = new CGroupParagraph(CViewBase::TCtorParam());
newParagraph->setResizeFromChildH(true);
newParagraph->setBrowseGroup (this);
newParagraph->setIndent(_Indent);
// Add to the group
......@@ -4123,6 +4126,9 @@ namespace NLGUI
if (!newLink->Link.empty())
{
newLink->setHTMLView (this);
newLink->setActionOnLeftClick("browse");
newLink->setParamsOnLeftClick("name=" + getId() + "|url=" + newLink->Link);
}
}
newLink->setText(tmpStr);
......@@ -5216,6 +5222,11 @@ namespace NLGUI
void CGroupHTML::doBrowseAnchor(const std::string &anchor)
{
if (_Anchors.count(anchor) == 0)
{
return;
}
CInterfaceElement *pIE = _Anchors.find(anchor)->second;
if (pIE)
{
......
......@@ -740,13 +740,11 @@ namespace NLGUI
CInterfaceGroup::updateCoords();
sint32 nCurrentX = 0; // Current offset of an element
EAlign addElt = _AddElt;
if ((addElt == Top) || (addElt == Bottom))
{
// Calculate size
sint32 newH = 0, newW = 0;
sint32 newH = 0;
bool bFirst = true;
for (uint32 i = 0; i < _Elements.size(); ++i)
......@@ -756,10 +754,7 @@ namespace NLGUI
if (!bFirst)
newH += _Space;
bFirst = false;
nCurrentX += _Elements[i].Element->getX();
newW = max (newW, _Elements[i].Element->getW()+(sint32)abs(nCurrentX));
}
_W = max(newW, _MinW);
_H = max(newH, _MinH);
if (_DynamicDisplaySize)
{
......@@ -767,10 +762,13 @@ namespace NLGUI
_MaxH = _H;
}
if (_H < _MaxH) setOfsY(0);
// if width is not from parent, then ensure minimum size
if ((_SizeRef & 1) == 0) _W = max(_W, _MinW);
}
else
{
sint32 newW = 0, newH = 0;
sint32 newW = 0;
bool bFirst = true;
for (uint32 i = 0; i < _Elements.size(); ++i)
......@@ -780,16 +778,17 @@ namespace NLGUI
if (!bFirst)
newW += _Space;
bFirst = false;
newH = max (newH, _Elements[i].Element->getH());
}
_W = max(newW, _MinW);
_H = max(newH, _MinH);
if (_DynamicDisplaySize)
{
_MaxW = _W;
_MaxH = _H;
}
if (_W < _MaxW) setOfsX(0);
// if height is not from parent, then ensure minimum size
if ((_SizeRef & 2) == 0) _H = max(_H, _MinH);
}
CInterfaceElement::updateCoords();
......
......@@ -240,6 +240,7 @@ namespace NLGUI
_GroupList->setY (4);
_GroupList->setSpace (_GroupMenu->_Space);
_GroupList->setSerializable( false );
_GroupList->setResizeFromChildW(true);
addGroup (_GroupList);
}
}
......
......@@ -59,7 +59,6 @@ namespace NLGUI
_TopSpace = 0;
_Indent = 0;
_FirstViewIndentView = false;
_BrowseGroup = NULL;
_TextId = 0;
}
......@@ -868,11 +867,8 @@ namespace NLGUI
ctrl->setParentPosRef (Hotspot_TL);
ctrl->setPosRef (Hotspot_TL);
ctrl->setActive(true);
if (_BrowseGroup)
{
ctrl->setActionOnLeftClick("browse");
ctrl->setParamsOnLeftClick("name="+_BrowseGroup->getId()+"|url="+link.Link->Link);
}
ctrl->setActionOnLeftClick(link.Link->getActionOnLeftClick());
ctrl->setParamsOnLeftClick(link.Link->getParamsOnLeftClick());
ctrl->setScale(true);
addCtrl(ctrl);
}
......
......@@ -180,8 +180,8 @@ int main(int argc, char **argv)
for (uint j = 0; j < size; ++j)
{
// TODO: find what computation do
// *(pRGBA++)-> = color;
pRGBA->modulateFromColorRGBOnly(*pRGBA, color);
++pRGBA;
}
NLMISC::COFile out;
......
......@@ -50,6 +50,24 @@
<command name="re" action="talk" params="mode=11|text=+" ctrlchar="false" />
<command name="r" action="talk" params="mode=11|text=+" ctrlchar="false" />
<command name="0" action="enter_talk" params="mode=12|channel=0" />
<command name="1" action="enter_talk" params="mode=12|channel=1" />
<command name="2" action="enter_talk" params="mode=12|channel=2" />
<command name="3" action="enter_talk" params="mode=12|channel=3" />
<command name="4" action="enter_talk" params="mode=12|channel=4" />
<command name="5" action="enter_talk" params="mode=12|channel=5" />
<command name="6" action="enter_talk" params="mode=12|channel=6" />
<command name="7" action="enter_talk" params="mode=12|channel=7" />
<command name="0" action="talk" params="mode=12|channel=0|text=+" ctrlchar="false" />
<command name="1" action="talk" params="mode=12|channel=1|text=+" ctrlchar="false" />
<command name="2" action="talk" params="mode=12|channel=2|text=+" ctrlchar="false" />
<command name="3" action="talk" params="mode=12|channel=3|text=+" ctrlchar="false" />
<command name="4" action="talk" params="mode=12|channel=4|text=+" ctrlchar="false" />
<command name="5" action="talk" params="mode=12|channel=5|text=+" ctrlchar="false" />
<command name="6" action="talk" params="mode=12|channel=6|text=+" ctrlchar="false" />
<command name="7" action="talk" params="mode=12|channel=7|text=+" ctrlchar="false" />
<command name="guild" action="enter_talk" params="mode=3" />
<command name="gu" action="enter_talk" params="mode=3" />
<command name="g" action="enter_talk" params="mode=3" />
......
......@@ -537,3 +537,17 @@ function game:openWebIGBrowserHeader()
ui.w = ui_webig_browser_w;
end
end
------------------------------------------------------------------------------------------------------------
local SavedUrl = "";
function game:chatUrl(url)
SavedUrl = url
runAH(nil, "active_menu", "menu=ui:interface:chat_uri_action_menu");
end
function game:chatUrlCopy()
runAH(nil, "copy_to_clipboard", SavedUrl)
end
function game:chatUrlBrowse()
runAH(nil, "browse", "name=ui:interface:webig:content:html|url=" .. SavedUrl)
end
......@@ -3127,4 +3127,19 @@
<action handler="set"
params="dblink=UI:SAVE:ISDETACHED:DYNAMIC_CHAT@0|value=0" />
</proc>
<!-- there seems to be no way to pass url to menu, use lua script for middleman -->
<group type="menu"
id="chat_uri_action_menu"
extends="base_menu">
<action id="copy"
name="uiCopy"
handler="lua"
params="game:chatUrlCopy()" />
<action id="openig"
name="uiBrowse"
handler="lua"
params="game:chatUrlBrowse()" />
</group>
</interface_config>
......@@ -2033,13 +2033,9 @@ void CClientConfig::release ()
// Are we in window mode ?
if (ClientCfg.Windowed /* && !isWindowMaximized() */)
{
// Save windows position
// Save windows position. width/height are saved when leaving ingame.
writeInt("PositionX", x);
writeInt("PositionY", y);
// Save windows size
writeInt("Width", std::max((sint)width, 800));
writeInt("Height", std::max((sint)height, 600));
}
}
......
......@@ -1375,8 +1375,24 @@ class CHandlerTalk : public IActionHandler
}
else
{
ChatMngr.setChatMode((CChatGroup::TGroupType)mode);
ChatMngr.chat(text, mode == CChatGroup::team);
if (mode == CChatGroup::dyn_chat)
{
uint channel;
fromString(getParam (sParams, "channel"), channel);
if (channel < CChatGroup::MaxDynChanPerPlayer)
{
PeopleInterraction.talkInDynamicChannel(channel, text);
}
else
{
nlwarning("/ah talk: invalid dyn_chat channel %d\n", channel);
}
}
else
{
ChatMngr.setChatMode((CChatGroup::TGroupType)mode);
ChatMngr.chat(text, mode == CChatGroup::team);
}
}
}
}
......@@ -1391,9 +1407,21 @@ class CHandlerEnterTalk : public IActionHandler
{
// Param
uint mode;
uint channel = 0;
fromString(getParam (sParams, "mode"), mode);
ChatMngr.updateChatModeAndButton(mode);
if (mode == CChatGroup::dyn_chat)
{
fromString(getParam(sParams, "channel"), channel);
if (channel >= CChatGroup::MaxDynChanPerPlayer)
{
channel = 0;
}
}
ChatMngr.updateChatModeAndButton(mode, channel);
}
};
REGISTER_ACTION_HANDLER( CHandlerEnterTalk, "enter_talk");
......
......@@ -1198,77 +1198,6 @@ NLMISC_COMMAND(db, "Modify Database","<Property> <Value>")
return true;
}
static bool talkInChan(uint32 nb,std::vector<std::string>args)
{
uint32 maxChans = CChatGroup::MaxDynChanPerPlayer;
if (nb>=maxChans)
{
return false;
}
if(!args.empty())
{
std::string tmp;
std::vector<std::string>::const_iterator first(args.begin()),last(args.end());
for(;first!=last;++first)
{
tmp = tmp + (*first);
tmp = tmp+" ";
}
ucstring uctmp;
uctmp.fromUtf8(tmp);
PeopleInterraction.talkInDynamicChannel(nb, uctmp);
return true;
}
else
{
ChatMngr.updateChatModeAndButton(CChatGroup::dyn_chat, nb);
}
return false;
}
NLMISC_COMMAND(0,"talk in 0th dynamic chat channel","<channel_nb> <sentence>")
{
return talkInChan(0,args);
}
NLMISC_COMMAND(1,"talk in first dynamic chat channel","<channel_nb> <sentence>")
{
return talkInChan(1,args);
}
NLMISC_COMMAND(2,"talk in 2nd dynamic chat channel","<channel_nb> <sentence>")
{
return talkInChan(2,args);
}
NLMISC_COMMAND(3,"talk in 3rd dynamic chat channel","<channel_nb> <sentence>")
{
return talkInChan(3,args);
}
NLMISC_COMMAND(4,"talk in 4th dynamic chat channel","<channel_nb> <sentence>")
{
return talkInChan(4,args);
}
NLMISC_COMMAND(5,"talk in 5th dynamic chat channel","<channel_nb> <sentence>")
{
return talkInChan(5,args);
}
NLMISC_COMMAND(6,"talk in 6th dynamic chat channel","<channel_nb> <sentence>")
{
return talkInChan(6,args);
}
NLMISC_COMMAND(7,"talk in 7th dynamic chat channel","<channel_nb> <sentence>")
{
return talkInChan(7,args);
}
NLMISC_COMMAND(setItemName, "set name of items, sbrick, etc..","<sheet_id> <name> <desc> <desc2>")
{
if (args.size() < 2) return false;
......
......@@ -20,6 +20,7 @@
// client
#include "chat_text_manager.h"
#include "nel/gui/view_text.h"
#include "nel/gui/group_paragraph.h"
#include "interface_manager.h"
using namespace std;
......@@ -149,34 +150,165 @@ static CInterfaceGroup *buildLineWithCommand(CInterfaceGroup *commandGroup, CVie
return group;
}
//=================================================================================
CViewBase *CChatTextManager::createMsgText(const ucstring &cstMsg, NLMISC::CRGBA col, bool justified /*=false*/)
static inline bool isUrlTag(const ucstring &s, ucstring::size_type index, ucstring::size_type textSize)
{
ucstring msg = cstMsg;
CInterfaceGroup *commandGroup = parseCommandTag(msg);
CViewText *vt = new CViewText(CViewText::TCtorParam());
// get parameters from config.xml
vt->setShadow(isTextShadowed());
vt->setShadowOutline(false);
vt->setFontSize(getTextFontSize());
vt->setMultiLine(true);
vt->setTextMode(justified ? CViewText::Justified : CViewText::DontClipWord);
vt->setMultiLineSpace(getTextMultiLineSpace());
vt->setModulateGlobalColor(false);
// Format http://, https://
// or markdown style (title)[http://..]
if(textSize > index+7)
{
bool markdown = false;
ucstring::size_type i = index;
// advance index to url section if markdown style link is detected
if (s[i] == '(')
{
// scan for ')[http://'
while(i < textSize-9)
{
if (s[i] == ')' && s[i+1] == '[')
{
i += 2;
markdown = true;
break;
}
else
if (s[i] == ')')
{
i += 1;
break;
}
i++;
}
}
ucstring cur_time;
if (showTimestamps())
if (textSize > i + 7)
{
bool isUrl = (toLower(s.substr(i, 7)) == ucstring("http://") || toLower(s.substr(i, 8)) == ucstring("https://"));
// match "text http://" and not "texthttp://"
if (isUrl && i > 0 && !markdown)
{
// '}' is in the list because of color tags, ie "@{FFFF}http://..."
const ucchar chars[] = {' ', '"', '\'', '(', '[', '}'};
isUrl = std::find(std::begin(chars), std::end(chars), s[i - 1]) != std::end(chars);
}
return isUrl;
}
}
return false;
}
// ***************************************************************************
// isUrlTag must match
static inline void getUrlTag(const ucstring &s, ucstring::size_type &index, ucstring &url, ucstring &title)
{
bool isMarkdown = false;
ucstring::size_type textSize = s.size();
ucstring::size_type pos;
// see if we have markdown format
if (s[index] == '(')
{
CCDBNodeLeaf *node = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:SHOW_CLOCK_12H", false);
if (node && node->getValueBool())
cur_time = CInterfaceManager::getTimestampHuman("[%I:%M:%S %p] ");
else
cur_time = CInterfaceManager::getTimestampHuman();
index++;
pos = index;
while(pos < textSize-9)
{
if (s[pos] == ')' && s[pos + 1] == '[')
{
isMarkdown = true;
title = s.substr(index, pos - index);
index = pos + 2;
break;
}
else if (s[pos] == ')')
{
break;
}
pos++;
}
}
// if text contain any color code, set the text formated and white,
// otherwise, set text normal and apply global color
size_t codePos = msg.find(ucstring("@{"));
ucchar chOpen = ' ';
ucchar chClose = ' ';
if (isMarkdown)
{
chOpen = '[';
chClose = ']';
}
else if (index > 0)
{
chOpen = s[index - 1];
if (chOpen == '\'') chClose = '\'';
else if (chOpen == '"') chClose = '"';
else if (chOpen == '(') chClose = ')';
else if (chOpen == '[') chClose = ']';
else chClose = ' ';
}
if (chOpen == chClose)
{
pos = s.find_first_of(chClose, index);
// handle common special case: 'text http://.../, text'
if (pos != ucstring::npos && index > 0)
{
if (s[index-1] == ' ' && (s[pos-1] == ',' || s[pos-1] == '.'))
{
pos--;
}
}
}
else
{
// scan for nested open/close tags
pos = index;
sint nested = 0;
while(pos < textSize)
{
if (s[pos] == chOpen)
{
nested++;
}
else if (s[pos] == chClose)
{
if (nested == 0)
{
break;
}
else
{
nested--;
}
}
pos++;
}
}
// fallback to full string length as we did match http:// already and url spans to the end probably
if (pos == ucstring::npos)
{
pos = textSize;
}
url = s.substr(index, pos - index);
index = pos;
// skip ']' closing char
if (isMarkdown) index++;
}
//=================================================================================
static void prependTimestamp(ucstring &msg)
{
ucstring cur_time;
CCDBNodeLeaf *node = NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:SHOW_CLOCK_12H", false);
if (node && node->getValueBool())
cur_time = CInterfaceManager::getTimestampHuman("[%I:%M:%S %p] ");
else