www.pudn.com > pueblo.zip > ChMenu.cpp


/*---------------------------------------------------------------------------- 
                        _                              _ _        
        /\             | |                            | (_)       
       /  \   _ __   __| |_ __ ___  _ __ ___   ___  __| |_  __ _  
      / /\ \ | '_ \ / _` | '__/ _ \| '_ ` _ \ / _ \/ _` | |/ _` | 
     / ____ \| | | | (_| | | | (_) | | | | | |  __/ (_| | | (_| | 
    /_/    \_\_| |_|\__,_|_|  \___/|_| |_| |_|\___|\__,_|_|\__,_| 
 
    The contents of this file are subject to the Andromedia Public 
	License Version 1.0 (the "License"); you may not use this file 
	except in compliance with the License. You may obtain a copy of 
	the License at http://www.andromedia.com/APL/ 
 
    Software distributed under the License is distributed on an 
	"AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 
	implied. See the License for the specific language governing 
	rights and limitations under the License. 
 
    The Original Code is Pueblo client code, released November 4, 1998. 
 
    The Initial Developer of the Original Code is Andromedia Incorporated. 
	Portions created by Andromedia are Copyright (C) 1998 Andromedia 
	Incorporated.  All Rights Reserved. 
 
	Andromedia Incorporated                         415.365.6700 
	818 Mission Street - 2nd Floor                  415.365.6701 fax 
	San Francisco, CA 94103 
 
    Contributor(s): 
	-------------------------------------------------------------------------- 
	   Chaco team:  Dan Greening, Glenn Crocker, Jim Doubek, 
	                Coyote Lussier, Pritham Shetty. 
 
					Wrote and designed original codebase. 
 
------------------------------------------------------------------------------ 
 
	This file consists of implementation of the ChMenu class. 
 
----------------------------------------------------------------------------*/ 
 
// $Header: /home/cvs/chaco/api/ChMenu.cpp,v 2.9 1996/03/14 03:02:45 pritham Exp $ 
 
#include  
 
#include "headers.h" 
 
#include  
#include  
#include "ChRMenu.h" 
 
 
 
/*---------------------------------------------------------------------------- 
	Constants 
----------------------------------------------------------------------------*/ 
 
#define NOT_IMPLEMENTED		TRACE2( "Function not implemented, file %s: line %d.", __FILE__, __LINE__) 
 
#if defined( CH_MSW ) 
 
	#define CH_FILE_MENU_NAME "&File" 
	#define CH_FILE_MENU_CLOSE_NAME "&Close" 
	#define CH_FILE_MENU_EXIT_NAME "E&xit" 
	#define CH_VIEW_MENU_NAME "&View" 
	#define CH_WINDOW_MENU_NAME "&Window" 
 
#elif defined( CH_UNIX ) 
 
	#define CH_FILE_MENU_NAME "File" 
	#define CH_FILE_MENU_EXIT_NAME "Exit" 
	#define CH_VIEW_MENU_NAME "View" 
	#define CH_WINDOW_MENU_NAME "Window" 
 
#endif	// defined( CH_UNIX ) 
 
 
/*---------------------------------------------------------------------------- 
	class ChMenu 
----------------------------------------------------------------------------*/ 
 
ChMenu::ChMenu( ChRMenuMgr* pMgr, string strTitle, const ChMsgHandler pDefHandler, chflag32 flOptions): 
					m_pMenuMgr( pMgr ),  
					m_strTitle(strTitle),  
					m_pHandler(pDefHandler),  
					m_pBlock( 0 ),  
					m_flOptions(flOptions) 
{ 
	 m_flState = CH_STATE_ENABLED; 
	 m_idModule = 0;	// set when installed 
} 
 
ChMenu::~ChMenu() 
{ 
	ChMenuItem*  pItem; 
 
	while (!m_items.IsEmpty()) 
	{ 
		pItem = m_items.RemoveHead(); 
		delete pItem; 
	} 
} 
 
