/******************************************************************************* * Copyright (c) 2012 OpenLegacy Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * OpenLegacy Inc. - initial API and implementation *******************************************************************************/ package org.openlegacy.ide.eclipse.components; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.TableEditor; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.openlegacy.ide.eclipse.Messages; import org.openlegacy.terminal.definitions.ScreenFieldDefinition; import org.openlegacy.terminal.definitions.SimpleScreenFieldDefinition; import org.openlegacy.terminal.services.ScreenIdentifier; import org.openlegacy.terminal.support.SimpleScreenIdentifier; public abstract class AbstractTablesComposite extends Composite { protected final static String ITEM_DATA_KEY = "data_key"; private final static String DELETE_BUTTON_ICON_FILENAME = "delete.png"; private Table fieldsTable; private Table identifiersTable; private int biggestColWidth; private int smallestColWidth = 40; private int colCount = 4; private int scrollBarWidth = 21; private int compositeWidth; private int compositeHeight; protected Object field = null; private List<ScreenFieldDefinition> fieldsDefinitions = null; protected List<ScreenFieldDefinition> removedFieldsDefinitions = new ArrayList<ScreenFieldDefinition>(); protected List<ScreenIdentifier> removedScreenIdentifiers = new ArrayList<ScreenIdentifier>(); public AbstractTablesComposite(Composite parent, int style, int width, int height) { super(parent, style); this.compositeWidth = width; this.compositeHeight = height; initialize(); } protected abstract void handleFieldsTableSelectionEvent(SelectionEvent e); protected abstract void handleIdentifiersTableSelectionEvent(SelectionEvent e); protected abstract void handleFieldsTableDeleteButtonSelectionEvent(TableItem item, Table table); protected abstract void handleIdentifiersTableDeleteButtonSelectionEvent(TableItem item, Table table); protected abstract FocusListener getFocusListener(); private void initialize() { GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 1; setLayout(gridLayout); int tableWidth = this.compositeWidth - gridLayout.marginWidth * 2; int tableHeight = (this.compositeHeight - (gridLayout.marginHeight * 2 + gridLayout.verticalSpacing)) / 2; this.biggestColWidth = tableWidth - this.smallestColWidth * (this.colCount - 1) - this.scrollBarWidth; GridData gd = new GridData(GridData.FILL_HORIZONTAL, GridData.FILL_VERTICAL, true, true); gd.widthHint = this.compositeWidth; gd.heightHint = this.compositeHeight; setLayoutData(gd); // GridData for tables gd = new GridData(GridData.FILL_HORIZONTAL, GridData.FILL_VERTICAL, true, true); gd.widthHint = tableWidth; gd.heightHint = tableHeight; // create table of fields this.fieldsTable = new Table(this, SWT.SINGLE | SWT.BORDER); this.fieldsTable.setLinesVisible(true); this.fieldsTable.setHeaderVisible(true); this.fieldsTable.setLayoutData(gd); this.fieldsTable.addSelectionListener(this.getSelectionListener()); this.fieldsTable.addSelectionListener(this.getTableEditor(this.fieldsTable)); gd = new GridData(GridData.FILL_HORIZONTAL, GridData.FILL_VERTICAL, true, true); gd.widthHint = tableWidth; gd.heightHint = tableHeight; // create table of identifiers this.identifiersTable = new Table(this, SWT.SINGLE | SWT.BORDER); this.identifiersTable.setLinesVisible(true); this.identifiersTable.setHeaderVisible(true); this.identifiersTable.setLayoutData(gd); this.identifiersTable.addSelectionListener(this.getSelectionListener()); this.identifiersTable.addFocusListener(this.getFocusListener()); } public void cleanupScreenentityDefinition(Map<String, ScreenFieldDefinition> map, List<ScreenIdentifier> list) { for (ScreenFieldDefinition field : this.removedFieldsDefinitions) { if (map.containsValue(field)) { map.values().remove(field); } } list.removeAll(this.removedScreenIdentifiers); } public void fillTables(List<ScreenFieldDefinition> fields, List<ScreenIdentifier> identifiers) { this.fieldsDefinitions = fields; this.fillColumnFieldsTableHeaders(); this.fillColumnIdentifiersTableHeaders(); this.fillFieldsTable(fields); this.fillIdentifiersTable(identifiers); } private void fillColumnFieldsTableHeaders() { this.fieldsTable.setRedraw(false); String[] titles = { Messages.label_col_fields, Messages.label_col_row, Messages.label_col_column }; for (int i = 0; i <= titles.length; i++) { TableColumn column = new TableColumn(this.fieldsTable, SWT.NONE); column.setText(i != titles.length ? titles[i] : ""); column.setWidth(i == 0 ? this.biggestColWidth : this.smallestColWidth); column.setResizable(false); } this.fieldsTable.setRedraw(true); } private void fillColumnIdentifiersTableHeaders() { this.identifiersTable.setRedraw(false); String[] titles = { Messages.label_col_identifiers, Messages.label_col_row, Messages.label_col_column }; for (int i = 0; i <= titles.length; i++) { TableColumn column = new TableColumn(this.identifiersTable, SWT.NONE); column.setText(i != titles.length ? titles[i] : ""); column.setWidth(i == 0 ? this.biggestColWidth : this.smallestColWidth); column.setResizable(false); } this.identifiersTable.setRedraw(true); } private void fillFieldsTable(List<ScreenFieldDefinition> fields) { this.fieldsTable.setRedraw(false); for (ScreenFieldDefinition field : fields) { TableItem item = new TableItem(this.fieldsTable, SWT.NONE); item.setText(0, field.getName()); item.setText(1, new Integer(field.getPosition().getRow()).toString()); item.setText(2, new Integer(field.getPosition().getColumn()).toString()); item.setData(ITEM_DATA_KEY, field); this.addDeleteBtnToTable(this.fieldsTable, item, 3); } this.fieldsTable.setRedraw(true); } private void fillIdentifiersTable(List<ScreenIdentifier> identifiers) { this.identifiersTable.setRedraw(false); for (ScreenIdentifier identifier : identifiers) { TableItem item = new TableItem(this.identifiersTable, SWT.NONE); SimpleScreenIdentifier ident = ((SimpleScreenIdentifier)identifier); item.setText(0, ident.getText()); item.setText(1, new Integer(ident.getPosition().getRow()).toString()); item.setText(2, new Integer(ident.getPosition().getColumn()).toString()); item.setData(ITEM_DATA_KEY, identifier); this.addDeleteBtnToTable(this.identifiersTable, item, 3); } this.identifiersTable.setRedraw(true); } private void addDeleteBtnToTable(Table table, TableItem item, int colIndex) { TableEditor editor = new TableEditor(table); Button deleteBtn = new Button(table, SWT.NONE); deleteBtn.setSize(table.getItemHeight(), this.smallestColWidth); Image image = new Image(getShell().getDisplay(), this.getClass().getClassLoader().getResourceAsStream( DELETE_BUTTON_ICON_FILENAME)); deleteBtn.setImage(image); deleteBtn.setData(ITEM_DATA_KEY, item); deleteBtn.pack(); deleteBtn.addSelectionListener(this.getDeleteButtonSelectionListener(colIndex)); editor.minimumWidth = deleteBtn.getSize().x; editor.horizontalAlignment = SWT.CENTER; editor.setEditor(deleteBtn, item, colIndex); } private SelectionListener getSelectionListener() { return new SelectionListener() { public void widgetSelected(SelectionEvent e) { AbstractTablesComposite.this.handleSelectionEvent(e); } public void widgetDefaultSelected(SelectionEvent e) { AbstractTablesComposite.this.handleSelectionEvent(e); } }; } private void handleSelectionEvent(SelectionEvent e) { if (e.getSource().equals(AbstractTablesComposite.this.fieldsTable)) { AbstractTablesComposite.this.handleFieldsTableSelectionEvent(e); } else if (e.getSource().equals(AbstractTablesComposite.this.identifiersTable)) { AbstractTablesComposite.this.handleIdentifiersTableSelectionEvent(e); } else { return; } } private SelectionAdapter getTableEditor(final Table table) { final TableEditor editor = new TableEditor(table); return new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { // The editor must have the same size as the cell and must // not be any smaller than 50 pixels. editor.horizontalAlignment = SWT.LEFT; editor.grabHorizontal = true; editor.minimumWidth = 50; final int EDITABLECOLUMN = 0; // Identify the selected row TableItem item = (TableItem)e.item; if (item == null) { return; } // The control that will be the editor must be a child of the Table Text newEditor = new Text(table, SWT.NONE); newEditor.setText(item.getText(EDITABLECOLUMN)); newEditor.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent me) { Text text = (Text)editor.getEditor(); // validate if (text.getText().matches("^[a-zA-Z]{1}\\w*")) { editor.getItem().setText(EDITABLECOLUMN, text.getText()); } else { int caretPos = text.getCaretPosition() - 1; text.setText(editor.getItem().getText(EDITABLECOLUMN)); text.setSelection(caretPos, caretPos); } } }); newEditor.selectAll(); newEditor.setFocus(); newEditor.addFocusListener(new FocusListener() { public void focusLost(FocusEvent e) { ScreenFieldDefinition field = (ScreenFieldDefinition)editor.getItem().getData(ITEM_DATA_KEY); int index = AbstractTablesComposite.this.fieldsDefinitions.indexOf(field); if (index > -1) { ScreenFieldDefinition editableField = AbstractTablesComposite.this.fieldsDefinitions.get(index); ((SimpleScreenFieldDefinition)editableField).setName(editor.getItem().getText()); } // Clean up any previous editor control Control oldEditor = editor.getEditor(); if (oldEditor != null) { oldEditor.dispose(); } AbstractTablesComposite.this.field = null; } public void focusGained(FocusEvent arg0) { return; } }); editor.setEditor(newEditor, item, EDITABLECOLUMN); } }; } private SelectionListener getDeleteButtonSelectionListener(final int colIndex) { return new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { // Identify the selected row TableItem item = (TableItem)e.widget.getData(ITEM_DATA_KEY); if (item == null) { return; } if (!(((Button)e.widget).getParent() instanceof Table)) { return; } Table table = (Table)((Button)e.widget).getParent(); if (table.equals(AbstractTablesComposite.this.fieldsTable)) { AbstractTablesComposite.this.handleFieldsTableDeleteButtonSelectionEvent(item, table); } else if (table.equals(AbstractTablesComposite.this.identifiersTable)) { AbstractTablesComposite.this.handleIdentifiersTableDeleteButtonSelectionEvent(item, table); } // remove button from table e.widget.dispose(); // 'refresh' happens when TableEditor.layout() is called for *all* the tableEditors and it gets called when the // table gets any of these events - SWT.KeyDown, SWT.KeyUp, SWT.MouseDown, SWT.MouseUp, SWT.Resize table.notifyListeners(SWT.MouseDown, new Event()); } }; } }