зеркало из https://github.com/mozilla/gecko-dev.git
339 строки
8.7 KiB
C++
339 строки
8.7 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 "CToolsAttachment.h"
|
||
|
||
#include "CEditView.h"
|
||
#include "CBrowserContext.h" // operator MWContext*()
|
||
#include "resgui.h" // TOOLS_MENU_BASE_LAST
|
||
#include "macutil.h" // CMediatedWindow
|
||
#include "UMenuUtils.h"
|
||
#include "edt.h"
|
||
//#include "CSpellChecker.h"
|
||
#include <LArray.h>
|
||
|
||
|
||
#define PERM_TOOLS_ITEMS 2
|
||
#define PERM_TOOLS_END_ITEMS 1
|
||
|
||
const CommandT cmd_ToolsHierItem = TOOLS_MENU_BASE_LAST;
|
||
|
||
LMenu *CToolsAttachment::sMenu = NULL;
|
||
Boolean CToolsAttachment::sInvalidMenu = true;
|
||
LArray CToolsAttachment::sMenusList;
|
||
|
||
//===========================================================
|
||
// CToolsAttachment
|
||
//===========================================================
|
||
CToolsAttachment::CToolsAttachment()
|
||
{
|
||
}
|
||
|
||
|
||
MWContext *CToolsAttachment::GetTopWindowContext()
|
||
{
|
||
// Ok, ok. I know this is skanky,
|
||
// but there is no common way to get the context from a window: it depends on the window type.
|
||
// So, we look around for a CEditView somewhere in the top window.
|
||
// A CEditView we understand (and get an MWContext from).
|
||
|
||
CMediatedWindow* topWin = NULL; // find the top window to use the plugin in
|
||
CWindowIterator iter(WindowType_Any);
|
||
// do {
|
||
iter.Next(topWin);
|
||
// } while (topWin && topWin->GetWindowType() != WindowType_Editor && topWin->GetWindowType() != WindowType_Compose);
|
||
|
||
if (topWin == NULL)
|
||
return NULL;
|
||
|
||
if ( topWin->GetWindowType() != WindowType_Editor && topWin->GetWindowType() != WindowType_Compose )
|
||
return NULL;
|
||
|
||
CEditView *editView = (CEditView *)(topWin->FindPaneByID(CEditView::pane_ID));
|
||
|
||
if (editView == NULL || editView->GetNSContext() == NULL)
|
||
return NULL;
|
||
|
||
return editView->GetNSContext()->operator MWContext*();
|
||
}
|
||
|
||
|
||
// Processes:
|
||
void CToolsAttachment::ExecuteSelf( MessageT inMessage, void* ioParam )
|
||
{
|
||
mExecuteHost = FALSE;
|
||
switch ( inMessage )
|
||
{
|
||
// case cmd_CheckSpelling: // spell checker
|
||
// return;
|
||
|
||
case cmd_EditorPluginStop:
|
||
MWContext *cntxt = GetTopWindowContext();
|
||
if (cntxt)
|
||
EDT_StopPlugin(cntxt);
|
||
return;
|
||
|
||
case msg_CommandStatus:
|
||
{
|
||
SCommandStatus* status = (SCommandStatus*)ioParam;
|
||
|
||
switch ( status->command )
|
||
{
|
||
case cmd_EditorPluginStop:
|
||
MWContext *cntxt = GetTopWindowContext();
|
||
*(status->enabled) = cntxt && EDT_IsPluginActive(cntxt);
|
||
*(status->usesMark) = FALSE;
|
||
return;
|
||
|
||
default:
|
||
if ( status->command >= TOOLS_MENU_BASE && status->command <= TOOLS_MENU_BASE_LAST )
|
||
{
|
||
*(status->enabled) = TRUE;
|
||
*(status->usesMark) = FALSE;
|
||
return;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
|
||
default:
|
||
{
|
||
if ( inMessage >= TOOLS_MENU_BASE && inMessage <= TOOLS_MENU_BASE_LAST )
|
||
{
|
||
int32 index = inMessage - TOOLS_MENU_BASE;
|
||
|
||
for (int32 CategoryIndex = 0; CategoryIndex < EDT_NumberOfPluginCategories(); CategoryIndex++)
|
||
for (int32 PluginIndex = 0; PluginIndex < EDT_NumberOfPlugins(CategoryIndex); PluginIndex++)
|
||
if (index-- == 0)
|
||
{ // count down until we find which one...
|
||
MWContext *cntxt = GetTopWindowContext();
|
||
if (cntxt)
|
||
EDT_PerformPlugin(cntxt, CategoryIndex, PluginIndex, 0, 0); // what is the result for?
|
||
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
mExecuteHost = TRUE; // Let application handle it
|
||
}
|
||
|
||
|
||
LMenu *CToolsAttachment::GetMenu()
|
||
{
|
||
if (!sMenu)
|
||
sMenu = new LMenu(cToolsMenuID);
|
||
|
||
return sMenu;
|
||
}
|
||
|
||
void CToolsAttachment::UpdateMenu()
|
||
{
|
||
if (!sInvalidMenu || !GetMenu() || !LMenuBar::GetCurrentMenuBar())
|
||
return;
|
||
|
||
int i;
|
||
|
||
// <20> delete all the dynamically created menus
|
||
// <20><>delete all the hierarchical menus we have added from the menubar
|
||
for ( i = 1; i <= sMenusList.GetCount(); i++ )
|
||
{
|
||
LMenu* m;
|
||
sMenusList.FetchItemAt( i, &m );
|
||
if ( m )
|
||
LMenuBar::GetCurrentMenuBar()->RemoveMenu( m );
|
||
delete m;
|
||
}
|
||
|
||
// <20> delete all the menu items after the line in Tools menu
|
||
MenuHandle menu = sMenu->GetMacMenuH();
|
||
if ( menu )
|
||
{
|
||
int howMany = ::CountMItems( menu );
|
||
for ( i = howMany - PERM_TOOLS_END_ITEMS; i > PERM_TOOLS_ITEMS; i-- )
|
||
sMenu->RemoveItem( i );
|
||
}
|
||
sMenusList.RemoveItemsAt( sMenusList.GetCount(), 1 );
|
||
|
||
int whichItem = PERM_TOOLS_ITEMS;
|
||
int commandNum = TOOLS_MENU_BASE;
|
||
int nextMenuID = cEditorPluginsFirstHierMenuID;
|
||
|
||
Try_
|
||
{
|
||
ThrowIfNil_( sMenu );
|
||
MenuHandle mHand = sMenu->GetMacMenuH();
|
||
|
||
ThrowIfNil_( mHand );
|
||
|
||
for (int32 CategoryIndex = 0; CategoryIndex < EDT_NumberOfPluginCategories(); CategoryIndex++) {
|
||
|
||
CStr255 headerName( EDT_GetPluginCategoryName( CategoryIndex ) );
|
||
CreateMenuString( headerName ); // make sure it isn't too long
|
||
|
||
whichItem = UMenuUtils::InsertMenuItem(mHand, headerName, whichItem); // returns actual insert loc
|
||
sMenu->SetCommand(whichItem, cmd_ToolsHierItem);
|
||
|
||
// <20> Are there actually any menu items to put on this Hierarchical menu?
|
||
if (EDT_NumberOfPlugins(CategoryIndex)) {
|
||
|
||
// <20> do we have any hierarchical menus left?
|
||
if (nextMenuID <= cEditorPluginsLastHierMenuID) {
|
||
|
||
LMenu* subMenu = (LMenuBar::GetCurrentMenuBar())->FetchMenu( nextMenuID );
|
||
if ( !subMenu )
|
||
{
|
||
StringHandle menuStringH = GetString( NEW_RESID );
|
||
Assert_(menuStringH);
|
||
if (menuStringH)
|
||
{
|
||
StHandleLocker locker((Handle)menuStringH);
|
||
subMenu = new LMenu( nextMenuID,
|
||
(unsigned char *)*menuStringH );
|
||
LMenuBar::GetCurrentMenuBar()->InstallMenu( subMenu, hierMenu );
|
||
}
|
||
}
|
||
else
|
||
SysBeep( 1 );
|
||
|
||
nextMenuID++;
|
||
|
||
if ( subMenu )
|
||
{
|
||
sMenusList.InsertItemsAt( 1, sMenusList.GetCount(), &subMenu );
|
||
// <20><>make item hierarchical
|
||
::SetItemCmd( mHand, whichItem, hMenuCmd );
|
||
::SetItemMark( mHand, whichItem, subMenu->GetMenuID() );
|
||
FillMenu(
|
||
CategoryIndex,
|
||
subMenu,
|
||
commandNum,
|
||
0 );
|
||
}
|
||
|
||
} else {
|
||
|
||
// <20> There are no hierarchical menus left,
|
||
// so we will just add these onto the bottom of the main tools menu.
|
||
// We have already put the (disabled) category name in the main tools menu
|
||
|
||
FillMenu(
|
||
CategoryIndex,
|
||
sMenu,
|
||
commandNum,
|
||
whichItem );
|
||
|
||
whichItem += EDT_NumberOfPlugins(CategoryIndex);
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
// this is a hack. The menu item "Stop Active Plug-in" gets pushed around and loses its command. So, reset it.
|
||
sMenu->SetCommand(++whichItem, cmd_EditorPluginStop);
|
||
|
||
}
|
||
Catch_( inErr )
|
||
{
|
||
}
|
||
EndCatch_
|
||
|
||
|
||
sInvalidMenu = true;
|
||
}
|
||
|
||
void CToolsAttachment::FillMenu(
|
||
int32 CategoryIndex,
|
||
LMenu* newMenu,
|
||
int& commandNum, // next menu to create
|
||
int whichItem ) // id of the first item to insert
|
||
{
|
||
Try_
|
||
{
|
||
ThrowIfNil_( newMenu );
|
||
MenuHandle mHand = newMenu->GetMacMenuH();
|
||
|
||
ThrowIfNil_( mHand );
|
||
|
||
for (int32 PluginIndex = 0; PluginIndex < EDT_NumberOfPlugins(CategoryIndex); PluginIndex++) {
|
||
|
||
// <20> should really convert this to sMenu chars
|
||
CStr255 pluginName( EDT_GetPluginName( CategoryIndex, PluginIndex) );
|
||
CreateMenuString( pluginName );
|
||
|
||
whichItem = UMenuUtils::InsertMenuItem(mHand, pluginName, whichItem); // returns actual insert loc
|
||
newMenu->SetCommand(whichItem, commandNum++);
|
||
|
||
}
|
||
}
|
||
Catch_( inErr )
|
||
{
|
||
}
|
||
EndCatch_
|
||
}
|
||
|
||
void CToolsAttachment::RemoveMenus()
|
||
{
|
||
if (sMenu)
|
||
{
|
||
LMenuBar *currentMenuBar = LMenuBar::GetCurrentMenuBar();
|
||
|
||
if (currentMenuBar)
|
||
{
|
||
currentMenuBar->RemoveMenu(sMenu);
|
||
|
||
for (ArrayIndexT index = 1; index <= sMenusList.GetCount(); ++index)
|
||
{
|
||
LMenu *menu;
|
||
sMenusList.FetchItemAt(index, &menu);
|
||
|
||
if (menu)
|
||
currentMenuBar->RemoveMenu(menu);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void CToolsAttachment::InstallMenus()
|
||
{
|
||
if (sMenu)
|
||
{
|
||
LMenuBar *currentMenuBar = LMenuBar::GetCurrentMenuBar();
|
||
|
||
if (currentMenuBar)
|
||
{
|
||
for (ArrayIndexT index = sMenusList.GetCount(); index > 0; --index)
|
||
{
|
||
LMenu *menu;
|
||
sMenusList.FetchItemAt(index, &menu);
|
||
|
||
if (menu)
|
||
{
|
||
StValueChanger<EDebugAction> okayToFail(gDebugThrow, debugAction_Nothing);
|
||
currentMenuBar->InstallMenu(menu, hierMenu);
|
||
}
|
||
}
|
||
StValueChanger<EDebugAction> okayToFail(gDebugThrow, debugAction_Nothing);
|
||
currentMenuBar->InstallMenu(sMenu, InstallMenu_AtEnd);
|
||
}
|
||
}
|
||
}
|