/**
* File: LaTeX_Menu_Manager.bsh
* Purpose: Define the class ModeMenuManager that does the following when used:
* When a user switches into another buffer check whether it is in the (la)tex mode
* and if so copy LaTeX Tool Plugin's menu to the menu bar next to "Help"
* (i.e. create a top-most menu for it). When the buffer is left remove it.
*
* It could be easily modified for another mode/menu combination or even to handle
* more modes menus.
*
* The inner class starts listening on the EditBus until a view is created. At
* that moment it creates a new ModeMenuManager for the view and removes self
* from the bus listeners.
*
* To use this macro:
* 1. Store this file in jEdit user startup directory (e.g. $HOME/.jedit/startup)
* A.2. Create in the jEdit user startup directory a .bsh file with a single line:
* _myModeMenuManagerXQ953 = new ModeMenuManager.InitialRegistrator();
* (you can use the variable to remove the mode manager later on - see its remove())
* A.3. Remove the lines at the end of this file that do the same.
* OR
* B.2 ignore the steps A.2, A.3 and you are done.
*
* Requirements:
* The plugin LaTeX Tools must be installed.
*
* @author Jakub Holy, maly.velky@email.cz
* @date Dec 30, 2005
*/
public class ModeMenuManager
implements org.gjt.sp.jedit.EBComponent
{
View theView;
DockableWindowManager wm;
javax.swing.JMenuBar menuBar;
Buffer buffer = null;
/** Store the menu we've added so we can remove it when needed. */
javax.swing.JMenuItem addedMenu = null;
/** We're waiting for the 1st active buffer to get loaded. */
boolean waitFor1stBuff = true;
/** Singleton.*/
public static Object theModeMenuManager = null;
/** The modes for which to perform the given action */
static final String[] MODES = new String[]{"tex", "latex"};
/** The plugin to activate when in one of the given modes */
static final String PLUGIN_CLASS = "uk.co.antroy.latextools.LaTeXPlugin";
static final String PLUGIN_NAME = "LaTeX Tools";
/* // BeanShell doesn't manage to delcare this
public static ModeMenuManager getModeMenuManager( View view )
{
return (theModeMenuManager != null)? theModeMenuManager :
new ModeMenuManager(view);
}
//*/
/** Create a new instance and register to the bus if this is the 1st instance. */
public ModeMenuManager( View view )
{
// TODO: it's better to reinitialize always (user could have switched views...)
theView = view;
wm = view.getDockableWindowManager();
menuBar = view.getJMenuBar();
// Start listening for jEdit events
if (theModeMenuManager == null)
{
theModeMenuManager = this;
EditBus.addToBus( this );
Log.log( Log.DEBUG, this, "Listening for bus events..." );
}
// Check whether the given plugin is present
Object plugin = jEdit.getPlugin( PLUGIN_CLASS, true );
if ( plugin == null )
{
Log.log( Log.DEBUG, this, "ERROR: the plugin " + PLUGIN_CLASS
+ " ("+PLUGIN_NAME+") is not available." );
Macros.error( view ,
"LaTeX_Menu_Manager.bsh: Sorry but it seems that the necessary\n" +
"plugin of the class \"" + PLUGIN_CLASS + "\" is not available.\n" +
"Thus this macro won't work. Please remove it from your startup\n" +
"directory or install the missing plugin ( perhaps the plugin \""+
PLUGIN_NAME+"\" )."
);
}
} // constr
/** @return true if the given action should be performed for the mode modeName. */
boolean doApplyForMode(String modeName)
{
//String mode = (modeName != null)? modeName : buffer.getMode().getName();
// For all my modes:
for(int i = 0; i < MODES.length; ++i)
{
if(MODES[i].equals( modeName ))
{
return true;
}
}
return false;
}
/** Add/remove mode-related menu when buffer mode has changed (e.g. buffers switched). */
void manageBufferModeChng()
{
Log.log( Log.DEBUG, this, "ENTRY: manageBufferModeChng!" );
buffer = theView.getBuffer();
// can't get mode until done loading
if(!buffer.isLoaded())
{
VFSManager.waitForRequests();
}
if( doApplyForMode(buffer.getMode().getName()) )
{
Log.log( Log.DEBUG, this, "manageBufferModeChng: buffer is in (la)tex =>"
+"going to create the menu if not present already" );
// Check that the menu haven't been created already
if ( addedMenu != null ) { return; }
/* IDEA:
* Vytvor objekt - listener/observer na EditBus (pri startu jeditu), ktery
* pri akci EditPaneUpdate.BUFFER_CHANGED podle buffer.getMode().getName()
* prida nove menu/ odebere menu z minuleho modu
* Ma 2 pole: ptr na view.getJMenuBar() a HashMap ("mode name", JMenu)
* Kdyz menu pro dany mod jeste neexistuje, tak ho vytvori a vlozi.
* Pozn.: Ale dela tak jen pro nektere, podporovane mody
* (this.isModeSupported( name ); ) Pro podporovane mody existuje
* v hashi vstup od vytvoreni objektu?
*/
// Create a copy of the menu ...
// menu = new javax.swing.JMenu("Menu Label")
// menu.setMnemonic( java.awt.event.KeyEvent.VK_M )
// Create & add menu (a submenu or an item) for the given plugin
addedMenu = createMenuItems( PLUGIN_CLASS );
if( addedMenu == null )
{ return; }
menuBar.add( addedMenu );
menuBar.repaint(); // Inportant: there may be a small delay ( < 2 sec)
}
else
{
// Remove the last menu == the one we've added
// but only if it hasn't been removed already or never created
/*if ( jEdit.getLastBuffer().getMode().getName().equals("tex") )*/ {
//javax.swing.JMenu lastMenu = menuBar.getMenu( menuBar.getMenuCount() - 1 );
Log.log( Log.DEBUG, this, "manageBufferModeChng: not (la)tex and menu not created => doing nothing." );
if ( addedMenu != null )
{
Log.log( Log.DEBUG, this, "manageBufferModeChng: removing the menu" );
menuBar.remove( addedMenu );
menuBar.repaint();
addedMenu = null;
}
}
} // if-else a supported mode
} // manageBufferModeChng
/** Create a menu for the given plugin class (either 1 item or a submenu).
* Mostly copied from EditPlugin.createMenuItems. jEdit finds all information
* needed to create the menu in the properties that the plugin has set.
* @param pluginClassName full plugin class name such as uk.co.antroy.latextools.LaTeXPlugin
* To find it out run Macros->Properties->jEdit properties and look
* for the name of your plugin - there shall be a line
* plugin.{plugin class name}.name={Your Plugin Name}
*/
public final JMenuItem createMenuItems( String pluginClassName )
{
//if(this instanceof Broken) return null;
String menuItemName = jEdit.getProperty("plugin." +
pluginClassName + ".menu-item");
if(menuItemName != null)
return GUIUtilities.loadMenuItem(menuItemName);
String menuProperty = "plugin." + pluginClassName + ".menu";
String codeProperty = "plugin." + pluginClassName + ".menu.code";
if(jEdit.getProperty(menuProperty) != null
|| jEdit.getProperty(codeProperty) != null)
{
String pluginName = jEdit.getProperty("plugin." +
pluginClassName + ".name");
return new EnhancedMenu(menuProperty,pluginName);
}
return null;
} // createMenuItems
/** Handles a message sent on the EditBus - calls manageBufferModeChng. */
public void handleMessage(EBMessage message)
{
if ( message instanceof EditPaneUpdate ) // buffer switched
{
Log.log(Log.DEBUG, this, "ModeMenuManager: received EditPaneU. bus message:" + message );
EditPaneUpdate paneMsg = (EditPaneUpdate)message;
if ( paneMsg.getWhat().equals( EditPaneUpdate.BUFFER_CHANGED ) )
{
this.manageBufferModeChng();
}
}
else if ( waitFor1stBuff && (message instanceof BufferUpdate) ) // 1st buffer loaded
{
BufferUpdate buffMsg = (BufferUpdate)message;
// If loading of the buffer has been finished and it's the active
// buff. check whether it's in MODE and if so show the menu
if ( buffMsg.getWhat().equals( BufferUpdate.LOADED ) &&
buffMsg.getBuffer().equals( theView.getBuffer() ) )
{
waitFor1stBuff = false;
this.manageBufferModeChng();
}
} // if-else message type
} // handleMessage
/** When startup scripts are run 'view' doesn't exist yet.*/
public class InitialRegistrator
implements org.gjt.sp.jedit.EBComponent
{
ModeMenuManager theMMManager = null;
public InitialRegistrator()
{
EditBus.addToBus( this ); /// EditBus.removeFromBus( this );
}
public void handleMessage(EBMessage message)
{
if( message instanceof ViewUpdate )
{
Log.log(Log.DEBUG, this, "**** Registrator: received EditPaneU. bus message:" + message );
ViewUpdate viewMsg = (ViewUpdate)message;
if ( viewMsg.getWhat().equals( ViewUpdate.CREATED ) )
{
Log.log(Log.DEBUG, this, "**** Registrator: view created" );
// Create a new mode menu manager and disconnect self from the bus
theMMManager = new ModeMenuManager( viewMsg.getView() );
EditBus.removeFromBus( this );
}
} // InitialRegistrator.handleMessage
} // handleMessage
public ModeMenuManager getManager() {
return theMMManager;
}
/** Remove the manager from the bus.*/
public void removeManager() {
if( theMMManager == null ) { return; }
EditBus.removeFromBus( this.theMMManager );
this.theMMManager = null;
}
}
} // ModeMenuManager
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
// You can use _myModeMenuManagerXQ953.remove() later on to remove the
// mode menu manager so that it will stop doing its job.
ModeMenuManager.InitialRegistrator _myModeMenuManagerXQ953 =
new ModeMenuManager.InitialRegistrator();