/*
*
* Perforce/JBuilder Opentool
* Copyright (C) 2001 David Freels
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.dafreels.opentools;
//JBuilder
import com.borland.primetime.*;
import com.borland.primetime.actions.*;
import com.borland.primetime.node.*;
import com.borland.primetime.editor.*;
import com.borland.jbuilder.*;
import com.borland.primetime.ide.*;
import com.borland.primetime.properties.*;
//Java
import java.util.ArrayList;
import javax.swing.*;
import java.awt.event.*;
//JBuilder/Perforce
import com.dafreels.opentools.properties.*;
import com.dafreels.opentools.actions.*;
import com.dafreels.opentools.actions.ui.StatusDialog;
//Perforce VCS
import com.dafreels.vcs.util.ExtensionRegistry;
import com.dafreels.vcs.command.*;
import java.util.HashMap;
import java.awt.Component;
import java.util.List;
/**
* Title: Description: Copyright: Copyright (c) 2001 Company: DF Systems
*
*@author David Freels
*@created July 6, 2001
*@version 1.0
*/
public class Main implements BrowserListener, KeyListener
{
public final static MessageCategory PERFORCEMESSAGES = new MessageCategory("Perforce Messages");
public final static JBuilderProperties m_props = new JBuilderProperties();
public final static Main main = new Main();
public final static String VERSION_NUM = "1.0.7";
public final static HashMap _askCache = new HashMap();
public static PerforceAction _editAction = new EditAction(true);
public static boolean _lookedForVi,_usingVi, _first = true;
protected static PerforceActionProvider m_toolbarProvider;
/**
* Description of the Method
*
*@param major Description of Parameter
*@param minor Description of Parameter
*/
public static void initOpenTool(byte major, byte minor)
{
// Check OpenTools version number
if(major != PrimeTime.CURRENT_MAJOR_VERSION)
{
return;
}
System.out.println("##########################################");
System.out.println("# Initializing Perforce Open Tool v "+VERSION_NUM);
System.out.println("##########################################");
//Register the extensions
ArrayList list = new ArrayList(10);
list.add("java");
list.add("jsp");
list.add("html");
list.add("htm");
list.add("gif");
list.add("jpg");
list.add("js");
list.add("css");
list.add("txt");
list.add("xml");
// support for user supplied file extensions.
String s= System.getProperty("com.dafreels.Extensions");
if ( s != null )
{
java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(s, ",");
while ( tokenizer.hasMoreTokens())
{
list.add(tokenizer.nextToken());
}
}
ExtensionRegistry.newInstance(list);
PerforceActionProvider pm = new PerforceActionProvider(false);
//Add to the popup menu
ProjectView.registerContextActionProvider(pm);
PerforceActionProvider pm2 = new PerforceActionProvider(true);
PerforceGroup pg = new PerforceGroup();
PropertyManager.registerPropertyGroup(pg);
//Add to the Source tab
TabbedContentManager.GROUP_NodeContext1.add(pm2.getActionGroup());
// can't use the m_props here since the JBuilderProperties requires
// an active Browser.
if ( Boolean.getBoolean("Perforce.addToToolbar"))
{
m_toolbarProvider = new PerforceActionProvider(true);
Browser.addToolBarGroup(m_toolbarProvider.getActionGroup());
}
if ( Boolean.getBoolean("Perforce.readOnlyTypingLocksFile"))
{
_editAction = new LockAction(true);
}
else
{
_editAction = new EditAction(true);
}
Browser.addStaticBrowserListener(main);
System.out.println("\n##########################################");
System.out.println("# Perforce Open Tool v "+VERSION_NUM+" loaded");
System.out.println("##########################################");
}
public static void refreshNodes(Node[] nodes)
{
for(int i = 0; i < nodes.length; i++)
{
System.out.println("checking "+nodes[i].getLongDisplayName());
nodes[i].check();
}
//System.gc();
}
public void browserActivated(com.borland.primetime.ide.Browser browser)
{
if ( browser == null )
{
return;
}
}
public void browserClosed(com.borland.primetime.ide.Browser browser)
{
}
public void browserDeactivated(com.borland.primetime.ide.Browser browser)
{
if ( browser == null )
{
return;
}
browser.removeKeyListener(this);
}
public void browserClosing(com.borland.primetime.ide.Browser browser) throws com.borland.primetime.util.VetoException
{
ProcessReader.stopReader();
}
public void browserNodeActivated(com.borland.primetime.ide.Browser browser,
com.borland.primetime.node.Node node)
{
if ( node instanceof FileNode )
{
FileNode fnode = (FileNode)node;
if ( !fnode.isReadOnly() )
{
return;
}
String fileName = fnode.getLongDisplayName();
if ( !ExtensionRegistry.getInstance().validateFile(fileName))
{
return;
}
if ( _askCache.get(fileName) == null )
{
EditorPane editor = EditorAction.getFocusedEditor();
if ( editor != null )
{
editor.addKeyListener(this);
}
}
}
}
public void browserViewerDeactivating(com.borland.primetime.ide.Browser browser, com.borland.primetime.node.Node node, com.borland.primetime.ide.NodeViewer nodeViewer) throws com.borland.primetime.util.VetoException
{
}
public void browserProjectClosed(com.borland.primetime.ide.Browser browser, com.borland.primetime.node.Project project)
{
}
public void browserOpened(final com.borland.primetime.ide.Browser browser)
{
browser.addKeyListener(this);
if ( _first && (m_props.getExecutable() == null || m_props.getExecutable().length() == 0) )
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JOptionPane.showMessageDialog(browser,
"Please set up the Perforce OpenTool before use.\n"+
"The Perforce Options Page can be accessed under\n"+
"the Perforce tab on the Editor Options dialog\n",
"Perforce OpenTool", JOptionPane.INFORMATION_MESSAGE );
}
});
_first = false;
}
if ( m_props.addToToolbar() && m_toolbarProvider == null )
{
m_toolbarProvider = new PerforceActionProvider(true);
browser.addToolBarGroup(m_toolbarProvider.getActionGroup());
}
else if ( !m_props.addToToolbar() && m_toolbarProvider != null )
{
browser.removeToolBarGroup(m_toolbarProvider.getActionGroup());
m_toolbarProvider = null;
}
}
public void browserViewerActivated(com.borland.primetime.ide.Browser browser, com.borland.primetime.node.Node node, com.borland.primetime.ide.NodeViewer nodeViewer)
{
}
public void browserNodeClosed(com.borland.primetime.ide.Browser browser, com.borland.primetime.node.Node node)
{
if ( node instanceof FileNode )
{
String fileName = ((FileNode)node).getLongDisplayName();
if ( !ExtensionRegistry.getInstance().validateFile(fileName))
{
return;
}
EditorPane editor = EditorManager.getEditor(node);
if ( editor != null )
{
editor.removeKeyListener(this);
}
}
}
public void browserProjectActivated(com.borland.primetime.ide.Browser browser, com.borland.primetime.node.Project project)
{
if ( m_props.addToToolbar() && m_toolbarProvider == null )
{
m_toolbarProvider = new PerforceActionProvider(true);
browser.addToolBarGroup(m_toolbarProvider.getActionGroup());
}
else if ( !m_props.addToToolbar() && m_toolbarProvider != null )
{
browser.removeToolBarGroup(m_toolbarProvider.getActionGroup());
m_toolbarProvider = null;
}
}
/**
* support for the About OpenTool
* @param key the value requested. One of 4 values: <code>TITLE</code>, <code>AUTHOR</code>,
* <code>VERSION</code>, <code>DESCRIPTION</code>
* @return the key value
* @author Mark Ackerman
*/
public static String getOpenToolInfo(Object key)
{
if ( key == null ) return "";
String keyStr = key.toString();
if ( "TITLE".equalsIgnoreCase(keyStr))
{
return "Perforce OpenTool";
}
else if ( "AUTHOR".equalsIgnoreCase(keyStr))
{
return "David Freels";
}
else if ( "VERSION".equalsIgnoreCase(keyStr))
{
return VERSION_NUM;
}
else if ( "DESCRIPTION".equalsIgnoreCase(keyStr))
{
return "Open tool to Integrate JBuilder and Perforce";
}
return "";
}
public void keyPressed(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
Browser browser = Browser.getActiveBrowser();
if ( browser == null )
{
return;
}
if ( validCharacter(e.getKeyChar()) )
{
Node node = browser.getActiveNode();
if ( node instanceof FileNode )
{
FileNode fnode = (FileNode)node;
if ( fnode.isReadOnly() )
{
String path = fnode.getLongDisplayName();
if ( _askCache.get(path) == null)
{
int opt = JOptionPane.showConfirmDialog(browser,
"Edit the file " + fnode.getDisplayName()+"?",
"Edit in Perforce?", JOptionPane.YES_NO_CANCEL_OPTION );
if ( opt == JOptionPane.YES_OPTION)
{
if ( isLatestFile(browser))
{
_editAction.actionPerformed(browser);
}
else
{ // don't remove the key listener.
return;
}
}
else if ( opt == JOptionPane.CANCEL_OPTION )
{
return;
}
else
{ // said no or canceled the dialog so don't ask again
_askCache.put(path, path);
}
}
EditorPane editor = EditorManager.getEditor(fnode);
if ( editor != null )
{
editor.removeKeyListener(this);
}
}
}
}
}
/**
* check to see if the ActiveNode has the latest revision
* @param browser the current Browser
* @return true if the ActiveNode has the latest revision
*/
public static boolean isLatestFile(Browser browser)
{
Node node = browser.getActiveNode();
if ( node == null )
{
return false;
}
com.dafreels.vcs.command.Command command =
new com.dafreels.vcs.command.Command(com.dafreels.vcs.command.Command.STATUS);
command.addPath(node.getLongDisplayName());
com.dafreels.vcs.command.CommandTool.runCommand(command, m_props);
String msg;
boolean haveErrors = MessageFormatter.getErrorMessageCount() > 0;
MessageWriter.outputErrorMessages(MessageFormatter.getInstance());
String haveRev = null, headRev = null;
while ( (msg = MessageFormatter.getNextMessage()) != null)
{
if ( msg.startsWith(StatusDialog.LEAD_IN))
{
msg = msg.substring(4);
if ( msg.startsWith(StatusDialog.HEAD_REV ))
{
headRev = StatusDialog.getArg(msg);
}
else if ( msg.startsWith(StatusDialog.HAVE_REV))
{
haveRev = StatusDialog.getArg(msg);
}
}
if ( haveRev != null && headRev != null )
{
break;
}
}
if ( haveRev == null || headRev == null )
{
return true;
}
boolean haveLatest = haveRev.equals(headRev);
if ( !haveLatest )
{
int opt = JOptionPane.showConfirmDialog(browser, "You don't have the latest Revision."+
"\nHead Revision="+headRev+" Have Revision:"+haveRev+"\nSync to Head Revision?",
"Missing Revision",JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);
if ( opt == JOptionPane.YES_OPTION )
{
SyncAction syncAction = new SyncAction(true);
syncAction.actionPerformed(browser);
return true;
}
}
return haveLatest;
}
public void removeFileFromAskCache(String file)
{
if ( file == null )
{
return;
}
if ( _askCache.remove(file) == null )
{
System.out.println("removeFileFromAskCache: didn't find "+
file+" in cache");
}
}
public void removeFilesFromAskCache(List files)
{
if ( files == null )
{
return;
}
for (int i = 0; i < files.size(); i++ )
{
if ( _askCache.remove(files.get(i)) == null )
{
System.out.println("removeFilesFromAskCache: didn't find "+
files.get(i)+" in cache");
}
}
}
/**
* check to see if the character type is a character that should invoke a
* question to the user.
* If the VI opentool is used the 'h','j','k','l','y','n','N','G','m'
* characters and any number do not prompt the user
* @param c the character typed
* @return whether to ask the user or not
*/
boolean validCharacter(char c)
{
checkIfViUsed(); // can this be done in the initOpenTool?
if ( _usingVi )
{ // additional checking for VI opentool
if ( c == 'h' || c == 'j' || c == 'k' || c == 'l' || c == 'y'|| c== 'n'
|| c == 'N' || c == 'G' || c == 'm' )
{
return false;
}
return Character.isLetter(c);
/*
switch ( c )
{
case KeyEvent.VK_H: // left
case KeyEvent.VK_J: // down
case KeyEvent.VK_K: // up
case KeyEvent.VK_L: // right
return false;
default:
return Character.isLetter(c);
}
*/
}
else
{
return Character.isLetterOrDigit(c);
}
}
/**
* support for the VI opentool. VI has both a command mode and an insert mode.
* we only want to listener for keystrokes that take the editor into insert mode.
*/
void checkIfViUsed()
{
if ( ! _lookedForVi )
{
javax.swing.text.Caret caret = EditorManager.getCaret();
try {
Class viCls = Class.forName("org.jbopentools.editor.jbvi.JBViCaret");
_usingVi = viCls.isAssignableFrom(caret.getClass());
}
catch ( Exception e)
{ // empty
_usingVi = false;
}
}
_lookedForVi = true;
}
}