/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.ui.editors.object.struct;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.core.CoreMessages;
import org.jkiss.dbeaver.core.DBeaverCore;
import org.jkiss.dbeaver.core.DBeaverUI;
import org.jkiss.dbeaver.model.DBPEvaluationContext;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.runtime.DBRRunnableWithProgress;
import org.jkiss.dbeaver.model.struct.DBSEntity;
import org.jkiss.dbeaver.model.struct.DBSEntityAttribute;
import org.jkiss.dbeaver.ui.DBeaverIcons;
import org.jkiss.dbeaver.ui.UIUtils;
import org.jkiss.dbeaver.ui.controls.CustomTableEditor;
import org.jkiss.dbeaver.ui.controls.TableColumnSortListener;
import org.jkiss.utils.CommonUtils;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.List;
/**
* AttributesSelectorPage
*
* @author Serge Rider
*/
public abstract class AttributesSelectorPage extends BaseObjectEditPage {
protected DBSEntity entity;
protected Table columnsTable;
protected List<AttributeInfo> attributes = new ArrayList<>();
protected Button toggleButton;
protected Group columnsGroup;
protected static class AttributeInfo {
DBSEntityAttribute attribute;
int position;
Map<String, Object> properties = new HashMap<>();
public AttributeInfo(DBSEntityAttribute attribute)
{
this.attribute = attribute;
this.position = -1;
}
public DBSEntityAttribute getAttribute() {
return attribute;
}
public int getPosition() {
return position;
}
public Object getProperty(String name) {
return properties.get(name);
}
public void setProperty(String name, Object value) {
if (value == null) {
properties.remove(name);
} else {
properties.put(name, value);
}
}
@Override
public String toString() {
return attribute.getName();
}
}
public AttributesSelectorPage(
String title,
DBSEntity entity)
{
super(NLS.bind(CoreMessages.dialog_struct_columns_select_title, title, entity.getName()));
this.entity = entity;
}
public Map<String, Object> getAttributeProperties(DBSEntityAttribute attr) {
for (AttributeInfo attrInfo : attributes) {
if (attrInfo.attribute == attr) {
return attrInfo.properties;
}
}
return Collections.emptyMap();
}
public Object getAttributeProperty(DBSEntityAttribute attr, String propName) {
for (AttributeInfo attrInfo : attributes) {
if (attrInfo.attribute == attr) {
return attrInfo.properties.get(propName);
}
}
return null;
}
@Override
protected Composite createPageContents(Composite parent) {
final Composite panel = UIUtils.createPlaceholder(parent, 1);
panel.setLayoutData(new GridData(GridData.FILL_BOTH));
{
final Composite tableGroup = createTableNameInput(panel);
createContentsBeforeColumns(tableGroup);
}
createColumnsGroup(panel);
createContentsAfterColumns(panel);
fillAttributes(entity);
return panel;
}
protected void createColumnsGroup(Composite panel)
{
columnsGroup = UIUtils.createControlGroup(panel, CoreMessages.dialog_struct_columns_select_group_columns, 1, GridData.FILL_BOTH, 0);
//columnsViewer = new TableViewer(columnsGroup, SWT.BORDER | SWT.SINGLE | SWT.CHECK);
columnsTable = new Table(columnsGroup, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION | SWT.CHECK);
columnsTable.setHeaderVisible(true);
GridData gd = new GridData(GridData.FILL_BOTH);
//gd.widthHint = 300;
//gd.heightHint = 200;
columnsTable.setLayoutData(gd);
columnsTable.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e)
{
handleItemSelect((TableItem) e.item, true);
}
});
createAttributeColumns(columnsTable);
final CustomTableEditor tableEditor = new CustomTableEditor(columnsTable) {
@Override
protected Control createEditor(Table table, final int index, final TableItem item) {
return createCellEditor(table, index, item, (AttributeInfo)item.getData());
}
@Override
protected void saveEditorValue(Control control, int index, TableItem item) {
saveCellValue(control, index, item, (AttributeInfo)item.getData());
}
};
toggleButton = new Button(columnsGroup, SWT.PUSH);
toggleButton.setText("Select All");
gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
gd.widthHint = 120;
toggleButton.setLayoutData(gd);
toggleButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e)
{
TableItem[] items = columnsTable.getItems();
if (hasCheckedColumns()) {
// Clear all checked
for (TableItem item : items) {
if (item.getChecked()) {
item.setChecked(false);
handleItemSelect(item, true);
}
}
} else {
// Check all
for (TableItem item : items) {
if (!item.getChecked()) {
item.setChecked(true);
handleItemSelect(item, true);
}
}
}
}
});
}
protected void createAttributeColumns(Table columnsTable) {
TableColumn colName = UIUtils.createTableColumn(columnsTable, SWT.NONE, CoreMessages.dialog_struct_columns_select_column);
colName.addListener(SWT.Selection, new TableColumnSortListener(columnsTable, 0));
TableColumn colPosition = UIUtils.createTableColumn(columnsTable, SWT.CENTER, "#"); //$NON-NLS-1$
colPosition.addListener(SWT.Selection, new TableColumnSortListener(columnsTable, 1));
TableColumn colType = UIUtils.createTableColumn(columnsTable, SWT.RIGHT, "Type"); //$NON-NLS-1$
colType.addListener(SWT.Selection, new TableColumnSortListener(columnsTable, 2));
}
protected int fillAttributeColumns(DBSEntityAttribute attribute, AttributeInfo attributeInfo, TableItem columnItem) {
columnItem.setText(0, attribute.getName());
columnItem.setText(1, String.valueOf(attribute.getOrdinalPosition()));
columnItem.setText(2, attribute.getFullTypeName());
return 2;
}
protected Control createCellEditor(Table table, int index, TableItem item, AttributeInfo data) {
/*
final Text text = new Text(table, SWT.BORDER);
text.setText(item.getText(index));
text.selectAll();
return text;
*/
return null;
}
protected void saveCellValue(Control control, int index, TableItem item, AttributeInfo data) {
//item.setText(index, control.getText());
}
protected void fillAttributes(final DBSEntity entity)
{
// Collect attributes
final List<DBSEntityAttribute> attributes = new ArrayList<>();
try {
DBeaverUI.runInProgressService(new DBRRunnableWithProgress() {
@Override
public void run(DBRProgressMonitor monitor) throws InvocationTargetException, InterruptedException
{
try {
for (DBSEntityAttribute attr : CommonUtils.safeCollection(entity.getAttributes(monitor))) {
if (!DBUtils.isHiddenObject(attr)) {
attributes.add(attr);
}
}
} catch (DBException e) {
throw new InvocationTargetException(e);
}
}
});
} catch (InvocationTargetException e) {
UIUtils.showErrorDialog(
getShell(),
CoreMessages.dialog_struct_columns_select_error_load_columns_title,
CoreMessages.dialog_struct_columns_select_error_load_columns_message,
e.getTargetException());
} catch (InterruptedException e) {
// do nothing
}
for (DBSEntityAttribute attribute : attributes) {
TableItem columnItem = new TableItem(columnsTable, SWT.NONE);
AttributeInfo col = new AttributeInfo(attribute);
this.attributes.add(col);
DBNDatabaseNode attributeNode = DBeaverCore.getInstance().getNavigatorModel().findNode(attribute);
if (attributeNode != null) {
columnItem.setImage(0, DBeaverIcons.getImage(attributeNode.getNodeIcon()));
}
fillAttributeColumns(attribute, col, columnItem);
columnItem.setData(col);
if (isColumnSelected(attribute)) {
columnItem.setChecked(true);
handleItemSelect(columnItem, false);
}
}
UIUtils.packColumns(columnsTable);
updateToggleButton();
}
private Composite createTableNameInput(Composite panel) {
final Composite tableGroup = new Composite(panel, SWT.NONE);
tableGroup.setLayout(new GridLayout(2, false));
tableGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Text tableNameLabel = UIUtils.createLabelText(
tableGroup,
CoreMessages.dialog_struct_columns_select_label_table,
DBUtils.getObjectFullName(entity, DBPEvaluationContext.UI), SWT.BORDER | SWT.READ_ONLY);
return tableGroup;
}
private void handleItemSelect(TableItem item, boolean notify)
{
final AttributeInfo col = (AttributeInfo) item.getData();
if (item.getChecked() && col.position < 0) {
// Checked
col.position = 0;
for (AttributeInfo tmp : attributes) {
if (tmp != col && tmp.position >= col.position) {
col.position = tmp.position + 1;
}
}
item.setText(1, String.valueOf(col.position + 1));
} else if (!item.getChecked() && col.position >= 0) {
// Unchecked
item.setText(1, ""); //$NON-NLS-1$
TableItem[] allItems = columnsTable.getItems();
for (AttributeInfo tmp : attributes) {
if (tmp != col && tmp.position >= col.position) {
tmp.position--;
for (TableItem ai : allItems) {
if (ai.getData() == tmp) {
ai.setText(1, String.valueOf(tmp.position + 1));
break;
}
}
}
}
col.position = -1;
}
if (notify) {
handleColumnsChange();
updateToggleButton();
updatePageState();
}
}
private boolean hasCheckedColumns()
{
boolean hasCheckedColumns = false;
for (AttributeInfo tmp : attributes) {
if (tmp.position >= 0) {
hasCheckedColumns = true;
break;
}
}
return hasCheckedColumns;
}
private void updateToggleButton()
{
if (hasCheckedColumns()) {
toggleButton.setText("Clear All");
} else {
toggleButton.setText("Select All");
}
}
public Collection<DBSEntityAttribute> getSelectedAttributes()
{
List<DBSEntityAttribute> tableColumns = new ArrayList<>();
Set<AttributeInfo> orderedAttributes = new TreeSet<>(new Comparator<AttributeInfo>() {
@Override
public int compare(AttributeInfo o1, AttributeInfo o2) {
return o1.position - o2.position;
}
});
orderedAttributes.addAll(attributes);
for (AttributeInfo col : orderedAttributes) {
if (col.position >= 0) {
tableColumns.add(col.attribute);
}
}
return tableColumns;
}
protected void createContentsBeforeColumns(Composite panel)
{
}
protected void createContentsAfterColumns(Composite panel)
{
}
public boolean isColumnSelected(DBSEntityAttribute attribute)
{
return false;
}
protected void handleColumnsChange()
{
}
@Override
public boolean isPageComplete() {
for (TableItem item : columnsTable.getItems()) {
if (item.getChecked()) {
return true;
}
}
return false;
}
}