1
2
3
4
5
6
7
8
9
10
11 package com.jsql.view.swing.util;
12
13 import com.formdev.flatlaf.FlatLaf;
14 import com.formdev.flatlaf.intellijthemes.FlatLightFlatIJTheme;
15 import com.jsql.util.I18nUtil;
16 import com.jsql.util.LogLevelUtil;
17 import com.jsql.view.swing.console.JTextPaneAppender;
18 import com.jsql.view.swing.sql.SqlEngine;
19 import com.jsql.view.swing.text.action.DeleteNextCharAction;
20 import com.jsql.view.swing.text.action.DeletePrevCharAction;
21 import org.apache.commons.lang3.StringUtils;
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.Logger;
24 import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
25 import org.fife.ui.rsyntaxtextarea.Theme;
26
27 import javax.swing.*;
28 import javax.swing.border.Border;
29 import javax.swing.text.DefaultCaret;
30 import javax.swing.text.DefaultEditorKit;
31 import javax.swing.text.JTextComponent;
32 import javax.swing.text.StyleConstants;
33 import java.awt.*;
34 import java.io.BufferedInputStream;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.lang.reflect.InvocationTargetException;
38 import java.util.ArrayList;
39 import java.util.List;
40 import java.util.Objects;
41
42
43
44
45 public class UiUtil {
46
47 private static final Logger LOGGER = LogManager.getRootLogger();
48
49 public static final Border BORDER_5PX = BorderFactory.createEmptyBorder(5, 5, 5, 5);
50
51 public static final ImageIcon ICON_FLAG_AR = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/ar.png")));
52 public static final ImageIcon ICON_FLAG_ZH = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/zh.png")));
53 public static final ImageIcon ICON_FLAG_RU = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/ru.png")));
54 public static final ImageIcon ICON_FLAG_TR = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/tr.png")));
55 public static final ImageIcon ICON_FLAG_EN = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/en.png")));
56 public static final ImageIcon ICON_FLAG_FR = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/fr.png")));
57 public static final ImageIcon ICON_FLAG_HI = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/hi.png")));
58 public static final ImageIcon ICON_FLAG_CS = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/cs.png")));
59 public static final ImageIcon ICON_FLAG_DE = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/de.png")));
60 public static final ImageIcon ICON_FLAG_NL = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/nl.png")));
61 public static final ImageIcon ICON_FLAG_IN = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/in.png")));
62 public static final ImageIcon ICON_FLAG_IT = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/it.png")));
63 public static final ImageIcon ICON_FLAG_ES = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/es.png")));
64 public static final ImageIcon ICON_FLAG_PT = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/pt.png")));
65 public static final ImageIcon ICON_FLAG_PL = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/pl.png")));
66 public static final ImageIcon ICON_FLAG_JA = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/ja.png")));
67 public static final ImageIcon ICON_FLAG_KO = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/ko.png")));
68 public static final ImageIcon ICON_FLAG_RO = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/ro.png")));
69 public static final ImageIcon ICON_FLAG_LK = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/lk.png")));
70 public static final ImageIcon ICON_FLAG_SE = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/se.png")));
71 public static final ImageIcon ICON_FLAG_FI = new ImageIcon(Objects.requireNonNull(UiUtil.class.getClassLoader().getResource("swing/images/flags/fi.png")));
72
73 public static final ModelSvgIcon DATABASE_BOLD = new ModelSvgIcon("database-bold", 0x1C274C)
74 .withTab("DATABASE_TAB", "DATABASE_TOOLTIP");
75 public static final ModelSvgIcon ADMIN = new ModelSvgIcon("admin", 0.02f)
76 .withTab("ADMINPAGE_TAB", "ADMINPAGE_TOOLTIP");
77 public static final ModelSvgIcon DOWNLOAD = new ModelSvgIcon("download", 0.55f)
78 .withTab("FILE_TAB", "FILE_TOOLTIP");
79 public static final ModelSvgIcon TERMINAL = new ModelSvgIcon("terminal", 0.50f)
80 .withTab("EXPLOIT_TAB", "EXPLOIT_TOOLTIP");
81 public static final ModelSvgIcon UPLOAD = new ModelSvgIcon("upload", 0.55f);
82 public static final ModelSvgIcon LOCK = new ModelSvgIcon("lock", 0.02f)
83 .withTab("BRUTEFORCE_TAB", "BRUTEFORCE_TOOLTIP");
84 public static final ModelSvgIcon TEXTFIELD = new ModelSvgIcon("textfield", 0.02f)
85 .withTab("CODER_TAB", "CODER_TOOLTIP");
86 public static final ModelSvgIcon BATCH = new ModelSvgIcon("batch", 0.02f)
87 .withTab("SCANLIST_TAB", "SCANLIST_TOOLTIP");
88
89 public static final ModelSvgIcon TABLE_LINEAR = new ModelSvgIcon("table-linear", 0x212121);
90 public static final ModelSvgIcon TABLE_BOLD = new ModelSvgIcon("table-bold", 0x212121);
91 public static final ModelSvgIcon NETWORK = new ModelSvgIcon("network", 0.02f);
92 public static final ModelSvgIcon DATABASE_LINEAR = new ModelSvgIcon("database-linear", 0x1C274C);
93 public static final ModelSvgIcon CUP = new ModelSvgIcon("cup", 0.02f);
94 public static final ModelSvgIcon CONSOLE = new ModelSvgIcon("console", 0.02f);
95 public static final ModelSvgIcon BINARY = new ModelSvgIcon("binary", 0.02f);
96 public static final ModelSvgIcon CHUNK = new ModelSvgIcon("chunk", 0.02f);
97 public static final ModelSvgIcon COG = new ModelSvgIcon("cog", 0.02f);
98
99 public static final ModelSvgIcon CROSS_RED = new ModelSvgIcon("cross", new Color(0x0F0F0F), null, LogLevelUtil.COLOR_RED, 0.025f);
100 private static final String NAME_ARROW = "arrow";
101 private static final String NAME_ARROW_LEFT = "arrow-left";
102 public static final ModelSvgIcon ARROW = new ModelSvgIcon(UiUtil.NAME_ARROW, new Color(0x005a96), "ComboBox.buttonArrowColor", 1f);
103 public static final ModelSvgIcon ARROW_HOVER = new ModelSvgIcon(UiUtil.NAME_ARROW, new Color(0x005a96), "ComboBox.buttonHoverArrowColor", 1f);
104 public static final ModelSvgIcon ARROW_PRESSED = new ModelSvgIcon(UiUtil.NAME_ARROW, new Color(0x005a96), "ComboBox.buttonPressedArrowColor", 1f);
105 public static final ModelSvgIcon ARROW_LEFT = new ModelSvgIcon(UiUtil.NAME_ARROW_LEFT, new Color(0x005a96), "ComboBox.buttonArrowColor", 1f);
106 public static final ModelSvgIcon ARROW_LEFT_HOVER = new ModelSvgIcon(UiUtil.NAME_ARROW_LEFT, new Color(0x005a96), "ComboBox.buttonHoverArrowColor", 1f);
107 public static final ModelSvgIcon ARROW_LEFT_PRESSED = new ModelSvgIcon(UiUtil.NAME_ARROW_LEFT, new Color(0x005a96), "ComboBox.buttonPressedArrowColor", 1f);
108 private static final String NAME_EXPAND = "expand";
109 public static final ModelSvgIcon EXPAND = new ModelSvgIcon(UiUtil.NAME_EXPAND, Color.BLACK, "ComboBox.buttonArrowColor", 0.02f);
110 public static final ModelSvgIcon EXPAND_HOVER = new ModelSvgIcon(UiUtil.NAME_EXPAND, Color.BLACK, "ComboBox.buttonHoverArrowColor", 0.02f);
111 public static final ModelSvgIcon EXPAND_PRESSED = new ModelSvgIcon(UiUtil.NAME_EXPAND, Color.BLACK, "ComboBox.buttonPressedArrowColor", 0.02f);
112
113 public static final ModelSvgIcon HOURGLASS = new ModelSvgIcon("hourglass", 0.02f);
114 public static final ModelSvgIcon ARROW_UP = new ModelSvgIcon("arrow-up", 0.02f);
115 public static final ModelSvgIcon ARROW_DOWN = new ModelSvgIcon("arrow-down", 0.02f);
116 public static final ModelSvgIcon SQUARE = new ModelSvgIcon("square", 0.01f);
117 public static final ModelSvgIcon TICK_GREEN = new ModelSvgIcon("tick", Color.BLACK, null, LogLevelUtil.COLOR_GREEN, 0.02f);
118 public static final ModelSvgIcon GLOBE = new ModelSvgIcon("globe", 0.025f);
119 public static final ModelSvgIcon APP_ICON = new ModelSvgIcon("app", 0.04f);
120 public static final ModelSvgIcon APP_BIG = new ModelSvgIcon("app", 0.5f);
121 public static final ModelSvgIcon APP_MIDDLE = new ModelSvgIcon("app", 0.25f);
122
123 public static final String PATH_PAUSE = "swing/images/icons/pause.png";
124
125 public static final String FONT_NAME_MONO_NON_ASIAN = "Ubuntu Mono";
126 public static final int FONT_SIZE_MONO_NON_ASIAN = 14;
127 public static final String FONT_NAME_MONO_ASIAN = "Monospace";
128 public static final int FONT_SIZE_MONO_ASIAN = 13;
129
130
131
132
133 public static final String FONT_NAME_MONOSPACED = "Monospaced";
134 public static final String TEXTAREA_FONT = "TextArea.font";
135 public static final String TEXTPANE_FONT = "TextPane.font";
136 public static final Font FONT_MONO_NON_ASIAN = new Font(
137 UiUtil.FONT_NAME_MONO_NON_ASIAN,
138 Font.PLAIN,
139 UIManager.getDefaults().getFont(UiUtil.TEXTAREA_FONT).getSize() + 2
140 );
141
142 public static final Font FONT_MONO_ASIAN = new Font(
143 UiUtil.FONT_NAME_MONO_ASIAN,
144 Font.PLAIN,
145 UIManager.getDefaults().getFont(UiUtil.TEXTPANE_FONT).getSize()
146 );
147
148 public static final Font FONT_MONO_ASIAN_BIG = new Font(
149 UiUtil.FONT_NAME_MONO_ASIAN,
150 Font.PLAIN,
151 UIManager.getDefaults().getFont(UiUtil.TEXTPANE_FONT).getSize() + 2
152 );
153
154 public static final Font FONT_NON_MONO = new Font(
155 "Segoe UI",
156 Font.PLAIN,
157 UIManager.getDefaults().getFont(UiUtil.TEXTPANE_FONT).getSize()
158 );
159
160 public static final Font FONT_NON_MONO_BIG = new Font(
161 UIManager.getDefaults().getFont("TextField.font").getName(),
162 Font.PLAIN,
163 UIManager.getDefaults().getFont("TextField.font").getSize() + 2
164 );
165
166 private UiUtil() {
167
168 }
169
170
171
172
173 public static void prepareGUI() {
174 UiUtil.loadFonts();
175
176 ToolTipManager.sharedInstance().setDismissDelay(3 * ToolTipManager.sharedInstance().getDismissDelay());
177 UIManager.put(UiUtil.TEXTAREA_FONT, UiUtil.FONT_MONO_NON_ASIAN);
178 UIManager.put(UiUtil.TEXTPANE_FONT, UIManager.getFont(UiUtil.TEXTAREA_FONT));
179 }
180
181 private static void loadFonts() {
182 var graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
183 try (InputStream fontStream = new BufferedInputStream(
184 Objects.requireNonNull(UiUtil.class.getClassLoader().getResourceAsStream("swing/font/UbuntuMono-R-ctrlchar.ttf"))
185 )) {
186 var ubuntuFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
187 graphicsEnvironment.registerFont(ubuntuFont);
188 } catch (FontFormatException | IOException e) {
189 LOGGER.log(LogLevelUtil.CONSOLE_ERROR, "Loading Font Ubuntu Mono with control characters failed", e);
190 }
191 }
192
193
194
195
196
197 public static List<Image> getIcons() {
198 List<Image> images = new ArrayList<>();
199
200 try {
201 images.add(UiUtil.APP_ICON.getIcon().getImage());
202 images.add(UiUtil.APP_MIDDLE.getIcon().getImage());
203 images.add(UiUtil.APP_BIG.getIcon().getImage());
204 } catch (NoClassDefFoundError e) {
205 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
206 }
207 return images;
208 }
209
210 public static void drawPlaceholder(JTextComponent textComponent, Graphics g, String placeholderText) {
211 UiUtil.drawPlaceholder(textComponent, g, placeholderText, 0, g.getFontMetrics().getAscent() + 2);
212 }
213
214 public static void drawPlaceholder(JTextComponent textComponent, Graphics g, String placeholderText, int x, int y) {
215 int w = textComponent.getWidth();
216
217 ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
218
219 var insets = textComponent.getInsets();
220 var fontMetrics = g.getFontMetrics();
221
222 int c0 = UIManager.getColor("TextArea.background").getRGB();
223 int c1 = UIManager.getColor("TextArea.foreground").getRGB();
224 var m = 0xfefefefe;
225 int c2 = ((c0 & m) >>> 1) + ((c1 & m) >>> 1);
226
227 g.setColor(new Color(c2, true));
228
229 var fontNonUbuntu = UiUtil.FONT_NON_MONO_BIG.equals(textComponent.getFont())
230 ? UiUtil.FONT_MONO_ASIAN_BIG.deriveFont(Font.ITALIC)
231 : UiUtil.FONT_MONO_ASIAN.deriveFont(Font.ITALIC);
232 g.setFont(
233 I18nViewUtil.isNonUbuntu(I18nUtil.getCurrentLocale())
234 || !ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale()).isLeftToRight()
235 ? fontNonUbuntu
236 : textComponent.getFont().deriveFont(Font.ITALIC)
237 );
238
239 g.drawString(placeholderText, (
240 textComponent.getComponentOrientation().isLeftToRight()
241 ? x + insets.left + 2
242 : w - (fontMetrics.stringWidth(placeholderText) + insets.left + 2 + 2*x)
243 ), y);
244 }
245
246 public static void init(JTextComponent component) {
247 component.setCaret(new DefaultCaret() {
248 @Override
249 public void setSelectionVisible(boolean visible) {
250 super.setSelectionVisible(true);
251 }
252 });
253 component.getActionMap().put(DefaultEditorKit.deletePrevCharAction, new DeletePrevCharAction());
254 component.getActionMap().put(DefaultEditorKit.deleteNextCharAction, new DeleteNextCharAction());
255 }
256
257 public static void applySyntaxTheme(RSyntaxTextArea textArea) {
258 try {
259 boolean isDark = UIManager.getLookAndFeel().getName().matches(".*(Dark|High Contrast).*");
260 var xmlTheme = String.format("/org/fife/ui/rsyntaxtextarea/themes/%s.xml", isDark ? "dark" : "default");
261 Theme theme = Theme.load(SqlEngine.class.getResourceAsStream(xmlTheme));
262 theme.apply(textArea);
263 } catch (IOException e) {
264 throw new IllegalArgumentException(e);
265 }
266 }
267
268 public static void applyTheme(String nameTheme) {
269 try {
270 UIManager.setLookAndFeel(StringUtils.isBlank(nameTheme) ? FlatLightFlatIJTheme.class.getName() : nameTheme);
271 } catch (ClassNotFoundException e) {
272 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, "Theme not found, falling back to default theme");
273 try {
274 UIManager.setLookAndFeel(FlatLightFlatIJTheme.class.getName());
275 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e2) {
276 throw new IllegalArgumentException(e);
277 }
278 } catch (InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
279 throw new IllegalArgumentException(e);
280 }
281 FlatLaf.updateUI();
282
283
284 StyleConstants.setForeground(JTextPaneAppender.ATTRIBUTE_WARN, LogLevelUtil.COLOR_RED);
285 StyleConstants.setForeground(JTextPaneAppender.ATTRIBUTE_INFORM, LogLevelUtil.COLOR_BLU);
286 StyleConstants.setForeground(JTextPaneAppender.ATTRIBUTE_SUCCESS, LogLevelUtil.COLOR_GREEN);
287 }
288
289 public static GridLayout getColumnLayout(int size) {
290 return new GridLayout((size + 1) / 2, 2);
291 }
292 }