summaryrefslogtreecommitdiff
path: root/platform/dvcs-impl/src/com/intellij/dvcs/push/ui
diff options
context:
space:
mode:
Diffstat (limited to 'platform/dvcs-impl/src/com/intellij/dvcs/push/ui')
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java4
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java53
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java53
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java30
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java9
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsFullCommitDetailsNode.java12
-rw-r--r--platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java25
7 files changed, 137 insertions, 49 deletions
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java
index 5d0d20cdc4c0..b5747de91bf7 100644
--- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/EditableTreeNode.java
@@ -20,7 +20,9 @@ import org.jetbrains.annotations.NotNull;
public interface EditableTreeNode extends CustomRenderedTreeNode {
- void fireOnChange(@NotNull String value);
+ void fireOnChange();
+
+ void fireOnCancel();
void fireOnSelectionChange(boolean isSelected);
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java
index b07bf9243f8a..0b4bcb0fbef0 100644
--- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/PushLog.java
@@ -31,7 +31,6 @@ import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.tree.TreeUtil;
import com.intellij.vcs.log.VcsFullCommitDetails;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.CellEditorListener;
@@ -56,6 +55,7 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
private final ChangesBrowser myChangesBrowser;
private final CheckboxTree myTree;
private final MyTreeCellRenderer myTreeCellRenderer;
+ //private final AtomicBoolean myIgnoreStopEditing = new AtomicBoolean(false);
public PushLog(Project project, CheckedTreeNode root) {
DefaultTreeModel treeModel = new DefaultTreeModel(root);
@@ -96,14 +96,17 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
treeCellEditor.addCellEditorListener(new CellEditorListener() {
@Override
public void editingStopped(ChangeEvent e) {
+ DefaultMutableTreeNode node = (DefaultMutableTreeNode)myTree.getLastSelectedPathComponent();
+ if (node != null && node instanceof EditableTreeNode) {
+ ((EditableTreeNode)node).fireOnChange();
+ }
}
@Override
public void editingCanceled(ChangeEvent e) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)myTree.getLastSelectedPathComponent();
if (node != null && node instanceof EditableTreeNode) {
- //todo restore from appropriate editor
- ((EditableTreeNode)node).fireOnChange(((EditableTreeNode)node).getValue());
+ ((EditableTreeNode)node).fireOnCancel();
}
}
});
@@ -119,10 +122,13 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
TreePath[] nodes = myTree.getSelectionPaths();
if (nodes != null) {
ArrayList<Change> changes = new ArrayList<Change>();
- for (TreePath node : nodes) {
- Object nodeInfo = ((DefaultMutableTreeNode)node.getLastPathComponent()).getUserObject();
- if (nodeInfo instanceof VcsFullCommitDetails) {
- changes.addAll(((VcsFullCommitDetails)nodeInfo).getChanges());
+ for (TreePath path : nodes) {
+ if (path.getLastPathComponent() instanceof VcsFullCommitDetailsNode) {
+ VcsFullCommitDetailsNode commitDetailsNode = (VcsFullCommitDetailsNode)path.getLastPathComponent();
+ changes.addAll(commitDetailsNode.getUserObject().getChanges());
+ }
+ else if (path.getLastPathComponent() instanceof RepositoryNode) {
+ changes.addAll(collectAllChanges((RepositoryNode)path.getLastPathComponent()));
}
}
myChangesBrowser.getViewer().setEmptyText("No differences");
@@ -151,10 +157,29 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
add(splitter);
}
+ @NotNull
+ private static Collection<? extends Change> collectAllChanges(@NotNull RepositoryNode rootNode) {
+ ArrayList<Change> changes = new ArrayList<Change>();
+ if (rootNode.getChildCount() <= 0) return changes;
+ for (DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)rootNode.getFirstChild();
+ childNode != null;
+ childNode = (DefaultMutableTreeNode)rootNode.getChildAfter(childNode)) {
+ if (childNode instanceof VcsFullCommitDetailsNode) {
+ changes.addAll(((VcsFullCommitDetailsNode)childNode).getUserObject().getChanges());
+ }
+ }
+ return changes;
+ }
+
private void setDefaultEmptyText() {
myChangesBrowser.getViewer().setEmptyText("No commits selected");
}
+ public void selectNode(@NotNull DefaultMutableTreeNode node) {
+ TreePath selectionPath = new TreePath(node.getPath());
+ myTree.addSelectionPath(selectionPath);
+ }
+
// Make changes available for diff action
@Override
public void calcData(DataKey key, DataSink sink) {
@@ -173,7 +198,7 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
@Override
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
if (e.getKeyCode() == KeyEvent.VK_ENTER && myTree.isEditing()) {
- myTree.cancelEditing();
+ myTree.stopEditing();
return true;
}
return super.processKeyBinding(ks, e, condition, pressed);
@@ -185,6 +210,10 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
setChildren(parentNode, Collections.singleton(loading));
}
+ public JComponent getPreferredFocusedComponent() {
+ return myTree;
+ }
+
private class MyTreeCellEditor extends DefaultCellEditor {
public MyTreeCellEditor(JTextField field) {
@@ -265,6 +294,7 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
final DefaultTreeModel model = ((DefaultTreeModel)myTree.getModel());
model.nodeStructureChanged(parentNode);
TreePath path = TreeUtil.getPathFromRoot(parentNode);
+ //myIgnoreStopEditing.set(true);
if (shouldExpand) {
myTree.expandPath(path);
}
@@ -274,16 +304,15 @@ public class PushLog extends JPanel implements TypeSafeDataProvider {
}
finally {
TREE_CONSTRUCTION_LOCK.writeLock().unlock();
+ //myIgnoreStopEditing.set(false);
}
}
- @Nullable
- public JComponent startEditNode(@NotNull TreeNode node) {
+ public void startEditNode(@NotNull TreeNode node) {
TreePath path = TreeUtil.getPathFromRoot(node);
if (!myTree.isEditing()) {
+ myTree.setSelectionPath(path);
myTree.startEditingAtPath(path);
}
- return (JComponent)myTree.getCellEditor()
- .getTreeCellEditorComponent(myTree, node, false, false, false, myTree.getRowForPath(path));
}
}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java
index 24a26ece96d9..05e752c4be85 100644
--- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryNode.java
@@ -17,26 +17,27 @@ package com.intellij.dvcs.push.ui;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.ui.CheckedTreeNode;
-import com.intellij.ui.ColoredTreeCellRenderer;
-import com.intellij.ui.EditorTextField;
-import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.ui.*;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
+import java.util.ArrayList;
-public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode {
- protected final static String ENTER_REMOTE = "Enter Remote";
+public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode, Comparable<RepositoryNode> {
@NotNull private final RepositoryWithBranchPanel myRepositoryPanel;
-
+ @NotNull protected SimpleColoredText myTargetPresentation;
private ProgressIndicator myCurrentIndicator;
- public RepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel) {
+ public RepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel, @NotNull SimpleColoredText targetPresentation) {
super(repositoryPanel);
myRepositoryPanel = repositoryPanel;
+ myTargetPresentation = targetPresentation;
+ }
+
+ public void setTargetPresentation(@NotNull SimpleColoredText targetPresentation) {
+ myTargetPresentation = targetPresentation;
}
public boolean isCheckboxVisible() {
@@ -51,30 +52,38 @@ public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode
renderer.append(myRepositoryPanel.getSourceName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
renderer.append(myRepositoryPanel.getArrow(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
EditorTextField textField = myRepositoryPanel.getRemoteTextFiled();
- renderTargetName(renderer, textField, myRepositoryPanel.getRemoteTargetName());
+ renderTargetName(renderer, textField);
Insets insets = BorderFactory.createEmptyBorder().getBorderInsets(textField);
renderer.setBorder(new EmptyBorder(insets));
}
- protected void renderTargetName(@NotNull ColoredTreeCellRenderer renderer, @NotNull EditorTextField textField,
- @NotNull String targetName) {
- if (StringUtil.isEmptyOrSpaces(targetName)) {
- renderer.append(ENTER_REMOTE, SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES, textField);
- }
- else {
- renderer.append(targetName, SimpleTextAttributes.SYNTHETIC_ATTRIBUTES, textField);
+ protected void renderTargetName(@NotNull ColoredTreeCellRenderer renderer, @NotNull EditorTextField textField) {
+ ArrayList<String> strings = myTargetPresentation.getTexts();
+ ArrayList<SimpleTextAttributes> attributes = myTargetPresentation.getAttributes();
+ for (int i = 0; i < strings.size(); i++) {
+ renderer.append(strings.get(i), attributes.get(i), textField);
}
}
@Override
+ public Object getUserObject() {
+ return myRepositoryPanel;
+ }
+
+ @Override
@NotNull
public String getValue() {
return myRepositoryPanel.getRemoteTargetName();
}
@Override
- public void fireOnChange(@NotNull String value) {
- myRepositoryPanel.fireOnChange(value);
+ public void fireOnChange() {
+ myRepositoryPanel.fireOnChange();
+ }
+
+ @Override
+ public void fireOnCancel() {
+ myRepositoryPanel.fireOnCancel();
}
@Override
@@ -94,4 +103,10 @@ public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode
public ProgressIndicator startLoading() {
return myCurrentIndicator = new EmptyProgressIndicator();
}
+
+ public int compareTo(@NotNull RepositoryNode repositoryNode) {
+ String name = myRepositoryPanel.getRepositoryName();
+ RepositoryWithBranchPanel panel = (RepositoryWithBranchPanel)repositoryNode.getUserObject();
+ return name.compareTo(panel.getRepositoryName());
+ }
}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java
index c1afcdd52839..cd93d0653c36 100644
--- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/RepositoryWithBranchPanel.java
@@ -36,7 +36,6 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
-import java.util.Collection;
import java.util.List;
public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCellRenderer {
@@ -48,12 +47,14 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel
private final JLabel myRepositoryLabel;
private final ColoredTreeCellRenderer myTextRenderer;
@NotNull private final List<RepositoryNodeListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+ private String myOldDestination;
public RepositoryWithBranchPanel(Project project, @NotNull String repoName,
- @NotNull String sourceName, String targetName, @NotNull Collection<String> targetVariants) {
+ @NotNull String sourceName, String targetName, @NotNull final List<String> targetVariants) {
super();
setLayout(new BorderLayout());
myRepositoryCheckbox = new JBCheckBox();
+ myRepositoryCheckbox.setFocusable(false);
myRepositoryCheckbox.setOpaque(false);
myRepositoryCheckbox.addActionListener(new ActionListener() {
@Override
@@ -64,8 +65,14 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel
myRepositoryLabel = new JLabel(repoName);
myLocalBranch = new JBLabel(sourceName);
myArrowLabel = new JLabel(" -> ");
+ myOldDestination = targetName;
TextFieldWithAutoCompletionListProvider<String> provider =
- new TextFieldWithAutoCompletion.StringsCompletionProvider(targetVariants, null);
+ new TextFieldWithAutoCompletion.StringsCompletionProvider(targetVariants, null) {
+ @Override
+ public int compare(String item1, String item2) {
+ return Integer.valueOf(ContainerUtil.indexOf(targetVariants, item1)).compareTo(ContainerUtil.indexOf(targetVariants, item2));
+ }
+ };
myDestBranchTextField = new TextFieldWithAutoCompletion<String>(project, provider, true, targetName) {
@Override
@@ -77,15 +84,17 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel
protected void updateBorder(@NotNull final EditorEx editor) {
}
};
- myDestBranchTextField.setBorder(UIUtil.getTableFocusCellHighlightBorder());//getTextFieldBorder());
+ myDestBranchTextField.setBorder(UIUtil.getTableFocusCellHighlightBorder());
myDestBranchTextField.setOneLineMode(true);
myDestBranchTextField.setOpaque(true);
- myDestBranchTextField.addFocusListener(new FocusAdapter() {
+ FocusAdapter focusListener = new FocusAdapter() {
@Override
public void focusGained(FocusEvent e) {
myDestBranchTextField.selectAll();
}
- });
+ };
+ myDestBranchTextField.addFocusListener(focusListener);
+ addFocusListener(focusListener);
myTextRenderer = new ColoredTreeCellRenderer() {
public void customizeCellRenderer(@NotNull JTree tree,
@@ -169,9 +178,10 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel
myListeners.add(listener);
}
- public void fireOnChange(@NotNull String newValue) {
+ public void fireOnChange() {
+ myOldDestination = myDestBranchTextField.getText();
for (RepositoryNodeListener listener : myListeners) {
- listener.onTargetChanged(newValue);
+ listener.onTargetChanged(myOldDestination);
}
}
@@ -180,6 +190,10 @@ public class RepositoryWithBranchPanel extends NonOpaquePanel implements TreeCel
listener.onSelectionChanged(isSelected);
}
}
+
+ public void fireOnCancel() {
+ myDestBranchTextField.setText(myOldDestination);
+ }
}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java
index c566dd6f2867..81fb2bd1a9d0 100644
--- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/SingleRepositoryNode.java
@@ -17,6 +17,7 @@ package com.intellij.dvcs.push.ui;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.EditorTextField;
+import com.intellij.ui.SimpleColoredText;
import com.intellij.ui.SimpleTextAttributes;
import org.jetbrains.annotations.NotNull;
@@ -28,8 +29,8 @@ public class SingleRepositoryNode extends RepositoryNode {
@NotNull private final RepositoryWithBranchPanel myRepositoryPanel;
- public SingleRepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel) {
- super(repositoryPanel);
+ public SingleRepositoryNode(@NotNull RepositoryWithBranchPanel repositoryPanel, @NotNull SimpleColoredText customTargetPresentation) {
+ super(repositoryPanel, customTargetPresentation);
myRepositoryPanel = repositoryPanel;
}
@@ -43,10 +44,8 @@ public class SingleRepositoryNode extends RepositoryNode {
renderer.append(myRepositoryPanel.getSourceName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
renderer.append(myRepositoryPanel.getArrow(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
EditorTextField textField = myRepositoryPanel.getRemoteTextFiled();
- String targetName = myRepositoryPanel.getRemoteTargetName();
- renderTargetName(renderer, textField, targetName);
+ renderTargetName(renderer, textField);
Insets insets = BorderFactory.createEmptyBorder().getBorderInsets(textField);
renderer.setBorder(new EmptyBorder(insets));
}
-
}
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsFullCommitDetailsNode.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsFullCommitDetailsNode.java
index 0df7af05d496..51e8aaf3e9db 100644
--- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsFullCommitDetailsNode.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsFullCommitDetailsNode.java
@@ -17,6 +17,7 @@ package com.intellij.dvcs.push.ui;
import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkHtmlRenderer;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
@@ -30,16 +31,21 @@ public class VcsFullCommitDetailsNode extends DefaultMutableTreeNode implements
@NotNull private final Project myProject;
private final VcsFullCommitDetails myCommit;
- public VcsFullCommitDetailsNode(@NotNull Project project, VcsFullCommitDetails commit) {
+ public VcsFullCommitDetailsNode(@NotNull Project project, @NotNull VcsFullCommitDetails commit) {
super(commit, false);
myProject = project;
myCommit = commit;
}
@Override
+ public VcsFullCommitDetails getUserObject() {
+ return myCommit;
+ }
+
+ @Override
public void render(@NotNull ColoredTreeCellRenderer renderer) {
- renderer
- .append(myCommit.getSubject(), new SimpleTextAttributes(SimpleTextAttributes.STYLE_SMALLER, renderer.getForeground()));
+ String subject = StringUtil.shortenTextWithEllipsis(myCommit.getSubject(), 80, 0);
+ renderer.append(subject, new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, renderer.getForeground()));
}
public String getTooltip() {
diff --git a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java
index b441952f7a43..22f1e74abbbd 100644
--- a/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java
+++ b/platform/dvcs-impl/src/com/intellij/dvcs/push/ui/VcsPushDialog.java
@@ -15,11 +15,13 @@
*/
package com.intellij.dvcs.push.ui;
+import com.intellij.CommonBundle;
import com.intellij.dvcs.push.PushController;
import com.intellij.dvcs.push.VcsPushOptionsPanel;
import com.intellij.dvcs.repo.Repository;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.OptionAction;
import com.intellij.openapi.ui.ValidationInfo;
import net.miginfocom.swing.MigLayout;
@@ -32,8 +34,11 @@ import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
+import static com.intellij.openapi.ui.Messages.OK;
+
public class VcsPushDialog extends DialogWrapper {
+ @NotNull private final Project myProject;
private final PushLog myListPanel;
private final PushController myController;
private final Action[] myExecutorActions = {new DvcsPushAction("&Force Push", true)};
@@ -43,8 +48,9 @@ public class VcsPushDialog extends DialogWrapper {
public VcsPushDialog(@NotNull Project project, @NotNull List<? extends Repository> selectedRepositories) {
super(project);
+ myProject = project;
myController = new PushController(project, this, selectedRepositories);
- myListPanel = myController.getPushPanelInfo();
+ myListPanel = myController.getPushPanelLog();
myAdditionalOptionsFromVcsPanel = new JPanel(new MigLayout("ins 0 0, flowx"));
init();
setOKButtonText("Push");
@@ -82,6 +88,12 @@ public class VcsPushDialog extends DialogWrapper {
return actions.toArray(new Action[actions.size()]);
}
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return myListPanel.getPreferredFocusedComponent();
+ }
+
@NotNull
@Override
protected Action getOKAction() {
@@ -127,6 +139,12 @@ public class VcsPushDialog extends DialogWrapper {
@Override
public void actionPerformed(ActionEvent e) {
+ if (myForce) {
+ int answer = Messages.showOkCancelDialog(myProject, getConfirmationMessage(),
+ "Force Push",
+ "&Force Push", CommonBundle.getCancelButtonText(), Messages.getWarningIcon());
+ if (answer != OK) return;
+ }
myController.push(myForce);
close(OK_EXIT_CODE);
}
@@ -141,4 +159,9 @@ public class VcsPushDialog extends DialogWrapper {
myOptions = actions;
}
}
+
+ @NotNull
+ private static String getConfirmationMessage() {
+ return "You're going to force push. It will overwrite commits at the remote. Are you sure you want to proceed?";
+ }
}