gdx-studio

#libgdx#java#desktop

git clone https://git.pyrossh.dev/gdx-studio

An IDE for creating Games using libgdx and Java supported on all platforms Android, iOS, Desktop


src/gdxstudio/panel/BaseTable.java
package gdxstudio.panel;
import gdxstudio.Style;

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;

import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSpinner.DefaultEditor;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;

import com.badlogic.gdx.scenes.scene2d.Touchable;

import web.laf.lite.layout.ToolbarLayout;
import web.laf.lite.layout.VerticalFlowLayout;
import web.laf.lite.utils.UIUtils;
import web.laf.lite.widget.NumberTextField;

public abstract class BaseTable extends JPanel implements ActionListener, TableModelListener {
	private static final long serialVersionUID = 1L;
	
	protected DefaultTableModel tableModel = new DefaultTableModel(){
		private static final long serialVersionUID = 1L;

		 @Override
         public Class<?> getColumnClass(int columnIndex) {
             return String.class;
         }
		 
		 public boolean isCellEditable(int row, int column) {
	            if (column == 1)
	                return true;
	            return false;
			}
	};
	public final JTable table = new JTable(tableModel){
		private static final long serialVersionUID = 1L;

		public TableCellEditor getCellEditor(int row, int column)
        {
            int modelColumn = convertColumnIndexToModel( column );
            if (modelColumn == 1){
            	if(row<editors.size())
            		return editors.get(row);
            }
            return super.getCellEditor(row, column);
        }
	};
	protected final JScrollPane scrollPane;
	protected final List<TableCellEditor> editors = new ArrayList<TableCellEditor>(3);
	protected final JButton headerButton;
	
	public BaseTable(String title, DefaultTableModel model, DefaultTableCellRenderer renderer){
		super(new VerticalFlowLayout());
		if(model != null)
			 tableModel = model;
		UIUtils.setShadeWidth(this, 0);
		UIUtils.setRound(this, 0);
		//UIUtils.setDrawSides(this, false, false, false, false);
		table.setTableHeader(null);
		if(renderer != null)
			table.setDefaultRenderer(String.class, renderer);
		else
			table.setDefaultRenderer(String.class, new BaseRenderer());
		table.setShowGrid(true);
		table.setColumnSelectionAllowed(false);
		table.setRowSelectionAllowed(false);
		table.setCellSelectionEnabled(true);
		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		tableModel.setColumnCount(2);
		tableModel.addTableModelListener(this);
		clear();
		headerButton = new Style.TitleButton(title, this);
		if(!title.isEmpty()){
			add(headerButton);
		}
		scrollPane = new JScrollPane(table);
		scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
		scrollPane.setPreferredSize(new Dimension(200, table.getRowCount()*table.getRowHeight()));
		UIUtils.setDrawBorder(scrollPane, false);
		add(scrollPane);
	}
	
	public BaseTable(String title){
		this(title, null, null);
	}
	
	public void lock(){
		tableModel.removeTableModelListener(this);
	}
	
	public void unlock(){
		tableModel.addTableModelListener(this);
	}
	
	public void enable(){
		table.setEnabled(true);
	}
	
	public void disable(){
		table.setEnabled(false);
	}
	
	public void addRow(String key, String value){
		tableModel.addRow(new String[]{key, value});
	}
	
	public void addRow(String key, boolean value){
		tableModel.addRow(new Object[]{key, new Boolean(value)});
	}
	
	public void update(String... propertyAndValueNames){
		if(table.isEditing())
			table.getCellEditor().stopCellEditing();
		tableModel.getDataVector().clear();
		for(int i=0;i<propertyAndValueNames.length;i+=2)
			addRow(propertyAndValueNames[i], propertyAndValueNames[i+1]);
		table.setEnabled(true);
		table.repaint();
	}
	
	public void clear(String... propertyNames){
		if(table.isEditing())
			table.getCellEditor().stopCellEditing();
		tableModel.getDataVector().clear();
		for(int i=0;i<propertyNames.length;i++)
			addRow(propertyNames[i], "");
		table.repaint();
		table.setEnabled(false);
	}
	
