JTextField para nomes

Para quem necessitar, segue um modelo de JTextField para nomes, que coloca automaticamente as primeiras letras do nome em maíusculo enquanto o usuário digita, ele reconhece casos como "Pedro da Silva" e "José C. da Silva"; qualquer dúvida ou sugestões enviem comentários.

[code]
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public class NomeTextField2 extends JTextField
{
public NomeTextField2()
{
super();
setDocument(new PlainDocument()
{
@Override
public void insertString(int offs, String str, AttributeSet a)
throws BadLocationException
{
if (offs != 0 && str.contains(" "))
{
ajustaTexto();
}
super.insertString(offs, str, a);
}
});
addFocusListener(new FocusListener()
{

		@Override
		public void focusLost(FocusEvent e)
		{
			ajustaTexto();
		}

		@Override
		public void focusGained(FocusEvent e)
		{
		}
	});
}

private void ajustaTexto()
{
	setText(PrimeiraMaiuscula(getText()));
}

private String PrimeiraMaiuscula(String o)
{
	if (o == null)
	{
		return null;
	}
	StringBuffer nome = new StringBuffer();
	String[] tmp;
	tmp = o.toLowerCase().split(" ");
	for (int i = 0; i < tmp.length; i++)
	{
		if (tmp[i].length() > 2 || (tmp[i].length() == 2 && tmp[i].substring(1, 2).equals(".")))
		{
			nome.append(tmp[i].replaceFirst(tmp[i].substring(0, 1), tmp[i].substring(0, 1)
					.toUpperCase())
					+ " ");
		}
		else
		{
			nome.append(tmp[i] + " ");
		}
	}
	return nome.toString().trim();
}

}[/code]

Pelo código, se eu entrar com “Jô Soares”, ele vai passar o nome para “jô Soares”, não? Assim como outros nomes, sobrenomes e apelidos com duas letras - Zé, Jó, Li (um nome chinês), Ah (um nome coreano), etc.

Realmente, é bem difícil fazer “capitalization” - o nome desse troço em inglês (deixar as palavras começando por maiúsculas, mas não todas). Eu me lembro de um livro bem antigo de C++ onde um dos exercícios era exatamente esse, e o autor ficava se estendendo por páginas e páginas por causa dos casos particulares.

É verdade, como fiz pensando em meu uso, onde não há cadastro de apelidos e nomes estrangeiros, não me preocupei, mas isso pode ser facilmente incluído, bastando utilizar um array com os “de, do,dos” que ligam os sobrenomes de algumas pessoas.

É justamente por isso que estou enviando o código e não apenas o jar, para que cada um possa adaptá-lo à sua necessidade.

Essa nova versão ficou melhor, tem um hashset de prefixos de nomes que pode ser personalizado.

public class NomeTextField2 extends JTextField
{
       private static final Set<String> prefixos = new HashSet<String>(Arrays.asList(new String[] {
			"da", "das", "de", "do", "dos" }));

	public NomeTextField2()
	{
		super();
		setDocument(new PlainDocument()
		{
			@Override
			public void insertString(int offs, String str, AttributeSet a)
					throws BadLocationException
			{
				if (offs != 0 && str.contains(" "))
				{
					ajustaTexto();
				}
				super.insertString(offs, str, a);
			}
		});
		addFocusListener(new FocusListener()
		{

			@Override
			public void focusLost(FocusEvent e)
			{
				ajustaTexto();
			}

			@Override
			public void focusGained(FocusEvent e)
			{
			}
		});
	}

	private void ajustaTexto()
	{
		setText(PrimeiraMaiuscula(getText()));
	}

	private String PrimeiraMaiuscula(String o)
	{
		if (o == null)
		{
			return null;
		}
		StringBuffer nome = new StringBuffer();
		String[] tmp;
		tmp = o.toLowerCase().split(" ");
		
		for (int i = 0; i < tmp.length; i++)
		{
			if (!prefixos.contains(tmp[i]))
			{
				nome.append(tmp[i].replaceFirst(tmp[i].substring(0, 1), tmp[i].substring(0, 1)
						.toUpperCase())
						+ " ");
			}
			else
			{
				nome.append(tmp[i] + " ");
			}
		}
		return nome.toString().trim();
	}
}