/* Written By and � 2004 Amleth Ojalen (amleth@amleth.com)
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list
of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "StdAfx.h"
#include "cablogfiledraw.h"
#include "MemDC.h"
#define GetRed(dColor) ( dColor & 0x0000FF)
#define GetGreen(dColor) ((dColor & 0x00FF00) >> 8)
#define GetBlue(dColor) ((dColor & 0xFF0000) >> 16)
CABLogFileDraw::CABLogFileDraw(void)
{
m_iLineHeight = 0;
m_iMarginLeft = 0;
m_iCharWidth = 0;
m_iTopLine = 0;
m_Font = NULL;
m_iTabWidth = 4;
m_Selection.top = 0;
m_Selection.left = 0;
m_Selection.right = 0;
m_Selection.bottom = 0;
m_dTextBackColor = RGB(0xFF, 0xFF, 0xFF);
m_dTextColor = RGB(0x00, 0x00, 0x00);
m_dLineColor = RGB(0xFF, 0xFF, 0xFF);
m_dLineBackColor = RGB(0x88, 0x88, 0x88);
m_dNewTextColor = RGB(0xFF, 0x00, 0x00);
m_dSelColor = RGB(0xFF, 0xFF, 0xFF);
m_dSelBackColor = RGB(0x00, 0x00, 0x00);
m_dTagColor = RGB(0xFF, 0x99, 0xFF);
m_Fade[0] = 0xFFFFFFFF;
}
CABLogFileDraw::~CABLogFileDraw(void)
{
if (m_Font)
{
delete m_Font;
m_Font = NULL;
}
}
void CABLogFileDraw::LoadFadeSteps()
{
// this will load the fade steps into an array for quick access
int iCounter;
byte bRed;
byte bGreen;
byte bBlue;
int iRed;
int iGreen;
int iBlue;
double dRed;
double dGreen;
double dBlue;
iRed = GetRed(m_dNewTextColor) - GetRed(m_dTextColor);
iGreen = GetGreen(m_dNewTextColor) - GetGreen(m_dTextColor);
iBlue = GetBlue(m_dNewTextColor) - GetBlue(m_dTextColor);
dRed = (double)iRed / (double)FADE_STEPS;
dGreen = (double)iGreen / (double)FADE_STEPS;
dBlue = (double)iBlue / (double)FADE_STEPS;
for (iCounter = 0; iCounter < FADE_STEPS; iCounter++)
{
bRed = (byte)(GetRed(m_dTextColor) + (dRed * iCounter));
bGreen = (byte)(GetGreen(m_dTextColor) + (dGreen * iCounter));
bBlue = (byte)(GetBlue(m_dTextColor) + (dBlue * iCounter));
m_Fade[iCounter] = RGB(bRed, bGreen, bBlue);
}
}
void CABLogFileDraw::Draw(CDC * pDC, CRect * pRect, CABLogBuffer * pBuffer)
{
// this will draw from the data ontp pDC
// from m_iTopLine and m_iLeftChar
// Create a memory DC from drawing
CMemDC dc(pDC, pRect);
CFont * pOldFont;
long lCounter;
if (m_Font == NULL)
{
// if this is the first time around create the font
m_Font = new CFont;
m_Font->CreateFont(14,0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH,"courier new");
}
pOldFont = dc.SelectObject(m_Font);
if (m_iLineHeight == 0)
{
// if this is the first time around get line height
CSize tSize;
tSize = dc.GetTextExtent("W_");
m_iLineHeight = tSize.cy;
}
if (m_iCharWidth == 0)
{
// if this is the first time around get line Width
CSize tSize;
tSize = dc.GetTextExtent("W");
m_iCharWidth= tSize.cx;
// make the Tabs
for (lCounter = 0; lCounter < _MAX_TABS; lCounter ++)
m_iTabs[lCounter] = lCounter * m_iCharWidth * m_iTabWidth;
}
int iDocLineCount;
// errase the background
dc.FillSolidRect(pRect, m_dTextBackColor);
iDocLineCount = pBuffer->GetLineCount();
if (iDocLineCount > 0)
{
// is there any lines to draw
CABLogBuffer::S_ABLogLine * pLine;
int iLastLine;
int iTopOffset;
int iLineCount;
CSize tOutPos;
// wokr out the last line to display
iLastLine = m_iTopLine + (pRect->Height() / m_iLineHeight) + 2;
if (iLastLine > iDocLineCount)
iLastLine = iDocLineCount;
iLineCount = m_iTopOffset;
iTopOffset = m_iTopOffset;
if (m_iMarginLeft == 0)
{
// if this is the first time around get the Left margin
CSize tSize;
tSize = dc.GetTextExtent("000000");
m_iMarginLeft = tSize.cx + 6 + m_iCharWidth * 2;
}
// fill the margin
dc.FillSolidRect(0,0, m_iMarginLeft - 2, pRect->Height(), m_dLineBackColor);
for (lCounter = m_iTopLine; lCounter < iLastLine; lCounter++)
{
// do for all the lines that we are displaying
CString strLineNo;
int iOffset;
int iTabOffset;
int iFadeStep;
// print line
dc.SetBkColor(m_dTextBackColor);
pLine = pBuffer->GetLine(lCounter);
// work out the TabOffset and the printign offset.
// this only matters if m_iLeftChar > 0
iOffset = m_iMarginLeft + m_iLeftOffset - (m_iLeftChar * m_iCharWidth);
iTabOffset = ((0-m_iLeftChar) * m_iCharWidth) + m_iLeftOffset;
// draw the line
WriteLine(&dc, pLine, lCounter, &iOffset, &iTopOffset, 0, iTabOffset, pRect, pBuffer);
// fill the background for the LineNumbers
dc.FillSolidRect(0,iTopOffset, m_iMarginLeft - 2, m_iLineHeight, m_dLineBackColor);
dc.SetBkColor(m_dLineBackColor);
//check to see if this is a newly modified line
// if so change the color.
pBuffer->HitTest(lCounter, pLine->m_lLineLength-1, NULL, &iFadeStep);
if (iFadeStep != 0)
dc.SetTextColor(m_dNewTextColor);
else
dc.SetTextColor(m_dLineColor);
// Draw the Line Number
strLineNo.Format("%06i", lCounter + 1);
dc.TextOut(m_iCharWidth * 2, iTopOffset, strLineNo);
// draw the Tag symbol if the line is tagged
if ((pLine->m_dFlags & LF_TAGGED) == LF_TAGGED)
dc.FillSolidRect(1, iTopOffset + 1, ((m_iCharWidth* 2) -2), m_iLineHeight -2, m_dTagColor);
iTopOffset +=m_iLineHeight;
}
dc.FillSolidRect(0,iTopOffset, m_iMarginLeft - 2, m_iLineHeight, m_dLineBackColor);
}
else
{
//blank Document
}
dc.SelectObject(pOldFont);
}
void CABLogFileDraw::WriteLine(CDC * pDC, CABLogBuffer::S_ABLogLine * pLine, long lLine, int * iX, int * iY, int iLeftChar, int iTabOffset, CRect * pRect, CABLogBuffer * pBuffer)
{
// this works out the steps to draw a line
int iColorIndex;
int iNewColorIndex;
int iLineOffset;
int iLineStart;
bool bSelected;
bool bNewSelected;
if ((pLine->m_lLineLength - iLeftChar) > 0)
{
// there is something to draw.
iLineOffset = iLeftChar;
iLineStart = iLineOffset;
// check to first drable character and get is properties.
pBuffer->HitTest(lLine, iLineOffset, &bSelected, &iColorIndex);
iLineOffset ++;
while (iLineOffset < pLine->m_lLineLength)
{
// get the next characters properties.
pBuffer->HitTest(lLine, iLineOffset, &bNewSelected, &iNewColorIndex);
if ((bNewSelected != bSelected) || (iNewColorIndex != iColorIndex))
{
// the next character is different so draw the previous characters.
WriteText(pDC, (LPCTSTR)&pLine->m_pLinePointer[iLineStart], iLineOffset - iLineStart, iX, iY, bSelected, m_Fade[iColorIndex], false, iTabOffset, pRect);
iLineStart = iLineOffset;
bSelected = bNewSelected;
iColorIndex = iNewColorIndex;
}
// go to the next character
iLineOffset++;
}
if ((iLineOffset - iLineStart) > 0)
// if there is any text left over draw it.
WriteText(pDC, (LPCTSTR)&pLine->m_pLinePointer[iLineStart], iLineOffset - iLineStart, iX, iY, bSelected, m_Fade[iColorIndex], true, iTabOffset, pRect);
}
}
void CABLogFileDraw::WriteText(CDC * pDC, LPCTSTR strText, int iLength, int * iX, int * iY, bool bSelected, DWORD dColor, bool bLast, int iTabOffset, CRect * pRect)
{
// this actually draws the text.
CSize tSize;
if (bSelected)
{
// its selected
pDC->SetBkColor(m_dSelBackColor);
pDC->SetTextColor(m_dSelColor);
}
else
{
// its not selected
pDC->SetBkColor(m_dTextBackColor);
if (dColor == 0xFFFFFFFF)
// default color
pDC->SetTextColor(m_dTextColor);
else
pDC->SetTextColor(dColor);
}
// draw the text
tSize = pDC->TabbedTextOut(*iX, *iY, strText, iLength, _MAX_TABS, m_iTabs, iTabOffset);
*iX+= tSize.cx;
if (bLast && bSelected)
{
// this is the last character, and it is selected
// draw a selected background for the rest of the line
CRect tRect;
tRect = *pRect;
tRect.left = *iX;
tRect.top = *iY;
tRect.bottom = tRect.top + m_iLineHeight;
pDC->FillSolidRect(tRect, m_dSelBackColor);
}
}