Skip to content

Commit c41455a

Browse files
committed
[FEATURE] CSV/TSV editor settings editor and features implemented
1 parent 8c3914c commit c41455a

File tree

7 files changed

+432
-10
lines changed

7 files changed

+432
-10
lines changed

src/main/java/net/seesharpsoft/intellij/plugins/csv/annotation/CsvAnnotator.java

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@
99
import com.intellij.openapi.util.Key;
1010
import com.intellij.openapi.util.TextRange;
1111
import com.intellij.psi.PsiElement;
12+
import com.intellij.psi.tree.IElementType;
1213
import com.intellij.xml.util.XmlStringUtil;
1314
import net.seesharpsoft.intellij.plugins.csv.CsvColumnInfo;
1415
import net.seesharpsoft.intellij.plugins.csv.CsvHelper;
16+
import net.seesharpsoft.intellij.plugins.csv.editor.CsvEditorSettingsExternalizable;
1517
import net.seesharpsoft.intellij.plugins.csv.psi.CsvFile;
1618
import net.seesharpsoft.intellij.plugins.csv.psi.CsvTypes;
19+
import net.seesharpsoft.intellij.plugins.csv.settings.CsvCodeStyleSettings;
1720
import org.jetbrains.annotations.NotNull;
1821

1922
import java.awt.*;
@@ -27,12 +30,16 @@ public class CsvAnnotator implements Annotator {
2730

2831
protected static final Integer MAX_COLUMN_HIGHLIGHT_COLORS = 10;
2932
protected static final Key<Integer> MAX_NO_OF_DEFINED_COLUMN_HIGHLIGHT_COLORS = Key.create("CSV_LAST_DEFINED_COLOR_INDEX_KEY");
30-
33+
protected static final Key<TextAttributes> TAB_SEPARATOR_HIGHLIGHT_COLOR = Key.create("CSV_TAB_SEPARATOR_HIGHLIGHT_COLOR");
34+
protected static final Key<Boolean> TAB_SEPARATOR_HIGHLIGHT_COLOR_DETERMINED = Key.create("CSV_TAB_SEPARATOR_HIGHLIGHT_COLOR_DETERMINED");
35+
3136
public static final ColorDescriptor[] COLOR_DESCRIPTORS;
37+
3238
static {
3339
List<ColorDescriptor> colorDescriptorList = new ArrayList();
3440
for (int i = 0; i < MAX_COLUMN_HIGHLIGHT_COLORS; ++i) {
35-
colorDescriptorList.add(new ColorDescriptor(String.format("Column Highlighting Color %d", i + 1), ColorKey.createColorKey(String.format("CSV_COLUMN_COLOR_%d", i + 1), (Color) null), ColorDescriptor.Kind.BACKGROUND));
41+
colorDescriptorList.add(new ColorDescriptor(String.format("Column Highlighting Color %d", i + 1),
42+
ColorKey.createColorKey(String.format("CSV_COLUMN_COLOR_%d", i + 1), (Color) null), ColorDescriptor.Kind.BACKGROUND));
3643
}
3744
COLOR_DESCRIPTORS = colorDescriptorList.toArray(new ColorDescriptor[MAX_COLUMN_HIGHLIGHT_COLORS]);
3845
}
@@ -42,11 +49,16 @@ public class CsvAnnotator implements Annotator {
4249

4350
@Override
4451
public void annotate(@NotNull final PsiElement element, @NotNull final AnnotationHolder holder) {
45-
if (CsvHelper.getElementType(element) != CsvTypes.FIELD || !(element.getContainingFile() instanceof CsvFile)) {
52+
IElementType elementType = CsvHelper.getElementType(element);
53+
if ((elementType != CsvTypes.FIELD && elementType != CsvTypes.COMMA) || !(element.getContainingFile() instanceof CsvFile)) {
4654
return;
4755
}
4856

4957
CsvFile csvFile = (CsvFile) element.getContainingFile();
58+
if (handleSeparatorElement(element, holder, elementType, csvFile)) {
59+
return;
60+
}
61+
5062
CsvColumnInfo<PsiElement> columnInfo = csvFile.getMyColumnInfoMap().getColumnInfo(element);
5163

5264
if (columnInfo != null) {
@@ -70,14 +82,39 @@ public void annotate(@NotNull final PsiElement element, @NotNull final Annotatio
7082
}
7183
}
7284

85+
protected boolean handleSeparatorElement(@NotNull PsiElement element, @NotNull AnnotationHolder holder, IElementType elementType, CsvFile csvFile) {
86+
if (elementType == CsvTypes.COMMA) {
87+
TextAttributes textAttributes = holder.getCurrentAnnotationSession().getUserData(TAB_SEPARATOR_HIGHLIGHT_COLOR);
88+
if (!Boolean.TRUE.equals(holder.getCurrentAnnotationSession().getUserData(TAB_SEPARATOR_HIGHLIGHT_COLOR_DETERMINED))) {
89+
String separator = CsvCodeStyleSettings.getCurrentSeparator(csvFile.getProject(), csvFile.getLanguage());
90+
if (CsvEditorSettingsExternalizable.getInstance().isHighlightTabSeparator() && separator.equals(CsvCodeStyleSettings.TAB_SEPARATOR)) {
91+
textAttributes = new TextAttributes(null,
92+
CsvEditorSettingsExternalizable.getInstance().getTabHighlightColor(),
93+
null, null, 0);
94+
holder.getCurrentAnnotationSession().putUserData(TAB_SEPARATOR_HIGHLIGHT_COLOR, textAttributes);
95+
holder.getCurrentAnnotationSession().putUserData(TAB_SEPARATOR_HIGHLIGHT_COLOR_DETERMINED, Boolean.TRUE);
96+
}
97+
}
98+
if (textAttributes != null) {
99+
Annotation annotation = holder.createAnnotation(CSV_COLUMN_INFO_SEVERITY, element.getTextRange(), "<TAB>");
100+
annotation.setEnforcedTextAttributes(textAttributes);
101+
annotation.setNeedsUpdateOnTyping(false);
102+
}
103+
return true;
104+
}
105+
return false;
106+
}
107+
73108
protected TextAttributes getTextAttributes(AnnotationSession annotationSession, CsvColumnInfo<PsiElement> columnInfo) {
74109
EditorColorsScheme editorColorsScheme = EditorColorsManager.getInstance().getGlobalScheme();
75110
Integer maxNoOfDefinedColumnHighlightColors = annotationSession.getUserData(MAX_NO_OF_DEFINED_COLUMN_HIGHLIGHT_COLORS);
76111
if (maxNoOfDefinedColumnHighlightColors == null) {
77112
maxNoOfDefinedColumnHighlightColors = 0;
78-
for (int colorDescriptorIndex = 0; colorDescriptorIndex < COLOR_DESCRIPTORS.length; ++colorDescriptorIndex) {
79-
if (editorColorsScheme.getColor(COLOR_DESCRIPTORS[colorDescriptorIndex].getKey()) != null) {
80-
maxNoOfDefinedColumnHighlightColors = colorDescriptorIndex + 1;
113+
if (CsvEditorSettingsExternalizable.getInstance().isColumnHighlightingEnabled()) {
114+
for (int colorDescriptorIndex = 0; colorDescriptorIndex < COLOR_DESCRIPTORS.length; ++colorDescriptorIndex) {
115+
if (editorColorsScheme.getColor(COLOR_DESCRIPTORS[colorDescriptorIndex].getKey()) != null) {
116+
maxNoOfDefinedColumnHighlightColors = colorDescriptorIndex + 1;
117+
}
81118
}
82119
}
83120
annotationSession.putUserData(MAX_NO_OF_DEFINED_COLUMN_HIGHLIGHT_COLORS, maxNoOfDefinedColumnHighlightColors);
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package net.seesharpsoft.intellij.plugins.csv.editor;
2+
3+
import com.intellij.openapi.application.ApplicationManager;
4+
import com.intellij.openapi.components.PersistentStateComponent;
5+
import com.intellij.openapi.components.ServiceManager;
6+
import com.intellij.openapi.components.State;
7+
import com.intellij.openapi.components.Storage;
8+
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
9+
import org.jetbrains.annotations.NotNull;
10+
11+
import java.awt.*;
12+
import java.beans.PropertyChangeListener;
13+
import java.beans.PropertyChangeSupport;
14+
15+
@State(
16+
name = "CsvEditorSettings",
17+
storages = {@Storage("csv-plugin.xml")}
18+
)
19+
@SuppressWarnings("all")
20+
public class CsvEditorSettingsExternalizable implements PersistentStateComponent<CsvEditorSettingsExternalizable.OptionSet> {
21+
22+
public static final class OptionSet {
23+
public boolean CARET_ROW_SHOWN;
24+
public boolean USE_SOFT_WRAP;
25+
public boolean COLUMN_HIGHTLIGHTING;
26+
public boolean HIGHTLIGHT_TAB_SEPARATOR;
27+
public String TAB_HIGHLIGHT_COLOR;
28+
29+
public OptionSet() {
30+
EditorSettingsExternalizable editorSettingsExternalizable = EditorSettingsExternalizable.getInstance();
31+
CARET_ROW_SHOWN = editorSettingsExternalizable.isCaretRowShown();
32+
USE_SOFT_WRAP = editorSettingsExternalizable.isUseSoftWraps();
33+
COLUMN_HIGHTLIGHTING = false;
34+
HIGHTLIGHT_TAB_SEPARATOR = true;
35+
TAB_HIGHLIGHT_COLOR = "-7984";
36+
}
37+
}
38+
39+
private OptionSet myOptions = new OptionSet();
40+
private final PropertyChangeSupport myPropertyChangeSupport = new PropertyChangeSupport(this);
41+
42+
public CsvEditorSettingsExternalizable() {
43+
}
44+
45+
public static CsvEditorSettingsExternalizable getInstance() {
46+
return ApplicationManager.getApplication().isDisposed() ? new CsvEditorSettingsExternalizable() : ServiceManager.getService(CsvEditorSettingsExternalizable.class);
47+
}
48+
49+
public void addPropertyChangeListener(PropertyChangeListener listener) {
50+
this.myPropertyChangeSupport.addPropertyChangeListener(listener);
51+
}
52+
53+
public void removePropertyChangeListener(PropertyChangeListener listener) {
54+
this.myPropertyChangeSupport.removePropertyChangeListener(listener);
55+
}
56+
57+
@Override
58+
public OptionSet getState() {
59+
return this.myOptions;
60+
}
61+
62+
@Override
63+
public void loadState(@NotNull OptionSet state) {
64+
this.myOptions = state;
65+
}
66+
67+
/*********** Settings section **********/
68+
69+
public boolean isCaretRowShown() {
70+
return getState().CARET_ROW_SHOWN;
71+
}
72+
public void setCaretRowShown(boolean caretRowShown) {
73+
getState().CARET_ROW_SHOWN = caretRowShown;
74+
}
75+
76+
public boolean isUseSoftWraps() {
77+
return getState().USE_SOFT_WRAP;
78+
}
79+
public void setUseSoftWraps(boolean useSoftWraps) {
80+
getState().USE_SOFT_WRAP = useSoftWraps;
81+
}
82+
83+
public boolean isColumnHighlightingEnabled() {
84+
return getState().COLUMN_HIGHTLIGHTING;
85+
}
86+
public void setColumnHighlightingEnabled(boolean columnHighlightingEnabled) {
87+
getState().COLUMN_HIGHTLIGHTING = columnHighlightingEnabled;
88+
}
89+
90+
public boolean isHighlightTabSeparator() {
91+
return getState().HIGHTLIGHT_TAB_SEPARATOR;
92+
}
93+
public void setHighlightTabSeparator(boolean highlightTabSeparator) {
94+
getState().HIGHTLIGHT_TAB_SEPARATOR = highlightTabSeparator;
95+
}
96+
97+
public Color getTabHighlightColor() {
98+
String color = getState().TAB_HIGHLIGHT_COLOR;
99+
try {
100+
return color == null || color.isEmpty() ? null : Color.decode(getState().TAB_HIGHLIGHT_COLOR);
101+
} catch (NumberFormatException exc) {
102+
return null;
103+
}
104+
}
105+
public void setTabHighlightColor(Color color) {
106+
getState().TAB_HIGHLIGHT_COLOR = color == null ? "" : "" + color.getRGB();
107+
}
108+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="net.seesharpsoft.intellij.plugins.csv.editor.CsvEditorSettingsPanel">
3+
<grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
4+
<margin top="0" left="0" bottom="0" right="0"/>
5+
<constraints>
6+
<xy x="20" y="20" width="1180" height="578"/>
7+
</constraints>
8+
<properties>
9+
<enabled value="true"/>
10+
</properties>
11+
<border type="none">
12+
<font/>
13+
<title-color color="-16777216"/>
14+
</border>
15+
<children>
16+
<grid id="d2422" binding="panelHighlighting" layout-manager="GridLayoutManager" row-count="5" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
17+
<margin top="10" left="10" bottom="10" right="10"/>
18+
<constraints>
19+
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
20+
</constraints>
21+
<properties/>
22+
<border type="etched" title="Highlighting"/>
23+
<children>
24+
<component id="a9e55" class="javax.swing.JCheckBox" binding="cbCaretRowShown">
25+
<constraints>
26+
<grid row="0" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
27+
</constraints>
28+
<properties>
29+
<text value="Highlight caret row"/>
30+
</properties>
31+
</component>
32+
<component id="314e1" class="javax.swing.JCheckBox" binding="cbColumnHighlighting">
33+
<constraints>
34+
<grid row="1" column="0" row-span="1" col-span="4" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
35+
</constraints>
36+
<properties>
37+
<text value="Enable column highlighting (Editor &gt; Color Scheme &gt; CSV &gt; Column Hightlighting Colors)"/>
38+
</properties>
39+
</component>
40+
<component id="57ffb" class="com.intellij.ui.CheckBoxWithColorChooser" binding="cbTabHighlightColor" custom-create="true">
41+
<constraints>
42+
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
43+
</constraints>
44+
<properties/>
45+
</component>
46+
<hspacer id="a767a">
47+
<constraints>
48+
<grid row="3" column="0" row-span="1" col-span="4" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
49+
</constraints>
50+
</hspacer>
51+
</children>
52+
</grid>
53+
<grid id="6ba47" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
54+
<margin top="10" left="10" bottom="10" right="10"/>
55+
<constraints>
56+
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
57+
</constraints>
58+
<properties/>
59+
<border type="etched" title="Others"/>
60+
<children>
61+
<component id="6fb36" class="javax.swing.JCheckBox" binding="cbUseSoftWraps">
62+
<constraints>
63+
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
64+
</constraints>
65+
<properties>
66+
<text value="Use soft wraps"/>
67+
</properties>
68+
</component>
69+
<hspacer id="d39ae">
70+
<constraints>
71+
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
72+
</constraints>
73+
</hspacer>
74+
</children>
75+
</grid>
76+
<vspacer id="ff292">
77+
<constraints>
78+
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
79+
</constraints>
80+
</vspacer>
81+
</children>
82+
</grid>
83+
</form>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package net.seesharpsoft.intellij.plugins.csv.editor;
2+
3+
import com.intellij.openapi.options.ConfigurationException;
4+
import com.intellij.openapi.options.SearchableConfigurable;
5+
import com.intellij.ui.CheckBoxWithColorChooser;
6+
import org.jetbrains.annotations.Nls;
7+
import org.jetbrains.annotations.NotNull;
8+
import org.jetbrains.annotations.Nullable;
9+
10+
import javax.swing.*;
11+
import java.awt.*;
12+
import java.util.Objects;
13+
14+
public class CsvEditorSettingsPanel implements SearchableConfigurable {
15+
private JCheckBox cbCaretRowShown;
16+
private JPanel myMainPanel;
17+
private JCheckBox cbUseSoftWraps;
18+
private JCheckBox cbColumnHighlighting;
19+
private JPanel panelHighlighting;
20+
private CheckBoxWithColorChooser cbTabHighlightColor;
21+
22+
@NotNull
23+
@Override
24+
public String getId() {
25+
return "Csv.Editor.Settings";
26+
}
27+
28+
@Nls(capitalization = Nls.Capitalization.Title)
29+
@Override
30+
public String getDisplayName() {
31+
return "CSV/TSV Editor Settings";
32+
}
33+
34+
@Nullable
35+
@Override
36+
public JComponent createComponent() {
37+
return myMainPanel;
38+
}
39+
40+
@Override
41+
public boolean isModified() {
42+
CsvEditorSettingsExternalizable csvEditorSettingsExternalizable = CsvEditorSettingsExternalizable.getInstance();
43+
return isModified(cbCaretRowShown, csvEditorSettingsExternalizable.isCaretRowShown()) ||
44+
isModified(cbUseSoftWraps, csvEditorSettingsExternalizable.isUseSoftWraps()) ||
45+
isModified(cbColumnHighlighting, csvEditorSettingsExternalizable.isColumnHighlightingEnabled()) ||
46+
cbTabHighlightColor.isSelected() != csvEditorSettingsExternalizable.isHighlightTabSeparator() ||
47+
!Objects.equals(cbTabHighlightColor.getColor(), csvEditorSettingsExternalizable.getTabHighlightColor());
48+
}
49+
50+
@Override
51+
public void reset() {
52+
CsvEditorSettingsExternalizable csvEditorSettingsExternalizable = CsvEditorSettingsExternalizable.getInstance();
53+
cbCaretRowShown.setSelected(csvEditorSettingsExternalizable.isCaretRowShown());
54+
cbUseSoftWraps.setSelected(csvEditorSettingsExternalizable.isUseSoftWraps());
55+
cbColumnHighlighting.setSelected(csvEditorSettingsExternalizable.isColumnHighlightingEnabled());
56+
cbTabHighlightColor.setSelected(csvEditorSettingsExternalizable.isHighlightTabSeparator());
57+
cbTabHighlightColor.setColor(csvEditorSettingsExternalizable.getTabHighlightColor());
58+
}
59+
60+
@Override
61+
public void apply() throws ConfigurationException {
62+
CsvEditorSettingsExternalizable csvEditorSettingsExternalizable = CsvEditorSettingsExternalizable.getInstance();
63+
csvEditorSettingsExternalizable.setCaretRowShown(cbCaretRowShown.isSelected());
64+
csvEditorSettingsExternalizable.setUseSoftWraps(cbUseSoftWraps.isSelected());
65+
csvEditorSettingsExternalizable.setColumnHighlightingEnabled(cbColumnHighlighting.isSelected());
66+
csvEditorSettingsExternalizable.setHighlightTabSeparator(cbTabHighlightColor.isSelected());
67+
csvEditorSettingsExternalizable.setTabHighlightColor(cbTabHighlightColor.getColor());
68+
}
69+
70+
private void createUIComponents() {
71+
cbTabHighlightColor = new CheckBoxWithColorChooser("Highlight tab separator ");
72+
cbTabHighlightColor.setColor(Color.CYAN);
73+
}
74+
}

0 commit comments

Comments
 (0)