"""
Make_Accessors.py - A Jython macro for jEdit that creates
getters and setters for Java class members. This macro reads
the current source file, and tries to pick out member
declarations. It displays these in a table and you can pick
which get/set methods you would like created.

Copyright (C) 2002 Ollie Rutherfurd <oliver@rutherfurd.net>

$Id: Make_Accessors.py 51 2003-07-23 20:48:53Z oliver $
"""

__author__ = 'Ollie Rutherfurd'
__version__ = '$Revision: 1.11 $'[11:-2]

from java.awt import BorderLayout
from java.awt.event import ActionListener, KeyListener
from java.lang import Boolean, String
from javax.swing import Box, BoxLayout, JButton, JDialog, \
	 JLabel, JPanel, JScrollPane, JTable, JTextArea
from javax.swing.border import EmptyBorder
from javax.swing.table import DefaultTableModel
from org.gjt.sp.jedit import Macros
import re


class MembersModel(DefaultTableModel):

	# TODO: fix so final and/or static members are found
	DECLARATION = re.compile(r'^\s*(?:private|protected)\s+([^\s]+)\s+([^\s]+)\s*;$')
	COLS = ('Getter','Setter','Type','Name')

	def __init__(self,buff):
		self.members = []

		DefaultTableModel.__init__(self)

		for i in range(buff.getLineCount()):
			line  = buff.getLineText(i)
			m = self.DECLARATION.match(line)
			if m:
				type,name = m.groups()
				# TODO: figure out whether get/set
				#	is needed
				self.members.append([1,1,type,name])

	def getColumnCount(self):
		"""@sig int getColumnCount()"""
		return 4

	def getRowCount(self):
		"""@sig int getRowCount()"""
		return len(self.members)

	def getColumnClass(self,c):
		"""@sig Class getColumnClass(int c)"""
		if c in (0,1):
			return Boolean(0).getClass()
		return String('').getClass()

	def isCellEditable(self,r,c):
		"""@sig boolean isCellEditable(int r, int c)"""
		if c in (0,1):
			return 1
		return 0

	def getColumnName(self,c):
		"""@sig String getColumnName(int c)"""
		return self.COLS[c]

	def getValueAt(self,r,c):
		"""@sig Object getValueAt(int r,int c)"""
		if c in (0,1):
			return Boolean(self.members[r][c])
		return self.members[r][c]

	def setValueAt(self,v,r,c):
		"""@sig void setValueAt(Object v, int r, int c)"""
		self.members[r][c] = v


class MakeAccessors(JDialog,ActionListener,KeyListener):

	def __init__(self,view,title='Make Accessors',modal=1):
		JDialog.__init__(self,view,title,modal)

		self.view = view

		content = JPanel(BorderLayout())
		content.border = EmptyBorder(10,10,10,10)
		self.contentPane = content

		self.membersModel = MembersModel(view.getBuffer())
		self.output = JTextArea(26,60)

		panel = JPanel(border=EmptyBorder(5,5,5,5))
		panel.layout = BoxLayout(panel, BoxLayout.Y_AXIS)
		panel.add(Box.createGlue())
		panel.add(JLabel('Members:'))
		panel.add(Box.createVerticalStrut(6))
		panel.add(JScrollPane(JTable(self.membersModel)))
		panel.add(Box.createVerticalStrut(6))
		panel.add(JLabel('Output:'))
		panel.add(Box.createVerticalStrut(6))
		panel.add(JScrollPane(self.output))
		panel.add(Box.createGlue())

		content.add(panel,BorderLayout.CENTER)

		panel = JPanel(border=EmptyBorder(10,50,0,50))
		panel.layout = BoxLayout(panel,BoxLayout.X_AXIS)
		panel.add(Box.createGlue())
		self.genBtn = JButton('Create',actionPerformed=self.actionPerformed)
		self.insBtn = JButton('Insert',actionPerformed=self.actionPerformed)
		self.closeBtn = JButton('Close',actionPerformed=self.actionPerformed)
		self.getRootPane().setDefaultButton(self.genBtn)
		panel.add(self.genBtn)
		panel.add(Box.createHorizontalStrut(6))
		panel.add(self.insBtn)
		panel.add(Box.createHorizontalStrut(6))
		panel.add(self.closeBtn)
		panel.add(Box.createGlue())

		content.add(panel,BorderLayout.SOUTH)

		self.pack()
		self.setSize(450,500)
		self.setLocationRelativeTo(view)
		self.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE)
		self.show()

	def actionPerformed(self,evt):
		if evt.getSource() == self.genBtn:
			self.genCode()
		elif evt.getSource() == self.insBtn:
			self.view.getTextArea().setSelectedText(self.output.getText())
		else:
			self.view = None
			self.close()

	def genCode(self):
		code = []
		text = self.view.getTextArea().getText()
		for (mk_getter,mk_setter,type,name) in self.membersModel.members:
			if mk_getter:
				getter = makeGetter((type,name))
				# TODO: fix so final methods will be found
				if text.find(getter.split('\n')[1][:-1].strip()) == -1:
					code.append(getter)
			if mk_setter:
				setter = makeSetter((type,name))
				# TODO: fix so final methods will be found
				if text.find(setter.split('\n')[1][:-1].strip()) == -1:
					code.append(setter)
		self.output.setText(''.join(code))

	def close(self):
		self.dispose()


def makeGetter((type,name)):
	return """
	public %s get%s(){
		return this.%s;
	}
""" % (type,name[0].upper() + name[1:],name,)


def makeSetter((type,name)):
	return """
	public void set%s(%s %s){
		this.%s = %s;
	}
""" % (name[0].upper() + name[1:],
	type,name,name,name,)


def main():

	if not init.buffer.mode.name == 'java':
		Macros.error(init.view, \
			'This macro only works with Java buffers. This buffer is %s.' \
			% (init.buffer.mode.name,))
		return

	d = MakeAccessors(init.view)


if __name__ in ('__main__','main'):
	main()

# :indentSize=4:lineSeparator=\n:noTabs=false:tabSize=4:

