/*
Project : RSS Reader plugin for Internet Explorer
File name : RRPNewsButton.h
Date :
Pupose : It encapsulates News Button which has the responsibility of showing
News in cool owner-drawn drop down menu.
Note : It handle some Window Messaged chainded to it by RRPToolbar class
This messages are of course related with Button
Send comments
or Bugs to : prafulla_t@users.sourceforge.net
*/
#include "stdafx.h"
#include "RRPNewsButton.h"
#include "Resource.h"
#include "RRPConfigurationManager.h"
int RRPNewsButton::buttonsCount = 1;
RRPNewsButton::RRPNewsButton(void) {
rssFileName = NULL;
debug = RRPDebugInfoLogger::getInstance();
buttonClicked = false;
dummyNewsItem = "This is absoulutely bakwas news item!!!!";
startIndex = 0;
endIndex = 0;
rssParser = NULL;
}
void RRPNewsButton::setToolbar(RRPToolbar *rrpToolbar) {
this->rrpToolbar = rrpToolbar;
//I dont know why this message need to be sent
::SendMessage(*rrpToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L);
}
void RRPNewsButton::setRssFetcher(RRPRssFetcher *fetcher) {
this->rssFetcher = fetcher;
return;
}
RRPNewsButton::~RRPNewsButton(void) {
if(rssFileName)
delete rssFileName;
if(rssParser)
delete rssParser;
}
BOOL RRPNewsButton::createButton(char *nameOfButton,int commandID,CString newsHeader,BYTE buttonStyle) {
this->commandID = commandID;
this->newsHeader = newsHeader;
rrpToolbar->InsertButton(buttonsCount,commandID,buttonStyle | BTNS_BUTTON | BTNS_AUTOSIZE ,TBSTATE_ENABLED,0,-1,0);
changeButtonCaption(nameOfButton);
ZeroMemory(&buttonRect,sizeof(buttonRect));
buttonsCount++;
rrpToolbar->GetItemRect(rrpToolbar->CommandToIndex(commandID),&buttonRect);
rrpToolbar->MapWindowPoints(HWND_DESKTOP, (POINT *)&buttonRect, 2);
refreshNews();
return true;
}
LRESULT RRPNewsButton::OnButtonDropDown(int idCtrl, LPNMHDR pnmh, BOOL& bHandled) {
NMTOOLBAR* ptb = reinterpret_cast<NMTOOLBAR *>(pnmh);
//Creating Menu
if(ptb->iItem == commandID) {
buttonClicked = true;
CMenu menuPopup;
CMenuHandle sub;
rrpToolbar->GetItemRect(rrpToolbar->CommandToIndex(commandID),&buttonRect);
rrpToolbar->MapWindowPoints(HWND_DESKTOP, (POINT *)&buttonRect, 2);
menuPosition.x = buttonRect.left;
menuPosition.y = buttonRect.bottom;
menuPopup.CreatePopupMenu();
MenuItem *menuItem = new MenuItem();
::ZeroMemory(menuItem,sizeof(MenuItem));
menuItem->name = new char[newsHeader.GetLength()+1];
strcpy_s(menuItem->name,newsHeader.GetLength()+1,newsHeader);
menuItem->commandID = commandID;
menuPopup.AppendMenu(MF_STRING | MF_OWNERDRAW,ID_NEWS_HEADER,(LPTSTR)menuItem);
menuPopup.AppendMenu(MF_STRING | MF_OWNERDRAW,ID_MENU_SEPARATOR,(LPTSTR)menuItem);
//Inserting actual news item now
/*
RRPRssItemIterator *it = rssParser->getItemIterator();
int i = 0;
while(it->hasNext()) {
RRPRssItem *item = it->getItem();
//menuItem->name = new char[strlen(item->getTitle()) + 1];
//strcpy_s(menuItem->name,strlen(item->getTitle()) + 1,item->getTitle());
menuPopup.AppendMenu(MF_STRING | MF_OWNERDRAW,ID_NEWS_ITEM_START + i,reinterpret_cast<LPTSTR>(menuItem));
i++;
}
*/
int n = rssParser->getVectorSize();
int i = 0;
if(startIndex < n)
for(i = startIndex;i < (startIndex + 5);i++) {
if(i == n) {
endIndex = i;
break;
}
RRPRssItem *item = rssParser->getRssItem(i);
menuPopup.AppendMenu(MF_STRING | MF_OWNERDRAW,ID_NEWS_ITEM_START + i,reinterpret_cast<LPTSTR>(menuItem));
}
endIndex = i;
//No need to have a menu item here but passing it just like that
menuPopup.AppendMenu(MF_STRING | MF_OWNERDRAW,ID_MENU_SEPARATOR,reinterpret_cast<LPTSTR>(menuItem));
char *indexString = new char[25];
if(startIndex == endIndex)
sprintf(indexString,"%d-%d",startIndex,endIndex);
else
sprintf(indexString,"%d-%d",startIndex + 1,endIndex);
menuItem->name = new char[25];
strcpy(menuItem->name,indexString);
menuPopup.AppendMenu(MF_STRING | MF_OWNERDRAW,ID_NEWS_FOOTER,reinterpret_cast<LPTSTR>(menuItem));
//menuPopup.AppendMenu(MF_STRING ,1001,message);
//menuPopup.AppendMenu(MF_SEPARATOR,25000);
::TrackPopupMenu(menuPopup.Detach(), TPM_LEFTALIGN | TPM_RIGHTBUTTON, menuPosition.x, menuPosition.y, 0, (*rrpToolbar), NULL);
menuTooltip->ShowToolTip(FALSE);
}
return 0;
}
void RRPNewsButton::changeButtonCaption(char *str,DWORD dwMask) {
TBBUTTONINFO tbi;
ZeroMemory(&tbi,sizeof(tbi));
tbi.cbSize = sizeof(TBBUTTONINFO);
tbi.dwMask = TBIF_TEXT;
tbi.pszText = _T(str);
nameOfButton = str;
newsHeader = str;
rrpToolbar->SetButtonInfo(commandID, &tbi);
}
LRESULT RRPNewsButton::OnClick(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) {
debug->log(newsHeader);
return 0;
}
LRESULT RRPNewsButton::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
return 0;
}
LRESULT RRPNewsButton::OnDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
DRAWITEMSTRUCT* lpDIS = reinterpret_cast<DRAWITEMSTRUCT *>(lParam);
MenuItem *menuItem = reinterpret_cast<MenuItem *>(lpDIS->itemData);
//Drawing Menu
//First_News_Button_Clicked_...
if(menuItem->commandID == commandID) {
//debug->log("Drawing news header");
CDCHandle dc = lpDIS->hDC;
RECT rc = lpDIS->rcItem;
if (lpDIS->itemState & ODS_FOCUS)
dc.DrawFocusRect(&rc);
dc.FillSolidRect(&lpDIS->rcItem, RGB(255,255,255));
int nIndexDC = dc.SaveDC();
CBrush br;
dc.SetBkMode(TRANSPARENT);
int nLen = 6;
//Font for Heading
CFont cf;
cf.CreateFont(20,0,0,0,FW_NORMAL,FALSE, FALSE, FALSE,DEFAULT_CHARSET ,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH,_T("Times New Roman"));
HFONT hf = dc.SelectFont(cf);
const COLORREF clrBlue = RGB(0, 0, 255);
const COLORREF clrRed = RGB(255, 0, 0);
if(lpDIS->itemID == ID_MENU_SEPARATOR) {
rc.top += (rc.bottom - rc.top) / 2; // vertical center
dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separator line
return 0;
}
rc.left += 15 + 2;
//Next Prev And that "Trying to load" news String
if(lpDIS->itemID==ID_NEWS_FOOTER) {
CFont nextPrevStringFont;
CFont bottomLineFont;
LOGFONT lf = { 0 };
cf.GetLogFont(lf);
dc.SetTextColor(clrBlue);
lf.lfHeight = 16;
nextPrevStringFont.CreateFontIndirect(&lf);
dc.SelectFont(nextPrevStringFont);
rc.right -= 25;
dc.DrawText("Next",-1,&rc,DT_RIGHT);
rc.left += 10;
dc.DrawText("Prev",-1,&rc,DT_LEFT);
dc.SelectFont(nextPrevStringFont);
CFont msg;
cf.GetLogFont(lf);
dc.SetTextColor(clrBlue);
lf.lfHeight = 13;
msg.CreateFontIndirect(&lf);
dc.SelectFont(msg);
//Drawing Index String
char indexString[25];
if(startIndex == endIndex)
sprintf(indexString,"%d-%d",startIndex,endIndex);
else {
rc.top += 1;
sprintf(indexString,"%d-%d",startIndex+1,endIndex);
}
dc.DrawText(menuItem->name,-1,&rc,DT_CENTER);
rc.top=rc.top+10;
if(startIndex == endIndex)
dc.DrawText("Trying to Load news",-1,&rc,DT_CENTER);
dc.RestoreDC(nIndexDC);
return 0;
}
if(lpDIS->itemID == ID_NEWS_HEADER) {
CFont other_line;
CFont bottom_line;
//Length = 26
CString newsHeaderTruncated;
if(newsHeader.GetLength() >= 26) {
int i;
for(i = 0;i < newsHeader.GetLength();i++)
newsHeaderTruncated += newsHeader[i];
CString dotDotDot("...");
newsHeaderTruncated += dotDotDot;
dc.DrawText(newsHeaderTruncated,-1,&rc,DT_CENTER);
}
else
dc.DrawText(newsHeader,-1,&rc,DT_CENTER);
LOGFONT lf = { 0 };
cf.GetLogFont(lf);
lf.lfHeight = 12;
other_line.CreateFontIndirect(&lf);
dc.SelectFont(other_line);
rc.top=rc.top+20;
dc.DrawText(getDate(),-1,&rc,DT_CENTER);
}
else {
//Get the Rss item to draw
int rssItemIndex = lpDIS->itemID - ID_NEWS_ITEM_START;
RRPRssItem *rssItem = rssParser->getRssItem(rssItemIndex);
CFont newsItems;
LOGFONT lf = { 0 };
cf.GetLogFont(lf);
lf.lfHeight = 16;
if (lpDIS->itemState & ODS_SELECTED)
dc.SetTextColor(clrRed);
else
dc.SetTextColor(clrBlue);
newsItems.CreateFontIndirect(&lf);
dc.SelectFont(newsItems);
rc.right=300;
dc.DrawText(rssItem->getTitle(),-1,&rc,DT_WORDBREAK|DT_NOCLIP|DT_MODIFYSTRING|DT_END_ELLIPSIS);
CPoint ArrowTip=CPoint(rc.left-10,rc.top+5);
CPoint ptDest;
CPoint ptOrig = ArrowTip;
COLORREF cr =RGB(0,0,255);
CPen penArrow, penOld;
if (lpDIS->itemState & ODS_SELECTED)
penArrow.CreatePen(PS_SOLID,1,clrRed);
else
penArrow.CreatePen(PS_SOLID,1,clrBlue);
penOld = dc.SelectPen(penArrow);
if (lpDIS->itemState & ODS_SELECTED)
dc.SetPixel(ArrowTip,clrRed);
else
dc.SetPixel(ArrowTip,clrBlue);
ArrowTip -= CPoint(3,0);
dc.MoveTo(ArrowTip);
ptDest = ArrowTip;
ptDest += CPoint(0,7);
dc.LineTo(ptDest);
for(int i=2;i>=-4;i--) {
CPoint temp=ArrowTip-CPoint(i,0);
temp += CPoint(1,0);
dc.MoveTo(temp);
temp += CPoint(0,7);
dc.LineTo(temp);
}
dc.SelectPen(penOld);
}
dc.RestoreDC(nIndexDC);
return 0;
}
return 0;
}
LRESULT RRPNewsButton::OnMeasureItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
MEASUREITEMSTRUCT* pmis = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam);
MenuItem *menuItem = (MenuItem *)pmis->itemData;
if(menuItem->commandID == commandID) {
CClientDC dc((*rrpToolbar));
HFONT hFont = ((HFONT)GetStockObject( DEFAULT_GUI_FONT ));
int nLen = 6;
CFont newsItems;
CFont cf;
cf.CreateFont(20,0,0,0,FW_NORMAL,FALSE, FALSE, FALSE,DEFAULT_CHARSET ,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH,"Times New Roman");
HFONT hf = dc.SelectFont(cf);
dc.SelectFont( cf ); //GetFont()
LOGFONT lf = { 0 };
cf.GetLogFont(lf);
lf.lfHeight = 16;
lf.lfUnderline=1;
newsItems.CreateFontIndirect(&lf);
dc.SelectFont(newsItems);
dc.SetTextColor(RGB(0,255,0));
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
pmis->itemWidth = 290;
if(pmis->itemID == ID_NEWS_HEADER) {
pmis->itemHeight = 2*(tm.tmHeight + tm.tmInternalLeading);
return 0;
}
if(pmis->itemID == ID_MENU_SEPARATOR) {
pmis->itemHeight = 10;
return 0;
}
if(pmis->itemID == ID_NEWS_FOOTER) {
pmis->itemHeight = 24;
return 0;
}
else {
//Get the Rss item to draw
int rssItemIndex = pmis->itemID - ID_NEWS_ITEM_START;
RRPRssItem *rssItem = rssParser->getRssItem(rssItemIndex);
RECT rcText = { 0,0,250, 0 };
pmis->itemHeight=dc.DrawText(rssItem->getTitle(),-1,&rcText,DT_WORDBREAK| DT_CALCRECT|DT_MODIFYSTRING|DT_END_ELLIPSIS);
pmis->itemHeight += 7;
return 0;
}
//Default Size -- Never gets set
pmis->itemWidth = 290;
pmis->itemHeight = 290;
}
return 0;
}
LRESULT RRPNewsButton::OnMenuSelect(WPARAM additionalParam, WPARAM wParam, LPARAM lParam, BOOL& bHandled) {
WORD nID = LOWORD(wParam);
if(nID >= ID_NEWS_ITEM_START) {
int rssItemIndex = nID - ID_NEWS_ITEM_START;
RRPRssItem *rssItem = rssParser->getRssItem(rssItemIndex);
CString desc = CString(rssItem->getDescription(),strlen(rssItem->getDescription()));
BOOL hasImage,hasTable;
desc = rssItem->removeTags(desc,hasImage,hasTable);
if(hasImage)
desc = desc+ "\r\n"+"Click on the Link to view the Image associated with this News";
else
desc = desc + "\r\n"+"Click on the Link to get more details";
TCHAR *buf = new TCHAR[desc.GetLength()+1];
int i ;
for(i = 0;i<desc.GetLength();i++)
buf[i] = desc[i];
buf[i] = '\0';
POINT *pt = reinterpret_cast<POINT *>(additionalParam);
menuTooltip->OnMenuSelect(buf,LOWORD(wParam),
HIWORD(wParam), (HMENU)lParam,pt->x,pt->y);
}
return 0;
}
RECT RRPNewsButton::getButtonRect() {
return buttonRect;
}
UINT RRPNewsButton::getCommandID() {
return commandID;
}
BOOL RRPNewsButton::isButtonClicked() {
return buttonClicked;
}
void RRPNewsButton::setButtonClicked(BOOL value) {
buttonClicked = value;
}
void RRPNewsButton::OnNextHotSpotClicked() {
try {
int n = rssParser->getVectorSize();
if(n > 0) {
if((startIndex + 5) < n)
startIndex += 5;
else
startIndex = 0;
BOOL handled = 1;
NMTOOLBAR *toolbarData = new NMTOOLBAR();
//This is the field we need
toolbarData->iItem = commandID;
//Dropping menu manually!!
OnButtonDropDown(0,reinterpret_cast<LPNMHDR>(toolbarData),handled);
}
}
catch(...) {
}
}
void RRPNewsButton::OnPrevHotSpotClicked() {
try {
int n = rssParser->getVectorSize();
if(n > 0) {
if((startIndex - 5) >= 0)
startIndex -= 5;
else
startIndex = (n/5)*5;
if(startIndex == n)
startIndex -= 5;
BOOL handled = 1;
NMTOOLBAR *toolbarData = new NMTOOLBAR();
toolbarData->iItem = commandID;
//Dropping menu manually!!
OnButtonDropDown(0,reinterpret_cast<LPNMHDR>(toolbarData),handled);
}
}
catch(...) {
}
}
void RRPNewsButton::removeRssFile(bool justRemoveRssFile) {
if(justRemoveRssFile == false) {
char *nameOfRssFile = new char[25];
sprintf(nameOfRssFile,"%d",commandID);
strcat(nameOfRssFile,".xml");
rssFetcher->removeRssFromList(nameOfRssFile,NULL);
}
remove(rssFileName);
if(rssFileName) {
delete rssFileName;
rssFileName = NULL;
}
}
void RRPNewsButton::refreshNews() {
//Setting Rss for this button
// RRPConfigurationManager *ptr = new RRPConfigurationManager();
RRPConfigurationManager *ptr = rrpToolbar->getConfigManger();
// char *rssDir = RRPConfigurationManager::getInstance()->getInstallationDirectory();
char *rssDir = ptr->getInstallationDirectory();
char *rssDirectory = new char[strlen(rssDir) + 30];
strcpy(rssDirectory,rssDir);
strcat(rssDirectory,"\\rss");
char *nameOfRssFile = new char[25];
sprintf(nameOfRssFile,"%d",commandID);
strcat(nameOfRssFile,".xml");
strcat(rssDirectory,"\\");
strcat(rssDirectory,nameOfRssFile);
//rss is stored in Rss subdir in the installation directory
//The name of the rss is same as the command id of the button which
//is showing the corresponding news
if(rssParser) {
delete rssParser;
rssParser = NULL;
}
rssParser = new RRPRssParser(rssDirectory);
rssFileName = rssDirectory;
OFSTRUCT fileInformation;
HFILE fileHandle = OpenFile(rssFileName,&fileInformation,OF_READ);
bool veryOld = false;
if(fileHandle != HFILE_ERROR) {
FILETIME lastModifiedTime;
::GetFileTime(reinterpret_cast<HANDLE>(fileHandle),NULL,NULL,&lastModifiedTime);
// DWORD d = ::CompareFileTime(&(rrpToolbar->getStartTIme()),&lastModifiedTime);
SYSTEMTIME startTime,lastWriteTime;
::FileTimeToSystemTime(&(rrpToolbar->getStartTIme()),&startTime);
::FileTimeToSystemTime(&lastModifiedTime,&lastWriteTime);
//Checking whether XML was written at least 30 mins
//before the toolbar started
//It is so,tell fetcher process to load it again
if(startTime.wYear > lastWriteTime.wYear)
veryOld = true;
else if(startTime.wMonth > lastWriteTime.wMonth)
veryOld = true;
else if(startTime.wDay > lastWriteTime.wDay)
veryOld = true;
else if(startTime.wHour > lastWriteTime.wHour)
veryOld = true;
else if((startTime.wMinute - lastWriteTime.wMinute) >= 30)
veryOld = true;
/* if(rrpToolbar->getStartTIme().dwHighDateTime > lastModifiedTime.dwHighDateTime)
veryOld = true;
else
if(rrpToolbar->getStartTIme().dwHighDateTime < lastModifiedTime.dwHighDateTime)
veryOld = false;
else
if(rrpToolbar->getStartTIme().dwHighDateTime == lastModifiedTime.dwHighDateTime)
if((rrpToolbar->getStartTIme().dwLowDateTime - lastModifiedTime.dwLowDateTime) >= (DWORD)360000000)
veryOld = true;*/
CloseHandle(reinterpret_cast<HANDLE>(fileHandle));
}
unsigned long flag = 0;
// if(INTERNET_CONNECTION_MODEM == ret) {
//If file does not exists, or parser error or link modified ,tell the fetcher process about it..
if((fileHandle == HFILE_ERROR) || rssParser->isError() || ptr->isModified() || veryOld) {
RRPConfigurationManager *configManager = ptr;
int n = configManager->getSize();
for(int i =0;i<n;i++)
if(configManager->getItem(i)) {
if(configManager->getItem(i)->title && configManager->getItem(i)->link)
if(strcmp(configManager->getItem(i)->title,nameOfButton) == 0) {
rssFetcher->sendFetchRssRequest(nameOfRssFile,configManager->getItem(i)->link);
rrpToolbar->setBusyFlag(true);
}
}
}
rssParser->parse();
if(nameOfRssFile) {
delete nameOfRssFile;
nameOfRssFile = NULL;
}
/* //Creating menu tooltip
menuTooltip = new RRPMenuTooltip();
menuTooltip->Create((*rrpToolbar), _T(""),_Module.GetResourceInstance(),TTS_NOPREFIX | TTS_BALLOON
, _T("Brief Description"));
*/
}
LRESULT RRPNewsButton::OnMenuClick(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) {
if(wID >= ID_NEWS_ITEM_START) {
int rssItemIndex = wID - ID_NEWS_ITEM_START;
RRPRssItem *rssItem = rssParser->getRssItem(rssItemIndex);
if(rssItem) {
CComBSTR bsSite(rssItem->getLink());
webBrowser->Navigate(bsSite.Detach(),NULL,NULL,NULL,NULL);
}
// debug->log("Link is :: %s",rssItem->getLink());
}
return 0;
}
char* RRPNewsButton::getDate() {
static char* days_of_week[] =
{
{ "Sunday" },
{ "Monday" },
{ "Tuesday" },
{ "Wednesday" },
{ "Thursday" },
{ "Friday" },
{ "Saturday" },
} ;
static char* months_of_year[] =
{
{ "" },
{ "January" },
{ "February" },
{ "March" },
{ "April" },
{ "May" },
{ "June" },
{ "July" },
{ "August" },
{ "September" },
{ "October" },
{ "November" },
{ "December" },
} ;
static char *temp = new char[255];
SYSTEMTIME p;
GetLocalTime(&p);
sprintf(temp,"%s,%d %s %d %d:%d:%d",days_of_week[p.wDayOfWeek],p.wDay,months_of_year[p.wMonth],p.wYear,p.wHour,p.wMinute,p.wSecond);
return temp;
}