com.samebug.clients.idea.ui.component.WriteTip.java Source code

Java tutorial

Introduction

Here is the source code for com.samebug.clients.idea.ui.component.WriteTip.java

Source

/**
 * Copyright 2016 Samebug, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.samebug.clients.idea.ui.component;

import com.intellij.openapi.application.ApplicationManager;
import com.samebug.clients.common.ui.TextUtil;
import com.samebug.clients.idea.resources.SamebugBundle;
import com.samebug.clients.idea.ui.ColorUtil;
import org.apache.commons.lang.StringUtils;
import org.jdesktop.swingx.prompt.PromptSupport;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.TextAttribute;
import java.util.HashMap;

final public class WriteTip extends JPanel {
    public static final int maxCharacters = 140;
    public static final int minCharacters = 5;
    public static final int maxLines = 7;

    public final JLabel tipTitle;
    public final JLabel tipDescription;
    public final JTextArea tipBody;
    public final LengthCounter lengthCounter;
    public final JLabel sourceTitle;
    public final JLabel sourceDescription;
    public final JTextField sourceLink;
    public final ErrorPanel errorPanel;
    public final JLabel cancel;
    public final SBButton submit;

    final Actions actions;

    public WriteTip(final Actions actions) {
        tipTitle = new TipTitle();
        tipDescription = new DescriptionLabel(SamebugBundle.message("samebug.tip.write.tip.description"));
        tipBody = new TipBody();
        lengthCounter = new LengthCounter();
        sourceTitle = new SourceTitle();
        sourceDescription = new DescriptionLabel(SamebugBundle.message("samebug.tip.write.source.description"));
        sourceLink = new SourceLink();
        errorPanel = new ErrorPanel();
        cancel = new CancelButton();
        submit = new SubmitButton();
        this.actions = actions;

        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        add(new TransparentPanel() {
            {
                add(tipTitle);
            }
        });
        add(new TransparentPanel() {
            {
                setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
                add(tipDescription);
            }
        });
        add(new JScrollPane(tipBody));
        add(new TransparentPanel() {
            {
                setLayout(new FlowLayout(FlowLayout.RIGHT));
                add(lengthCounter);
            }
        });
        add(new TransparentPanel() {
            {
                add(sourceTitle);
            }
        });
        add(new TransparentPanel() {
            {
                setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
                add(sourceDescription);
            }
        });
        add(new TransparentPanel() {
            {
                add(sourceLink);
            }
        });
        add(new TransparentPanel() {
            {
                setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
                add(errorPanel);
            }
        });
        add(new TransparentPanel() {
            {
                setLayout(new FlowLayout(FlowLayout.RIGHT, 20, 0));
                add(cancel);
                add(submit);
            }
        });

        PromptSupport.setPrompt(SamebugBundle.message("samebug.tip.write.tip.placeholder"), tipBody);
        PromptSupport.setPrompt(SamebugBundle.message("samebug.tip.write.source.placeholder"), sourceLink);
        updateSubmitButton(true);

        ((AbstractDocument) tipBody.getDocument()).setDocumentFilter(new TipConstraints());
        tipBody.getDocument().addDocumentListener(new TipEditorListener());

        submit.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (submit.isEnabled()) {
                    final String tip = tipBody.getText();
                    final String rawSourceUrl = sourceLink.getText();
                    beginPostTip();
                    actions.onClickSubmitTip(tip, rawSourceUrl);
                }
            }
        });
    }

    @Override
    public Color getBackground() {
        return ColorUtil.writeTipPanel();
    }

    final class TipTitle extends JLabel {
        {
            setText(SamebugBundle.message("samebug.tip.write.tip.title"));
            final HashMap<TextAttribute, Object> attributes = new HashMap<TextAttribute, Object>();
            attributes.put(TextAttribute.SIZE, 20);
            setFont(getFont().deriveFont(attributes));
        }
    }

    final class SourceTitle extends JLabel {
        {
            setText(SamebugBundle.message("samebug.tip.write.source.title"));
            final HashMap<TextAttribute, Object> attributes = new HashMap<TextAttribute, Object>();
            attributes.put(TextAttribute.SIZE, 16);
            setFont(getFont().deriveFont(attributes));
            setMaximumSize(new Dimension(Integer.MAX_VALUE, getPreferredSize().height));
        }
    }

    final class DescriptionLabel extends JLabel {
        public DescriptionLabel(final String label) {
            super(label);
        }
    }

    final class TipBody extends JTextArea {
        {
            setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            setRows(4);
            setLineWrap(true);
            setWrapStyleWord(true);
            setMaximumSize(new Dimension(Integer.MAX_VALUE, getPreferredSize().height));
        }

        @Override
        public Color getBackground() {
            return ColorUtil.highlightPanel();
        }
    }

    final class SourceLink extends JTextField {
        {
            setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
        }

        @Override
        public Color getBackground() {
            return ColorUtil.highlightPanel();
        }
    }

    final class LengthCounter extends JLabel {
        int length;

        {
            length = 0;
            setText(String.format("%d/%d", length, maxCharacters));
        }

        @Override
        public Color getForeground() {
            if (minCharacters <= length && length <= maxCharacters) {
                return ColorUtil.unemphasizedText();
            } else {
                return ColorUtil.alertPanel();
            }
        }

        public void updateLength(final int length) {
            assert (length >= 0);
            this.length = length;
            setText(String.format("%d/%d", length, maxCharacters));
        }
    }

    final class ErrorPanel extends JPanel {
        {
            setLayout(new BorderLayout());
            setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
            setVisible(false);
        }

        @Override
        public Color getBackground() {
            return ColorUtil.alertPanel();
        }
    }

    final class CancelButton extends JLabel {
        {
            final HashMap<TextAttribute, Object> attributes = new HashMap<TextAttribute, Object>();
            attributes.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
            setFont(getFont().deriveFont(attributes));
            setText(SamebugBundle.message("samebug.tip.write.cancel"));
            setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        }

        @Override
        public Color getBackground() {
            return ColorUtil.writeTipPanel();
        }
    }

    final class SubmitButton extends SBButton {
        public SubmitButton() {
            super(SamebugBundle.message("samebug.tip.write.submit"));
        }

        @Override
        public Color getBackground() {
            return ColorUtil.ctaButton();
        }

        @Override
        public Color getForeground() {
            return ColorUtil.highlightPanel();
        }
    }

    final class TipConstraints extends DocumentFilter {
        @Override
        public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
                throws BadLocationException {
            super.replace(fb, offs, length, str, a);
            final int textSize = fb.getDocument().getLength();
            String text = fb.getDocument().getText(0, textSize);
            int lineBreaks = StringUtils.countMatches(text, TextUtil.lineSeparator);
            if (lineBreaks >= maxLines) {
                int lastLineBreakIndex = StringUtils.ordinalIndexOf(text, TextUtil.lineSeparator, maxLines);
                remove(fb, lastLineBreakIndex, text.length() - lastLineBreakIndex);
            }

        }
    }

    final class TipEditorListener implements DocumentListener {
        @Override
        public void insertUpdate(DocumentEvent e) {
            lengthCounter.updateLength(e.getDocument().getLength());
            lengthCounter.repaint();
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            lengthCounter.updateLength(e.getDocument().getLength());
            lengthCounter.repaint();
        }

        @Override
        public void changedUpdate(DocumentEvent e) {
            lengthCounter.updateLength(e.getDocument().getLength());
            lengthCounter.repaint();
        }
    }

    void updateSubmitButton(boolean enabled) {
        submit.setHighlighted(enabled);
        submit.setEnabled(enabled);
    }

    public void beginPostTip() {
        ApplicationManager.getApplication().assertIsDispatchThread();
        updateSubmitButton(false);

    }

    public void finishPostTipWithError(final String message) {
        ApplicationManager.getApplication().assertIsDispatchThread();
        errorPanel.removeAll();
        errorPanel.add(new ErrorLabel(message));
        errorPanel.setVisible(true);
        updateSubmitButton(true);
        revalidate();
        repaint();
    }

    public void finishPostTipWithSuccess() {
        ApplicationManager.getApplication().assertIsDispatchThread();
        updateSubmitButton(true);
    }

    public interface Actions {
        void onClickSubmitTip(String tip, String rawSourceUrl);
    }
}