mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-08 06:50:56 +03:00
System File Chooser: added "approve" callback to SystemFileChooser
This commit is contained in:
@@ -25,6 +25,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -81,6 +82,7 @@ import com.formdev.flatlaf.ui.FlatNativeWindowsLibrary;
|
|||||||
* as first item and selects it by default.
|
* as first item and selects it by default.
|
||||||
* Use {@code chooser.addChoosableFileFilter( chooser.getAcceptAllFileFilter() )}
|
* Use {@code chooser.addChoosableFileFilter( chooser.getAcceptAllFileFilter() )}
|
||||||
* to place <b>All Files</b> filter somewhere else.
|
* to place <b>All Files</b> filter somewhere else.
|
||||||
|
* <li>Accessory components are not supported.
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -131,6 +133,9 @@ public class SystemFileChooser
|
|||||||
*/
|
*/
|
||||||
private boolean keepAcceptAllAtEnd = true;
|
private boolean keepAcceptAllAtEnd = true;
|
||||||
|
|
||||||
|
private ApproveCallback approveCallback;
|
||||||
|
private int approveResult = APPROVE_OPTION;
|
||||||
|
|
||||||
/** @see JFileChooser#JFileChooser() */
|
/** @see JFileChooser#JFileChooser() */
|
||||||
public SystemFileChooser() {
|
public SystemFileChooser() {
|
||||||
this( (File) null );
|
this( (File) null );
|
||||||
@@ -407,10 +412,71 @@ public class SystemFileChooser
|
|||||||
return filters.size() == 1 && filters.get( 0 ) == getAcceptAllFileFilter();
|
return filters.size() == 1 && filters.get( 0 ) == getAcceptAllFileFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ApproveCallback getApproveCallback() {
|
||||||
|
return approveCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a callback that is invoked when user presses "OK" button (or double-clicks a file).
|
||||||
|
* The file dialog is still open.
|
||||||
|
* If the callback returns {@link #CANCEL_OPTION}, then the file dialog stays open.
|
||||||
|
* If it returns {@link #APPROVE_OPTION} (or any other value other than {@link #CANCEL_OPTION}),
|
||||||
|
* the file dialog is closed and the {@code show...Dialog()} methods return that value.
|
||||||
|
* <p>
|
||||||
|
* The callback has two parameters:
|
||||||
|
* <ul>
|
||||||
|
* <li>{@code File[] selectedFiles} - one or more selected files
|
||||||
|
* <li>{@code ApproveContext context} - context object that provides additional methods
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* chooser.setApproveCallback( (selectedFiles, context) -> {
|
||||||
|
* // do something
|
||||||
|
* return SystemFileChooser.APPROVE_OPTION; // or SystemFileChooser.CANCEL_OPTION
|
||||||
|
* } );
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* or
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* chooser.setApproveCallback( this::approveCallback );
|
||||||
|
*
|
||||||
|
* ...
|
||||||
|
*
|
||||||
|
* private boolean approveCallback( File[] selectedFiles, ApproveContext context ) {
|
||||||
|
* // do something
|
||||||
|
* return SystemFileChooser.APPROVE_OPTION; // or SystemFileChooser.CANCEL_OPTION
|
||||||
|
* }
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* <b>WARNING:</b> Do not show a Swing dialog for the callback. This will not work!
|
||||||
|
* <p>
|
||||||
|
* Instead use {@link ApproveContext#showMessageDialog(int, String, String, int, String...)},
|
||||||
|
* which shows a modal system message dialog as child of the file dialog.
|
||||||
|
*
|
||||||
|
* <pre>{@code
|
||||||
|
* chooser.setApproveCallback( (selectedFiles, context) -> {
|
||||||
|
* if( !selectedFiles[0].getName().startsWith( "blabla" ) ) {
|
||||||
|
* context.showMessageDialog( JOptionPane.WARNING_MESSAGE,
|
||||||
|
* "File name must start with 'blabla' :)", null, 0 );
|
||||||
|
* return SystemFileChooser.CANCEL_OPTION;
|
||||||
|
* }
|
||||||
|
* return SystemFileChooser.APPROVE_OPTION;
|
||||||
|
* } );
|
||||||
|
* }</pre>
|
||||||
|
*
|
||||||
|
* @see ApproveContext
|
||||||
|
* @see JFileChooser#approveSelection()
|
||||||
|
*/
|
||||||
|
public void setApproveCallback( ApproveCallback approveCallback ) {
|
||||||
|
this.approveCallback = approveCallback;
|
||||||
|
}
|
||||||
|
|
||||||
private int showDialogImpl( Component parent ) {
|
private int showDialogImpl( Component parent ) {
|
||||||
|
approveResult = APPROVE_OPTION;
|
||||||
File[] files = getProvider().showDialog( parent, this );
|
File[] files = getProvider().showDialog( parent, this );
|
||||||
setSelectedFiles( files );
|
setSelectedFiles( files );
|
||||||
return (files != null) ? APPROVE_OPTION : CANCEL_OPTION;
|
return (files != null) ? approveResult : CANCEL_OPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
private FileChooserProvider getProvider() {
|
private FileChooserProvider getProvider() {
|
||||||
@@ -464,14 +530,31 @@ public class SystemFileChooser
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
// convert file names to file objects
|
// convert file names to file objects
|
||||||
|
return filenames2files( filenames );
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract String[] showSystemDialog( Window owner, SystemFileChooser fc );
|
||||||
|
|
||||||
|
boolean invokeApproveCallback( SystemFileChooser fc, String[] files, ApproveContext context ) {
|
||||||
|
if( files == null || files.length == 0 )
|
||||||
|
return false; // should never happen
|
||||||
|
|
||||||
|
ApproveCallback approveCallback = fc.getApproveCallback();
|
||||||
|
int result = approveCallback.approve( filenames2files( files ), context );
|
||||||
|
if( result == CANCEL_OPTION )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
fc.approveResult = result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File[] filenames2files( String[] filenames ) {
|
||||||
FileSystemView fsv = FileSystemView.getFileSystemView();
|
FileSystemView fsv = FileSystemView.getFileSystemView();
|
||||||
File[] files = new File[filenames.length];
|
File[] files = new File[filenames.length];
|
||||||
for( int i = 0; i < filenames.length; i++ )
|
for( int i = 0; i < filenames.length; i++ )
|
||||||
files[i] = fsv.createFileObject( filenames[i] );
|
files[i] = fsv.createFileObject( filenames[i] );
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract String[] showSystemDialog( Window owner, SystemFileChooser fc );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class WindowsFileChooserProvider -----------------------------------
|
//---- class WindowsFileChooserProvider -----------------------------------
|
||||||
@@ -549,12 +632,50 @@ public class SystemFileChooser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// callback
|
||||||
|
FlatNativeWindowsLibrary.FileChooserCallback callback = (fc.getApproveCallback() != null)
|
||||||
|
? (files, hwndFileDialog) -> {
|
||||||
|
return invokeApproveCallback( fc, files, new WindowsApproveContext( hwndFileDialog ) );
|
||||||
|
} : null;
|
||||||
|
|
||||||
// show system file dialog
|
// show system file dialog
|
||||||
return FlatNativeWindowsLibrary.showFileChooser( owner, open,
|
return FlatNativeWindowsLibrary.showFileChooser( owner, open,
|
||||||
fc.getDialogTitle(), approveButtonText, null, fileName,
|
fc.getDialogTitle(), approveButtonText, null, fileName,
|
||||||
folder, saveAsItem, null, null, optionsSet, optionsClear, null,
|
folder, saveAsItem, null, null, optionsSet, optionsClear, callback,
|
||||||
fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) );
|
fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class WindowsApproveContext ----
|
||||||
|
|
||||||
|
private static class WindowsApproveContext
|
||||||
|
extends ApproveContext
|
||||||
|
{
|
||||||
|
private final long hwndFileDialog;
|
||||||
|
|
||||||
|
WindowsApproveContext( long hwndFileDialog ) {
|
||||||
|
this.hwndFileDialog = hwndFileDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int showMessageDialog( int messageType, String primaryText,
|
||||||
|
String secondaryText, int defaultButton, String... buttons )
|
||||||
|
{
|
||||||
|
// concat primary and secondary texts
|
||||||
|
if( secondaryText != null )
|
||||||
|
primaryText = primaryText + "\n\n" + secondaryText;
|
||||||
|
|
||||||
|
// button menmonics ("&" -> "&&", "__" -> "_", "_" -> "&")
|
||||||
|
for( int i = 0; i < buttons.length; i++ )
|
||||||
|
buttons[i] = buttons[i].replace( "&", "&&" ).replace( "__", "\u0001" ).replace( '_', '&' ).replace( '\u0001', '_' );
|
||||||
|
|
||||||
|
// use "OK" button if no buttons given
|
||||||
|
if( buttons.length == 0 )
|
||||||
|
buttons = new String[] { UIManager.getString( "OptionPane.okButtonText", Locale.getDefault() ) };
|
||||||
|
|
||||||
|
return FlatNativeWindowsLibrary.showMessageDialog( hwndFileDialog,
|
||||||
|
messageType, null, primaryText, defaultButton, buttons );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class MacFileChooserProvider ---------------------------------------
|
//---- class MacFileChooserProvider ---------------------------------------
|
||||||
@@ -613,12 +734,42 @@ public class SystemFileChooser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// callback
|
||||||
|
FlatNativeMacLibrary.FileChooserCallback callback = (fc.getApproveCallback() != null)
|
||||||
|
? (files, hwndFileDialog) -> {
|
||||||
|
return invokeApproveCallback( fc, files, new MacApproveContext( hwndFileDialog ) );
|
||||||
|
} : null;
|
||||||
|
|
||||||
// show system file dialog
|
// show system file dialog
|
||||||
return FlatNativeMacLibrary.showFileChooser( open,
|
return FlatNativeMacLibrary.showFileChooser( open,
|
||||||
fc.getDialogTitle(), fc.getApproveButtonText(), null, null, null,
|
fc.getDialogTitle(), fc.getApproveButtonText(), null, null, null,
|
||||||
nameFieldStringValue, directoryURL, optionsSet, optionsClear, null,
|
nameFieldStringValue, directoryURL, optionsSet, optionsClear, callback,
|
||||||
fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) );
|
fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class MacApproveContext ----
|
||||||
|
|
||||||
|
private static class MacApproveContext
|
||||||
|
extends ApproveContext
|
||||||
|
{
|
||||||
|
private final long hwndFileDialog;
|
||||||
|
|
||||||
|
MacApproveContext( long hwndFileDialog ) {
|
||||||
|
this.hwndFileDialog = hwndFileDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int showMessageDialog( int messageType, String primaryText,
|
||||||
|
String secondaryText, int defaultButton, String... buttons )
|
||||||
|
{
|
||||||
|
// remove button menmonics ("__" -> "_", "_" -> "")
|
||||||
|
for( int i = 0; i < buttons.length; i++ )
|
||||||
|
buttons[i] = buttons[i].replace( "__", "\u0001" ).replace( "_", "" ).replace( "\u0001", "_" );
|
||||||
|
|
||||||
|
return FlatNativeMacLibrary.showMessageDialog( hwndFileDialog,
|
||||||
|
messageType, primaryText, secondaryText, defaultButton, buttons );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class LinuxFileChooserProvider -------------------------------------
|
//---- class LinuxFileChooserProvider -------------------------------------
|
||||||
@@ -690,10 +841,17 @@ public class SystemFileChooser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// callback
|
||||||
|
FlatNativeLinuxLibrary.FileChooserCallback callback = (fc.getApproveCallback() != null)
|
||||||
|
? (files, hwndFileDialog) -> {
|
||||||
|
return invokeApproveCallback( fc, files, new LinuxApproveContext( hwndFileDialog ) );
|
||||||
|
} : null;
|
||||||
|
|
||||||
// show system file dialog
|
// show system file dialog
|
||||||
return FlatNativeLinuxLibrary.showFileChooser( owner, open,
|
return FlatNativeLinuxLibrary.showFileChooser( owner, open,
|
||||||
fc.getDialogTitle(), approveButtonText, currentName, currentFolder,
|
fc.getDialogTitle(), approveButtonText, currentName, currentFolder,
|
||||||
optionsSet, optionsClear, null, fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) );
|
optionsSet, optionsClear, callback,
|
||||||
|
fileTypeIndex, fileTypes.toArray( new String[fileTypes.size()] ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
private String caseInsensitiveGlobPattern( String ext ) {
|
private String caseInsensitiveGlobPattern( String ext ) {
|
||||||
@@ -712,6 +870,26 @@ public class SystemFileChooser
|
|||||||
}
|
}
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class LinuxApproveContext ----
|
||||||
|
|
||||||
|
private static class LinuxApproveContext
|
||||||
|
extends ApproveContext
|
||||||
|
{
|
||||||
|
private final long hwndFileDialog;
|
||||||
|
|
||||||
|
LinuxApproveContext( long hwndFileDialog ) {
|
||||||
|
this.hwndFileDialog = hwndFileDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int showMessageDialog( int messageType, String primaryText,
|
||||||
|
String secondaryText, int defaultButton, String... buttons )
|
||||||
|
{
|
||||||
|
return FlatNativeLinuxLibrary.showMessageDialog( hwndFileDialog,
|
||||||
|
messageType, primaryText, secondaryText, defaultButton, buttons );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class SwingFileChooserProvider -------------------------------------
|
//---- class SwingFileChooserProvider -------------------------------------
|
||||||
@@ -727,6 +905,8 @@ public class SystemFileChooser
|
|||||||
File[] files = isMultiSelectionEnabled()
|
File[] files = isMultiSelectionEnabled()
|
||||||
? getSelectedFiles()
|
? getSelectedFiles()
|
||||||
: new File[] { getSelectedFile() };
|
: new File[] { getSelectedFile() };
|
||||||
|
if( files == null || files.length == 0 )
|
||||||
|
return; // should never happen
|
||||||
|
|
||||||
if( getDialogType() == OPEN_DIALOG || isDirectorySelectionEnabled() ) {
|
if( getDialogType() == OPEN_DIALOG || isDirectorySelectionEnabled() ) {
|
||||||
if( !checkMustExist( this, files ) )
|
if( !checkMustExist( this, files ) )
|
||||||
@@ -735,6 +915,17 @@ public class SystemFileChooser
|
|||||||
if( !checkOverwrite( this, files ) )
|
if( !checkOverwrite( this, files ) )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// callback
|
||||||
|
ApproveCallback approveCallback = fc.getApproveCallback();
|
||||||
|
if( approveCallback != null ) {
|
||||||
|
int result = approveCallback.approve( files, new SwingApproveContext( this ) );
|
||||||
|
if( result == CANCEL_OPTION )
|
||||||
|
return;
|
||||||
|
|
||||||
|
fc.approveResult = result;
|
||||||
|
}
|
||||||
|
|
||||||
super.approveSelection();
|
super.approveSelection();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -831,6 +1022,47 @@ public class SystemFileChooser
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class SwingApproveContext ----
|
||||||
|
|
||||||
|
private static class SwingApproveContext
|
||||||
|
extends ApproveContext
|
||||||
|
{
|
||||||
|
private final JFileChooser chooser;
|
||||||
|
|
||||||
|
SwingApproveContext( JFileChooser chooser ) {
|
||||||
|
this.chooser = chooser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int showMessageDialog( int messageType, String primaryText,
|
||||||
|
String secondaryText, int defaultButton, String... buttons )
|
||||||
|
{
|
||||||
|
// title
|
||||||
|
String title = chooser.getDialogTitle();
|
||||||
|
if( title == null ) {
|
||||||
|
Window window = SwingUtilities.windowForComponent( chooser );
|
||||||
|
if( window instanceof JDialog )
|
||||||
|
title = ((JDialog)window).getTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// concat primary and secondary texts
|
||||||
|
if( secondaryText != null )
|
||||||
|
primaryText = primaryText + "\n\n" + secondaryText;
|
||||||
|
|
||||||
|
// remove button menmonics ("__" -> "_", "_" -> "")
|
||||||
|
for( int i = 0; i < buttons.length; i++ )
|
||||||
|
buttons[i] = buttons[i].replace( "__", "\u0001" ).replace( "_", "" ).replace( "\u0001", "_" );
|
||||||
|
|
||||||
|
// use "OK" button if no buttons given
|
||||||
|
if( buttons.length == 0 )
|
||||||
|
buttons = new String[] { UIManager.getString( "OptionPane.okButtonText", Locale.getDefault() ) };
|
||||||
|
|
||||||
|
return JOptionPane.showOptionDialog( chooser,
|
||||||
|
primaryText, title, JOptionPane.YES_NO_OPTION, messageType,
|
||||||
|
null, buttons, buttons[Math.min( Math.max( defaultButton, 0 ), buttons.length - 1 )] );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FileFilter ---------------------------------------------------
|
//---- class FileFilter ---------------------------------------------------
|
||||||
@@ -892,4 +1124,41 @@ public class SystemFileChooser
|
|||||||
return UIManager.getString( "FileChooser.acceptAllFileFilterText" );
|
return UIManager.getString( "FileChooser.acceptAllFileFilterText" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class ApproveCallback ----------------------------------------------
|
||||||
|
|
||||||
|
public interface ApproveCallback {
|
||||||
|
/**
|
||||||
|
* @param selectedFiles one or more selected files
|
||||||
|
* @param context context object that provides additional methods
|
||||||
|
* @return If the callback returns {@link #CANCEL_OPTION}, then the file dialog stays open.
|
||||||
|
* If it returns {@link #APPROVE_OPTION} (or any other value other than {@link #CANCEL_OPTION}),
|
||||||
|
* the file dialog is closed and the {@code show...Dialog()} methods return that value.
|
||||||
|
*/
|
||||||
|
int approve( File[] selectedFiles, ApproveContext context );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class ApproveContext -----------------------------------------------
|
||||||
|
|
||||||
|
public static abstract class ApproveContext {
|
||||||
|
/**
|
||||||
|
* Shows a modal (operating system) message dialog as child of the system file chooser.
|
||||||
|
* <p>
|
||||||
|
* Use this instead of {@link JOptionPane} in approve callbacks.
|
||||||
|
*
|
||||||
|
* @param messageType type of message being displayed:
|
||||||
|
* {@link JOptionPane#ERROR_MESSAGE}, {@link JOptionPane#INFORMATION_MESSAGE},
|
||||||
|
* {@link JOptionPane#WARNING_MESSAGE}, {@link JOptionPane#QUESTION_MESSAGE} or
|
||||||
|
* {@link JOptionPane#PLAIN_MESSAGE}
|
||||||
|
* @param primaryText primary text
|
||||||
|
* @param secondaryText secondary text; shown below of primary text; or {@code null}
|
||||||
|
* @param defaultButton index of the default button, which can be pressed using ENTER key
|
||||||
|
* @param buttons texts of the buttons; if no buttons given the a default "OK" button is shown.
|
||||||
|
* Use '_' for mnemonics (e.g. "_Choose")
|
||||||
|
* Use '__' for '_' character (e.g. "Choose__and__Quit").
|
||||||
|
* @return index of pressed button; or -1 for ESC key
|
||||||
|
*/
|
||||||
|
public abstract int showMessageDialog( int messageType, String primaryText,
|
||||||
|
String secondaryText, int defaultButton, String... buttons );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ import com.formdev.flatlaf.themes.FlatMacDarkLaf;
|
|||||||
import com.formdev.flatlaf.themes.FlatMacLightLaf;
|
import com.formdev.flatlaf.themes.FlatMacLightLaf;
|
||||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
import com.formdev.flatlaf.util.StringUtils;
|
import com.formdev.flatlaf.util.StringUtils;
|
||||||
|
import com.formdev.flatlaf.util.SystemFileChooser;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
@@ -96,6 +97,8 @@ class FlatThemeFileEditor
|
|||||||
private static final String KEY_SHOW_RGB_COLORS = "showRgbColors";
|
private static final String KEY_SHOW_RGB_COLORS = "showRgbColors";
|
||||||
private static final String KEY_SHOW_COLOR_LUMA = "showColorLuma";
|
private static final String KEY_SHOW_COLOR_LUMA = "showColorLuma";
|
||||||
|
|
||||||
|
private static final int NEW_PROPERTIES_FILE_OPTION = 100;
|
||||||
|
|
||||||
private File dir;
|
private File dir;
|
||||||
private Preferences state;
|
private Preferences state;
|
||||||
private boolean inLoadDirectory;
|
private boolean inLoadDirectory;
|
||||||
@@ -227,48 +230,45 @@ class FlatThemeFileEditor
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// choose directory
|
// choose directory
|
||||||
JFileChooser chooser = new JFileChooser( dir ) {
|
SystemFileChooser chooser = new SystemFileChooser( dir );
|
||||||
@Override
|
chooser.setFileSelectionMode( SystemFileChooser.DIRECTORIES_ONLY );
|
||||||
public void approveSelection() {
|
chooser.setApproveCallback( this::checkDirectory );
|
||||||
if( !checkDirectory( this, getSelectedFile() ) )
|
int result = chooser.showOpenDialog( this );
|
||||||
return;
|
if( result == SystemFileChooser.CANCEL_OPTION )
|
||||||
|
|
||||||
super.approveSelection();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
chooser.setFileSelectionMode( JFileChooser.DIRECTORIES_ONLY );
|
|
||||||
if( chooser.showOpenDialog( this ) != JFileChooser.APPROVE_OPTION )
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
File selectedFile = chooser.getSelectedFile();
|
File selectedFile = chooser.getSelectedFile();
|
||||||
if( selectedFile == null || selectedFile.equals( dir ) )
|
if( selectedFile == null || selectedFile.equals( dir ) )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if( result == NEW_PROPERTIES_FILE_OPTION ) {
|
||||||
|
if( !newPropertiesFile( selectedFile ) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// open new directory
|
// open new directory
|
||||||
loadDirectory( selectedFile );
|
loadDirectory( selectedFile );
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkDirectory( Component parentComponent, File dir ) {
|
private int checkDirectory( File[] selectedFiles, SystemFileChooser.ApproveContext context ) {
|
||||||
|
File dir = selectedFiles[0];
|
||||||
if( !dir.isDirectory() ) {
|
if( !dir.isDirectory() ) {
|
||||||
JOptionPane.showMessageDialog( parentComponent,
|
showMessageDialog( context, "Directory '" + dir + "' does not exist.", null );
|
||||||
"Directory '" + dir + "' does not exist.",
|
return SystemFileChooser.CANCEL_OPTION;
|
||||||
getTitle(), JOptionPane.INFORMATION_MESSAGE );
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( getPropertiesFiles( dir ).length == 0 ) {
|
if( getPropertiesFiles( dir ).length == 0 ) {
|
||||||
UIManager.put( "OptionPane.sameSizeButtons", false );
|
UIManager.put( "OptionPane.sameSizeButtons", false );
|
||||||
int result = JOptionPane.showOptionDialog( parentComponent,
|
int result = showMessageDialog( context,
|
||||||
"Directory '" + dir + "' does not contain properties files.\n\n"
|
"Directory '" + dir + "' does not contain properties files.",
|
||||||
+ "Do you want create a new theme in this directory?\n\n"
|
"Do you want create a new theme in this directory?\n\n"
|
||||||
+ "Or do you want modify/extend core themes and create empty"
|
+ "Or do you want modify/extend core themes and create empty"
|
||||||
+ " 'FlatLightLaf.properties' and 'FlatDarkLaf.properties' files in this directory?",
|
+ " 'FlatLightLaf.properties' and 'FlatDarkLaf.properties' files in this directory?",
|
||||||
getTitle(), JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null,
|
"_New Theme", "_Modify Core Themes", "_Cancel" );
|
||||||
new Object[] { "New Theme", "Modify Core Themes", "Cancel" }, null );
|
|
||||||
UIManager.put( "OptionPane.sameSizeButtons", null );
|
UIManager.put( "OptionPane.sameSizeButtons", null );
|
||||||
|
|
||||||
if( result == 0 )
|
if( result == 0 )
|
||||||
return newPropertiesFile( dir );
|
return NEW_PROPERTIES_FILE_OPTION;
|
||||||
else if( result == 1 ) {
|
else if( result == 1 ) {
|
||||||
try {
|
try {
|
||||||
String content =
|
String content =
|
||||||
@@ -280,18 +280,37 @@ class FlatThemeFileEditor
|
|||||||
"\n";
|
"\n";
|
||||||
writeFile( new File( dir, "FlatLightLaf.properties" ), content );
|
writeFile( new File( dir, "FlatLightLaf.properties" ), content );
|
||||||
writeFile( new File( dir, "FlatDarkLaf.properties" ), content );
|
writeFile( new File( dir, "FlatDarkLaf.properties" ), content );
|
||||||
return true;
|
return SystemFileChooser.APPROVE_OPTION;
|
||||||
} catch( IOException ex ) {
|
} catch( IOException ex ) {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
|
|
||||||
JOptionPane.showMessageDialog( parentComponent,
|
showMessageDialog( context,
|
||||||
"Failed to create 'FlatLightLaf.properties' or 'FlatDarkLaf.properties'." );
|
"Failed to create 'FlatLightLaf.properties' or 'FlatDarkLaf.properties'.", null );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return SystemFileChooser.CANCEL_OPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return SystemFileChooser.APPROVE_OPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int showMessageDialog( SystemFileChooser.ApproveContext context,
|
||||||
|
String primaryText, String secondaryText, String... buttons )
|
||||||
|
{
|
||||||
|
if( context != null ) {
|
||||||
|
// invoked from SystemFileChooser
|
||||||
|
return context.showMessageDialog( JOptionPane.INFORMATION_MESSAGE,
|
||||||
|
primaryText, secondaryText, 0, buttons );
|
||||||
|
} else {
|
||||||
|
// invoked from directoryChanged()
|
||||||
|
if( secondaryText != null )
|
||||||
|
primaryText = primaryText + "\n\n" + secondaryText;
|
||||||
|
for( int i = 0; i < buttons.length; i++ )
|
||||||
|
buttons[i] = buttons[i].replace( "_", "" );
|
||||||
|
return JOptionPane.showOptionDialog( this, primaryText, getTitle(),
|
||||||
|
JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null,
|
||||||
|
(buttons.length > 0) ? buttons : null, null );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void directoryChanged() {
|
private void directoryChanged() {
|
||||||
@@ -302,7 +321,15 @@ class FlatThemeFileEditor
|
|||||||
if( dir == null )
|
if( dir == null )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( checkDirectory( this, dir ) )
|
directoryField.hidePopup();
|
||||||
|
|
||||||
|
int result = checkDirectory( new File[] { dir }, null );
|
||||||
|
if( result == NEW_PROPERTIES_FILE_OPTION ) {
|
||||||
|
if( !newPropertiesFile( dir ) )
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( result != SystemFileChooser.CANCEL_OPTION )
|
||||||
loadDirectory( dir );
|
loadDirectory( dir );
|
||||||
else {
|
else {
|
||||||
// remove from directories history
|
// remove from directories history
|
||||||
@@ -390,6 +417,9 @@ class FlatThemeFileEditor
|
|||||||
File[] propertiesFiles = dir.listFiles( (d, name) -> {
|
File[] propertiesFiles = dir.listFiles( (d, name) -> {
|
||||||
return name.endsWith( ".properties" );
|
return name.endsWith( ".properties" );
|
||||||
} );
|
} );
|
||||||
|
if( propertiesFiles == null )
|
||||||
|
propertiesFiles = new File[0];
|
||||||
|
|
||||||
Arrays.sort( propertiesFiles, (f1, f2) -> {
|
Arrays.sort( propertiesFiles, (f1, f2) -> {
|
||||||
String n1 = toSortName( f1.getName() );
|
String n1 = toSortName( f1.getName() );
|
||||||
String n2 = toSortName( f2.getName() );
|
String n2 = toSortName( f2.getName() );
|
||||||
|
|||||||
Reference in New Issue
Block a user