	@Override
	public void tableChanged(TableModelEvent e) {
		if(e.getType() == TableModelEvent.UPDATE && e.getLastRow() < tableModel.getRowCount()){
			String key = (String)tableModel.getValueAt(e.getLastRow(), e.getColumn()-1);
			String value = tableModel.getValueAt(e.getLastRow(), e.getColumn()).toString();
			setProperty(key, value);
		}
	}
	
	
	public void setProperty(String name, String value){
	}
	
	public void updateProperty(String key, String value, int row){
		lock();
		tableModel.setValueAt(value, row, 1);
		unlock();
	}
	
	public int getRowCount(){
		return table.getRowCount();
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		scrollPane.setVisible(!scrollPane.isVisible());
		validate();
		repaint();
	}
	
	
	public SpinnerIntegerEditor createIntegerSpinner(final String key){
		final SpinnerIntegerEditor editor = new SpinnerIntegerEditor();
		editor.spinner.addChangeListener(new ChangeListener(){
			@Override
			public void stateChanged(ChangeEvent arg0) {
				setProperty(key, editor.spinner.getValue().toString());
			}
        });
		return editor;
	}
	
	public SpinnerFloatEditor createFloatSpinner(final String key){
		final SpinnerFloatEditor editor = new SpinnerFloatEditor();
		editor.spinner.addChangeListener(new ChangeListener(){
			@Override
			public void stateChanged(ChangeEvent arg0) {
				setProperty(key, editor.spinner.getValue().toString());
			}
        });
		return editor;
	}
	
	public static JSpinner createSpinnerInteger(){
		JSpinner spinner = new JSpinner(new SpinnerNumberModel(new Integer(0), new Integer(-99999),
				new Integer(99999), new Integer(1)));
		UIUtils.setDrawBorder(spinner, false);
		UIUtils.setShadeWidth(spinner, 0);
		UIUtils.setRound(spinner, 0);
		UIUtils.setDrawFocus(spinner, false);
		spinner.setFocusable(false);
		return spinner;
	}
	
	public static JSpinner createSpinnerFloat(){
		JSpinner spinner = new JSpinner(new SpinnerNumberModel(new Float(0), new Float(-99999),
				new Float(99999), new Float(0.1f)));
		UIUtils.setDrawBorder(spinner, false);
		UIUtils.setShadeWidth(spinner, 0);
		UIUtils.setRound(spinner, 0);
		UIUtils.setDrawFocus(spinner, false);
		spinner.setFocusable(false);
		return spinner;
	}
	
	public static DefaultCellEditor createTextFieldEditor(){
		JTextField tf = new JTextField();
		UIUtils.setShadeWidth(tf, 0);
		UIUtils.setRound(tf, 0);
		UIUtils.setDrawFocus(tf, false);
		tf.setFocusable(false);
		return new DefaultCellEditor(tf);
	}
	
	public static JTextField createTextField(){
		JTextField tf = new JTextField();
		UIUtils.setShadeWidth(tf, 0);
		UIUtils.setRound(tf, 0);
		UIUtils.setDrawFocus(tf, false);
		tf.setFocusable(false);
		return tf;
	}
	
	public static DefaultCellEditor createNumberField(){
		NumberTextField tf = new NumberTextField();
		UIUtils.setShadeWidth(tf, 0);
		UIUtils.setRound(tf, 0);
		UIUtils.setDrawFocus(tf, false);
		tf.setFocusable(false);
		return new DefaultCellEditor(tf);
	}
	
	public static JComboBox<String> createComboBox(){
		JComboBox<String> combo = new JComboBox<String>();
		UIUtils.setShadeWidth(combo, 0);
		UIUtils.setRound(combo, 0);
		UIUtils.setDrawFocus(combo, false);
		combo.setFocusable(false);
		return combo;
	}
	
	public static JComboBox<String> createComboBox(String... items){
		JComboBox<String> combo = new JComboBox<String>(items);
		UIUtils.setShadeWidth(combo, 0);
		UIUtils.setRound(combo, 0);
		UIUtils.setDrawFocus(combo, false);
		return combo;
	}
	
	public static DefaultCellEditor createBooleanEditor(){
		return new DefaultCellEditor(createComboBox("false", "true"));
	}
	
	public static DefaultCellEditor createTouchableEditor(){
		return new DefaultCellEditor(createComboBox(Touchable.enabled.toString()
				, Touchable.disabled.toString(), Touchable.childrenOnly.toString()));
	}
	
	public static TableCellEditor createCheckBoxEditor(){
		return new CheckBoxEditor();
	}
}