ChMenuItem* ChMenu::InsertItem( string strTitle, const ChMsgHandler pHandler, chint16 sPosition ) 
{ 
	ChMenuItem*  pItem = new ChMenuItem( strTitle, pHandler, this ); 
 
	InsertInList( pItem, sPosition ); 
 
	return pItem; 
} 
 
ChMenuItem* ChMenu::InsertItem( ChMenu *pCascadeMenu, chint16 sPosition ) 
{ 
	ChMenuItem*  pItem = new ChMenuItem( pCascadeMenu, this ); 
 
	InsertInList( pItem, sPosition ); 
 
	return pItem; 
} 
 
ChMenuItem* ChMenu::InsertSeparator( chint16 sPosition ) 
{ 
	ChMenuItem*  pItem = new ChMenuItem( ChMenuItem::CH_MENU_ITEM_SEPARATOR, this ); 
 
	InsertInList( pItem, sPosition ); 
 
	return pItem; 
} 
 
ChMenuItem* ChMenu::FindItem( string strTitle, chint16 sPosition ) 
{ 
	ChPosition pos = FindItemPosition( sPosition ); 
	ChMenuItem*  pItem = 0; 
 
	while( pos != NULL ) 
	{ 
    	pItem = m_items.GetNext( pos ); 
		if (pItem->GetTitle() == strTitle ) return pItem; 
	} 
 
	return 0; 
} 
 
 
ChMenuItem* ChMenu::FindItem( ChMenu *pMenu, chint16 sPosition )	// add to docs!! 
{ 
	ChPosition pos = FindItemPosition( sPosition ); 
	ChMenuItem*  pItem = 0; 
 
	while( pos != NULL ) 
	{ 
    	pItem = m_items.GetNext( pos ); 
		if (pItem->GetType() == ChMenuItem::CH_MENU_ITEM_CASCADE && pMenu == pItem->GetMenu() ) 
		{ 
			return pItem; 
		} 
	} 
 
	return 0; 
} 
 
 
ChMenuItem* ChMenu::FindItem(chint16 sPosition ) 
{ 
	ChMenuItem*  pItem = 0;		   // change to call FindItemPosition 
 
	if (CH_MENU_END == sPosition) 
	{ 
		pItem = m_items.GetTail(); 
	} 
	else 
	{ 
		ChPosition pos = m_items.FindIndex( sPosition ); 
		if (pos) 
		{ 
			pItem = m_items.Get( pos ); 
		} 
	} 
	return pItem; 
} 
 
 
ChPosition ChMenu::FindItemPosition(chint16 sPosition ) 
{ 
	ChPosition pos = 0; 
 
	if (CH_MENU_END == sPosition) 
	{ 
		pos = m_items.GetTailPosition(); 
	} 
	else 
	{ 
		 pos = m_items.FindIndex(sPosition); 
	} 
	return pos; 
} 
 
 
void ChMenu::Promote( bool boolToHead ) 
{ 
	if (IsInstalled()) 
	{ 
		m_pBlock->Promote( this, boolToHead ); 
	} 
	else 
	{ 
		NOT_IMPLEMENTED;					// throw??	 (programmer error) 
	} 
} 
 
 
void ChMenu::Enable( bool boolEnable ) 
{ 
	bool isEnabled; 
 
	isEnabled = (m_flState &  CH_STATE_ENABLED) != 0; 
	if (boolEnable) 
	{ 
		m_flState |= (chflag32)CH_STATE_ENABLED; 
	} 
	else 
	{ 
		m_flState &= ~(chflag32)CH_STATE_ENABLED; 
	} 
 
	if ((isEnabled != boolEnable) && IsInstalled()) 
	{ 
		NOT_IMPLEMENTED; 
	} 
} 
 
 
/*---------------------------------------------------------------------------- 
	ChMenu::Install 
------------------------------------------------------------------------------ 
 
	Installs a menu	for module idModule. 
 
----------------------------------------------------------------------------*/ 
 
