"""
Find_and_Open.py - A Jython macro for jEdit that let's
one search a directory tree for files using Unix shell-style
wildcards. If only one file is found it is opened, if multiple
files are found then a dialog is displayed so the user can
pick which file(s) to open.

Copyright (C) 2002 Ollie Rutherfurd <oliver@rutherfurd.net>

$Id: Find_and_Open.py 28 2003-03-25 22:40:28Z oliver $
"""

from java.awt import BorderLayout
from java.awt.event import ActionListener, KeyEvent, \
	KeyListener, MouseListener
from javax.swing import Box, BoxLayout, DefaultListCellRenderer, \
	JButton, JDialog, JLabel, JList, JPanel, JScrollPane, \
	ListSelectionModel
from javax.swing.border import EmptyBorder

from org.gjt.sp.jedit import GUIUtilities, Macros
from org.gjt.sp.jedit.browser import VFSBrowser

import fnmatch
import os

LAST_DIR = 'macro.py_find_and_open.last-dir'

class FilePicker(JDialog,ActionListener,KeyListener,MouseListener):

	"""
	Dialog to display a list of files found, so user can
	pick which to open.
	"""

	def __init__(self,view,pattern,rootdir,filesFound,modal=1):
		JDialog.__init__(self,view,'Select Files to Open',modal)
		self.view=view

		panel = JPanel(BorderLayout(), border=EmptyBorder(12,12,12,12))
		self.setContentPane(panel)

		panel.add(JLabel('Found %d files matching %s in %s' % (len(filesFound),pattern,rootdir,)), BorderLayout.NORTH)
		self.fileList = fileList = JList(filesFound, keyListener=self, mouseListener=self)
		panel.add(JScrollPane(fileList),BorderLayout.CENTER)

		buttons = JPanel(border=EmptyBorder(12,50,0,50))
		buttons.setLayout(BoxLayout(buttons, BoxLayout.X_AXIS))

		self.ok = JButton("Open",actionListener=self)
		close = JButton("Cancel",actionListener=self)
		self.ok.setPreferredSize(close.getPreferredSize())
		self.getRootPane().setDefaultButton(self.ok)
		buttons.add(Box.createGlue())
		buttons.add(self.ok)
		buttons.add(Box.createHorizontalStrut(6))
		buttons.add(close)
		buttons.add(Box.createGlue())
		panel.add(buttons, BorderLayout.SOUTH)

		self.addKeyListener(self)

		self.pack()
		self.setLocationRelativeTo(self.view)
		self.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE)
		self.setVisible(1)

	def openSelected(self):
		files = self.fileList.getSelectedValues()
		[jEdit.openFile(self.view, f) for f in files]

	def close(self):
		self.view = None
		self.dispose()

	def actionPerformed(self,evt):
		if evt.source == self.ok:
			self.openSelected()
		self.close()

	def keyPressed(self,evt):
		if evt.getKeyCode() == KeyEvent.VK_ESCAPE:
			self.close()

	keyReleased = keyTyped = lambda self,evt: None

	def mouseClicked(self,evt):
		if evt.clickCount > 1:
			self.openSelected()
			self.close()

	mouseEntered = mouseExited = mousePressed = mouseReleased = lambda self,evt: None


def getFilePattern(v):
	return Macros.input(v, 'File Pattern', '')

def getRootDirectory(v,default):
	dirs = GUIUtilities.showVFSFileDialog(v, default, VFSBrowser.CHOOSE_DIRECTORY_DIALOG,0)
	if dirs:
		return dirs[0]
	return None

def findFiles(view,rootdir,pattern):
	found = []
	def callback((found,pattern), directory, files):
		found.extend([os.path.join(directory,f) \
			for f in files \
			if fnmatch.fnmatch(f,pattern)])
	os.path.walk(rootdir, callback, (found,pattern))
	return found

def main(view):

	# retrieve last used directory
	rootdir = jEdit.getProperty(LAST_DIR,os.getcwd())

	# get directory to search from
	rootdir = getRootDirectory(view,rootdir)
	if not rootdir:
		return

	# save selected directory for next time
	jEdit.setProperty(LAST_DIR,rootdir)

	# get file pattern to search for
	pattern = getFilePattern(view)
	if not pattern:
		return

	# find matching files
	files = [os.path.join(rootdir, f) for f in findFiles(view,rootdir,pattern)]

	# if 1 file found, then open it
	if len(files) == 1:
		jEdit.openFile(view,files[0])
	# if more than 1 file found, then user needs
	# to decide which to open
	elif len(files) > 1:
		FilePicker(view, pattern, rootdir, files)
	# nothing found...
	else:
		view.getStatus().setMessageAndClear("'%s' not found in '%s'." % (pattern,rootdir))


if __name__ in ('__main__','main'):
	main(init.view)

# :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:

