Commit 2c7a9616 authored by Kirill Kirichenko's avatar Kirill Kirichenko
Browse files

IDEA-171869 Win10 LaF search fields reworked

parent d5bf513b
Showing with 237 additions and 88 deletions
+237 -88
......@@ -23,6 +23,7 @@ import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI;
import com.intellij.ide.ui.laf.intellij.MacIntelliJIconCache;
import com.intellij.ide.ui.laf.intellij.MacIntelliJTextFieldUI;
import com.intellij.ide.ui.laf.intellij.WinIntelliJTextFieldUI;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.actionSystem.impl.InplaceActionButtonLook;
......@@ -59,6 +60,8 @@ import javax.swing.text.DefaultEditorKit;
import javax.swing.text.PlainDocument;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
......@@ -385,7 +388,8 @@ public class SearchTextArea extends NonOpaquePanel implements PropertyChangeList
@NotNull
private LafHelper createHelper() {
return SystemInfo.isMac && !UIUtil.isUnderDarcula() ? new MacLafHelper() : new DefaultLafHelper();
return UIUtil.isUnderWin10LookAndFeel() ? new Win10LafHelper() :
SystemInfo.isMac && !UIUtil.isUnderDarcula() ? new MacLafHelper() : new DefaultLafHelper();
}
private static abstract class LafHelper {
......@@ -530,4 +534,82 @@ public class SearchTextArea extends NonOpaquePanel implements PropertyChangeList
}
}
}
private class Win10LafHelper extends DefaultLafHelper implements Border {
private Win10LafHelper() {
MouseListener ml = new MouseAdapter() {
@Override public void mouseEntered(MouseEvent e) {
setHover(true);
}
@Override public void mouseExited(MouseEvent e) {
setHover(false);
}
private void setHover(Boolean hover) {
putClientProperty(WinIntelliJTextFieldUI.HOVER_PROPERTY, hover);
repaint();
}
};
myTextArea.addMouseListener(ml);
addMouseListener(ml);
}
@Override
Border getBorder() {
return this;
}
@Override
void paint(Graphics2D g) {
Rectangle r = new Rectangle(getSize());
JBInsets.removeFrom(r, getInsets());
Graphics2D g2 = (Graphics2D)g.create();
try {
g2.setColor(myTextArea.getBackground());
g2.fill(r);
} finally {
g2.dispose();
}
}
@Override public Insets getBorderInsets(Component c) {
return JBUI.insets(1, 0).asUIResource();
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2 = (Graphics2D)g.create();
try {
Insets i = getInsets();
g2.translate(x + i.left, y + i.top);
width -= i.left + i.right;
height -= i.top + i.bottom;
if (myTextArea.hasFocus()) {
g2.setColor(UIManager.getColor("TextField.focusedBorderColor"));
} else if (isEnabled() && getClientProperty(WinIntelliJTextFieldUI.HOVER_PROPERTY) == Boolean.TRUE) {
g2.setColor(UIManager.getColor("TextField.hoverBorderColor"));
} else {
g2.setColor(UIManager.getColor("TextField.borderColor"));
}
int bw = JBUI.scale(1);
Path2D border = new Path2D.Double(Path2D.WIND_EVEN_ODD);
border.append(new Rectangle2D.Double(0, 0, width, height), false);
border.append(new Rectangle2D.Double(bw, bw, width - bw*2, height - bw*2), false);
g2.fill(border);
} finally {
g2.dispose();
}
}
@Override
public boolean isBorderOpaque() {
return false;
}
}
}
......@@ -28,8 +28,6 @@ import com.intellij.ide.actions.CopyReferenceAction;
import com.intellij.ide.actions.GotoFileAction;
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextBorder;
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI;
import com.intellij.ide.ui.laf.intellij.MacIntelliJTextBorder;
import com.intellij.ide.ui.laf.intellij.MacIntelliJTextFieldUI;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.MnemonicHelper;
import com.intellij.openapi.actionSystem.*;
......@@ -1135,19 +1133,14 @@ public abstract class ChooseByNameBase {
private MyTextField() {
super(40);
if (!UIUtil.isUnderGTKLookAndFeel()) {
if (SystemInfo.isMac && UIUtil.isUnderIntelliJLaF()) {
if (!(getUI() instanceof MacIntelliJTextFieldUI)) {
setUI(MacIntelliJTextFieldUI.createUI(this));
}
setBorder(new MacIntelliJTextBorder());
} else {
if (!(getUI() instanceof DarculaTextFieldUI)) {
setUI(DarculaTextFieldUI.createUI(this));
}
setBorder(new DarculaTextBorder());
// Set UI and border for Darcula and all except Win10, Mac and GTK
if (!UIUtil.isUnderGTKLookAndFeel() && !UIUtil.isUnderDefaultMacTheme() && !UIUtil.isUnderWin10LookAndFeel()) {
if (!(getUI() instanceof DarculaTextFieldUI)) {
setUI(DarculaTextFieldUI.createUI(this));
}
setBorder(new DarculaTextBorder());
}
enableEvents(AWTEvent.KEY_EVENT_MASK);
myCompletionKeyStroke = getShortcut(IdeActions.ACTION_CODE_COMPLETION);
forwardStroke = getShortcut(IdeActions.ACTION_GOTO_FORWARD);
......
......@@ -17,7 +17,10 @@ package com.intellij.ide.ui.laf.intellij;
import com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI;
import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.border.Border;
......@@ -26,6 +29,7 @@ import java.awt.*;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import static com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI.isSquare;
import static com.intellij.ide.ui.laf.intellij.WinIntelliJButtonUI.DISABLED_ALPHA_LEVEL;
/**
......@@ -43,9 +47,13 @@ public class WinIntelliJButtonBorder implements Border, UIResource {
Graphics2D g2 = (Graphics2D)g.create();
AbstractButton b = (AbstractButton)c;
ButtonModel bm = b.getModel();
Rectangle r = new Rectangle(x, y, width, height);
try {
g2.translate(x, y);
if (isSquare(c)) {
JBInsets.removeFrom(r, b.getInsets());
}
g2.translate(r.x, r.y);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
......@@ -66,8 +74,8 @@ public class WinIntelliJButtonBorder implements Border, UIResource {
}
Path2D border = new Path2D.Double(Path2D.WIND_EVEN_ODD);
border.append(new Rectangle2D.Double(0, 0, width, height), false);
border.append(new Rectangle2D.Double(bw, bw, width - 2*bw, height - 2*bw), false);
border.append(new Rectangle2D.Double(0, 0, r.width, r.height), false);
border.append(new Rectangle2D.Double(bw, bw, r.width - 2*bw, r.height - 2*bw), false);
g2.setColor(color);
g2.fill(border);
......@@ -81,7 +89,8 @@ public class WinIntelliJButtonBorder implements Border, UIResource {
if (c.getParent() instanceof ActionToolbar) {
return JBUI.insets(4, 16).asUIResource();
} else if (DarculaButtonUI.isSquare(c)) {
return JBUI.insets(0, 0).asUIResource();
int i = (UIUtil.getParentOfType(Wrapper.class, c) != null) ? 1 : 0;
return JBUI.insets(i).asUIResource();
} else if (DarculaButtonUI.isHelpButton((JComponent)c)) {
return JBUI.insets(0, 0, 0, 10).asUIResource();
} else {
......
......@@ -17,6 +17,7 @@ package com.intellij.ide.ui.laf.intellij;
import com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI;
import com.intellij.util.ui.JBDimension;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.MacUIUtil;
import sun.swing.SwingUtilities2;
......@@ -75,7 +76,17 @@ public class WinIntelliJButtonUI extends DarculaButtonUI {
Graphics2D g2 = (Graphics2D)g.create();
try {
g2.translate(0, 0);
Rectangle r = new Rectangle(c.getSize());
Container parent = c.getParent();
if (c.isOpaque() && parent != null) {
g2.setColor(parent.getBackground());
g2.fill(r);
}
if (isSquare(c)) { // Count insets for square buttons
JBInsets.removeFrom(r, c.getInsets());
}
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, MacUIUtil.USE_QUARTZ ? RenderingHints.VALUE_STROKE_PURE : RenderingHints.VALUE_STROKE_NORMALIZE);
......@@ -83,8 +94,8 @@ public class WinIntelliJButtonUI extends DarculaButtonUI {
c.hasFocus() || bm.isRollover() ? UIManager.getColor("Button.intellij.native.focusedBackgroundColor") :
c.getBackground();
g.setColor(color);
g.fillRect(0, 0, c.getWidth(), c.getHeight());
g2.setColor(color);
g2.fill(r);
paintContents(g2, b);
} finally {
......
......@@ -20,6 +20,7 @@ import com.intellij.ide.ui.laf.darcula.ui.DarculaComboBoxUI;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.ui.JBDimension;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.JBUI;
......@@ -44,6 +45,7 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
private static final String HOVER_PROPERTY = "JComboBox.mouseHover";
private static final String PRESSED_PROPERTY = "JComboBox.mousePressed";
private static final Border DEFAULT_EDITOR_BORDER = JBUI.Borders.empty(1, 0);
private static final int IN_PANEL_OFFSET = 1;
private MouseListener mouseListener;
......@@ -97,49 +99,48 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
}
@Override public void paint(Graphics g, JComponent c) {
int w = c.getWidth();
int h = c.getHeight();
if (c.isOpaque()) {
Container parent = c.getParent();
if (parent != null) {
g.setColor(isTableCellEditor(c) && editor != null ? editor.getBackground() : parent.getBackground());
g.fillRect(0, 0, c.getWidth(), c.getHeight());
Graphics2D g2 = (Graphics2D)g.create();
try{
Rectangle r = new Rectangle(c.getSize());
if (c.isOpaque()) {
Container parent = c.getParent();
if (parent != null) {
g2.setColor(isTableCellEditor(c) && editor != null ? editor.getBackground() : parent.getBackground());
g2.fill(r);
}
}
}
int bw = JBUI.scale(1);
g.setColor(getComboBackground());
g.fillRect(bw, bw, w-2*bw, h-2*bw);
if (!isTableCellEditor(c)) {
paintBorder(c, g, 0, 0, w, h);
hasFocus = comboBox.hasFocus();
}
g2.setColor(getComboBackground());
resizeInPanel(r);
JBInsets.removeFrom(r, JBUI.insets(1));
g2.fill(r);
if (!comboBox.isEditable()) {
Rectangle r = rectangleForCurrentValue();
paintCurrentValue(g, r, hasFocus);
if (!comboBox.isEditable()) {
hasFocus = comboBox.hasFocus();
paintCurrentValue(g, rectangleForCurrentValue(), hasFocus);
}
} finally {
g2.dispose();
}
}
@Override protected Rectangle rectangleForCurrentValue() {
int width = comboBox.getWidth();
int height = comboBox.getHeight();
Insets insets = getInsets();
int buttonSize = height - (insets.top + insets.bottom);
if ( arrowButton != null ) {
int w = comboBox.getWidth();
int h = comboBox.getHeight();
Insets i = getInsets();
int buttonSize = h - (i.top + i.bottom);
if (arrowButton != null) {
buttonSize = arrowButton.getWidth();
}
Rectangle rect = (comboBox.getComponentOrientation().isLeftToRight()) ?
new Rectangle(insets.left, insets.top,
width - (insets.left + insets.right + buttonSize),
height - (insets.top + insets.bottom)) :
new Rectangle(insets.left + buttonSize, insets.top,
width - (insets.left + insets.right + buttonSize),
height - (insets.top + insets.bottom));
new Rectangle(i.left, i.top,
w - (i.left + i.right + buttonSize),
h - (i.top + i.bottom)) :
new Rectangle(i.left + buttonSize, i.top,
w - (i.left + i.right + buttonSize),
h - (i.top + i.bottom));
if (editor instanceof JComponent) {
JBInsets.removeFrom(rect, ((JComponent)editor).getInsets());
......@@ -258,7 +259,9 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
};
button.setOpaque(false);
button.setBorder(JBUI.Borders.empty(1, 0, 1, 1));
int vOffset = inPanel() ? IN_PANEL_OFFSET : 0;
button.setBorder(JBUI.Borders.empty(1 + vOffset, 0, 1 + vOffset, 1));
buttonReleaseListener = new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
......@@ -424,13 +427,16 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
return; //NPE on LaF change
}
Rectangle r = new Rectangle(x, y, width, height);
Graphics2D g2 = (Graphics2D)g.create();
try {
checkFocus();
g2.translate(x, y);
resizeInPanel(r);
g2.translate(r.x, r.y);
checkFocus();
if (Registry.is("ide.inplace.errors.outline") && comboBox.getClientProperty("JComponent.error.outline") == Boolean.TRUE) {
DarculaUIUtil.paintErrorBorder(g2, width, height, 0, true, hasFocus);
DarculaUIUtil.paintErrorBorder(g2, r.width, r.height, 0, true, hasFocus);
} else if (comboBox.isEnabled()) {
if (comboBox.isEditable()) {
if (hasFocus) {
......@@ -455,14 +461,30 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
int bw = JBUI.scale(1);
Path2D border = new Path2D.Double(Path2D.WIND_EVEN_ODD);
border.append(new Rectangle2D.Double(0, 0, width, height), false);
border.append(new Rectangle2D.Double(bw, bw, width - bw*2, height - bw*2), false);
border.append(new Rectangle2D.Double(0, 0, r.width, r.height), false);
border.append(new Rectangle2D.Double(bw, bw, r.width - bw*2, r.height - bw*2), false);
g2.fill(border);
} finally {
g2.dispose();
}
}
private boolean inPanel() {
return UIUtil.getParentOfType(Wrapper.class, comboBox) != null;
}
private void resizeInPanel(Rectangle r) {
if (inPanel()) {
Insets i = comboBox.getInsets();
r.y += i.top;
r.height -= i.top + i.bottom;
int offset = JBUI.scale(IN_PANEL_OFFSET);
r.x += offset;
r.width -= offset;
}
}
private boolean isHover() {
return comboBox != null && comboBox.getClientProperty(HOVER_PROPERTY) == Boolean.TRUE ||
arrowButton != null && arrowButton.getClientProperty(HOVER_PROPERTY) == Boolean.TRUE;
......@@ -485,7 +507,10 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
@Override
protected Insets getInsets() {
return JBUI.insets(0, 5, 0, 0).asUIResource();
boolean inPanel = inPanel();
int vOffset = inPanel ? IN_PANEL_OFFSET : 0;
int hOffset = 5 + (inPanel ? IN_PANEL_OFFSET : 0);
return JBUI.insets(vOffset, hOffset, vOffset, 0).asUIResource();
}
@Override
......
......@@ -27,7 +27,9 @@ import java.awt.*;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import static com.intellij.ide.ui.laf.darcula.ui.TextFieldWithPopupHandlerUI.isSearchFieldWithHistoryPopup;
import static com.intellij.ide.ui.laf.intellij.WinIntelliJTextFieldUI.HOVER_PROPERTY;
import static com.intellij.ide.ui.laf.intellij.WinIntelliJTextFieldUI.adjustVerticalInsets;
/**
* @author Konstantin Bulenkov
......@@ -35,32 +37,28 @@ import static com.intellij.ide.ui.laf.intellij.WinIntelliJTextFieldUI.HOVER_PROP
public class WinIntelliJTextBorder extends DarculaTextBorder {
@Override
public Insets getBorderInsets(Component c) {
int vOffset = TextFieldWithPopupHandlerUI.isSearchField(c) ? 6 : 4;
if (TextFieldWithPopupHandlerUI.isSearchFieldWithHistoryPopup(c)) {
return JBUI.insets(vOffset, 7 + 16 + 3, vOffset, 7 + 16).asUIResource();
}
else if (TextFieldWithPopupHandlerUI.isSearchField(c)) {
return JBUI.insets(vOffset, 4 + 16 + 3, vOffset, 7 + 16).asUIResource();
}
else if (c instanceof JTextField && c.getParent() instanceof ColorPanel) {
if (isSearchFieldWithHistoryPopup(c)) {
return JBUI.insets(3, 26, 3, 23).asUIResource();
} else if (TextFieldWithPopupHandlerUI.isSearchField(c)) {
return JBUI.insets(3, 20, 3, 23).asUIResource();
} else if (c instanceof JTextField && c.getParent() instanceof ColorPanel) {
return JBUI.insets(3, 3, 2, 2).asUIResource();
}
else {
} else {
return JBUI.insets(3, 5).asUIResource();
}
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
if (TextFieldWithPopupHandlerUI.isSearchField(c)) return;
Graphics2D g2 = (Graphics2D)g.create();
try {
g2.translate(x, y);
Rectangle r = new Rectangle(x, y, width, height);
adjustVerticalInsets(r, (JComponent)c);
g2.translate(r.x, r.y);
Object eop = ((JComponent)c).getClientProperty("JComponent.error.outline");
if (Registry.is("ide.inplace.errors.outline") && Boolean.parseBoolean(String.valueOf(eop))) {
DarculaUIUtil.paintErrorBorder(g2, width, height, 0, true, c.hasFocus());
DarculaUIUtil.paintErrorBorder(g2, r.width, r.height, 0, true, c.hasFocus());
} else {
//boolean editable = !(c instanceof JTextComponent) || ((JTextComponent)c).isEditable();
JComponent jc = (JComponent)c;
......@@ -81,8 +79,8 @@ public class WinIntelliJTextBorder extends DarculaTextBorder {
int bw = JBUI.scale(1);
Path2D border = new Path2D.Double(Path2D.WIND_EVEN_ODD);
border.append(new Rectangle2D.Double(0, 0, width, height), false);
border.append(new Rectangle2D.Double(bw, bw, width - bw*2, height - bw*2), false);
border.append(new Rectangle2D.Double(0, 0, r.width, r.height), false);
border.append(new Rectangle2D.Double(bw, bw, r.width - bw*2, r.height - bw*2), false);
g2.fill(border);
}
......
......@@ -17,6 +17,9 @@ package com.intellij.ide.ui.laf.intellij;
import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI;
import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
......@@ -59,8 +62,7 @@ public class WinIntelliJTextFieldUI extends DarculaTextFieldUI {
@Override
protected void paintBackground(Graphics g) {
JTextComponent c = getComponent();
if (UIUtil.getParentOfType(JComboBox.class, c) != null ||
UIUtil.getParentOfType(JSpinner.class, c) != null) return;
if (UIUtil.getParentOfType(JComboBox.class, c) != null) return;
Graphics2D g2 = (Graphics2D)g.create();
try {
......@@ -70,11 +72,9 @@ public class WinIntelliJTextFieldUI extends DarculaTextFieldUI {
g2.fillRect(0, 0, c.getWidth(), c.getHeight());
}
paintTextFieldBackground(c, g2);
if (isSearchField(c)) {
Rectangle r = getDrawingRect();
paintSearchField(g2, c, r);
} else if (c.getBorder() instanceof WinIntelliJTextBorder){
paintTextFieldBackground(c, g2);
paintSearchField(g2, c, getDrawingRect());
}
} finally {
g2.dispose();
......@@ -82,19 +82,50 @@ public class WinIntelliJTextFieldUI extends DarculaTextFieldUI {
}
static void paintTextFieldBackground(JComponent c, Graphics2D g2) {
g2.setColor(c.isEnabled() ? c.getBackground() : UIManager.getColor("Button.background"));
g2.setColor(c.isEnabled() ? c.getBackground() : UIManager.getColor("TextField.inactiveBackground"));
if (!c.isEnabled()) {
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.35f));
}
int bw = JBUI.scale(1);
g2.fillRect(bw, bw, c.getWidth() - bw*2, c.getHeight() - bw*2);
Rectangle r = new Rectangle(c.getSize());
adjustVerticalInsets(r, c);
g2.fill(r);
}
static void adjustVerticalInsets(Rectangle r, JComponent c) {
if (UIUtil.getParentOfType(Wrapper.class, c) != null && isSearchFieldWithHistoryPopup(c)) {
Insets i = c.getInsets();
i.left = i.right = 0;
JBInsets.removeFrom(r, i);
}
}
@Override public Dimension getPreferredSize(JComponent c) {
Dimension size = super.getPreferredSize(c);
size.height = isSearchField(c) ? size.height : JBUI.scale(22);
size.height = JBUI.scale(22);
return size;
}
@Override protected void paintSearchField(Graphics2D g, JTextComponent c, Rectangle r) {
Icon searchIcon = isSearchFieldWithHistoryPopup(c) ?
UIManager.getIcon("TextField.darcula.searchWithHistory.icon") :
UIManager.getIcon("TextField.darcula.search.icon");
if (searchIcon == null) {
searchIcon = IconLoader.findIcon("/com/intellij/ide/ui/laf/icons/search.png", DarculaTextFieldUI.class, true);
}
int yOffset = isSearchFieldWithHistoryPopup(c) ? JBUI.scale(1) : 0;
searchIcon.paintIcon(c, g, JBUI.scale(4), (c.getHeight() - searchIcon.getIconHeight()) / 2 + yOffset);
if (hasText()) {
Icon clearIcon = UIManager.getIcon("TextField.darcula.clear.icon");
if (clearIcon == null) {
clearIcon = IconLoader.findIcon("/com/intellij/ide/ui/laf/icons/clear.png", DarculaTextFieldUI.class, true);
}
clearIcon.paintIcon(c, g, c.getWidth() - clearIcon.getIconWidth() - JBUI.scale(4),
(c.getHeight() - searchIcon.getIconHeight()) / 2);
}
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment