package com.buildml.eclipse.packages.properties; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; 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 com.buildml.eclipse.bobj.UIAction; import com.buildml.eclipse.bobj.UIDirectory; import com.buildml.eclipse.utils.AlertDialog; import com.buildml.eclipse.utils.BmlPropertyPage; import com.buildml.eclipse.utils.GraphitiUtils; import com.buildml.eclipse.utils.UndoOpAdapter; import com.buildml.eclipse.utils.dialogs.VFSTreeSelectionDialog; import com.buildml.model.IActionMgr; import com.buildml.model.IPackageMemberMgr; import com.buildml.model.IPackageMemberMgr.PackageDesc; import com.buildml.model.undo.ActionUndoOp; import com.buildml.model.IPackageRootMgr; import com.buildml.utils.errors.ErrorCode; import com.buildml.utils.errors.FatalError; /** * An Eclipse "property" page that allows viewing/editing of an actions top-level properties * Objects of this class are referenced in the plugin.xml file and are dynamically * created when the properties dialog is opened for a UIAction object. * * @author Peter Smith <psmith@arapiki.com> */ public class ActionPropertyPage extends BmlPropertyPage { /*=====================================================================================* * FIELDS/TYPES *=====================================================================================*/ /** The ID of the underlying action */ private int actionId; /** The original path ID of the directory this action executed in (before we changed it) */ private int originalPathId; /** The new path ID of the directory this action executes in */ private int selectedPathId; /** The package that this action resides in */ private PackageDesc pkg; /** The SWT label that displays the directory path */ private Label actionDirectoryLabelValue; /** The main panel of this properties page */ private Composite panel; /*=====================================================================================* * CONSTRUCTORS *=====================================================================================*/ /** * Create a new ActionShellCommandPage object. */ public ActionPropertyPage() { /* nothing */ } /*=====================================================================================* * PUBLIC METHODS *=====================================================================================*/ /** * The user has pressed the OK button */ @Override public boolean performOk() { /* create an undo/redo operation that will invoke the underlying database changes */ ActionUndoOp op = new ActionUndoOp(buildStore, actionId); op.recordSlotChange(IActionMgr.DIRECTORY_SLOT_ID, originalPathId, selectedPathId); new UndoOpAdapter("Change Action", op).invoke(); // TODO: put this operation in the same MultiUndoOp as the performOK() for shell commands. // This is possibly done via the BmlPropertyPage parent class. return super.performOk(); } /*=====================================================================================* * PROTECTED METHODS *=====================================================================================*/ /** * Create the widgets that appear within the properties dialog box. */ @Override protected Control createContents(Composite parent) { /* determine the numeric ID of the action */ UIAction action = (UIAction) GraphitiUtils.getBusinessObjectFromElement(getElement(), UIAction.class); if (action == null) { return null; } actionId = action.getId(); setTitle("Action Properties:"); /* create a panel in which all sub-widgets are added. */ panel = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(3, false); layout.marginHeight = 0; layout.marginWidth = 0; panel.setLayout(layout); /* * Display the action's type (e.g. "Shell Command") */ String actionType = "Invalid"; int actionTypeId = actionMgr.getActionType(actionId); if (actionTypeId != ErrorCode.NOT_FOUND) { String actionTypeString = actionTypeMgr.getName(actionTypeId); if (actionTypeString != null) { actionType = actionTypeString; } } new Label(panel, SWT.NONE).setText("Action Type : "); new Label(panel, SWT.NONE).setText(actionType); new Label(panel, SWT.NONE); /* filler */ /* * Display the package that the action belongs to */ String packageName = "Invalid"; pkg = pkgMemberMgr.getPackageOfMember(IPackageMemberMgr.TYPE_ACTION, actionId); if (pkg != null) { String packageNameString = pkgMgr.getName(pkg.pkgId); if (packageNameString != null) { packageName = packageNameString; } } new Label(panel, SWT.NONE).setText("Action Package : "); new Label(panel, SWT.NONE).setText(packageName); new Label(panel, SWT.NONE); /* filler */ /* * Display the action's directory, providing the option to change the directory. */ originalPathId = (Integer) actionMgr.getSlotValue(actionId, IActionMgr.DIRECTORY_SLOT_ID); String pathString = fileMgr.getPathName(originalPathId); new Label(panel, SWT.NONE).setText("Action Directory : "); actionDirectoryLabelValue = new Label(panel, SWT.NONE); actionDirectoryLabelValue.setText(pathString); Button editDirectoryButton = new Button(panel, SWT.NONE); editDirectoryButton.setText(" Edit Directory "); /* * When "Edit Directory" is selected, allow selection of a new directory, * then refresh the labels appropriately. */ editDirectoryButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { editDirectory(); refreshPage(); } }); return panel; } /*=====================================================================================* * PRIVATE METHODS *=====================================================================================*/ /** * The user has pressed the "edit" directory button, so proceed to allow them to edit * the action's directory. */ protected void editDirectory() { /* * Determine and source or generated roots for this package. The selected directory * must fall within one of them. If not, we reject the selection and try again. */ int srcRootId = pkgRootMgr.getPackageRoot(pkg.pkgId, IPackageRootMgr.SOURCE_ROOT); int genRootId = pkgRootMgr.getPackageRoot(pkg.pkgId, IPackageRootMgr.GENERATED_ROOT); if ((srcRootId == ErrorCode.NOT_FOUND) || (genRootId == ErrorCode.NOT_FOUND)) { throw new FatalError("Unable to fetch source or generated package root for package " + pkg.pkgId); } /* repeat until cancelled, or a valid selection is made */ boolean done = false; while (!done) { /* bring up the selection dialog so the user can select a directory */ VFSTreeSelectionDialog dialog = new VFSTreeSelectionDialog(getShell(), buildStore, "Select the directory in which this action should execute", true, false); /* * if OK is pressed, then fetch the selected directory, validate that it's within * the package's root. The performOK() method will actually put the change into effect. */ if (dialog.open() == VFSTreeSelectionDialog.OK) { Object[] result = dialog.getResult(); if (result.length == 1) { UIDirectory selection = (UIDirectory)result[0]; int possiblePathId = selection.getId(); /* validate that the selected directory is within the package roots */ if (fileMgr.isAncestorOf(srcRootId, possiblePathId) || fileMgr.isAncestorOf(genRootId, possiblePathId)) { selectedPathId = possiblePathId; done = true; } /* else - give an error */ else { String pkgSrcRoot = fileMgr.getPathName(srcRootId); String pkgGenRoot = fileMgr.getPathName(genRootId); AlertDialog.displayErrorDialog("Invalid Directory", "The directory you have selected is not within the current package's " + "source or generated root." + "\n\nPackage Source Root : " + pkgSrcRoot + "\nPackage Generated Root : " + pkgGenRoot); } } } /* else cancelled */ else { done = true; } } } /*-------------------------------------------------------------------------------------*/ /** * Redraw the page with the latest values. */ private void refreshPage() { actionDirectoryLabelValue.setText(fileMgr.getPathName(selectedPathId)); panel.layout(); } /*-------------------------------------------------------------------------------------*/ /* (non-Javadoc) * @see org.eclipse.jface.preference.PreferencePage#performDefaults() */ @Override protected void performDefaults() { selectedPathId = originalPathId; refreshPage(); super.performDefaults(); } /*-------------------------------------------------------------------------------------*/ }