ChMenu* ChMenu::Install( const ChModuleID idModule,	bool boolToHead ) 
{ 
	return GetMenuMgr()->Install( this, idModule, boolToHead ); 
} 
 
 
ChMenu* ChMenu::Install( const string& strModuleName, bool boolToHead) 
{ 
	return GetMenuMgr()->Install( this, strModuleName, boolToHead ); 
} 
 
void ChMenu::Uninstall() 
{ 
	if (m_pBlock) 
	{ 
		ChRMenu *pRMenu = m_pBlock->GetRMenu(); 
		if(m_pBlock->GetRMenu()->Uninstall( this, m_pBlock )) 
		{ 
			delete pRMenu; 
		} 
	} 
	m_pBlock = 0; 
} 
 
void ChMenu::SetTitle( string strTitle ) 
{ 
	// needs to deinstall and reinstall 
 
	if (IsInstalled()) 
	{ 
		NOT_IMPLEMENTED; 
	} 
	else 
	{ 
		m_strTitle = strTitle; 
	} 
} 
 
 
 
/*---------------------------------------------------------------------------- 
	ChMenu derived classes: predefined menus 
	These need work to be internationalized!! 
----------------------------------------------------------------------------*/ 
 
/*---------------------------------------------------------------------------- 
	ChHelpMenu publics 
----------------------------------------------------------------------------*/ 
 
ChHelpMenu::ChHelpMenu( ChRMenuMgr* pMgr, ChMsgHandler pHandler, chflag32 flOptions ) : 
				ChMenu( pMgr, "&Help", pHandler, flOptions ) 
{ 
	string		strName; 
	 
	strName = GetMenuMgr()->GetItem( ID_HELP_INDEX )->GetTitle(); 
	this->InsertItem( strName ); 
} 
 
 
/*---------------------------------------------------------------------------- 
	ChEditMenu publics 
----------------------------------------------------------------------------*/ 
 
ChEditMenu::ChEditMenu( ChRMenuMgr* pMgr, ChMsgHandler pHandler, chflag32 flOptions ) : 
				ChMenu( pMgr, "&Edit", pHandler, flOptions ) 
{ 
	string		strName; 
	 
	strName = GetMenuMgr()->GetItem( ID_EDIT_CUT )->GetTitle(); 
	this->InsertItem( strName ); 
 
	strName = GetMenuMgr()->GetItem( ID_EDIT_COPY )->GetTitle(); 
	this->InsertItem(strName); 
 
	strName = GetMenuMgr()->GetItem( ID_EDIT_PASTE )->GetTitle(); 
	this->InsertItem( strName ); 
} 
 
 
/*---------------------------------------------------------------------------- 
	ChFileMenu publics 
----------------------------------------------------------------------------*/ 
 
ChFileMenu::ChFileMenu( ChRMenuMgr* pMgr, ChMsgHandler pHandler, chflag32 flOptions ) : 
				ChMenu( pMgr, CH_FILE_MENU_NAME, pHandler, flOptions ) 
{ 
	string		strName; 
	ChRMenuItem	*pRMenuItem; 
 
	pRMenuItem = GetMenuMgr()->GetItem( ID_FILE_CLOSE ); 
	if (pRMenuItem) 
		strName = pRMenuItem->GetTitle(); 
	else 
		strName = CH_FILE_MENU_CLOSE_NAME; 
	this->InsertItem( strName ); 
} 
 
 
/*---------------------------------------------------------------------------- 
	ChViewMenu publics 
----------------------------------------------------------------------------*/ 
 
ChViewMenu::ChViewMenu( ChRMenuMgr* pMgr, ChMsgHandler pHandler, chflag32 flOptions ) : 
				ChMenu( pMgr, CH_VIEW_MENU_NAME, pHandler, flOptions ) 
{ 
} 
 
 
/*---------------------------------------------------------------------------- 
	ChWindowMenu publics 
----------------------------------------------------------------------------*/ 
 
