gecko-dev/cmd/winfe/navbar.cpp

579 lines
16 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
// Embedded menu and close box for Aurora (Created by Dave Hyatt)
#include "stdafx.h"
#include "cxabstra.h"
#include "navbar.h"
#include "navfram.h"
#include "usertlbr.h"
#include "dropmenu.h"
#include "rdfliner.h"
#include "htrdf.h"
#include "xp_ncent.h"
// The Nav Center vocab element
extern "C" RDF_NCVocab gNavCenter;
extern void DrawUpButton(HDC dc, CRect& rect);
BEGIN_MESSAGE_MAP(CNavTitleBar, CWnd)
//{{AFX_MSG_MAP(CNavTitleBar)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code !
ON_WM_CREATE()
ON_WM_SIZE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP ( )
ON_WM_MOUSEMOVE()
ON_WM_PAINT()
ON_WM_TIMER()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CNavTitleBar::CNavTitleBar()
:m_bHasFocus(FALSE), m_bDrawCloseFrame(FALSE), m_bDrawModeFrame(FALSE), m_bDrawAddFrame(FALSE)
{
m_pBackgroundImage = NULL;
m_View = NULL;
m_hFocusTimer = 0;
}
CNavTitleBar::~CNavTitleBar()
{
}
void CNavTitleBar::OnPaint( )
{
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
// Read in all the properties
if (!m_View) return;
HT_Resource topNode = HT_TopNode(m_View);
void* data;
PRBool foundData = FALSE;
m_ForegroundColor = RGB(0,0,0);
m_BackgroundColor = RGB(192,192,192);
m_BackgroundImageURL = "";
m_ControlStripForegroundColor = RGB(255,255,255);
m_ControlStripBackgroundColor = RGB(64,64,64);
m_ControlStripBackgroundImageURL = "";
// Control strip colors
// Foreground color
HT_GetTemplateData(topNode, gNavCenter->controlStripFGColor, HT_COLUMN_STRING, &data);
if (data)
WFE_ParseColor((char*)data, &m_ControlStripForegroundColor);
// background color
HT_GetTemplateData(topNode, gNavCenter->controlStripBGColor, HT_COLUMN_STRING, &data);
if (data)
WFE_ParseColor((char*)data, &m_ControlStripBackgroundColor);
// Background image URL
HT_GetTemplateData(topNode, gNavCenter->controlStripBGURL, HT_COLUMN_STRING, &data);
if (data)
m_ControlStripBackgroundImageURL = (char*)data;
m_pControlStripBackgroundImage = NULL; // Clear out the BG image.
// Main Title strip colors
// Foreground color
HT_GetTemplateData(topNode, gNavCenter->titleBarFGColor, HT_COLUMN_STRING, &data);
if (data)
WFE_ParseColor((char*)data, &m_ForegroundColor);
// background color
HT_GetTemplateData(topNode, gNavCenter->titleBarBGColor, HT_COLUMN_STRING, &data);
if (data)
WFE_ParseColor((char*)data, &m_BackgroundColor);
// Background image URL
HT_GetTemplateData(topNode, gNavCenter->titleBarBGURL, HT_COLUMN_STRING, &data);
if (data)
m_BackgroundImageURL = (char*)data;
m_pBackgroundImage = NULL; // Clear out the BG image.
HPALETTE pOldPalette = NULL;
if (sysInfo.m_iBitsPerPixel < 16 && (::GetDeviceCaps(dc.m_hDC, RASTERCAPS) & RC_PALETTE))
{
// Use the palette, since we have less than 16 bits per pixel and are
// using a palette-based device.
HPALETTE hPalette = WFE_GetUIPalette(GetParentFrame());
::SelectPalette(dc.m_hDC, hPalette, FALSE);
// Find the nearest match in our palette for our colors.
ResolveToPaletteColor(m_BackgroundColor, hPalette);
ResolveToPaletteColor(m_ForegroundColor, hPalette);
ResolveToPaletteColor(m_ControlStripBackgroundColor, hPalette);
ResolveToPaletteColor(m_ControlStripForegroundColor, hPalette);
}
CRect controlStripRect(rect);
CRect titleBarRect(rect);
int navBarTotalHeight = 0;
int navBarControlStripHeight = 0;
int navBarTitleBarHeight = 0;
HT_GetTemplateData(topNode, gNavCenter->showTitleBar, HT_COLUMN_STRING, &data);
if (data)
{
CString answer((char*)data);
if (answer.GetLength() > 0 && (answer.GetAt(0) == 'Y' || answer.GetAt(0) == 'y'))
{
navBarTotalHeight += NAVBAR_TITLEBAR_HEIGHT;
navBarTitleBarHeight += NAVBAR_TITLEBAR_HEIGHT;
}
}
// Whether or not to show the control strip.
HT_GetTemplateData(topNode, gNavCenter->showControlStrip, HT_COLUMN_STRING, &data);
if (data)
{
CString answer((char*)data);
if (answer.GetLength() > 0 && (answer.GetAt(0) == 'Y' || answer.GetAt(0) == 'y'))
{
navBarTotalHeight += NAVBAR_CONTROLSTRIP_HEIGHT;
navBarControlStripHeight = NAVBAR_CONTROLSTRIP_HEIGHT;
}
}
controlStripRect.top = navBarTitleBarHeight;
controlStripRect.bottom = navBarTotalHeight;
titleBarRect.top = 0;
titleBarRect.bottom = controlStripRect.top;
CBrush faceBrush(m_BackgroundColor);
if (m_BackgroundImageURL != "")
{
// There's a background that needs to be drawn.
m_pBackgroundImage = LookupImage(m_BackgroundImageURL, NULL);
}
if (m_pBackgroundImage && m_pBackgroundImage->FrameSuccessfullyLoaded())
{
// Draw the strip of the background image that should be placed
// underneath this line.
PaintBackground(dc.m_hDC, titleBarRect, m_pBackgroundImage);
}
else
{
dc.FillRect(&titleBarRect, &faceBrush);
}
CBrush controlStripFaceBrush(m_ControlStripBackgroundColor);
if (m_ControlStripBackgroundImageURL != "")
{
// There's a background that needs to be drawn.
m_pControlStripBackgroundImage = LookupImage(m_ControlStripBackgroundImageURL, NULL);
}
if (m_pControlStripBackgroundImage && m_pControlStripBackgroundImage->FrameSuccessfullyLoaded())
{
// Draw the strip of the background image that should be placed
// underneath this line.
PaintBackground(dc.m_hDC, controlStripRect, m_pControlStripBackgroundImage);
}
else
{
dc.FillRect(&controlStripRect, &controlStripFaceBrush);
}
if (navBarTitleBarHeight > 0)
{
// Draw the title strip text.
CString titleText(HT_GetNodeName(HT_TopNode(m_View)));
CFont arialFont;
LOGFONT lf;
XP_MEMSET(&lf,0,sizeof(LOGFONT));
lf.lfHeight = 120;
lf.lfWeight = 700;
strcpy(lf.lfFaceName, "Arial");
arialFont.CreatePointFontIndirect(&lf, &dc);
HFONT font = (HFONT)arialFont.GetSafeHandle();
HFONT hOldFont = (HFONT)::SelectObject(dc.m_hDC, font);
CRect sizeRect(titleBarRect);
int height = CIntlWin::DrawText(CS_UTF8, dc.m_hDC, titleText.GetBuffer(0), titleText.GetLength(), &sizeRect, DT_CALCRECT | DT_WORDBREAK);
if (sizeRect.Width() > rect.Width() - 9)
{
// Don't write into the close box area!
sizeRect.right = sizeRect.left + (rect.Width() - 9);
}
sizeRect.left += 4; // indent slightly horizontally
sizeRect.right += 4;
// Center the text vertically.
sizeRect.top = (titleBarRect.Height() - height) / 2;
sizeRect.bottom = sizeRect.top + height;
// Draw the text
int nOldBkMode = dc.SetBkMode(TRANSPARENT);
UINT nFormat = DT_SINGLELINE | DT_VCENTER | DT_EXTERNALLEADING;
COLORREF oldColor;
oldColor = dc.SetTextColor(m_ForegroundColor);
CIntlWin::DrawText(CS_UTF8, dc.m_hDC, titleText.GetBuffer(0), -1, &sizeRect, nFormat);
dc.SetTextColor(oldColor);
dc.SetBkMode(nOldBkMode);
::SelectObject(dc.m_hDC, hOldFont);
}
if (navBarControlStripHeight > 0)
{
// Draw the control strip text.
CFont smallArialFont;
LOGFONT lf2;
XP_MEMSET(&lf2,0,sizeof(LOGFONT));
lf2.lfHeight = 90;
lf2.lfWeight = 400;
strcpy(lf2.lfFaceName, "Arial");
smallArialFont.CreatePointFontIndirect(&lf2, &dc);
HFONT smallFont = (HFONT)smallArialFont.GetSafeHandle();
HFONT hOldFont = (HFONT)::SelectObject(dc.m_hDC, smallFont);
// The ADD button
CString addText("Add Page"); // Will use an extensible HT mechanism eventually. Hardcode for now.
//HT_GetTemplateData(topNode, gNavCenter->controlStripModeText, HT_COLUMN_STRING, &data);
//if (data)
// modeText = (char*)data;
CRect addRect(controlStripRect);
int smallHeight = CIntlWin::DrawText(CS_UTF8, dc.m_hDC, addText.GetBuffer(0), addText.GetLength(), &addRect, DT_CALCRECT | DT_WORDBREAK);
if (addRect.Width() > rect.Width() - 9)
{
// Don't write into the close box area!
addRect.right = addRect.left + (rect.Width() - 9);
}
addRect.left += 4; // indent slightly horizontally
addRect.right += 4;
// Center the text vertically.
addRect.top = controlStripRect.top + (controlStripRect.Height() - smallHeight) / 2;
addRect.bottom = addRect.top + smallHeight;
// Cache the rect
cachedAddRect.top = controlStripRect.top;
cachedAddRect.left = 0;
cachedAddRect.bottom = controlStripRect.bottom;
cachedAddRect.right = addRect.right + 3;
// The MANAGE button
CString modeText("Edit Bookmarks"); // Will use an extensible HT mechanism eventually. Hardcode for now.
//HT_GetTemplateData(topNode, gNavCenter->controlStripModeText, HT_COLUMN_STRING, &data);
//if (data)
// modeText = (char*)data;
CRect modeRect(controlStripRect);
smallHeight = CIntlWin::DrawText(CS_UTF8,dc.m_hDC, modeText.GetBuffer(0), modeText.GetLength(), &modeRect, DT_CALCRECT | DT_WORDBREAK);
if (modeRect.Width() > rect.Width() - 9)
{
// Don't write into the close box area!
modeRect.right = modeRect.left + (rect.Width() - 9);
}
modeRect.left += cachedAddRect.right + 10; // account for add rect and indent slightly horizontally
modeRect.right += cachedAddRect.right + 10;
// Center the text vertically.
modeRect.top = addRect.top;
modeRect.bottom = addRect.bottom;
modeRect.right += 4;
// Cache the rect
cachedModeRect.top = controlStripRect.top;
cachedModeRect.left = cachedAddRect.right + 6;
cachedModeRect.bottom = controlStripRect.bottom;
cachedModeRect.right = cachedModeRect.left + modeRect.Width() + 3;
CString closeText("Close");
HT_GetTemplateData(topNode, gNavCenter->controlStripCloseText, HT_COLUMN_STRING, &data);
if (data)
closeText = (char*)data;
CRect closeRect(controlStripRect);
CIntlWin::DrawText(CS_UTF8, dc.m_hDC, closeText.GetBuffer(0), closeText.GetLength(), &closeRect, DT_CALCRECT | DT_WORDBREAK);
int closeWidth = closeRect.Width();
closeRect.right = rect.right - 4;
closeRect.left = closeRect.right - closeWidth;
// Center the text vertically.
closeRect.top = modeRect.top;
closeRect.bottom = modeRect.bottom;
CRect arrowRect;
arrowRect.top = controlStripRect.top;
arrowRect.left = closeRect.left - 12;
arrowRect.right = arrowRect.left + 12;
arrowRect.bottom = controlStripRect.bottom;
// Cache the rect
cachedCloseRect.top = controlStripRect.top;
cachedCloseRect.left = arrowRect.left;
cachedCloseRect.bottom = controlStripRect.bottom;
cachedCloseRect.right = closeRect.right + 3;
// Now compute the close box rect.
HT_Pane pane = HT_GetPane(HT_GetView(topNode));
if (HT_GetWindowType(pane) == HT_STANDALONE_WINDOW ||
HT_GetWindowType(pane) == HT_EMBEDDED_WINDOW)
{
// Don't allow the close box to exist.
cachedCloseRect.SetRect(0,0,0,0);
closeRect.SetRect(0,0,0,0);
arrowRect.SetRect(0,0,0,0);
}
if (HT_GetWindowType(pane) != HT_STANDALONE_WINDOW &&
HT_GetWindowType(pane) != HT_EMBEDDED_WINDOW)
DrawArrow(dc.m_hDC, m_ControlStripForegroundColor, LEFT_ARROW, arrowRect, TRUE);
// Draw the text
int nOldBkMode = dc.SetBkMode(TRANSPARENT);
int oldColor = dc.SetTextColor(m_ControlStripForegroundColor);
UINT nFormat = DT_SINGLELINE | DT_VCENTER | DT_EXTERNALLEADING;
if (HT_GetWindowType(pane) != HT_STANDALONE_WINDOW &&
HT_GetWindowType(pane) != HT_EMBEDDED_WINDOW)
CIntlWin::DrawText(CS_UTF8, dc.m_hDC, closeText.GetBuffer(0), -1, &closeRect, nFormat);
CIntlWin::DrawText(CS_UTF8, dc.m_hDC, modeText.GetBuffer(0), -1, &modeRect, nFormat);
CIntlWin::DrawText(CS_UTF8, dc.m_hDC, addText.GetBuffer(0), -1, &addRect, nFormat);
// See if we're supposed to draw a framing rect.
CBrush controlBrush(m_ControlStripForegroundColor);
if (m_bDrawCloseFrame)
{
dc.FrameRect(cachedCloseRect, &controlBrush);
}
if (m_bDrawModeFrame)
{
dc.FrameRect(cachedModeRect, &controlBrush);
}
if (m_bDrawAddFrame)
{
dc.FrameRect(cachedAddRect, &controlBrush);
}
dc.SetTextColor(oldColor);
dc.SetBkMode(nOldBkMode);
::SelectObject(dc.m_hDC, hOldFont);
}
}
int CNavTitleBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
return 0;
}
void CNavTitleBar::OnLButtonDown (UINT nFlags, CPoint point )
{
// Called when the user clicks on us.
m_PointHit = point;
CFrameWnd* pFrameWnd = GetParentFrame();
if (pFrameWnd->IsKindOf(RUNTIME_CLASS(CNSNavFrame)))
SetCapture();
}
void CNavTitleBar::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
CNSNavFrame* navFrameParent = (CNSNavFrame*)GetParentFrame();
if (abs(point.x - m_PointHit.x) > 3 ||
abs(point.y - m_PointHit.y) > 3)
{
ReleaseCapture();
// Start a drag
CRDFOutliner* pOutliner = (CRDFOutliner*)HT_GetViewFEData(m_View);
MapWindowPoints(navFrameParent, &point, 1);
navFrameParent->StartDrag(point);
}
}
else
{
BOOL oldCloseFrame = m_bDrawCloseFrame;
BOOL oldModeFrame = m_bDrawModeFrame;
BOOL oldAddFrame = m_bDrawAddFrame;
m_bDrawCloseFrame = FALSE;
m_bDrawModeFrame = FALSE;
m_bDrawAddFrame = FALSE;
if (cachedCloseRect.PtInRect(point))
{
m_bDrawCloseFrame = TRUE;
m_hFocusTimer = SetTimer(IDT_STRIPFOCUS, STRIPFOCUS_DELAY_MS, NULL);
}
else if (cachedModeRect.PtInRect(point))
{
m_bDrawModeFrame = TRUE;
m_hFocusTimer = SetTimer(IDT_STRIPFOCUS, STRIPFOCUS_DELAY_MS, NULL);
}
else if (cachedAddRect.PtInRect(point))
{
m_bDrawAddFrame = TRUE;
m_hFocusTimer = SetTimer(IDT_STRIPFOCUS, STRIPFOCUS_DELAY_MS, NULL);
}
if (oldCloseFrame != m_bDrawCloseFrame)
InvalidateRect(cachedCloseRect);
if (oldModeFrame != m_bDrawModeFrame)
InvalidateRect(cachedModeRect);
if (oldAddFrame != m_bDrawAddFrame)
InvalidateRect(cachedAddRect);
}
}
void CNavTitleBar::OnLButtonUp(UINT nFlags, CPoint point)
{
if (GetCapture() == this)
{
ReleaseCapture();
}
if (cachedCloseRect.PtInRect(point))
{
// Destroy the window.
CFrameWnd* pFrameWnd = GetParentFrame();
if (pFrameWnd->IsKindOf(RUNTIME_CLASS(CNSNavFrame)))
((CNSNavFrame*)pFrameWnd)->DeleteNavCenter();
}
else if (cachedModeRect.PtInRect(point))
{
//CRDFOutliner* pOutliner = (CRDFOutliner*)HT_GetViewFEData(m_View);
//HT_ToggleTreeMode(m_View);
CFrameWnd* pFrameWnd = GetParentFrame();
if (pFrameWnd->IsKindOf(RUNTIME_CLASS(CNSNavFrame)))
{
CNSNavFrame* pNavFrame = (CNSNavFrame*)pFrameWnd;
CRDFOutliner* pOutliner = (CRDFOutliner*)
(pNavFrame->GetContentView()->GetOutlinerParent()->GetOutliner());
pOutliner->SetIsPopup(FALSE);
pNavFrame->UnhookFromButton();
pNavFrame->ForceFloat(TRUE);
}
}
else if (cachedAddRect.PtInRect(point))
{
CGenericFrame* pFrame = (CGenericFrame*)FEU_GetLastActiveFrame(MWContextBrowser);
if (pFrame)
{
CAbstractCX* pAbstract = pFrame->GetMainContext();
MWContext* mwContext = pAbstract->GetContext();
History_entry *pHistEnt = SHIST_GetCurrent( &(mwContext->hist) );
if (pHistEnt)
{
HT_AddToContainer( HT_TopNode(m_View), pHistEnt->address, mwContext->title );
}
}
}
}
void CNavTitleBar::OnSize( UINT nType, int cx, int cy )
{
}
void CNavTitleBar::SetHTView(HT_View view)
{
m_View = view;
Invalidate();
}
void CNavTitleBar::OnTimer(UINT nIDEvent)
{
if (nIDEvent == IDT_STRIPFOCUS)
{
POINT point;
KillTimer(IDT_STRIPFOCUS);
m_hFocusTimer = 0;
GetCursorPos(&point);
CRect rcClient;
GetWindowRect(&rcClient);
if (!rcClient.PtInRect(point))
{
m_bDrawCloseFrame = FALSE;
m_bDrawModeFrame = FALSE;
m_bDrawAddFrame = FALSE;
Invalidate();
UpdateWindow();
}
else
m_hFocusTimer = SetTimer(IDT_STRIPFOCUS, STRIPFOCUS_DELAY_MS, NULL);
}
CWnd::OnTimer(nIDEvent);
}
int CNavTitleBar::GetHeightBasedOnProperties()
{
if (!m_View)
return 0;
HT_Resource topNode = HT_TopNode(m_View);
void* data;
PRBool foundData = FALSE;
// Whether or not to show the title bar.
int height = 0;
HT_GetTemplateData(topNode, gNavCenter->showTitleBar, HT_COLUMN_STRING, &data);
if (data)
{
CString answer((char*)data);
if (answer.GetLength() > 0 && (answer.GetAt(0) == 'Y' || answer.GetAt(0) == 'y'))
height += NAVBAR_TITLEBAR_HEIGHT;
}
// Whether or not to show the control strip.
HT_GetTemplateData(topNode, gNavCenter->showControlStrip, HT_COLUMN_STRING, &data);
if (data)
{
CString answer((char*)data);
if (answer.GetLength() > 0 && (answer.GetAt(0) == 'Y' || answer.GetAt(0) == 'y'))
height += NAVBAR_CONTROLSTRIP_HEIGHT;
}
return height;
}