mirror of
https://github.com/tribes2/engine.git
synced 2026-01-20 03:34:48 +00:00
301 lines
10 KiB
C++
301 lines
10 KiB
C++
//-----------------------------------------------------------------------------
|
|
// V12 Engine
|
|
//
|
|
// Copyright (c) 2001 GarageGames.Com
|
|
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "GUI/guiChannelVectorCtrl.h"
|
|
#include "GUI/channelVector.h"
|
|
#include "GUI/guiScrollCtrl.h"
|
|
#include "dgl/dgl.h"
|
|
|
|
IMPLEMENT_CONOBJECT(GuiChannelVectorCtrl);
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
void GuiChannelVectorCtrl::lineInserted(const U32 arg)
|
|
{
|
|
AssertFatal(mMessageVector != NULL, "Should not be here unless we're attached!");
|
|
|
|
GuiScrollCtrl* pScroll = NULL;
|
|
GuiControl* pParent = getParent();
|
|
if (pParent) {
|
|
GuiControl* pGrandParent = pParent->getParent();
|
|
if (pGrandParent)
|
|
pScroll = dynamic_cast<GuiScrollCtrl*>(pGrandParent);
|
|
}
|
|
|
|
bool scrollToBottom = false;
|
|
if (pScroll != NULL)
|
|
scrollToBottom = pScroll->getCurrVPos() == 1.0;
|
|
|
|
mSpecialMarkers.insert(arg);
|
|
createSpecialMarkers(mSpecialMarkers[arg], mMessageVector->getLine(arg).message);
|
|
|
|
const ChannelVector::SpecialMarkers &tags = ((ChannelVector *) mMessageVector)->getLineTags(arg);
|
|
|
|
if (tags.numSpecials)
|
|
{
|
|
U32 n = mSpecialMarkers[arg].numSpecials+tags.numSpecials;
|
|
SpecialMarkers::Special *s = new SpecialMarkers::Special[n];
|
|
|
|
for (U32 i = 0, j = 0, k = 0; k < n; ++k)
|
|
{
|
|
if (i < mSpecialMarkers[arg].numSpecials &&
|
|
(j == tags.numSpecials ||
|
|
mSpecialMarkers[arg].specials[i].start <= tags.specials[j].start))
|
|
s[k] = mSpecialMarkers[arg].specials[i++];
|
|
else
|
|
{
|
|
s[k].specialType = tags.specials[j].specialType;
|
|
s[k].start = tags.specials[j].start;
|
|
s[k].end = tags.specials[j].end;
|
|
++j;
|
|
}
|
|
}
|
|
mSpecialMarkers[arg].numSpecials = n;
|
|
delete [] mSpecialMarkers[arg].specials;
|
|
mSpecialMarkers[arg].specials = s;
|
|
}
|
|
|
|
mLineWrappings.insert(arg);
|
|
createLineWrapping(mLineWrappings[arg], mMessageVector->getLine(arg).message);
|
|
|
|
mLineElements.insert(arg);
|
|
createLineElement(mLineElements[arg], mLineWrappings[arg], mSpecialMarkers[arg]);
|
|
|
|
U32 numLines = 0;
|
|
for (U32 i = 0; i < mLineWrappings.size(); i++) {
|
|
// We need to rebuild the physicalLineStart markers at the same time as
|
|
// we find out how many of them are left...
|
|
mLineElements[i].physicalLineStart = numLines;
|
|
|
|
numLines += mLineWrappings[i].numLines;
|
|
}
|
|
|
|
U32 newHeight = (mProfile->mFont->getHeight() + mLineSpacingPixels) * getMax(numLines, U32(1));
|
|
resize(mBounds.point, Point2I(mBounds.extent.x, newHeight));
|
|
|
|
if (arg == mSpecialMarkers.size() - 1 && scrollToBottom == true)
|
|
pScroll->scrollTo(0, 1);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
void GuiChannelVectorCtrl::onRender(Point2I offset,
|
|
const RectI& updateRect,
|
|
GuiControl*fr)
|
|
{
|
|
GuiControl::onRender(offset, updateRect,fr);
|
|
if (isAttached()) {
|
|
U32 linePixels = mProfile->mFont->getHeight() + mLineSpacingPixels;
|
|
U32 currLine = 0;
|
|
for (U32 i = 0; i < mMessageVector->getNumLines(); i++) {
|
|
|
|
TextElement* pElement = mLineElements[i].headLineElements;
|
|
ColorI lastColor = mProfile->mFontColor;
|
|
|
|
dglSetBitmapModulation(lastColor);
|
|
while (pElement != NULL) {
|
|
Point2I localStart(pElement == mLineElements[i].headLineElements ? 0 : mLineContinuationIndent, currLine * linePixels);
|
|
|
|
Point2I globalCheck = localToGlobalCoord(localStart);
|
|
U32 globalRangeStart = globalCheck.y;
|
|
U32 globalRangeEnd = globalCheck.y + mProfile->mFont->getHeight();
|
|
if (globalRangeStart > updateRect.point.y + updateRect.extent.y ||
|
|
globalRangeEnd < updateRect.point.y) {
|
|
currLine++;
|
|
pElement = pElement->nextPhysicalLine;
|
|
continue;
|
|
}
|
|
|
|
TextElement* walkAcross = pElement;
|
|
while (walkAcross) {
|
|
if (walkAcross->start > walkAcross->end)
|
|
break;
|
|
|
|
Point2I globalStart = localToGlobalCoord(localStart);
|
|
|
|
U32 strWidth;
|
|
if (walkAcross->specialReference == -1) {
|
|
dglSetBitmapModulation(lastColor);
|
|
dglSetTextAnchorColor(mProfile->mFontColor);
|
|
strWidth = dglDrawTextN(mProfile->mFont, globalStart, &mMessageVector->getLine(i).message[walkAcross->start],
|
|
walkAcross->end - walkAcross->start + 1, mProfile->mFontColors);
|
|
dglGetBitmapModulation(&lastColor);
|
|
} else {
|
|
SpecialMarkers::Special &s = mSpecialMarkers[i].specials[walkAcross->specialReference];
|
|
|
|
dglGetBitmapModulation(&lastColor);
|
|
if (s.specialType >= 0)
|
|
dglSetBitmapModulation(mSpecialColor);
|
|
else
|
|
{
|
|
U32 colorIndex;
|
|
|
|
switch(s.specialType)
|
|
{
|
|
case ChannelVector::NickTag:
|
|
colorIndex = NickColor;
|
|
|
|
break;
|
|
case ChannelVector::TribeTag:
|
|
colorIndex = TribeColor;
|
|
|
|
break;
|
|
case ChannelVector::ServerTag:
|
|
colorIndex = ServerColor;
|
|
|
|
break;
|
|
}
|
|
|
|
dglSetBitmapModulation(mProfile->mFontColors[colorIndex]);
|
|
}
|
|
dglSetTextAnchorColor(mProfile->mFontColor);
|
|
strWidth = dglDrawTextN(mProfile->mFont, globalStart, &mMessageVector->getLine(i).message[walkAcross->start],
|
|
walkAcross->end - walkAcross->start + 1);
|
|
|
|
// in case we have 2 in a row...
|
|
dglSetBitmapModulation(lastColor);
|
|
}
|
|
|
|
if (walkAcross->specialReference != -1) {
|
|
Point2I lineStart = localStart;
|
|
Point2I lineEnd = localStart;
|
|
SpecialMarkers::Special &s = mSpecialMarkers[i].specials[walkAcross->specialReference];
|
|
|
|
lineStart.y += mProfile->mFont->getBaseline() + 2;
|
|
lineEnd.x += strWidth;
|
|
lineEnd.y += mProfile->mFont->getBaseline() + 2;
|
|
|
|
if (s.specialType >= 0)
|
|
dglDrawLine(localToGlobalCoord(lineStart),
|
|
localToGlobalCoord(lineEnd),
|
|
mSpecialColor);
|
|
else
|
|
{
|
|
U32 colorIndex;
|
|
|
|
switch(s.specialType)
|
|
{
|
|
case ChannelVector::NickTag:
|
|
colorIndex = NickColor;
|
|
|
|
break;
|
|
case ChannelVector::TribeTag:
|
|
colorIndex = TribeColor;
|
|
|
|
break;
|
|
case ChannelVector::ServerTag:
|
|
colorIndex = ServerColor;
|
|
|
|
break;
|
|
}
|
|
|
|
dglDrawLine(localToGlobalCoord(lineStart),
|
|
localToGlobalCoord(lineEnd),
|
|
mProfile->mFontColors[colorIndex]);
|
|
}
|
|
}
|
|
|
|
localStart.x += strWidth;
|
|
walkAcross = walkAcross->nextInLine;
|
|
}
|
|
|
|
currLine++;
|
|
pElement = pElement->nextPhysicalLine;
|
|
}
|
|
}
|
|
dglClearBitmapModulation();
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
void GuiChannelVectorCtrl::onMouseUp(const GuiEvent& event)
|
|
{
|
|
GuiControl::onMouseUp(event);
|
|
mouseUnlock();
|
|
|
|
// Is this an up from a dragged click?
|
|
if (mMouseDown == false)
|
|
return;
|
|
|
|
// Find the special we are in, if any...
|
|
|
|
S32 currSpecialLine;
|
|
S32 currSpecialRef;
|
|
findSpecialFromCoord(globalToLocalCoord(event.mousePoint), &currSpecialLine, &currSpecialRef);
|
|
|
|
if (currSpecialRef != -1 &&
|
|
(currSpecialLine == mMouseSpecialLine &&
|
|
currSpecialRef == mMouseSpecialRef))
|
|
{
|
|
// Execute the callback
|
|
char type[16];
|
|
const char *content;
|
|
|
|
SpecialMarkers& rSpecial = mSpecialMarkers[currSpecialLine];
|
|
S32 specialStart = rSpecial.specials[currSpecialRef].start;
|
|
S32 specialEnd = rSpecial.specials[currSpecialRef].end;
|
|
|
|
switch (rSpecial.specials[currSpecialRef].specialType)
|
|
{
|
|
case ChannelVector::TribeTag:
|
|
if (currSpecialRef &&
|
|
rSpecial.specials[currSpecialRef-1].specialType == ChannelVector::NickTag)
|
|
{
|
|
--currSpecialRef;
|
|
specialStart = rSpecial.specials[currSpecialRef].start;
|
|
specialEnd = rSpecial.specials[currSpecialRef].end;
|
|
}
|
|
else
|
|
{
|
|
++currSpecialRef;
|
|
specialStart = rSpecial.specials[currSpecialRef].start;
|
|
specialEnd = rSpecial.specials[currSpecialRef].end;
|
|
}
|
|
case ChannelVector::NickTag:
|
|
dStrcpy(type,"warrior");
|
|
content = "";
|
|
|
|
break;
|
|
case ChannelVector::ServerTag:
|
|
{
|
|
const ChannelVector::SpecialMarkers &tags = ((ChannelVector *) mMessageVector)->getLineTags(currSpecialLine);
|
|
|
|
dStrcpy(type,"server");
|
|
for (U32 i = 0; i < tags.numSpecials; ++i)
|
|
if (tags.specials[i].start == specialStart)
|
|
{
|
|
content = tags.specials[i].content;
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
dStrcpy(type,"http");
|
|
content = "";
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
char* copyURL = new char[specialEnd - specialStart + 2];
|
|
|
|
dStrncpy(copyURL, &mMessageVector->getLine(currSpecialLine).message[specialStart], specialEnd - specialStart + 1);
|
|
copyURL[specialEnd - specialStart + 1] = '\0';
|
|
|
|
Con::executef(this, 4, "urlClickCallback", type, copyURL, content);
|
|
|
|
delete [] copyURL;
|
|
}
|
|
|
|
mMouseDown = false;
|
|
mMouseSpecialLine = -1;
|
|
mMouseSpecialRef = -1;
|
|
}
|