diff options
author | kwilk | 2011-07-05 22:38:19 +0000 |
---|---|---|
committer | Ryan D. Brooks | 2011-07-05 22:38:19 +0000 |
commit | da53851eb2edb1d4f52612775d287c5b6e73daa0 (patch) | |
tree | 513a3c2b5e9580b71c4f603921b1ff6f8a31d496 | |
parent | 9a9f5184b77e0d48150af8ddd806e36f0097e920 (diff) | |
download | org.eclipse.osee-da53851eb2edb1d4f52612775d287c5b6e73daa0.tar.gz org.eclipse.osee-da53851eb2edb1d4f52612775d287c5b6e73daa0.tar.xz org.eclipse.osee-da53851eb2edb1d4f52612775d287c5b6e73daa0.zip |
feature: ChangeArtifactType blam accepts plain text as GUID input
9 files changed, 203 insertions, 33 deletions
diff --git a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ChangeArtifactType.java b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ChangeArtifactType.java index e8114157590..9b3897ced63 100644 --- a/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ChangeArtifactType.java +++ b/plugins/org.eclipse.osee.framework.skynet.core/src/org/eclipse/osee/framework/skynet/core/artifact/ChangeArtifactType.java @@ -31,6 +31,8 @@ import org.eclipse.osee.framework.database.core.ConnectionHandler; import org.eclipse.osee.framework.database.core.IOseeStatement; import org.eclipse.osee.framework.database.core.IdJoinQuery; import org.eclipse.osee.framework.database.core.JoinUtility; +import org.eclipse.osee.framework.jdk.core.type.MutableBoolean; +import org.eclipse.osee.framework.jdk.core.type.Pair; import org.eclipse.osee.framework.logging.OseeLog; import org.eclipse.osee.framework.skynet.core.event.OseeEventManager; import org.eclipse.osee.framework.skynet.core.event.model.ArtifactEvent; @@ -50,6 +52,7 @@ public class ChangeArtifactType { private static List<Attribute<?>> attributesToPurge; private static List<RelationLink> relationsToDelete; private static final IStatus promptStatus = new Status(IStatus.WARNING, Activator.PLUGIN_ID, 256, "", null); + private static boolean userAnsweredYesToAll = false; /** * Changes the descriptor of the artifacts to the provided artifact descriptor @@ -66,7 +69,7 @@ public class ChangeArtifactType { processAttributes(artifact, artifactType); processRelations(artifact, artifactType); artifactsUserAccepted.add(artifact); - if (doesUserAcceptArtifactChange(artifact, artifactType)) { + if (userAnsweredYesToAll || doesUserAcceptArtifactChange(artifact, artifactType)) { ArtifactType originalType = artifact.getArtifactType(); boolean success = changeArtifactTypeThroughHistory(artifact, artifactType); if (success) { @@ -162,13 +165,24 @@ public class ChangeArtifactType { * artifact type else false. */ private static boolean doesUserAcceptArtifactChange(final Artifact artifact, final ArtifactType artifactType) { - if (!relationsToDelete.isEmpty() || !attributesToPurge.isEmpty()) { + if ((!relationsToDelete.isEmpty() || !attributesToPurge.isEmpty()) && !userAnsweredYesToAll) { StringBuffer sb = new StringBuffer(50); getConflictString(sb, artifact, artifactType); try { - return (Boolean) DebugPlugin.getDefault().getStatusHandler(promptStatus).handleStatus(promptStatus, - sb.toString()); + Object result = + DebugPlugin.getDefault().getStatusHandler(promptStatus).handleStatus(promptStatus, sb.toString()); + + MutableBoolean answer = null; + + if (result instanceof Pair<?, ?>) { + Pair<?, ?> value = (Pair<?, ?>) result; + answer = (MutableBoolean) value.getFirst(); + Integer kindOfAnswer = (Integer) value.getSecond(); + + userAnsweredYesToAll = kindOfAnswer == 1 && answer; + } + return answer == null ? false : answer.getValue(); } catch (Exception ex) { OseeLog.log(Activator.class, Level.SEVERE, ex); return false; diff --git a/plugins/org.eclipse.osee.framework.skynet.core/support/OseeTypes_Framework.osee b/plugins/org.eclipse.osee.framework.skynet.core/support/OseeTypes_Framework.osee index 647d2bd1085..f48226f2bba 100644 --- a/plugins/org.eclipse.osee.framework.skynet.core/support/OseeTypes_Framework.osee +++ b/plugins/org.eclipse.osee.framework.skynet.core/support/OseeTypes_Framework.osee @@ -586,6 +586,7 @@ artifactType "System Requirement" extends "Requirement" , "MS Word Template" { attribute "Verification Level" attribute "Effectivity" attribute "Verification Acceptance Criteria" + attribute "Verification Event" } attributeType "Req Type" extends EnumeratedAttribute { diff --git a/plugins/org.eclipse.osee.framework.ui.plugin/src/org/eclipse/osee/framework/ui/plugin/xnavigate/XNavigateComposite.java b/plugins/org.eclipse.osee.framework.ui.plugin/src/org/eclipse/osee/framework/ui/plugin/xnavigate/XNavigateComposite.java index fb687fe35f6..6275cf4d37f 100644 --- a/plugins/org.eclipse.osee.framework.ui.plugin/src/org/eclipse/osee/framework/ui/plugin/xnavigate/XNavigateComposite.java +++ b/plugins/org.eclipse.osee.framework.ui.plugin/src/org/eclipse/osee/framework/ui/plugin/xnavigate/XNavigateComposite.java @@ -71,18 +71,14 @@ public class XNavigateComposite extends Composite { this.navigateViewItems = navigateViewItems; setLayout(new GridLayout()); - setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - - createControl(this); + createControl(); } - private void createControl(Composite parent) { - filteredTree = new OSEEFilteredTree(parent, SWT.SINGLE | SWT.BORDER, patternFilter); + private void createControl() { + filteredTree = new OSEEFilteredTree(this, SWT.SINGLE | SWT.BORDER, patternFilter); filteredTree.getViewer().setContentProvider(new XNavigateContentProvider()); - filteredTree.setInitialText(""); filteredTree.getViewer().setLabelProvider(new XNavigateLabelProvider()); filteredTree.getViewer().getTree().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - // Disable native tree tooltip filteredTree.getViewer().getTree().setToolTipText(""); filteredTree.getViewer().getTree().addListener(SWT.Dispose, tableListener); diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/AbstractBlam.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/AbstractBlam.java index c16d2ba40ea..6b8068cba8e 100644 --- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/AbstractBlam.java +++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/AbstractBlam.java @@ -15,6 +15,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.xml.parsers.ParserConfigurationException; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -29,6 +31,7 @@ import org.eclipse.osee.framework.core.operation.OperationLogger; import org.eclipse.osee.framework.core.operation.Operations; import org.eclipse.osee.framework.database.IOseeDatabaseService; import org.eclipse.osee.framework.jdk.core.util.Lib; +import org.eclipse.osee.framework.jdk.core.util.Strings; import org.eclipse.osee.framework.logging.OseeLevel; import org.eclipse.osee.framework.logging.OseeLog; import org.eclipse.osee.framework.skynet.core.artifact.Artifact; @@ -47,12 +50,52 @@ import org.xml.sax.SAXException; * @author Ryan D. Brooks */ public abstract class AbstractBlam implements IDynamicWidgetLayoutListener { + + private static final String DEFAULT_DESCRIPTION = + "Select parameters below and click the play button at the top right."; + + private final Pattern capitalLetter = Pattern.compile("[A-Z]{1}?[a-z]+"); + + public enum BlamUiSource { + DEFAULT, + FILE + } + public static final String branchXWidgetXml = "<xWidgets><XWidget xwidgetType=\"XBranchSelectWidget\" displayName=\"Branch\" /></xWidgets>"; public static final String emptyXWidgetsXml = "<xWidgets/>"; protected IOseeDatabaseService databaseService; private OperationLogger logger; + private final String description; + private final BlamUiSource source; + private final String name; + + public AbstractBlam() { + this(null, DEFAULT_DESCRIPTION, BlamUiSource.DEFAULT); + } + + public AbstractBlam(String name, String usageDescription, BlamUiSource source) { + this.name = Strings.isValid(name) ? name : generateNameFromClass(); + this.description = Strings.isValid(usageDescription) ? usageDescription : DEFAULT_DESCRIPTION; + this.source = source != null ? source : BlamUiSource.DEFAULT; + } + + private String generateNameFromClass() { + String className = getName(); + if (Strings.isValid(className) && className.indexOf(" ") == -1) { + StringBuilder generatedName = new StringBuilder(className.length() + 7); + + Matcher capMatch = capitalLetter.matcher(className); + for (boolean found = capMatch.find(); found || !capMatch.hitEnd(); found = capMatch.find()) { + generatedName.append(capMatch.start() > 0 ? " " + capMatch.group() : capMatch.group()); + } + return generatedName.toString(); + } else { + return className; + } + } + public void runOperation(VariableMap variableMap, IProgressMonitor monitor) throws Exception { throw new OseeStateException( "either runOperation or createOperation but be overriden by subclesses of AbstractBlam"); @@ -68,9 +111,14 @@ public abstract class AbstractBlam implements IDynamicWidgetLayoutListener { */ public abstract Collection<String> getCategories(); - @SuppressWarnings("unused") public String getXWidgetsXml() throws OseeCoreException { - return AbstractBlam.branchXWidgetXml; + switch (source) { + case FILE: + return getXWidgetsXmlFromUiFile(getClass().getSimpleName(), SkynetGuiPlugin.PLUGIN_ID); + case DEFAULT: + default: + return AbstractBlam.branchXWidgetXml; + } } /** @@ -101,11 +149,11 @@ public abstract class AbstractBlam implements IDynamicWidgetLayoutListener { } public String getDescriptionUsage() { - return "Select parameters below and click the play button at the top right."; + return this.description; } public String getName() { - return getClass().getSimpleName(); + return Strings.isValid(this.name) ? this.name : getClass().getSimpleName(); } public void setOseeDatabaseService(IOseeDatabaseService service) { diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/ChangeArtifactTypeBlam.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/ChangeArtifactTypeBlam.java index ec4cbbfe597..f0ee01ceb4d 100644 --- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/ChangeArtifactTypeBlam.java +++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/ChangeArtifactTypeBlam.java @@ -13,9 +13,29 @@ package org.eclipse.osee.framework.ui.skynet.blam.operation; import java.util.Arrays; import java.util.Collection; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.osee.framework.jdk.core.util.GUID; +import org.eclipse.osee.framework.logging.OseeLevel; +import org.eclipse.osee.framework.logging.OseeLog; +import org.eclipse.osee.framework.skynet.core.artifact.Artifact; import org.eclipse.osee.framework.skynet.core.artifact.ChangeArtifactType; +import org.eclipse.osee.framework.skynet.core.artifact.search.ArtifactQuery; +import org.eclipse.osee.framework.ui.skynet.SkynetGuiPlugin; import org.eclipse.osee.framework.ui.skynet.blam.AbstractBlam; import org.eclipse.osee.framework.ui.skynet.blam.VariableMap; +import org.eclipse.osee.framework.ui.skynet.widgets.XBranchSelectWidget; +import org.eclipse.osee.framework.ui.skynet.widgets.XListDropViewer; +import org.eclipse.osee.framework.ui.skynet.widgets.XModifiedListener; +import org.eclipse.osee.framework.ui.skynet.widgets.XWidget; +import org.eclipse.osee.framework.ui.skynet.widgets.workflow.DynamicXWidgetLayout; +import org.eclipse.osee.framework.ui.swt.Displays; +import org.eclipse.swt.SWT; +import org.eclipse.swt.dnd.Clipboard; +import org.eclipse.swt.dnd.TextTransfer; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.ui.forms.widgets.FormToolkit; /** * Changes the descriptor type of an artifact to the provided descriptor. @@ -24,9 +44,14 @@ import org.eclipse.osee.framework.ui.skynet.blam.VariableMap; */ public class ChangeArtifactTypeBlam extends AbstractBlam { - @Override - public String getName() { - return "Change Artifact Type"; + private XListDropViewer artifactListWidget; + private XBranchSelectWidget branchWidget; + + private static final String description = + "Start by drag-and-drop or by pasting GUIDs of artifacts. Log what the previous type of each artifact was because that information is loss after running this blam"; + + public ChangeArtifactTypeBlam() { + super(null, description, BlamUiSource.FILE); } @Override @@ -36,19 +61,56 @@ public class ChangeArtifactTypeBlam extends AbstractBlam { } @Override - public String getXWidgetsXml() { - return "<xWidgets><XWidget xwidgetType=\"XListDropViewer\" displayName=\"artifacts\" />" + - // - "<XWidget xwidgetType=\"XArtifactTypeComboViewer\" displayName=\"New Artifact Type\" /></xWidgets>"; + public void widgetCreating(XWidget xWidget, FormToolkit toolkit, Artifact art, DynamicXWidgetLayout dynamicXWidgetLayout, XModifiedListener modListener, boolean isEditable) { + String widgetLabel = xWidget.getLabel(); + + if (widgetLabel.equals("artifacts")) { + artifactListWidget = (XListDropViewer) xWidget; + } else if (widgetLabel.equals("Branch")) { + branchWidget = (XBranchSelectWidget) xWidget; + } } @Override - public Collection<String> getCategories() { - return Arrays.asList("Admin"); + public void widgetCreated(XWidget xWidget, FormToolkit toolkit, Artifact art, DynamicXWidgetLayout dynamicXWidgetLayout, XModifiedListener modListener, boolean isEditable) { + String widgetName = xWidget.getLabel(); + if (widgetName.equals("artifacts")) { + final Menu popupMenu = artifactListWidget.popupMenu(); + MenuItem paste = new MenuItem(popupMenu, SWT.NONE); + paste.setText("Paste GUIDs from Clipboard"); + paste.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + Displays.ensureInDisplayThread(new Runnable() { + @Override + public void run() { + final Clipboard cb = new Clipboard(popupMenu.getDisplay()); + TextTransfer transfer = TextTransfer.getInstance(); + String data = (String) cb.getContents(transfer); + + String[] guids = data.split("\t|\n|\r"); + for (String guid : guids) { + if (GUID.isValid(guid)) { + try { + Artifact artifact = ArtifactQuery.getArtifactFromId(guid, branchWidget.getSelection()); + artifactListWidget.addToInput(artifact); + } catch (Exception ex) { + OseeLog.log(SkynetGuiPlugin.class, OseeLevel.SEVERE_POPUP, ex); + } + } + } + } + }); + } + + }); + + } } @Override - public String getDescriptionUsage() { - return "Log what the previous type of each artifact was because that information is loss after running this blam"; + public Collection<String> getCategories() { + return Arrays.asList("Admin"); } }
\ No newline at end of file diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/XWidgetsExampleBlam.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/XWidgetsExampleBlam.java index ab970848811..6c21b5e58f6 100644 --- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/XWidgetsExampleBlam.java +++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/blam/operation/XWidgetsExampleBlam.java @@ -40,7 +40,7 @@ public class XWidgetsExampleBlam extends AbstractBlam { @Override public String getXWidgetsXml() throws OseeCoreException { - return getXWidgetsXmlFromUiFile(getClass().getSimpleName(), SkynetGuiPlugin.PLUGIN_ID); + return getXWidgetsXmlFromUiFile(getName(), SkynetGuiPlugin.PLUGIN_ID); } @Override diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/handler/RemoveTrackChangesHandler.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/handler/RemoveTrackChangesHandler.java index f960f6189d8..82d7a9c7334 100644 --- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/handler/RemoveTrackChangesHandler.java +++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/handler/RemoveTrackChangesHandler.java @@ -13,31 +13,51 @@ package org.eclipse.osee.framework.ui.skynet.handler; import java.util.logging.Level; import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.core.IStatusHandler; +import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.osee.framework.jdk.core.type.MutableBoolean; +import org.eclipse.osee.framework.jdk.core.type.Pair; import org.eclipse.osee.framework.logging.OseeLog; import org.eclipse.osee.framework.ui.skynet.SkynetGuiPlugin; import org.eclipse.osee.framework.ui.skynet.render.RenderingUtil; import org.eclipse.osee.framework.ui.swt.Displays; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.PlatformUI; /** * @author Jeff C. Phillips */ public class RemoveTrackChangesHandler implements IStatusHandler { + + private final int YES = 0; + private final int YES_TO_ALL = 1; + private final int NO = 2; + @Override public Object handleStatus(IStatus status, Object source) { final MutableBoolean isOkToRemove = new MutableBoolean(false); final String message = (String) source; + final Pair<MutableBoolean, Integer> answer = new Pair<MutableBoolean, Integer>(isOkToRemove, NO); + if (RenderingUtil.arePopupsAllowed()) { Displays.pendInDisplayThread(new Runnable() { @Override public void run() { - boolean doesUserConfirm = - MessageDialog.openQuestion(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), - "Confirm Removal Of Track Changes ", message); + + MoreChangesHandlingDialog dialog = + new MoreChangesHandlingDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), + "Confirm Removal Of Track Changes ", null, message, MessageDialog.QUESTION, new String[] { + IDialogConstants.YES_LABEL, + IDialogConstants.YES_TO_ALL_LABEL, + IDialogConstants.NO_LABEL}, 0); + dialog.updateStyle(); + + boolean doesUserConfirm = dialog.open() == YES || dialog.open() == YES_TO_ALL; isOkToRemove.setValue(doesUserConfirm); + answer.setSecond(dialog.open()); } }); } else { @@ -45,6 +65,19 @@ public class RemoveTrackChangesHandler implements IStatusHandler { isOkToRemove.setValue(true); OseeLog.log(SkynetGuiPlugin.class, Level.INFO, "Test - accept track change removal."); } - return isOkToRemove.getValue(); + return answer; } + private class MoreChangesHandlingDialog extends MessageDialog { + public MoreChangesHandlingDialog(Shell parentShell, String dialogTitle, Image dialogTitleImage, String dialogMessage, int dialogImageType, String[] dialogButtonLabels, int defaultIndex) { + super(parentShell, dialogTitle, dialogTitleImage, dialogMessage, dialogImageType, dialogButtonLabels, + defaultIndex); + } + + public void updateStyle() { + int newStyle = getShellStyle(); + newStyle &= SWT.SHEET; + setShellStyle(getShellStyle() | newStyle); + } + } + } diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/widgets/XListDropViewer.java b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/widgets/XListDropViewer.java index 2b7bd461a6f..db8bf6bc9e0 100644 --- a/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/widgets/XListDropViewer.java +++ b/plugins/org.eclipse.osee.framework.ui.skynet/src/org/eclipse/osee/framework/ui/skynet/widgets/XListDropViewer.java @@ -38,6 +38,8 @@ public class XListDropViewer extends XListViewer { private ArrayContentProvider myArrayContentProvider = null; private ArtifactLabelProvider myArtifactLabelProvider = null; + private Menu popupMenu; + public XListDropViewer(String displayLabel) { super(displayLabel); this.myArrayContentProvider = new ArrayContentProvider(); @@ -48,7 +50,7 @@ public class XListDropViewer extends XListViewer { @Override protected void createControls(Composite parent, int horizontalSpan) { - Menu popupMenu = new Menu(parent); + popupMenu = new Menu(parent); setMultiSelect(true); super.setListMenu(popupMenu); super.createControls(parent, horizontalSpan); @@ -59,7 +61,7 @@ public class XListDropViewer extends XListViewer { myTableViewer.getTable().setMenu(popupMenu); } - private void createRemoveFromMenuItem(Menu popupMenu) { + private void createRemoveFromMenuItem(final Menu popupMenu) { removeFromMenuItem = new MenuItem(popupMenu, SWT.PUSH); removeFromMenuItem.setText("Remove From This Blam's Parameters "); removeFromMenuItem.addSelectionListener(new SelectionAdapter() { @@ -83,6 +85,10 @@ public class XListDropViewer extends XListViewer { }); } + public Menu popupMenu() { + return popupMenu; + } + /** * Adds artifacts to the viewer's input. */ @@ -120,6 +126,11 @@ public class XListDropViewer extends XListViewer { } @Override + public void performTextDrop(String text) { + System.out.println("You dragged: " + text); + } + + @Override public Artifact[] getArtifacts() { return null; } diff --git a/plugins/org.eclipse.osee.framework.ui.skynet/ui/ChangeArtifactTypeBlamUi.xml b/plugins/org.eclipse.osee.framework.ui.skynet/ui/ChangeArtifactTypeBlamUi.xml new file mode 100644 index 00000000000..550a8db3b67 --- /dev/null +++ b/plugins/org.eclipse.osee.framework.ui.skynet/ui/ChangeArtifactTypeBlamUi.xml @@ -0,0 +1,5 @@ +<xWidgets> + <XWidget xwidgetType="XBranchSelectWidget" displayName="Branch" /> + <XWidget xwidgetType="XListDropViewer" displayName="artifacts" /> + <XWidget xwidgetType="XArtifactTypeComboViewer" displayName="New Artifact Type" /> +</xWidgets> |