pjs/cmd/winfe/frameglu.cpp

591 строка
17 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.
*/
#include "stdafx.h"
#include "secnav.h"
#include "frameglu.h"
#include "mainfrm.h"
#include "ipframe.h"
#include "prefapi.h"
// Our active frame stack.
CPtrList CFrameGlue::m_cplActiveFrameStack;
// A way to correctly get the frame glue out of a frame at run time though
// the class derivations and casting are not right....
CFrameGlue *CFrameGlue::GetFrameGlue(CFrameWnd *pFrame) {
// Use IsKindOf to determine the frame's class type.
// From there, we can correctly cast the frame window pointer, and
// further cast to the abstract base class of CFrameGlue.
CFrameGlue *pRetval = NULL;
if(pFrame->IsKindOf(RUNTIME_CLASS(CGenericFrame))) {
pRetval = (CFrameGlue *)((CGenericFrame *)pFrame);
}
else if(pFrame->IsKindOf(RUNTIME_CLASS(CInPlaceFrame))) {
pRetval = (CFrameGlue *)((CInPlaceFrame *)pFrame);
}
#ifdef DEBUG
if(pRetval == NULL) {
// If you got here, either you need to add appropriate casting statements
// in the above if to resolve the CFrameGlue, or you have found a bug.
TRACE("Invalid frame window has no frame glue!\n");
// ASSERT(0);
}
#endif // DEBUG
return(pRetval);
}
CFrameGlue::CFrameGlue() {
m_pActiveContext = NULL;
m_pMainContext = NULL;
m_bCanRestoreState = FALSE;
m_iCSID = theApp.m_iCSID;
m_pChrome = NULL;
// location bar
// note I just changed this from 1.0 version to be more appropriate chouck 24-jan-95
XP_Bool bBar;
PREF_GetBoolPref("browser.chrome.show_url_bar",&bBar);
m_bLocationBar = bBar;
// show the starter buttons?
PREF_GetBoolPref("browser.chrome.show_directory_buttons",&bBar);
m_bStarter = bBar;
PREF_GetBoolPref("browser.chrome.show_toolbar",&bBar);
m_bShowToolbar = bBar;
// No find replace dialog yet.
m_pFindReplace = NULL;
m_pClipChildMap = NULL;
m_isBackgroundPalette = FALSE;
}
CFrameGlue::~CFrameGlue() {
// Take all entries of this frame in the active frame stack out.
POSITION pos;
while( pos = m_cplActiveFrameStack.Find( (LPVOID) this ) ){
m_cplActiveFrameStack.RemoveAt( pos );
}
// When the frame goes down, let the window context know.
if(GetMainWinContext()) {
GetMainWinContext()->ClearFrame();
}
if( m_pClipChildMap != NULL ) {
m_pClipChildMap->RemoveAll();
delete m_pClipChildMap;
m_pClipChildMap = NULL;
}
}
// Generic way to get a frame out of the context.
CFrameGlue *GetFrame(MWContext *pContext)
{
CFrameGlue *pRetval = NULL;
if(pContext != NULL) {
if(ABSTRACTCX(pContext) && ABSTRACTCX(pContext)->IsFrameContext()) {
pRetval = ABSTRACTCX(pContext)->GetFrame();
}
}
return(pRetval);
}
CAbstractCX *CFrameGlue::GetMainContext() const
{
return(m_pMainContext);
}
CAbstractCX *CFrameGlue::GetActiveContext() const
{
return(m_pActiveContext);
}
CWinCX *CFrameGlue::GetMainWinContext() const
{
if (m_pMainContext && m_pMainContext->IsFrameContext()) {
return((CWinCX *) m_pMainContext);
}
return NULL;
}
CWinCX *CFrameGlue::GetActiveWinContext() const
{
if (m_pActiveContext && m_pActiveContext->IsFrameContext()) {
return((CWinCX *) m_pActiveContext);
}
return NULL;
}
void CFrameGlue::SetMainContext(CAbstractCX *pContext) {
m_pMainContext = pContext;
}
CPtrList CFrameGlue::m_cplActiveContextCBList;
void CFrameGlue::SetActiveContext(CAbstractCX *pContext)
{
m_pActiveContext = pContext;
POSITION rIndex = m_cplActiveContextCBList.GetHeadPosition();
while(rIndex != NULL) {
ActiveContextCB cb = (ActiveContextCB)m_cplActiveContextCBList.GetNext(rIndex);
(cb)(this, pContext);
}
}
void CFrameGlue::AddActiveContextCB(ActiveContextCB cb)
{
m_cplActiveContextCBList.AddTail((LPVOID)cb);
}
void CFrameGlue::RemoveActiveContextCB(ActiveContextCB cb)
{
POSITION rIndex = m_cplActiveContextCBList.Find((LPVOID)cb);
if(rIndex) {
m_cplActiveContextCBList.RemoveAt(rIndex);
}
}
// Override to test if frame is an editor
BOOL CFrameGlue::IsEditFrame()
{
return(FALSE);
}
CPtrList CFrameGlue::m_cplActiveNotifyCBList;
// Add to the top of the stack of active frames.
void CFrameGlue::SetAsActiveFrame()
{
POSITION rIndex = m_cplActiveNotifyCBList.GetHeadPosition();
while(rIndex != NULL) {
ActiveNotifyCB cb = (ActiveNotifyCB) m_cplActiveNotifyCBList.GetNext(rIndex);
(cb)(this);
}
POSITION pos = m_cplActiveFrameStack.Find( (LPVOID) this );
if (pos) {
m_cplActiveFrameStack.RemoveAt( pos );
}
TRY {
m_cplActiveFrameStack.AddHead((void *)this);
}
CATCH(CException, e) {
// didn't work, Silently fail...
ASSERT(0);
}
END_CATCH
}
void CFrameGlue::AddActiveNotifyCB( ActiveNotifyCB cb )
{
m_cplActiveNotifyCBList.AddTail( (LPVOID) cb );
}
void CFrameGlue::RemoveActiveNotifyCB( ActiveNotifyCB cb )
{
POSITION rIndex = m_cplActiveNotifyCBList.Find( (LPVOID) cb );
if (rIndex) {
m_cplActiveNotifyCBList.RemoveAt( rIndex );
}
}
// Find a browser window in the active stack, only use cxType types.
// Default is to NOT find editor windows when cxType = MWContextBrowser
CFrameGlue *CFrameGlue::GetLastActiveFrame(MWContextType cxType, int nFindEditor)
{
CFrameGlue *pRetval = NULL;
// Loop through all active frames.
POSITION rIndex = m_cplActiveFrameStack.GetHeadPosition();
while(rIndex != NULL) {
pRetval = (CFrameGlue *)m_cplActiveFrameStack.GetNext(rIndex);
// See if we can get the type from the context, and verify the type.
if(pRetval->GetMainContext() != NULL) {
MWContextType cxRetType = pRetval->GetMainContext()->GetContext()->type;
if(cxType == MWContextAny || cxRetType == cxType) {
// If looking for only Browser, skip an editor frame
if (cxType == MWContextBrowser){
BOOL bIsEditor = EDT_IS_EDITOR(pRetval->GetMainContext()->GetContext());
if((nFindEditor == FEU_FINDBROWSERONLY && bIsEditor) ||
(nFindEditor == FEU_FINDEDITORONLY && !bIsEditor)) {
// Failed the check. clear retval.
pRetval = NULL;
continue;
}
}
// Don't allow Netcaster either
if (pRetval->GetMainContext()->GetContext() == theApp.m_pNetcasterWindow
|| (pRetval->GetMainContext()->GetContext()->name && (XP_STRCASECMP(pRetval->GetMainContext()->GetContext()->name,"Netscape_Netcaster_Drawer") == 0))) {
pRetval = NULL;
continue;
}
// Found one.
break;
}
}
// Failed the check. clear retval.
pRetval = NULL;
}
return(pRetval);
}
CFrameGlue *CFrameGlue::GetLastActiveFrameByCustToolbarType(CString custToolbar, CFrameWnd *pCurrentFrame, BOOL bUseSaveInfo)
{
CFrameGlue *pRetval = NULL;
// Loop through all active frames.
POSITION rIndex = m_cplActiveFrameStack.GetHeadPosition();
while(rIndex != NULL) {
pRetval = (CFrameGlue *)m_cplActiveFrameStack.GetNext(rIndex);
// if it's the current frame, then keep looking because we want the one before it.
if(pRetval->GetFrameWnd() == pCurrentFrame) {
pRetval = NULL;
continue;
}
// See if we share the same custtoolbar string.
if((pRetval->m_pChrome) && (pRetval->m_pChrome->GetCustToolbarString() == custToolbar)){
if(bUseSaveInfo){
// if customizable toolbar saves its prefs, then break
// this is used to ignore windows like View Page Source and View Page Info
if(pRetval->m_pChrome->GetCustomizableToolbar()->GetSaveToolbarInfo())
break;
}
else
break;
}
// Failed the check. clear retval.
pRetval = NULL;
}
return(pRetval);
}
CFrameGlue *CFrameGlue::GetBottomFrame(MWContextType cxType, int nFindEditor)
{
CFrameGlue *pRetval = NULL;
// Loop through all active frames until we reach the bottom.
POSITION rIndex = m_cplActiveFrameStack.GetTailPosition();
while(rIndex != NULL) {
pRetval = (CFrameGlue *)m_cplActiveFrameStack.GetPrev(rIndex);
// See if we can get the type from the context, and verify the type.
if(pRetval->GetMainContext() != NULL) {
MWContextType cxRetType = pRetval->GetMainContext()->GetContext()->type;
if(cxType == MWContextAny || cxRetType == cxType) {
// If looking for only Browser, skip an editor frame
if (cxType == MWContextBrowser){
BOOL bIsEditor = EDT_IS_EDITOR(pRetval->GetMainContext()->GetContext());
if((nFindEditor == FEU_FINDBROWSERONLY && bIsEditor) ||
(nFindEditor == FEU_FINDEDITORONLY && !bIsEditor)) {
// Failed the check. clear retval.
continue;
}
}
// Found one
break;
}
}
}
return(pRetval);
}
// Find the number of active frames of type cxType
int CFrameGlue::GetNumActiveFrames(MWContextType cxType, int nFindEditor)
{
int nCount = 0;
CFrameGlue *pRetval = NULL;
// Loop through all active frames.
POSITION rIndex = m_cplActiveFrameStack.GetHeadPosition();
while(rIndex != NULL) {
pRetval = (CFrameGlue *)m_cplActiveFrameStack.GetNext(rIndex);
// See if we can get the type from the context, and verify the type.
if(pRetval->GetMainContext() != NULL) {
MWContextType cxRetType = pRetval->GetMainContext()->GetContext()->type;
if(cxType == MWContextAny || cxRetType == cxType) {
// If looking for only Browser, skip an editor frame
if (cxType == MWContextBrowser){
BOOL bIsEditor = EDT_IS_EDITOR(pRetval->GetMainContext()->GetContext());
if((nFindEditor == FEU_FINDBROWSERONLY && bIsEditor) ||
(nFindEditor == FEU_FINDEDITORONLY && !bIsEditor)) {
continue;
}
}
// Found one so increase count.
nCount++;
}
}
}
return(nCount);
}
// Find a browser window by context ID....
CFrameGlue *CFrameGlue::FindFrameByID(DWORD dwID, MWContextType cxType)
{
CFrameGlue *pRetval = NULL;
// Must have a context first.
CAbstractCX *pCX = CAbstractCX::FindContextByID(dwID);
if(pCX != NULL) {
// Must be a window context.
if(pCX->IsFrameContext() == TRUE) {
// Make sure the context is of the correct type.
if(cxType == MWContextAny || cxType == pCX->GetContext()->type) {
pRetval = VOID2CX(pCX, CAbstractCX)->GetFrame();
}
}
}
return(pRetval);
}
// Common command handler for all frames.
// Call in your OnCommand derivation.
BOOL CFrameGlue::CommonCommand(UINT wParam, LONG lParam) {
UINT nID = LOWORD(wParam);
if (IS_PLACESMENU_ID(nID) || IS_HELPMENU_ID(nID)) {
char * url = NULL;
if (IS_PLACESMENU_ID(nID))
PREF_CopyIndexConfigString("menu.places.item",CASTINT(nID-FIRST_PLACES_MENU_ID),"url",&url);
else
PREF_CopyIndexConfigString("menu.help.item",CASTINT(nID-FIRST_HELP_MENU_ID),"url",&url);
if (!url) return FALSE;
if(!GetMainContext())
return(FALSE);
// if we are a browser window and NOT an editor just load it locally
if(GetMainContext()->GetContext()->type == MWContextBrowser &&
!EDT_IS_EDITOR(GetMainContext()->GetContext()) ){
GetMainContext()->NormalGetUrl(url);
return(TRUE);
}
// look for a browser window we can load into
CFrameGlue *pFrameGlue = CFrameGlue::GetLastActiveFrame(MWContextBrowser);
if(pFrameGlue != NULL && pFrameGlue->GetMainContext() != NULL) {
CAbstractCX * pCX = pFrameGlue->GetMainContext();
if (pCX != NULL) {
CFrameWnd * pWnd = pFrameGlue->GetFrameWnd();
if (pWnd->IsIconic())
pWnd->ShowWindow(SW_RESTORE);
pWnd->BringWindowToTop();
pCX->NormalGetUrl(url);
}
// pFrameGlue->GetMainContext()->NormalGetUrl(szLoadString(nID + LOAD_URL_COUNT));
return(TRUE);
}
// if we got here we must not have found a viable window --- create a new one
MWContext * pContext = CFE_CreateNewDocWindow(NULL, NULL);
ABSTRACTCX(pContext)->NormalGetUrl(url);
XP_FREE(url);
return(TRUE);
} else if ( nID == ID_SECURITY_ADVISOR ) {
CAbstractCX *pCX = GetMainContext();
if (pCX != NULL)
{
MWContext * pContext = pCX->GetContext();
if (pContext != NULL)
{
URL_Struct * pURL = pCX->CreateUrlFromHist(TRUE);
SECNAV_SecurityAdvisor(pContext, pURL);
}
}
}
return(FALSE);
}
#define CLIP_BIT 0x80000000L
#define GET_CLIP_BIT(x) ( (DWORD)(x) & CLIP_BIT )
#define CLIP_COUNT(x) ( (DWORD)(x) & 0x0000FFFFL )
void CFrameGlue::ClipChildren(CWnd *pWnd, BOOL bSet)
{
// ASSERT( GetFrameWnd()->IsChild(pWnd) );
#ifdef _DEBUG
if (GetFrameWnd() && !GetFrameWnd()->IsChild(pWnd))
TRACE("pWnd is not a child of this frame\n");
#endif
// If the child window hash table does not exist, then create one
if( m_pClipChildMap == NULL ) {
m_pClipChildMap = new CMapPtrToPtr();
}
//
// For every window in the hierarchy between pWnd and the top level
// frame, set or clear its WS_CLIPCHILDREN style bit.
//
while( (pWnd = pWnd->GetParent()) != NULL ) {
DWORD dwStyle;
void *item = 0;
void *key = (void*)pWnd->m_hWnd;
dwStyle = ::GetWindowLong(pWnd->m_hWnd, GWL_STYLE);
// Add the window to the map if necessary...
if( m_pClipChildMap->Lookup(key, item) == FALSE && bSet ) {
item = (void *)((dwStyle & WS_CLIPCHILDREN) ? CLIP_BIT : 0L);
m_pClipChildMap->SetAt(key, item);
}
// Setting the WS_CLIPCHILDREN bit...
if( bSet ) {
// Set the style the first time...
if( CLIP_COUNT(item) == 0 ) {
::SetWindowLong(pWnd->m_hWnd, GWL_STYLE,(dwStyle|WS_CLIPCHILDREN));
}
// Increment the count and save the new state...
item = (void *) (((DWORD)item) + 1);
m_pClipChildMap->SetAt(key, item);
}
// Clearing the WS_CLIPCHILDREN bit...
else if (CLIP_COUNT(item)) {
// Decrement the count...
item = (void *) (((DWORD)item) - 1);
// Restore the window to its original state and remove it
// from the map.
if( CLIP_COUNT(item) == 0 ) {
if( GET_CLIP_BIT(item) == 0 ) {
::SetWindowLong(pWnd->m_hWnd, GWL_STYLE,
(dwStyle & ~WS_CLIPCHILDREN) );
}
m_pClipChildMap->RemoveKey(key);
}
// Save the new state...
else {
m_pClipChildMap->SetAt(key, item);
}
}
}
}
BOOL CFrameGlue::RealizePalette(CWnd *pWnd, HWND hFocusWnd,BOOL background)
{
CWinCX *pWinCX = GetMainWinContext();
HDC hdc = pWinCX->GetContextDC();
if (hdc) {
::SelectPalette(hdc, pWinCX->GetPalette(), background);
int colorRealized = ::RealizePalette(hdc);
int lCount = XP_ListCount(pWinCX->GetContext()->grid_children);
if (lCount) {
// Go through each child.
MWContext *pChild;
XP_List *pTraverse = pWinCX->GetContext()->grid_children;
while (pChild = (MWContext *)XP_ListNextObject(pTraverse)) {
ASSERT(ABSTRACTCX(pChild)->IsWindowContext());
::InvalidateRect(PANECX(pChild)->GetPane(), NULL, TRUE);
::UpdateWindow(PANECX(pChild)->GetPane());
}
}
SetIsBackgroundPalette(background);
::InvalidateRect(pWinCX->GetPane(), NULL, TRUE);
::UpdateWindow(pWinCX->GetPane());
#ifdef MOZ_TASKBAR
if(theApp.GetTaskBarMgr().IsInitialized() && theApp.GetTaskBarMgr().IsFloating())
theApp.GetTaskBarMgr().ChangeTaskBarsPalette(hFocusWnd);
#endif /* MOZ_TASKBAR */
pWnd->SendMessageToDescendants(WM_PALETTECHANGED, (WPARAM)hFocusWnd);
return (colorRealized > 0) ? TRUE : FALSE;
}
else return FALSE;
}
void CFrameGlue::ClearContext(CAbstractCX *pGone) {
// Clear out the appropriate context
// fields, if set.
// Can't have an active without a main.
if(GetMainContext() == pGone) {
SetActiveContext(NULL);
SetMainContext(NULL);
}
else if(GetActiveContext() == pGone) {
SetActiveContext(NULL);
}
else if(pGone && pGone->IsGridParent()) {
// Need to see if pGone is a parent of the active context.
// If so, we need to clear our active context as the child
// context won't be able to look us up to call this
// function due to the recursive implemenation of
// CWinCX::GetFrame() which it uses to make this call
MWContext *pChild;
XP_List *pTraverse = pGone->GetContext()->grid_children;
while((pChild = (MWContext*)XP_ListNextObject(pTraverse))) {
ClearContext(ABSTRACTCX(pChild));
}
}
}
// NULL frame implementation, for CFrameGlue when there is no frame.
CFrameWnd *CNullFrame::GetFrameWnd() {
return(NULL);
}
void CNullFrame::UpdateHistoryDialog() {
}
CAbstractCX *CNullFrame::GetMainContext() const {
return(NULL);
}
CAbstractCX *CNullFrame::GetActiveContext() const {
return(NULL);
}