ChWindowMenu::ChWindowMenu( ChRMenuMgr* pMgr, ChMsgHandler pHandler, chflag32 flOptions ) : 
				ChMenu( pMgr, CH_WINDOW_MENU_NAME, pHandler, flOptions ) 
{ 
} 
 
 
/*---------------------------------------------------------------------------- 
	ChMenu private or protected helper methods 
----------------------------------------------------------------------------*/ 
 
ChMenuItem* ChMenu::FindItemByID(chuint32 id) 
{ 
	string strName = GetMenuMgr()->GetItem(id)->GetTitle(); 
	return( FindItem(strName) ); 
} 
 
ChMenuItem* ChMenu::InsertInList( ChMenuItem* pItem, chint16 sPosition) 
{ 
	if (sPosition >= m_items.GetCount()) sPosition = CH_MENU_END; 
 
	if (CH_MENU_END == sPosition) 
	{ 
		m_items.AddTail( pItem ); 
	} 
	else 
	{ 
		ChPosition pos = m_items.FindIndex( sPosition ); 
		m_items.InsertBefore( pos, pItem ); 
	} 
 
	if (IsInstalled()) 
	{ 
		//chuint32 luAt = -1; 
		m_pBlock->InstallItem( pItem, 0, CH_MENU_AT_EXISTING ); 
	} 
 
	return pItem; 
} 
 
void ChMenu::RemoveItem(ChMenuItem* pItem) 
{ 
	ChPosition	pos = m_items.Find( pItem ); 
 
	if (pos) 
	{ 
		m_items.Remove( pos ); 
	} 
} 
 
/*---------------------------------------------------------------------------- 
	ChMenuItem constructors and destructor 
----------------------------------------------------------------------------*/ 
 
ChMenuItem::ChMenuItem( string strTitle, const ChMsgHandler pHandler, 
						ChMenu *pParent ) : 
 				m_strTitle( strTitle ), 
 				m_strHelp( "" ), m_pParent( pParent ), m_type( CH_MENU_ITEM_TEXT ), 
				m_pRItem( 0 ), m_fsAccMods(0),	m_luAccChar(0) 
{ 
	//m_flState = CH_STATE_ENABLED;		  	// this is normal, enabled, but not checked 
	m_flState = 0;		  	// this is normal, enabled, but not checked 
	m_pHandler = pHandler; 
	if (pHandler) 
	{ 
		m_ppHandler = &m_pHandler; 
	} 
	else 
	{ 
		m_ppHandler = pParent->GetHandlerAddr(); 
	} 
} 
 
ChMenuItem::ChMenuItem( ChMenu *pCascadeMenu,  ChMenu *pParent ): 
		m_strHelp(""), 
		m_pCascade(pCascadeMenu), 
		m_pParent(pParent), 
		m_type(CH_MENU_ITEM_CASCADE), 
		m_pRItem( 0 ), 
		m_fsAccMods(0),	m_luAccChar(0) 
{ 
	m_pHandler = 0; 
	m_ppHandler = pParent->GetHandlerAddr(); 
	//m_flState = CH_STATE_ENABLED;		  	// this is normal, enabled, but not checked 
	m_flState = 0;		  	// this is normal, enabled, but not checked 
	m_strTitle = pCascadeMenu->GetTitle(); 
} 
 
ChMenuItem::ChMenuItem( ChMenuItem::ItemType eType, ChMenu *pParent ): 
	m_strHelp(""), m_pParent(pParent), m_pRItem( 0 ), 
	m_fsAccMods(0),	m_luAccChar(0) 
{ 
	m_ppHandler = pParent->GetHandlerAddr(); 
	//m_flState = CH_STATE_ENABLED;		  	// this is normal, enabled, but not checked 
	m_flState = 0;		  	// this is normal, enabled, but not checked 
	if (CH_MENU_ITEM_SEPARATOR == eType) 
	{ 
		m_type = CH_MENU_ITEM_SEPARATOR; 
	} 
	else 
	{ 
		NOT_IMPLEMENTED;	   // Throw?? 
	} 
} 
 
 
ChMenuItem::~ChMenuItem() 
{ 
	if (m_pRItem) m_pRItem->GetBlock()->DeleteItem(m_pRItem, this); 
	if (m_pParent) 
	{ 
		m_pParent->RemoveItem(this); 
		m_pParent = 0; 
	} 
} 
 
