/*******************************************************************************
* Copyright (c) 2016 Weasis Team and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nicolas Roduit - initial API and implementation
*******************************************************************************/
package org.weasis.core.ui.pref;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Window;
import java.io.File;
import java.time.ZonedDateTime;
import java.time.format.FormatStyle;
import java.util.Enumeration;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextPane;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.weasis.core.api.gui.util.AbstractItemDialogPage;
import org.weasis.core.api.gui.util.AppProperties;
import org.weasis.core.api.gui.util.GuiExecutor;
import org.weasis.core.api.gui.util.JMVUtils;
import org.weasis.core.api.gui.util.WinUtil;
import org.weasis.core.api.service.AuditLog;
import org.weasis.core.api.service.AuditLog.LEVEL;
import org.weasis.core.api.service.BundleTools;
import org.weasis.core.api.service.WProperties;
import org.weasis.core.api.util.LocalUtil;
import org.weasis.core.api.util.StringUtil;
import org.weasis.core.ui.Messages;
public class GeneralSetting extends AbstractItemDialogPage {
private static final Logger LOGGER = LoggerFactory.getLogger(GeneralSetting.class);
public static final String pageName = Messages.getString("GeneralSetting.gen"); //$NON-NLS-1$
private LookInfo oldUILook;
private final GridBagLayout gridBagLayout1 = new GridBagLayout();
private final JLabel jLabelMLook = new JLabel();
private final JComboBox<LookInfo> jComboBoxlnf = new JComboBox<>();
private final JTextPane txtpnNote = new JTextPane();
private final JLabel labelLocale2 =
new JLabel(Messages.getString("GeneralSetting.language.data") + StringUtil.COLON); //$NON-NLS-1$
@SuppressWarnings("serial")
private final JLocaleFormat comboBoxFormat = new JLocaleFormat() {
@Override
public void valueHasChanged() {
txtpnNote.setText(getText());
}
};
private final JLabel labelLocale = new JLabel(Messages.getString("GeneralSetting.language") + StringUtil.COLON); //$NON-NLS-1$
@SuppressWarnings("serial")
private final JLocaleLanguage comboBoxLang = new JLocaleLanguage() {
@Override
public void valueHasChanged() {
comboBoxFormat.refresh();
}
};
private final JCheckBox chckbxConfirmClosing =
new JCheckBox(Messages.getString("GeneralSetting.closingConfirmation")); //$NON-NLS-1$
private final JButton button = new JButton(Messages.getString("GeneralSetting.show")); //$NON-NLS-1$
private final JCheckBox chckbxFileLog = new JCheckBox(Messages.getString("GeneralSetting.rol_log")); //$NON-NLS-1$
private final JPanel panel = new JPanel();
private final JLabel lblLogLevel = new JLabel(Messages.getString("GeneralSetting.log_level") + StringUtil.COLON); //$NON-NLS-1$
private final JComboBox<LEVEL> comboBoxLogLevel = new JComboBox<>(LEVEL.values());
private final Component horizontalStrut = Box.createHorizontalStrut(10);
private final JLabel labelNumber = new JLabel(Messages.getString("GeneralSetting.log_nb") + StringUtil.COLON); //$NON-NLS-1$
private final JSpinner spinner = new JSpinner();
private final JLabel labelSize = new JLabel(Messages.getString("GeneralSetting.log_size") + StringUtil.COLON); //$NON-NLS-1$
private final JSpinner spinner1 = new JSpinner();
private final Component horizontalStrut1 = Box.createHorizontalStrut(10);
private final Component horizontalStrut2 = Box.createHorizontalStrut(10);
private final JPanel panel1 = new JPanel();
private final JLabel lblStacktraceLimit = new JLabel(Messages.getString("GeneralSetting.stack_limit") + StringUtil.COLON); //$NON-NLS-1$
private final JComboBox<String> comboBoxStackLimit =
new JComboBox<>(new String[] { "", "0", "1", "3", "5", "10", "20", "50", "100" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$
public GeneralSetting() {
super(pageName);
setComponentPosition(0);
setList(jComboBoxlnf, UIManager.getInstalledLookAndFeels());
try {
JMVUtils.setNumberModel(spinner, getIntPreferences(AuditLog.LOG_FILE_NUMBER, 5, null), 1, 99, 1);
JMVUtils.setNumberModel(spinner1, getIntPreferences(AuditLog.LOG_FILE_SIZE, 10, "MB"), 1, 99, 1); //$NON-NLS-1$
jbInit();
initialize(true);
} catch (Exception e) {
LOGGER.error("Cannot initialize GeneralSetting", e); //$NON-NLS-1$
}
}
private void jbInit() {
this.setLayout(gridBagLayout1);
jLabelMLook.setText(Messages.getString("GeneralSetting.lf") + StringUtil.COLON); //$NON-NLS-1$
GridBagConstraints gbcButton = new GridBagConstraints();
gbcButton.insets = new Insets(7, 5, 5, 15);
gbcButton.gridx = 2;
gbcButton.gridy = 0;
button.addActionListener(e -> {
LookInfo item = (LookInfo) jComboBoxlnf.getSelectedItem();
final String finalLafClassName = item.getClassName();
Runnable runnable = () -> {
try {
Dialog dialog = WinUtil.getParentDialog(GeneralSetting.this);
UIManager.setLookAndFeel(finalLafClassName);
SwingUtilities.updateComponentTreeUI(dialog);
} catch (Exception e1) {
LOGGER.error("Can't change look and feel", e1); //$NON-NLS-1$
}
};
GuiExecutor.instance().execute(runnable);
});
add(button, gbcButton);
GridBagConstraints gbcLabel = new GridBagConstraints();
gbcLabel.insets = new Insets(15, 10, 5, 5);
gbcLabel.anchor = GridBagConstraints.LINE_END;
gbcLabel.gridx = 0;
gbcLabel.gridy = 1;
add(labelLocale, gbcLabel);
GridBagConstraints gbcComboBox = new GridBagConstraints();
gbcComboBox.gridwidth = 3;
gbcComboBox.anchor = GridBagConstraints.WEST;
gbcComboBox.insets = new Insets(15, 0, 5, 0);
gbcComboBox.gridx = 1;
gbcComboBox.gridy = 1;
add(comboBoxLang, gbcComboBox);
GridBagConstraints gbcLabel2 = new GridBagConstraints();
gbcLabel2.insets = new Insets(5, 10, 5, 5);
gbcLabel2.anchor = GridBagConstraints.LINE_END;
gbcLabel2.gridx = 0;
gbcLabel2.gridy = 2;
add(labelLocale2, gbcLabel2);
GridBagConstraints gbcComboBox2 = new GridBagConstraints();
gbcComboBox2.gridwidth = 3;
gbcComboBox2.anchor = GridBagConstraints.WEST;
gbcComboBox2.insets = new Insets(5, 0, 5, 0);
gbcComboBox2.gridx = 1;
gbcComboBox2.gridy = 2;
add(comboBoxFormat, gbcComboBox2);
GridBagConstraints gbcTxtpnNote = new GridBagConstraints();
gbcTxtpnNote.anchor = GridBagConstraints.WEST;
gbcTxtpnNote.gridwidth = 4;
gbcTxtpnNote.insets = new Insets(5, 10, 5, 10);
gbcTxtpnNote.fill = GridBagConstraints.HORIZONTAL;
gbcTxtpnNote.gridx = 0;
gbcTxtpnNote.gridy = 3;
txtpnNote.setEditorKit(JMVUtils.buildHTMLEditorKit(txtpnNote));
txtpnNote.setContentType("text/html"); //$NON-NLS-1$
txtpnNote.setEditable(false);
txtpnNote.setText(getText());
add(txtpnNote, gbcTxtpnNote);
GridBagConstraints gbcChckbxConfirmationMessageWhen = new GridBagConstraints();
gbcChckbxConfirmationMessageWhen.gridwidth = 4;
gbcChckbxConfirmationMessageWhen.anchor = GridBagConstraints.WEST;
gbcChckbxConfirmationMessageWhen.insets = new Insets(10, 10, 5, 0);
gbcChckbxConfirmationMessageWhen.gridx = 0;
gbcChckbxConfirmationMessageWhen.gridy = 4;
add(chckbxConfirmClosing, gbcChckbxConfirmationMessageWhen);
GridBagConstraints gbcPanel = new GridBagConstraints();
gbcPanel.anchor = GridBagConstraints.WEST;
gbcPanel.gridwidth = 4;
gbcPanel.insets = new Insets(5, 5, 0, 10);
gbcPanel.fill = GridBagConstraints.HORIZONTAL;
gbcPanel.gridx = 0;
gbcPanel.gridy = 5;
FlowLayout flowLayout = (FlowLayout) panel.getLayout();
flowLayout.setAlignment(FlowLayout.LEADING);
add(panel, gbcPanel);
chckbxFileLog.addActionListener(e -> checkRolingLog());
panel.add(chckbxFileLog);
panel.add(horizontalStrut1);
panel.add(labelNumber);
panel.add(spinner);
panel.add(horizontalStrut2);
panel.add(labelSize);
panel.add(spinner1);
this.add(jLabelMLook, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.LINE_END,
GridBagConstraints.NONE, new Insets(7, 10, 5, 5), 0, 0));
this.add(jComboBoxlnf, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(7, 2, 5, 15), 5, -2));
GridBagConstraints gbcPanel1 = new GridBagConstraints();
gbcPanel1.gridwidth = 4;
gbcPanel1.insets = new Insets(0, 10, 5, 10);
gbcPanel1.fill = GridBagConstraints.BOTH;
gbcPanel1.gridx = 0;
gbcPanel1.gridy = 6;
FlowLayout flowLayout2 = (FlowLayout) panel1.getLayout();
flowLayout2.setAlignment(FlowLayout.LEADING);
add(panel1, gbcPanel1);
panel1.add(lblLogLevel);
JPanel panel2 = new JPanel();
FlowLayout flowLayout1 = (FlowLayout) panel2.getLayout();
flowLayout1.setHgap(10);
flowLayout1.setAlignment(FlowLayout.RIGHT);
flowLayout1.setVgap(7);
GridBagConstraints gbcPanel2 = new GridBagConstraints();
gbcPanel2.weighty = 1.0;
gbcPanel2.weightx = 1.0;
gbcPanel2.anchor = GridBagConstraints.SOUTHWEST;
gbcPanel2.gridwidth = 4;
gbcPanel2.insets = new Insets(5, 10, 0, 10);
gbcPanel2.fill = GridBagConstraints.HORIZONTAL;
gbcPanel2.gridx = 0;
gbcPanel2.gridy = 7;
add(panel2, gbcPanel2);
JButton btnNewButton = new JButton(Messages.getString("restore.values")); //$NON-NLS-1$
panel2.add(btnNewButton);
btnNewButton.addActionListener(e -> {
resetoDefaultValues();
initialize(false);
});
}
private static String getText() {
ZonedDateTime now = ZonedDateTime.now();
return String.format(Messages.getString("GeneralSetting.txtNote"), //$NON-NLS-1$
new Object[] { LocalUtil.getDateTimeFormatter(FormatStyle.SHORT).format(now),
LocalUtil.getDateTimeFormatter(FormatStyle.MEDIUM).format(now),
LocalUtil.getDateTimeFormatter(FormatStyle.LONG).format(now),
LocalUtil.getDateTimeFormatter(FormatStyle.FULL).format(now),
LocalUtil.getNumberInstance().format(2543456.3465) });
}
private void checkRolingLog() {
boolean rolling = chckbxFileLog.isSelected();
spinner.setEnabled(rolling);
spinner1.setEnabled(rolling);
}
private static int getIntPreferences(String key, int defaultvalue, String removedSuffix) {
if (key != null) {
String s = BundleTools.SYSTEM_PREFERENCES.getProperty(key);
if (s != null) {
if (removedSuffix != null) {
int index = s.lastIndexOf(removedSuffix);
if (index > 0) {
s = s.substring(0, index);
}
}
try {
return Integer.parseInt(s);
} catch (NumberFormatException ignore) {
}
}
}
return defaultvalue;
}
protected void initialize(boolean afirst) {
WProperties prfs = BundleTools.SYSTEM_PREFERENCES;
chckbxConfirmClosing.setSelected(prfs.getBooleanProperty(BundleTools.CONFIRM_CLOSE, false));
panel1.add(comboBoxLogLevel);
comboBoxLogLevel.setSelectedItem(LEVEL.getLevel(prfs.getProperty(AuditLog.LOG_LEVEL, "INFO")));//$NON-NLS-1$
panel1.add(horizontalStrut);
panel1.add(lblStacktraceLimit);
int limit = getIntPreferences(AuditLog.LOG_STACKTRACE_LIMIT, 3, null);
if (limit > 0
&& (limit != 1 || limit != 3 || limit != 5 || limit != 10 || limit != 20 || limit != 50 || limit != 100)) {
comboBoxStackLimit.addItem(Integer.toString(limit));
}
comboBoxStackLimit.setSelectedItem(limit >= 0 ? Integer.toString(limit) : "");// $NON-NLS-1$ //$NON-NLS-1$
panel1.add(comboBoxStackLimit);
chckbxFileLog.setSelected(StringUtil.hasText(prfs.getProperty(AuditLog.LOG_FILE, ""))); //$NON-NLS-1$
spinner.setValue(getIntPreferences(AuditLog.LOG_FILE_NUMBER, 5, null));
spinner1.setValue(getIntPreferences(AuditLog.LOG_FILE_SIZE, 10, "MB")); //$NON-NLS-1$
checkRolingLog();
comboBoxLang.selectLocale(prfs.getProperty("locale.lang.code")); //$NON-NLS-1$
comboBoxFormat.selectLocale();
String className = prfs.getProperty("weasis.look"); //$NON-NLS-1$
if (className == null) {
LookAndFeel currentLAF = javax.swing.UIManager.getLookAndFeel();
if (currentLAF != null) {
className = currentLAF.getClass().getName();
}
}
LookInfo oldLaf = null;
if (className != null) {
for (int i = 0; i < jComboBoxlnf.getItemCount(); i++) {
LookInfo look = jComboBoxlnf.getItemAt(i);
if (className.equals(look.getClassName())) {
oldLaf = look;
break;
}
}
}
if (oldLaf == null) {
jComboBoxlnf.setSelectedIndex(0);
oldLaf = (LookInfo) jComboBoxlnf.getSelectedItem();
} else {
jComboBoxlnf.setSelectedItem(oldLaf);
}
if (afirst) {
oldUILook = oldLaf;
}
}
public void setList(JComboBox<LookInfo> jComboBox, LookAndFeelInfo[] look) {
jComboBox.removeAllItems();
for (int i = 0; i < look.length; i++) {
jComboBox.addItem(new LookInfo(look[i].getName(), look[i].getClassName()));
}
}
@Override
public void closeAdditionalWindow() {
BundleTools.SYSTEM_PREFERENCES.putBooleanProperty("weasis.confirm.closing", chckbxConfirmClosing.isSelected()); //$NON-NLS-1$
String limit = (String) comboBoxStackLimit.getSelectedItem();
BundleTools.SYSTEM_PREFERENCES.setProperty(AuditLog.LOG_STACKTRACE_LIMIT,
StringUtil.hasText(limit) ? limit : "-1"); //$NON-NLS-1$
LEVEL level = (LEVEL) comboBoxLogLevel.getSelectedItem();
BundleTools.SYSTEM_PREFERENCES.setProperty(AuditLog.LOG_LEVEL, level.toString());
BundleTools.SYSTEM_PREFERENCES.setProperty(AuditLog.LOG_FILE_ACTIVATION,
String.valueOf(chckbxFileLog.isSelected()));
String logFile =
chckbxFileLog.isSelected() ? AppProperties.WEASIS_PATH + File.separator + "log" + File.separator //$NON-NLS-1$
+ "default.log" : ""; //$NON-NLS-1$ //$NON-NLS-2$
BundleTools.SYSTEM_PREFERENCES.setProperty(AuditLog.LOG_FILE, logFile);
String fileNb = null;
String fileSize = null;
if (chckbxFileLog.isSelected()) {
fileNb = spinner.getValue().toString();
fileSize = spinner1.getValue().toString() + "MB"; //$NON-NLS-1$
BundleTools.SYSTEM_PREFERENCES.setProperty(AuditLog.LOG_FILE_NUMBER, fileNb);
BundleTools.SYSTEM_PREFERENCES.setProperty(AuditLog.LOG_FILE_SIZE, fileSize);
}
String pattern = BundleTools.SYSTEM_PREFERENCES.getProperty(AuditLog.LOG_PATTERN,
"{0,date,dd.MM.yyyy HH:mm:ss.SSS} *{4}* [{2}] {3}: {5}"); //$NON-NLS-1$
BundleContext context = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
AuditLog.createOrUpdateLogger(context, "default.log", new String[] { "org" }, level.toString(), logFile, //$NON-NLS-1$ //$NON-NLS-2$
pattern, fileNb, fileSize, limit);
LookInfo look = (LookInfo) jComboBoxlnf.getSelectedItem();
if (look != null) {
BundleTools.SYSTEM_PREFERENCES.put("weasis.look", look.getClassName()); //$NON-NLS-1$
}
// save preferences in local file
BundleTools.saveSystemPreferences();
// Restore old laf to avoid display issues.
final String finalLafClassName = oldUILook.getClassName();
LookAndFeel currentLAF = javax.swing.UIManager.getLookAndFeel();
if (currentLAF != null && !finalLafClassName.equals(currentLAF.getClass().getName())) {
Runnable runnable = () -> {
try {
WinUtil.getParentDialog(GeneralSetting.this).setVisible(false);
UIManager.setLookAndFeel(finalLafClassName);
for (Window window : Window.getWindows()) {
SwingUtilities.updateComponentTreeUI(window);
}
} catch (Exception e) {
LOGGER.error("Can't change look and feel", e); //$NON-NLS-1$
}
};
GuiExecutor.instance().execute(runnable);
}
}
@Override
public void resetoDefaultValues() {
BundleTools.SYSTEM_PREFERENCES.resetProperty(BundleTools.CONFIRM_CLOSE, "false");//$NON-NLS-1$
// Reset properties used by OSGI service (Sling Logger)
BundleTools.SYSTEM_PREFERENCES.resetServiceProperty(AuditLog.LOG_STACKTRACE_LIMIT, "3"); //$NON-NLS-1$
BundleTools.SYSTEM_PREFERENCES.resetServiceProperty(AuditLog.LOG_LEVEL, "INFO"); //$NON-NLS-1$
BundleTools.SYSTEM_PREFERENCES.resetServiceProperty(AuditLog.LOG_FILE, ""); //$NON-NLS-1$
BundleTools.SYSTEM_PREFERENCES.resetServiceProperty(AuditLog.LOG_FILE_NUMBER, "5"); //$NON-NLS-1$
BundleTools.SYSTEM_PREFERENCES.resetServiceProperty(AuditLog.LOG_FILE_SIZE, "10MB"); //$NON-NLS-1$
BundleTools.SYSTEM_PREFERENCES.resetProperty("locale.lang.code", "en"); //$NON-NLS-1$ //$NON-NLS-2$
// Reset cache of locale format
LocalUtil.setLocaleFormat(null);
// Reset format to the config.properties value or null (default system value)
BundleTools.SYSTEM_PREFERENCES.resetProperty("locale.format.code", null);//$NON-NLS-1$
BundleTools.SYSTEM_PREFERENCES.resetProperty("weasis.look", null); //$NON-NLS-1$
}
static class LookInfo {
private final String name;
private final String className;
public LookInfo(String name, String className) {
this.name = name;
this.className = className;
}
public String getName() {
return name;
}
public String getClassName() {
return className;
}
@Override
public String toString() {
return name;
}
}
public static String setLookAndFeel(String look) {
// Do not display metal LAF in bold, it is ugly
UIManager.put("swing.boldMetal", Boolean.FALSE); //$NON-NLS-1$
// Display slider value is set to false (already in all LAF by the panel title), used by GTK LAF
UIManager.put("Slider.paintValue", Boolean.FALSE); //$NON-NLS-1$
String laf = getAvailableLookAndFeel(look);
try {
UIManager.setLookAndFeel(laf);
} catch (Exception e) {
laf = UIManager.getSystemLookAndFeelClassName();
LOGGER.error("Unable to set the Look&Feel", e); //$NON-NLS-1$
}
// Fix font issue for displaying some Asiatic characters. Some L&F have special fonts.
setUIFont(new javax.swing.plaf.FontUIResource("SansSerif", Font.PLAIN, 12)); //$NON-NLS-1$
return laf;
}
public static String getAvailableLookAndFeel(String look) {
UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
String laf = null;
if (look != null) {
for (int i = 0, n = lafs.length; i < n; i++) {
if (lafs[i].getClassName().equals(look)) {
laf = look;
break;
}
}
}
if (laf == null) {
if (AppProperties.OPERATING_SYSTEM.startsWith("mac")) { //$NON-NLS-1$
laf = "com.apple.laf.AquaLookAndFeel"; //$NON-NLS-1$
} else {
// Try to set Nimbus, concurrent thread issue
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6785663
for (int i = 0, n = lafs.length; i < n; i++) {
if ("Nimbus".equals(lafs[i].getName())) { //$NON-NLS-1$
laf = lafs[i].getClassName();
break;
}
}
}
// Should never happen
if (laf == null) {
laf = UIManager.getSystemLookAndFeelClassName();
}
}
return laf;
}
public static void setUIFont(javax.swing.plaf.FontUIResource font) {
Enumeration<Object> keys = UIManager.getDefaults().keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
if (UIManager.get(key) instanceof javax.swing.plaf.FontUIResource) {
UIManager.put(key, font);
}
}
}
}