package rocks.inspectit.ui.rcp.form; import java.util.ArrayList; import java.util.List; import org.eclipse.core.commands.Command; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.expressions.IEvaluationContext; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.PopupDialog; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IViewPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.forms.ManagedForm; import org.eclipse.ui.forms.events.HyperlinkAdapter; import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.ExpandableComposite; import org.eclipse.ui.forms.widgets.FormText; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.forms.widgets.Section; import org.eclipse.ui.forms.widgets.TableWrapData; import org.eclipse.ui.forms.widgets.TableWrapLayout; import org.eclipse.ui.handlers.IHandlerService; import rocks.inspectit.shared.all.exception.BusinessException; import rocks.inspectit.shared.all.util.ObjectUtils; import rocks.inspectit.shared.cs.storage.IStorageData; import rocks.inspectit.shared.cs.storage.StorageData; import rocks.inspectit.shared.cs.storage.label.AbstractStorageLabel; import rocks.inspectit.ui.rcp.InspectIT; import rocks.inspectit.ui.rcp.InspectITImages; import rocks.inspectit.ui.rcp.editor.viewers.StyledCellIndexLabelProvider; import rocks.inspectit.ui.rcp.formatter.ImageFormatter; import rocks.inspectit.ui.rcp.formatter.NumberFormatter; import rocks.inspectit.ui.rcp.formatter.TextFormatter; import rocks.inspectit.ui.rcp.handlers.AddStorageLabelHandler; import rocks.inspectit.ui.rcp.handlers.RemoveStorageLabelHandler; import rocks.inspectit.ui.rcp.provider.ILocalStorageDataProvider; import rocks.inspectit.ui.rcp.provider.IStorageDataProvider; import rocks.inspectit.ui.rcp.repository.CmrRepositoryDefinition; import rocks.inspectit.ui.rcp.repository.CmrRepositoryDefinition.OnlineStatus; import rocks.inspectit.ui.rcp.storage.label.edit.LabelValueEditingSupport; import rocks.inspectit.ui.rcp.storage.label.edit.LabelValueEditingSupport.LabelEditListener; import rocks.inspectit.ui.rcp.util.SafeExecutor; import rocks.inspectit.ui.rcp.view.impl.StorageManagerView; /** * Form for displaying the {@link StorageData} properties. * * @author Ivan Senic * */ public class StorageDataPropertyForm implements ISelectionChangedListener { /** * Number of max characters displayed for storage description. */ private static final int MAX_DESCRIPTION_LENGTH = 150; /** * Storage data holding the main information about the storage. */ private IStorageData storageData; /** * Leaf that is displayed currently. */ private IStorageDataProvider storageDataProvider; /** * Toolkit used to create widgets. */ private final FormToolkit toolkit; /** * {@link ManagedForm}. */ private final ManagedForm managedForm; /** * Form that will be created. */ private final ScrolledForm form; /** * Label for ID. */ private Label uniqueId; /** * Label for repository. */ private Label repository; /** * Label for description. */ private FormText description; /** * Label for size on disk. */ private Label sizeOnDisk; /** * Label for storage state. */ private Label state; /** * Table of storage labels. */ private TableViewer labelsTableViewer; /** * Add new label button. */ private Button addNewLabel; /** * remove labels button. */ private Button removeLabels; /** * Main composite where widgets are. */ private Composite mainComposite; /** * {@link TableViewerColumn} for label values. Needed for editing support. */ private TableViewerColumn valueViewerColumn; /** * Default constructor. * * @param parent * Parent where form will be created. */ public StorageDataPropertyForm(Composite parent) { this(parent, null); } /** * Secondary constructor. Set the displayed storage leaf. * * @param parent * Parent where form will be created. * @param storageDataProvider * {@link IStorageDataProvider} to display. */ public StorageDataPropertyForm(Composite parent, IStorageDataProvider storageDataProvider) { this.managedForm = new ManagedForm(parent); this.toolkit = managedForm.getToolkit(); this.form = managedForm.getForm(); this.storageDataProvider = storageDataProvider; if (null != storageDataProvider) { this.storageData = storageDataProvider.getStorageData(); } initWidget(); } /** * Third constructor. Lets set everything. * * @param parent * Parent where form will be created. * @param storageDataProvider * {@link IStorageDataProvider} to display. Can be <code>null</code>. * @param storageData * {@link IStorageData} to display. Can be <code>null</code>. */ public StorageDataPropertyForm(Composite parent, IStorageDataProvider storageDataProvider, IStorageData storageData) { this.managedForm = new ManagedForm(parent); this.toolkit = managedForm.getToolkit(); this.form = managedForm.getForm(); this.storageDataProvider = storageDataProvider; this.storageData = storageData; initWidget(); } /** * Instantiate the widgets. */ private void initWidget() { Composite body = form.getBody(); body.setLayout(new TableWrapLayout()); managedForm.getToolkit().decorateFormHeading(form.getForm()); mainComposite = toolkit.createComposite(body, SWT.NONE); mainComposite.setLayout(new TableWrapLayout()); mainComposite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); // START - General section Section generalSection = toolkit.createSection(mainComposite, ExpandableComposite.TITLE_BAR); generalSection.setText("General information"); Composite generalComposite = toolkit.createComposite(generalSection, SWT.NONE); TableWrapLayout tableWrapLayout = new TableWrapLayout(); tableWrapLayout.numColumns = 2; generalComposite.setLayout(tableWrapLayout); generalComposite.setLayoutData(new TableWrapData(TableWrapData.FILL)); toolkit.createLabel(generalComposite, "Repository:"); repository = toolkit.createLabel(generalComposite, null, SWT.WRAP); toolkit.createLabel(generalComposite, "Description:"); description = toolkit.createFormText(generalComposite, true); description.setLayoutData(new TableWrapData(TableWrapData.FILL)); description.addHyperlinkListener(new HyperlinkAdapter() { @Override public void linkActivated(HyperlinkEvent e) { showStorageDescriptionBox(); } }); toolkit.createLabel(generalComposite, "Size on disk:"); sizeOnDisk = toolkit.createLabel(generalComposite, null, SWT.WRAP); toolkit.createLabel(generalComposite, "State:"); state = toolkit.createLabel(generalComposite, null, SWT.WRAP); toolkit.createLabel(generalComposite, "Unique ID:"); uniqueId = toolkit.createLabel(generalComposite, null, SWT.WRAP); uniqueId.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); generalSection.setClient(generalComposite); generalSection.setLayout(new TableWrapLayout()); generalSection.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); // END - General section // START - Label section Section labelSection = toolkit.createSection(mainComposite, ExpandableComposite.TITLE_BAR); labelSection.setText("Labels"); Composite labelComposite = toolkit.createComposite(labelSection, SWT.NONE); tableWrapLayout = new TableWrapLayout(); tableWrapLayout.numColumns = 2; labelComposite.setLayout(tableWrapLayout); labelComposite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); Table table = toolkit.createTable(labelComposite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.VIRTUAL); table.setHeaderVisible(true); table.setLinesVisible(true); TableWrapData tableWrapData = new TableWrapData(TableWrapData.FILL_GRAB); tableWrapData.colspan = 2; tableWrapData.heightHint = 150; table.setLayoutData(tableWrapData); labelsTableViewer = new TableViewer(table); TableViewerColumn viewerColumn = new TableViewerColumn(labelsTableViewer, SWT.NONE); viewerColumn.getColumn().setText("Type"); viewerColumn.getColumn().setMoveable(false); viewerColumn.getColumn().setResizable(true); viewerColumn.getColumn().setWidth(140); valueViewerColumn = new TableViewerColumn(labelsTableViewer, SWT.NONE); valueViewerColumn.getColumn().setText("Value"); valueViewerColumn.getColumn().setMoveable(false); valueViewerColumn.getColumn().setResizable(true); valueViewerColumn.getColumn().setWidth(140); labelsTableViewer.setContentProvider(new ArrayContentProvider()); labelsTableViewer.setLabelProvider(new StyledCellIndexLabelProvider() { @Override protected StyledString getStyledText(Object element, int index) { if (element instanceof AbstractStorageLabel) { AbstractStorageLabel<?> label = (AbstractStorageLabel<?>) element; switch (index) { case 0: return new StyledString(TextFormatter.getLabelName(label)); case 1: return new StyledString(TextFormatter.getLabelValue(label, false)); default: } } return null; } @Override protected Image getColumnImage(Object element, int index) { if ((index == 0) && (element instanceof AbstractStorageLabel)) { return ImageFormatter.getImageForLabel(((AbstractStorageLabel<?>) element).getStorageLabelType()); } return null; } }); labelsTableViewer.setComparator(new ViewerComparator() { @Override public int compare(Viewer viewer, Object e1, Object e2) { if ((e1 instanceof AbstractStorageLabel) && (e2 instanceof AbstractStorageLabel)) { return ((AbstractStorageLabel<?>) e1).compareTo((AbstractStorageLabel<?>) e2); } return super.compare(viewer, e1, e2); } }); labelsTableViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { if (labelsTableViewer.getSelection().isEmpty() || !isRemoteStorageDisplayed()) { removeLabels.setEnabled(false); } else { removeLabels.setEnabled(true); } } }); addNewLabel = toolkit.createButton(labelComposite, "Add", SWT.PUSH); addNewLabel.setToolTipText("Add new label(s)"); addNewLabel.setEnabled(false); addNewLabel.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class); ICommandService commandService = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); Command command = commandService.getCommand(AddStorageLabelHandler.COMMAND); ExecutionEvent executionEvent = handlerService.createExecutionEvent(command, new Event()); try { command.executeWithChecks(executionEvent); } catch (Exception exception) { throw new RuntimeException(exception); } } }); removeLabels = toolkit.createButton(labelComposite, "Remove", SWT.PUSH); removeLabels.setToolTipText("Remove selected label(s)"); removeLabels.setEnabled(false); removeLabels.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (!labelsTableViewer.getSelection().isEmpty()) { List<AbstractStorageLabel<?>> inputList = new ArrayList<>(); for (Object object : ((StructuredSelection) labelsTableViewer.getSelection()).toArray()) { if (object instanceof AbstractStorageLabel) { inputList.add((AbstractStorageLabel<?>) object); } } IHandlerService handlerService = (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class); ICommandService commandService = (ICommandService) PlatformUI.getWorkbench().getService(ICommandService.class); Command command = commandService.getCommand(RemoveStorageLabelHandler.COMMAND); ExecutionEvent executionEvent = handlerService.createExecutionEvent(command, new Event()); IEvaluationContext context = (IEvaluationContext) executionEvent.getApplicationContext(); context.addVariable(RemoveStorageLabelHandler.INPUT, inputList); try { command.executeWithChecks(executionEvent); } catch (Exception exception) { throw new RuntimeException(exception); } } } }); labelSection.setClient(labelComposite); labelSection.setLayout(new TableWrapLayout()); labelSection.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB)); // END - General section refreshData(); } /** * Sets layout data for the form. * * @param layoutData * LayoutData. */ public void setLayoutData(Object layoutData) { form.setLayoutData(layoutData); } /** * {@inheritDoc} */ @Override public void selectionChanged(SelectionChangedEvent event) { ISelection selection = event.getSelection(); if (!selection.isEmpty()) { if (selection instanceof StructuredSelection) { StructuredSelection structuredSelection = (StructuredSelection) selection; Object firstElement = structuredSelection.getFirstElement(); if (firstElement instanceof IStorageDataProvider) { if (!ObjectUtils.equals(storageDataProvider, firstElement)) { storageDataProvider = (IStorageDataProvider) firstElement; storageData = storageDataProvider.getStorageData(); final CmrRepositoryDefinition cmrRepositoryDefinition = storageDataProvider.getCmrRepositoryDefinition(); LabelValueEditingSupport editingSupport = new LabelValueEditingSupport(labelsTableViewer, storageDataProvider.getStorageData(), cmrRepositoryDefinition); editingSupport.addLabelEditListener(new LabelEditListener() { @Override public void preLabelValueChange(AbstractStorageLabel<?> label) { if (cmrRepositoryDefinition.getOnlineStatus() != OnlineStatus.OFFLINE) { try { cmrRepositoryDefinition.getStorageService().removeLabelFromStorage(storageDataProvider.getStorageData(), label); } catch (BusinessException e) { InspectIT.getDefault().createErrorDialog("Label value can not be updated.", e, -1); } } } @Override public void postLabelValueChange(AbstractStorageLabel<?> label) { if (cmrRepositoryDefinition.getOnlineStatus() != OnlineStatus.OFFLINE) { try { label.setId(0); cmrRepositoryDefinition.getStorageService().addLabelToStorage(storageDataProvider.getStorageData(), label, true); refreshStorageManagerView(cmrRepositoryDefinition); } catch (BusinessException e) { InspectIT.getDefault().createErrorDialog("Label value can not be updated.", e, -1); } } } }); valueViewerColumn.setEditingSupport(editingSupport); refreshData(); } return; } else if (firstElement instanceof ILocalStorageDataProvider) { IStorageData localStorageData = ((ILocalStorageDataProvider) firstElement).getLocalStorageData(); if (!ObjectUtils.equals(storageData, localStorageData)) { storageDataProvider = null; // NOPMD storageData = localStorageData; valueViewerColumn.setEditingSupport(null); refreshData(); } return; } } } if ((null != storageDataProvider) || (null != storageData)) { storageDataProvider = null; // NOPMD storageData = null; // NOPMD valueViewerColumn.setEditingSupport(null); refreshData(); } } /** * Refresh the data after selection is changed. */ private void refreshData() { // refresh data asynchronously SafeExecutor.asyncExec(new Runnable() { @Override public void run() { form.setBusy(true); if (isDataExistsForDisplay()) { // data exists, we display info we have form.setText(storageData.getName()); form.setMessage(null, IMessageProvider.NONE); mainComposite.setVisible(true); uniqueId.setText(storageData.getId()); String desc = storageData.getDescription(); if (null != desc) { if (desc.length() > MAX_DESCRIPTION_LENGTH) { description.setText("<form><p>" + desc.substring(0, MAX_DESCRIPTION_LENGTH) + ".. <a href=\"More\">[More]</a></p></form>", true, false); } else { description.setText(desc, false, false); } } else { description.setText("", false, false); } sizeOnDisk.setText(NumberFormatter.humanReadableByteCount(storageData.getDiskSize())); labelsTableViewer.setInput(storageData.getLabelList()); labelsTableViewer.refresh(); addNewLabel.setEnabled(isRemoteStorageDisplayed()); // depending of type enable/disable widgets if (isRemoteStorageDisplayed()) { // for remote storage CmrRepositoryDefinition cmrRepositoryDefinition = storageDataProvider.getCmrRepositoryDefinition(); repository.setText(cmrRepositoryDefinition.getName() + " (" + cmrRepositoryDefinition.getIp() + ":" + cmrRepositoryDefinition.getPort() + ")"); state.setText(TextFormatter.getStorageStateTextualRepresentation(storageDataProvider.getStorageData().getState())); Image img = ImageFormatter.getImageForStorageLeaf((StorageData) storageData); form.setImage(img); } else { // for downloaded storage repository.setText("Available locally"); state.setText("Downloaded"); form.setImage(InspectIT.getDefault().getImage(InspectITImages.IMG_STORAGE_DOWNLOADED)); } } else { // nothing is selected we display the proper info form.setText(null); form.setMessage("Please select a storage to see its properties.", IMessageProvider.INFORMATION); mainComposite.setVisible(false); } form.getBody().layout(true, true); form.setBusy(false); } }, form); } /** * Shows storage description box. */ private void showStorageDescriptionBox() { int shellStyle = SWT.CLOSE | SWT.TITLE | SWT.BORDER | SWT.APPLICATION_MODAL | SWT.RESIZE; PopupDialog popupDialog = new PopupDialog(form.getShell(), shellStyle, true, false, false, false, false, "Storage description", "Storage description") { private static final int CURSOR_SIZE = 15; @Override protected Control createDialogArea(Composite parent) { Composite composite = (Composite) super.createDialogArea(parent); Text text = toolkit.createText(parent, null, SWT.MULTI | SWT.READ_ONLY | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL); GridData gd = new GridData(GridData.BEGINNING | GridData.FILL_BOTH); gd.horizontalIndent = 3; gd.verticalIndent = 3; text.setLayoutData(gd); text.setText(storageData.getDescription()); return composite; } @Override protected Point getInitialLocation(Point initialSize) { // show popup relative to cursor Display display = getShell().getDisplay(); Point location = display.getCursorLocation(); location.x += CURSOR_SIZE; location.y += CURSOR_SIZE; return location; } @Override protected Point getInitialSize() { return new Point(400, 200); } }; popupDialog.open(); } /** * Refreshes the {@link StorageManagerView}, but only reloads the storages from given * repository. * * @param cmrRepositoryDefinition * {@link CmrRepositoryDefinition}. */ private void refreshStorageManagerView(CmrRepositoryDefinition cmrRepositoryDefinition) { IViewPart viewPart = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(StorageManagerView.VIEW_ID); if (viewPart instanceof StorageManagerView) { ((StorageManagerView) viewPart).refresh(cmrRepositoryDefinition); } } /** * @return Returns if any data exists for displaying. */ private boolean isDataExistsForDisplay() { return null != storageData; } /** * @return Returns if the remote storage is displayed. */ private boolean isRemoteStorageDisplayed() { return null != storageDataProvider; } /** * @return If form is disposed. */ public boolean isDisposed() { return form.isDisposed(); } /** * Disposes the form. */ public void dispose() { form.dispose(); } }