mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-04 08:55:11 +00:00
795 lines
31 KiB
Java
795 lines
31 KiB
Java
/*
|
|
* Copyright (C) 2010-2021 JPEXS
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package com.jpexs.decompiler.flash.gui;
|
|
|
|
import com.jpexs.decompiler.flash.configuration.Configuration;
|
|
import com.jpexs.decompiler.flash.configuration.ConfigurationItem;
|
|
import java.awt.BorderLayout;
|
|
import java.awt.Color;
|
|
import java.awt.Component;
|
|
import java.awt.Desktop;
|
|
import java.awt.Dimension;
|
|
import java.awt.Font;
|
|
import java.awt.Graphics;
|
|
import java.awt.GraphicsConfiguration;
|
|
import java.awt.GraphicsDevice;
|
|
import java.awt.GraphicsEnvironment;
|
|
import java.awt.Image;
|
|
import java.awt.Insets;
|
|
import java.awt.Rectangle;
|
|
import java.awt.SystemColor;
|
|
import java.awt.TexturePaint;
|
|
import java.awt.Toolkit;
|
|
import java.awt.Window;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.KeyEvent;
|
|
import java.awt.event.WindowEvent;
|
|
import java.awt.image.BufferedImage;
|
|
import java.awt.image.VolatileImage;
|
|
import java.io.IOException;
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
import java.net.URL;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
import javax.imageio.ImageIO;
|
|
import javax.swing.AbstractAction;
|
|
import javax.swing.Action;
|
|
import javax.swing.ActionMap;
|
|
import javax.swing.Icon;
|
|
import javax.swing.ImageIcon;
|
|
import javax.swing.InputMap;
|
|
import javax.swing.JButton;
|
|
import javax.swing.JCheckBox;
|
|
import javax.swing.JComponent;
|
|
import javax.swing.JDialog;
|
|
import javax.swing.JEditorPane;
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JMenuItem;
|
|
import javax.swing.JOptionPane;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JPopupMenu;
|
|
import javax.swing.JRootPane;
|
|
import javax.swing.JTable;
|
|
import javax.swing.JTree;
|
|
import javax.swing.KeyStroke;
|
|
import javax.swing.LookAndFeel;
|
|
import javax.swing.SwingConstants;
|
|
import javax.swing.SwingUtilities;
|
|
import javax.swing.UIDefaults;
|
|
import javax.swing.UIManager;
|
|
import javax.swing.UnsupportedLookAndFeelException;
|
|
import javax.swing.plaf.FontUIResource;
|
|
import javax.swing.plaf.basic.BasicColorChooserUI;
|
|
import javax.swing.table.DefaultTableCellRenderer;
|
|
import javax.swing.table.DefaultTableColumnModel;
|
|
import javax.swing.table.TableCellRenderer;
|
|
import javax.swing.table.TableColumn;
|
|
import javax.swing.table.TableModel;
|
|
import javax.swing.text.JTextComponent;
|
|
import javax.swing.tree.TreeModel;
|
|
import javax.swing.tree.TreePath;
|
|
import org.pushingpixels.flamingo.api.common.icon.ImageWrapperResizableIcon;
|
|
import org.pushingpixels.substance.api.ColorSchemeAssociationKind;
|
|
import org.pushingpixels.substance.api.ComponentState;
|
|
import org.pushingpixels.substance.api.DecorationAreaType;
|
|
import org.pushingpixels.substance.api.SubstanceColorScheme;
|
|
import org.pushingpixels.substance.api.SubstanceConstants;
|
|
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
|
|
import org.pushingpixels.substance.api.SubstanceSkin;
|
|
import org.pushingpixels.substance.api.fonts.FontPolicy;
|
|
import org.pushingpixels.substance.api.fonts.FontSet;
|
|
import org.pushingpixels.substance.api.skin.SubstanceOfficeBlue2007LookAndFeel;
|
|
import org.pushingpixels.substance.internal.utils.SubstanceColorSchemeUtilities;
|
|
|
|
/**
|
|
* Contains methods for GUI
|
|
*
|
|
* @author JPEXS
|
|
*/
|
|
public class View {
|
|
|
|
public static Color getDefaultBackgroundColor() {
|
|
if (Configuration.useRibbonInterface.get()) {
|
|
return SubstanceLookAndFeel.getCurrentSkin().getColorScheme(DecorationAreaType.GENERAL, ColorSchemeAssociationKind.FILL, ComponentState.ENABLED).getBackgroundFillColor();
|
|
} else {
|
|
return SystemColor.control;
|
|
}
|
|
}
|
|
|
|
private static Color swfBackgroundColor = null;
|
|
|
|
public static void setSwfBackgroundColor(Color swfBackgroundColor) {
|
|
View.swfBackgroundColor = swfBackgroundColor;
|
|
}
|
|
|
|
public static Color getSwfBackgroundColor() {
|
|
if (swfBackgroundColor == null) {
|
|
return getDefaultBackgroundColor();
|
|
}
|
|
return swfBackgroundColor;
|
|
}
|
|
|
|
private static final BufferedImage transparentTexture;
|
|
|
|
public static final TexturePaint transparentPaint;
|
|
|
|
private static FontPolicy defaultFontPolicy;
|
|
|
|
private static final Color transparentColor1 = new Color(0x99, 0x99, 0x99);
|
|
|
|
private static final Color transparentColor2 = new Color(0x66, 0x66, 0x66);
|
|
|
|
static {
|
|
transparentTexture = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
|
|
Graphics g = transparentTexture.getGraphics();
|
|
g.setColor(transparentColor1);
|
|
g.fillRect(0, 0, 16, 16);
|
|
g.setColor(transparentColor2);
|
|
g.fillRect(0, 0, 8, 8);
|
|
g.fillRect(8, 8, 8, 8);
|
|
transparentPaint = new TexturePaint(View.transparentTexture, new Rectangle(0, 0, transparentTexture.getWidth(), transparentTexture.getHeight()));
|
|
}
|
|
|
|
/**
|
|
* Sets windows Look and Feel
|
|
*/
|
|
public static void setLookAndFeel() {
|
|
|
|
// Save default font for Chinese characters
|
|
final Font defaultFont = (new JLabel()).getFont();
|
|
try {
|
|
|
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
|
|
} catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException ignored) {
|
|
}
|
|
|
|
try {
|
|
LookAndFeel oldLookAndFeel = UIManager.getLookAndFeel();
|
|
if (!(oldLookAndFeel instanceof SubstanceOfficeBlue2007LookAndFeel)) {
|
|
UIManager.setLookAndFeel(new SubstanceOfficeBlue2007LookAndFeel());
|
|
oldLookAndFeel.uninitialize();
|
|
}
|
|
|
|
SubstanceSkin currentSkin = SubstanceLookAndFeel.getCurrentSkin();
|
|
if (currentSkin != null) {
|
|
String currentSkinName = currentSkin.getClass().getName();
|
|
String newSkinName = Configuration.guiSkin.get();
|
|
if (!currentSkinName.equals(newSkinName)) {
|
|
SubstanceLookAndFeel.setSkin(newSkinName);
|
|
}
|
|
} else {
|
|
Logger.getLogger(View.class.getName()).log(Level.SEVERE, "Current skin is null");
|
|
SubstanceLookAndFeel.setSkin("com.jpexs.decompiler.flash.gui.OceanicSkin");
|
|
}
|
|
|
|
UIManager.put(SubstanceLookAndFeel.COLORIZATION_FACTOR, 0.999);//This works for not changing labels color and not changing Dialogs title
|
|
UIManager.put("Tree.expandedIcon", getIcon("expand16"));
|
|
UIManager.put("Tree.collapsedIcon", getIcon("collapse16"));
|
|
UIManager.put("ColorChooserUI", BasicColorChooserUI.class.getName());
|
|
UIManager.put("ColorChooser.swatchesRecentSwatchSize", new Dimension(20, 20));
|
|
UIManager.put("ColorChooser.swatchesSwatchSize", new Dimension(20, 20));
|
|
UIManager.put("RibbonApplicationMenuPopupPanelUI", MyRibbonApplicationMenuPopupPanelUI.class.getName());
|
|
UIManager.put("RibbonApplicationMenuButtonUI", MyRibbonApplicationMenuButtonUI.class.getName());
|
|
UIManager.put("ProgressBarUI", MyProgressBarUI.class.getName());
|
|
UIManager.put("TextField.background", Color.white);
|
|
UIManager.put("FormattedTextField.background", Color.white);
|
|
UIManager.put("CommandButtonUI", MyCommandButtonUI.class.getName());
|
|
|
|
if (defaultFontPolicy == null) {
|
|
defaultFontPolicy = SubstanceLookAndFeel.getFontPolicy();
|
|
}
|
|
|
|
FontPolicy pol = defaultFontPolicy;
|
|
final FontSet fs = pol.getFontSet("Substance", null);
|
|
|
|
double fontSizeMultiplier = Configuration.guiFontSizeMultiplier.get();
|
|
|
|
// Restore default font for chinese characters
|
|
SubstanceLookAndFeel.setFontPolicy(new FontPolicy() {
|
|
private final FontSet fontSet = new FontSet() {
|
|
private FontUIResource controlFont;
|
|
|
|
private FontUIResource menuFont;
|
|
|
|
private FontUIResource titleFont;
|
|
|
|
private FontUIResource windowTitleFont;
|
|
|
|
private FontUIResource smallFont;
|
|
|
|
private FontUIResource messageFont;
|
|
|
|
private int getFontSize(int defaultFontSize) {
|
|
return (int) (defaultFontSize * fontSizeMultiplier);
|
|
}
|
|
|
|
@Override
|
|
public FontUIResource getControlFont() {
|
|
if (controlFont == null) {
|
|
FontUIResource f = fs.getControlFont();
|
|
controlFont = new FontUIResource(defaultFont.getName(), f.getStyle(), getFontSize(f.getSize()));
|
|
}
|
|
return controlFont;
|
|
}
|
|
|
|
@Override
|
|
public FontUIResource getMenuFont() {
|
|
if (menuFont == null) {
|
|
FontUIResource f = fs.getMenuFont();
|
|
menuFont = new FontUIResource(defaultFont.getName(), f.getStyle(), getFontSize(f.getSize()));
|
|
}
|
|
return menuFont;
|
|
}
|
|
|
|
@Override
|
|
public FontUIResource getTitleFont() {
|
|
if (titleFont == null) {
|
|
FontUIResource f = fs.getTitleFont();
|
|
titleFont = new FontUIResource(defaultFont.getName(), f.getStyle(), getFontSize(f.getSize()));
|
|
}
|
|
return titleFont;
|
|
}
|
|
|
|
@Override
|
|
public FontUIResource getWindowTitleFont() {
|
|
if (windowTitleFont == null) {
|
|
FontUIResource f = fs.getWindowTitleFont();
|
|
windowTitleFont = new FontUIResource(defaultFont.getName(), f.getStyle(), getFontSize(f.getSize()));
|
|
}
|
|
return windowTitleFont;
|
|
}
|
|
|
|
@Override
|
|
public FontUIResource getSmallFont() {
|
|
if (smallFont == null) {
|
|
FontUIResource f = fs.getSmallFont();
|
|
smallFont = new FontUIResource(defaultFont.getName(), f.getStyle(), getFontSize(f.getSize()));
|
|
}
|
|
return smallFont;
|
|
}
|
|
|
|
@Override
|
|
public FontUIResource getMessageFont() {
|
|
if (messageFont == null) {
|
|
FontUIResource f = fs.getMessageFont();
|
|
messageFont = new FontUIResource(defaultFont.getName(), f.getStyle(), getFontSize(f.getSize()));
|
|
}
|
|
return messageFont;
|
|
}
|
|
};
|
|
|
|
@Override
|
|
public FontSet getFontSet(String string, UIDefaults uid) {
|
|
return fontSet;
|
|
}
|
|
});
|
|
} catch (UnsupportedLookAndFeelException ex) {
|
|
Logger.getLogger(View.class.getName()).log(Level.SEVERE, null, ex);
|
|
}
|
|
|
|
UIManager.put(SubstanceLookAndFeel.TABBED_PANE_CONTENT_BORDER_KIND, SubstanceConstants.TabContentPaneBorderKind.SINGLE_FULL);
|
|
|
|
JFrame.setDefaultLookAndFeelDecorated(true);
|
|
JDialog.setDefaultLookAndFeelDecorated(true);
|
|
}
|
|
|
|
/**
|
|
* Loads image from resources
|
|
*
|
|
* @param name Name of the image
|
|
* @return loaded Image
|
|
*/
|
|
public static BufferedImage loadImage(String name) {
|
|
URL imageURL = View.class.getResource("/com/jpexs/decompiler/flash/gui/graphics/" + name + ".png");
|
|
try {
|
|
return ImageIO.read(imageURL);
|
|
} catch (IOException ex) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets icon of specified frame to ASDec icon
|
|
*
|
|
* @param f Frame to set icon in
|
|
*/
|
|
public static void setWindowIcon(Window f) {
|
|
if (Configuration.useRibbonInterface.get()) {
|
|
List<Image> images = new ArrayList<>();
|
|
MyResizableIcon[] icons = MyRibbonApplicationMenuButtonUI.getIcons();
|
|
MyResizableIcon icon = icons[1];
|
|
int[] sizes = new int[]{256, 128, 64, 42, 40, 32, 20, 16};
|
|
for (int size : sizes) {
|
|
icon.setIconSize(size, size);
|
|
BufferedImage bi = new BufferedImage(size, size, BufferedImage.TYPE_4BYTE_ABGR);
|
|
icon.paintIcon(f, bi.getGraphics(), 0, 0);
|
|
images.add(bi);
|
|
}
|
|
f.setIconImages(images);
|
|
} else {
|
|
List<Image> images = new ArrayList<>();
|
|
images.add(loadImage("icon16"));
|
|
images.add(loadImage("icon32"));
|
|
images.add(loadImage("icon48"));
|
|
images.add(loadImage("icon256"));
|
|
f.setIconImages(images);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Centers specified frame on the screen
|
|
*
|
|
* @param f Frame to center on the screen
|
|
*/
|
|
public static void centerScreen(Window f) {
|
|
centerScreen(f, 0); // todo, set screen to the currently active screen instead of the first screen in a multi screen setup, (maybe by using the screen where the main window is now classic or ribbon?)
|
|
}
|
|
|
|
public static void centerScreen(Window f, int screen) {
|
|
|
|
GraphicsDevice[] allDevices = getEnv().getScreenDevices();
|
|
int topLeftX, topLeftY, screenX, screenY, windowPosX, windowPosY;
|
|
|
|
if (screen < allDevices.length && screen > -1) {
|
|
topLeftX = allDevices[screen].getDefaultConfiguration().getBounds().x;
|
|
topLeftY = allDevices[screen].getDefaultConfiguration().getBounds().y;
|
|
|
|
screenX = allDevices[screen].getDefaultConfiguration().getBounds().width;
|
|
screenY = allDevices[screen].getDefaultConfiguration().getBounds().height;
|
|
|
|
Insets bounds = Toolkit.getDefaultToolkit().getScreenInsets(allDevices[screen].getDefaultConfiguration());
|
|
screenX = screenX - bounds.right;
|
|
screenY = screenY - bounds.bottom;
|
|
} else {
|
|
topLeftX = allDevices[0].getDefaultConfiguration().getBounds().x;
|
|
topLeftY = allDevices[0].getDefaultConfiguration().getBounds().y;
|
|
|
|
screenX = allDevices[0].getDefaultConfiguration().getBounds().width;
|
|
screenY = allDevices[0].getDefaultConfiguration().getBounds().height;
|
|
|
|
Insets bounds = Toolkit.getDefaultToolkit().getScreenInsets(allDevices[0].getDefaultConfiguration());
|
|
screenX = screenX - bounds.right;
|
|
screenY = screenY - bounds.bottom;
|
|
}
|
|
|
|
windowPosX = ((screenX - f.getWidth()) / 2) + topLeftX;
|
|
windowPosY = ((screenY - f.getHeight()) / 2) + topLeftY;
|
|
|
|
f.setLocation(windowPosX, windowPosY);
|
|
}
|
|
|
|
public static ImageIcon getIcon(String name, int size) {
|
|
ImageIcon icon = getIcon(getPrefferedIconName(name, size));
|
|
if (icon.getIconWidth() == size && icon.getIconHeight() == size) {
|
|
return icon;
|
|
}
|
|
icon.getImage();
|
|
BufferedImage bi = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
|
|
bi.createGraphics().drawImage(icon.getImage(), 0, 0, size, size, null, null);
|
|
return new ImageIcon(bi);
|
|
}
|
|
|
|
public static ImageIcon getIcon(String name) {
|
|
return new ImageIcon(View.class.getClassLoader().getResource("com/jpexs/decompiler/flash/gui/graphics/" + name + ".png"));
|
|
}
|
|
|
|
private static final KeyStroke escapeStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
|
|
|
|
private static final String dispatchWindowClosingActionMapKey = "com.jpexs.dispatch:WINDOW_CLOSING";
|
|
|
|
public static void installEscapeCloseOperation(final JDialog dialog) {
|
|
Action dispatchClosing = new AbstractAction() {
|
|
@Override
|
|
public void actionPerformed(ActionEvent event) {
|
|
dialog.dispatchEvent(new WindowEvent(
|
|
dialog, WindowEvent.WINDOW_CLOSING));
|
|
}
|
|
};
|
|
JRootPane root = dialog.getRootPane();
|
|
root.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
|
|
escapeStroke, dispatchWindowClosingActionMapKey);
|
|
root.getActionMap().put(dispatchWindowClosingActionMapKey, dispatchClosing);
|
|
}
|
|
|
|
public static boolean iconExists(String resource) {
|
|
return View.class.getResource("/com/jpexs/decompiler/flash/gui/graphics/" + resource + ".png") != null;
|
|
}
|
|
|
|
private static String getPrefferedIconName(String resource, int preferredSize) {
|
|
Matcher m = Pattern.compile("(.*[^0-9])([0-9]+)").matcher(resource);
|
|
if (m.matches()) {
|
|
int origSize = Integer.parseInt(m.group(2));
|
|
String name = m.group(1);
|
|
if (origSize != preferredSize) {
|
|
if (iconExists(name + preferredSize)) {
|
|
return name + preferredSize;
|
|
}
|
|
}
|
|
}
|
|
return resource;
|
|
}
|
|
|
|
public static ImageWrapperResizableIcon getResizableIcon(String resource, int preferredSize) {
|
|
return getResizableIcon(getPrefferedIconName(resource, preferredSize));
|
|
}
|
|
|
|
public static ImageWrapperResizableIcon getResizableIcon(String resource) {
|
|
return ImageWrapperResizableIcon.getIcon(View.class.getResource("/com/jpexs/decompiler/flash/gui/graphics/" + resource + ".png"), new Dimension(256, 256));
|
|
}
|
|
|
|
public static MyResizableIcon getMyResizableIcon(String resource) {
|
|
try {
|
|
return new MyResizableIcon(ImageIO.read(View.class.getResourceAsStream("/com/jpexs/decompiler/flash/gui/graphics/" + resource + ".png")));
|
|
} catch (IOException ex) {
|
|
Logger.getLogger(View.class.getName()).log(Level.SEVERE, null, ex);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static void checkAccess() {
|
|
if (!SwingUtilities.isEventDispatchThread()) {
|
|
throw new RuntimeException("This method should be called from UI thread.");
|
|
}
|
|
}
|
|
|
|
public static void execInEventDispatch(Runnable r) {
|
|
if (SwingUtilities.isEventDispatchThread()) {
|
|
r.run();
|
|
} else {
|
|
try {
|
|
SwingUtilities.invokeAndWait(r);
|
|
} catch (InterruptedException ex) {
|
|
} catch (InvocationTargetException ex) {
|
|
Logger.getLogger(View.class.getName()).log(Level.SEVERE, null, ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void execInEventDispatchLater(Runnable r) {
|
|
if (SwingUtilities.isEventDispatchThread()) {
|
|
r.run();
|
|
} else {
|
|
SwingUtilities.invokeLater(r);
|
|
}
|
|
}
|
|
|
|
public static int showOptionDialog(final Component parentComponent, final Object message, final String title, final int optionType, final int messageType, final Icon icon, final Object[] options, final Object initialValue) {
|
|
final int[] ret = new int[1];
|
|
execInEventDispatch(() -> {
|
|
ret[0] = JOptionPane.showOptionDialog(parentComponent, message, title, optionType, messageType, icon, options, initialValue);
|
|
});
|
|
return ret[0];
|
|
}
|
|
|
|
public static int showConfirmDialog(Component parentComponent, Object message, String title, int optionType) {
|
|
return showConfirmDialog(parentComponent, message, title, optionType, JOptionPane.PLAIN_MESSAGE);
|
|
}
|
|
|
|
public static int showConfirmDialog(final Component parentComponent, final Object message, final String title, final int optionType, final int messageTyp) {
|
|
final int[] ret = new int[1];
|
|
execInEventDispatch(() -> {
|
|
ret[0] = JOptionPane.showConfirmDialog(parentComponent, message, title, optionType, messageTyp);
|
|
});
|
|
return ret[0];
|
|
}
|
|
|
|
public static int showConfirmDialog(Component parentComponent, String message, String title, int optionType, ConfigurationItem<Boolean> showAgainConfig, int defaultOption) {
|
|
return showConfirmDialog(parentComponent, message, title, optionType, JOptionPane.PLAIN_MESSAGE, showAgainConfig, defaultOption);
|
|
}
|
|
|
|
public static int showConfirmDialog(final Component parentComponent, String message, final String title, final int optionType, final int messageType, ConfigurationItem<Boolean> showAgainConfig, int defaultOption) {
|
|
|
|
JCheckBox donotShowAgainCheckBox = null;
|
|
JPanel warPanel = null;
|
|
if (showAgainConfig != null) {
|
|
if (!showAgainConfig.get()) {
|
|
return defaultOption;
|
|
}
|
|
|
|
JLabel warLabel = new JLabel("<html>" + message.replace("\r\n", "<br>") + "</html>");
|
|
warPanel = new JPanel(new BorderLayout());
|
|
warPanel.add(warLabel, BorderLayout.CENTER);
|
|
donotShowAgainCheckBox = new JCheckBox(AppStrings.translate("message.confirm.donotshowagain"));
|
|
warPanel.add(donotShowAgainCheckBox, BorderLayout.SOUTH);
|
|
}
|
|
|
|
final int[] ret = new int[1];
|
|
final Object messageObj = warPanel == null ? message : warPanel;
|
|
execInEventDispatch(() -> {
|
|
ret[0] = JOptionPane.showConfirmDialog(parentComponent, messageObj, title, optionType, messageType);
|
|
});
|
|
|
|
if (donotShowAgainCheckBox != null) {
|
|
showAgainConfig.set(!donotShowAgainCheckBox.isSelected());
|
|
}
|
|
|
|
return ret[0];
|
|
}
|
|
|
|
public static void showMessageDialog(final Component parentComponent, final String message, final String title, final int messageType) {
|
|
showMessageDialog(parentComponent, message, title, messageType, null);
|
|
}
|
|
|
|
public static void showMessageDialog(final Component parentComponent, final String message, final String title, final int messageType, ConfigurationItem<Boolean> showAgainConfig) {
|
|
|
|
execInEventDispatch(() -> {
|
|
Object msg = message;
|
|
JCheckBox donotShowAgainCheckBox = null;
|
|
if (showAgainConfig != null) {
|
|
if (!showAgainConfig.get()) {
|
|
return;
|
|
}
|
|
|
|
JLabel warLabel = new JLabel("<html>" + message.replace("\r\n", "<br>") + "</html>");
|
|
final JPanel warPanel = new JPanel(new BorderLayout());
|
|
warPanel.add(warLabel, BorderLayout.CENTER);
|
|
donotShowAgainCheckBox = new JCheckBox(AppStrings.translate("message.confirm.donotshowagain"));
|
|
warPanel.add(donotShowAgainCheckBox, BorderLayout.SOUTH);
|
|
msg = warPanel;
|
|
}
|
|
final Object fmsg = msg;
|
|
|
|
JOptionPane.showMessageDialog(parentComponent, fmsg, title, messageType);
|
|
if (donotShowAgainCheckBox != null) {
|
|
showAgainConfig.set(!donotShowAgainCheckBox.isSelected());
|
|
}
|
|
});
|
|
}
|
|
|
|
public static void showMessageDialog(final Component parentComponent, final Object message) {
|
|
execInEventDispatch(() -> {
|
|
JOptionPane.showMessageDialog(parentComponent, message);
|
|
});
|
|
}
|
|
|
|
public static String showInputDialog(final Object message, final Object initialSelection) {
|
|
final String[] ret = new String[1];
|
|
execInEventDispatch(() -> {
|
|
ret[0] = JOptionPane.showInputDialog(message, initialSelection);
|
|
});
|
|
return ret[0];
|
|
}
|
|
|
|
public static SubstanceColorScheme getColorScheme() {
|
|
return SubstanceColorSchemeUtilities.getActiveColorScheme(new JButton(), ComponentState.ENABLED);
|
|
}
|
|
|
|
public static void refreshTree(JTree tree, TreeModel model) {
|
|
List<List<String>> expandedNodes = getExpandedNodes(tree);
|
|
tree.setModel(model);
|
|
expandTreeNodes(tree, expandedNodes);
|
|
}
|
|
|
|
public static List<List<String>> getExpandedNodes(JTree tree) {
|
|
List<List<String>> expandedNodes = new ArrayList<>();
|
|
int rowCount = tree.getRowCount();
|
|
for (int i = 0; i < rowCount; i++) {
|
|
try {
|
|
TreePath path = tree.getPathForRow(i);
|
|
if (tree.isExpanded(path)) {
|
|
List<String> pathAsStringList = new ArrayList<>();
|
|
for (Object pathCompnent : path.getPath()) {
|
|
pathAsStringList.add(pathCompnent.toString());
|
|
}
|
|
expandedNodes.add(pathAsStringList);
|
|
}
|
|
} catch (IndexOutOfBoundsException | NullPointerException ex) {
|
|
// TreeNode was removed, ignore
|
|
}
|
|
}
|
|
return expandedNodes;
|
|
}
|
|
|
|
public static void expandTreeNodes(JTree tree, List<List<String>> pathsToExpand) {
|
|
for (List<String> pathAsStringList : pathsToExpand) {
|
|
expandTreeNode(tree, pathAsStringList);
|
|
}
|
|
}
|
|
|
|
private static TreePath expandTreeNode(JTree tree, List<String> pathAsStringList) {
|
|
TreePath tp = getTreePathByPathStrings(tree, pathAsStringList);
|
|
tree.expandPath(tp);
|
|
return tp;
|
|
}
|
|
|
|
public static TreePath getTreePathByPathStrings(JTree tree, List<String> pathAsStringList) {
|
|
TreeModel model = tree.getModel();
|
|
if (model == null) {
|
|
return null;
|
|
}
|
|
|
|
Object node = model.getRoot();
|
|
|
|
if (pathAsStringList.isEmpty()) {
|
|
return null;
|
|
}
|
|
if (!pathAsStringList.get(0).equals(node.toString())) {
|
|
return null;
|
|
}
|
|
|
|
List<Object> path = new ArrayList<>();
|
|
path.add(node);
|
|
|
|
for (int i = 1; i < pathAsStringList.size(); i++) {
|
|
String name = pathAsStringList.get(i);
|
|
int childCount = model.getChildCount(node);
|
|
for (int j = 0; j < childCount; j++) {
|
|
Object child = model.getChild(node, j);
|
|
if (child.toString().equals(name)) {
|
|
node = child;
|
|
path.add(node);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
TreePath tp = new TreePath(path.toArray(new Object[path.size()]));
|
|
return tp;
|
|
}
|
|
|
|
public static void expandTreeNodes(JTree tree, TreePath parent, boolean expand) {
|
|
expandTreeNodesRecursive(tree, parent, expand);
|
|
}
|
|
|
|
private static void expandTreeNodesRecursive(JTree tree, TreePath parent, boolean expand) {
|
|
TreeModel model = tree.getModel();
|
|
|
|
Object node = parent.getLastPathComponent();
|
|
int childCount = model.getChildCount(node);
|
|
for (int j = 0; j < childCount; j++) {
|
|
Object child = model.getChild(node, j);
|
|
TreePath path = parent.pathByAddingChild(child);
|
|
expandTreeNodesRecursive(tree, path, expand);
|
|
}
|
|
|
|
if (expand) {
|
|
tree.expandPath(parent);
|
|
} else {
|
|
tree.collapsePath(parent);
|
|
}
|
|
}
|
|
|
|
public static void addEditorAction(JEditorPane editor, AbstractAction a, String key, String name, String keyStroke) {
|
|
KeyStroke ks = KeyStroke.getKeyStroke(keyStroke);
|
|
a.putValue(Action.ACCELERATOR_KEY, ks);
|
|
a.putValue(Action.NAME, name);
|
|
|
|
String actionName = key;
|
|
ActionMap amap = editor.getActionMap();
|
|
InputMap imap = editor.getInputMap(JTextComponent.WHEN_FOCUSED);
|
|
imap.put(ks, actionName);
|
|
amap.put(actionName, a);
|
|
|
|
JPopupMenu pmenu = editor.getComponentPopupMenu();
|
|
JMenuItem findUsagesMenu = new JMenuItem(a);
|
|
pmenu.add(findUsagesMenu);
|
|
}
|
|
|
|
public static boolean navigateUrl(String url) {
|
|
if (Desktop.isDesktopSupported()) {
|
|
Desktop desktop = Desktop.getDesktop();
|
|
if (desktop.isSupported(Desktop.Action.BROWSE)) {
|
|
try {
|
|
URI uri = new URI(url);
|
|
desktop.browse(uri);
|
|
return true;
|
|
} catch (URISyntaxException | IOException ex) {
|
|
Logger.getLogger(View.class.getName()).log(Level.SEVERE, null, ex);
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public static JTable autoResizeColWidth(final JTable table, final TableModel model) {
|
|
View.execInEventDispatch(() -> {
|
|
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
|
table.setModel(model);
|
|
|
|
int margin = 5;
|
|
|
|
for (int i = 0; i < table.getColumnCount(); i++) {
|
|
int vColIndex = i;
|
|
DefaultTableColumnModel colModel = (DefaultTableColumnModel) table.getColumnModel();
|
|
TableColumn col = colModel.getColumn(vColIndex);
|
|
int width;
|
|
|
|
// Get width of column header
|
|
TableCellRenderer renderer = col.getHeaderRenderer();
|
|
|
|
if (renderer == null) {
|
|
renderer = table.getTableHeader().getDefaultRenderer();
|
|
}
|
|
|
|
Component comp = renderer.getTableCellRendererComponent(table, col.getHeaderValue(), false, false, 0, 0);
|
|
|
|
width = comp.getPreferredSize().width;
|
|
|
|
// Get maximum width of column data
|
|
for (int r = 0; r < table.getRowCount(); r++) {
|
|
renderer = table.getCellRenderer(r, vColIndex);
|
|
comp = renderer.getTableCellRendererComponent(table, table.getValueAt(r, vColIndex), false, false,
|
|
r, vColIndex);
|
|
width = Math.max(width, comp.getPreferredSize().width);
|
|
}
|
|
|
|
// Add margin
|
|
width += 2 * margin;
|
|
|
|
// Set the width
|
|
col.setPreferredWidth(width);
|
|
}
|
|
|
|
((DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer()).setHorizontalAlignment(
|
|
SwingConstants.LEFT);
|
|
|
|
// table.setAutoCreateRowSorter(true);
|
|
table.getTableHeader().setReorderingAllowed(false);
|
|
});
|
|
|
|
return table;
|
|
}
|
|
|
|
private static GraphicsEnvironment env;
|
|
|
|
public static GraphicsEnvironment getEnv() {
|
|
if (env == null) {
|
|
env = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
|
}
|
|
return env;
|
|
}
|
|
|
|
private static GraphicsConfiguration conf;
|
|
|
|
public static GraphicsConfiguration getDefaultConfiguration() {
|
|
if (conf == null) {
|
|
conf = getEnv().getDefaultScreenDevice().getDefaultConfiguration();
|
|
}
|
|
return conf;
|
|
}
|
|
|
|
public static BufferedImage toCompatibleImage(BufferedImage image) {
|
|
if (image.getColorModel().equals(getDefaultConfiguration().getColorModel())) {
|
|
return image;
|
|
}
|
|
|
|
return getDefaultConfiguration().createCompatibleImage(image.getWidth(), image.getHeight(), image.getTransparency());
|
|
}
|
|
|
|
public static VolatileImage createRenderImage(int width, int height, int transparency) {
|
|
VolatileImage image = getDefaultConfiguration().createCompatibleVolatileImage(width, height, transparency);
|
|
|
|
int valid = image.validate(getDefaultConfiguration());
|
|
|
|
if (valid == VolatileImage.IMAGE_INCOMPATIBLE) {
|
|
image = createRenderImage(width, height, transparency);
|
|
return image;
|
|
}
|
|
|
|
return image;
|
|
}
|
|
}
|