ChMenuItem *ChMenuItem::Enable( bool boolEnable, bool boolSilent ) 
{ 
	bool isEnabled; 
 
	isEnabled = (m_flState &  CH_STATE_ENABLED) != 0; 
	if (boolEnable) 
	{ 
		m_flState |= (chflag32)CH_STATE_ENABLED; 
	} 
	else 
	{ 
		m_flState &= ~(chflag32)CH_STATE_ENABLED; 
	} 
 
	// VSP : (isEnabled != boolEnable) commented code after consulting with Jim. 5/9/95 
	// For some reason isEnabled is true when it should be false, this will cause it to sync 
	// with the current state. 
	if (!boolSilent && /*(isEnabled != boolEnable) && */ m_pParent->IsInstalled()) 
	{ 
		m_pRItem->Enable( boolEnable ); 
	} 
	return this; 
} 
 
ChMenuItem * ChMenuItem::Check( bool boolCheck, bool boolSilent ) 
{ 
	bool isChecked; 
 
	isChecked = (m_flState &  CH_STATE_CHECKED) != 0; 
	if (boolCheck) 
	{ 
		m_flState |= (chflag32)CH_STATE_CHECKED; 
	} 
	else 
	{ 
		m_flState &= ~(chflag32)CH_STATE_CHECKED; 
	} 
 
	if (!boolSilent && (isChecked != boolCheck) && m_pParent->IsInstalled()) 
	{ 
		m_pRItem->Check(boolCheck); 
	} 
 
	return this; 
} 
 
ChMenuItem * ChMenuItem::SetTitle(string strTitle) 
{ 
	m_strTitle = strTitle; 
 
	if ( m_pParent->IsInstalled()) 
	{ 
		// It seems like this should cause a de-install 
		// and re-install of theitem 
		NOT_IMPLEMENTED; 
	} 
	return this; 
} 
 
ChMenuItem * ChMenuItem::SetHandler(const ChMsgHandler pHandler) 
{ 
	// Note that this -does not- affect RItem if installed 
	m_pHandler = pHandler; 
	if (pHandler) 
	{ 
		m_ppHandler = &m_pHandler; 
	} 
	else 
	{ 
		m_ppHandler = m_pParent->GetHandlerAddr(); 
	} 
	return this; 
} 
 
ChMenuItem * ChMenuItem::SetHelpText(string strHelp) 
{ 
	// Note that this -does not- affect RItem if installed 
	m_strHelp = strHelp; 
	return this; 
} 
 
ChMenuItem* ChMenuItem::SetAccelerator( const chuint32 luChar, const chflag16 fsMods ) 
{ 
	m_fsAccMods = fsMods; 
	m_luAccChar = luChar;  
	return this; 
} 
 
 
chint16 ChMenuItem::GetIndex() 
{ 
	chint16	sIndex; 
 
	sIndex = m_pParent->GetItemIndex( this ); 
 
	return sIndex; 
} 
 
// Helper function for ChMenuItem::GetIndex 
chint16 ChMenu::GetItemIndex(ChMenuItem*  pItem) 
{ 
	chint16	sIndex; 
	ChMenuItem*  pItemInList = 0; 
	ChPosition pos; 
 
	for( pos = m_items.GetHeadPosition(), sIndex = 0; pos != NULL; sIndex++) 
	{ 
    	pItemInList = m_items.GetNext( pos ); 
		if (pItem == pItemInList ) break; 
	} 
	if (!pos) 
	{ 
		// exception?? 
		NOT_IMPLEMENTED; 
	} 
 
	return sIndex; 
}