1
2
3
4
5
6
7
8
9
10
11 package com.jsql.view.swing.tree.model;
12
13 import com.jsql.model.bean.database.AbstractElementDatabase;
14 import com.jsql.model.suspendable.AbstractSuspendable;
15 import com.jsql.util.I18nUtil;
16 import com.jsql.util.LogLevelUtil;
17 import com.jsql.util.StringUtil;
18 import com.jsql.view.swing.tree.action.ActionLoadStop;
19 import com.jsql.view.swing.tree.action.ActionPauseUnpause;
20 import com.jsql.view.swing.tree.ImageOverlap;
21 import com.jsql.view.swing.tree.PanelNode;
22 import com.jsql.view.swing.tree.custom.JPopupMenuCustomExtract;
23 import com.jsql.view.swing.util.I18nViewUtil;
24 import com.jsql.view.swing.util.MediatorHelper;
25 import com.jsql.view.swing.util.UiStringUtil;
26 import com.jsql.view.swing.util.UiUtil;
27 import org.apache.logging.log4j.LogManager;
28 import org.apache.logging.log4j.Logger;
29
30 import javax.swing.*;
31 import javax.swing.border.LineBorder;
32 import javax.swing.tree.DefaultMutableTreeNode;
33 import javax.swing.tree.TreePath;
34 import java.awt.*;
35 import java.awt.event.MouseEvent;
36
37
38
39
40 public abstract class AbstractNodeModel {
41
42 private static final Logger LOGGER = LogManager.getRootLogger();
43 private static final String TREE_BACKGROUND = "Tree.background";
44
45
46
47
48 private AbstractElementDatabase elementDatabase;
49
50
51
52
53 private String textEmptyNode;
54
55
56
57
58 private int indexProgress = 0;
59
60
61
62
63 private boolean isSelected = false;
64
65
66
67
68 private boolean isRunning = false;
69
70
71
72
73
74 private boolean isAnyCheckboxSelected = false;
75
76
77
78
79
80 private boolean isLoaded = false;
81
82
83
84
85
86 private boolean isProgressing = false;
87
88
89
90
91
92 private boolean isLoading = false;
93
94 private PanelNode panelNode;
95
96 private boolean isEdited;
97
98
99
100
101
102 protected AbstractNodeModel(AbstractElementDatabase elementDatabase) {
103 this.elementDatabase = elementDatabase;
104 }
105
106
107
108
109
110 protected AbstractNodeModel(String emptyObject) {
111 this.textEmptyNode = emptyObject;
112 }
113
114
115
116
117
118
119 protected abstract void buildMenu(JPopupMenuCustomExtract tablePopupMenu, TreePath path);
120
121
122
123
124
125
126 public abstract boolean isPopupDisplayable();
127
128
129
130
131
132
133 protected abstract Icon getLeafIcon(boolean isLeaf);
134
135
136
137
138
139 public abstract void runAction();
140
141
142
143
144
145
146 public void showPopup(DefaultMutableTreeNode currentTableNode, TreePath path, MouseEvent e) {
147 var popupMenu = new JPopupMenuCustomExtract();
148 AbstractSuspendable suspendableTask = MediatorHelper.model().getMediatorUtils().getThreadUtil().get(this.elementDatabase);
149
150 this.initItemLoadPause(currentTableNode, popupMenu, suspendableTask);
151 this.initItemRenameReload(currentTableNode, path, popupMenu);
152 this.buildMenu(popupMenu, path);
153 this.displayPopupMenu(e, popupMenu);
154 }
155
156 private void displayPopupMenu(MouseEvent e, JPopupMenuCustomExtract popupMenu) {
157 popupMenu.applyComponentOrientation(ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale()));
158
159 popupMenu.show(
160 MediatorHelper.treeDatabase(),
161 ComponentOrientation.RIGHT_TO_LEFT.equals(ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale()))
162 ? e.getX() - popupMenu.getWidth()
163 : e.getX(),
164 e.getY()
165 );
166
167 popupMenu.setLocation(
168 ComponentOrientation.RIGHT_TO_LEFT.equals(ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale()))
169 ? e.getXOnScreen() - popupMenu.getWidth()
170 : e.getXOnScreen(),
171 e.getYOnScreen()
172 );
173 }
174
175 private void initItemRenameReload(DefaultMutableTreeNode currentTableNode, TreePath path, JPopupMenuCustomExtract popupMenu) {
176 String textReload;
177
178 if (this instanceof NodeModelDatabase) {
179 textReload = I18nViewUtil.valueByKey("RELOAD_TABLES");
180 } else if (this instanceof NodeModelTable) {
181 textReload = I18nViewUtil.valueByKey("RELOAD_COLUMNS");
182 } else {
183 textReload = "?";
184 }
185
186 JMenuItem menuItemReload = new JMenuItem(textReload);
187 menuItemReload.setEnabled(!this.isRunning);
188 menuItemReload.addActionListener(actionEvent -> this.runAction());
189
190 JMenuItem menuItemRename = new JMenuItem(I18nViewUtil.valueByKey("RENAME_NODE"));
191 menuItemRename.setEnabled(!this.isRunning);
192 menuItemRename.addActionListener(actionEvent -> {
193 AbstractNodeModel nodeModel = (AbstractNodeModel) currentTableNode.getUserObject();
194 nodeModel.setIsEdited(true);
195
196 this.getPanel().getNodeLabel().setVisible(false);
197 this.getPanel().getTextFieldEditable().setVisible(true);
198
199 MediatorHelper.treeDatabase().setSelectionPath(path);
200 });
201
202 popupMenu.add(new JSeparator());
203 popupMenu.add(menuItemRename);
204 popupMenu.add(menuItemReload);
205 }
206
207 private void initItemLoadPause(
208 DefaultMutableTreeNode currentTableNode,
209 JPopupMenuCustomExtract popupMenu,
210 AbstractSuspendable suspendableTask
211 ) {
212 JMenuItem menuItemLoad = new JMenuItem(
213 this.isRunning
214 ? I18nViewUtil.valueByKey("THREAD_STOP")
215 : I18nViewUtil.valueByKey("THREAD_LOAD"),
216 'o'
217 );
218 if (!this.isAnyCheckboxSelected && !this.isRunning) {
219 menuItemLoad.setEnabled(false);
220 }
221 menuItemLoad.addActionListener(new ActionLoadStop(this, currentTableNode));
222
223 JMenuItem menuItemPause = new JMenuItem(
224
225 suspendableTask != null && suspendableTask.isPaused()
226 ? I18nViewUtil.valueByKey("THREAD_RESUME")
227 : I18nViewUtil.valueByKey("THREAD_PAUSE"),
228 's'
229 );
230 if (!this.isRunning) {
231 menuItemPause.setEnabled(false);
232 }
233 menuItemPause.addActionListener(new ActionPauseUnpause(this));
234
235 popupMenu.add(menuItemLoad);
236 popupMenu.add(menuItemPause);
237 }
238
239
240
241
242 public Component getComponent(
243 final JTree tree,
244 Object nodeRenderer,
245 final boolean isSelected,
246 boolean isLeaf,
247 boolean hasFocus
248 ) {
249 DefaultMutableTreeNode currentNode = (DefaultMutableTreeNode) nodeRenderer;
250 this.panelNode = new PanelNode(tree, currentNode);
251
252 if (isSelected) {
253 this.panelNode.setBackground(
254 hasFocus
255 ? UIManager.getColor("Tree.selectionBackground")
256 : UIManager.getColor("Tree.selectionInactiveBackground")
257 );
258 } else {
259 this.panelNode.setBackground(UIManager.getColor(AbstractNodeModel.TREE_BACKGROUND));
260 }
261
262 this.initIcon(isLeaf);
263
264 AbstractNodeModel nodeModel = (AbstractNodeModel) currentNode.getUserObject();
265 this.initEditable(nodeModel.isEdited);
266 this.initLabel(isSelected, hasFocus, nodeModel.isEdited);
267 this.initProgress(currentNode);
268
269 return this.panelNode;
270 }
271
272 private void initIcon(boolean isLeaf) {
273 this.panelNode.showIcon();
274 this.panelNode.setIconNode(this.getLeafIcon(isLeaf));
275 }
276
277 private void initProgress(DefaultMutableTreeNode currentNode) {
278 if (this.isLoading) {
279 this.displayProgress(this.panelNode, currentNode);
280 this.panelNode.hideIcon();
281 } else if (this.isProgressing) {
282 this.panelNode.showLoader();
283 this.panelNode.hideIcon();
284
285 AbstractSuspendable suspendableTask = MediatorHelper.model().getMediatorUtils().getThreadUtil().get(this.elementDatabase);
286 if (suspendableTask != null && suspendableTask.isPaused()) {
287 this.panelNode.setLoaderIcon(new ImageOverlap(UiUtil.HOURGLASS.getIcon(), UiUtil.PATH_PAUSE));
288 }
289 }
290 }
291
292 private void initLabel(final boolean isSelected, boolean hasFocus, boolean isEdited) {
293
294 JLabel nodeLabel = this.panelNode.getNodeLabel();
295 try {
296 nodeLabel.setText(UiStringUtil.detectUtf8Html(this.toString()));
297 } catch (NullPointerException e) {
298 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
299 }
300 nodeLabel.setVisible(!isEdited);
301
302 if (isSelected) {
303 if (hasFocus) {
304 nodeLabel.setForeground(UIManager.getColor("Tree.selectionForeground"));
305 nodeLabel.setBackground(UIManager.getColor("Tree.selectionBackground"));
306 } else {
307 nodeLabel.setForeground(UIManager.getColor("Tree.selectionInactiveForeground"));
308 nodeLabel.setBackground(UIManager.getColor("Tree.selectionInactiveBackground"));
309 }
310 nodeLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
311 } else {
312 if (hasFocus) {
313 nodeLabel.setBackground(UIManager.getColor("Tree.foreground"));
314 nodeLabel.setBackground(UIManager.getColor(AbstractNodeModel.TREE_BACKGROUND));
315 nodeLabel.setBorder(new LineBorder(UIManager.getColor("Tree.selectionBorderColor"), 1, false));
316 } else {
317 nodeLabel.setBackground(UIManager.getColor("Tree.foreground"));
318 nodeLabel.setBackground(UIManager.getColor(AbstractNodeModel.TREE_BACKGROUND));
319 nodeLabel.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
320 }
321 }
322 }
323
324 private void initEditable(boolean isEdited) {
325 if (StringUtil.isUtf8(this.getElementDatabase().toString())) {
326 this.panelNode.getTextFieldEditable().setFont(UiUtil.FONT_MONO_ASIAN);
327 } else {
328 this.panelNode.getTextFieldEditable().setFont(UiUtil.FONT_NON_MONO);
329 }
330
331 this.panelNode.getTextFieldEditable().setText(StringUtil.detectUtf8(this.getElementDatabase().toString()));
332 this.panelNode.getTextFieldEditable().setVisible(isEdited);
333 }
334
335
336
337
338
339
340 protected void displayProgress(PanelNode panelNode, DefaultMutableTreeNode currentNode) {
341 int dataCount = this.elementDatabase.getChildCount();
342 panelNode.getProgressBar().setMaximum(dataCount);
343 panelNode.getProgressBar().setValue(this.indexProgress);
344 panelNode.getProgressBar().setVisible(true);
345
346
347 AbstractSuspendable suspendableTask = MediatorHelper.model().getMediatorUtils().getThreadUtil().get(this.elementDatabase);
348 if (suspendableTask != null && suspendableTask.isPaused()) {
349 panelNode.getProgressBar().pause();
350 }
351 }
352
353 @Override
354 public String toString() {
355 return this.elementDatabase != null ? this.elementDatabase.getLabelWithCount() : this.textEmptyNode;
356 }
357
358
359
360
361
362
363
364
365 protected AbstractElementDatabase getParent() {
366 return this.elementDatabase.getParent();
367 }
368
369 public AbstractElementDatabase getElementDatabase() {
370 return this.elementDatabase;
371 }
372
373 public void setIndexProgress(int indexProgress) {
374 this.indexProgress = indexProgress;
375 }
376
377 public boolean isSelected() {
378 return this.isSelected;
379 }
380
381 public void setSelected(boolean isSelected) {
382 this.isSelected = isSelected;
383 }
384
385 public boolean isRunning() {
386 return this.isRunning;
387 }
388
389 public void setRunning(boolean isRunning) {
390 this.isRunning = isRunning;
391 }
392
393 public void setIsAnyCheckboxSelected(boolean isAnyCheckboxSelected) {
394 this.isAnyCheckboxSelected = isAnyCheckboxSelected;
395 }
396
397 public boolean isLoaded() {
398 return this.isLoaded;
399 }
400
401 public void setLoaded(boolean isLoaded) {
402 this.isLoaded = isLoaded;
403 }
404
405 public void setProgressing(boolean isProgressing) {
406 this.isProgressing = isProgressing;
407 }
408
409 public void setLoading(boolean isLoading) {
410 this.isLoading = isLoading;
411 }
412
413 public PanelNode getPanel() {
414 return this.panelNode;
415 }
416
417 public void setIsEdited(boolean isEdited) {
418 this.isEdited = isEdited;
419 }
420
421 public void setText(String textI18n) {
422 this.textEmptyNode = textI18n;
423 }
424 }