class BaseRenderer extends DefaultTableCellRenderer {
	private static final long serialVersionUID = 1L;
	JLabel label = new JLabel("      ");
	JCheckBox checkBox = new JCheckBox();
	JSpinner spinnerFloat = BaseTable.createSpinnerFloat();
	JSpinner spinnerInteger = BaseTable.createSpinnerInteger();
	
	public BaseRenderer(){
		spinnerInteger.setBorder(BorderFactory.createEmptyBorder());
		spinnerFloat.setBorder(BorderFactory.createEmptyBorder());
	}

	@Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
		setBorder(noFocusBorder);
		if(column == 0)
        	return new HeaderLabel(value.toString());
		else {
			if(value instanceof Boolean) { // Boolean
	    	    checkBox.setSelected(((Boolean) value).booleanValue());
	    	    checkBox.repaint();
	    	    checkBox.setHorizontalAlignment(JLabel.CENTER);
	    	    return checkBox;
	    	}
		}
        return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
    }
}

class HeaderLabel extends JLabel{
	private static final long serialVersionUID = 1L;

	HeaderLabel(String text){
		super(text);
		setHorizontalAlignment ( JLabel.CENTER );
		UIUtils.setMargin(this, new Insets(0,0,0,0));
		setForeground(Style.font);
	}

	@Override
	public void paint ( Graphics g){
		Style.drawTableHeader(g, getWidth(), getHeight());
		super.paint(g);
	}
}

class ColorEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
	private static final long serialVersionUID = 1L;
	Color currentColor = Color.red;
	JButton button;
	JColorChooser colorChooser;
	JDialog dialog;
	JPanel pan;
	protected static final String EDIT = "edit";

	public ColorEditor() {
		//Set up the editor (from the table's point of view),
		//which is a button.
		//This button brings up the color chooser dialog,
		//which is the editor from the user's point of view.
		button = new JButton();
		button.setActionCommand(EDIT);
		button.addActionListener(this);
		button.setBorderPainted(false);
		button.setRolloverEnabled(false);
		button.setOpaque(true);
		pan = new JPanel(new ToolbarLayout());
		pan.setOpaque(false);
		UIUtils.setMargin(pan, new Insets(2,3,2,3));
		pan.add(button);
		//Set up the dialog that the button brings up.
		colorChooser = new JColorChooser();
		dialog = JColorChooser.createDialog(button,
				"Pick a Color",true,  //modal
				colorChooser,
				this,  //OK button handler
				null); //no CANCEL button handler
	}

	/**
	 * Handles events from the editor button and from
	 * the dialog's OK button.
	 */
	public void actionPerformed(ActionEvent e) {
		if (EDIT.equals(e.getActionCommand())) {
			//The user has clicked the cell, so
			//bring up the dialog.
			button.setBackground(currentColor);
			colorChooser.setColor(currentColor);
			dialog.setVisible(true);

			//Make the renderer reappear.
			fireEditingStopped();

		} else { //User pressed dialog's "OK" button.
			currentColor = colorChooser.getColor();
			dialog.setVisible(false);
		}
	}

	//Implement the one CellEditor method that AbstractCellEditor doesn't.
	@Override
	public String getCellEditorValue() {
		return String.format("%02x%02x%02x%02x",currentColor.getRed(), 
				currentColor.getGreen(), currentColor.getBlue(), currentColor.getAlpha());
	}

	//Implement the one method defined by TableCellEditor.
	@Override
	public Component getTableCellEditorComponent(JTable table,
			Object value,
			boolean isSelected,
			int row,
			int column) {
		String colorString = (String) value;
		if(colorString.length() == 8 && colorString.matches("[0-9A-Fa-f]+")){
			 com.badlogic.gdx.graphics.Color cl = com.badlogic.gdx.graphics.Color.valueOf(colorString);
			 currentColor = new Color(cl.r, cl.g, cl.b, cl.a);
		}
		return pan;
	}

	@Override
	public void addCellEditorListener(CellEditorListener arg0) {
		super.addCellEditorListener(arg0);
	}

	@Override
	public void cancelCellEditing() {
		dialog.setVisible(false);
		super.cancelCellEditing();
	}

	@Override
	public boolean isCellEditable(EventObject arg0) {
		return true;
	}

	@Override
	public void removeCellEditorListener(CellEditorListener arg0) {
		super.removeCellEditorListener(arg0);
	}

	@Override
	public boolean shouldSelectCell(EventObject arg0) {
		return super.shouldSelectCell(arg0);
	}

	@Override
	public boolean stopCellEditing() {
		dialog.setVisible(false);
		return super.stopCellEditing();
	}
}

class CheckBoxEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
	private static final long serialVersionUID = 1L;
	private JCheckBox checkBox;
	
	public CheckBoxEditor() {
		checkBox = new JCheckBox();
		checkBox.setHorizontalAlignment(JLabel.LEFT);
		//checkBox.addActionListener(this);
	}
	
	public CheckBoxEditor(boolean value) {
		checkBox = new JCheckBox();
		checkBox.setSelected(value);
		checkBox.setHorizontalAlignment(JLabel.LEFT);
		//checkBox.addActionListener(this);
	}
	
	/**
	 * Handles events from the editor button and from
	 * the dialog's OK button.
	 */
	public void actionPerformed(ActionEvent e) {
	}

	//Implement the one CellEditor method that AbstractCellEditor doesn't.
	@Override
	public Boolean getCellEditorValue() {
		return checkBox.isSelected();
	}

	//Implement the one method defined by TableCellEditor.
	@Override
	public Component getTableCellEditorComponent(JTable table,
			Object value,
			boolean isSelected,
			int row,
			int column) {
		checkBox.setSelected(((Boolean) value).booleanValue());
		checkBox.repaint();
		return checkBox;
	}

	@Override
	public void addCellEditorListener(CellEditorListener arg0) {
		super.addCellEditorListener(arg0);
	}

	@Override
	public void cancelCellEditing() {
		super.cancelCellEditing();
	}

	@Override
	public boolean isCellEditable(EventObject arg0) {
		return true;
	}

	@Override
	public void removeCellEditorListener(CellEditorListener arg0) {
		super.removeCellEditorListener(arg0);
	}

	@Override
	public boolean shouldSelectCell(EventObject arg0) {
		return super.shouldSelectCell(arg0);
	}

	@Override
	public boolean stopCellEditing() {
		return super.stopCellEditing();
	}
}

class SpinnerIntegerEditor extends AbstractCellEditor implements TableCellEditor {
	private static final long serialVersionUID = 1L;
	JSpinner spinner;

    // Initializes the spinner.
    public SpinnerIntegerEditor() {
        spinner = BaseTable.createSpinnerInteger();
        spinner.setBorder(BorderFactory.createEmptyBorder());
        ((DefaultEditor) spinner.getEditor()).getTextField().setEditable(false);
    }

    // Prepares the spinner component and returns it.
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
    		int row, int column) {
    	float f = (Float) Float.parseFloat(value.toString());
        spinner.setValue((int) f);
        return spinner;
    }

    public boolean isCellEditable( EventObject eo ) {
        return true;
    }

    // Returns the spinners current value.
    public Object getCellEditorValue() {
        return spinner.getValue();
    }

    public boolean stopCellEditing() {
        try {
            spinner.commitEdit();
        } catch ( java.text.ParseException e ) {
            JOptionPane.showMessageDialog(null,"Invalid value, discarding.");
        }
        return super.stopCellEditing();
    }
}

class SpinnerFloatEditor extends AbstractCellEditor implements TableCellEditor {
	private static final long serialVersionUID = 1L;
	JSpinner spinner;

    // Initializes the spinner.
    public SpinnerFloatEditor() {
        spinner = BaseTable.createSpinnerFloat();
        spinner.setBorder(BorderFactory.createEmptyBorder());
        ((DefaultEditor) spinner.getEditor()).getTextField().setEditable(false);
    }

    // Prepares the spinner component and returns it.
    public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
    		int row, int column) {
        spinner.setValue((Float)Float.parseFloat(value.toString()));
        return spinner;
    }

    public boolean isCellEditable( EventObject eo ) {
        return true;
    }

    // Returns the spinners current value.
    public Object getCellEditorValue() {
        return spinner.getValue();
    }

    public boolean stopCellEditing() {
        try {
            spinner.commitEdit();
        } catch ( java.text.ParseException e ) {
            JOptionPane.showMessageDialog(null, "Invalid value, discarding.");
        }
        return super.stopCellEditing();
    }
}