/******************************************************************************* * Copyright 2017 Capital One Services, LLC and Bitwise, Inc. * 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 hydrograph.ui.propertywindow.widgets.customwidgets.runtimeproperty; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnViewerEditor; import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy; import org.eclipse.jface.viewers.ICellEditorValidator; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerEditor; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.graphics.Point; 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.Label; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.forms.widgets.ColumnLayout; import org.eclipse.ui.forms.widgets.ColumnLayoutData; import hydrograph.ui.common.util.Constants; import hydrograph.ui.common.util.CustomColorRegistry; import hydrograph.ui.common.util.ImagePathConstant; import hydrograph.ui.common.util.OSValidator; import hydrograph.ui.propertywindow.messages.Messages; import hydrograph.ui.propertywindow.propertydialog.PropertyDialogButtonBar; import hydrograph.ui.propertywindow.widgets.dialog.hiveInput.SingleClickEvent; import hydrograph.ui.propertywindow.widgets.utility.WidgetUtility; /** * Class for runtime property dialog. * This class is responsible to provide UI to read runtime properties from user. * * @author Bitwise * */ public class RuntimePropertyDialog extends Dialog { private static final String ERROR = "ERROR"; private static final String[] PROPS = { Constants.PROPERTY_NAME, Constants.PROPERTY_VALUE }; private String PROPERTY_EXISTS_ERROR = Messages.RuntimePropertAlreadyExists; private String PROPERTY_NAME_BLANK_ERROR = Messages.EmptyNameNotification; private String PROPERTY_VALUE_BLANK_ERROR = Messages.EmptyValueNotification; private TableViewer tableViewer; private List<RuntimeProperties> propertyList; private Map<String, String> runtimePropertyMap; private Table table; private Label lblPropertyError; private Button deleteButton; private Button upButton; private Button downButton; private String windowLabel; private boolean isAnyUpdatePerformed; private PropertyDialogButtonBar propertyDialogButtonBar; private boolean closeDialog; private boolean okPressed; private boolean okPressedAfterUpdate; private static final String INFORMATION="Information"; private boolean ctrlKeyPressed = false; /** * Create the dialog. * * @param parentShell * @param propertyDialogButtonBar */ public RuntimePropertyDialog(Shell parentShell, PropertyDialogButtonBar propertyDialogButtonBar, String windowLabel) { super(parentShell); if(StringUtils.isNotBlank(windowLabel)) this.windowLabel=windowLabel; else this.windowLabel=Constants.RUNTIME_PROPERTIES_WINDOW_LABEL; propertyList = new LinkedList<RuntimeProperties>(); runtimePropertyMap = new LinkedHashMap<String, String>(); this.propertyDialogButtonBar = propertyDialogButtonBar; } /** * Create contents of the dialog. * * @param parent */ @Override protected Control createDialogArea(Composite parent) { isAnyUpdatePerformed = false; Composite container = (Composite) super.createDialogArea(parent); container.getShell().setText(windowLabel); ColumnLayout cl_container = new ColumnLayout(); cl_container.verticalSpacing = 0; cl_container.maxNumColumns = 1; container.setLayout(cl_container); addButtonPanel(container); Composite composite_2 = new Composite(container, SWT.NONE); composite_2.setLayout(new GridLayout(1, false)); ColumnLayoutData cld_composite_2 = new ColumnLayoutData(); cld_composite_2.heightHint = 453; composite_2.setLayoutData(cld_composite_2); createTable(composite_2); addErrorLabel(container); return container; } private void addErrorLabel(Composite container) { Composite composite_3 = new Composite(container, SWT.NONE); ColumnLayout cl_coposite_3 = new ColumnLayout(); cl_coposite_3.topMargin=0; composite_3.setLayout(cl_coposite_3); ColumnLayoutData cld_composite_3 = new ColumnLayoutData(); cld_composite_3.heightHint = 19; composite_3.setLayoutData(cld_composite_3); lblPropertyError = new Label(composite_3, SWT.NONE); ColumnLayoutData cld_lblPropertyError = new ColumnLayoutData(); cld_lblPropertyError.heightHint = 25; lblPropertyError.setLayoutData(cld_lblPropertyError); lblPropertyError.setVisible(false); lblPropertyError.setForeground(CustomColorRegistry.INSTANCE.getColorFromRegistry( 255, 0, 0)); } /** * Returns runtime property map * * @return - runtimePropertyMap - Map<String, String> */ public Map<String, String> getRuntimeProperties() { return runtimePropertyMap; } private void addButtonPanel(Composite container) { Composite composite_1 = new Composite(container, SWT.NONE); composite_1.setLayout(new GridLayout(4, false)); ColumnLayoutData cld_composite_1 = new ColumnLayoutData(); cld_composite_1.horizontalAlignment = ColumnLayoutData.RIGHT; cld_composite_1.heightHint = 30; composite_1.setLayoutData(cld_composite_1); Button addButton = new Button(composite_1, SWT.NONE); addButton.setToolTipText(Messages.ADD_KEY_SHORTCUT_TOOLTIP); addButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); addButton.setImage(ImagePathConstant.ADD_BUTTON.getImageFromRegistry()); attachAddButtonListern(addButton); deleteButton = new Button(composite_1, SWT.NONE); deleteButton.setToolTipText(Messages.DELETE_KEY_SHORTCUT_TOOLTIP); deleteButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); deleteButton.setImage(ImagePathConstant.DELETE_BUTTON.getImageFromRegistry()); attachDeleteButtonListener(deleteButton); upButton = new Button(composite_1, SWT.NONE); upButton.setToolTipText(Messages.MOVE_UP_KEY_SHORTCUT_TOOLTIP); upButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); upButton.setImage(ImagePathConstant.MOVEUP_BUTTON.getImageFromRegistry()); attachUpButtonListener(upButton); downButton = new Button(composite_1, SWT.NONE); downButton.setToolTipText(Messages.MOVE_DOWN_KEY_SHORTCUT_TOOLTIP); downButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); downButton.setImage(ImagePathConstant.MOVEDOWN_BUTTON.getImageFromRegistry()); attachDownButtonListerner(downButton); deleteButton.setEnabled(false); upButton.setEnabled(false); downButton.setEnabled(false); } private void attachDownButtonListerner(Button downButton) { downButton.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { moveRowDown(); } }); } private void moveRowDown() { int index1 = 0, index2 = 0; index1 = table.getSelectionIndex(); if (index1 < propertyList.size() - 1) { String text = tableViewer.getTable().getItem(index1).getText(0); String text1 = tableViewer.getTable().getItem(index1).getText(1); index2 = index1 + 1; String data = tableViewer.getTable().getItem(index2).getText(0); String data1 = tableViewer.getTable().getItem(index2).getText(1); RuntimeProperties p = new RuntimeProperties(); p.setPropertyName(data); p.setPropertyValue(data1); propertyList.set(index1, p); p = new RuntimeProperties(); p.setPropertyName(text); p.setPropertyValue(text1); propertyList.set(index2, p); tableViewer.refresh(); table.setSelection(index1 + 1); } } private void attachUpButtonListener(Button upButton) { upButton.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { moveRowUp(); } }); } private void moveRowUp() { int index1 = 0, index2 = 0; index1 = table.getSelectionIndex(); if (index1 > 0) { String text = tableViewer.getTable().getItem(index1).getText(0); String text1 = tableViewer.getTable().getItem(index1).getText(1); index2 = index1 - 1; String data = tableViewer.getTable().getItem(index2).getText(0); String data2 = tableViewer.getTable().getItem(index2).getText(1); RuntimeProperties p = new RuntimeProperties(); p.setPropertyName(data); p.setPropertyValue(data2); propertyList.set(index1, p); p = new RuntimeProperties(); p.setPropertyName(text); p.setPropertyValue(text1); propertyList.set(index2, p); tableViewer.refresh(); table.setSelection(index1 - 1); } } private void attachDeleteButtonListener(final Button deleteButton) { deleteButton.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { deleteRow(); } }); } private void deleteRow() { WidgetUtility.setCursorOnDeleteRow(tableViewer, propertyList); isAnyUpdatePerformed = true; tableViewer.refresh(); if (propertyList.size() < 1) { deleteButton.setEnabled(false); } if (propertyList.size()<= 1) { upButton.setEnabled(false); downButton.setEnabled(false); } if(lblPropertyError.getVisible()){ lblPropertyError.setVisible(false); } } private void attachAddButtonListern(Button addButton) { addButton.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { addNewRow(); } }); } private void addNewRow() { table.getParent().setFocus(); tableViewer.getControl().getShell().setFocus(); addNewProperty(tableViewer); if (propertyList.size() >= 1) { deleteButton.setEnabled(true); } if (propertyList.size() >= 2) { upButton.setEnabled(true); downButton.setEnabled(true); } } /** * Create contents of the button bar. * * @param parent */ @Override protected void createButtonsForButtonBar(Composite parent) { createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); } @Override protected void okPressed() { if(OSValidator.isMac()){ for(CellEditor cellEditor : tableViewer.getCellEditors()){ if(cellEditor !=null){ cellEditor.getControl().setEnabled(false); //Saves the existing value of CellEditor cellEditor.getControl().setEnabled(true); } } } if (validate()) { runtimePropertyMap.clear(); for (RuntimeProperties temp : propertyList) { runtimePropertyMap.put(temp.getPropertyName(), temp.getPropertyValue()); } if (isAnyUpdatePerformed && propertyDialogButtonBar != null) { propertyDialogButtonBar.enableApplyButton(true); } else if (isAnyUpdatePerformed) okPressedAfterUpdate = true; okPressed = true; super.okPressed(); } } @Override protected void cancelPressed() { if (isAnyUpdatePerformed) { int style = SWT.APPLICATION_MODAL | SWT.YES | SWT.NO |SWT.ICON_INFORMATION; MessageBox messageBox = new MessageBox(new Shell(), style); messageBox.setText(INFORMATION); messageBox.setMessage(Messages.MessageBeforeClosingWindow); if (messageBox.open() == SWT.YES) { closeDialog = super.close(); } } else { closeDialog = super.close(); } } /** * Return the initial size of the dialog. */ @Override protected Point getInitialSize() { return new Point(646, 587); } // Add New Property After Validating old properties private void addNewProperty(TableViewer tabViewer) { isAnyUpdatePerformed = true; RuntimeProperties property = new RuntimeProperties(); if (propertyList.size() != 0) { if (!validate()) { return; } property.setPropertyName(""); property.setPropertyValue(""); propertyList.add(property); tabViewer.refresh(); tableViewer.editElement(tableViewer.getElementAt(propertyList.size() - 1), 0); } else { property.setPropertyName(""); property.setPropertyValue(""); propertyList.add(property); tabViewer.refresh(); tableViewer.editElement(tableViewer.getElementAt(0), 0); } } /** * * Set runtime properties. * * @param runtimePropertyMap */ public void setRuntimeProperties(Map<String, String> runtimePropertyMap) { this.runtimePropertyMap = runtimePropertyMap; } // Loads Already Saved Properties.. private void loadProperties(TableViewer tv) { if (runtimePropertyMap != null && !runtimePropertyMap.isEmpty()) { for (String key : runtimePropertyMap.keySet()) { RuntimeProperties p = new RuntimeProperties(); if (validateBeforeLoad(key, runtimePropertyMap.get(key))) { p.setPropertyName(key); p.setPropertyValue(runtimePropertyMap.get(key)); propertyList.add(p); } } tv.refresh(); } //$NON-NLS-1$ } private boolean validateBeforeLoad(String key, String keyValue) { if (key.trim().isEmpty()) { return false; } return true; } // Method for creating Table private void createTable(Composite composite) { tableViewer = new TableViewer(composite, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION|SWT.NO_SCROLL | SWT.V_SCROLL); tableViewer.setData(Constants.WINDOW_TITLE, windowLabel); table = tableViewer.getTable(); GridData gd_table = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1); gd_table.heightHint = 422; gd_table.widthHint = 431; table.setLayoutData(gd_table); table.addMouseListener(new MouseAdapter() { @Override public void mouseDoubleClick(MouseEvent e) { addNewProperty(tableViewer); if (propertyList.size() >= 1) { deleteButton.setEnabled(true); } if (propertyList.size() >= 2) { upButton.setEnabled(true); downButton.setEnabled(true); } } @Override public void mouseDown(MouseEvent e) { lblPropertyError.setVisible(false); } }); attachShortcutListner(Constants.PROPERTY_TABLE); tableViewer.getTable().addTraverseListener(new TraverseListener() { @Override public void keyTraversed(TraverseEvent e) { if (e.keyCode == SWT.ARROW_UP) { e.doit = false; } else if (e.keyCode == SWT.ARROW_DOWN) { e.doit = false; } else if (e.keyCode == SWT.TRAVERSE_ARROW_NEXT) { e.doit = false; } else if (e.keyCode == SWT.TRAVERSE_ARROW_PREVIOUS) { e.doit = false; } } }); // table.setBounds(10, 68, 465, 400); tableViewer.setContentProvider(new PropertyContentProvider()); tableViewer.setLabelProvider(new PropertyLabelProvider()); tableViewer.setInput(propertyList); TableColumn column1 = new TableColumn(table, SWT.LEFT_TO_RIGHT); column1.setText(Messages.PROPERTY_NAME); TableColumn column2 = new TableColumn(table, SWT.LEFT_TO_RIGHT); column2.setText(Messages.PROPERTY_VALUE); for (int i = 0, n = table.getColumnCount(); i < n; i++) { table.getColumn(i).pack(); } column1.setWidth(280); column2.setWidth(374); table.setHeaderVisible(true); table.setLinesVisible(true); final CellEditor propertyNameeditor = new TextCellEditor(table); CellEditor propertyValueeditor = new TextCellEditor(table); CellEditor[] editors = new CellEditor[] { propertyNameeditor, propertyValueeditor }; propertyNameeditor.setValidator(createNameEditorValidator(PROPERTY_NAME_BLANK_ERROR)); propertyValueeditor.setValidator(createValueEditorValidator(PROPERTY_VALUE_BLANK_ERROR)); tableViewer.setColumnProperties(PROPS); tableViewer.setCellModifier(new RunTimePropertyCellModifier(tableViewer)); tableViewer.setCellEditors(editors); // enables the tab functionality TableViewerEditor.create(tableViewer, new ColumnViewerEditorActivationStrategy(tableViewer), ColumnViewerEditor.KEYBOARD_ACTIVATION | ColumnViewerEditor.TABBING_HORIZONTAL | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR | ColumnViewerEditor.TABBING_VERTICAL); loadProperties(tableViewer); if (propertyList.size() != 0) { deleteButton.setEnabled(true); } if (propertyList.size() >= 2) { upButton.setEnabled(true); downButton.setEnabled(true); } attachShortcutListner(Constants.PROPERTY_NAME); attachShortcutListner(Constants.PROPERTY_VALUE); tableViewer.getTable().addMouseListener(new SingleClickEvent(new Runnable() { @Override public void run() { validate(); } })); } private void attachShortcutListner(String controlName){ Control currentControl; if (controlName == Constants.PROPERTY_NAME) currentControl = tableViewer.getCellEditors()[0].getControl(); else if(controlName == Constants.PROPERTY_VALUE) currentControl = tableViewer.getCellEditors()[1].getControl(); else currentControl = table; currentControl.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent event) { if(event.keyCode == SWT.CTRL || event.keyCode == SWT.COMMAND){ ctrlKeyPressed = false; } } @Override public void keyPressed(KeyEvent event) { if(event.keyCode == SWT.CTRL || event.keyCode == SWT.COMMAND){ ctrlKeyPressed = true; } if (ctrlKeyPressed && event.keyCode == Constants.KEY_D) { deleteRow(); } else if (ctrlKeyPressed && event.keyCode == Constants.KEY_N){ addNewRow(); } else if (ctrlKeyPressed && event.keyCode == SWT.ARROW_UP){ moveRowUp(); } else if (ctrlKeyPressed && event.keyCode == SWT.ARROW_DOWN){ moveRowDown(); } } }); } /** * Validate. * * @return true, if successful */ private boolean validate() { int propertyCounter = 0; for (RuntimeProperties runtimeProperties : propertyList) { if (runtimeProperties.getPropertyName().trim().isEmpty()) { table.setSelection(propertyCounter); lblPropertyError.setVisible(true); lblPropertyError.setText(Messages.EmptyNameNotification); return false; } propertyCounter++; } return true; } // Creates CellNAme Validator for table's cells private ICellEditorValidator createNameEditorValidator(final String ErrorMessage) { ICellEditorValidator propertyValidator = new ICellEditorValidator() { @Override public String isValid(Object value) { isAnyUpdatePerformed = true; String currentSelectedFld = table.getItem(table.getSelectionIndex()).getText(); String valueToValidate = String.valueOf(value).trim(); if (StringUtils.isEmpty(valueToValidate)) { lblPropertyError.setText(ErrorMessage); lblPropertyError.setVisible(true); return ERROR; } for (RuntimeProperties temp : propertyList) { if (!currentSelectedFld.equalsIgnoreCase(valueToValidate) && temp.getPropertyName().equalsIgnoreCase(valueToValidate)) { lblPropertyError.setText(PROPERTY_EXISTS_ERROR); lblPropertyError.setVisible(true); return ERROR; } else { lblPropertyError.setVisible(false); } } return null; } }; return propertyValidator; } // Creates Value Validator for table's cells private ICellEditorValidator createValueEditorValidator(final String ErrorMessage) { ICellEditorValidator propertyValidator = new ICellEditorValidator() { @Override public String isValid(Object value) { isAnyUpdatePerformed = true; String valueToValidate = String.valueOf(value).trim(); if (valueToValidate.isEmpty()) { lblPropertyError.setText(ErrorMessage); lblPropertyError.setVisible(true); return ERROR; //$NON-NLS-1$ } else { lblPropertyError.setVisible(false); } return null; } }; return propertyValidator; } @Override public boolean close() { if(!okPressed){ cancelPressed(); return closeDialog; }else{ return super.close(); } } /** * This method is used to determine whether ok button is pressed after any update. * * @return */ public boolean isOkPressedAfterUpdate(){ return this.okPressedAfterUpdate; } public boolean isOkPressed(){ return this.okPressed; } }