Java tutorial
/* * Copyright 2015 The ISTLab. Use of this source code is governed by a GNU AFFERO GPL 3.0 license * that can be found in the LICENSE file. */ package gr.aueb.dmst.istlab.unixtools.views.preferences; import java.util.ArrayList; import java.util.StringTokenizer; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.RowLayout; 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.FileDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.ui.IWorkbench; import gr.aueb.dmst.istlab.unixtools.controllers.PreferencesTableController; import gr.aueb.dmst.istlab.unixtools.controllers.WizardMainPageController; import gr.aueb.dmst.istlab.unixtools.core.model.CustomCommand; import gr.aueb.dmst.istlab.unixtools.plugin.PluginContext; import gr.aueb.dmst.istlab.unixtools.util.PropertiesLoader; import gr.aueb.dmst.istlab.unixtools.views.dialogs.EditCustomCommandDialogView; import gr.aueb.dmst.istlab.unixtools.views.wizard.WizardBasePage; /** * This class represents the custom commands' page we use for this plugin. It has a table with 4 * columns (command, name, shell, output) holding the custom commands. It also has 5 buttons that * help with the table's management : Add : adds a new command to the table, following a wizard * style creation Edit : edits an already added command to the table. Remove : removes one or more * command entries from the table. Import : imports a yaml file containing custom commands * overwriting the existing ones in the table. Might add appending option. Export : exports the * custom commands from the table to a yaml file. */ public final class PreferencesTableView extends AbstractPreferencesPageView { private Button addButton; private Button editButton; private Button removeButton; private Button importButton; private Button exportButton; private Table customCommandsTable; private boolean changed; private PreferencesTableController controller; @Override public void init(IWorkbench workbench) { super.init(workbench); } @Override protected Control createContents(Composite parent) { PluginContext pluginContext = PluginContext.getInstance(); this.controller = pluginContext.getPreferencesTableController(); // set the layout this.setComposite(new Composite(parent, parent.getStyle())); this.setCCLayout(this.getComposite()); // create the command table and the buttons this.customCommandsTable = createCommandTable(this.getComposite()); this.createButtons(this.getComposite()); this.controller.deserializeCustomCommands(); this.refresh(); return this.getComposite(); } /** * Creates the buttons used in this preference page * * @param composite */ private void createButtons(Composite composite) { Composite buttonGroup = new Composite(composite, SWT.NONE); GridData gridData = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); RowLayout rowLayout = new RowLayout(); buttonGroup.setLayoutData(gridData); rowLayout.type = SWT.VERTICAL; rowLayout.pack = false; buttonGroup.setLayout(rowLayout); this.addButton = createButton(buttonGroup, "Add"); this.editButton = createButton(buttonGroup, "Edit"); this.removeButton = createButton(buttonGroup, "Remove"); this.importButton = createButton(buttonGroup, "Import"); this.exportButton = createButton(buttonGroup, "Export"); this.addButton.addSelectionListener(new AddCustomCommandButtonListener()); this.editButton.addSelectionListener(new EditCustomCommandButtonListener()); this.removeButton.addSelectionListener(new RemoveCustomCommandButtonListener()); this.importButton.addSelectionListener(new ImportCustomCommandButtonListener()); this.exportButton.addSelectionListener(new ExportCustomCommandButtonListener()); } /** * Creates a push button on the given composite/panel with the given name * * @param buttonGroup * @param buttonLabel * @return a button */ private Button createButton(Composite buttonGroup, String buttonLabel) { Button button = new Button(buttonGroup, SWT.PUSH); button.setText(buttonLabel); return button; } /** * Creates a table for the custom commands stored in this preference page * * @param composite * @return a table of custom commands */ private Table createCommandTable(Composite composite) { Label label = new Label(composite, SWT.NONE); GridData labelData = new GridData(); GridData tableData = new GridData(SWT.FILL, SWT.FILL, true, true); Table table = new Table(composite, SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION); String[] titles = PropertiesLoader.titles; label.setText(PropertiesLoader.CUSTOM_COMMAND_PAGE_DESCRIPTION); labelData.horizontalSpan = 2; label.setLayoutData(labelData); table.setLayoutData(tableData); table.setLinesVisible(true); table.setHeaderVisible(true); for (String title : titles) { TableColumn column = new TableColumn(table, SWT.NONE); column.setText(title); } return table; } /** * The addition follows a wizard style implementation, divided into 3 pages : a Command Page where * the user can specify the newly added command's name, the command itself, and the shell's * starting directory for the command. The user also gets the command's description and an auto * complete feature to help him/her choose from the command prototypes. The second page is an * Argument page, where the user can select from the available arguments for the command, and * finally, the third page is a Resource page, where the user can attach an input file to the * command or add a pipe. If the user chooses to pipe the wizard starts all over again, showing in * the first page the state of the command so far. NOTE : When piping , the shell's directory path * and the command's nickname, are extracted from the last part of the pipe i.e from the last * wizard that pops up. */ public CustomCommand handleAddButton() { CustomCommand commandToAdd = null; WizardBasePage wizard = new WizardBasePage(); wizard.setNeedsProgressMonitor(true); wizard.setShell(PreferencesTableView.this.getComposite().getShell()); WizardDialog wizardDialog = new WizardDialog(PreferencesTableView.this.getComposite().getShell(), wizard); if (wizardDialog.open() == WizardDialog.OK) { commandToAdd = new CustomCommand(); commandToAdd.setCommand(wizard.getActualCommand()); commandToAdd.setName(wizard.getNickname()); commandToAdd.setShellDirectory(wizard.getShellDirectory()); commandToAdd.setHasConsoleOutput(wizard.isOutputToScreen()); commandToAdd.setOutputFilename(wizard.getLastOutputFile()); this.changed = true; } WizardBasePage.clearValues(); return commandToAdd; } /** * This method handles the pressing of the edit button. The user is able to edit the command he * selected from the table. The user cannot edit multiple commands at the same time. */ public String[] handleEditButton() { String[] editedInfo = null; int selection = this.customCommandsTable.getSelectionIndex(); if (selection == -1) { return null; } if (this.customCommandsTable.getSelectionIndices().length > 1) { MessageDialog.openInformation(this.getShell(), "Please be careful!!", "One command can be edited at a time!"); return null; } Shell shell = this.getShell(); EditCustomCommandDialogView dialog = new EditCustomCommandDialogView(shell); dialog.create(); dialog.setDefaultValues(this.customCommandsTable.getItem(selection).getText(0), this.customCommandsTable.getItem(selection).getText(1), this.customCommandsTable.getItem(selection).getText(2)); if (dialog.open() == Window.OK) { editedInfo = new String[5]; editedInfo[0] = Integer.toString(selection); editedInfo[1] = dialog.getCommand(); editedInfo[2] = dialog.getName(); editedInfo[3] = dialog.getShellPath(); this.changed = true; } return editedInfo; } /** * This method handles the pressing of the remove button. Removes the selected command from the * table. Supports multiple command removal at the same time. */ public int[] handleRemoveButton() { int[] selectedItems = this.customCommandsTable.getSelectionIndices(); this.changed = true; return ((selectedItems.length > 0) ? selectedItems : null); } public String handleImportButton() { String filename = null; // ask the user if he/she wants to overwrite the existing table MessageDialog messageDialog = new MessageDialog(getShell(), "Import commands", null, PropertiesLoader.CUSTOM_COMMAND_PAGE_IMPORT_MESSAGE, MessageDialog.QUESTION_WITH_CANCEL, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL }, 0); if (messageDialog.open() == MessageDialog.OK) { // User has selected to open a single file FileDialog fileDialog = new FileDialog(getShell(), SWT.OPEN); filename = fileDialog.open(); } return filename; } public String handleExportButton() { String filename = null; // User has selected to open a single file FileDialog dialog = new FileDialog(getShell(), SWT.SAVE); filename = dialog.open(); return filename; } @Override public boolean performOk() { this.controller.serializeCustomCommands(); if (changed) { // override the previous command list TableItem[] items = this.customCommandsTable.getItems(); ArrayList<CustomCommand> newCommands = new ArrayList<CustomCommand>(); for (int i = 0; i < items.length; ++i) { CustomCommand customCommand = new CustomCommand(); customCommand.setCommand(items[i].getText(0)); customCommand.setName(items[i].getText(1)); customCommand.setShellDirectory(items[i].getText(2)); if (this.getEditedCommandsOutputFile(items[i].getText(0)).isEmpty()) { customCommand.setHasConsoleOutput(true); } else { customCommand.setHasConsoleOutput(false); customCommand.setOutputFilename(this.getEditedCommandsOutputFile(items[i].getText(0))); } newCommands.add(customCommand); } this.controller.saveCustomCommands(newCommands); this.changed = false; } return true; } /** * Return the last output file of the given command or an empty string if the command outputs to * the screen * * @param actualCommand * @return */ private String getEditedCommandsOutputFile(String actualCommand) { // get the command's pipes StringTokenizer tokenizer = new StringTokenizer(actualCommand, "|"); String lastPipe = null; // get the last pipe while (tokenizer.hasMoreTokens()) { lastPipe = tokenizer.nextToken(); } tokenizer = new StringTokenizer(lastPipe, ">"); // if countTokens() == 1 means we dont have any output files if (tokenizer.countTokens() == 1) { return ""; } else { String lastFile = null; // otherwise get the last output file while (tokenizer.hasMoreTokens()) { lastFile = tokenizer.nextToken(); } return lastFile.trim(); } } @Override protected void createFieldEditors() { } @Override public void refresh() { // refresh the custom commands this.customCommandsTable.clearAll(); this.customCommandsTable.removeAll(); for (CustomCommand customCommand : this.controller.getCustomCommands()) { TableItem item = new TableItem(this.customCommandsTable, SWT.NONE); item.setText(0, customCommand.getCommand()); item.setForeground(0, Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)); item.setText(1, customCommand.getName()); item.setForeground(1, Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)); item.setText(2, customCommand.getShellDirectory()); item.setForeground(2, Display.getCurrent().getSystemColor(SWT.COLOR_BLACK)); } for (int i = 0; i < this.customCommandsTable.getColumnCount(); ++i) { TableColumn column = this.customCommandsTable.getColumn(i); column.pack(); if (column.getWidth() > PropertiesLoader.CUSTOM_COMMANDS_TABLE_COLUMN_WIDTH) { column.setWidth(PropertiesLoader.CUSTOM_COMMANDS_TABLE_COLUMN_WIDTH); } } } private class AddCustomCommandButtonListener implements SelectionListener { @Override public void widgetDefaultSelected(SelectionEvent arg0) { } @Override public void widgetSelected(SelectionEvent arg0) { CustomCommand commandToAdd = handleAddButton(); controller.addCustomCommand(commandToAdd); refresh(); } } private class EditCustomCommandButtonListener implements SelectionListener { @Override public void widgetDefaultSelected(SelectionEvent arg0) { } @Override public void widgetSelected(SelectionEvent arg0) { String[] editedInfo = handleEditButton(); if (editedInfo != null) { int index = Integer.parseInt(editedInfo[0]); CustomCommand customCommand = controller.getCustomCommands().get(index); WizardMainPageController.getCustomCommandsNames().remove(customCommand.getName()); customCommand.setCommand(editedInfo[1]); customCommand.setName(editedInfo[2]); customCommand.setShellDirectory(editedInfo[3]); if (getEditedCommandsOutputFile(editedInfo[1]).isEmpty()) { customCommand.setHasConsoleOutput(true); } else { customCommand.setHasConsoleOutput(false); customCommand.setOutputFilename(getEditedCommandsOutputFile(editedInfo[1])); } WizardMainPageController.getCustomCommandsNames().add(customCommand.getName()); controller.editCustomCommand(controller.getCustomCommands().get(index), customCommand); refresh(); } } } private class RemoveCustomCommandButtonListener implements SelectionListener { @Override public void widgetDefaultSelected(SelectionEvent arg0) { } @Override public void widgetSelected(SelectionEvent arg0) { int[] selectedItems = handleRemoveButton(); if (selectedItems != null) { CustomCommand[] selectedCommands = new CustomCommand[selectedItems.length]; for (int i = 0; i < selectedCommands.length; ++i) { selectedCommands[i] = controller.getCustomCommands().get(selectedItems[i]); } controller.removeCustomCommand(selectedCommands); refresh(); } } } private class ImportCustomCommandButtonListener implements SelectionListener { @Override public void widgetDefaultSelected(SelectionEvent arg0) { } @Override public void widgetSelected(SelectionEvent arg0) { String filename = handleImportButton(); controller.importCustomCommand(filename); refresh(); } } private class ExportCustomCommandButtonListener implements SelectionListener { @Override public void widgetDefaultSelected(SelectionEvent arg0) { } @Override public void widgetSelected(SelectionEvent arg0) { String filename = handleExportButton(); controller.exportCustomCommand(filename); } } }