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