Towel release 1.1

Opa, vou usar sim. Vai estar no proximo release, obrigado.

Quem tiver mais AggregateFunctions interessantes pode enviar também :smiley:

Olá Marky,

Duvida simples , eu tenho um codigo para carregar uma tabela e eu estou querendo que apenas uma unica coluna possa ser editada, mas acontece um erro de null.

...
public LayoutFilesTopComponent() {
        initComponents();
        setName(NbBundle.getMessage(LayoutFilesTopComponent.class, "CTL_LayoutFilesTopComponent"));
        setToolTipText(NbBundle.getMessage(LayoutFilesTopComponent.class, "HINT_LayoutFilesTopComponent"));        
        FieldResolverFactory tab = new FieldResolverFactory(TbParlayout.class);
        FieldResolver ord = tab.createResolver("ordem", "Ordem");
        FieldResolver ativo = tab.createResolver("ativo", "Ativo");
        FieldResolver alias = tab.createResolver("alias", "Alias");        
        ativo.setFormatter(new FormatAtivo());
        base = new ObjectTableModel<TbParlayout>(new FieldResolver[]{ativo, ord, alias});        
    }

...
private void jComboBox1ItemStateChanged(java.awt.event.ItemEvent evt) {
        base.setData(dados.getResult((String) jComboBox1.getSelectedItem()));      
        eTable1.setModel(base);        
        base.setColEditable(2, true);      
        
    }
...

onde estou errando ?

hello !!

Acho que isso pode ajudar, eu geralmente uso fieldresolver porque assim eu não preciso mexer nas minhas classes de entidades.
Então comecei a investigar o erro e achei a diferença e acredito que seja um possível bug.

O setColEditable não funciona quando vc usa o fieldresolver apenas quando se utiliza o annotations.

Será que essa é a unica solução ?!

abraços
Daniel

Achei o Erro,

Como eu falei, o erro não ocorre quando se utiliza Annotations.
Tomei a liberdade de fazer um download do codigo e achei o erro !!!

Existe uma diferença no construtor da classe ObjectTableModel, quando se usa o construtor com AnnotationResolver ele inicializa o array editableCol, bom direto no codigo vejam :

Código Original

...
public ObjectTableModel(AnnotationResolver resolver, String cols) {
		data = new ArrayList<T>();
		this.fields = (FieldResolver[]) resolver.resolve(cols).clone();
		editDefault = false;
		editableCol = new Boolean[fields.length];
	}
...
public ObjectTableModel(FieldResolver fields[]) {
		data = new ArrayList<T>();
		this.fields = (FieldResolver[]) fields.clone();
		editDefault = false;               
	}
...

Agora apenas o construtor alterado

...
public ObjectTableModel(FieldResolver fields[]) {
		data = new ArrayList<T>();
		this.fields = (FieldResolver[]) fields.clone();
		editDefault = false; 
                editableCol = new Boolean[fields.length]; // Aqui está a diferença !!
	}
...

é isso ai, valeu !

abcs
Daniel

Nossa… nunca tinha reparado.

Obrigado, já vou atualizar no projeto.

Tarde!!!

Mark, é possível fazer um format de uma coluna para que seja um combo ?

abcs !

Daniel

olá amigos !! bom dia novamente !!

Pessoal realmente não sei mais oq fazer:
tenho um combo box que quando tento dar um refresh os dados ficam em branco.

vou colocar uma parte do codigo para ilustrar melhor :

//var
 private ObjectComboBoxModel<TbLayout> combolayout;
 private ConsParLay daolayout;
...
//inicialização 
 daolayout = Lookup.getDefault().lookup(ConsParLay.class); // query na base de dados
 combolayout = new ObjectComboBoxModel<TbLayout>();
 combolayout.setFormatter(new layoutFormat());
 jComboBox1.setModel(combolayout);

// momento quando a janela é aberta
@Override
    public void componentOpened() {
        loadCombo1();        
    }
public void loadCombo1(){
        combolayout.clear();
        combolayout.setData(daolayout.getLayout());
        combolayout.setSelectedItem(null);        
    }

//formatter
class layoutFormat implements Formatter {
        @Override
        public String format(Object arg0) {
            if(arg0==null)
                return null;
            TbLayout a = (TbLayout) arg0;           
            return a.getLayout();
        }
        @Override
        public String getName() {
            return "Layout";
        }
        @Override
        public Object parse(Object arg0) {
            return null;//Never get invoked, JComboBox cannot be editable
        }
    }    

