isolate UI for better testability
[idea/community.git] / python / educational-core / student / src / com / jetbrains / edu / learning / ui / CCCreateAnswerPlaceholderPanel.java
1 package com.jetbrains.edu.learning.ui;
2
3 import com.intellij.icons.AllIcons;
4 import com.intellij.openapi.actionSystem.ActionManager;
5 import com.intellij.openapi.actionSystem.AnAction;
6 import com.intellij.openapi.actionSystem.AnActionEvent;
7 import com.intellij.openapi.actionSystem.DefaultActionGroup;
8 import com.intellij.ui.ColorUtil;
9 import com.intellij.ui.JBColor;
10 import com.intellij.ui.components.JBLabel;
11 import com.intellij.uiDesigner.core.GridLayoutManager;
12 import com.intellij.util.ui.UIUtil;
13 import org.jetbrains.annotations.NotNull;
14
15 import javax.swing.*;
16 import java.awt.*;
17 import java.awt.event.FocusAdapter;
18 import java.awt.event.FocusEvent;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 public class CCCreateAnswerPlaceholderPanel {
23   private static final String NEXT_HINT = "Next Hint";
24   private static final String PREVIOUS_HINT = "Previous Hint";
25   private static final String ADD_HINT = "Add Hint";
26   private static final String REMOVE_HINT = "Remove Hint";
27   private static final String HINT_PLACEHOLDER = "Type here to add hint";
28
29   private JPanel myPanel;
30   private JTextArea myHintTextArea;
31   private JPanel myHintsPanel;
32   private JBLabel myHintLabel;
33   private JPanel actionsPanel;
34   private JTextArea myPlaceholderTextArea;
35   private List<String> myHints = new ArrayList<>();
36   private int myShownHintNumber = 0;
37
38   public CCCreateAnswerPlaceholderPanel(String placeholderText, List<String> hints) {
39     if (hints.isEmpty()) {
40       myHints.add(HINT_PLACEHOLDER);
41     }
42     else {
43       myHints.addAll(hints);
44     }
45
46     myPlaceholderTextArea.setBorder(BorderFactory.createLineBorder(JBColor.border()));
47     myHintsPanel.setBorder(BorderFactory.createLineBorder(JBColor.border()));
48     ((GridLayoutManager)myHintsPanel.getLayout()).setHGap(1);
49
50     myHintTextArea.setFont(myPlaceholderTextArea.getFont());
51     myHintTextArea.addFocusListener(createFocusListenerToSetDefaultHintText());
52
53     actionsPanel.add(createHintToolbarComponent(), BorderLayout.WEST);
54     showHint(myHints.get(myShownHintNumber));
55     myPlaceholderTextArea.setText(placeholderText);
56   }
57
58   @NotNull
59   private FocusAdapter createFocusListenerToSetDefaultHintText() {
60     return new FocusAdapter() {
61       @Override
62       public void focusGained(FocusEvent e) {
63         if (myHintTextArea.getText().equals(HINT_PLACEHOLDER)) {
64           myHintTextArea.setForeground(UIUtil.getActiveTextColor());
65           myHintTextArea.setText("");
66         }
67       }
68
69       @Override
70       public void focusLost(FocusEvent e) {
71         if (myShownHintNumber == 0 && myHintTextArea.getText().isEmpty()) {
72           myHintTextArea.setForeground(UIUtil.getInactiveTextColor());
73           myHintTextArea.setText(HINT_PLACEHOLDER);
74         }
75       }
76     };
77   }
78
79   private JComponent createHintToolbarComponent() {
80     final DefaultActionGroup addRemoveGroup = new DefaultActionGroup();
81     addRemoveGroup.addAll(new AddHint(), new RemoveHint(), new ShowNext(), new ShowPrevious());
82     return ActionManager.getInstance().createActionToolbar("Hint", addRemoveGroup, false).getComponent();
83   }
84
85   private void updateHintNumberLabel() {
86     if (myHints.size() > 1) {
87       final String color = String.valueOf(ColorUtil.toHex(UIUtil.getHeaderInactiveColor()));
88       myHintLabel.setText(UIUtil.toHtml("Hint" + " <font color=\"" + color + "\">(" + (myShownHintNumber + 1) + "/" + myHints.size() + ")</font>:"));
89     }
90     else {
91       myHintLabel.setText("Hint: ");
92     }
93   }
94
95   public void showHint(String hintText) {
96     if (myHints.get(myShownHintNumber).equals(HINT_PLACEHOLDER)) {
97       myHintTextArea.setForeground(UIUtil.getInactiveTextColor());
98     }
99     else {
100       myHintTextArea.setForeground(UIUtil.getActiveTextColor());
101     }
102
103     myHintTextArea.setText(hintText);
104     updateHintNumberLabel();
105   }
106
107   public String getAnswerPlaceholderText() {
108     return myPlaceholderTextArea.getText();
109   }
110
111   public List<String> getHints() {
112     final String hintText = myHintTextArea.getText();
113     if (myShownHintNumber == 0 && hintText.equals(HINT_PLACEHOLDER)) {
114       myHints.set(myShownHintNumber, "");
115     }
116     else {
117       myHints.set(myShownHintNumber, hintText);
118     }
119
120     return myHints;
121   }
122
123   public JComponent getPreferredFocusedComponent() {
124     return myPlaceholderTextArea;
125   }
126
127   public JPanel getMailPanel() {
128     return myPanel;
129   }
130
131   private class ShowNext extends AnAction {
132
133     public ShowNext() {
134       super(NEXT_HINT, NEXT_HINT, AllIcons.Actions.Forward);
135     }
136
137     @Override
138     public void actionPerformed(AnActionEvent e) {
139       myHints.set(myShownHintNumber, myHintTextArea.getText());
140       showHint(myHints.get(++myShownHintNumber));
141     }
142
143     @Override
144     public void update(AnActionEvent e) {
145       e.getPresentation().setEnabled(myShownHintNumber + 1 < myHints.size());
146     }
147   }
148
149   private class ShowPrevious extends AnAction {
150
151     public ShowPrevious() {
152       super(PREVIOUS_HINT, PREVIOUS_HINT, AllIcons.Actions.Back);
153     }
154
155     @Override
156     public void actionPerformed(AnActionEvent e) {
157       myHints.set(myShownHintNumber, myHintTextArea.getText());
158       showHint(myHints.get(--myShownHintNumber));
159     }
160
161     @Override
162     public void update(AnActionEvent e) {
163       e.getPresentation().setEnabled(myShownHintNumber - 1 >= 0);
164     }
165   }
166
167   private class AddHint extends AnAction {
168
169     public AddHint() {
170       super(ADD_HINT, ADD_HINT, AllIcons.General.Add);
171     }
172
173     @Override
174     public void actionPerformed(AnActionEvent e) {
175       myHints.add("");
176       myShownHintNumber++;
177       showHint("");
178     }
179   }
180
181   private class RemoveHint extends AnAction {
182
183     public RemoveHint() {
184       super(REMOVE_HINT, REMOVE_HINT, AllIcons.General.Remove);
185     }
186
187     @Override
188     public void actionPerformed(AnActionEvent e) {
189       myHints.remove(myShownHintNumber);
190       myShownHintNumber += myShownHintNumber < myHints.size() ? 0 : -1;
191       showHint(myHints.get(myShownHintNumber));
192     }
193
194     @Override
195     public void update(AnActionEvent e) {
196       e.getPresentation().setEnabled(myHints.size() > 1);
197     }
198   }
199 }