//novo layout

 private void jButton11ActionPerformed(java.awt.event.ActionEvent evt) {                                          
        
        TbLayout n = new TbLayout();
        n.setLayout(jTextField2.getText());       
        daolayout.Save(n);
        daolayout.Commit();
        loadCombo1();
        
        jTextField2.setText("");
        jTextField2.setEditable(false);
        
        
    } 

Sinceramente não sei mais oq fazer para arrumar, faço isso em outras coisas e funciona perfeitamente.

abraços
Daniel

Voce consegue reproduzir de uma maneira mais simples para isolarmos o problema?

É só criar um código simples com objetos fakes e invés de um DAO voce usa alguma List.

ok, fiz outra tela apenas com um combo e um botao, mas da o mesmo problema.

segue :

public final class tesTopComponent extends TopComponent {
List<TbLayout> l = new ArrayList<TbLayout>();
    private ObjectComboBoxModel<TbLayout> combolayout;

    public tesTopComponent() {
        initComponents();
        setName(NbBundle.getMessage(tesTopComponent.class, "CTL_tesTopComponent"));
        setToolTipText(NbBundle.getMessage(tesTopComponent.class, "HINT_tesTopComponent"));
        combolayout = new ObjectComboBoxModel<TbLayout>();
        combolayout.setFormatter(new layoutFormat());
        jComboBox1.setModel(combolayout);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        jComboBox1 = new javax.swing.JComboBox();
        jButton1 = new javax.swing.JButton();

        org.openide.awt.Mnemonics.setLocalizedText(jButton1, org.openide.util.NbBundle.getMessage(tesTopComponent.class, "tesTopComponent.jButton1.text")); // NOI18N
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(107, 107, 107)
                        .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, 182, javax.swing.GroupLayout.PREFERRED_SIZE))
                    .addGroup(layout.createSequentialGroup()
                        .addGap(162, 162, 162)
                        .addComponent(jButton1)))
                .addContainerGap(111, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(41, 41, 41)
                .addComponent(jComboBox1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(18, 18, 18)
                .addComponent(jButton1)
                .addContainerGap(198, Short.MAX_VALUE))
        );
    }// </editor-fold>

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
 TbLayout c=new TbLayout(System.currentTimeMillis());
        c.setLayout("teste1"+System.currentTimeMillis());
        l.add(c);
        //combolayout.setData(daolayout.getLayout());
        combolayout.setData(l);        // TODO add your handling code here:
    }

    // Variables declaration - do not modify
    private javax.swing.JButton jButton1;
    private javax.swing.JComboBox jComboBox1;
    // End of variables declaration
    @Override
    public void componentOpened() {
        TbLayout c=new TbLayout(System.currentTimeMillis());
        c.setLayout("teste1"+System.currentTimeMillis());
        l.add(c);
        //combolayout.setData(daolayout.getLayout());
        combolayout.setData(l);
        combolayout.setSelectedItem(null);  
    }

    @Override
    public void componentClosed() {
        // TODO add custom code on component closing
    }

    void writeProperties(java.util.Properties p) {
        // better to version settings since initial version as advocated at
        // http://wiki.apidesign.org/wiki/PropertyFiles
        p.setProperty("version", "1.0");
        // TODO store your settings
    }

    void readProperties(java.util.Properties p) {
        String version = p.getProperty("version");
        // TODO read your settings according to their version
    }
    
    class layoutFormat implements Formatter {
        @Override
        public String format(Object arg0) {
            if(arg0==null)
                return null;
            TbLayout a = (TbLayout) arg0;           
            return a.getLayout();
        }
        @Override
        public String getName() {
            return "Layout";
        }
        @Override
        public Object parse(Object arg0) {
            return null;//Never get invoked, JComboBox cannot be editable
        }
    }    

Tarde !!!

Marky, depois de muito quebrar a cabeça fiz alguns testes e que aqui funcionou, agora eu não sei te falar se o problema acontece apenas para quem desenvolve com netbeans ( que é o meu caso ), acabei fazendo mais um teste com uma jframe bem simples fora de um netbeans module, e também ocorre o problema…

…depois de pesquisar em alguns forum e conversar com um colega aqui do banco, que me perguntou sobre os eventos de atualização ( fireContentsChanged,fireIntervalAdded ) resolvir fazer alguns alterações que funcionaram, ok até aqui resolvido !!!
Mas com isso apareceu um outro problema, quando vc usa apenas o add os itens são duplicados e ainda não achei uma solução para isso…

Enfim fica aqui o workaround !!!

abraços !

segue o codigo alterado :

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.think.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.ComboBoxModel;

import com.towel.bean.DefaultFormatter;
import com.towel.bean.Formatter;
import javax.swing.AbstractListModel;




public class ObjectComboBoxModel<T> extends AbstractListModel implements ComboBoxModel {
	private List<T> data;
	private T selectedItem;
	private Formatter formatter;
	private Map<Object, T> maps = new HashMap<Object, T>();

	public ObjectComboBoxModel() {
		data = new ArrayList<T>();
		formatter = new DefaultFormatter();
                //
	}

	public void setFormatter(Formatter formatter) {
		if (formatter == null) {
			System.out.println("Formatter can't be null. A default one will be set.");
			formatter = new DefaultFormatter();
		}

		this.formatter = formatter;
		maps.clear();
		for (T t : data){
                   maps.put(formatter.format(t), t); 
                }
                
                
	}

//	public void add(T obj) {
//		data.add(obj);
//		maps.put(formatter.format(obj), obj);
//                
//	}

	public void clear() {
		data.clear();
		maps.clear();
	}

	public void setData(List<T> list) {
		data = list;
		maps.clear();
		for (T t : data){
                    maps.put(formatter.format(t), t);                   
                } 
             fireContentsChanged(data, 0, data.size()-1);

	}

	public T getSelectedObject() {
		return selectedItem;
	}

	@Override
	public Object getSelectedItem() {
		return formatter.format(selectedItem);
	}

	@Override
	public void setSelectedItem(Object arg0) {
		selectedItem = maps.get(arg0);

	}

	public void setSelectedObject(T obj) {
		selectedItem = obj;
	}

	@Override
	public Object getElementAt(int arg0) {
		return formatter.format(data.get(arg0));
	}

	@Override
	public int getSize() {
		return data.size();
	}

//	@Override
//	public void addListDataListener(ListDataListener l) {
//	}
//
//	@Override
//	public void removeListDataListener(ListDataListener l) {
//	}
}

Bom dia !

Apenas para fazer uma correção sobre o código acima, não é preciso excluir o metodo add(obj).

O erro era do meu código de teste !

abraços
Daniel

O seu problema foi resolvido?

Precisou modficar algo do Towel?

Eu tive que alterar sim, eu fiz um extend do AbstractListModel para poder usar os eventos de fireXXXX e deste modo não precisa implementar os listeners addListDataListener e removeListDataListener.

Fiz vários testes e em qualquer situação o combo é atualizado, bom segue o codigo alterado !!

abraços
Daniel

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.ComboBoxModel;
import com.towel.bean.DefaultFormatter;
import com.towel.bean.Formatter;
import javax.swing.AbstractListModel;




public class ObjectComboBoxModel<T> extends AbstractListModel implements ComboBoxModel {
	private List<T> data;
	private T selectedItem;
	private Formatter formatter;
	private Map<Object, T> maps = new HashMap<Object, T>();

	public ObjectComboBoxModel() {
		data = new ArrayList<T>();
		formatter = new DefaultFormatter();                
	}

	public void setFormatter(Formatter formatter) {
		if (formatter == null) {
			System.out.println("Formatter can't be null. A default one will be set.");
			formatter = new DefaultFormatter();
		}

		this.formatter = formatter;
		maps.clear();
		for (T t : data){
                   maps.put(formatter.format(t), t); 
                }
                
                
	}

	public void add(T obj) {
		data.add(obj);
		maps.put(formatter.format(obj), obj);
                fireIntervalAdded(data, data.size()-1, data.size()-1);
	}

	public void clear() {
		data.clear();
		maps.clear();
	}

	public void setData(List<T> list) {
		data = list;
		maps.clear();
		for (T t : data){
                    maps.put(formatter.format(t), t);                   
                } 
             fireContentsChanged(data, 0, data.size()-1);

	}

	public T getSelectedObject() {
		return selectedItem;
	}

	@Override
	public Object getSelectedItem() {
		return formatter.format(selectedItem);
	}

	@Override
	public void setSelectedItem(Object arg0) {
		selectedItem = maps.get(arg0);

	}

	public void setSelectedObject(T obj) {
		selectedItem = obj;
	}

	@Override
	public Object getElementAt(int arg0) {
		return formatter.format(data.get(arg0));
	}

	@Override
	public int getSize() {
		return data.size();
	}

        
//	@Override
//	public void addListDataListener(ListDataListener l) {
//	}
//
//	@Override
//	public void removeListDataListener(ListDataListener l) {
//	}
}

Valeu, vou atualizar no projeto.

Fala Marky,

Pergunta: o Towel não implementa nada para utilizar o JList ?

ou você tem outra sugestão ?

abraços
Daniel