mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 14:00:55 +03:00
Compare commits
41 Commits
0d4946230e
...
bdb7438672
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdb7438672 | ||
|
|
299250a710 | ||
|
|
1e2a75a19c | ||
|
|
1eee35035d | ||
|
|
5c2d8ba555 | ||
|
|
0f27125107 | ||
|
|
f2882370de | ||
|
|
6715886b24 | ||
|
|
35e86ba772 | ||
|
|
dade1cba5a | ||
|
|
3e8b213367 | ||
|
|
202a0d159b | ||
|
|
5d247f6269 | ||
|
|
d81bcd5254 | ||
|
|
03e5f8623e | ||
|
|
54d6959533 | ||
|
|
112116556d | ||
|
|
3283cfe22f | ||
|
|
aecb496142 | ||
|
|
1e3e4d7c61 | ||
|
|
b808f6e803 | ||
|
|
f3ca3a001a | ||
|
|
d524536575 | ||
|
|
0a4c01cd40 | ||
|
|
d513ec497b | ||
|
|
07fc190b5f | ||
|
|
078e59a443 | ||
|
|
d49282dfe8 | ||
|
|
c73fd51704 | ||
|
|
251198c66d | ||
|
|
d7462bd424 | ||
|
|
9af7f95197 | ||
|
|
2e16ded5d4 | ||
|
|
91e8d04a9f | ||
|
|
9453d55abd | ||
|
|
641fada6c4 | ||
|
|
a303cd2dec | ||
|
|
2b810addd8 | ||
|
|
63272a03cf | ||
|
|
49a0a83eca | ||
|
|
516bd80702 |
79
.github/workflows/natives.yml
vendored
79
.github/workflows/natives.yml
vendored
@@ -33,13 +33,30 @@ jobs:
|
|||||||
|
|
||||||
- uses: gradle/actions/wrapper-validation@v4
|
- uses: gradle/actions/wrapper-validation@v4
|
||||||
|
|
||||||
- name: install libxt-dev
|
- name: apt update (Linux)
|
||||||
if: matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-24.04-arm'
|
if: matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-24.04-arm'
|
||||||
run: sudo apt install libxt-dev
|
run: sudo apt-get update
|
||||||
|
|
||||||
- name: install g++-aarch64-linux-gnu
|
- name: install libxt-dev and libgtk-3-dev (Linux)
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-24.04-arm'
|
||||||
run: sudo apt install g++-aarch64-linux-gnu
|
run: sudo apt-get install libxt-dev libgtk-3-dev
|
||||||
|
|
||||||
|
# - name: Download libgtk-3.so for arm64 (Linux)
|
||||||
|
# if: matrix.os == 'ubuntu-latest'
|
||||||
|
# working-directory: flatlaf-natives/flatlaf-natives-linux/lib/aarch64
|
||||||
|
# run: |
|
||||||
|
# pwd
|
||||||
|
# ls -l /usr/lib/x86_64-linux-gnu/libgtk*
|
||||||
|
# wget --no-verbose https://ports.ubuntu.com/pool/main/g/gtk%2b3.0/libgtk-3-0_3.24.18-1ubuntu1_arm64.deb
|
||||||
|
# ls -l
|
||||||
|
# ar -x libgtk-3-0_3.24.18-1ubuntu1_arm64.deb data.tar.xz
|
||||||
|
# tar -xvf data.tar.xz --wildcards --to-stdout "./usr/lib/aarch64-linux-gnu/libgtk-3.so.0.*" > libgtk-3.so
|
||||||
|
# rm libgtk-3-0_3.24.18-1ubuntu1_arm64.deb data.tar.xz
|
||||||
|
# ls -l
|
||||||
|
|
||||||
|
# - name: install g++-aarch64-linux-gnu (Linux)
|
||||||
|
# if: matrix.os == 'ubuntu-latest'
|
||||||
|
# run: sudo apt-get install g++-aarch64-linux-gnu
|
||||||
|
|
||||||
- name: Setup Java 11
|
- name: Setup Java 11
|
||||||
uses: actions/setup-java@v4
|
uses: actions/setup-java@v4
|
||||||
@@ -53,10 +70,60 @@ jobs:
|
|||||||
# tar.exe: Couldn't open ~/.gradle/caches/modules-2/modules-2.lock: Permission denied
|
# tar.exe: Couldn't open ~/.gradle/caches/modules-2/modules-2.lock: Permission denied
|
||||||
run: ./gradlew build-natives --no-daemon
|
run: ./gradlew build-natives --no-daemon
|
||||||
|
|
||||||
|
- name: Sign Windows DLLs
|
||||||
|
if: matrix.os == 'windows-latest'
|
||||||
|
uses: skymatic/code-sign-action@v3
|
||||||
|
with:
|
||||||
|
certificate: '${{ secrets.CODE_SIGN_CERT_BASE64 }}'
|
||||||
|
password: '${{ secrets.CODE_SIGN_CERT_PASSWORD }}'
|
||||||
|
certificatesha1: '${{ secrets.CODE_SIGN_CERT_SHA1 }}'
|
||||||
|
folder: 'flatlaf-core/src/main/resources/com/formdev/flatlaf/natives'
|
||||||
|
|
||||||
|
- name: Sign macOS natives
|
||||||
|
if: matrix.os == 'DISABLED--macos-latest'
|
||||||
|
env:
|
||||||
|
CERT_BASE64: ${{ secrets.CODE_SIGN_CERT_BASE64 }}
|
||||||
|
CERT_PASSWORD: ${{ secrets.CODE_SIGN_CERT_PASSWORD }}
|
||||||
|
CERT_IDENTITY: ${{ secrets.CODE_SIGN_CERT_IDENTITY }}
|
||||||
|
run: |
|
||||||
|
# https://docs.github.com/en/actions/use-cases-and-examples/deploying/installing-an-apple-certificate-on-macos-runners-for-xcode-development
|
||||||
|
# create variables
|
||||||
|
CERTIFICATE_PATH=$RUNNER_TEMP/cert.p12
|
||||||
|
KEYCHAIN_PATH=$RUNNER_TEMP/signing.keychain-db
|
||||||
|
KEYCHAIN_PASSWORD=$CERT_PASSWORD
|
||||||
|
# decode certificate
|
||||||
|
printenv CERT_BASE64 | base64 --decode > $CERTIFICATE_PATH
|
||||||
|
# create temporary keychain
|
||||||
|
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||||
|
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||||||
|
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||||
|
# import certificate to keychain
|
||||||
|
security import $CERTIFICATE_PATH -P "$CERT_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||||||
|
# set partition list (required for codesign)
|
||||||
|
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||||||
|
# add keychain to keychain search list
|
||||||
|
security list-keychains -d user -s $KEYCHAIN_PATH
|
||||||
|
# sign code
|
||||||
|
codesign --sign "$CERT_IDENTITY" --force --verbose=4 --timestamp \
|
||||||
|
flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/libflatlaf-macos-*.dylib
|
||||||
|
codesign --display --verbose=4 flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/libflatlaf-macos-*.dylib
|
||||||
|
# cleanup
|
||||||
|
security delete-keychain $KEYCHAIN_PATH
|
||||||
|
|
||||||
|
- name: Set artifacts pattern
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
case ${{ matrix.os }} in
|
||||||
|
windows-latest) echo "artifactPattern=flatlaf-windows-*.dll" >> $GITHUB_ENV ;;
|
||||||
|
macos-latest) echo "artifactPattern=libflatlaf-macos-*.dylib" >> $GITHUB_ENV ;;
|
||||||
|
ubuntu-latest) echo "artifactPattern=libflatlaf-linux-x86_64.so" >> $GITHUB_ENV ;;
|
||||||
|
ubuntu-24.04-arm) echo "artifactPattern=libflatlaf-linux-arm64.so" >> $GITHUB_ENV ;;
|
||||||
|
esac
|
||||||
|
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: FlatLaf-natives-build-artifacts-${{ matrix.os }}
|
name: FlatLaf-natives-build-artifacts-${{ matrix.os }}
|
||||||
path: |
|
path: |
|
||||||
flatlaf-core/src/main/resources/com/formdev/flatlaf/natives
|
flatlaf-core/src/main/resources/com/formdev/flatlaf/natives/${{ env.artifactPattern }}
|
||||||
flatlaf-natives/flatlaf-natives-*/build
|
flatlaf-natives/flatlaf-natives-*/build
|
||||||
|
|||||||
@@ -3,6 +3,13 @@ FlatLaf Change Log
|
|||||||
|
|
||||||
## 3.7-SNAPSHOT
|
## 3.7-SNAPSHOT
|
||||||
|
|
||||||
|
#### New features and improvements
|
||||||
|
|
||||||
|
- System File Chooser allows using **operating system file dialogs** in Java
|
||||||
|
Swing applications. (PR #988)
|
||||||
|
|
||||||
|
#### Fixed bugs
|
||||||
|
|
||||||
- TextField: Fixed wrong leading/trailing icon placement if border is set to
|
- TextField: Fixed wrong leading/trailing icon placement if border is set to
|
||||||
`null`. (issue #1047)
|
`null`. (issue #1047)
|
||||||
- Extras: UI defaults inspector: Exclude inspector window from being blocked by
|
- Extras: UI defaults inspector: Exclude inspector window from being blocked by
|
||||||
@@ -10,6 +17,7 @@ FlatLaf Change Log
|
|||||||
- JideButton, JideToggleButton, JideSplitButton and JideToggleSplitButton: Paint
|
- JideButton, JideToggleButton, JideSplitButton and JideToggleSplitButton: Paint
|
||||||
border in button style `TOOLBAR_STYLE` if in selected state. (issue #1045)
|
border in button style `TOOLBAR_STYLE` if in selected state. (issue #1045)
|
||||||
|
|
||||||
|
|
||||||
## 3.6.2
|
## 3.6.2
|
||||||
|
|
||||||
#### New features and improvements
|
#### New features and improvements
|
||||||
|
|||||||
@@ -113,6 +113,10 @@ tasks {
|
|||||||
"version" to version,
|
"version" to version,
|
||||||
"release" to "1.8", // Java version
|
"release" to "1.8", // Java version
|
||||||
"failonerror" to "true" )
|
"failonerror" to "true" )
|
||||||
|
|
||||||
|
"fixcrlf"(
|
||||||
|
"file" to "${project.name}-sigtest.txt",
|
||||||
|
"eol" to "lf" )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
|
|
||||||
package com.formdev.flatlaf;
|
package com.formdev.flatlaf;
|
||||||
|
|
||||||
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
import com.formdev.flatlaf.util.SystemFileChooser;
|
||||||
import com.formdev.flatlaf.util.UIScale;
|
import com.formdev.flatlaf.util.UIScale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -246,6 +248,17 @@ public interface FlatSystemProperties
|
|||||||
*/
|
*/
|
||||||
String USE_SUB_MENU_SAFE_TRIANGLE = "flatlaf.useSubMenuSafeTriangle";
|
String USE_SUB_MENU_SAFE_TRIANGLE = "flatlaf.useSubMenuSafeTriangle";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether {@link SystemFileChooser} uses operating system file dialogs.
|
||||||
|
* If set to {@code false}, the {@link JFileChooser} is used instead.
|
||||||
|
* <p>
|
||||||
|
* <strong>Allowed Values</strong> {@code false} and {@code true}<br>
|
||||||
|
* <strong>Default</strong> {@code true}
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
String USE_SYSTEM_FILE_CHOOSER = "flatlaf.useSystemFileChooser";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a system property is set and returns {@code true} if its value
|
* Checks whether a system property is set and returns {@code true} if its value
|
||||||
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
* is {@code "true"} (case-insensitive), otherwise it returns {@code false}.
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.awt.event.MouseEvent;
|
|||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,9 +35,9 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
* @since 2.5
|
* @since 2.5
|
||||||
*/
|
*/
|
||||||
class FlatNativeLinuxLibrary
|
public class FlatNativeLinuxLibrary
|
||||||
{
|
{
|
||||||
private static int API_VERSION_LINUX = 3001;
|
private static int API_VERSION_LINUX = 3002;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether native library is loaded/available.
|
* Checks whether native library is loaded/available.
|
||||||
@@ -44,10 +45,13 @@ class FlatNativeLinuxLibrary
|
|||||||
* <b>Note</b>: It is required to invoke this method before invoking any other
|
* <b>Note</b>: It is required to invoke this method before invoking any other
|
||||||
* method of this class. Otherwise, the native library may not be loaded.
|
* method of this class. Otherwise, the native library may not be loaded.
|
||||||
*/
|
*/
|
||||||
static boolean isLoaded() {
|
public static boolean isLoaded() {
|
||||||
return SystemInfo.isLinux && FlatNativeLibrary.isLoaded( API_VERSION_LINUX );
|
return SystemInfo.isLinux && FlatNativeLibrary.isLoaded( API_VERSION_LINUX );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---- X Window System ----------------------------------------------------
|
||||||
|
|
||||||
// direction for _NET_WM_MOVERESIZE message
|
// direction for _NET_WM_MOVERESIZE message
|
||||||
// see https://specifications.freedesktop.org/wm-spec/latest/ar01s04.html
|
// see https://specifications.freedesktop.org/wm-spec/latest/ar01s04.html
|
||||||
static final int
|
static final int
|
||||||
@@ -124,4 +128,109 @@ class FlatNativeLinuxLibrary
|
|||||||
return (window instanceof JFrame && JFrame.isDefaultLookAndFeelDecorated() && ((JFrame)window).isUndecorated()) ||
|
return (window instanceof JFrame && JFrame.isDefaultLookAndFeelDecorated() && ((JFrame)window).isUndecorated()) ||
|
||||||
(window instanceof JDialog && JDialog.isDefaultLookAndFeelDecorated() && ((JDialog)window).isUndecorated());
|
(window instanceof JDialog && JDialog.isDefaultLookAndFeelDecorated() && ((JDialog)window).isUndecorated());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---- GTK ----------------------------------------------------------------
|
||||||
|
|
||||||
|
private static Boolean isGtk3Available;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether GTK 3 is available.
|
||||||
|
* Use this before invoking any native method that uses GTK.
|
||||||
|
* Otherwise the app may terminate immediately if GTK is not installed.
|
||||||
|
* <p>
|
||||||
|
* This works because Java uses {@code dlopen(RTLD_LAZY)} to load JNI libraries,
|
||||||
|
* which only resolves symbols as the code that references them is executed.
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
public static boolean isGtk3Available() {
|
||||||
|
if( isGtk3Available == null )
|
||||||
|
isGtk3Available = isLibAvailable( "libgtk-3.so.0" ) || isLibAvailable( "libgtk-3.so" );
|
||||||
|
return isGtk3Available;
|
||||||
|
}
|
||||||
|
|
||||||
|
private native static boolean isLibAvailable( String libname );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://docs.gtk.org/gtk3/iface.FileChooser.html#properties
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
public static final int
|
||||||
|
FC_select_folder = 1 << 0,
|
||||||
|
FC_select_multiple = 1 << 1,
|
||||||
|
FC_show_hidden = 1 << 2,
|
||||||
|
FC_local_only = 1 << 3, // default
|
||||||
|
FC_do_overwrite_confirmation = 1 << 4, // GTK 3 only; removed and always-on in GTK 4
|
||||||
|
FC_create_folders = 1 << 5; // default for Save
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the Linux/GTK system file dialog
|
||||||
|
* <a href="https://docs.gtk.org/gtk3/class.FileChooserDialog.html">GtkFileChooserDialog</a>.
|
||||||
|
* <p>
|
||||||
|
* Uses {@code GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER} if {@link #FC_select_folder} is set in parameter {@code optionsSet}.
|
||||||
|
* Otherwise uses {@code GTK_FILE_CHOOSER_ACTION_OPEN} if parameter {@code open} is {@code true},
|
||||||
|
* or {@code GTK_FILE_CHOOSER_ACTION_SAVE} if {@code false}.
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method blocks the current thread until the user closes
|
||||||
|
* the file dialog. It is highly recommended to invoke it from a new thread
|
||||||
|
* to avoid blocking the AWT event dispatching thread.
|
||||||
|
*
|
||||||
|
* @param owner the owner of the file dialog; or {@code null}
|
||||||
|
* @param open if {@code true}, shows the open dialog; if {@code false}, shows the save dialog
|
||||||
|
* @param title text displayed in dialog title; or {@code null}
|
||||||
|
* @param okButtonLabel text displayed in default button; or {@code null}.
|
||||||
|
* Use '_' for mnemonics (e.g. "_Choose")
|
||||||
|
* Use '__' for '_' character (e.g. "Choose__and__Quit").
|
||||||
|
* @param currentName user-editable filename currently shown in the filename field in save dialog; or {@code null}
|
||||||
|
* @param currentFolder current directory shown in the dialog; or {@code null}
|
||||||
|
* @param optionsSet options to set; see {@code FOS_*} constants
|
||||||
|
* @param optionsClear options to clear; see {@code FOS_*} constants
|
||||||
|
* @param callback approve callback; or {@code null}
|
||||||
|
* @param fileTypeIndex the file type that appears as selected (zero-based)
|
||||||
|
* @param fileTypes file types that the dialog can open or save.
|
||||||
|
* Two or more strings and {@code null} are required for each filter.
|
||||||
|
* First string is the display name of the filter shown in the combobox (e.g. "Text Files").
|
||||||
|
* Subsequent strings are the filter patterns (e.g. "*.txt" or "*").
|
||||||
|
* {@code null} is required to mark end of filter.
|
||||||
|
* @return file path(s) that the user selected; an empty array if canceled;
|
||||||
|
* or {@code null} on failures (no dialog shown)
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
public native static String[] showFileChooser( Window owner, boolean open,
|
||||||
|
String title, String okButtonLabel, String currentName, String currentFolder,
|
||||||
|
int optionsSet, int optionsClear, FileChooserCallback callback,
|
||||||
|
int fileTypeIndex, String... fileTypes );
|
||||||
|
|
||||||
|
/** @since 3.7 */
|
||||||
|
public interface FileChooserCallback {
|
||||||
|
boolean approve( String[] files, long hwndFileDialog );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a GTK message box
|
||||||
|
* <a href="https://docs.gtk.org/gtk3/class.MessageDialog.html">GtkMessageDialog</a>.
|
||||||
|
* <p>
|
||||||
|
* For use in {@link FileChooserCallback} only.
|
||||||
|
*
|
||||||
|
* @param hwndParent the parent of the message box
|
||||||
|
* @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; if the dialog has a secondary text,
|
||||||
|
* this will appear as title in a larger bold font
|
||||||
|
* @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
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
public native static int showMessageDialog( long hwndParent, int messageType,
|
||||||
|
String primaryText, String secondaryText, int defaultButton, String... buttons );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +45,7 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
*/
|
*/
|
||||||
public class FlatNativeMacLibrary
|
public class FlatNativeMacLibrary
|
||||||
{
|
{
|
||||||
private static int API_VERSION_MACOS = 2001;
|
private static int API_VERSION_MACOS = 2002;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether native library is loaded/available.
|
* Checks whether native library is loaded/available.
|
||||||
@@ -68,4 +69,88 @@ public class FlatNativeMacLibrary
|
|||||||
/** @since 3.4 */ public native static Rectangle getWindowButtonsBounds( Window window );
|
/** @since 3.4 */ public native static Rectangle getWindowButtonsBounds( Window window );
|
||||||
/** @since 3.4 */ public native static boolean isWindowFullScreen( Window window );
|
/** @since 3.4 */ public native static boolean isWindowFullScreen( Window window );
|
||||||
/** @since 3.4 */ public native static boolean toggleWindowFullScreen( Window window );
|
/** @since 3.4 */ public native static boolean toggleWindowFullScreen( Window window );
|
||||||
|
|
||||||
|
|
||||||
|
/** @since 3.7 */
|
||||||
|
public static final int
|
||||||
|
// NSOpenPanel (extends NSSavePanel)
|
||||||
|
FC_canChooseFiles = 1 << 0, // default
|
||||||
|
FC_canChooseDirectories = 1 << 1,
|
||||||
|
FC_resolvesAliases = 1 << 2, // default
|
||||||
|
FC_allowsMultipleSelection = 1 << 3,
|
||||||
|
FC_accessoryViewDisclosed = 1 << 4,
|
||||||
|
// NSSavePanel
|
||||||
|
FC_showsTagField = 1 << 8, // default for Save
|
||||||
|
FC_canCreateDirectories = 1 << 9, // default for Save
|
||||||
|
FC_canSelectHiddenExtension = 1 << 10,
|
||||||
|
FC_showsHiddenFiles = 1 << 11,
|
||||||
|
FC_extensionHidden = 1 << 12,
|
||||||
|
FC_allowsOtherFileTypes = 1 << 13,
|
||||||
|
FC_treatsFilePackagesAsDirectories = 1 << 14,
|
||||||
|
// custom
|
||||||
|
FC_showSingleFilterField = 1 << 24;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the macOS system file dialogs
|
||||||
|
* <a href="https://developer.apple.com/documentation/appkit/nsopenpanel?language=objc">NSOpenPanel</a> or
|
||||||
|
* <a href="https://developer.apple.com/documentation/appkit/nssavepanel?language=objc">NSSavePanel</a>.
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method blocks the current thread until the user closes
|
||||||
|
* the file dialog. It is highly recommended to invoke it from a new thread
|
||||||
|
* to avoid blocking the AWT event dispatching thread.
|
||||||
|
*
|
||||||
|
* @param owner the owner of the file dialog; or {@code null}
|
||||||
|
* @param dark appearance of the file dialog: {@code 1} = dark, {@code 0} = light, {@code -1} = default
|
||||||
|
* @param open if {@code true}, shows the open dialog; if {@code false}, shows the save dialog
|
||||||
|
* @param title text displayed at top of save dialog (not used in open dialog); or {@code null}
|
||||||
|
* @param prompt text displayed in default button; or {@code null}
|
||||||
|
* @param message text displayed at top of open/save dialogs; or {@code null}
|
||||||
|
* @param filterFieldLabel text displayed in front of the filter combobox; or {@code null}
|
||||||
|
* @param nameFieldLabel text displayed in front of the filename text field in save dialog (not used in open dialog); or {@code null}
|
||||||
|
* @param nameFieldStringValue user-editable filename currently shown in the name field in save dialog (not used in open dialog); or {@code null}
|
||||||
|
* @param directoryURL current directory shown in the dialog; or {@code null}
|
||||||
|
* @param optionsSet options to set; see {@code FC_*} constants
|
||||||
|
* @param optionsClear options to clear; see {@code FC_*} constants
|
||||||
|
* @param fileTypeIndex the file type that appears as selected (zero-based)
|
||||||
|
* @param fileTypes file types that the dialog can open or save.
|
||||||
|
* Two or more strings and {@code null} are required for each filter.
|
||||||
|
* First string is the display name of the filter shown in the combobox (e.g. "Text Files").
|
||||||
|
* Subsequent strings are the filter patterns (e.g. "txt" or "*").
|
||||||
|
* {@code null} is required to mark end of filter.
|
||||||
|
* @return file path(s) that the user selected; an empty array if canceled;
|
||||||
|
* or {@code null} on failures (no dialog shown)
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
public native static String[] showFileChooser( Window owner, int dark, boolean open,
|
||||||
|
String title, String prompt, String message, String filterFieldLabel,
|
||||||
|
String nameFieldLabel, String nameFieldStringValue, String directoryURL,
|
||||||
|
int optionsSet, int optionsClear, FileChooserCallback callback,
|
||||||
|
int fileTypeIndex, String... fileTypes );
|
||||||
|
|
||||||
|
/** @since 3.7 */
|
||||||
|
public interface FileChooserCallback {
|
||||||
|
boolean approve( String[] files, long hwndFileDialog );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a macOS alert
|
||||||
|
* <a href="https://developer.apple.com/documentation/appkit/nsalert?language=objc">NSAlert</a>.
|
||||||
|
* <p>
|
||||||
|
* For use in {@link FileChooserCallback} only.
|
||||||
|
*
|
||||||
|
* @param hwndParent the parent of the message box
|
||||||
|
* @param alertStyle type of alert being displayed:
|
||||||
|
* {@link JOptionPane#ERROR_MESSAGE}, {@link JOptionPane#INFORMATION_MESSAGE} or
|
||||||
|
* {@link JOptionPane#WARNING_MESSAGE}
|
||||||
|
* @param messageText main message of the alert
|
||||||
|
* @param informativeText additional information about the alert; shown below of main message; 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
|
||||||
|
* @return index of pressed button
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
public native static int showMessageDialog( long hwndParent, int alertStyle,
|
||||||
|
String messageText, String informativeText, int defaultButton, String... buttons );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Window;
|
import java.awt.Window;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,7 +31,7 @@ import com.formdev.flatlaf.util.SystemInfo;
|
|||||||
*/
|
*/
|
||||||
public class FlatNativeWindowsLibrary
|
public class FlatNativeWindowsLibrary
|
||||||
{
|
{
|
||||||
private static int API_VERSION_WINDOWS = 1001;
|
private static int API_VERSION_WINDOWS = 1002;
|
||||||
|
|
||||||
private static long osBuildNumber = Long.MIN_VALUE;
|
private static long osBuildNumber = Long.MIN_VALUE;
|
||||||
|
|
||||||
@@ -158,4 +159,125 @@ public class FlatNativeWindowsLibrary
|
|||||||
// DwmSetWindowAttribute() expects COLORREF as attribute value, which is defined as DWORD
|
// DwmSetWindowAttribute() expects COLORREF as attribute value, which is defined as DWORD
|
||||||
return dwmSetWindowAttributeDWORD( hwnd, attribute, rgb );
|
return dwmSetWindowAttributeDWORD( hwnd, attribute, rgb );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FILEOPENDIALOGOPTIONS
|
||||||
|
* see https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/ne-shobjidl_core-_fileopendialogoptions
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
public static final int
|
||||||
|
FOS_OVERWRITEPROMPT = 0x2, // default for Save
|
||||||
|
FOS_STRICTFILETYPES = 0x4,
|
||||||
|
FOS_NOCHANGEDIR = 0x8, // default
|
||||||
|
FOS_PICKFOLDERS = 0x20,
|
||||||
|
FOS_FORCEFILESYSTEM = 0x40,
|
||||||
|
FOS_ALLNONSTORAGEITEMS = 0x80,
|
||||||
|
FOS_NOVALIDATE = 0x100,
|
||||||
|
FOS_ALLOWMULTISELECT = 0x200,
|
||||||
|
FOS_PATHMUSTEXIST = 0x800, // default
|
||||||
|
FOS_FILEMUSTEXIST = 0x1000, // default for Open
|
||||||
|
FOS_CREATEPROMPT = 0x2000,
|
||||||
|
FOS_SHAREAWARE = 0x4000,
|
||||||
|
FOS_NOREADONLYRETURN = 0x8000, // default for Save
|
||||||
|
FOS_NOTESTFILECREATE = 0x10000,
|
||||||
|
FOS_HIDEMRUPLACES = 0x20000,
|
||||||
|
FOS_HIDEPINNEDPLACES = 0x40000,
|
||||||
|
FOS_NODEREFERENCELINKS = 0x100000,
|
||||||
|
FOS_OKBUTTONNEEDSINTERACTION = 0x200000,
|
||||||
|
FOS_DONTADDTORECENT = 0x2000000,
|
||||||
|
FOS_FORCESHOWHIDDEN = 0x10000000,
|
||||||
|
FOS_DEFAULTNOMINIMODE = 0x20000000,
|
||||||
|
FOS_FORCEPREVIEWPANEON = 0x40000000,
|
||||||
|
FOS_SUPPORTSTREAMABLEITEMS = 0x80000000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the Windows system
|
||||||
|
* <a href="https://learn.microsoft.com/en-us/windows/win32/shell/common-file-dialog">file dialogs</a>
|
||||||
|
* <a href="https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ifileopendialog">IFileOpenDialog</a> or
|
||||||
|
* <a href="https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ifilesavedialog">IFileSaveDialog</a>.
|
||||||
|
* <p>
|
||||||
|
* <b>Note:</b> This method blocks the current thread until the user closes
|
||||||
|
* the file dialog. It is highly recommended to invoke it from a new thread
|
||||||
|
* to avoid blocking the AWT event dispatching thread.
|
||||||
|
*
|
||||||
|
* @param owner the owner of the file dialog; or {@code null}
|
||||||
|
* @param open if {@code true}, shows the open dialog; if {@code false}, shows the save dialog
|
||||||
|
* @param title text displayed in dialog title; or {@code null}
|
||||||
|
* @param okButtonLabel text displayed in default button; or {@code null}.
|
||||||
|
* Use '&' for mnemonics (e.g. "&Choose").
|
||||||
|
* Use '&&' for '&' character (e.g. "Choose && Quit").
|
||||||
|
* @param fileNameLabel text displayed in front of the filename text field; or {@code null}
|
||||||
|
* @param fileName user-editable filename currently shown in the filename field; or {@code null}
|
||||||
|
* @param folder current directory shown in the dialog; or {@code null}
|
||||||
|
* @param saveAsItem file to be used as the initial entry in a Save As dialog; or {@code null}.
|
||||||
|
* File name is shown in filename text field, folder is selected in view.
|
||||||
|
* To be used for saving files that already exist. For new files use {@code fileName}.
|
||||||
|
* @param defaultFolder folder used as a default if there is not a recently used folder value available; or {@code null}.
|
||||||
|
* Windows somewhere stores default folder on a per-app basis.
|
||||||
|
* So this is probably used only once when the app opens a file dialog for first time.
|
||||||
|
* @param defaultExtension default extension to be added to file name in save dialog; or {@code null}
|
||||||
|
* @param optionsSet options to set; see {@code FOS_*} constants
|
||||||
|
* @param optionsClear options to clear; see {@code FOS_*} constants
|
||||||
|
* @param callback approve callback; or {@code null}
|
||||||
|
* @param fileTypeIndex the file type that appears as selected (zero-based)
|
||||||
|
* @param fileTypes file types that the dialog can open or save.
|
||||||
|
* Pairs of strings are required for each filter.
|
||||||
|
* First string is the display name of the filter shown in the combobox (e.g. "Text Files").
|
||||||
|
* Second string is the filter pattern (e.g. "*.txt", "*.exe;*.dll" or "*.*").
|
||||||
|
* @return file path(s) that the user selected; an empty array if canceled;
|
||||||
|
* or {@code null} on failures (no dialog shown)
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
public native static String[] showFileChooser( Window owner, boolean open,
|
||||||
|
String title, String okButtonLabel, String fileNameLabel, String fileName,
|
||||||
|
String folder, String saveAsItem, String defaultFolder, String defaultExtension,
|
||||||
|
int optionsSet, int optionsClear, FileChooserCallback callback,
|
||||||
|
int fileTypeIndex, String... fileTypes );
|
||||||
|
|
||||||
|
/** @since 3.7 */
|
||||||
|
public interface FileChooserCallback {
|
||||||
|
boolean approve( String[] files, long hwndFileDialog );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a modal Windows message dialog.
|
||||||
|
* <p>
|
||||||
|
* For use in {@link FileChooserCallback} only.
|
||||||
|
*
|
||||||
|
* @param hwndParent the parent of the message box
|
||||||
|
* @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 title dialog box title; or {@code null} to use title from parent window
|
||||||
|
* @param text message to be displayed
|
||||||
|
* @param defaultButton index of the default button, which can be pressed using ENTER key
|
||||||
|
* @param buttons texts of the buttons.
|
||||||
|
* Use '&' for mnemonics (e.g. "&Choose").
|
||||||
|
* Use '&&' for '&' character (e.g. "Choose && Quit").
|
||||||
|
* @return index of pressed button; or -1 for ESC key
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
public native static int showMessageDialog( long hwndParent, int messageType,
|
||||||
|
String title, String text, int defaultButton, String... buttons );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a Windows message box
|
||||||
|
* <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox">MessageBox</a>.
|
||||||
|
* <p>
|
||||||
|
* For use in {@link FileChooserCallback} only.
|
||||||
|
*
|
||||||
|
* @param hwndParent the parent of the message box
|
||||||
|
* @param text message to be displayed
|
||||||
|
* @param caption dialog box title
|
||||||
|
* @param type see <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox#parameters">MessageBox parameter uType</a>
|
||||||
|
* @return see <a href="https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox#return-value">MessageBox Return value</a>
|
||||||
|
*
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
public native static int showMessageBox( long hwndParent, String text, String caption, int type );
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -18,6 +18,7 @@ package com.formdev.flatlaf.demo;
|
|||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.*;
|
import java.awt.event.*;
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
@@ -49,6 +50,7 @@ import com.formdev.flatlaf.extras.FlatSVGUtils;
|
|||||||
import com.formdev.flatlaf.util.ColorFunctions;
|
import com.formdev.flatlaf.util.ColorFunctions;
|
||||||
import com.formdev.flatlaf.util.FontUtils;
|
import com.formdev.flatlaf.util.FontUtils;
|
||||||
import com.formdev.flatlaf.util.LoggingFacade;
|
import com.formdev.flatlaf.util.LoggingFacade;
|
||||||
|
import com.formdev.flatlaf.util.SystemFileChooser;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import net.miginfocom.layout.ConstraintParser;
|
import net.miginfocom.layout.ConstraintParser;
|
||||||
import net.miginfocom.layout.LC;
|
import net.miginfocom.layout.LC;
|
||||||
@@ -172,6 +174,48 @@ class DemoFrame
|
|||||||
chooser.showSaveDialog( this );
|
chooser.showSaveDialog( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void openSystemActionPerformed() {
|
||||||
|
SystemFileChooser chooser = new SystemFileChooser();
|
||||||
|
chooser.setMultiSelectionEnabled( true );
|
||||||
|
chooser.addChoosableFileFilter( new SystemFileChooser.FileNameExtensionFilter(
|
||||||
|
"Text Files", "txt", "md" ) );
|
||||||
|
chooser.addChoosableFileFilter( new SystemFileChooser.FileNameExtensionFilter(
|
||||||
|
"PDF Files", "pdf" ) );
|
||||||
|
chooser.addChoosableFileFilter( new SystemFileChooser.FileNameExtensionFilter(
|
||||||
|
"Archives", "zip", "tar", "jar", "7z" ) );
|
||||||
|
|
||||||
|
if( chooser.showOpenDialog( this ) != SystemFileChooser.APPROVE_OPTION )
|
||||||
|
return;
|
||||||
|
|
||||||
|
File[] files = chooser.getSelectedFiles();
|
||||||
|
System.out.println( Arrays.toString( files ).replace( ",", "\n" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveAsSystemActionPerformed() {
|
||||||
|
SystemFileChooser chooser = new SystemFileChooser();
|
||||||
|
chooser.addChoosableFileFilter( new SystemFileChooser.FileNameExtensionFilter(
|
||||||
|
"Text Files", "txt", "md" ) );
|
||||||
|
chooser.addChoosableFileFilter( new SystemFileChooser.FileNameExtensionFilter(
|
||||||
|
"Images", "png", "gif", "jpg" ) );
|
||||||
|
|
||||||
|
if( chooser.showSaveDialog( this ) != SystemFileChooser.APPROVE_OPTION )
|
||||||
|
return;
|
||||||
|
|
||||||
|
File file = chooser.getSelectedFile();
|
||||||
|
System.out.println( file );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void selectFolderSystemActionPerformed() {
|
||||||
|
SystemFileChooser chooser = new SystemFileChooser();
|
||||||
|
chooser.setFileSelectionMode( SystemFileChooser.DIRECTORIES_ONLY );
|
||||||
|
|
||||||
|
if( chooser.showOpenDialog( this ) != SystemFileChooser.APPROVE_OPTION )
|
||||||
|
return;
|
||||||
|
|
||||||
|
File directory = chooser.getSelectedFile();
|
||||||
|
System.out.println( directory );
|
||||||
|
}
|
||||||
|
|
||||||
private void exitActionPerformed() {
|
private void exitActionPerformed() {
|
||||||
dispose();
|
dispose();
|
||||||
}
|
}
|
||||||
@@ -508,6 +552,9 @@ class DemoFrame
|
|||||||
JMenuItem newMenuItem = new JMenuItem();
|
JMenuItem newMenuItem = new JMenuItem();
|
||||||
JMenuItem openMenuItem = new JMenuItem();
|
JMenuItem openMenuItem = new JMenuItem();
|
||||||
JMenuItem saveAsMenuItem = new JMenuItem();
|
JMenuItem saveAsMenuItem = new JMenuItem();
|
||||||
|
JMenuItem openSystemMenuItem = new JMenuItem();
|
||||||
|
JMenuItem saveAsSystemMenuItem = new JMenuItem();
|
||||||
|
JMenuItem selectFolderSystemMenuItem = new JMenuItem();
|
||||||
JMenuItem closeMenuItem = new JMenuItem();
|
JMenuItem closeMenuItem = new JMenuItem();
|
||||||
exitMenuItem = new JMenuItem();
|
exitMenuItem = new JMenuItem();
|
||||||
JMenu editMenu = new JMenu();
|
JMenu editMenu = new JMenu();
|
||||||
@@ -608,6 +655,25 @@ class DemoFrame
|
|||||||
fileMenu.add(saveAsMenuItem);
|
fileMenu.add(saveAsMenuItem);
|
||||||
fileMenu.addSeparator();
|
fileMenu.addSeparator();
|
||||||
|
|
||||||
|
//---- openSystemMenuItem ----
|
||||||
|
openSystemMenuItem.setText("Open (System)...");
|
||||||
|
openSystemMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()|KeyEvent.SHIFT_DOWN_MASK));
|
||||||
|
openSystemMenuItem.addActionListener(e -> openSystemActionPerformed());
|
||||||
|
fileMenu.add(openSystemMenuItem);
|
||||||
|
|
||||||
|
//---- saveAsSystemMenuItem ----
|
||||||
|
saveAsSystemMenuItem.setText("Save As (System)...");
|
||||||
|
saveAsSystemMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()|KeyEvent.SHIFT_DOWN_MASK));
|
||||||
|
saveAsSystemMenuItem.addActionListener(e -> saveAsSystemActionPerformed());
|
||||||
|
fileMenu.add(saveAsSystemMenuItem);
|
||||||
|
|
||||||
|
//---- selectFolderSystemMenuItem ----
|
||||||
|
selectFolderSystemMenuItem.setText("Select Folder (System)...");
|
||||||
|
selectFolderSystemMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()|KeyEvent.SHIFT_DOWN_MASK));
|
||||||
|
selectFolderSystemMenuItem.addActionListener(e -> selectFolderSystemActionPerformed());
|
||||||
|
fileMenu.add(selectFolderSystemMenuItem);
|
||||||
|
fileMenu.addSeparator();
|
||||||
|
|
||||||
//---- closeMenuItem ----
|
//---- closeMenuItem ----
|
||||||
closeMenuItem.setText("Close");
|
closeMenuItem.setText("Close");
|
||||||
closeMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
closeMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_W, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
JFDML JFormDesigner: "8.2.1.0.348" Java: "21.0.1" encoding: "UTF-8"
|
JFDML JFormDesigner: "8.3" encoding: "UTF-8"
|
||||||
|
|
||||||
new FormModel {
|
new FormModel {
|
||||||
contentType: "form/swing"
|
contentType: "form/swing"
|
||||||
@@ -182,6 +182,27 @@ new FormModel {
|
|||||||
"mnemonic": 83
|
"mnemonic": 83
|
||||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "saveAsActionPerformed", false ) )
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "saveAsActionPerformed", false ) )
|
||||||
} )
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||||
|
name: "separator9"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "openSystemMenuItem"
|
||||||
|
"text": "Open (System)..."
|
||||||
|
"accelerator": static javax.swing.KeyStroke getKeyStroke( 79, 4291, false )
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openSystemActionPerformed", false ) )
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "saveAsSystemMenuItem"
|
||||||
|
"text": "Save As (System)..."
|
||||||
|
"accelerator": static javax.swing.KeyStroke getKeyStroke( 83, 4291, false )
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "saveAsSystemActionPerformed", false ) )
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "selectFolderSystemMenuItem"
|
||||||
|
"text": "Select Folder (System)..."
|
||||||
|
"accelerator": static javax.swing.KeyStroke getKeyStroke( 70, 4291, false )
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "selectFolderSystemActionPerformed", false ) )
|
||||||
|
} )
|
||||||
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
add( new FormComponent( "javax.swing.JPopupMenu$Separator" ) {
|
||||||
name: "separator2"
|
name: "separator2"
|
||||||
} )
|
} )
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.formdev.flatlaf.demo;
|
package com.formdev.flatlaf.demo;
|
||||||
|
|
||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
|
import java.util.prefs.Preferences;
|
||||||
import javax.swing.JDialog;
|
import javax.swing.JDialog;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -27,6 +28,7 @@ import com.formdev.flatlaf.fonts.inter.FlatInterFont;
|
|||||||
import com.formdev.flatlaf.fonts.jetbrains_mono.FlatJetBrainsMonoFont;
|
import com.formdev.flatlaf.fonts.jetbrains_mono.FlatJetBrainsMonoFont;
|
||||||
import com.formdev.flatlaf.fonts.roboto.FlatRobotoFont;
|
import com.formdev.flatlaf.fonts.roboto.FlatRobotoFont;
|
||||||
import com.formdev.flatlaf.fonts.roboto_mono.FlatRobotoMonoFont;
|
import com.formdev.flatlaf.fonts.roboto_mono.FlatRobotoMonoFont;
|
||||||
|
import com.formdev.flatlaf.util.SystemFileChooser;
|
||||||
import com.formdev.flatlaf.util.SystemInfo;
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,6 +75,28 @@ public class FlatLafDemo
|
|||||||
DemoPrefs.init( PREFS_ROOT_PATH );
|
DemoPrefs.init( PREFS_ROOT_PATH );
|
||||||
DemoPrefs.initSystemScale();
|
DemoPrefs.initSystemScale();
|
||||||
|
|
||||||
|
// SystemFileChooser state storage
|
||||||
|
SystemFileChooser.setStateStore( new SystemFileChooser.StateStore() {
|
||||||
|
private static final String KEY_PREFIX = "fileChooser.";
|
||||||
|
private final Preferences state = Preferences.userRoot().node( PREFS_ROOT_PATH );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String get( String key, String def ) {
|
||||||
|
String value = state.get( KEY_PREFIX + key, def );
|
||||||
|
System.out.println( "SystemFileChooser State GET " + key + " = " + value );
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put( String key, String value ) {
|
||||||
|
System.out.println( "SystemFileChooser State PUT " + key + " = " + value );
|
||||||
|
if( value != null )
|
||||||
|
state.put( KEY_PREFIX + key, value );
|
||||||
|
else
|
||||||
|
state.remove( KEY_PREFIX + key );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
SwingUtilities.invokeLater( () -> {
|
SwingUtilities.invokeLater( () -> {
|
||||||
// install fonts for lazy loading
|
// install fonts for lazy loading
|
||||||
FlatInterFont.installLazy();
|
FlatInterFont.installLazy();
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ To build the library on Linux, some packages needs to be installed:
|
|||||||
|
|
||||||
- `build-essential` - GCC and development tools
|
- `build-essential` - GCC and development tools
|
||||||
- `libxt-dev` - X11 toolkit development headers
|
- `libxt-dev` - X11 toolkit development headers
|
||||||
|
- `libgtk-3-dev` - GTK 3 toolkit development headers
|
||||||
- `g++-aarch64-linux-gnu` - GNU C++ compiler for the arm64 architecture (only on
|
- `g++-aarch64-linux-gnu` - GNU C++ compiler for the arm64 architecture (only on
|
||||||
x86_64 Linux for cross-compiling for arm64 architecture)
|
x86_64 Linux for cross-compiling for arm64 architecture)
|
||||||
|
|
||||||
@@ -32,19 +33,39 @@ To build the library on Linux, some packages needs to be installed:
|
|||||||
### Ubuntu
|
### Ubuntu
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
sudo apt update
|
sudo apt-get update
|
||||||
sudo apt install build-essential libxt-dev
|
sudo apt-get install build-essential libxt-dev libgtk-3-dev
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
Only on x86_64 Linux for cross-compiling for arm64 architecture:
|
#### Cross-compile for arm64 architecture on x86_64 Linux
|
||||||
|
|
||||||
|
Only needed on x86_64 Linux if you want cross-compile for arm64 architecture:
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
sudo apt install g++-aarch64-linux-gnu
|
sudo apt-get install g++-aarch64-linux-gnu
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Download `libgtk-3.so` for arm64 architecture:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
cd flatlaf-natives/flatlaf-natives-linux/lib/aarch64
|
||||||
|
wget --no-verbose https://ports.ubuntu.com/pool/main/g/gtk%2b3.0/libgtk-3-0_3.24.18-1ubuntu1_arm64.deb
|
||||||
|
ar -x libgtk-3-0_3.24.18-1ubuntu1_arm64.deb data.tar.xz
|
||||||
|
tar -xvf data.tar.xz --wildcards --to-stdout "./usr/lib/aarch64-linux-gnu/libgtk-3.so.0.*" > libgtk-3.so
|
||||||
|
rm libgtk-3-0_3.24.18-1ubuntu1_arm64.deb data.tar.xz
|
||||||
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
### Fedora
|
||||||
|
|
||||||
|
~~~
|
||||||
|
sudo dnf group install c-development
|
||||||
|
sudo dnf install libXt-devel gtk3-devel
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
### CentOS
|
### CentOS
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
sudo yum install libXt-devel
|
sudo yum install libXt-devel gtk3-devel
|
||||||
~~~
|
~~~
|
||||||
|
|||||||
@@ -65,15 +65,37 @@ tasks {
|
|||||||
|
|
||||||
includes.from(
|
includes.from(
|
||||||
"${javaHome}/include",
|
"${javaHome}/include",
|
||||||
"${javaHome}/include/linux"
|
"${javaHome}/include/linux",
|
||||||
|
|
||||||
|
// for GTK
|
||||||
|
"/usr/include/gtk-3.0",
|
||||||
|
"/usr/include/glib-2.0",
|
||||||
|
if( name.contains( "X86-64" ) ) "/usr/lib/x86_64-linux-gnu/glib-2.0/include"
|
||||||
|
else "/usr/lib/aarch64-linux-gnu/glib-2.0/include",
|
||||||
|
"/usr/include/gdk-pixbuf-2.0",
|
||||||
|
"/usr/include/atk-1.0",
|
||||||
|
"/usr/include/cairo",
|
||||||
|
"/usr/include/pango-1.0",
|
||||||
|
"/usr/include/harfbuzz",
|
||||||
)
|
)
|
||||||
|
|
||||||
compilerArgs.addAll( toolChain.map {
|
compilerArgs.addAll( toolChain.map {
|
||||||
when( it ) {
|
when( it ) {
|
||||||
is Gcc, is Clang -> listOf()
|
is Gcc, is Clang -> listOf( "-fvisibility=hidden" )
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
// check required Java version
|
||||||
|
if( JavaVersion.current() < JavaVersion.VERSION_11 ) {
|
||||||
|
println()
|
||||||
|
println( "WARNING: Java 11 or later required to build Linux native library (running ${System.getProperty( "java.version" )})" )
|
||||||
|
println( " Native library built with older Java versions throw following exception when running in Java 17+:" )
|
||||||
|
println( " java.lang.UnsatisfiedLinkError: .../libjawt.so: version `SUNWprivate_1.1' not found" )
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
withType<LinkSharedLibrary>().configureEach {
|
withType<LinkSharedLibrary>().configureEach {
|
||||||
@@ -88,7 +110,7 @@ tasks {
|
|||||||
|
|
||||||
linkerArgs.addAll( toolChain.map {
|
linkerArgs.addAll( toolChain.map {
|
||||||
when( it ) {
|
when( it ) {
|
||||||
is Gcc, is Clang -> listOf( "-L${jawtPath}", "-l${jawt}" )
|
is Gcc, is Clang -> listOf( "-L${jawtPath}", "-l${jawt}", "-lgtk-3" )
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
@@ -128,7 +150,20 @@ tasks {
|
|||||||
"-I", "${javaHome}/include/linux",
|
"-I", "${javaHome}/include/linux",
|
||||||
"-I", "$include",
|
"-I", "$include",
|
||||||
|
|
||||||
|
// for GTK
|
||||||
|
"-I", "/usr/include/gtk-3.0",
|
||||||
|
"-I", "/usr/include/glib-2.0",
|
||||||
|
"-I", "/usr/lib/x86_64-linux-gnu/glib-2.0/include",
|
||||||
|
"-I", "/usr/include/gdk-pixbuf-2.0",
|
||||||
|
"-I", "/usr/include/atk-1.0",
|
||||||
|
"-I", "/usr/include/cairo",
|
||||||
|
"-I", "/usr/include/pango-1.0",
|
||||||
|
"-I", "/usr/include/harfbuzz",
|
||||||
|
|
||||||
"$src/ApiVersion.cpp",
|
"$src/ApiVersion.cpp",
|
||||||
|
"$src/GtkFileChooser.cpp",
|
||||||
|
"$src/GtkMessageDialog.cpp",
|
||||||
|
"$src/JNIUtils.cpp",
|
||||||
"$src/X11WmUtils.cpp",
|
"$src/X11WmUtils.cpp",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -152,10 +187,15 @@ tasks {
|
|||||||
"-o", "$outDir/$libraryName",
|
"-o", "$outDir/$libraryName",
|
||||||
|
|
||||||
"$objDir/ApiVersion.o",
|
"$objDir/ApiVersion.o",
|
||||||
|
"$objDir/GtkFileChooser.o",
|
||||||
|
"$objDir/GtkMessageDialog.o",
|
||||||
|
"$objDir/JNIUtils.o",
|
||||||
"$objDir/X11WmUtils.o",
|
"$objDir/X11WmUtils.o",
|
||||||
|
|
||||||
|
"-lstdc++",
|
||||||
"-L${layout.projectDirectory}/lib/aarch64",
|
"-L${layout.projectDirectory}/lib/aarch64",
|
||||||
"-ljawt",
|
"-ljawt",
|
||||||
|
"-lgtk-3",
|
||||||
)
|
)
|
||||||
|
|
||||||
doLast {
|
doLast {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
// increase this version if changing API or functionality of native library
|
// increase this version if changing API or functionality of native library
|
||||||
// also update version in Java class com.formdev.flatlaf.ui.FlatNativeLinuxLibrary
|
// also update version in Java class com.formdev.flatlaf.ui.FlatNativeLinuxLibrary
|
||||||
#define API_VERSION_LINUX 3001
|
#define API_VERSION_LINUX 3002
|
||||||
|
|
||||||
|
|
||||||
//---- JNI methods ------------------------------------------------------------
|
//---- JNI methods ------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <jawt.h>
|
||||||
|
#include <linux/jawt_md.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include "JNIUtils.h"
|
||||||
|
#include "com_formdev_flatlaf_ui_FlatNativeLinuxLibrary.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
|
||||||
|
// declare external methods
|
||||||
|
extern Window getWindowHandle( JNIEnv* env, JAWT* awt, jobject window, Display** display_return );
|
||||||
|
|
||||||
|
// declare internal methods
|
||||||
|
static jobjectArray fileListToStringArray( JNIEnv* env, GSList* fileList );
|
||||||
|
|
||||||
|
//---- helper -----------------------------------------------------------------
|
||||||
|
|
||||||
|
#define isOptionSet( option ) ((optionsSet & com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_ ## option) != 0)
|
||||||
|
#define isOptionClear( option ) ((optionsClear & com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_ ## option) != 0)
|
||||||
|
#define isOptionSetOrClear( option ) isOptionSet( option ) || isOptionClear( option )
|
||||||
|
|
||||||
|
static jobjectArray newJavaStringArray( JNIEnv* env, jsize count ) {
|
||||||
|
jclass stringClass = env->FindClass( "java/lang/String" );
|
||||||
|
return env->NewObjectArray( count, stringClass, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initFilters( GtkFileChooser* chooser, JNIEnv* env, jint fileTypeIndex, jobjectArray fileTypes ) {
|
||||||
|
jint length = env->GetArrayLength( fileTypes );
|
||||||
|
if( length <= 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
GtkFileFilter* filter = NULL;
|
||||||
|
int filterIndex = 0;
|
||||||
|
for( int i = 0; i < length; i++ ) {
|
||||||
|
jstring jstr = (jstring) env->GetObjectArrayElement( fileTypes, i );
|
||||||
|
if( jstr == NULL ) {
|
||||||
|
if( filter != NULL ) {
|
||||||
|
gtk_file_chooser_add_filter( chooser, filter );
|
||||||
|
if( fileTypeIndex == filterIndex )
|
||||||
|
gtk_file_chooser_set_filter( chooser, filter );
|
||||||
|
filter = NULL;
|
||||||
|
filterIndex++;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoReleaseStringUTF8 str( env, jstr );
|
||||||
|
if( filter == NULL ) {
|
||||||
|
filter = gtk_file_filter_new();
|
||||||
|
gtk_file_filter_set_name( filter, str );
|
||||||
|
} else
|
||||||
|
gtk_file_filter_add_pattern( filter, str );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkWindow* getGdkWindow( JNIEnv* env, jobject window ) {
|
||||||
|
// get the AWT
|
||||||
|
JAWT awt;
|
||||||
|
awt.version = JAWT_VERSION_1_4;
|
||||||
|
if( !JAWT_GetAWT( env, &awt ) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// get Xlib window and display from AWT window
|
||||||
|
Display* display;
|
||||||
|
Window w = getWindowHandle( env, &awt, window, &display );
|
||||||
|
if( w == 0 )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// based on GetAllocNativeWindowHandle() from https://github.com/btzy/nativefiledialog-extended
|
||||||
|
// https://github.com/btzy/nativefiledialog-extended/blob/29e3bcb578345b9fa345d1d7683f00c150565ca3/src/nfd_gtk.cpp#L384-L437
|
||||||
|
GdkDisplay* gdkDisplay = gdk_x11_lookup_xdisplay( display );
|
||||||
|
if( gdkDisplay == NULL ) {
|
||||||
|
// search for existing X11 display (there should only be one, even if multiple screens are connected)
|
||||||
|
GdkDisplayManager* displayManager = gdk_display_manager_get();
|
||||||
|
GSList* displays = gdk_display_manager_list_displays( displayManager );
|
||||||
|
for( GSList* l = displays; l; l = l->next ) {
|
||||||
|
if( GDK_IS_X11_DISPLAY( l->data ) ) {
|
||||||
|
gdkDisplay = GDK_DISPLAY( l->data );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_slist_free( displays );
|
||||||
|
|
||||||
|
// create our own X11 display
|
||||||
|
if( gdkDisplay == NULL ) {
|
||||||
|
gdk_set_allowed_backends( "x11" );
|
||||||
|
gdkDisplay = gdk_display_manager_open_display( displayManager, NULL );
|
||||||
|
gdk_set_allowed_backends( NULL );
|
||||||
|
|
||||||
|
if( gdkDisplay == NULL )
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gdk_x11_window_foreign_new_for_display( gdkDisplay, w );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_realize( GtkWidget* dialog, gpointer data ) {
|
||||||
|
GdkWindow* gdkOwner = static_cast<GdkWindow*>( data );
|
||||||
|
|
||||||
|
// make file dialog a transient of owner window,
|
||||||
|
// which centers file dialog on owner and keeps file dialog above owner
|
||||||
|
gdk_window_set_transient_for( gtk_widget_get_window( dialog ), gdkOwner );
|
||||||
|
|
||||||
|
// necessary because gdk_x11_window_foreign_new_for_display() increases the reference counter
|
||||||
|
g_object_unref( gdkOwner );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ResponseData {
|
||||||
|
JNIEnv* env;
|
||||||
|
jobject callback;
|
||||||
|
GSList* fileList;
|
||||||
|
|
||||||
|
ResponseData( JNIEnv* _env, jobject _callback ) {
|
||||||
|
env = _env;
|
||||||
|
callback = _callback;
|
||||||
|
fileList = NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void handle_response( GtkWidget* dialog, gint responseId, gpointer data ) {
|
||||||
|
// get filenames if user pressed OK
|
||||||
|
if( responseId == GTK_RESPONSE_ACCEPT ) {
|
||||||
|
ResponseData *response = static_cast<ResponseData*>( data );
|
||||||
|
if( response->callback != NULL ) {
|
||||||
|
GSList* fileList = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER( dialog ) );
|
||||||
|
jobjectArray files = fileListToStringArray( response->env, fileList );
|
||||||
|
|
||||||
|
GtkWindow* window = GTK_WINDOW( dialog );
|
||||||
|
|
||||||
|
// invoke callback: boolean approve( String[] files, long hwnd );
|
||||||
|
jclass cls = response->env->GetObjectClass( response->callback );
|
||||||
|
jmethodID approveID = response->env->GetMethodID( cls, "approve", "([Ljava/lang/String;J)Z" );
|
||||||
|
if( approveID != NULL && !response->env->CallBooleanMethod( response->callback, approveID, files, window ) )
|
||||||
|
return; // keep dialog open
|
||||||
|
}
|
||||||
|
|
||||||
|
response->fileList = gtk_file_chooser_get_filenames( GTK_FILE_CHOOSER( dialog ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide/destroy file dialog and quit loop
|
||||||
|
gtk_widget_hide( dialog );
|
||||||
|
gtk_widget_destroy( dialog );
|
||||||
|
gtk_main_quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- JNI methods ------------------------------------------------------------
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_showFileChooser
|
||||||
|
( JNIEnv* env, jclass cls, jobject owner, jboolean open,
|
||||||
|
jstring title, jstring okButtonLabel, jstring currentName, jstring currentFolder,
|
||||||
|
jint optionsSet, jint optionsClear, jobject callback, jint fileTypeIndex, jobjectArray fileTypes )
|
||||||
|
{
|
||||||
|
// initialize GTK
|
||||||
|
if( !gtk_init_check( NULL, NULL ) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// convert Java strings to C strings
|
||||||
|
AutoReleaseStringUTF8 ctitle( env, title );
|
||||||
|
AutoReleaseStringUTF8 cokButtonLabel( env, okButtonLabel );
|
||||||
|
AutoReleaseStringUTF8 ccurrentName( env, currentName );
|
||||||
|
AutoReleaseStringUTF8 ccurrentFolder( env, currentFolder );
|
||||||
|
|
||||||
|
// create GTK file chooser dialog
|
||||||
|
// https://docs.gtk.org/gtk3/class.FileChooserDialog.html
|
||||||
|
bool selectFolder = isOptionSet( FC_select_folder );
|
||||||
|
bool multiSelect = isOptionSet( FC_select_multiple );
|
||||||
|
GtkWidget* dialog = gtk_file_chooser_dialog_new(
|
||||||
|
(ctitle != NULL) ? ctitle
|
||||||
|
: (selectFolder ? (multiSelect ? _("Select Folders") : _("Select Folder"))
|
||||||
|
: (open ? ((multiSelect ? _("Open Files") : _("Open File"))) : _("Save File"))),
|
||||||
|
NULL, // can not use AWT X11 window as parent because GtkWindow is required
|
||||||
|
selectFolder ? GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
|
||||||
|
: (open ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE),
|
||||||
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
||||||
|
(cokButtonLabel != NULL) ? cokButtonLabel
|
||||||
|
: (selectFolder ? _("_Select") : (open ? _("_Open") : _("_Save"))), GTK_RESPONSE_ACCEPT,
|
||||||
|
NULL ); // marks end of buttons
|
||||||
|
GtkFileChooser* chooser = GTK_FILE_CHOOSER( dialog );
|
||||||
|
|
||||||
|
// set current name and folder
|
||||||
|
if( !open && ccurrentName != NULL )
|
||||||
|
gtk_file_chooser_set_current_name( chooser, ccurrentName );
|
||||||
|
if( ccurrentFolder != NULL )
|
||||||
|
gtk_file_chooser_set_current_folder( chooser, ccurrentFolder );
|
||||||
|
|
||||||
|
// set options
|
||||||
|
if( isOptionSetOrClear( FC_select_multiple ) )
|
||||||
|
gtk_file_chooser_set_select_multiple( chooser, isOptionSet( FC_select_multiple ) );
|
||||||
|
if( isOptionSetOrClear( FC_show_hidden ) )
|
||||||
|
gtk_file_chooser_set_show_hidden( chooser, isOptionSet( FC_show_hidden ) );
|
||||||
|
if( isOptionSetOrClear( FC_local_only ) )
|
||||||
|
gtk_file_chooser_set_local_only( chooser, isOptionSet( FC_local_only ) );
|
||||||
|
if( isOptionSetOrClear( FC_do_overwrite_confirmation ) )
|
||||||
|
gtk_file_chooser_set_do_overwrite_confirmation( chooser, isOptionSet( FC_do_overwrite_confirmation ) );
|
||||||
|
if( isOptionSetOrClear( FC_create_folders ) )
|
||||||
|
gtk_file_chooser_set_create_folders( chooser, isOptionSet( FC_create_folders ) );
|
||||||
|
|
||||||
|
// initialize filter
|
||||||
|
initFilters( chooser, env, fileTypeIndex, fileTypes );
|
||||||
|
|
||||||
|
// setup modality
|
||||||
|
GdkWindow* gdkOwner = (owner != NULL) ? getGdkWindow( env, owner ) : NULL;
|
||||||
|
if( gdkOwner != NULL ) {
|
||||||
|
gtk_window_set_modal( GTK_WINDOW( dialog ), true );
|
||||||
|
|
||||||
|
// file dialog should use same screen as owner
|
||||||
|
gtk_window_set_screen( GTK_WINDOW( dialog ), gdk_window_get_screen( gdkOwner ) );
|
||||||
|
|
||||||
|
// set the transient when the file dialog is realized
|
||||||
|
g_signal_connect( dialog, "realize", G_CALLBACK( handle_realize ), gdkOwner );
|
||||||
|
}
|
||||||
|
|
||||||
|
// show dialog
|
||||||
|
// (similar to what's done in sun_awt_X11_GtkFileDialogPeer.c)
|
||||||
|
ResponseData responseData( env, callback );
|
||||||
|
g_signal_connect( dialog, "response", G_CALLBACK( handle_response ), &responseData );
|
||||||
|
gtk_widget_show( dialog );
|
||||||
|
|
||||||
|
// necessary to bring file dialog to the front (and make it active)
|
||||||
|
// see issues:
|
||||||
|
// https://github.com/btzy/nativefiledialog-extended/issues/31
|
||||||
|
// https://github.com/mlabbe/nativefiledialog/pull/92
|
||||||
|
// https://github.com/guillaumechereau/noc/pull/11
|
||||||
|
if( GDK_IS_X11_DISPLAY( gtk_widget_get_display( GTK_WIDGET( dialog ) ) ) ) {
|
||||||
|
GdkWindow* gdkWindow = gtk_widget_get_window( GTK_WIDGET( dialog ) );
|
||||||
|
gdk_window_set_events( gdkWindow, static_cast<GdkEventMask>( gdk_window_get_events( gdkWindow ) | GDK_PROPERTY_CHANGE_MASK ) );
|
||||||
|
gtk_window_present_with_time( GTK_WINDOW( dialog ), gdk_x11_get_server_time( gdkWindow ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// start event loop (will be quit in respone handler)
|
||||||
|
gtk_main();
|
||||||
|
|
||||||
|
// canceled?
|
||||||
|
if( responseData.fileList == NULL )
|
||||||
|
return newJavaStringArray( env, 0 );
|
||||||
|
|
||||||
|
// convert GSList to Java string array
|
||||||
|
return fileListToStringArray( env, responseData.fileList );
|
||||||
|
}
|
||||||
|
|
||||||
|
static jobjectArray fileListToStringArray( JNIEnv* env, GSList* fileList ) {
|
||||||
|
guint count = g_slist_length( fileList );
|
||||||
|
jobjectArray array = newJavaStringArray( env, count );
|
||||||
|
GSList* it = fileList;
|
||||||
|
for( int i = 0; i < count; i++, it = it->next ) {
|
||||||
|
gchar* path = (gchar*) it->data;
|
||||||
|
jstring jpath = env->NewStringUTF( path );
|
||||||
|
g_free( path );
|
||||||
|
|
||||||
|
env->SetObjectArrayElement( array, i, jpath );
|
||||||
|
env->DeleteLocalRef( jpath );
|
||||||
|
}
|
||||||
|
g_slist_free( fileList );
|
||||||
|
return array;
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <jawt.h>
|
||||||
|
#include <linux/jawt_md.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include "JNIUtils.h"
|
||||||
|
#include "com_formdev_flatlaf_ui_FlatNativeLinuxLibrary.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_showMessageDialog
|
||||||
|
( JNIEnv* env, jclass cls, jlong hwndParent, jint messageType, jstring primaryText, jstring secondaryText,
|
||||||
|
jint defaultButton, jobjectArray buttons )
|
||||||
|
{
|
||||||
|
GtkWindow* window = (GtkWindow*) hwndParent;
|
||||||
|
|
||||||
|
// convert message type
|
||||||
|
GtkMessageType gmessageType;
|
||||||
|
switch( messageType ) {
|
||||||
|
case /* JOptionPane.ERROR_MESSAGE */ 0: gmessageType = GTK_MESSAGE_ERROR; break;
|
||||||
|
case /* JOptionPane.INFORMATION_MESSAGE */ 1: gmessageType = GTK_MESSAGE_INFO; break;
|
||||||
|
case /* JOptionPane.WARNING_MESSAGE */ 2: gmessageType = GTK_MESSAGE_WARNING; break;
|
||||||
|
case /* JOptionPane.QUESTION_MESSAGE */ 3: gmessageType = GTK_MESSAGE_QUESTION; break;
|
||||||
|
default:
|
||||||
|
case /* JOptionPane.PLAIN_MESSAGE */ -1: gmessageType = GTK_MESSAGE_OTHER; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert Java strings to C strings
|
||||||
|
AutoReleaseStringUTF8 cprimaryText( env, primaryText );
|
||||||
|
AutoReleaseStringUTF8 csecondaryText( env, secondaryText );
|
||||||
|
|
||||||
|
// create GTK file chooser dialog
|
||||||
|
// https://docs.gtk.org/gtk3/class.MessageDialog.html
|
||||||
|
jint buttonCount = env->GetArrayLength( buttons );
|
||||||
|
GtkWidget* dialog = gtk_message_dialog_new( window, GTK_DIALOG_MODAL, gmessageType,
|
||||||
|
(buttonCount > 0) ? GTK_BUTTONS_NONE : GTK_BUTTONS_OK,
|
||||||
|
"%s", (const gchar*) cprimaryText );
|
||||||
|
if( csecondaryText != NULL )
|
||||||
|
gtk_message_dialog_format_secondary_text( GTK_MESSAGE_DIALOG( dialog ), "%s", (const gchar*) csecondaryText );
|
||||||
|
|
||||||
|
// add buttons
|
||||||
|
for( int i = 0; i < buttonCount; i++ ) {
|
||||||
|
AutoReleaseStringUTF8 str( env, (jstring) env->GetObjectArrayElement( buttons, i ) );
|
||||||
|
gtk_dialog_add_button( GTK_DIALOG( dialog ), str, i );
|
||||||
|
}
|
||||||
|
|
||||||
|
// set default button
|
||||||
|
gtk_dialog_set_default_response( GTK_DIALOG( dialog ), MIN( MAX( defaultButton, 0 ), buttonCount - 1 ) );
|
||||||
|
|
||||||
|
// show message dialog
|
||||||
|
gint responseID = gtk_dialog_run( GTK_DIALOG( dialog ) );
|
||||||
|
gtk_widget_destroy( dialog );
|
||||||
|
|
||||||
|
// return -1 if closed with ESC key
|
||||||
|
return (responseID >= 0) ? responseID : -1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// avoid inlining of printf()
|
||||||
|
#define _NO_CRT_STDIO_INLINE
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include "JNIUtils.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---- class AutoReleaseStringUTF8 --------------------------------------------
|
||||||
|
|
||||||
|
AutoReleaseStringUTF8::AutoReleaseStringUTF8( JNIEnv* _env, jstring _javaString ) {
|
||||||
|
env = _env;
|
||||||
|
javaString = _javaString;
|
||||||
|
chars = (javaString != NULL) ? env->GetStringUTFChars( javaString, NULL ) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoReleaseStringUTF8::~AutoReleaseStringUTF8() {
|
||||||
|
if( chars != NULL )
|
||||||
|
env->ReleaseStringUTFChars( javaString, chars );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- JNI methods ------------------------------------------------------------
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_isLibAvailable
|
||||||
|
( JNIEnv* env, jclass cls, jstring libname )
|
||||||
|
{
|
||||||
|
AutoReleaseStringUTF8 clibname( env, libname );
|
||||||
|
|
||||||
|
void* lib = dlopen( clibname, RTLD_LAZY );
|
||||||
|
if( lib == NULL )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dlclose( lib );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
@@ -25,18 +25,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
bool sendEvent( JNIEnv *env, jobject window, const char *atom_name,
|
// declare exported methods
|
||||||
long data0, long data1, long data2, long data3, long data4 );
|
|
||||||
bool isWMHintSupported( Display* display, Window rootWindow, Atom atom );
|
|
||||||
Window getWindowHandle( JNIEnv* env, JAWT* awt, jobject window, Display** display_return );
|
Window getWindowHandle( JNIEnv* env, JAWT* awt, jobject window, Display** display_return );
|
||||||
|
|
||||||
|
// declare internal methods
|
||||||
|
static bool sendEvent( JNIEnv *env, jobject window, const char *atom_name,
|
||||||
|
long data0, long data1, long data2, long data3, long data4 );
|
||||||
|
static bool isWMHintSupported( Display* display, Window rootWindow, Atom atom );
|
||||||
|
|
||||||
|
|
||||||
//---- JNI methods ------------------------------------------------------------
|
//---- JNI methods ------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send _NET_WM_MOVERESIZE to window to initiate moving or resizing.
|
* Send _NET_WM_MOVERESIZE to window to initiate moving or resizing.
|
||||||
*
|
*
|
||||||
* https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html#idm45446104441728
|
* https://specifications.freedesktop.org/wm-spec/latest/ar01s04.html#id-1.5.4
|
||||||
* https://gitlab.gnome.org/GNOME/gtk/-/blob/main/gdk/x11/gdksurface-x11.c#L3841-3881
|
* https://gitlab.gnome.org/GNOME/gtk/-/blob/main/gdk/x11/gdksurface-x11.c#L3841-3881
|
||||||
*/
|
*/
|
||||||
extern "C"
|
extern "C"
|
||||||
@@ -79,7 +82,7 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_xS
|
|||||||
0 );
|
0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sendEvent( JNIEnv *env, jobject window, const char *atom_name,
|
static bool sendEvent( JNIEnv *env, jobject window, const char *atom_name,
|
||||||
long data0, long data1, long data2, long data3, long data4 )
|
long data0, long data1, long data2, long data3, long data4 )
|
||||||
{
|
{
|
||||||
// get the AWT
|
// get the AWT
|
||||||
@@ -131,7 +134,7 @@ bool sendEvent( JNIEnv *env, jobject window, const char *atom_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool isWMHintSupported( Display* display, Window rootWindow, Atom atom ) {
|
static bool isWMHintSupported( Display* display, Window rootWindow, Atom atom ) {
|
||||||
Atom type;
|
Atom type;
|
||||||
int format;
|
int format;
|
||||||
unsigned long n_atoms;
|
unsigned long n_atoms;
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---- class AutoReleaseStringUTF8 --------------------------------------------
|
||||||
|
|
||||||
|
class AutoReleaseStringUTF8 {
|
||||||
|
JNIEnv* env;
|
||||||
|
jstring javaString;
|
||||||
|
const char* chars;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AutoReleaseStringUTF8( JNIEnv* _env, jstring _javaString );
|
||||||
|
~AutoReleaseStringUTF8();
|
||||||
|
|
||||||
|
operator const gchar*() { return chars; }
|
||||||
|
};
|
||||||
@@ -9,6 +9,18 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
#undef com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_MOVE
|
#undef com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_MOVE
|
||||||
#define com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_MOVE 8L
|
#define com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_MOVE 8L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_select_folder
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_select_folder 1L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_select_multiple
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_select_multiple 2L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_show_hidden
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_show_hidden 4L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_local_only
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_local_only 8L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_do_overwrite_confirmation
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_do_overwrite_confirmation 16L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_create_folders
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_FC_create_folders 32L
|
||||||
/*
|
/*
|
||||||
* Class: com_formdev_flatlaf_ui_FlatNativeLinuxLibrary
|
* Class: com_formdev_flatlaf_ui_FlatNativeLinuxLibrary
|
||||||
* Method: xMoveOrResizeWindow
|
* Method: xMoveOrResizeWindow
|
||||||
@@ -25,6 +37,30 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_xM
|
|||||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_xShowWindowMenu
|
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_xShowWindowMenu
|
||||||
(JNIEnv *, jclass, jobject, jint, jint);
|
(JNIEnv *, jclass, jobject, jint, jint);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_formdev_flatlaf_ui_FlatNativeLinuxLibrary
|
||||||
|
* Method: isLibAvailable
|
||||||
|
* Signature: (Ljava/lang/String;)Z
|
||||||
|
*/
|
||||||
|
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_isLibAvailable
|
||||||
|
(JNIEnv *, jclass, jstring);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_formdev_flatlaf_ui_FlatNativeLinuxLibrary
|
||||||
|
* Method: showFileChooser
|
||||||
|
* Signature: (Ljava/awt/Window;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILcom/formdev/flatlaf/ui/FlatNativeLinuxLibrary/FileChooserCallback;I[Ljava/lang/String;)[Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_showFileChooser
|
||||||
|
(JNIEnv *, jclass, jobject, jboolean, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_formdev_flatlaf_ui_FlatNativeLinuxLibrary
|
||||||
|
* Method: showMessageDialog
|
||||||
|
* Signature: (JILjava/lang/String;Ljava/lang/String;I[Ljava/lang/String;)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeLinuxLibrary_showMessageDialog
|
||||||
|
(JNIEnv *, jclass, jlong, jint, jstring, jstring, jint, jobjectArray);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ tasks {
|
|||||||
|
|
||||||
compilerArgs.addAll( toolChain.map {
|
compilerArgs.addAll( toolChain.map {
|
||||||
when( it ) {
|
when( it ) {
|
||||||
is Gcc, is Clang -> listOf( "-x", "objective-c++", "-mmacosx-version-min=$minOs" )
|
is Gcc, is Clang -> listOf( "-x", "objective-c++", "-mmacosx-version-min=$minOs", "-fvisibility=hidden" )
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
|
|||||||
@@ -46,7 +46,33 @@
|
|||||||
JNI_COCOA_CATCH() \
|
JNI_COCOA_CATCH() \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define JNI_THREAD_ENTER( jvm, returnValue ) \
|
||||||
|
JNIEnv *env; \
|
||||||
|
bool detach = false; \
|
||||||
|
switch( jvm->GetEnv( (void**) &env, JNI_VERSION_1_6 ) ) { \
|
||||||
|
case JNI_OK: break; \
|
||||||
|
case JNI_EDETACHED: \
|
||||||
|
if( jvm->AttachCurrentThread( (void**) &env, NULL ) != JNI_OK ) \
|
||||||
|
return returnValue; \
|
||||||
|
detach = true; \
|
||||||
|
break; \
|
||||||
|
default: return returnValue; \
|
||||||
|
} \
|
||||||
|
@try {
|
||||||
|
|
||||||
|
#define JNI_THREAD_EXIT( jvm ) \
|
||||||
|
} @finally { \
|
||||||
|
if( env->ExceptionCheck() ) \
|
||||||
|
env->ExceptionDescribe(); \
|
||||||
|
if( detach ) \
|
||||||
|
jvm->DetachCurrentThread(); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
jclass findClass( JNIEnv *env, const char* className, bool globalRef );
|
jclass findClass( JNIEnv *env, const char* className, bool globalRef );
|
||||||
jfieldID getFieldID( JNIEnv *env, jclass cls, const char* fieldName, const char* fieldSignature, bool staticField );
|
jfieldID getFieldID( JNIEnv *env, jclass cls, const char* fieldName, const char* fieldSignature, bool staticField );
|
||||||
jmethodID getMethodID( JNIEnv *env, jclass cls, const char* methodName, const char* methodSignature, bool staticMethod );
|
jmethodID getMethodID( JNIEnv *env, jclass cls, const char* methodName, const char* methodSignature, bool staticMethod );
|
||||||
|
|
||||||
|
NSString* JavaToNSString( JNIEnv *env, jstring javaString );
|
||||||
|
jstring NSToJavaString( JNIEnv *env, NSString *nsString );
|
||||||
|
jstring NormalizedPathJavaFromNSString( JNIEnv* env, NSString *nsString );
|
||||||
|
|||||||
@@ -13,6 +13,32 @@ extern "C" {
|
|||||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_MEDIUM 1L
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_MEDIUM 1L
|
||||||
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_LARGE
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_LARGE
|
||||||
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_LARGE 2L
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_BUTTONS_SPACING_LARGE 2L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_canChooseFiles
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_canChooseFiles 1L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_canChooseDirectories
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_canChooseDirectories 2L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_resolvesAliases
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_resolvesAliases 4L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_allowsMultipleSelection
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_allowsMultipleSelection 8L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_accessoryViewDisclosed
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_accessoryViewDisclosed 16L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_showsTagField
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_showsTagField 256L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_canCreateDirectories
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_canCreateDirectories 512L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_canSelectHiddenExtension
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_canSelectHiddenExtension 1024L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_showsHiddenFiles
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_showsHiddenFiles 2048L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_extensionHidden
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_extensionHidden 4096L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_allowsOtherFileTypes
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_allowsOtherFileTypes 8192L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_treatsFilePackagesAsDirectories
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_treatsFilePackagesAsDirectories 16384L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_showSingleFilterField
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeMacLibrary_FC_showSingleFilterField 16777216L
|
||||||
/*
|
/*
|
||||||
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||||
* Method: setWindowRoundedBorder
|
* Method: setWindowRoundedBorder
|
||||||
@@ -53,6 +79,22 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_isWi
|
|||||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_toggleWindowFullScreen
|
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_toggleWindowFullScreen
|
||||||
(JNIEnv *, jclass, jobject);
|
(JNIEnv *, jclass, jobject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||||
|
* Method: showFileChooser
|
||||||
|
* Signature: (Ljava/awt/Window;IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILcom/formdev/flatlaf/ui/FlatNativeMacLibrary/FileChooserCallback;I[Ljava/lang/String;)[Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_showFileChooser
|
||||||
|
(JNIEnv *, jclass, jobject, jint, jboolean, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_formdev_flatlaf_ui_FlatNativeMacLibrary
|
||||||
|
* Method: showMessageDialog
|
||||||
|
* Signature: (JILjava/lang/String;Ljava/lang/String;I[Ljava/lang/String;)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_showMessageDialog
|
||||||
|
(JNIEnv *, jclass, jlong, jint, jstring, jstring, jint, jobjectArray);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <jni.h>
|
#import <jni.h>
|
||||||
#include "com_formdev_flatlaf_ui_FlatNativeLibrary.h"
|
#import "com_formdev_flatlaf_ui_FlatNativeLibrary.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
// increase this version if changing API or functionality of native library
|
// increase this version if changing API or functionality of native library
|
||||||
// also update version in Java class com.formdev.flatlaf.ui.FlatNativeMacLibrary
|
// also update version in Java class com.formdev.flatlaf.ui.FlatNativeMacLibrary
|
||||||
#define API_VERSION_MACOS 2001
|
#define API_VERSION_MACOS 2002
|
||||||
|
|
||||||
|
|
||||||
//---- JNI methods ------------------------------------------------------------
|
//---- JNI methods ------------------------------------------------------------
|
||||||
|
|||||||
@@ -75,3 +75,38 @@ jmethodID getMethodID( JNIEnv *env, jclass cls, const char* methodName, const ch
|
|||||||
|
|
||||||
return methodID;
|
return methodID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSString* JavaToNSString( JNIEnv *env, jstring javaString ) {
|
||||||
|
if( javaString == NULL )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
int len = env->GetStringLength( javaString );
|
||||||
|
const jchar* chars = env->GetStringChars( javaString, NULL );
|
||||||
|
if( chars == NULL )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
NSString* nsString = [NSString stringWithCharacters:(unichar*)chars length:len];
|
||||||
|
env->ReleaseStringChars( javaString, chars );
|
||||||
|
return nsString;
|
||||||
|
}
|
||||||
|
|
||||||
|
jstring NSToJavaString( JNIEnv *env, NSString *nsString ) {
|
||||||
|
if( nsString == NULL )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
jsize len = [nsString length];
|
||||||
|
unichar* buffer = (unichar*) calloc( len, sizeof( unichar ) );
|
||||||
|
if( buffer == NULL )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
[nsString getCharacters:buffer];
|
||||||
|
jstring javaString = env->NewString( buffer, len );
|
||||||
|
free( buffer );
|
||||||
|
return javaString;
|
||||||
|
}
|
||||||
|
|
||||||
|
jstring NormalizedPathJavaFromNSString( JNIEnv* env, NSString *nsString ) {
|
||||||
|
return (nsString != NULL)
|
||||||
|
? NSToJavaString( env, [nsString precomposedStringWithCanonicalMapping] )
|
||||||
|
: NULL;
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,406 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
#import <jni.h>
|
||||||
|
#import "JNIUtils.h"
|
||||||
|
#import "JNFRunLoop.h"
|
||||||
|
#import "com_formdev_flatlaf_ui_FlatNativeMacLibrary.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
|
||||||
|
// declare internal methods
|
||||||
|
static jobjectArray newJavaStringArray( JNIEnv* env, jsize count );
|
||||||
|
static jobjectArray urlsToStringArray( JNIEnv* env, NSArray* urls );
|
||||||
|
static NSArray* getDialogURLs( NSSavePanel* dialog );
|
||||||
|
|
||||||
|
//---- class FileChooserDelegate ----------------------------------------------
|
||||||
|
|
||||||
|
@interface FileChooserDelegate : NSObject <NSOpenSavePanelDelegate, NSWindowDelegate> {
|
||||||
|
NSArray* _filters;
|
||||||
|
|
||||||
|
JavaVM* _jvm;
|
||||||
|
jobject _callback;
|
||||||
|
NSMutableSet* _urlsSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@property (nonatomic, assign) NSSavePanel* dialog;
|
||||||
|
|
||||||
|
- (void) initFilterAccessoryView: (NSMutableArray*)filters :(int)filterIndex
|
||||||
|
:(NSString*)filterFieldLabel :(bool)showSingleFilterField;
|
||||||
|
- (void) selectFormat: (id)sender;
|
||||||
|
- (void) selectFormatAtIndex: (int)index;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation FileChooserDelegate
|
||||||
|
|
||||||
|
- (void) initFilterAccessoryView: (NSMutableArray*)filters :(int)filterIndex
|
||||||
|
:(NSString*)filterFieldLabel :(bool)showSingleFilterField
|
||||||
|
{
|
||||||
|
_filters = filters;
|
||||||
|
|
||||||
|
// get filter names
|
||||||
|
NSArray* filterNames = filters.lastObject;
|
||||||
|
[filters removeLastObject];
|
||||||
|
|
||||||
|
// do not add filter/format combobox if there is only one filter
|
||||||
|
if( filters.count <= 1 && !showSingleFilterField ) {
|
||||||
|
[self selectFormatAtIndex:0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create label
|
||||||
|
NSTextField* label = [[NSTextField alloc] initWithFrame:NSZeroRect];
|
||||||
|
label.stringValue = (filterFieldLabel != NULL) ? filterFieldLabel : @"Format:";
|
||||||
|
label.editable = NO;
|
||||||
|
label.bordered = NO;
|
||||||
|
label.bezeled = NO;
|
||||||
|
label.drawsBackground = NO;
|
||||||
|
|
||||||
|
// create combobox
|
||||||
|
NSPopUpButton* popupButton = [[NSPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:NO];
|
||||||
|
[popupButton addItemsWithTitles:filterNames];
|
||||||
|
[popupButton selectItemAtIndex:MIN( MAX( filterIndex, 0 ), filterNames.count - 1 )];
|
||||||
|
[popupButton setTarget:self];
|
||||||
|
[popupButton setAction:@selector(selectFormat:)];
|
||||||
|
|
||||||
|
// create view
|
||||||
|
NSView* accessoryView = [[NSView alloc] initWithFrame:NSZeroRect];
|
||||||
|
[accessoryView addSubview:label];
|
||||||
|
[accessoryView addSubview:popupButton];
|
||||||
|
|
||||||
|
// autolayout
|
||||||
|
label.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
popupButton.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
|
int labelWidth = label.intrinsicContentSize.width;
|
||||||
|
int gap = 12;
|
||||||
|
int popupButtonWidth = popupButton.intrinsicContentSize.width;
|
||||||
|
int popupButtonMinimumWidth = 140;
|
||||||
|
int totalWidth = labelWidth + gap + MAX( popupButtonWidth, popupButtonMinimumWidth );
|
||||||
|
[accessoryView addConstraints:@[
|
||||||
|
// horizontal layout
|
||||||
|
[label.leadingAnchor constraintEqualToAnchor:accessoryView.centerXAnchor constant:-(totalWidth / 2)],
|
||||||
|
[popupButton.leadingAnchor constraintEqualToAnchor:label.trailingAnchor constant:gap],
|
||||||
|
[popupButton.widthAnchor constraintGreaterThanOrEqualToConstant:popupButtonMinimumWidth],
|
||||||
|
|
||||||
|
// vertical layout
|
||||||
|
[popupButton.topAnchor constraintEqualToAnchor:accessoryView.topAnchor constant:8],
|
||||||
|
[popupButton.bottomAnchor constraintEqualToAnchor:accessoryView.bottomAnchor constant:-8],
|
||||||
|
[label.firstBaselineAnchor constraintEqualToAnchor:popupButton.firstBaselineAnchor],
|
||||||
|
]];
|
||||||
|
|
||||||
|
[_dialog setAccessoryView:accessoryView];
|
||||||
|
|
||||||
|
// initial filter
|
||||||
|
[self selectFormatAtIndex:filterIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) selectFormat: (id)sender {
|
||||||
|
NSPopUpButton* popupButton = (NSPopUpButton*) sender;
|
||||||
|
[self selectFormatAtIndex:popupButton.indexOfSelectedItem];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) selectFormatAtIndex: (int)index {
|
||||||
|
index = MIN( MAX( index, 0 ), _filters.count - 1 );
|
||||||
|
NSArray* fileTypes = [_filters objectAtIndex:index];
|
||||||
|
|
||||||
|
// use deprecated allowedFileTypes instead of newer allowedContentTypes (since macOS 11+)
|
||||||
|
// to support older macOS versions 10.14+ and because of some problems with allowedContentTypes:
|
||||||
|
// https://github.com/chromium/chromium/blob/d8e0032963b7ca4728ff4117933c0feb3e479b7a/components/remote_cocoa/app_shim/select_file_dialog_bridge.mm#L209-232
|
||||||
|
_dialog.allowedFileTypes = [fileTypes containsObject:@"*"] ? nil : fileTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- NSOpenSavePanelDelegate ----
|
||||||
|
|
||||||
|
- (void) initCallback: (JavaVM*)jvm :(jobject)callback {
|
||||||
|
_jvm = jvm;
|
||||||
|
_callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) panel: (id) sender validateURL:(NSURL*) url error:(NSError**) outError {
|
||||||
|
JNI_COCOA_TRY()
|
||||||
|
|
||||||
|
if( _callback == NULL )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
NSArray* urls = getDialogURLs( sender );
|
||||||
|
|
||||||
|
// if multiple files are selected for opening, then the validateURL method
|
||||||
|
// is invoked for earch file, but our callback should be invoked only once for all files
|
||||||
|
if( urls != NULL && urls.count > 1 ) {
|
||||||
|
if( _urlsSet == NULL ) {
|
||||||
|
// invoked for first selected file --> invoke callback
|
||||||
|
_urlsSet = [NSMutableSet setWithArray:urls];
|
||||||
|
[_urlsSet removeObject:url];
|
||||||
|
} else {
|
||||||
|
// invoked for other selected files --> do not invoke callback
|
||||||
|
[_urlsSet removeObject:url];
|
||||||
|
if( _urlsSet.count == 0 )
|
||||||
|
_urlsSet = NULL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JNI_THREAD_ENTER( _jvm, true )
|
||||||
|
|
||||||
|
jobjectArray files = urlsToStringArray( env, urls );
|
||||||
|
jlong window = (jlong) sender;
|
||||||
|
|
||||||
|
// invoke callback: boolean approve( String[] files, long hwnd );
|
||||||
|
jclass cls = env->GetObjectClass( _callback );
|
||||||
|
jmethodID approveID = env->GetMethodID( cls, "approve", "([Ljava/lang/String;J)Z" );
|
||||||
|
if( approveID != NULL && !env->CallBooleanMethod( _callback, approveID, files, window ) ) {
|
||||||
|
_urlsSet = NULL;
|
||||||
|
return false; // keep dialog open
|
||||||
|
}
|
||||||
|
|
||||||
|
JNI_THREAD_EXIT( _jvm )
|
||||||
|
JNI_COCOA_CATCH()
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- NSWindowDelegate ----
|
||||||
|
|
||||||
|
- (void) windowDidBecomeMain:(NSNotification *) notification {
|
||||||
|
JNI_COCOA_TRY()
|
||||||
|
|
||||||
|
// Disable main menu bar because the file dialog is modal and it should be not possible
|
||||||
|
// to select any menu item. Otherwiese an action could show a Swing dialog, which would
|
||||||
|
// be shown under the file dialog.
|
||||||
|
//
|
||||||
|
// NOTE: It is not necessary to re-enable the main menu bar because Swing does this itself.
|
||||||
|
// When the file dialog is closed and a Swing window becomes active,
|
||||||
|
// macOS sends windowDidBecomeMain (and windowDidBecomeKey) message to AWTWindow,
|
||||||
|
// which invokes [self activateWindowMenuBar],
|
||||||
|
// which invokes [CMenuBar activate:menuBar modallyDisabled:isDisabled],
|
||||||
|
// which updates main menu bar.
|
||||||
|
NSMenu* mainMenu = [NSApp mainMenu];
|
||||||
|
int count = [mainMenu numberOfItems];
|
||||||
|
for( int i = 0; i < count; i++ ) {
|
||||||
|
NSMenuItem* menuItem = [mainMenu itemAtIndex:i];
|
||||||
|
NSMenu *subenu = [menuItem submenu];
|
||||||
|
if( [subenu isJavaMenu] )
|
||||||
|
[menuItem setEnabled:NO];
|
||||||
|
}
|
||||||
|
|
||||||
|
JNI_COCOA_CATCH()
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
//---- helper -----------------------------------------------------------------
|
||||||
|
|
||||||
|
#define isOptionSet( option ) ((optionsSet & com_formdev_flatlaf_ui_FlatNativeMacLibrary_ ## option) != 0)
|
||||||
|
#define isOptionClear( option ) ((optionsClear & com_formdev_flatlaf_ui_FlatNativeMacLibrary_ ## option) != 0)
|
||||||
|
#define isOptionSetOrClear( option ) isOptionSet( option ) || isOptionClear( option )
|
||||||
|
|
||||||
|
static jobjectArray newJavaStringArray( JNIEnv* env, jsize count ) {
|
||||||
|
jclass stringClass = env->FindClass( "java/lang/String" );
|
||||||
|
return env->NewObjectArray( count, stringClass, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static NSMutableArray* initFilters( JNIEnv* env, jobjectArray fileTypes ) {
|
||||||
|
jint length = env->GetArrayLength( fileTypes );
|
||||||
|
if( length <= 0 )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
NSMutableArray* filterNames = [NSMutableArray array];
|
||||||
|
NSMutableArray* filters = [NSMutableArray array];
|
||||||
|
NSString* filterName = NULL;
|
||||||
|
NSMutableArray* filter = NULL;
|
||||||
|
for( int i = 0; i < length; i++ ) {
|
||||||
|
jstring jstr = (jstring) env->GetObjectArrayElement( fileTypes, i );
|
||||||
|
if( jstr == NULL ) {
|
||||||
|
if( filter != NULL ) {
|
||||||
|
if( filter.count > 0 ) {
|
||||||
|
[filterNames addObject:filterName];
|
||||||
|
[filters addObject:filter];
|
||||||
|
}
|
||||||
|
filterName = NULL;
|
||||||
|
filter = NULL;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString* str = JavaToNSString( env, jstr );
|
||||||
|
env->DeleteLocalRef( jstr );
|
||||||
|
if( filter == NULL ) {
|
||||||
|
filterName = str;
|
||||||
|
filter = [NSMutableArray array];
|
||||||
|
} else
|
||||||
|
[filter addObject:str];
|
||||||
|
}
|
||||||
|
|
||||||
|
if( filters.count == 0 )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// add filter names to array (removed again after creating combobox)
|
||||||
|
[filters addObject:filterNames];
|
||||||
|
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- JNI methods ------------------------------------------------------------
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_showFileChooser
|
||||||
|
( JNIEnv* env, jclass cls, jobject owner, jint dark, jboolean open,
|
||||||
|
jstring title, jstring prompt, jstring message, jstring filterFieldLabel,
|
||||||
|
jstring nameFieldLabel, jstring nameFieldStringValue, jstring directoryURL,
|
||||||
|
jint optionsSet, jint optionsClear, jobject callback, jint fileTypeIndex, jobjectArray fileTypes )
|
||||||
|
{
|
||||||
|
JNI_COCOA_ENTER()
|
||||||
|
|
||||||
|
JavaVM* jvm;
|
||||||
|
if( env->GetJavaVM( &jvm ) != JNI_OK )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// convert Java strings to NSString (on Java thread)
|
||||||
|
NSString* nsTitle = JavaToNSString( env, title );
|
||||||
|
NSString* nsPrompt = JavaToNSString( env, prompt );
|
||||||
|
NSString* nsMessage = JavaToNSString( env, message );
|
||||||
|
NSString* nsFilterFieldLabel = JavaToNSString( env, filterFieldLabel );
|
||||||
|
NSString* nsNameFieldLabel = JavaToNSString( env, nameFieldLabel );
|
||||||
|
NSString* nsNameFieldStringValue = JavaToNSString( env, nameFieldStringValue );
|
||||||
|
NSString* nsDirectoryURL = JavaToNSString( env, directoryURL );
|
||||||
|
NSMutableArray* filters = initFilters( env, fileTypes );
|
||||||
|
|
||||||
|
NSArray* urls = NULL;
|
||||||
|
NSArray** purls = &urls;
|
||||||
|
|
||||||
|
// show file dialog on macOS thread
|
||||||
|
[FlatJNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
|
||||||
|
JNI_COCOA_TRY()
|
||||||
|
|
||||||
|
// create open/save panel
|
||||||
|
NSSavePanel* dialog = open ? [NSOpenPanel openPanel] : [NSSavePanel savePanel];
|
||||||
|
|
||||||
|
// set appearance
|
||||||
|
if( dark == 1 )
|
||||||
|
dialog.appearance = [NSAppearance appearanceNamed:NSAppearanceNameDarkAqua];
|
||||||
|
else if( dark == 0 )
|
||||||
|
dialog.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
|
||||||
|
|
||||||
|
if( nsTitle != NULL )
|
||||||
|
dialog.title = nsTitle;
|
||||||
|
if( nsPrompt != NULL )
|
||||||
|
dialog.prompt = nsPrompt;
|
||||||
|
if( nsMessage != NULL )
|
||||||
|
dialog.message = nsMessage;
|
||||||
|
if( nsNameFieldLabel != NULL )
|
||||||
|
dialog.nameFieldLabel = nsNameFieldLabel;
|
||||||
|
if( nsNameFieldStringValue != NULL )
|
||||||
|
dialog.nameFieldStringValue = nsNameFieldStringValue;
|
||||||
|
if( nsDirectoryURL != NULL )
|
||||||
|
dialog.directoryURL = [NSURL fileURLWithPath:nsDirectoryURL isDirectory:YES];
|
||||||
|
|
||||||
|
// set open options
|
||||||
|
if( open ) {
|
||||||
|
NSOpenPanel* openDialog = (NSOpenPanel*) dialog;
|
||||||
|
|
||||||
|
bool canChooseFiles = isOptionSet( FC_canChooseFiles );
|
||||||
|
bool canChooseDirectories = isOptionSet( FC_canChooseDirectories );
|
||||||
|
if( !canChooseFiles && !canChooseDirectories )
|
||||||
|
canChooseFiles = true;
|
||||||
|
openDialog.canChooseFiles = canChooseFiles;
|
||||||
|
openDialog.canChooseDirectories = canChooseDirectories;
|
||||||
|
|
||||||
|
if( isOptionSetOrClear( FC_resolvesAliases ) )
|
||||||
|
openDialog.resolvesAliases = isOptionSet( FC_resolvesAliases );
|
||||||
|
if( isOptionSetOrClear( FC_allowsMultipleSelection ) )
|
||||||
|
openDialog.allowsMultipleSelection = isOptionSet( FC_allowsMultipleSelection );
|
||||||
|
}
|
||||||
|
|
||||||
|
// set options
|
||||||
|
if( isOptionSetOrClear( FC_showsTagField ) )
|
||||||
|
dialog.showsTagField = isOptionSet( FC_showsTagField );
|
||||||
|
if( isOptionSetOrClear( FC_canCreateDirectories ) )
|
||||||
|
dialog.canCreateDirectories = isOptionSet( FC_canCreateDirectories );
|
||||||
|
if( isOptionSetOrClear( FC_canSelectHiddenExtension ) )
|
||||||
|
dialog.canSelectHiddenExtension = isOptionSet( FC_canSelectHiddenExtension );
|
||||||
|
if( isOptionSetOrClear( FC_showsHiddenFiles) )
|
||||||
|
dialog.showsHiddenFiles = isOptionSet( FC_showsHiddenFiles);
|
||||||
|
if( isOptionSetOrClear( FC_extensionHidden ) )
|
||||||
|
dialog.extensionHidden = isOptionSet( FC_extensionHidden );
|
||||||
|
if( isOptionSetOrClear( FC_allowsOtherFileTypes ) )
|
||||||
|
dialog.allowsOtherFileTypes = isOptionSet( FC_allowsOtherFileTypes );
|
||||||
|
if( isOptionSetOrClear( FC_treatsFilePackagesAsDirectories ) )
|
||||||
|
dialog.treatsFilePackagesAsDirectories = isOptionSet( FC_treatsFilePackagesAsDirectories );
|
||||||
|
|
||||||
|
FileChooserDelegate* delegate = [FileChooserDelegate new];
|
||||||
|
delegate.dialog = dialog;
|
||||||
|
|
||||||
|
// initialize filter accessory view
|
||||||
|
if( filters != NULL ) {
|
||||||
|
[delegate initFilterAccessoryView:filters :fileTypeIndex :nsFilterFieldLabel :isOptionSet( FC_showSingleFilterField )];
|
||||||
|
|
||||||
|
if( open && isOptionSetOrClear( FC_accessoryViewDisclosed ) )
|
||||||
|
((NSOpenPanel*)dialog).accessoryViewDisclosed = isOptionSet( FC_accessoryViewDisclosed );
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize callback
|
||||||
|
if( callback != NULL )
|
||||||
|
[delegate initCallback :jvm :callback];
|
||||||
|
|
||||||
|
// set file dialog delegate
|
||||||
|
dialog.delegate = delegate;
|
||||||
|
|
||||||
|
// show dialog
|
||||||
|
NSModalResponse response = [dialog runModal];
|
||||||
|
[delegate release];
|
||||||
|
if( response != NSModalResponseOK ) {
|
||||||
|
*purls = @[];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*purls = getDialogURLs( dialog );
|
||||||
|
|
||||||
|
JNI_COCOA_CATCH()
|
||||||
|
}];
|
||||||
|
|
||||||
|
if( urls == NULL )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// convert URLs to Java string array
|
||||||
|
return urlsToStringArray( env, urls );
|
||||||
|
|
||||||
|
JNI_COCOA_EXIT()
|
||||||
|
}
|
||||||
|
|
||||||
|
static NSArray* getDialogURLs( NSSavePanel* dialog ) {
|
||||||
|
if( [dialog isKindOfClass:[NSOpenPanel class]] )
|
||||||
|
return [[NSArray alloc] initWithArray: static_cast<NSOpenPanel*>(dialog).URLs];
|
||||||
|
|
||||||
|
NSURL* url = dialog.URL;
|
||||||
|
// use '[[NSArray alloc] initWithObject:url]' here because '@[url]' crashes on macOS 10.14
|
||||||
|
return (url != NULL) ? [[NSArray alloc] initWithObject:url] : @[];
|
||||||
|
}
|
||||||
|
|
||||||
|
static jobjectArray urlsToStringArray( JNIEnv* env, NSArray* urls ) {
|
||||||
|
jsize count = (urls != NULL) ? urls.count : 0;
|
||||||
|
jobjectArray array = newJavaStringArray( env, count );
|
||||||
|
for( int i = 0; i < count; i++ ) {
|
||||||
|
jstring filename = NormalizedPathJavaFromNSString( env, [urls[i] path] );
|
||||||
|
env->SetObjectArrayElement( array, i, filename );
|
||||||
|
env->DeleteLocalRef( filename );
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import <objc/runtime.h>
|
||||||
|
#import <jni.h>
|
||||||
|
#import "JNIUtils.h"
|
||||||
|
#import "JNFRunLoop.h"
|
||||||
|
#import "com_formdev_flatlaf_ui_FlatNativeMacLibrary.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_showMessageDialog
|
||||||
|
( JNIEnv* env, jclass cls, jlong hwndParent, jint alertStyle, jstring messageText, jstring informativeText,
|
||||||
|
jint defaultButton, jobjectArray buttons )
|
||||||
|
{
|
||||||
|
JNI_COCOA_ENTER()
|
||||||
|
|
||||||
|
// convert Java strings to NSString (on Java thread)
|
||||||
|
NSString* nsMessageText = JavaToNSString( env, messageText );
|
||||||
|
NSString* nsInformativeText = JavaToNSString( env, informativeText );
|
||||||
|
|
||||||
|
jint buttonCount = env->GetArrayLength( buttons );
|
||||||
|
NSMutableArray* nsButtons = [NSMutableArray array];
|
||||||
|
for( int i = 0; i < buttonCount; i++ ) {
|
||||||
|
NSString* nsButton = JavaToNSString( env, (jstring) env->GetObjectArrayElement( buttons, i ) );
|
||||||
|
[nsButtons addObject:nsButton];
|
||||||
|
}
|
||||||
|
|
||||||
|
jint result = -1;
|
||||||
|
jint* presult = &result;
|
||||||
|
|
||||||
|
// show alert on macOS thread
|
||||||
|
[FlatJNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
|
||||||
|
NSAlert* alert = [[NSAlert alloc] init];
|
||||||
|
|
||||||
|
// use appearance from parent window
|
||||||
|
NSWindow* parent = (NSWindow*) hwndParent;
|
||||||
|
if( parent != NULL )
|
||||||
|
alert.window.appearance = parent.appearance;
|
||||||
|
|
||||||
|
// use empty string because if alert.messageText is not set it displays "Alert"
|
||||||
|
alert.messageText = (nsMessageText != NULL) ? nsMessageText : @"";
|
||||||
|
if( nsInformativeText != NULL )
|
||||||
|
alert.informativeText = nsInformativeText;
|
||||||
|
|
||||||
|
// alert style
|
||||||
|
switch( alertStyle ) {
|
||||||
|
case /* JOptionPane.ERROR_MESSAGE */ 0: alert.alertStyle = NSAlertStyleCritical; break;
|
||||||
|
default:
|
||||||
|
case /* JOptionPane.INFORMATION_MESSAGE */ 1: alert.alertStyle = NSAlertStyleInformational; break;
|
||||||
|
case /* JOptionPane.WARNING_MESSAGE */ 2: alert.alertStyle = NSAlertStyleWarning; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add buttons
|
||||||
|
for( int i = 0; i < nsButtons.count; i++ ) {
|
||||||
|
NSButton* b = [alert addButtonWithTitle:nsButtons[i]];
|
||||||
|
if( i == defaultButton )
|
||||||
|
alert.window.defaultButtonCell = b.cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
// show alert
|
||||||
|
NSInteger response = [alert runModal];
|
||||||
|
|
||||||
|
// if no buttons added, which shows a single OK button, the response is 0 when clicking OK
|
||||||
|
// if buttons added, response is 1000+buttonIndex
|
||||||
|
*presult = MAX( response - NSAlertFirstButtonReturn, 0 );
|
||||||
|
}];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
JNI_COCOA_EXIT()
|
||||||
|
}
|
||||||
@@ -39,13 +39,15 @@
|
|||||||
@implementation WindowData
|
@implementation WindowData
|
||||||
@end
|
@end
|
||||||
|
|
||||||
// declare internal methods
|
// declare exported methods
|
||||||
NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window );
|
NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window );
|
||||||
WindowData* getWindowData( NSWindow* nsWindow, bool allocate );
|
|
||||||
void setWindowButtonsHidden( NSWindow* nsWindow, bool hidden );
|
// declare internal methods
|
||||||
int getWindowButtonAreaWidth( NSWindow* nsWindow );
|
static WindowData* getWindowData( NSWindow* nsWindow, bool allocate );
|
||||||
int getWindowTitleBarHeight( NSWindow* nsWindow );
|
static void setWindowButtonsHidden( NSWindow* nsWindow, bool hidden );
|
||||||
bool isWindowFullScreen( NSWindow* nsWindow );
|
static int getWindowButtonAreaWidth( NSWindow* nsWindow );
|
||||||
|
static int getWindowTitleBarHeight( NSWindow* nsWindow );
|
||||||
|
static bool isWindowFullScreen( NSWindow* nsWindow );
|
||||||
|
|
||||||
|
|
||||||
NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window ) {
|
NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window ) {
|
||||||
@@ -79,7 +81,7 @@ NSWindow* getNSWindow( JNIEnv* env, jclass cls, jobject window ) {
|
|||||||
return (NSWindow *) jlong_to_ptr( env->GetLongField( platformWindow, ptrID ) );
|
return (NSWindow *) jlong_to_ptr( env->GetLongField( platformWindow, ptrID ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowData* getWindowData( NSWindow* nsWindow, bool allocate ) {
|
static WindowData* getWindowData( NSWindow* nsWindow, bool allocate ) {
|
||||||
static char key;
|
static char key;
|
||||||
WindowData* windowData = objc_getAssociatedObject( nsWindow, &key );
|
WindowData* windowData = objc_getAssociatedObject( nsWindow, &key );
|
||||||
if( windowData == NULL && allocate ) {
|
if( windowData == NULL && allocate ) {
|
||||||
@@ -252,7 +254,7 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_setW
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setWindowButtonsHidden( NSWindow* nsWindow, bool hidden ) {
|
static void setWindowButtonsHidden( NSWindow* nsWindow, bool hidden ) {
|
||||||
// get buttons
|
// get buttons
|
||||||
NSView* buttons[3] = {
|
NSView* buttons[3] = {
|
||||||
[nsWindow standardWindowButton:NSWindowCloseButton],
|
[nsWindow standardWindowButton:NSWindowCloseButton],
|
||||||
@@ -312,7 +314,7 @@ JNIEXPORT jobject JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_getWi
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getWindowButtonAreaWidth( NSWindow* nsWindow ) {
|
static int getWindowButtonAreaWidth( NSWindow* nsWindow ) {
|
||||||
// get buttons
|
// get buttons
|
||||||
NSView* buttons[3] = {
|
NSView* buttons[3] = {
|
||||||
[nsWindow standardWindowButton:NSWindowCloseButton],
|
[nsWindow standardWindowButton:NSWindowCloseButton],
|
||||||
@@ -344,7 +346,7 @@ int getWindowButtonAreaWidth( NSWindow* nsWindow ) {
|
|||||||
return right + left;
|
return right + left;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getWindowTitleBarHeight( NSWindow* nsWindow ) {
|
static int getWindowTitleBarHeight( NSWindow* nsWindow ) {
|
||||||
NSView* closeButton = [nsWindow standardWindowButton:NSWindowCloseButton];
|
NSView* closeButton = [nsWindow standardWindowButton:NSWindowCloseButton];
|
||||||
if( closeButton == NULL )
|
if( closeButton == NULL )
|
||||||
return -1;
|
return -1;
|
||||||
@@ -369,7 +371,7 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeMacLibrary_isWi
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isWindowFullScreen( NSWindow* nsWindow ) {
|
static bool isWindowFullScreen( NSWindow* nsWindow ) {
|
||||||
return ((nsWindow.styleMask & NSWindowStyleMaskFullScreen) != 0);
|
return ((nsWindow.styleMask & NSWindowStyleMaskFullScreen) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ tasks {
|
|||||||
compilerArgs.addAll( toolChain.map {
|
compilerArgs.addAll( toolChain.map {
|
||||||
when( it ) {
|
when( it ) {
|
||||||
is Gcc, is Clang -> listOf( "-O2", "-DUNICODE" )
|
is Gcc, is Clang -> listOf( "-O2", "-DUNICODE" )
|
||||||
is VisualCpp -> listOf( "/O2", "/Zl", "/GS-", "/DUNICODE" )
|
is VisualCpp -> listOf( "/O2", "/GS-", "/DUNICODE" )
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
@@ -80,8 +80,8 @@ tasks {
|
|||||||
|
|
||||||
linkerArgs.addAll( toolChain.map {
|
linkerArgs.addAll( toolChain.map {
|
||||||
when( it ) {
|
when( it ) {
|
||||||
is Gcc, is Clang -> listOf( "-lUser32", "-lGdi32", "-lshell32", "-lAdvAPI32", "-lKernel32", "-lDwmapi" )
|
is Gcc, is Clang -> listOf( "-lUser32", "-lGdi32", "-lshell32", "-lAdvAPI32", "-lKernel32", "-lDwmapi", "-lOle32", "-luuid" )
|
||||||
is VisualCpp -> listOf( "User32.lib", "Gdi32.lib", "shell32.lib", "AdvAPI32.lib", "Kernel32.lib", "Dwmapi.lib", "/NODEFAULTLIB" )
|
is VisualCpp -> listOf( "User32.lib", "Gdi32.lib", "shell32.lib", "AdvAPI32.lib", "Kernel32.lib", "Dwmapi.lib", "Ole32.lib", "uuid.lib" )
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
@@ -93,6 +93,15 @@ tasks {
|
|||||||
into( nativesDir )
|
into( nativesDir )
|
||||||
rename( linkedFile.get().asFile.name, libraryName )
|
rename( linkedFile.get().asFile.name, libraryName )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*dump
|
||||||
|
val dumpbin = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.42.34433/bin/Hostx64/x64/dumpbin.exe"
|
||||||
|
val dll = linkedFile.asFile.get()
|
||||||
|
val dllDir = dll.parent
|
||||||
|
exec { commandLine( dumpbin, "/all", "/rawdata:none", "/out:$dllDir/objdump.txt", dll ) }
|
||||||
|
exec { commandLine( dumpbin, "/all", "/out:$dllDir/full-contents.txt", dll ) }
|
||||||
|
exec { commandLine( dumpbin, "/disasm", "/out:$dllDir/disassemble.txt", dll ) }
|
||||||
|
dump*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
// increase this version if changing API or functionality of native library
|
// increase this version if changing API or functionality of native library
|
||||||
// also update version in Java class com.formdev.flatlaf.ui.FlatNativeWindowsLibrary
|
// also update version in Java class com.formdev.flatlaf.ui.FlatNativeWindowsLibrary
|
||||||
#define API_VERSION_WINDOWS 1001
|
#define API_VERSION_WINDOWS 1002
|
||||||
|
|
||||||
|
|
||||||
//---- JNI methods ------------------------------------------------------------
|
//---- JNI methods ------------------------------------------------------------
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// declare exported methods
|
||||||
HWND getWindowHandle( JNIEnv* env, jobject window );
|
HWND getWindowHandle( JNIEnv* env, jobject window );
|
||||||
|
|
||||||
//---- JNI methods ------------------------------------------------------------
|
//---- JNI methods ------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// avoid inlining of printf()
|
||||||
|
#define _NO_CRT_STDIO_INLINE
|
||||||
|
|
||||||
|
#include "JNIUtils.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---- class AutoReleaseString ------------------------------------------------
|
||||||
|
|
||||||
|
AutoReleaseString::AutoReleaseString( JNIEnv* _env, jstring _javaString ) {
|
||||||
|
env = _env;
|
||||||
|
javaString = _javaString;
|
||||||
|
chars = (javaString != NULL) ? env->GetStringChars( javaString, NULL ) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoReleaseString::~AutoReleaseString() {
|
||||||
|
if( chars != NULL )
|
||||||
|
env->ReleaseStringChars( javaString, chars );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- class AutoReleaseStringArray -------------------------------------------
|
||||||
|
|
||||||
|
AutoReleaseStringArray::AutoReleaseStringArray( JNIEnv* _env, jobjectArray _javaStringArray ) {
|
||||||
|
env = _env;
|
||||||
|
count = (_javaStringArray != NULL) ? env->GetArrayLength( _javaStringArray ) : 0;
|
||||||
|
if( count <= 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
javaStringArray = new jstring[count];
|
||||||
|
charsArray = new const jchar*[count];
|
||||||
|
|
||||||
|
for( int i = 0; i < count; i++ ) {
|
||||||
|
javaStringArray[i] = (jstring) env->GetObjectArrayElement( _javaStringArray, i );
|
||||||
|
charsArray[i] = env->GetStringChars( javaStringArray[i] , NULL );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoReleaseStringArray::~AutoReleaseStringArray() {
|
||||||
|
if( count == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
for( int i = 0; i < count; i++ ) {
|
||||||
|
env->ReleaseStringChars( javaStringArray[i], charsArray[i] );
|
||||||
|
env->DeleteLocalRef( javaStringArray[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] javaStringArray;
|
||||||
|
delete[] charsArray;
|
||||||
|
}
|
||||||
@@ -36,8 +36,11 @@
|
|||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
HINSTANCE _instance;
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
BOOL WINAPI _DllMainCRTStartup( HINSTANCE instance, DWORD reason, LPVOID reserved ) {
|
BOOL WINAPI _DllMainCRTStartup( HINSTANCE instance, DWORD reason, LPVOID reserved ) {
|
||||||
|
_instance = instance;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,333 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// avoid inlining of printf()
|
||||||
|
#define _NO_CRT_STDIO_INLINE
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <shobjidl.h>
|
||||||
|
#include "JNIUtils.h"
|
||||||
|
#include "com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
|
||||||
|
// declare external methods
|
||||||
|
extern HWND getWindowHandle( JNIEnv* env, jobject window );
|
||||||
|
|
||||||
|
// declare internal methods
|
||||||
|
static jobjectArray getFiles( JNIEnv* env, jboolean open, IFileDialog* dialog );
|
||||||
|
|
||||||
|
//---- class AutoReleasePtr ---------------------------------------------------
|
||||||
|
|
||||||
|
template<class T> class AutoReleasePtr {
|
||||||
|
T* ptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AutoReleasePtr() {
|
||||||
|
ptr = NULL;
|
||||||
|
}
|
||||||
|
AutoReleasePtr( T* p ) {
|
||||||
|
ptr = p;
|
||||||
|
ptr->AddRef();
|
||||||
|
}
|
||||||
|
~AutoReleasePtr() {
|
||||||
|
if( ptr != NULL )
|
||||||
|
ptr->Release();
|
||||||
|
}
|
||||||
|
T** operator&() { return &ptr; }
|
||||||
|
T* operator->() { return ptr; }
|
||||||
|
operator T*() { return ptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//---- class AutoReleaseIShellItem --------------------------------------------
|
||||||
|
|
||||||
|
class AutoReleaseIShellItem : public AutoReleasePtr<IShellItem> {
|
||||||
|
public:
|
||||||
|
AutoReleaseIShellItem( JNIEnv* env, jstring path ) {
|
||||||
|
AutoReleaseString cpath( env, path );
|
||||||
|
::SHCreateItemFromParsingName( cpath, NULL, IID_IShellItem, reinterpret_cast<void**>( &*this ) );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//---- class FilterSpec -------------------------------------------------------
|
||||||
|
|
||||||
|
class FilterSpec {
|
||||||
|
AutoReleaseStringArray fileTypes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UINT count = 0;
|
||||||
|
COMDLG_FILTERSPEC* specs = NULL;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FilterSpec( JNIEnv* _env, jobjectArray _fileTypes )
|
||||||
|
: fileTypes( _env, _fileTypes )
|
||||||
|
{
|
||||||
|
if( fileTypes.count == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
count = fileTypes.count / 2;
|
||||||
|
specs = new COMDLG_FILTERSPEC[fileTypes.count];
|
||||||
|
|
||||||
|
for( int i = 0; i < count; i++ ) {
|
||||||
|
specs[i].pszName = fileTypes[i * 2];
|
||||||
|
specs[i].pszSpec = fileTypes[(i * 2) + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~FilterSpec() {
|
||||||
|
if( specs != NULL )
|
||||||
|
delete[] specs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//---- class DialogEventHandler -----------------------------------------------
|
||||||
|
|
||||||
|
// see https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/winui/shell/appplatform/commonfiledialog/CommonFileDialogApp.cpp
|
||||||
|
|
||||||
|
class DialogEventHandler : public IFileDialogEvents {
|
||||||
|
JNIEnv* env;
|
||||||
|
jboolean open;
|
||||||
|
jobject callback;
|
||||||
|
LONG refCount = 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DialogEventHandler( JNIEnv* _env, jboolean _open, jobject _callback ) {
|
||||||
|
env = _env;
|
||||||
|
open = _open;
|
||||||
|
callback = _callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- IFileDialogEvents methods ----
|
||||||
|
|
||||||
|
IFACEMETHODIMP OnFileOk( IFileDialog* dialog ) {
|
||||||
|
if( callback == NULL )
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
// get files
|
||||||
|
jobjectArray files;
|
||||||
|
if( open ) {
|
||||||
|
AutoReleasePtr<IFileOpenDialog> openDialog;
|
||||||
|
HRESULT hr = dialog->QueryInterface( &openDialog );
|
||||||
|
files = SUCCEEDED( hr ) ? getFiles( env, true, openDialog ) : getFiles( env, false, dialog );
|
||||||
|
} else
|
||||||
|
files = getFiles( env, false, dialog );
|
||||||
|
|
||||||
|
// get hwnd of file dialog
|
||||||
|
HWND hwndFileDialog = 0;
|
||||||
|
AutoReleasePtr<IOleWindow> window;
|
||||||
|
if( SUCCEEDED( dialog->QueryInterface( &window ) ) )
|
||||||
|
window->GetWindow( &hwndFileDialog );
|
||||||
|
|
||||||
|
// invoke callback: boolean approve( String[] files, long hwnd );
|
||||||
|
jclass cls = env->GetObjectClass( callback );
|
||||||
|
jmethodID approveID = env->GetMethodID( cls, "approve", "([Ljava/lang/String;J)Z" );
|
||||||
|
if( approveID == NULL )
|
||||||
|
return S_OK;
|
||||||
|
return env->CallBooleanMethod( callback, approveID, files, hwndFileDialog ) ? S_OK : S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP OnFolderChange( IFileDialog* ) { return S_OK; }
|
||||||
|
IFACEMETHODIMP OnFolderChanging( IFileDialog*, IShellItem* ) { return S_OK; }
|
||||||
|
IFACEMETHODIMP OnHelp( IFileDialog* ) { return S_OK; }
|
||||||
|
IFACEMETHODIMP OnSelectionChange( IFileDialog* ) { return S_OK; }
|
||||||
|
IFACEMETHODIMP OnShareViolation( IFileDialog*, IShellItem*, FDE_SHAREVIOLATION_RESPONSE* ) { return S_OK; }
|
||||||
|
IFACEMETHODIMP OnTypeChange( IFileDialog*pfd ) { return S_OK; }
|
||||||
|
IFACEMETHODIMP OnOverwrite( IFileDialog*, IShellItem*, FDE_OVERWRITE_RESPONSE* ) { return S_OK; }
|
||||||
|
|
||||||
|
//---- IUnknown methods ----
|
||||||
|
|
||||||
|
IFACEMETHODIMP QueryInterface( REFIID riid, void** ppv ) {
|
||||||
|
if( riid != IID_IFileDialogEvents && riid != IID_IUnknown )
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
|
||||||
|
*ppv = static_cast<IFileDialogEvents*>( this );
|
||||||
|
AddRef();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP_(ULONG) AddRef() {
|
||||||
|
return InterlockedIncrement( &refCount );
|
||||||
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP_(ULONG) Release() {
|
||||||
|
LONG newRefCount = InterlockedDecrement( &refCount );
|
||||||
|
if( newRefCount == 0 )
|
||||||
|
delete this;
|
||||||
|
return newRefCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
~DialogEventHandler() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
//---- class CoInitializer ----------------------------------------------------
|
||||||
|
|
||||||
|
class CoInitializer {
|
||||||
|
public:
|
||||||
|
bool initialized;
|
||||||
|
|
||||||
|
CoInitializer() {
|
||||||
|
HRESULT result = ::CoInitializeEx( NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE );
|
||||||
|
initialized = SUCCEEDED( result );
|
||||||
|
}
|
||||||
|
~CoInitializer() {
|
||||||
|
if( initialized )
|
||||||
|
::CoUninitialize();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//---- helper -----------------------------------------------------------------
|
||||||
|
|
||||||
|
#define isOptionSet( option ) ((optionsSet & com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_ ## option) != 0)
|
||||||
|
#define CHECK_HRESULT( code ) { if( (code) != S_OK ) return NULL; }
|
||||||
|
|
||||||
|
static jobjectArray newJavaStringArray( JNIEnv* env, jsize count ) {
|
||||||
|
jclass stringClass = env->FindClass( "java/lang/String" );
|
||||||
|
return env->NewObjectArray( count, stringClass, NULL );
|
||||||
|
}
|
||||||
|
|
||||||
|
static jstring newJavaString( JNIEnv* env, LPWSTR str ) {
|
||||||
|
return env->NewString( reinterpret_cast<jchar*>( str ), static_cast<jsize>( wcslen( str ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- JNI methods ------------------------------------------------------------
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_showFileChooser
|
||||||
|
( JNIEnv* env, jclass cls, jobject owner, jboolean open,
|
||||||
|
jstring title, jstring okButtonLabel, jstring fileNameLabel, jstring fileName,
|
||||||
|
jstring folder, jstring saveAsItem, jstring defaultFolder, jstring defaultExtension,
|
||||||
|
jint optionsSet, jint optionsClear, jobject callback, jint fileTypeIndex, jobjectArray fileTypes )
|
||||||
|
{
|
||||||
|
// initialize COM library
|
||||||
|
CoInitializer coInitializer;
|
||||||
|
if( !coInitializer.initialized )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// handle limitations (without this, some Win32 method fails and this method returns NULL)
|
||||||
|
if( isOptionSet( FOS_PICKFOLDERS ) ) {
|
||||||
|
open = true; // always use IFileOpenDialog for picking folders
|
||||||
|
fileTypes = NULL; // no filter allowed for picking folders
|
||||||
|
}
|
||||||
|
if( !open && isOptionSet( FOS_ALLOWMULTISELECT ) )
|
||||||
|
optionsSet &= ~FOS_ALLOWMULTISELECT;
|
||||||
|
|
||||||
|
// convert Java strings to C strings
|
||||||
|
AutoReleaseString ctitle( env, title );
|
||||||
|
AutoReleaseString cokButtonLabel( env, okButtonLabel );
|
||||||
|
AutoReleaseString cfileNameLabel( env, fileNameLabel );
|
||||||
|
AutoReleaseString cfileName( env, fileName );
|
||||||
|
AutoReleaseIShellItem cfolder( env, folder );
|
||||||
|
AutoReleaseIShellItem csaveAsItem( env, saveAsItem );
|
||||||
|
AutoReleaseIShellItem cdefaultFolder( env, defaultFolder );
|
||||||
|
AutoReleaseString cdefaultExtension( env, defaultExtension );
|
||||||
|
FilterSpec specs( env, fileTypes );
|
||||||
|
|
||||||
|
// create IFileOpenDialog or IFileSaveDialog
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/shell/common-file-dialog
|
||||||
|
AutoReleasePtr<IFileDialog> dialog;
|
||||||
|
CHECK_HRESULT( ::CoCreateInstance( open ? CLSID_FileOpenDialog : CLSID_FileSaveDialog,
|
||||||
|
NULL, CLSCTX_INPROC_SERVER, open ? IID_IFileOpenDialog : IID_IFileSaveDialog,
|
||||||
|
reinterpret_cast<LPVOID*>( &dialog ) ) );
|
||||||
|
|
||||||
|
// set title, etc.
|
||||||
|
if( ctitle != NULL )
|
||||||
|
CHECK_HRESULT( dialog->SetTitle( ctitle ) );
|
||||||
|
if( cokButtonLabel != NULL )
|
||||||
|
CHECK_HRESULT( dialog->SetOkButtonLabel( cokButtonLabel ) );
|
||||||
|
if( cfileNameLabel != NULL )
|
||||||
|
CHECK_HRESULT( dialog->SetFileNameLabel( cfileNameLabel ) );
|
||||||
|
if( cfileName != NULL )
|
||||||
|
CHECK_HRESULT( dialog->SetFileName( cfileName ) );
|
||||||
|
if( cfolder != NULL )
|
||||||
|
CHECK_HRESULT( dialog->SetFolder( cfolder ) );
|
||||||
|
if( !open && csaveAsItem != NULL )
|
||||||
|
CHECK_HRESULT( ((IFileSaveDialog*)(IFileDialog*)dialog)->SetSaveAsItem( csaveAsItem ) );
|
||||||
|
if( cdefaultFolder != NULL )
|
||||||
|
CHECK_HRESULT( dialog->SetDefaultFolder( cdefaultFolder ) );
|
||||||
|
if( cdefaultExtension != NULL )
|
||||||
|
CHECK_HRESULT( dialog->SetDefaultExtension( cdefaultExtension ) );
|
||||||
|
|
||||||
|
// set options
|
||||||
|
FILEOPENDIALOGOPTIONS existingOptions;
|
||||||
|
CHECK_HRESULT( dialog->GetOptions( &existingOptions ) );
|
||||||
|
CHECK_HRESULT( dialog->SetOptions ( (existingOptions & ~optionsClear) | optionsSet ) );
|
||||||
|
|
||||||
|
// initialize filter
|
||||||
|
if( specs.count > 0 ) {
|
||||||
|
CHECK_HRESULT( dialog->SetFileTypes( specs.count, specs.specs ) );
|
||||||
|
if( fileTypeIndex > 0 )
|
||||||
|
CHECK_HRESULT( dialog->SetFileTypeIndex( min( fileTypeIndex + 1, specs.count ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// add event handler
|
||||||
|
AutoReleasePtr<DialogEventHandler> handler( new DialogEventHandler( env, open, callback ) );
|
||||||
|
DWORD dwCookie = 0;
|
||||||
|
CHECK_HRESULT( dialog->Advise( handler, &dwCookie ) );
|
||||||
|
|
||||||
|
// show dialog
|
||||||
|
HWND hwndOwner = (owner != NULL) ? getWindowHandle( env, owner ) : NULL;
|
||||||
|
HRESULT hr = dialog->Show( hwndOwner );
|
||||||
|
dialog->Unadvise( dwCookie );
|
||||||
|
if( hr == HRESULT_FROM_WIN32(ERROR_CANCELLED) )
|
||||||
|
return newJavaStringArray( env, 0 );
|
||||||
|
CHECK_HRESULT( hr );
|
||||||
|
|
||||||
|
// get selected files as Java string array
|
||||||
|
return getFiles( env, open, dialog );
|
||||||
|
}
|
||||||
|
|
||||||
|
static jobjectArray getFiles( JNIEnv* env, jboolean open, IFileDialog* dialog ) {
|
||||||
|
if( open ) {
|
||||||
|
AutoReleasePtr<IShellItemArray> shellItems;
|
||||||
|
DWORD count;
|
||||||
|
CHECK_HRESULT( ((IFileOpenDialog*)(IFileDialog*)dialog)->GetResults( &shellItems ) );
|
||||||
|
CHECK_HRESULT( shellItems->GetCount( &count ) );
|
||||||
|
|
||||||
|
// convert shell items to Java string array
|
||||||
|
jobjectArray array = newJavaStringArray( env, count );
|
||||||
|
for( int i = 0; i < count; i++ ) {
|
||||||
|
AutoReleasePtr<IShellItem> shellItem;
|
||||||
|
LPWSTR path;
|
||||||
|
CHECK_HRESULT( shellItems->GetItemAt( i, &shellItem ) );
|
||||||
|
CHECK_HRESULT( shellItem->GetDisplayName( SIGDN_FILESYSPATH, &path ) );
|
||||||
|
|
||||||
|
jstring jpath = newJavaString( env, path );
|
||||||
|
CoTaskMemFree( path );
|
||||||
|
|
||||||
|
env->SetObjectArrayElement( array, i, jpath );
|
||||||
|
env->DeleteLocalRef( jpath );
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
} else {
|
||||||
|
AutoReleasePtr<IShellItem> shellItem;
|
||||||
|
LPWSTR path;
|
||||||
|
CHECK_HRESULT( dialog->GetResult( &shellItem ) );
|
||||||
|
CHECK_HRESULT( shellItem->GetDisplayName( SIGDN_FILESYSPATH, &path ) );
|
||||||
|
|
||||||
|
// convert shell item to Java string array
|
||||||
|
jstring jpath = newJavaString( env, path );
|
||||||
|
CoTaskMemFree( path );
|
||||||
|
|
||||||
|
jobjectArray array = newJavaStringArray( env, 1 );
|
||||||
|
env->SetObjectArrayElement( array, 0, jpath );
|
||||||
|
env->DeleteLocalRef( jpath );
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,419 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// avoid inlining of printf()
|
||||||
|
#define _NO_CRT_STDIO_INLINE
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "JNIUtils.h"
|
||||||
|
#include "com_formdev_flatlaf_ui_FlatNativeWindowsLibrary.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
* @since 3.7
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ID_BUTTON1 101
|
||||||
|
|
||||||
|
// declare external fields
|
||||||
|
extern HINSTANCE _instance;
|
||||||
|
|
||||||
|
// declare internal methods
|
||||||
|
static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title, LPCWSTR text,
|
||||||
|
int defaultButton, int buttonCount, LPCWSTR* buttons );
|
||||||
|
static INT_PTR CALLBACK messageDialogProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
||||||
|
static int textLengthAsDLUs( HDC hdc, LPCWSTR str, int strLen );
|
||||||
|
static LONG pixel2dluX( LONG px );
|
||||||
|
static LONG pixel2dluY( LONG px );
|
||||||
|
static LONG dluX2pixel( LONG dluX );
|
||||||
|
static LPWORD lpwAlign( LPWORD lpIn );
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_showMessageBox
|
||||||
|
( JNIEnv* env, jclass cls, jlong hwndParent, jstring text, jstring caption, jint type )
|
||||||
|
{
|
||||||
|
// convert Java strings to C strings
|
||||||
|
AutoReleaseString ctext( env, text );
|
||||||
|
AutoReleaseString ccaption( env, caption );
|
||||||
|
|
||||||
|
return ::MessageBox( reinterpret_cast<HWND>( hwndParent ), ctext, ccaption, type );
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_showMessageDialog
|
||||||
|
( JNIEnv* env, jclass cls, jlong hwndParent, jint messageType, jstring title,
|
||||||
|
jstring text, jint defaultButton, jobjectArray buttons )
|
||||||
|
{
|
||||||
|
HWND owner = reinterpret_cast<HWND>( hwndParent );
|
||||||
|
|
||||||
|
// convert Java strings to C strings
|
||||||
|
AutoReleaseString ctitle( env, title );
|
||||||
|
AutoReleaseString ctext( env, text );
|
||||||
|
AutoReleaseStringArray cbuttons( env, buttons );
|
||||||
|
|
||||||
|
// get title from parent window if necessary
|
||||||
|
WCHAR parentTitle[100];
|
||||||
|
if( ctitle == NULL )
|
||||||
|
::GetWindowText( owner, parentTitle, 100 );
|
||||||
|
|
||||||
|
byte* templ = createInMemoryTemplate( owner, messageType, (ctitle != NULL) ? ctitle : parentTitle,
|
||||||
|
ctext, defaultButton, cbuttons.count, cbuttons );
|
||||||
|
if( templ == NULL )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
LRESULT ret = ::DialogBoxIndirect( _instance, (LPDLGTEMPLATE) templ, owner, messageDialogProc );
|
||||||
|
delete templ;
|
||||||
|
return (ret >= ID_BUTTON1) ? ret - ID_BUTTON1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// all values in DLUs
|
||||||
|
|
||||||
|
#define INSETS_TOP 12
|
||||||
|
#define INSETS_LEFT 12
|
||||||
|
#define INSETS_RIGHT 12
|
||||||
|
#define INSETS_BOTTOM 6
|
||||||
|
|
||||||
|
#define ICON_TEXT_GAP 8
|
||||||
|
|
||||||
|
#define LABEL_MIN_WIDTH 100
|
||||||
|
#define LABEL_MAX_WIDTH 250
|
||||||
|
#define LABEL_HEIGHT 8
|
||||||
|
|
||||||
|
#define BUTTON_WIDTH 50
|
||||||
|
#define BUTTON_HEIGHT 12
|
||||||
|
#define BUTTON_GAP 5
|
||||||
|
#define BUTTON_TOP_GAP 14
|
||||||
|
#define BUTTON_LEFT_RIGHT_GAP 8
|
||||||
|
|
||||||
|
// based on https://learn.microsoft.com/en-us/windows/win32/dlgbox/using-dialog-boxes#creating-a-template-in-memory
|
||||||
|
static byte* createInMemoryTemplate( HWND owner, int messageType, LPCWSTR title, LPCWSTR text,
|
||||||
|
int defaultButton, int buttonCount, LPCWSTR* buttons )
|
||||||
|
{
|
||||||
|
// get font info needed for DS_SETFONT
|
||||||
|
NONCLIENTMETRICS ncMetrics;
|
||||||
|
ncMetrics.cbSize = sizeof( NONCLIENTMETRICS );
|
||||||
|
if( !::SystemParametersInfo( SPI_GETNONCLIENTMETRICS, 0, &ncMetrics, 0 ) )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// create DC to use message font
|
||||||
|
HDC hdcOwner = ::GetDC( owner );
|
||||||
|
HDC hdc = ::CreateCompatibleDC( hdcOwner );
|
||||||
|
::ReleaseDC( owner, hdcOwner );
|
||||||
|
if( hdc == NULL )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
HFONT hfont = ::CreateFontIndirect( &ncMetrics.lfMessageFont );
|
||||||
|
if( hfont == NULL ) {
|
||||||
|
::DeleteDC( hdc );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ::SelectObject( hdc, hfont ) == NULL ) {
|
||||||
|
::DeleteDC( hdc );
|
||||||
|
::DeleteObject( hfont );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- calculate layout (in DLUs) ----
|
||||||
|
|
||||||
|
// layout icon
|
||||||
|
LPWSTR icon;
|
||||||
|
switch( messageType ) {
|
||||||
|
case /* JOptionPane.ERROR_MESSAGE */ 0: icon = IDI_ERROR; break;
|
||||||
|
case /* JOptionPane.INFORMATION_MESSAGE */ 1: icon = IDI_INFORMATION; break;
|
||||||
|
case /* JOptionPane.WARNING_MESSAGE */ 2: icon = IDI_WARNING; break;
|
||||||
|
case /* JOptionPane.QUESTION_MESSAGE */ 3: icon = IDI_QUESTION; break;
|
||||||
|
default:
|
||||||
|
case /* JOptionPane.PLAIN_MESSAGE */ -1: icon = NULL; break;
|
||||||
|
}
|
||||||
|
int ix = INSETS_LEFT;
|
||||||
|
int iy = INSETS_TOP;
|
||||||
|
int iw = pixel2dluX( ::GetSystemMetrics( SM_CXICON ) );
|
||||||
|
int ih = pixel2dluY( ::GetSystemMetrics( SM_CYICON ) );
|
||||||
|
|
||||||
|
// layout text
|
||||||
|
int tx = ix + (icon != NULL ? iw + ICON_TEXT_GAP : 0);
|
||||||
|
int ty = iy;
|
||||||
|
int tw = 0;
|
||||||
|
int th = 0;
|
||||||
|
if( text == NULL )
|
||||||
|
text = L"";
|
||||||
|
LPWSTR wrappedText = new WCHAR[wcslen( text ) + 1];
|
||||||
|
wcscpy( wrappedText, text );
|
||||||
|
LPWSTR lineStart = wrappedText;
|
||||||
|
for( LPWSTR t = wrappedText; ; t++ ) {
|
||||||
|
if( *t != '\n' && *t != 0 )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// calculate line width (in pixels) and number of charaters that fit into LABEL_MAX_WIDTH
|
||||||
|
int lineLen = t - lineStart;
|
||||||
|
int fit = 0;
|
||||||
|
SIZE size{ 0 };
|
||||||
|
if( !::GetTextExtentExPoint( hdc, lineStart, lineLen, dluX2pixel( LABEL_MAX_WIDTH ), &fit, NULL, &size ) )
|
||||||
|
break;
|
||||||
|
|
||||||
|
if( fit < lineLen ) {
|
||||||
|
// wrap too long line --> try to wrap at space character
|
||||||
|
bool wrapped = false;
|
||||||
|
for( LPWSTR t2 = lineStart + fit - 1; t2 > lineStart; t2-- ) {
|
||||||
|
if( *t2 == ' ' || *t2 == '\t' ) {
|
||||||
|
*t2 = '\n';
|
||||||
|
int w = textLengthAsDLUs( hdc, lineStart, t2 - lineStart );
|
||||||
|
tw = max( tw, w );
|
||||||
|
th += LABEL_HEIGHT;
|
||||||
|
|
||||||
|
// continue wrapping after inserted line break
|
||||||
|
t = t2;
|
||||||
|
lineStart = t + 1;
|
||||||
|
wrapped = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( !wrapped ) {
|
||||||
|
// not able to wrap at word --> break long word
|
||||||
|
int breakIndex = (lineStart + fit) - wrappedText;
|
||||||
|
int w = textLengthAsDLUs( hdc, lineStart, breakIndex );
|
||||||
|
tw = max( tw, w );
|
||||||
|
th += LABEL_HEIGHT;
|
||||||
|
|
||||||
|
// duplicate string
|
||||||
|
LPWSTR wrappedText2 = new WCHAR[wcslen( wrappedText ) + 1 + 1];
|
||||||
|
// use wcscpy(), instead of wcsncpy(), because this method is inlined and does not require linking to runtime lib
|
||||||
|
wcscpy( wrappedText2, wrappedText );
|
||||||
|
wrappedText2[breakIndex] = '\n';
|
||||||
|
wcscpy( wrappedText2 + breakIndex + 1, wrappedText + breakIndex );
|
||||||
|
|
||||||
|
// delete old text
|
||||||
|
delete[] wrappedText;
|
||||||
|
wrappedText = wrappedText2;
|
||||||
|
|
||||||
|
// continue wrapping after inserted line break
|
||||||
|
t = wrappedText + breakIndex;
|
||||||
|
lineStart = t + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// line fits into LABEL_MAX_WIDTH
|
||||||
|
int w = pixel2dluX( size.cx );
|
||||||
|
tw = max( tw, w );
|
||||||
|
th += LABEL_HEIGHT;
|
||||||
|
lineStart = t + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( *t == 0 )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tw = min( max( tw, LABEL_MIN_WIDTH ), LABEL_MAX_WIDTH );
|
||||||
|
th = max( th, LABEL_HEIGHT );
|
||||||
|
if( icon != NULL && th < ih )
|
||||||
|
ty += (ih - th) / 2; // vertically center text
|
||||||
|
|
||||||
|
// layout buttons
|
||||||
|
int* bw = new int[buttonCount];
|
||||||
|
int buttonTotalWidth = BUTTON_GAP * (buttonCount - 1);
|
||||||
|
for( int i = 0; i < buttonCount; i++ ) {
|
||||||
|
int w = textLengthAsDLUs( hdc, buttons[i], -1 ) + 16;
|
||||||
|
bw[i] = max( BUTTON_WIDTH, w );
|
||||||
|
buttonTotalWidth += bw[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// layout dialog
|
||||||
|
int dx = 0;
|
||||||
|
int dy = 0;
|
||||||
|
int dw = max( tx + tw + INSETS_RIGHT, BUTTON_LEFT_RIGHT_GAP + buttonTotalWidth + BUTTON_LEFT_RIGHT_GAP );
|
||||||
|
int dh = max( iy + ih, ty + th ) + BUTTON_TOP_GAP + BUTTON_HEIGHT + INSETS_BOTTOM;
|
||||||
|
|
||||||
|
// center dialog in owner
|
||||||
|
RECT ownerRect{ 0 };
|
||||||
|
if( ::GetClientRect( owner, &ownerRect ) ) {
|
||||||
|
dx = (pixel2dluX( ownerRect.right - ownerRect.left ) - dw) / 2;
|
||||||
|
dy = (pixel2dluY( ownerRect.bottom - ownerRect.top ) - dh) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// layout button area
|
||||||
|
int bx = dw - buttonTotalWidth - BUTTON_LEFT_RIGHT_GAP;
|
||||||
|
int by = dh - BUTTON_HEIGHT - INSETS_BOTTOM;
|
||||||
|
|
||||||
|
// get font info needed for DS_SETFONT
|
||||||
|
int fontPointSize = (ncMetrics.lfMessageFont.lfHeight < 0)
|
||||||
|
? -MulDiv( ncMetrics.lfMessageFont.lfHeight, 72, ::GetDeviceCaps( hdc, LOGPIXELSY ) )
|
||||||
|
: ncMetrics.lfMessageFont.lfHeight;
|
||||||
|
LPCWSTR fontFaceName = ncMetrics.lfMessageFont.lfFaceName;
|
||||||
|
|
||||||
|
// delete DC and font
|
||||||
|
::DeleteDC( hdc );
|
||||||
|
::DeleteObject( hfont );
|
||||||
|
|
||||||
|
// (approximately) calculate memory size needed for in-memory template
|
||||||
|
int templSize = (sizeof(DLGTEMPLATE) + /*menu*/ 2 + /*class*/ 2 + /*title*/ 2)
|
||||||
|
+ ((sizeof(DLGITEMTEMPLATE) + /*class*/ 4 + /*title/icon*/ 4 + /*creation data*/ 2) * (/*icon+text*/2 + buttonCount))
|
||||||
|
+ (title != NULL ? (wcslen( title ) + 1) * sizeof(wchar_t) : 0)
|
||||||
|
+ /*fontPointSize*/ 2 + ((wcslen( fontFaceName ) + 1) * sizeof(wchar_t))
|
||||||
|
+ ((wcslen( wrappedText ) + 1) * sizeof(wchar_t));
|
||||||
|
for( int i = 0; i < buttonCount; i++ )
|
||||||
|
templSize += ((wcslen( buttons[i] ) + 1) * sizeof(wchar_t));
|
||||||
|
|
||||||
|
templSize += (2 * (1 + 1 + buttonCount)); // necessary for DWORD alignment
|
||||||
|
templSize += 100; // some reserve
|
||||||
|
|
||||||
|
// allocate memory for in-memory template
|
||||||
|
byte* templ = new byte[templSize];
|
||||||
|
if( templ == NULL )
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
|
||||||
|
//---- define dialog box ----
|
||||||
|
|
||||||
|
LPDLGTEMPLATE lpdt = (LPDLGTEMPLATE) templ;
|
||||||
|
lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_SETFONT;
|
||||||
|
lpdt->cdit = /*text*/ 1 + buttonCount; // number of controls
|
||||||
|
lpdt->x = dx;
|
||||||
|
lpdt->y = dy;
|
||||||
|
lpdt->cx = dw;
|
||||||
|
lpdt->cy = dh;
|
||||||
|
|
||||||
|
LPWORD lpw = (LPWORD) (lpdt + 1);
|
||||||
|
*lpw++ = 0; // no menu
|
||||||
|
*lpw++ = 0; // predefined dialog box class (by default)
|
||||||
|
if( title != NULL ) {
|
||||||
|
wcscpy( (LPWSTR) lpw, title );
|
||||||
|
lpw += wcslen( title ) + 1;
|
||||||
|
} else
|
||||||
|
*lpw++ = 0; // no title
|
||||||
|
|
||||||
|
// for DS_SETFONT
|
||||||
|
*lpw++ = fontPointSize;
|
||||||
|
wcscpy( (LPWSTR) lpw, fontFaceName );
|
||||||
|
lpw += wcslen( fontFaceName ) + 1;
|
||||||
|
|
||||||
|
//---- define icon ----
|
||||||
|
|
||||||
|
if( icon != NULL ) {
|
||||||
|
lpdt->cdit++;
|
||||||
|
|
||||||
|
lpw = lpwAlign( lpw );
|
||||||
|
LPDLGITEMTEMPLATE lpdit = (LPDLGITEMTEMPLATE) lpw;
|
||||||
|
lpdit->x = ix;
|
||||||
|
lpdit->y = iy;
|
||||||
|
lpdit->cx = iw;
|
||||||
|
lpdit->cy = ih;
|
||||||
|
lpdit->id = ID_BUTTON1 - 1;
|
||||||
|
lpdit->style = WS_CHILD | WS_VISIBLE | SS_ICON;
|
||||||
|
|
||||||
|
lpw = (LPWORD) (lpdit + 1);
|
||||||
|
*lpw++ = 0xffff; *lpw++ = 0x0082; // Static class
|
||||||
|
*lpw++ = 0xffff; *lpw++ = (WORD) icon; // icon
|
||||||
|
*lpw++ = 0; // creation data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---- define text ----
|
||||||
|
|
||||||
|
lpw = lpwAlign( lpw );
|
||||||
|
LPDLGITEMTEMPLATE lpdit = (LPDLGITEMTEMPLATE) lpw;
|
||||||
|
lpdit->x = tx;
|
||||||
|
lpdit->y = ty;
|
||||||
|
lpdit->cx = tw;
|
||||||
|
lpdit->cy = th;
|
||||||
|
lpdit->id = ID_BUTTON1 - 2;
|
||||||
|
lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT | SS_NOPREFIX | SS_EDITCONTROL;
|
||||||
|
|
||||||
|
lpw = (LPWORD) (lpdit + 1);
|
||||||
|
*lpw++ = 0xffff; *lpw++ = 0x0082; // Static class
|
||||||
|
wcscpy( (LPWSTR) lpw, wrappedText ); lpw += wcslen( wrappedText ) + 1; // text
|
||||||
|
*lpw++ = 0; // creation data
|
||||||
|
|
||||||
|
|
||||||
|
//---- define buttons ----
|
||||||
|
|
||||||
|
defaultButton = min( max( defaultButton, 0 ), buttonCount - 1 );
|
||||||
|
int buttonId = ID_BUTTON1;
|
||||||
|
for( int i = 0; i < buttonCount; i++ ) {
|
||||||
|
lpw = lpwAlign( lpw );
|
||||||
|
LPDLGITEMTEMPLATE lpdit = (LPDLGITEMTEMPLATE) lpw;
|
||||||
|
lpdit->x = bx;
|
||||||
|
lpdit->y = by;
|
||||||
|
lpdit->cx = bw[i];
|
||||||
|
lpdit->cy = BUTTON_HEIGHT;
|
||||||
|
lpdit->id = buttonId++;
|
||||||
|
lpdit->style = WS_CHILD | WS_VISIBLE | WS_TABSTOP | (i == 0 ? WS_GROUP : 0)
|
||||||
|
| BS_TEXT | (i == defaultButton ? BS_DEFPUSHBUTTON : BS_PUSHBUTTON);
|
||||||
|
|
||||||
|
lpw = (LPWORD) (lpdit + 1);
|
||||||
|
*lpw++ = 0xffff; *lpw++ = 0x0080; // Button class
|
||||||
|
wcscpy( (LPWSTR) lpw, buttons[i] ); lpw += wcslen( buttons[i] ) + 1; // text
|
||||||
|
*lpw++ = 0; // creation data
|
||||||
|
|
||||||
|
bx += bw[i] + BUTTON_GAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] wrappedText;
|
||||||
|
delete[] bw;
|
||||||
|
|
||||||
|
return templ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL CALLBACK focusDefaultButtonProc( HWND hwnd, LPARAM lParam ) {
|
||||||
|
if( ::GetWindowLong( hwnd, GWL_ID ) >= ID_BUTTON1 ) {
|
||||||
|
LONG style = ::GetWindowLong( hwnd, GWL_STYLE );
|
||||||
|
if( (style & BS_DEFPUSHBUTTON) != 0 ) {
|
||||||
|
::SetFocus( hwnd );
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INT_PTR CALLBACK messageDialogProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) {
|
||||||
|
switch( uMsg ) {
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
::EnumChildWindows( hwnd, focusDefaultButtonProc, 0 );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_COMMAND:
|
||||||
|
::EndDialog( hwnd, wParam );
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int textLengthAsDLUs( HDC hdc, LPCWSTR str, int strLen ) {
|
||||||
|
SIZE size{ 0 };
|
||||||
|
::GetTextExtentPoint32( hdc, str, (strLen >= 0) ? strLen : wcslen( str ), &size );
|
||||||
|
return pixel2dluX( size.cx );
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG pixel2dluX( LONG px ) {
|
||||||
|
return MulDiv( px, 4, LOWORD( ::GetDialogBaseUnits() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG pixel2dluY( LONG py ) {
|
||||||
|
return MulDiv( py, 8, HIWORD( ::GetDialogBaseUnits() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static LONG dluX2pixel( LONG dluX ) {
|
||||||
|
return MulDiv( dluX, LOWORD( ::GetDialogBaseUnits() ), 4 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static LPWORD lpwAlign( LPWORD lpIn ) {
|
||||||
|
ULONG_PTR ul = (ULONG_PTR) lpIn;
|
||||||
|
ul += 3;
|
||||||
|
ul >>= 2;
|
||||||
|
ul <<= 2;
|
||||||
|
return (LPWORD) ul;
|
||||||
|
}
|
||||||
@@ -25,8 +25,8 @@
|
|||||||
* @author Karl Tauber
|
* @author Karl Tauber
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// see FlatWndProc.cpp
|
// declare external methods
|
||||||
HWND getWindowHandle( JNIEnv* env, jobject window );
|
extern HWND getWindowHandle( JNIEnv* env, jobject window );
|
||||||
|
|
||||||
//---- Utility ----------------------------------------------------------------
|
//---- Utility ----------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <jni.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---- class AutoReleaseString ------------------------------------------------
|
||||||
|
|
||||||
|
class AutoReleaseString {
|
||||||
|
JNIEnv* env;
|
||||||
|
jstring javaString;
|
||||||
|
const jchar* chars;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AutoReleaseString( JNIEnv* _env, jstring _javaString );
|
||||||
|
~AutoReleaseString();
|
||||||
|
|
||||||
|
operator LPCWSTR() { return (LPCWSTR) chars; }
|
||||||
|
};
|
||||||
|
|
||||||
|
//---- class AutoReleaseStringArray -------------------------------------------
|
||||||
|
|
||||||
|
class AutoReleaseStringArray {
|
||||||
|
JNIEnv* env;
|
||||||
|
jstring* javaStringArray;
|
||||||
|
const jchar** charsArray;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UINT count;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AutoReleaseStringArray( JNIEnv* _env, jobjectArray _javaStringArray );
|
||||||
|
~AutoReleaseStringArray();
|
||||||
|
|
||||||
|
operator LPCWSTR*() { return (LPCWSTR*) charsArray; }
|
||||||
|
};
|
||||||
@@ -27,6 +27,52 @@ extern "C" {
|
|||||||
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_COLOR_DEFAULT -1L
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_COLOR_DEFAULT -1L
|
||||||
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_COLOR_NONE
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_COLOR_NONE
|
||||||
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_COLOR_NONE -2L
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_DWMWA_COLOR_NONE -2L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_OVERWRITEPROMPT
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_OVERWRITEPROMPT 2L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_STRICTFILETYPES
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_STRICTFILETYPES 4L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_NOCHANGEDIR
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_NOCHANGEDIR 8L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_PICKFOLDERS
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_PICKFOLDERS 32L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_FORCEFILESYSTEM
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_FORCEFILESYSTEM 64L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_ALLNONSTORAGEITEMS
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_ALLNONSTORAGEITEMS 128L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_NOVALIDATE
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_NOVALIDATE 256L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_ALLOWMULTISELECT
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_ALLOWMULTISELECT 512L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_PATHMUSTEXIST
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_PATHMUSTEXIST 2048L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_FILEMUSTEXIST
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_FILEMUSTEXIST 4096L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_CREATEPROMPT
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_CREATEPROMPT 8192L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_SHAREAWARE
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_SHAREAWARE 16384L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_NOREADONLYRETURN
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_NOREADONLYRETURN 32768L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_NOTESTFILECREATE
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_NOTESTFILECREATE 65536L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_HIDEMRUPLACES
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_HIDEMRUPLACES 131072L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_HIDEPINNEDPLACES
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_HIDEPINNEDPLACES 262144L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_NODEREFERENCELINKS
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_NODEREFERENCELINKS 1048576L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_OKBUTTONNEEDSINTERACTION
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_OKBUTTONNEEDSINTERACTION 2097152L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_DONTADDTORECENT
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_DONTADDTORECENT 33554432L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_FORCESHOWHIDDEN
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_FORCESHOWHIDDEN 268435456L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_DEFAULTNOMINIMODE
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_DEFAULTNOMINIMODE 536870912L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_FORCEPREVIEWPANEON
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_FORCEPREVIEWPANEON 1073741824L
|
||||||
|
#undef com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_SUPPORTSTREAMABLEITEMS
|
||||||
|
#define com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_FOS_SUPPORTSTREAMABLEITEMS -2147483648L
|
||||||
/*
|
/*
|
||||||
* Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary
|
* Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary
|
||||||
* Method: getOSBuildNumberImpl
|
* Method: getOSBuildNumberImpl
|
||||||
@@ -67,6 +113,30 @@ JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_
|
|||||||
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_dwmSetWindowAttributeDWORD
|
JNIEXPORT jboolean JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_dwmSetWindowAttributeDWORD
|
||||||
(JNIEnv *, jclass, jlong, jint, jint);
|
(JNIEnv *, jclass, jlong, jint, jint);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary
|
||||||
|
* Method: showFileChooser
|
||||||
|
* Signature: (Ljava/awt/Window;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IILcom/formdev/flatlaf/ui/FlatNativeWindowsLibrary/FileChooserCallback;I[Ljava/lang/String;)[Ljava/lang/String;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jobjectArray JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_showFileChooser
|
||||||
|
(JNIEnv *, jclass, jobject, jboolean, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jstring, jint, jint, jobject, jint, jobjectArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary
|
||||||
|
* Method: showMessageDialog
|
||||||
|
* Signature: (JILjava/lang/String;Ljava/lang/String;I[Ljava/lang/String;)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_showMessageDialog
|
||||||
|
(JNIEnv *, jclass, jlong, jint, jstring, jstring, jint, jobjectArray);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: com_formdev_flatlaf_ui_FlatNativeWindowsLibrary
|
||||||
|
* Method: showMessageBox
|
||||||
|
* Signature: (JLjava/lang/String;Ljava/lang/String;I)I
|
||||||
|
*/
|
||||||
|
JNIEXPORT jint JNICALL Java_com_formdev_flatlaf_ui_FlatNativeWindowsLibrary_showMessageBox
|
||||||
|
(JNIEnv *, jclass, jlong, jstring, jstring, jint);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ dependencies {
|
|||||||
implementation( libs.jide.oss )
|
implementation( libs.jide.oss )
|
||||||
implementation( libs.glazedlists )
|
implementation( libs.glazedlists )
|
||||||
implementation( libs.netbeans.api.awt )
|
implementation( libs.netbeans.api.awt )
|
||||||
|
implementation( libs.nativejfilechooser )
|
||||||
|
|
||||||
components.all<TargetJvmVersion8Rule>()
|
components.all<TargetJvmVersion8Rule>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,382 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2025 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.testing;
|
||||||
|
|
||||||
|
import static com.formdev.flatlaf.ui.FlatNativeLinuxLibrary.*;
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.SecondaryLoop;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.Window;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import javax.swing.*;
|
||||||
|
import com.formdev.flatlaf.extras.components.*;
|
||||||
|
import com.formdev.flatlaf.extras.components.FlatTriStateCheckBox.State;
|
||||||
|
import com.formdev.flatlaf.testing.FlatSystemFileChooserTest.DummyModalDialog;
|
||||||
|
import com.formdev.flatlaf.ui.FlatNativeLinuxLibrary;
|
||||||
|
import net.miginfocom.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class FlatSystemFileChooserLinuxTest
|
||||||
|
extends FlatTestPanel
|
||||||
|
{
|
||||||
|
public static void main( String[] args ) {
|
||||||
|
SwingUtilities.invokeLater( () -> {
|
||||||
|
if( !FlatNativeLinuxLibrary.isLoaded() ) {
|
||||||
|
JOptionPane.showMessageDialog( null, "FlatLaf native library not loaded" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatTestFrame frame = FlatTestFrame.create( args, "FlatSystemFileChooserLinuxTest" );
|
||||||
|
FlatSystemFileChooserTest.addListeners( frame );
|
||||||
|
frame.showFrame( FlatSystemFileChooserLinuxTest::new );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatSystemFileChooserLinuxTest() {
|
||||||
|
initComponents();
|
||||||
|
|
||||||
|
fileTypesField.setSelectedItem( null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void open() {
|
||||||
|
openOrSave( true, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void save() {
|
||||||
|
openOrSave( false, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openDirect() {
|
||||||
|
openOrSave( true, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveDirect() {
|
||||||
|
openOrSave( false, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openOrSave( boolean open, boolean direct ) {
|
||||||
|
Window frame = SwingUtilities.windowForComponent( this );
|
||||||
|
if( ownerFrameRadioButton.isSelected() )
|
||||||
|
openOrSave( open, direct, frame );
|
||||||
|
else if( ownerDialogRadioButton.isSelected() )
|
||||||
|
new DummyModalDialog( frame, owner -> openOrSave( open, direct, owner ) ).setVisible( true );
|
||||||
|
else
|
||||||
|
openOrSave( open, direct, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openOrSave( boolean open, boolean direct, Window owner ) {
|
||||||
|
String title = n( titleField.getText() );
|
||||||
|
String okButtonLabel = n( okButtonLabelField.getText() );
|
||||||
|
String currentName = n( currentNameField.getText() );
|
||||||
|
String currentFolder = n( currentFolderField.getText() );
|
||||||
|
AtomicInteger optionsSet = new AtomicInteger();
|
||||||
|
AtomicInteger optionsClear = new AtomicInteger();
|
||||||
|
|
||||||
|
o( FC_select_folder, select_folderCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_select_multiple, select_multipleCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_show_hidden, show_hiddenCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_local_only, local_onlyCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_do_overwrite_confirmation, do_overwrite_confirmationCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_create_folders, create_foldersCheckBox, optionsSet, optionsClear );
|
||||||
|
|
||||||
|
String fileTypesStr = n( (String) fileTypesField.getSelectedItem() );
|
||||||
|
String[] fileTypes = {};
|
||||||
|
if( fileTypesStr != null ) {
|
||||||
|
if( !fileTypesStr.endsWith( ",null" ) )
|
||||||
|
fileTypesStr += ",null";
|
||||||
|
fileTypes = fileTypesStr.trim().split( "[,]+" );
|
||||||
|
for( int i = 0; i < fileTypes.length; i++ ) {
|
||||||
|
if( "null".equals( fileTypes[i] ) )
|
||||||
|
fileTypes[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int fileTypeIndex = fileTypeIndexSlider.getValue();
|
||||||
|
|
||||||
|
FlatNativeLinuxLibrary.FileChooserCallback callback = (files, hwndFileDialog) -> {
|
||||||
|
System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) );
|
||||||
|
if( showMessageDialogOnOKCheckBox.isSelected() ) {
|
||||||
|
System.out.println( FlatNativeLinuxLibrary.showMessageDialog( hwndFileDialog,
|
||||||
|
JOptionPane.INFORMATION_MESSAGE,
|
||||||
|
"primary text", "secondary text", 1, "Yes", "No" ) );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
System.out.println( FlatNativeLinuxLibrary.isGtk3Available() );
|
||||||
|
|
||||||
|
if( direct ) {
|
||||||
|
String[] files = FlatNativeLinuxLibrary.showFileChooser( owner, open,
|
||||||
|
title, okButtonLabel, currentName, currentFolder,
|
||||||
|
optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes );
|
||||||
|
|
||||||
|
filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" );
|
||||||
|
} else {
|
||||||
|
SecondaryLoop secondaryLoop = Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop();
|
||||||
|
|
||||||
|
String[] fileTypes2 = fileTypes;
|
||||||
|
new Thread( () -> {
|
||||||
|
String[] files = FlatNativeLinuxLibrary.showFileChooser( owner, open,
|
||||||
|
title, okButtonLabel, currentName, currentFolder,
|
||||||
|
optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes2 );
|
||||||
|
|
||||||
|
System.out.println( " secondaryLoop.exit() returned " + secondaryLoop.exit() );
|
||||||
|
|
||||||
|
EventQueue.invokeLater( () -> {
|
||||||
|
filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" );
|
||||||
|
} );
|
||||||
|
} ).start();
|
||||||
|
|
||||||
|
System.out.println( "---- enter secondary loop ----" );
|
||||||
|
System.out.println( "---- secondary loop exited (secondaryLoop.enter() returned " + secondaryLoop.enter() + ") ----" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String n( String s ) {
|
||||||
|
return s != null && !s.isEmpty() ? s : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void o( int option, FlatTriStateCheckBox checkBox, AtomicInteger optionsSet, AtomicInteger optionsClear ) {
|
||||||
|
if( checkBox.getState() == State.SELECTED )
|
||||||
|
optionsSet.set( optionsSet.get() | option );
|
||||||
|
else if( checkBox.getState() == State.UNSELECTED )
|
||||||
|
optionsClear.set( optionsClear.get() | option );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initComponents() {
|
||||||
|
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||||
|
JLabel ownerLabel = new JLabel();
|
||||||
|
ownerFrameRadioButton = new JRadioButton();
|
||||||
|
ownerDialogRadioButton = new JRadioButton();
|
||||||
|
ownerNullRadioButton = new JRadioButton();
|
||||||
|
JPanel ownerSpacer = new JPanel(null);
|
||||||
|
JLabel titleLabel = new JLabel();
|
||||||
|
titleField = new JTextField();
|
||||||
|
JPanel panel1 = new JPanel();
|
||||||
|
select_folderCheckBox = new FlatTriStateCheckBox();
|
||||||
|
select_multipleCheckBox = new FlatTriStateCheckBox();
|
||||||
|
do_overwrite_confirmationCheckBox = new FlatTriStateCheckBox();
|
||||||
|
create_foldersCheckBox = new FlatTriStateCheckBox();
|
||||||
|
show_hiddenCheckBox = new FlatTriStateCheckBox();
|
||||||
|
local_onlyCheckBox = new FlatTriStateCheckBox();
|
||||||
|
JLabel okButtonLabelLabel = new JLabel();
|
||||||
|
okButtonLabelField = new JTextField();
|
||||||
|
JLabel currentNameLabel = new JLabel();
|
||||||
|
currentNameField = new JTextField();
|
||||||
|
JLabel currentFolderLabel = new JLabel();
|
||||||
|
currentFolderField = new JTextField();
|
||||||
|
JLabel fileTypesLabel = new JLabel();
|
||||||
|
fileTypesField = new JComboBox<>();
|
||||||
|
JLabel fileTypeIndexLabel = new JLabel();
|
||||||
|
fileTypeIndexSlider = new JSlider();
|
||||||
|
JButton openButton = new JButton();
|
||||||
|
JButton saveButton = new JButton();
|
||||||
|
JButton openDirectButton = new JButton();
|
||||||
|
JButton saveDirectButton = new JButton();
|
||||||
|
showMessageDialogOnOKCheckBox = new JCheckBox();
|
||||||
|
JScrollPane filesScrollPane = new JScrollPane();
|
||||||
|
filesField = new JTextArea();
|
||||||
|
|
||||||
|
//======== this ========
|
||||||
|
setLayout(new MigLayout(
|
||||||
|
"ltr,insets dialog,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[left]" +
|
||||||
|
"[grow,fill]" +
|
||||||
|
"[fill]",
|
||||||
|
// rows
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[grow,fill]"));
|
||||||
|
|
||||||
|
//---- ownerLabel ----
|
||||||
|
ownerLabel.setText("owner");
|
||||||
|
add(ownerLabel, "cell 0 0");
|
||||||
|
|
||||||
|
//---- ownerFrameRadioButton ----
|
||||||
|
ownerFrameRadioButton.setText("JFrame");
|
||||||
|
ownerFrameRadioButton.setSelected(true);
|
||||||
|
add(ownerFrameRadioButton, "cell 1 0");
|
||||||
|
|
||||||
|
//---- ownerDialogRadioButton ----
|
||||||
|
ownerDialogRadioButton.setText("JDialog");
|
||||||
|
add(ownerDialogRadioButton, "cell 1 0");
|
||||||
|
|
||||||
|
//---- ownerNullRadioButton ----
|
||||||
|
ownerNullRadioButton.setText("null");
|
||||||
|
add(ownerNullRadioButton, "cell 1 0");
|
||||||
|
add(ownerSpacer, "cell 1 0,growx");
|
||||||
|
|
||||||
|
//---- titleLabel ----
|
||||||
|
titleLabel.setText("title");
|
||||||
|
add(titleLabel, "cell 0 1");
|
||||||
|
add(titleField, "cell 1 1");
|
||||||
|
|
||||||
|
//======== panel1 ========
|
||||||
|
{
|
||||||
|
panel1.setLayout(new MigLayout(
|
||||||
|
"insets 2,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[left]",
|
||||||
|
// rows
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]"));
|
||||||
|
|
||||||
|
//---- select_folderCheckBox ----
|
||||||
|
select_folderCheckBox.setText("select_folder");
|
||||||
|
select_folderCheckBox.setAllowIndeterminate(false);
|
||||||
|
select_folderCheckBox.setState(FlatTriStateCheckBox.State.UNSELECTED);
|
||||||
|
panel1.add(select_folderCheckBox, "cell 0 0");
|
||||||
|
|
||||||
|
//---- select_multipleCheckBox ----
|
||||||
|
select_multipleCheckBox.setText("select_multiple");
|
||||||
|
select_multipleCheckBox.setState(FlatTriStateCheckBox.State.UNSELECTED);
|
||||||
|
select_multipleCheckBox.setAllowIndeterminate(false);
|
||||||
|
panel1.add(select_multipleCheckBox, "cell 0 1");
|
||||||
|
|
||||||
|
//---- do_overwrite_confirmationCheckBox ----
|
||||||
|
do_overwrite_confirmationCheckBox.setText("do_overwrite_confirmation");
|
||||||
|
panel1.add(do_overwrite_confirmationCheckBox, "cell 0 2");
|
||||||
|
|
||||||
|
//---- create_foldersCheckBox ----
|
||||||
|
create_foldersCheckBox.setText("create_folders");
|
||||||
|
panel1.add(create_foldersCheckBox, "cell 0 3");
|
||||||
|
|
||||||
|
//---- show_hiddenCheckBox ----
|
||||||
|
show_hiddenCheckBox.setText("show_hidden");
|
||||||
|
panel1.add(show_hiddenCheckBox, "cell 0 4");
|
||||||
|
|
||||||
|
//---- local_onlyCheckBox ----
|
||||||
|
local_onlyCheckBox.setText("local_only");
|
||||||
|
panel1.add(local_onlyCheckBox, "cell 0 5");
|
||||||
|
}
|
||||||
|
add(panel1, "cell 2 1 1 6,aligny top,growy 0");
|
||||||
|
|
||||||
|
//---- okButtonLabelLabel ----
|
||||||
|
okButtonLabelLabel.setText("okButtonLabel");
|
||||||
|
add(okButtonLabelLabel, "cell 0 2");
|
||||||
|
add(okButtonLabelField, "cell 1 2");
|
||||||
|
|
||||||
|
//---- currentNameLabel ----
|
||||||
|
currentNameLabel.setText("currentName");
|
||||||
|
add(currentNameLabel, "cell 0 3");
|
||||||
|
add(currentNameField, "cell 1 3");
|
||||||
|
|
||||||
|
//---- currentFolderLabel ----
|
||||||
|
currentFolderLabel.setText("currentFolder");
|
||||||
|
add(currentFolderLabel, "cell 0 4");
|
||||||
|
add(currentFolderField, "cell 1 4");
|
||||||
|
|
||||||
|
//---- fileTypesLabel ----
|
||||||
|
fileTypesLabel.setText("fileTypes");
|
||||||
|
add(fileTypesLabel, "cell 0 5");
|
||||||
|
|
||||||
|
//---- fileTypesField ----
|
||||||
|
fileTypesField.setEditable(true);
|
||||||
|
fileTypesField.setModel(new DefaultComboBoxModel<>(new String[] {
|
||||||
|
"Text Files,*.txt,null",
|
||||||
|
"All Files,*,null",
|
||||||
|
"Text Files,*.txt,null,PDF Files,*.pdf,null,All Files,*,null",
|
||||||
|
"Text and PDF Files,*.txt,*.pdf,null"
|
||||||
|
}));
|
||||||
|
add(fileTypesField, "cell 1 5");
|
||||||
|
|
||||||
|
//---- fileTypeIndexLabel ----
|
||||||
|
fileTypeIndexLabel.setText("fileTypeIndex");
|
||||||
|
add(fileTypeIndexLabel, "cell 0 6");
|
||||||
|
|
||||||
|
//---- fileTypeIndexSlider ----
|
||||||
|
fileTypeIndexSlider.setMaximum(10);
|
||||||
|
fileTypeIndexSlider.setMajorTickSpacing(1);
|
||||||
|
fileTypeIndexSlider.setValue(0);
|
||||||
|
fileTypeIndexSlider.setPaintLabels(true);
|
||||||
|
fileTypeIndexSlider.setSnapToTicks(true);
|
||||||
|
add(fileTypeIndexSlider, "cell 1 6");
|
||||||
|
|
||||||
|
//---- openButton ----
|
||||||
|
openButton.setText("Open...");
|
||||||
|
openButton.addActionListener(e -> open());
|
||||||
|
add(openButton, "cell 0 7 3 1");
|
||||||
|
|
||||||
|
//---- saveButton ----
|
||||||
|
saveButton.setText("Save...");
|
||||||
|
saveButton.addActionListener(e -> save());
|
||||||
|
add(saveButton, "cell 0 7 3 1");
|
||||||
|
|
||||||
|
//---- openDirectButton ----
|
||||||
|
openDirectButton.setText("Open (no-thread)...");
|
||||||
|
openDirectButton.addActionListener(e -> openDirect());
|
||||||
|
add(openDirectButton, "cell 0 7 3 1");
|
||||||
|
|
||||||
|
//---- saveDirectButton ----
|
||||||
|
saveDirectButton.setText("Save (no-thread)...");
|
||||||
|
saveDirectButton.addActionListener(e -> saveDirect());
|
||||||
|
add(saveDirectButton, "cell 0 7 3 1");
|
||||||
|
|
||||||
|
//---- showMessageDialogOnOKCheckBox ----
|
||||||
|
showMessageDialogOnOKCheckBox.setText("show message dialog on OK");
|
||||||
|
add(showMessageDialogOnOKCheckBox, "cell 0 7 3 1");
|
||||||
|
|
||||||
|
//======== filesScrollPane ========
|
||||||
|
{
|
||||||
|
|
||||||
|
//---- filesField ----
|
||||||
|
filesField.setRows(8);
|
||||||
|
filesScrollPane.setViewportView(filesField);
|
||||||
|
}
|
||||||
|
add(filesScrollPane, "cell 0 8 3 1,growx");
|
||||||
|
|
||||||
|
//---- ownerButtonGroup ----
|
||||||
|
ButtonGroup ownerButtonGroup = new ButtonGroup();
|
||||||
|
ownerButtonGroup.add(ownerFrameRadioButton);
|
||||||
|
ownerButtonGroup.add(ownerDialogRadioButton);
|
||||||
|
ownerButtonGroup.add(ownerNullRadioButton);
|
||||||
|
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||||
|
}
|
||||||
|
|
||||||
|
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||||
|
private JRadioButton ownerFrameRadioButton;
|
||||||
|
private JRadioButton ownerDialogRadioButton;
|
||||||
|
private JRadioButton ownerNullRadioButton;
|
||||||
|
private JTextField titleField;
|
||||||
|
private FlatTriStateCheckBox select_folderCheckBox;
|
||||||
|
private FlatTriStateCheckBox select_multipleCheckBox;
|
||||||
|
private FlatTriStateCheckBox do_overwrite_confirmationCheckBox;
|
||||||
|
private FlatTriStateCheckBox create_foldersCheckBox;
|
||||||
|
private FlatTriStateCheckBox show_hiddenCheckBox;
|
||||||
|
private FlatTriStateCheckBox local_onlyCheckBox;
|
||||||
|
private JTextField okButtonLabelField;
|
||||||
|
private JTextField currentNameField;
|
||||||
|
private JTextField currentFolderField;
|
||||||
|
private JComboBox<String> fileTypesField;
|
||||||
|
private JSlider fileTypeIndexSlider;
|
||||||
|
private JCheckBox showMessageDialogOnOKCheckBox;
|
||||||
|
private JTextArea filesField;
|
||||||
|
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||||
|
}
|
||||||
@@ -0,0 +1,280 @@
|
|||||||
|
JFDML JFormDesigner: "8.2.2.0.9999" Java: "21.0.1" encoding: "UTF-8"
|
||||||
|
|
||||||
|
new FormModel {
|
||||||
|
contentType: "form/swing"
|
||||||
|
root: new FormRoot {
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.defaultVariableLocal": true
|
||||||
|
}
|
||||||
|
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||||
|
"$columnConstraints": "[left][grow,fill][fill]"
|
||||||
|
"$rowConstraints": "[][][][][][][][][grow,fill]"
|
||||||
|
} ) {
|
||||||
|
name: "this"
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "ownerLabel"
|
||||||
|
"text": "owner"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerFrameRadioButton"
|
||||||
|
"text": "JFrame"
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
"selected": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerDialogRadioButton"
|
||||||
|
"text": "JDialog"
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerNullRadioButton"
|
||||||
|
"text": "null"
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
|
||||||
|
name: "ownerSpacer"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0,growx"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "titleLabel"
|
||||||
|
"text": "title"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "titleField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 1"
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "insets 2,hidemode 3"
|
||||||
|
"$columnConstraints": "[left]"
|
||||||
|
"$rowConstraints": "[]0[]0[]0[]0[]0[]"
|
||||||
|
} ) {
|
||||||
|
name: "panel1"
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "select_folderCheckBox"
|
||||||
|
"text": "select_folder"
|
||||||
|
"allowIndeterminate": false
|
||||||
|
"state": enum com.formdev.flatlaf.extras.components.FlatTriStateCheckBox$State UNSELECTED
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "select_multipleCheckBox"
|
||||||
|
"text": "select_multiple"
|
||||||
|
"state": enum com.formdev.flatlaf.extras.components.FlatTriStateCheckBox$State UNSELECTED
|
||||||
|
"allowIndeterminate": false
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "do_overwrite_confirmationCheckBox"
|
||||||
|
"text": "do_overwrite_confirmation"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "create_foldersCheckBox"
|
||||||
|
"text": "create_folders"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "show_hiddenCheckBox"
|
||||||
|
"text": "show_hidden"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "local_onlyCheckBox"
|
||||||
|
"text": "local_only"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 5"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 1 1 6,aligny top,growy 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "okButtonLabelLabel"
|
||||||
|
"text": "okButtonLabel"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "okButtonLabelField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "currentNameLabel"
|
||||||
|
"text": "currentName"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "currentNameField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "currentFolderLabel"
|
||||||
|
"text": "currentFolder"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "currentFolderField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "fileTypesLabel"
|
||||||
|
"text": "fileTypes"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JComboBox" ) {
|
||||||
|
name: "fileTypesField"
|
||||||
|
"editable": true
|
||||||
|
"model": new javax.swing.DefaultComboBoxModel {
|
||||||
|
selectedItem: "Text Files,*.txt,null"
|
||||||
|
addElement( "Text Files,*.txt,null" )
|
||||||
|
addElement( "All Files,*,null" )
|
||||||
|
addElement( "Text Files,*.txt,null,PDF Files,*.pdf,null,All Files,*,null" )
|
||||||
|
addElement( "Text and PDF Files,*.txt,*.pdf,null" )
|
||||||
|
}
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "fileTypeIndexLabel"
|
||||||
|
"text": "fileTypeIndex"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JSlider" ) {
|
||||||
|
name: "fileTypeIndexSlider"
|
||||||
|
"maximum": 10
|
||||||
|
"majorTickSpacing": 1
|
||||||
|
"value": 0
|
||||||
|
"paintLabels": true
|
||||||
|
"snapToTicks": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "openButton"
|
||||||
|
"text": "Open..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "open", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "saveButton"
|
||||||
|
"text": "Save..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "save", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "openDirectButton"
|
||||||
|
"text": "Open (no-thread)..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openDirect", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "saveDirectButton"
|
||||||
|
"text": "Save (no-thread)..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "saveDirect", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "showMessageDialogOnOKCheckBox"
|
||||||
|
"text": "show message dialog on OK"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||||
|
name: "filesScrollPane"
|
||||||
|
add( new FormComponent( "javax.swing.JTextArea" ) {
|
||||||
|
name: "filesField"
|
||||||
|
"rows": 8
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 3 1,growx"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 0 )
|
||||||
|
"size": new java.awt.Dimension( 690, 630 )
|
||||||
|
} )
|
||||||
|
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||||
|
name: "ownerButtonGroup"
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 640 )
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,564 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.testing;
|
||||||
|
|
||||||
|
import static com.formdev.flatlaf.ui.FlatNativeMacLibrary.*;
|
||||||
|
import java.awt.SecondaryLoop;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.Window;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import javax.swing.*;
|
||||||
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.extras.components.*;
|
||||||
|
import com.formdev.flatlaf.extras.components.FlatTriStateCheckBox.State;
|
||||||
|
import com.formdev.flatlaf.testing.FlatSystemFileChooserTest.DummyModalDialog;
|
||||||
|
import com.formdev.flatlaf.ui.FlatNativeMacLibrary;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
|
import net.miginfocom.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class FlatSystemFileChooserMacTest
|
||||||
|
extends FlatTestPanel
|
||||||
|
{
|
||||||
|
public static void main( String[] args ) {
|
||||||
|
// macOS (see https://www.formdev.com/flatlaf/macos/)
|
||||||
|
if( SystemInfo.isMacOS ) {
|
||||||
|
// enable screen menu bar
|
||||||
|
// (moves menu bar from JFrame window to top of screen)
|
||||||
|
System.setProperty( "apple.laf.useScreenMenuBar", "true" );
|
||||||
|
|
||||||
|
// appearance of window title bars
|
||||||
|
// possible values:
|
||||||
|
// - "system": use current macOS appearance (light or dark)
|
||||||
|
// - "NSAppearanceNameAqua": use light appearance
|
||||||
|
// - "NSAppearanceNameDarkAqua": use dark appearance
|
||||||
|
// (needs to be set on main thread; setting it on AWT thread does not work)
|
||||||
|
System.setProperty( "apple.awt.application.appearance", "system" );
|
||||||
|
}
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater( () -> {
|
||||||
|
if( !FlatNativeMacLibrary.isLoaded() ) {
|
||||||
|
JOptionPane.showMessageDialog( null, "FlatLaf native library not loaded" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatTestFrame frame = FlatTestFrame.create( args, "FlatSystemFileChooserMacTest" );
|
||||||
|
FlatSystemFileChooserTest.addListeners( frame );
|
||||||
|
frame.showFrame( FlatSystemFileChooserMacTest::new );
|
||||||
|
frame.setJMenuBar( menuBar1 );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatSystemFileChooserMacTest() {
|
||||||
|
initComponents();
|
||||||
|
|
||||||
|
fileTypesField.setSelectedItem( null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void open() {
|
||||||
|
openOrSave( true, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void save() {
|
||||||
|
openOrSave( false, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openDirect() {
|
||||||
|
openOrSave( true, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveDirect() {
|
||||||
|
openOrSave( false, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openOrSave( boolean open, boolean direct ) {
|
||||||
|
Window frame = SwingUtilities.windowForComponent( this );
|
||||||
|
if( ownerFrameRadioButton.isSelected() )
|
||||||
|
openOrSave( open, direct, frame );
|
||||||
|
else if( ownerDialogRadioButton.isSelected() )
|
||||||
|
new DummyModalDialog( frame, owner -> openOrSave( open, direct, owner ) ).setVisible( true );
|
||||||
|
else
|
||||||
|
openOrSave( open, direct, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openOrSave( boolean open, boolean direct, Window owner ) {
|
||||||
|
String title = n( titleField.getText() );
|
||||||
|
String prompt = n( promptField.getText() );
|
||||||
|
String message = n( messageField.getText() );
|
||||||
|
String filterFieldLabel = n( filterFieldLabelField.getText() );
|
||||||
|
String nameFieldLabel = n( nameFieldLabelField.getText() );
|
||||||
|
String nameFieldStringValue = n( nameFieldStringValueField.getText() );
|
||||||
|
String directoryURL = n( directoryURLField.getText() );
|
||||||
|
AtomicInteger optionsSet = new AtomicInteger();
|
||||||
|
AtomicInteger optionsClear = new AtomicInteger();
|
||||||
|
|
||||||
|
// NSOpenPanel
|
||||||
|
if( canChooseFilesCheckBox.isSelected() )
|
||||||
|
optionsSet.set( optionsSet.get() | FC_canChooseFiles );
|
||||||
|
if( canChooseDirectoriesCheckBox.isSelected() )
|
||||||
|
optionsSet.set( optionsSet.get() | FC_canChooseDirectories );
|
||||||
|
o( FC_resolvesAliases, resolvesAliasesCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_allowsMultipleSelection, allowsMultipleSelectionCheckBox, optionsSet, optionsClear );
|
||||||
|
if( accessoryViewDisclosedCheckBox.isSelected() )
|
||||||
|
optionsSet.set( optionsSet.get() | FC_accessoryViewDisclosed );
|
||||||
|
|
||||||
|
// NSSavePanel
|
||||||
|
o( FC_showsTagField, showsTagFieldCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_canCreateDirectories, canCreateDirectoriesCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_canSelectHiddenExtension, canSelectHiddenExtensionCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_showsHiddenFiles, showsHiddenFilesCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_extensionHidden, extensionHiddenCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_allowsOtherFileTypes, allowsOtherFileTypesCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FC_treatsFilePackagesAsDirectories, treatsFilePackagesAsDirectoriesCheckBox, optionsSet, optionsClear );
|
||||||
|
|
||||||
|
// custom
|
||||||
|
if( showSingleFilterFieldCheckBox.isSelected() )
|
||||||
|
optionsSet.set( optionsSet.get() | FC_showSingleFilterField );
|
||||||
|
|
||||||
|
String fileTypesStr = n( (String) fileTypesField.getSelectedItem() );
|
||||||
|
String[] fileTypes = {};
|
||||||
|
if( fileTypesStr != null ) {
|
||||||
|
if( !fileTypesStr.endsWith( ",null" ) )
|
||||||
|
fileTypesStr += ",null";
|
||||||
|
fileTypes = fileTypesStr.trim().split( "[,]+" );
|
||||||
|
for( int i = 0; i < fileTypes.length; i++ ) {
|
||||||
|
if( "null".equals( fileTypes[i] ) )
|
||||||
|
fileTypes[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int fileTypeIndex = fileTypeIndexSlider.getValue();
|
||||||
|
|
||||||
|
FlatNativeMacLibrary.FileChooserCallback callback = (files, hwndFileDialog) -> {
|
||||||
|
System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) );
|
||||||
|
if( showMessageDialogOnOKCheckBox.isSelected() ) {
|
||||||
|
int result = FlatNativeMacLibrary.showMessageDialog( hwndFileDialog,
|
||||||
|
JOptionPane.INFORMATION_MESSAGE,
|
||||||
|
"primary text", "secondary text", 0, "Yes", "No" );
|
||||||
|
System.out.println( " result " + result );
|
||||||
|
if( result != 0 )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
int dark = FlatLaf.isLafDark() ? 1 : 0;
|
||||||
|
if( direct ) {
|
||||||
|
String[] files = FlatNativeMacLibrary.showFileChooser( owner, dark, open,
|
||||||
|
title, prompt, message, filterFieldLabel,
|
||||||
|
nameFieldLabel, nameFieldStringValue, directoryURL,
|
||||||
|
optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes );
|
||||||
|
|
||||||
|
filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" );
|
||||||
|
} else {
|
||||||
|
SecondaryLoop secondaryLoop = Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop();
|
||||||
|
|
||||||
|
String[] fileTypes2 = fileTypes;
|
||||||
|
new Thread( () -> {
|
||||||
|
String[] files = FlatNativeMacLibrary.showFileChooser( owner, dark, open,
|
||||||
|
title, prompt, message, filterFieldLabel,
|
||||||
|
nameFieldLabel, nameFieldStringValue, directoryURL,
|
||||||
|
optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes2 );
|
||||||
|
|
||||||
|
System.out.println( " secondaryLoop.exit() returned " + secondaryLoop.exit() );
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater( () -> {
|
||||||
|
filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" );
|
||||||
|
} );
|
||||||
|
} ).start();
|
||||||
|
|
||||||
|
System.out.println( "---- enter secondary loop ----" );
|
||||||
|
System.out.println( "---- secondary loop exited (secondaryLoop.enter() returned " + secondaryLoop.enter() + ") ----" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String n( String s ) {
|
||||||
|
return s != null && !s.isEmpty() ? s : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void o( int option, FlatTriStateCheckBox checkBox, AtomicInteger optionsSet, AtomicInteger optionsClear ) {
|
||||||
|
if( checkBox.getState() == State.SELECTED )
|
||||||
|
optionsSet.set( optionsSet.get() | option );
|
||||||
|
else if( checkBox.getState() == State.UNSELECTED )
|
||||||
|
optionsClear.set( optionsClear.get() | option );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void menuItemAction() {
|
||||||
|
System.out.println( "menu item action" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initComponents() {
|
||||||
|
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||||
|
JLabel ownerLabel = new JLabel();
|
||||||
|
ownerFrameRadioButton = new JRadioButton();
|
||||||
|
ownerDialogRadioButton = new JRadioButton();
|
||||||
|
ownerNullRadioButton = new JRadioButton();
|
||||||
|
JPanel ownerSpacer = new JPanel(null);
|
||||||
|
JLabel titleLabel = new JLabel();
|
||||||
|
titleField = new JTextField();
|
||||||
|
JPanel panel1 = new JPanel();
|
||||||
|
JLabel options1Label = new JLabel();
|
||||||
|
canChooseFilesCheckBox = new JCheckBox();
|
||||||
|
canChooseDirectoriesCheckBox = new JCheckBox();
|
||||||
|
resolvesAliasesCheckBox = new FlatTriStateCheckBox();
|
||||||
|
allowsMultipleSelectionCheckBox = new FlatTriStateCheckBox();
|
||||||
|
accessoryViewDisclosedCheckBox = new JCheckBox();
|
||||||
|
JLabel options2Label = new JLabel();
|
||||||
|
showsTagFieldCheckBox = new FlatTriStateCheckBox();
|
||||||
|
canCreateDirectoriesCheckBox = new FlatTriStateCheckBox();
|
||||||
|
canSelectHiddenExtensionCheckBox = new FlatTriStateCheckBox();
|
||||||
|
showsHiddenFilesCheckBox = new FlatTriStateCheckBox();
|
||||||
|
extensionHiddenCheckBox = new FlatTriStateCheckBox();
|
||||||
|
allowsOtherFileTypesCheckBox = new FlatTriStateCheckBox();
|
||||||
|
treatsFilePackagesAsDirectoriesCheckBox = new FlatTriStateCheckBox();
|
||||||
|
JLabel options3Label = new JLabel();
|
||||||
|
showSingleFilterFieldCheckBox = new JCheckBox();
|
||||||
|
JLabel promptLabel = new JLabel();
|
||||||
|
promptField = new JTextField();
|
||||||
|
JLabel messageLabel = new JLabel();
|
||||||
|
messageField = new JTextField();
|
||||||
|
JLabel filterFieldLabelLabel = new JLabel();
|
||||||
|
filterFieldLabelField = new JTextField();
|
||||||
|
JLabel nameFieldLabelLabel = new JLabel();
|
||||||
|
nameFieldLabelField = new JTextField();
|
||||||
|
JLabel nameFieldStringValueLabel = new JLabel();
|
||||||
|
nameFieldStringValueField = new JTextField();
|
||||||
|
JLabel directoryURLLabel = new JLabel();
|
||||||
|
directoryURLField = new JTextField();
|
||||||
|
JLabel fileTypesLabel = new JLabel();
|
||||||
|
fileTypesField = new JComboBox<>();
|
||||||
|
JLabel fileTypeIndexLabel = new JLabel();
|
||||||
|
fileTypeIndexSlider = new JSlider();
|
||||||
|
JButton openButton = new JButton();
|
||||||
|
JButton saveButton = new JButton();
|
||||||
|
JButton openDirectButton = new JButton();
|
||||||
|
JButton saveDirectButton = new JButton();
|
||||||
|
showMessageDialogOnOKCheckBox = new JCheckBox();
|
||||||
|
JScrollPane filesScrollPane = new JScrollPane();
|
||||||
|
filesField = new JTextArea();
|
||||||
|
menuBar1 = new JMenuBar();
|
||||||
|
JMenu menu1 = new JMenu();
|
||||||
|
JMenuItem menuItem1 = new JMenuItem();
|
||||||
|
JMenuItem menuItem2 = new JMenuItem();
|
||||||
|
JMenu menu2 = new JMenu();
|
||||||
|
JMenuItem menuItem3 = new JMenuItem();
|
||||||
|
JMenuItem menuItem4 = new JMenuItem();
|
||||||
|
|
||||||
|
//======== this ========
|
||||||
|
setLayout(new MigLayout(
|
||||||
|
"ltr,insets dialog,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[left]" +
|
||||||
|
"[grow,fill]" +
|
||||||
|
"[fill]",
|
||||||
|
// rows
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[grow,fill]"));
|
||||||
|
|
||||||
|
//---- ownerLabel ----
|
||||||
|
ownerLabel.setText("owner");
|
||||||
|
add(ownerLabel, "cell 0 0");
|
||||||
|
|
||||||
|
//---- ownerFrameRadioButton ----
|
||||||
|
ownerFrameRadioButton.setText("JFrame");
|
||||||
|
ownerFrameRadioButton.setSelected(true);
|
||||||
|
add(ownerFrameRadioButton, "cell 1 0");
|
||||||
|
|
||||||
|
//---- ownerDialogRadioButton ----
|
||||||
|
ownerDialogRadioButton.setText("JDialog");
|
||||||
|
add(ownerDialogRadioButton, "cell 1 0");
|
||||||
|
|
||||||
|
//---- ownerNullRadioButton ----
|
||||||
|
ownerNullRadioButton.setText("null");
|
||||||
|
add(ownerNullRadioButton, "cell 1 0");
|
||||||
|
add(ownerSpacer, "cell 1 0,growx");
|
||||||
|
|
||||||
|
//---- titleLabel ----
|
||||||
|
titleLabel.setText("title");
|
||||||
|
add(titleLabel, "cell 0 1");
|
||||||
|
add(titleField, "cell 1 1");
|
||||||
|
|
||||||
|
//======== panel1 ========
|
||||||
|
{
|
||||||
|
panel1.setLayout(new MigLayout(
|
||||||
|
"insets 2,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[left]",
|
||||||
|
// rows
|
||||||
|
"[]" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]para" +
|
||||||
|
"[]" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]para" +
|
||||||
|
"[]" +
|
||||||
|
"[]"));
|
||||||
|
|
||||||
|
//---- options1Label ----
|
||||||
|
options1Label.setText("NSOpenPanel options:");
|
||||||
|
panel1.add(options1Label, "cell 0 0");
|
||||||
|
|
||||||
|
//---- canChooseFilesCheckBox ----
|
||||||
|
canChooseFilesCheckBox.setText("canChooseFiles");
|
||||||
|
canChooseFilesCheckBox.setSelected(true);
|
||||||
|
panel1.add(canChooseFilesCheckBox, "cell 0 1");
|
||||||
|
|
||||||
|
//---- canChooseDirectoriesCheckBox ----
|
||||||
|
canChooseDirectoriesCheckBox.setText("canChooseDirectories");
|
||||||
|
panel1.add(canChooseDirectoriesCheckBox, "cell 0 2");
|
||||||
|
|
||||||
|
//---- resolvesAliasesCheckBox ----
|
||||||
|
resolvesAliasesCheckBox.setText("resolvesAliases");
|
||||||
|
resolvesAliasesCheckBox.setState(FlatTriStateCheckBox.State.SELECTED);
|
||||||
|
panel1.add(resolvesAliasesCheckBox, "cell 0 3");
|
||||||
|
|
||||||
|
//---- allowsMultipleSelectionCheckBox ----
|
||||||
|
allowsMultipleSelectionCheckBox.setText("allowsMultipleSelection");
|
||||||
|
panel1.add(allowsMultipleSelectionCheckBox, "cell 0 4");
|
||||||
|
|
||||||
|
//---- accessoryViewDisclosedCheckBox ----
|
||||||
|
accessoryViewDisclosedCheckBox.setText("accessoryViewDisclosed");
|
||||||
|
panel1.add(accessoryViewDisclosedCheckBox, "cell 0 5");
|
||||||
|
|
||||||
|
//---- options2Label ----
|
||||||
|
options2Label.setText("NSOpenPanel and NSSavePanel options:");
|
||||||
|
panel1.add(options2Label, "cell 0 6");
|
||||||
|
|
||||||
|
//---- showsTagFieldCheckBox ----
|
||||||
|
showsTagFieldCheckBox.setText("showsTagField");
|
||||||
|
panel1.add(showsTagFieldCheckBox, "cell 0 7");
|
||||||
|
|
||||||
|
//---- canCreateDirectoriesCheckBox ----
|
||||||
|
canCreateDirectoriesCheckBox.setText("canCreateDirectories");
|
||||||
|
panel1.add(canCreateDirectoriesCheckBox, "cell 0 8");
|
||||||
|
|
||||||
|
//---- canSelectHiddenExtensionCheckBox ----
|
||||||
|
canSelectHiddenExtensionCheckBox.setText("canSelectHiddenExtension");
|
||||||
|
panel1.add(canSelectHiddenExtensionCheckBox, "cell 0 9");
|
||||||
|
|
||||||
|
//---- showsHiddenFilesCheckBox ----
|
||||||
|
showsHiddenFilesCheckBox.setText("showsHiddenFiles");
|
||||||
|
panel1.add(showsHiddenFilesCheckBox, "cell 0 10");
|
||||||
|
|
||||||
|
//---- extensionHiddenCheckBox ----
|
||||||
|
extensionHiddenCheckBox.setText("extensionHidden");
|
||||||
|
panel1.add(extensionHiddenCheckBox, "cell 0 11");
|
||||||
|
|
||||||
|
//---- allowsOtherFileTypesCheckBox ----
|
||||||
|
allowsOtherFileTypesCheckBox.setText("allowsOtherFileTypes");
|
||||||
|
panel1.add(allowsOtherFileTypesCheckBox, "cell 0 12");
|
||||||
|
|
||||||
|
//---- treatsFilePackagesAsDirectoriesCheckBox ----
|
||||||
|
treatsFilePackagesAsDirectoriesCheckBox.setText("treatsFilePackagesAsDirectories");
|
||||||
|
panel1.add(treatsFilePackagesAsDirectoriesCheckBox, "cell 0 13");
|
||||||
|
|
||||||
|
//---- options3Label ----
|
||||||
|
options3Label.setText("Custom options:");
|
||||||
|
panel1.add(options3Label, "cell 0 14");
|
||||||
|
|
||||||
|
//---- showSingleFilterFieldCheckBox ----
|
||||||
|
showSingleFilterFieldCheckBox.setText("showSingleFilterField");
|
||||||
|
panel1.add(showSingleFilterFieldCheckBox, "cell 0 15");
|
||||||
|
}
|
||||||
|
add(panel1, "cell 2 1 1 10,aligny top,growy 0");
|
||||||
|
|
||||||
|
//---- promptLabel ----
|
||||||
|
promptLabel.setText("prompt");
|
||||||
|
add(promptLabel, "cell 0 2");
|
||||||
|
add(promptField, "cell 1 2");
|
||||||
|
|
||||||
|
//---- messageLabel ----
|
||||||
|
messageLabel.setText("message");
|
||||||
|
add(messageLabel, "cell 0 3");
|
||||||
|
add(messageField, "cell 1 3");
|
||||||
|
|
||||||
|
//---- filterFieldLabelLabel ----
|
||||||
|
filterFieldLabelLabel.setText("filterFieldLabel");
|
||||||
|
add(filterFieldLabelLabel, "cell 0 4");
|
||||||
|
add(filterFieldLabelField, "cell 1 4");
|
||||||
|
|
||||||
|
//---- nameFieldLabelLabel ----
|
||||||
|
nameFieldLabelLabel.setText("nameFieldLabel");
|
||||||
|
add(nameFieldLabelLabel, "cell 0 5");
|
||||||
|
add(nameFieldLabelField, "cell 1 5");
|
||||||
|
|
||||||
|
//---- nameFieldStringValueLabel ----
|
||||||
|
nameFieldStringValueLabel.setText("nameFieldStringValue");
|
||||||
|
add(nameFieldStringValueLabel, "cell 0 6");
|
||||||
|
add(nameFieldStringValueField, "cell 1 6");
|
||||||
|
|
||||||
|
//---- directoryURLLabel ----
|
||||||
|
directoryURLLabel.setText("directoryURL");
|
||||||
|
add(directoryURLLabel, "cell 0 7");
|
||||||
|
add(directoryURLField, "cell 1 7");
|
||||||
|
|
||||||
|
//---- fileTypesLabel ----
|
||||||
|
fileTypesLabel.setText("fileTypes");
|
||||||
|
add(fileTypesLabel, "cell 0 8");
|
||||||
|
|
||||||
|
//---- fileTypesField ----
|
||||||
|
fileTypesField.setEditable(true);
|
||||||
|
fileTypesField.setModel(new DefaultComboBoxModel<>(new String[] {
|
||||||
|
"Text Files,txt,null",
|
||||||
|
"All Files,*,null",
|
||||||
|
"Text Files,txt,null,PDF Files,pdf,null,All Files,*,null",
|
||||||
|
"Text and PDF Files,txt,pdf,null",
|
||||||
|
"Compressed,zip,gz,null,Disk Images,dmg,null"
|
||||||
|
}));
|
||||||
|
add(fileTypesField, "cell 1 8");
|
||||||
|
|
||||||
|
//---- fileTypeIndexLabel ----
|
||||||
|
fileTypeIndexLabel.setText("fileTypeIndex");
|
||||||
|
add(fileTypeIndexLabel, "cell 0 9");
|
||||||
|
|
||||||
|
//---- fileTypeIndexSlider ----
|
||||||
|
fileTypeIndexSlider.setMaximum(10);
|
||||||
|
fileTypeIndexSlider.setMajorTickSpacing(1);
|
||||||
|
fileTypeIndexSlider.setValue(0);
|
||||||
|
fileTypeIndexSlider.setPaintLabels(true);
|
||||||
|
fileTypeIndexSlider.setSnapToTicks(true);
|
||||||
|
add(fileTypeIndexSlider, "cell 1 9");
|
||||||
|
|
||||||
|
//---- openButton ----
|
||||||
|
openButton.setText("Open...");
|
||||||
|
openButton.addActionListener(e -> open());
|
||||||
|
add(openButton, "cell 0 11 3 1");
|
||||||
|
|
||||||
|
//---- saveButton ----
|
||||||
|
saveButton.setText("Save...");
|
||||||
|
saveButton.addActionListener(e -> save());
|
||||||
|
add(saveButton, "cell 0 11 3 1");
|
||||||
|
|
||||||
|
//---- openDirectButton ----
|
||||||
|
openDirectButton.setText("Open (no-thread)...");
|
||||||
|
openDirectButton.addActionListener(e -> openDirect());
|
||||||
|
add(openDirectButton, "cell 0 11 3 1");
|
||||||
|
|
||||||
|
//---- saveDirectButton ----
|
||||||
|
saveDirectButton.setText("Save (no-thread)...");
|
||||||
|
saveDirectButton.addActionListener(e -> saveDirect());
|
||||||
|
add(saveDirectButton, "cell 0 11 3 1");
|
||||||
|
|
||||||
|
//---- showMessageDialogOnOKCheckBox ----
|
||||||
|
showMessageDialogOnOKCheckBox.setText("show message dialog on OK");
|
||||||
|
add(showMessageDialogOnOKCheckBox, "cell 0 11 3 1");
|
||||||
|
|
||||||
|
//======== filesScrollPane ========
|
||||||
|
{
|
||||||
|
|
||||||
|
//---- filesField ----
|
||||||
|
filesField.setRows(8);
|
||||||
|
filesScrollPane.setViewportView(filesField);
|
||||||
|
}
|
||||||
|
add(filesScrollPane, "cell 0 12 3 1,growx");
|
||||||
|
|
||||||
|
//======== menuBar1 ========
|
||||||
|
{
|
||||||
|
|
||||||
|
//======== menu1 ========
|
||||||
|
{
|
||||||
|
menu1.setText("text");
|
||||||
|
|
||||||
|
//---- menuItem1 ----
|
||||||
|
menuItem1.setText("text");
|
||||||
|
menuItem1.addActionListener(e -> menuItemAction());
|
||||||
|
menu1.add(menuItem1);
|
||||||
|
|
||||||
|
//---- menuItem2 ----
|
||||||
|
menuItem2.setText("text");
|
||||||
|
menuItem2.addActionListener(e -> menuItemAction());
|
||||||
|
menu1.add(menuItem2);
|
||||||
|
}
|
||||||
|
menuBar1.add(menu1);
|
||||||
|
|
||||||
|
//======== menu2 ========
|
||||||
|
{
|
||||||
|
menu2.setText("text");
|
||||||
|
|
||||||
|
//---- menuItem3 ----
|
||||||
|
menuItem3.setText("text");
|
||||||
|
menuItem3.addActionListener(e -> menuItemAction());
|
||||||
|
menu2.add(menuItem3);
|
||||||
|
|
||||||
|
//---- menuItem4 ----
|
||||||
|
menuItem4.setText("text");
|
||||||
|
menuItem4.addActionListener(e -> menuItemAction());
|
||||||
|
menu2.add(menuItem4);
|
||||||
|
}
|
||||||
|
menuBar1.add(menu2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---- ownerButtonGroup ----
|
||||||
|
ButtonGroup ownerButtonGroup = new ButtonGroup();
|
||||||
|
ownerButtonGroup.add(ownerFrameRadioButton);
|
||||||
|
ownerButtonGroup.add(ownerDialogRadioButton);
|
||||||
|
ownerButtonGroup.add(ownerNullRadioButton);
|
||||||
|
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||||
|
}
|
||||||
|
|
||||||
|
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||||
|
private JRadioButton ownerFrameRadioButton;
|
||||||
|
private JRadioButton ownerDialogRadioButton;
|
||||||
|
private JRadioButton ownerNullRadioButton;
|
||||||
|
private JTextField titleField;
|
||||||
|
private JCheckBox canChooseFilesCheckBox;
|
||||||
|
private JCheckBox canChooseDirectoriesCheckBox;
|
||||||
|
private FlatTriStateCheckBox resolvesAliasesCheckBox;
|
||||||
|
private FlatTriStateCheckBox allowsMultipleSelectionCheckBox;
|
||||||
|
private JCheckBox accessoryViewDisclosedCheckBox;
|
||||||
|
private FlatTriStateCheckBox showsTagFieldCheckBox;
|
||||||
|
private FlatTriStateCheckBox canCreateDirectoriesCheckBox;
|
||||||
|
private FlatTriStateCheckBox canSelectHiddenExtensionCheckBox;
|
||||||
|
private FlatTriStateCheckBox showsHiddenFilesCheckBox;
|
||||||
|
private FlatTriStateCheckBox extensionHiddenCheckBox;
|
||||||
|
private FlatTriStateCheckBox allowsOtherFileTypesCheckBox;
|
||||||
|
private FlatTriStateCheckBox treatsFilePackagesAsDirectoriesCheckBox;
|
||||||
|
private JCheckBox showSingleFilterFieldCheckBox;
|
||||||
|
private JTextField promptField;
|
||||||
|
private JTextField messageField;
|
||||||
|
private JTextField filterFieldLabelField;
|
||||||
|
private JTextField nameFieldLabelField;
|
||||||
|
private JTextField nameFieldStringValueField;
|
||||||
|
private JTextField directoryURLField;
|
||||||
|
private JComboBox<String> fileTypesField;
|
||||||
|
private JSlider fileTypeIndexSlider;
|
||||||
|
private JCheckBox showMessageDialogOnOKCheckBox;
|
||||||
|
private JTextArea filesField;
|
||||||
|
private static JMenuBar menuBar1;
|
||||||
|
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||||
|
}
|
||||||
@@ -0,0 +1,440 @@
|
|||||||
|
JFDML JFormDesigner: "8.2.2.0.9999" Java: "21.0.1" encoding: "UTF-8"
|
||||||
|
|
||||||
|
new FormModel {
|
||||||
|
contentType: "form/swing"
|
||||||
|
root: new FormRoot {
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.defaultVariableLocal": true
|
||||||
|
}
|
||||||
|
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||||
|
"$columnConstraints": "[left][grow,fill][fill]"
|
||||||
|
"$rowConstraints": "[][][][][][][][][][][][][grow,fill]"
|
||||||
|
} ) {
|
||||||
|
name: "this"
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "ownerLabel"
|
||||||
|
"text": "owner"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerFrameRadioButton"
|
||||||
|
"text": "JFrame"
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
"selected": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerDialogRadioButton"
|
||||||
|
"text": "JDialog"
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerNullRadioButton"
|
||||||
|
"text": "null"
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
|
||||||
|
name: "ownerSpacer"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0,growx"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "titleLabel"
|
||||||
|
"text": "title"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "titleField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 1"
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "insets 2,hidemode 3"
|
||||||
|
"$columnConstraints": "[left]"
|
||||||
|
"$rowConstraints": "[][]0[]0[]0[]0[]para[][]0[]0[]0[]0[]0[]0[]para[][]"
|
||||||
|
} ) {
|
||||||
|
name: "panel1"
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "options1Label"
|
||||||
|
"text": "NSOpenPanel options:"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "canChooseFilesCheckBox"
|
||||||
|
"text": "canChooseFiles"
|
||||||
|
"selected": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "canChooseDirectoriesCheckBox"
|
||||||
|
"text": "canChooseDirectories"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "resolvesAliasesCheckBox"
|
||||||
|
"text": "resolvesAliases"
|
||||||
|
"state": enum com.formdev.flatlaf.extras.components.FlatTriStateCheckBox$State SELECTED
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "allowsMultipleSelectionCheckBox"
|
||||||
|
"text": "allowsMultipleSelection"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "accessoryViewDisclosedCheckBox"
|
||||||
|
"text": "accessoryViewDisclosed"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "options2Label"
|
||||||
|
"text": "NSOpenPanel and NSSavePanel options:"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "showsTagFieldCheckBox"
|
||||||
|
"text": "showsTagField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "canCreateDirectoriesCheckBox"
|
||||||
|
"text": "canCreateDirectories"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "canSelectHiddenExtensionCheckBox"
|
||||||
|
"text": "canSelectHiddenExtension"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 9"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "showsHiddenFilesCheckBox"
|
||||||
|
"text": "showsHiddenFiles"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 10"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "extensionHiddenCheckBox"
|
||||||
|
"text": "extensionHidden"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "allowsOtherFileTypesCheckBox"
|
||||||
|
"text": "allowsOtherFileTypes"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 12"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "treatsFilePackagesAsDirectoriesCheckBox"
|
||||||
|
"text": "treatsFilePackagesAsDirectories"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 13"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "options3Label"
|
||||||
|
"text": "Custom options:"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 14"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "showSingleFilterFieldCheckBox"
|
||||||
|
"text": "showSingleFilterField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 15"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 1 1 10,aligny top,growy 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "promptLabel"
|
||||||
|
"text": "prompt"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "promptField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "messageLabel"
|
||||||
|
"text": "message"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "messageField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "filterFieldLabelLabel"
|
||||||
|
"text": "filterFieldLabel"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "filterFieldLabelField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "nameFieldLabelLabel"
|
||||||
|
"text": "nameFieldLabel"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "nameFieldLabelField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "nameFieldStringValueLabel"
|
||||||
|
"text": "nameFieldStringValue"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "nameFieldStringValueField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "directoryURLLabel"
|
||||||
|
"text": "directoryURL"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "directoryURLField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 7"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "fileTypesLabel"
|
||||||
|
"text": "fileTypes"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JComboBox" ) {
|
||||||
|
name: "fileTypesField"
|
||||||
|
"editable": true
|
||||||
|
"model": new javax.swing.DefaultComboBoxModel {
|
||||||
|
selectedItem: "Text Files,txt,null"
|
||||||
|
addElement( "Text Files,txt,null" )
|
||||||
|
addElement( "All Files,*,null" )
|
||||||
|
addElement( "Text Files,txt,null,PDF Files,pdf,null,All Files,*,null" )
|
||||||
|
addElement( "Text and PDF Files,txt,pdf,null" )
|
||||||
|
addElement( "Compressed,zip,gz,null,Disk Images,dmg,null" )
|
||||||
|
}
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 8"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "fileTypeIndexLabel"
|
||||||
|
"text": "fileTypeIndex"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 9"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JSlider" ) {
|
||||||
|
name: "fileTypeIndexSlider"
|
||||||
|
"maximum": 10
|
||||||
|
"majorTickSpacing": 1
|
||||||
|
"value": 0
|
||||||
|
"paintLabels": true
|
||||||
|
"snapToTicks": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 9"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "openButton"
|
||||||
|
"text": "Open..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "open", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "saveButton"
|
||||||
|
"text": "Save..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "save", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "openDirectButton"
|
||||||
|
"text": "Open (no-thread)..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openDirect", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "saveDirectButton"
|
||||||
|
"text": "Save (no-thread)..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "saveDirect", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "showMessageDialogOnOKCheckBox"
|
||||||
|
"text": "show message dialog on OK"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||||
|
name: "filesScrollPane"
|
||||||
|
add( new FormComponent( "javax.swing.JTextArea" ) {
|
||||||
|
name: "filesField"
|
||||||
|
"rows": 8
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 12 3 1,growx"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 0 )
|
||||||
|
"size": new java.awt.Dimension( 750, 565 )
|
||||||
|
} )
|
||||||
|
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||||
|
name: "ownerButtonGroup"
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 575 )
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) {
|
||||||
|
name: "menuBar1"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableModifiers": 10
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||||
|
name: "menu1"
|
||||||
|
"text": "text"
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "menuItem1"
|
||||||
|
"text": "text"
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemAction", false ) )
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "menuItem2"
|
||||||
|
"text": "text"
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemAction", false ) )
|
||||||
|
} )
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||||
|
name: "menu2"
|
||||||
|
"text": "text"
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "menuItem3"
|
||||||
|
"text": "text"
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemAction", false ) )
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "menuItem4"
|
||||||
|
"text": "text"
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemAction", false ) )
|
||||||
|
} )
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 630 )
|
||||||
|
"size": new java.awt.Dimension( 76, 24 )
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,521 @@
|
|||||||
|
JFDML JFormDesigner: "8.3" encoding: "UTF-8"
|
||||||
|
|
||||||
|
new FormModel {
|
||||||
|
contentType: "form/swing"
|
||||||
|
root: new FormRoot {
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.defaultVariableLocal": true
|
||||||
|
}
|
||||||
|
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||||
|
"$columnConstraints": "[left][grow,fill][fill]"
|
||||||
|
"$rowConstraints": "[][][][][][][][][][grow,fill]"
|
||||||
|
} ) {
|
||||||
|
name: "this"
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "ownerLabel"
|
||||||
|
"text": "owner"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerFrameRadioButton"
|
||||||
|
"text": "JFrame"
|
||||||
|
"selected": true
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerDialogRadioButton"
|
||||||
|
"text": "JDialog"
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerNullRadioButton"
|
||||||
|
"text": "null"
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
|
||||||
|
name: "ownerSpacer"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0,growx"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "dialogTitleLabel"
|
||||||
|
"text": "dialogTitle"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "dialogTitleField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 1"
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "insets 2,hidemode 3"
|
||||||
|
"$columnConstraints": "[left]"
|
||||||
|
"$rowConstraints": "[]0[]0[][]para[][]"
|
||||||
|
} ) {
|
||||||
|
name: "panel1"
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "directorySelectionCheckBox"
|
||||||
|
"text": "directorySelection"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "multiSelectionEnabledCheckBox"
|
||||||
|
"text": "multiSelectionEnabled"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "useFileHidingCheckBox"
|
||||||
|
"text": "useFileHiding"
|
||||||
|
"selected": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "useSystemFileChooserCheckBox"
|
||||||
|
"text": "use SystemFileChooser"
|
||||||
|
"selected": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "persistStateCheckBox"
|
||||||
|
"text": "persist state"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "persistStateChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "stateStoreIDLabel"
|
||||||
|
"text": "ID:"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JComboBox" ) {
|
||||||
|
name: "stateStoreIDField"
|
||||||
|
"model": new javax.swing.DefaultComboBoxModel {
|
||||||
|
selectedItem: "abc"
|
||||||
|
addElement( "abc" )
|
||||||
|
addElement( "def" )
|
||||||
|
}
|
||||||
|
"editable": true
|
||||||
|
"selectedIndex": -1
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 5,growx"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 1 1 7,aligny top,growy 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "approveButtonTextLabel"
|
||||||
|
"text": "approveButtonText"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "approveButtonTextField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 2,growx"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "approveButtonMnemonicLabel"
|
||||||
|
"text": "approveButtonMnemonic"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "approveButtonMnemonicField"
|
||||||
|
"columns": 3
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "currentDirCheckBox"
|
||||||
|
"text": "current directory"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "currentDirChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "currentDirField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 3,growx"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "currentDirChooseButton"
|
||||||
|
"text": "..."
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "chooseCurrentDir", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "selectedFileCheckBox"
|
||||||
|
"text": "selected file"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "selectedFileChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "selectedFileField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 4,growx"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "selectedFileChooseButton"
|
||||||
|
"text": "..."
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "chooseSelectedFile", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "selectedFilesCheckBox"
|
||||||
|
"text": "selected files"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "selectedFilesChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "selectedFilesField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 5,growx"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "selectedFilesChooseButton"
|
||||||
|
"text": "..."
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "chooseSelectedFiles", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "fileTypesLabel"
|
||||||
|
"text": "fileTypes"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JComboBox" ) {
|
||||||
|
name: "fileTypesField"
|
||||||
|
"editable": true
|
||||||
|
"model": new javax.swing.DefaultComboBoxModel {
|
||||||
|
selectedItem: "Text Files,txt"
|
||||||
|
addElement( "Text Files,txt" )
|
||||||
|
addElement( "All Files,*" )
|
||||||
|
addElement( "Text Files,txt,PDF Files,pdf,All Files,*" )
|
||||||
|
addElement( "Text and PDF Files,txt;pdf" )
|
||||||
|
}
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "fileTypeIndexLabel"
|
||||||
|
"text": "fileTypeIndex"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JSlider" ) {
|
||||||
|
name: "fileTypeIndexSlider"
|
||||||
|
"maximum": 10
|
||||||
|
"majorTickSpacing": 1
|
||||||
|
"value": 0
|
||||||
|
"paintLabels": true
|
||||||
|
"snapToTicks": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 7,growx"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "useAcceptAllFileFilterCheckBox"
|
||||||
|
"text": "useAcceptAllFileFilter"
|
||||||
|
"selected": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 7"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "openButton"
|
||||||
|
"text": "Open..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "open", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "saveButton"
|
||||||
|
"text": "Save..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "save", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "swingOpenButton"
|
||||||
|
"text": "Swing Open..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "swingOpen", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "swingSaveButton"
|
||||||
|
"text": "Swing Save..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "swingSave", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "awtOpenButton"
|
||||||
|
"text": "AWT Open..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "awtOpen", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "awtSaveButton"
|
||||||
|
"text": "AWT Save..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "awtSave", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "javafxOpenButton"
|
||||||
|
"text": "JavaFX Open..."
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "javafxOpen", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "javafxSaveButton"
|
||||||
|
"text": "JavaFX Save..."
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "javafxSave", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||||
|
name: "outputScrollPane"
|
||||||
|
add( new FormComponent( "javax.swing.JTextArea" ) {
|
||||||
|
name: "outputField"
|
||||||
|
"rows": 20
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 9 3 1,growx"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 0 )
|
||||||
|
"size": new java.awt.Dimension( 825, 465 )
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JMenuBar", new FormLayoutManager( class javax.swing.JMenuBar ) ) {
|
||||||
|
name: "menuBar1"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableModifiers": 10
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||||
|
name: "menu1"
|
||||||
|
"text": "text"
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "menuItem1"
|
||||||
|
"text": "text"
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemAction", false ) )
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "menuItem2"
|
||||||
|
"text": "text"
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemAction", false ) )
|
||||||
|
} )
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JMenu", new FormLayoutManager( class javax.swing.JMenu ) ) {
|
||||||
|
name: "menu2"
|
||||||
|
"text": "text"
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "menuItem3"
|
||||||
|
"text": "text"
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemAction", false ) )
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JMenuItem" ) {
|
||||||
|
name: "menuItem4"
|
||||||
|
"text": "text"
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "menuItemAction", false ) )
|
||||||
|
} )
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 10, 570 )
|
||||||
|
} )
|
||||||
|
add( new FormWindow( "javax.swing.JDialog", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "hidemode 3"
|
||||||
|
"$columnConstraints": "[fill][fill]"
|
||||||
|
"$rowConstraints": "[]0[]0[]0[][]para[][198]"
|
||||||
|
} ) {
|
||||||
|
name: "dialog1"
|
||||||
|
"title": "Dummy Modal Dialog"
|
||||||
|
"modalityType": enum java.awt.Dialog$ModalityType APPLICATION_MODAL
|
||||||
|
"defaultCloseOperation": 2
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.className": "DummyModalDialog"
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.WindowListener", "windowOpened", "windowOpened", false ) )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "label1"
|
||||||
|
"text": "Modality type:"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "applicationRadioButton"
|
||||||
|
"text": "Application"
|
||||||
|
"selected": true
|
||||||
|
"$buttonGroup": new FormReference( "modalityTypeButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "modalityTypeChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "documentRadioButton"
|
||||||
|
"text": "Document"
|
||||||
|
"$buttonGroup": new FormReference( "modalityTypeButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "modalityTypeChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "toolkitRadioButton"
|
||||||
|
"text": "Toolkit"
|
||||||
|
"$buttonGroup": new FormReference( "modalityTypeButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "modalityTypeChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "modelessRadioButton"
|
||||||
|
"text": "modeless"
|
||||||
|
"$buttonGroup": new FormReference( "modalityTypeButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "modalityTypeChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "showModalDialogButton"
|
||||||
|
"text": "Show Modal Dialog..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showModalDialog", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4 2 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "showFileDialogButton"
|
||||||
|
"text": "Show File Dialog..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showFileDialog", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 5 2 1"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 20, 635 )
|
||||||
|
"size": new java.awt.Dimension( 290, 465 )
|
||||||
|
} )
|
||||||
|
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||||
|
name: "ownerButtonGroup"
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 475 )
|
||||||
|
} )
|
||||||
|
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||||
|
name: "modalityTypeButtonGroup"
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 115, 575 )
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,622 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2024 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.testing;
|
||||||
|
|
||||||
|
import static com.formdev.flatlaf.ui.FlatNativeWindowsLibrary.*;
|
||||||
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.SecondaryLoop;
|
||||||
|
import java.awt.Toolkit;
|
||||||
|
import java.awt.Window;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.prefs.Preferences;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.border.TitledBorder;
|
||||||
|
import com.formdev.flatlaf.demo.DemoPrefs;
|
||||||
|
import com.formdev.flatlaf.extras.components.*;
|
||||||
|
import com.formdev.flatlaf.extras.components.FlatTriStateCheckBox.State;
|
||||||
|
import com.formdev.flatlaf.testing.FlatSystemFileChooserTest.DummyModalDialog;
|
||||||
|
import com.formdev.flatlaf.ui.FlatNativeWindowsLibrary;
|
||||||
|
import net.miginfocom.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class FlatSystemFileChooserWindowsTest
|
||||||
|
extends FlatTestPanel
|
||||||
|
{
|
||||||
|
public static void main( String[] args ) {
|
||||||
|
SwingUtilities.invokeLater( () -> {
|
||||||
|
if( !FlatNativeWindowsLibrary.isLoaded() ) {
|
||||||
|
JOptionPane.showMessageDialog( null, "FlatLaf native library not loaded" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatTestFrame frame = FlatTestFrame.create( args, "FlatSystemFileChooserWindowsTest" );
|
||||||
|
FlatSystemFileChooserTest.addListeners( frame );
|
||||||
|
frame.showFrame( FlatSystemFileChooserWindowsTest::new );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatSystemFileChooserWindowsTest() {
|
||||||
|
initComponents();
|
||||||
|
|
||||||
|
fileTypesField.setSelectedItem( null );
|
||||||
|
|
||||||
|
Preferences state = DemoPrefs.getState();
|
||||||
|
messageField.setText( state.get( "systemfilechooser.windows.message", "some message" ) );
|
||||||
|
buttonsField.setText( state.get( "systemfilechooser.windows.buttons", "OK" ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void open() {
|
||||||
|
openOrSave( true, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void save() {
|
||||||
|
openOrSave( false, false );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openDirect() {
|
||||||
|
openOrSave( true, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveDirect() {
|
||||||
|
openOrSave( false, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openOrSave( boolean open, boolean direct ) {
|
||||||
|
Window frame = SwingUtilities.windowForComponent( this );
|
||||||
|
if( ownerFrameRadioButton.isSelected() )
|
||||||
|
openOrSave( open, direct, frame );
|
||||||
|
else if( ownerDialogRadioButton.isSelected() )
|
||||||
|
new DummyModalDialog( frame, owner -> openOrSave( open, direct, owner ) ).setVisible( true );
|
||||||
|
else
|
||||||
|
openOrSave( open, direct, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openOrSave( boolean open, boolean direct, Window owner ) {
|
||||||
|
String title = n( titleField.getText() );
|
||||||
|
String okButtonLabel = n( okButtonLabelField.getText() );
|
||||||
|
String fileNameLabel = n( fileNameLabelField.getText() );
|
||||||
|
String fileName = n( fileNameField.getText() );
|
||||||
|
String folder = n( folderField.getText() );
|
||||||
|
String saveAsItem = n( saveAsItemField.getText() );
|
||||||
|
String defaultFolder = n( defaultFolderField.getText() );
|
||||||
|
String defaultExtension = n( defaultExtensionField.getText() );
|
||||||
|
AtomicInteger optionsSet = new AtomicInteger();
|
||||||
|
AtomicInteger optionsClear = new AtomicInteger();
|
||||||
|
|
||||||
|
o( FOS_OVERWRITEPROMPT, overwritePromptCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_STRICTFILETYPES, strictFileTypesCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_NOCHANGEDIR, noChangeDirCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_PICKFOLDERS, pickFoldersCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_FORCEFILESYSTEM, forceFileSystemCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_ALLNONSTORAGEITEMS, allNonStorageItemsCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_NOVALIDATE, noValidateCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_ALLOWMULTISELECT, allowMultiSelectCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_PATHMUSTEXIST, pathMustExistCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_FILEMUSTEXIST, fileMustExistCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_CREATEPROMPT, createPromptCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_SHAREAWARE, shareAwareCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_NOREADONLYRETURN, noReadOnlyReturnCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_NOTESTFILECREATE, noTestFileCreateCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_HIDEMRUPLACES, hideMruPlacesCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_HIDEPINNEDPLACES, hidePinnedPlacesCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_NODEREFERENCELINKS, noDereferenceLinksCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_OKBUTTONNEEDSINTERACTION, okButtonNeedsInteractionCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_DONTADDTORECENT, dontAddToRecentCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_FORCESHOWHIDDEN, forceShowHiddenCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_DEFAULTNOMINIMODE, defaultNoMiniModeCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_FORCEPREVIEWPANEON, forcePreviewPaneonCheckBox, optionsSet, optionsClear );
|
||||||
|
o( FOS_SUPPORTSTREAMABLEITEMS, supportStreamableItemsCheckBox, optionsSet, optionsClear );
|
||||||
|
|
||||||
|
String fileTypesStr = n( (String) fileTypesField.getSelectedItem() );
|
||||||
|
String[] fileTypes = {};
|
||||||
|
if( fileTypesStr != null )
|
||||||
|
fileTypes = fileTypesStr.trim().split( "[,]+" );
|
||||||
|
int fileTypeIndex = fileTypeIndexSlider.getValue();
|
||||||
|
|
||||||
|
FlatNativeWindowsLibrary.FileChooserCallback callback = (files, hwndFileDialog) -> {
|
||||||
|
System.out.println( " -- callback " + hwndFileDialog + " " + Arrays.toString( files ) );
|
||||||
|
if( showMessageDialogOnOKCheckBox.isSelected() ) {
|
||||||
|
System.out.println( FlatNativeWindowsLibrary.showMessageDialog( hwndFileDialog,
|
||||||
|
JOptionPane.INFORMATION_MESSAGE,
|
||||||
|
null, "some text", 1, "Yes", "No" ) );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if( direct ) {
|
||||||
|
String[] files = FlatNativeWindowsLibrary.showFileChooser( owner, open,
|
||||||
|
title, okButtonLabel, fileNameLabel, fileName,
|
||||||
|
folder, saveAsItem, defaultFolder, defaultExtension,
|
||||||
|
optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes );
|
||||||
|
|
||||||
|
filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" );
|
||||||
|
} else {
|
||||||
|
SecondaryLoop secondaryLoop = Toolkit.getDefaultToolkit().getSystemEventQueue().createSecondaryLoop();
|
||||||
|
|
||||||
|
String[] fileTypes2 = fileTypes;
|
||||||
|
new Thread( () -> {
|
||||||
|
String[] files = FlatNativeWindowsLibrary.showFileChooser( owner, open,
|
||||||
|
title, okButtonLabel, fileNameLabel, fileName,
|
||||||
|
folder, saveAsItem, defaultFolder, defaultExtension,
|
||||||
|
optionsSet.get(), optionsClear.get(), callback, fileTypeIndex, fileTypes2 );
|
||||||
|
|
||||||
|
System.out.println( " secondaryLoop.exit() returned " + secondaryLoop.exit() );
|
||||||
|
|
||||||
|
EventQueue.invokeLater( () -> {
|
||||||
|
filesField.setText( (files != null) ? Arrays.toString( files ).replace( ',', '\n' ) : "null" );
|
||||||
|
} );
|
||||||
|
} ).start();
|
||||||
|
|
||||||
|
System.out.println( "---- enter secondary loop ----" );
|
||||||
|
System.out.println( "---- secondary loop exited (secondaryLoop.enter() returned " + secondaryLoop.enter() + ") ----" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String n( String s ) {
|
||||||
|
return s != null && !s.isEmpty() ? s : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void o( int option, FlatTriStateCheckBox checkBox, AtomicInteger optionsSet, AtomicInteger optionsClear ) {
|
||||||
|
if( checkBox.getState() == State.SELECTED )
|
||||||
|
optionsSet.set( optionsSet.get() | option );
|
||||||
|
else if( checkBox.getState() == State.UNSELECTED )
|
||||||
|
optionsClear.set( optionsClear.get() | option );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void messageDialog() {
|
||||||
|
long hwnd = getHWND( SwingUtilities.windowForComponent( this ) );
|
||||||
|
String message = messageField.getText();
|
||||||
|
String[] buttons = buttonsField.getText().trim().split( "[,]+" );
|
||||||
|
|
||||||
|
Preferences state = DemoPrefs.getState();
|
||||||
|
state.put( "systemfilechooser.windows.message", message );
|
||||||
|
state.put( "systemfilechooser.windows.buttons", buttonsField.getText() );
|
||||||
|
|
||||||
|
System.out.println( FlatNativeWindowsLibrary.showMessageDialog( hwnd,
|
||||||
|
JOptionPane.WARNING_MESSAGE, null, message, 1, buttons ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void messageBox() {
|
||||||
|
long hwnd = getHWND( SwingUtilities.windowForComponent( this ) );
|
||||||
|
String message = messageField.getText();
|
||||||
|
|
||||||
|
System.out.println( FlatNativeWindowsLibrary.showMessageBox( hwnd, message, null,
|
||||||
|
/* MB_ICONINFORMATION */ 0x00000040 | /* MB_YESNO */ 0x00000004 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initComponents() {
|
||||||
|
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||||
|
JLabel ownerLabel = new JLabel();
|
||||||
|
ownerFrameRadioButton = new JRadioButton();
|
||||||
|
ownerDialogRadioButton = new JRadioButton();
|
||||||
|
ownerNullRadioButton = new JRadioButton();
|
||||||
|
JPanel ownerSpacer = new JPanel(null);
|
||||||
|
JLabel titleLabel = new JLabel();
|
||||||
|
titleField = new JTextField();
|
||||||
|
JPanel panel1 = new JPanel();
|
||||||
|
overwritePromptCheckBox = new FlatTriStateCheckBox();
|
||||||
|
pathMustExistCheckBox = new FlatTriStateCheckBox();
|
||||||
|
noDereferenceLinksCheckBox = new FlatTriStateCheckBox();
|
||||||
|
strictFileTypesCheckBox = new FlatTriStateCheckBox();
|
||||||
|
fileMustExistCheckBox = new FlatTriStateCheckBox();
|
||||||
|
okButtonNeedsInteractionCheckBox = new FlatTriStateCheckBox();
|
||||||
|
noChangeDirCheckBox = new FlatTriStateCheckBox();
|
||||||
|
createPromptCheckBox = new FlatTriStateCheckBox();
|
||||||
|
dontAddToRecentCheckBox = new FlatTriStateCheckBox();
|
||||||
|
pickFoldersCheckBox = new FlatTriStateCheckBox();
|
||||||
|
shareAwareCheckBox = new FlatTriStateCheckBox();
|
||||||
|
forceShowHiddenCheckBox = new FlatTriStateCheckBox();
|
||||||
|
forceFileSystemCheckBox = new FlatTriStateCheckBox();
|
||||||
|
noReadOnlyReturnCheckBox = new FlatTriStateCheckBox();
|
||||||
|
defaultNoMiniModeCheckBox = new FlatTriStateCheckBox();
|
||||||
|
allNonStorageItemsCheckBox = new FlatTriStateCheckBox();
|
||||||
|
noTestFileCreateCheckBox = new FlatTriStateCheckBox();
|
||||||
|
forcePreviewPaneonCheckBox = new FlatTriStateCheckBox();
|
||||||
|
noValidateCheckBox = new FlatTriStateCheckBox();
|
||||||
|
hideMruPlacesCheckBox = new FlatTriStateCheckBox();
|
||||||
|
supportStreamableItemsCheckBox = new FlatTriStateCheckBox();
|
||||||
|
allowMultiSelectCheckBox = new FlatTriStateCheckBox();
|
||||||
|
hidePinnedPlacesCheckBox = new FlatTriStateCheckBox();
|
||||||
|
JPanel messageDialogPanel = new JPanel();
|
||||||
|
JLabel messageLabel = new JLabel();
|
||||||
|
JScrollPane messageScrollPane = new JScrollPane();
|
||||||
|
messageField = new JTextArea();
|
||||||
|
JLabel buttonsLabel = new JLabel();
|
||||||
|
buttonsField = new JTextField();
|
||||||
|
JLabel okButtonLabelLabel = new JLabel();
|
||||||
|
okButtonLabelField = new JTextField();
|
||||||
|
JLabel fileNameLabelLabel = new JLabel();
|
||||||
|
fileNameLabelField = new JTextField();
|
||||||
|
JLabel fileNameLabel = new JLabel();
|
||||||
|
fileNameField = new JTextField();
|
||||||
|
JLabel folderLabel = new JLabel();
|
||||||
|
folderField = new JTextField();
|
||||||
|
JLabel saveAsItemLabel = new JLabel();
|
||||||
|
saveAsItemField = new JTextField();
|
||||||
|
JLabel defaultFolderLabel = new JLabel();
|
||||||
|
defaultFolderField = new JTextField();
|
||||||
|
JLabel defaultExtensionLabel = new JLabel();
|
||||||
|
defaultExtensionField = new JTextField();
|
||||||
|
JLabel fileTypesLabel = new JLabel();
|
||||||
|
fileTypesField = new JComboBox<>();
|
||||||
|
JLabel fileTypeIndexLabel = new JLabel();
|
||||||
|
fileTypeIndexSlider = new JSlider();
|
||||||
|
JButton openButton = new JButton();
|
||||||
|
JButton saveButton = new JButton();
|
||||||
|
JButton openDirectButton = new JButton();
|
||||||
|
JButton saveDirectButton = new JButton();
|
||||||
|
showMessageDialogOnOKCheckBox = new JCheckBox();
|
||||||
|
JPanel hSpacer1 = new JPanel(null);
|
||||||
|
JButton messageDialogButton = new JButton();
|
||||||
|
JButton messageBoxButton = new JButton();
|
||||||
|
JScrollPane filesScrollPane = new JScrollPane();
|
||||||
|
filesField = new JTextArea();
|
||||||
|
|
||||||
|
//======== this ========
|
||||||
|
setLayout(new MigLayout(
|
||||||
|
"ltr,insets dialog,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[left]" +
|
||||||
|
"[grow,fill]" +
|
||||||
|
"[fill]",
|
||||||
|
// rows
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[]" +
|
||||||
|
"[grow,fill]"));
|
||||||
|
|
||||||
|
//---- ownerLabel ----
|
||||||
|
ownerLabel.setText("owner");
|
||||||
|
add(ownerLabel, "cell 0 0");
|
||||||
|
|
||||||
|
//---- ownerFrameRadioButton ----
|
||||||
|
ownerFrameRadioButton.setText("JFrame");
|
||||||
|
ownerFrameRadioButton.setSelected(true);
|
||||||
|
add(ownerFrameRadioButton, "cell 1 0");
|
||||||
|
|
||||||
|
//---- ownerDialogRadioButton ----
|
||||||
|
ownerDialogRadioButton.setText("JDialog");
|
||||||
|
add(ownerDialogRadioButton, "cell 1 0");
|
||||||
|
|
||||||
|
//---- ownerNullRadioButton ----
|
||||||
|
ownerNullRadioButton.setText("null");
|
||||||
|
add(ownerNullRadioButton, "cell 1 0");
|
||||||
|
add(ownerSpacer, "cell 1 0,growx");
|
||||||
|
|
||||||
|
//---- titleLabel ----
|
||||||
|
titleLabel.setText("title");
|
||||||
|
add(titleLabel, "cell 0 1");
|
||||||
|
add(titleField, "cell 1 1");
|
||||||
|
|
||||||
|
//======== panel1 ========
|
||||||
|
{
|
||||||
|
panel1.setLayout(new MigLayout(
|
||||||
|
"insets 2,hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[left]para" +
|
||||||
|
"[left]para" +
|
||||||
|
"[left]",
|
||||||
|
// rows
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[]0" +
|
||||||
|
"[grow]"));
|
||||||
|
|
||||||
|
//---- overwritePromptCheckBox ----
|
||||||
|
overwritePromptCheckBox.setText("overwritePrompt");
|
||||||
|
panel1.add(overwritePromptCheckBox, "cell 0 0");
|
||||||
|
|
||||||
|
//---- pathMustExistCheckBox ----
|
||||||
|
pathMustExistCheckBox.setText("pathMustExist");
|
||||||
|
panel1.add(pathMustExistCheckBox, "cell 1 0");
|
||||||
|
|
||||||
|
//---- noDereferenceLinksCheckBox ----
|
||||||
|
noDereferenceLinksCheckBox.setText("noDereferenceLinks");
|
||||||
|
panel1.add(noDereferenceLinksCheckBox, "cell 2 0");
|
||||||
|
|
||||||
|
//---- strictFileTypesCheckBox ----
|
||||||
|
strictFileTypesCheckBox.setText("strictFileTypes");
|
||||||
|
panel1.add(strictFileTypesCheckBox, "cell 0 1");
|
||||||
|
|
||||||
|
//---- fileMustExistCheckBox ----
|
||||||
|
fileMustExistCheckBox.setText("fileMustExist");
|
||||||
|
panel1.add(fileMustExistCheckBox, "cell 1 1");
|
||||||
|
|
||||||
|
//---- okButtonNeedsInteractionCheckBox ----
|
||||||
|
okButtonNeedsInteractionCheckBox.setText("okButtonNeedsInteraction");
|
||||||
|
panel1.add(okButtonNeedsInteractionCheckBox, "cell 2 1");
|
||||||
|
|
||||||
|
//---- noChangeDirCheckBox ----
|
||||||
|
noChangeDirCheckBox.setText("noChangeDir");
|
||||||
|
panel1.add(noChangeDirCheckBox, "cell 0 2");
|
||||||
|
|
||||||
|
//---- createPromptCheckBox ----
|
||||||
|
createPromptCheckBox.setText("createPrompt");
|
||||||
|
panel1.add(createPromptCheckBox, "cell 1 2");
|
||||||
|
|
||||||
|
//---- dontAddToRecentCheckBox ----
|
||||||
|
dontAddToRecentCheckBox.setText("dontAddToRecent");
|
||||||
|
panel1.add(dontAddToRecentCheckBox, "cell 2 2");
|
||||||
|
|
||||||
|
//---- pickFoldersCheckBox ----
|
||||||
|
pickFoldersCheckBox.setText("pickFolders");
|
||||||
|
pickFoldersCheckBox.setFont(pickFoldersCheckBox.getFont().deriveFont(pickFoldersCheckBox.getFont().getStyle() | Font.BOLD));
|
||||||
|
panel1.add(pickFoldersCheckBox, "cell 0 3");
|
||||||
|
|
||||||
|
//---- shareAwareCheckBox ----
|
||||||
|
shareAwareCheckBox.setText("shareAware");
|
||||||
|
panel1.add(shareAwareCheckBox, "cell 1 3");
|
||||||
|
|
||||||
|
//---- forceShowHiddenCheckBox ----
|
||||||
|
forceShowHiddenCheckBox.setText("forceShowHidden");
|
||||||
|
forceShowHiddenCheckBox.setFont(forceShowHiddenCheckBox.getFont().deriveFont(forceShowHiddenCheckBox.getFont().getStyle() | Font.BOLD));
|
||||||
|
panel1.add(forceShowHiddenCheckBox, "cell 2 3");
|
||||||
|
|
||||||
|
//---- forceFileSystemCheckBox ----
|
||||||
|
forceFileSystemCheckBox.setText("forceFileSystem");
|
||||||
|
panel1.add(forceFileSystemCheckBox, "cell 0 4");
|
||||||
|
|
||||||
|
//---- noReadOnlyReturnCheckBox ----
|
||||||
|
noReadOnlyReturnCheckBox.setText("noReadOnlyReturn");
|
||||||
|
panel1.add(noReadOnlyReturnCheckBox, "cell 1 4");
|
||||||
|
|
||||||
|
//---- defaultNoMiniModeCheckBox ----
|
||||||
|
defaultNoMiniModeCheckBox.setText("defaultNoMiniMode");
|
||||||
|
panel1.add(defaultNoMiniModeCheckBox, "cell 2 4");
|
||||||
|
|
||||||
|
//---- allNonStorageItemsCheckBox ----
|
||||||
|
allNonStorageItemsCheckBox.setText("allNonStorageItems");
|
||||||
|
panel1.add(allNonStorageItemsCheckBox, "cell 0 5");
|
||||||
|
|
||||||
|
//---- noTestFileCreateCheckBox ----
|
||||||
|
noTestFileCreateCheckBox.setText("noTestFileCreate");
|
||||||
|
panel1.add(noTestFileCreateCheckBox, "cell 1 5");
|
||||||
|
|
||||||
|
//---- forcePreviewPaneonCheckBox ----
|
||||||
|
forcePreviewPaneonCheckBox.setText("forcePreviewPaneon");
|
||||||
|
panel1.add(forcePreviewPaneonCheckBox, "cell 2 5");
|
||||||
|
|
||||||
|
//---- noValidateCheckBox ----
|
||||||
|
noValidateCheckBox.setText("noValidate");
|
||||||
|
panel1.add(noValidateCheckBox, "cell 0 6");
|
||||||
|
|
||||||
|
//---- hideMruPlacesCheckBox ----
|
||||||
|
hideMruPlacesCheckBox.setText("hideMruPlaces");
|
||||||
|
panel1.add(hideMruPlacesCheckBox, "cell 1 6");
|
||||||
|
|
||||||
|
//---- supportStreamableItemsCheckBox ----
|
||||||
|
supportStreamableItemsCheckBox.setText("supportStreamableItems");
|
||||||
|
panel1.add(supportStreamableItemsCheckBox, "cell 2 6");
|
||||||
|
|
||||||
|
//---- allowMultiSelectCheckBox ----
|
||||||
|
allowMultiSelectCheckBox.setText("allowMultiSelect");
|
||||||
|
allowMultiSelectCheckBox.setFont(allowMultiSelectCheckBox.getFont().deriveFont(allowMultiSelectCheckBox.getFont().getStyle() | Font.BOLD));
|
||||||
|
panel1.add(allowMultiSelectCheckBox, "cell 0 7");
|
||||||
|
|
||||||
|
//---- hidePinnedPlacesCheckBox ----
|
||||||
|
hidePinnedPlacesCheckBox.setText("hidePinnedPlaces");
|
||||||
|
panel1.add(hidePinnedPlacesCheckBox, "cell 1 7");
|
||||||
|
|
||||||
|
//======== messageDialogPanel ========
|
||||||
|
{
|
||||||
|
messageDialogPanel.setBorder(new TitledBorder("MessageDialog"));
|
||||||
|
messageDialogPanel.setLayout(new MigLayout(
|
||||||
|
"hidemode 3",
|
||||||
|
// columns
|
||||||
|
"[fill]" +
|
||||||
|
"[grow,fill]",
|
||||||
|
// rows
|
||||||
|
"[grow,fill]" +
|
||||||
|
"[]"));
|
||||||
|
|
||||||
|
//---- messageLabel ----
|
||||||
|
messageLabel.setText("Message");
|
||||||
|
messageDialogPanel.add(messageLabel, "cell 0 0,aligny top,growy 0");
|
||||||
|
|
||||||
|
//======== messageScrollPane ========
|
||||||
|
{
|
||||||
|
|
||||||
|
//---- messageField ----
|
||||||
|
messageField.setColumns(40);
|
||||||
|
messageField.setRows(4);
|
||||||
|
messageScrollPane.setViewportView(messageField);
|
||||||
|
}
|
||||||
|
messageDialogPanel.add(messageScrollPane, "cell 1 0");
|
||||||
|
|
||||||
|
//---- buttonsLabel ----
|
||||||
|
buttonsLabel.setText("Buttons:");
|
||||||
|
messageDialogPanel.add(buttonsLabel, "cell 0 1");
|
||||||
|
messageDialogPanel.add(buttonsField, "cell 1 1");
|
||||||
|
}
|
||||||
|
panel1.add(messageDialogPanel, "cell 0 8 3 1,grow");
|
||||||
|
}
|
||||||
|
add(panel1, "cell 2 1 1 10,growy");
|
||||||
|
|
||||||
|
//---- okButtonLabelLabel ----
|
||||||
|
okButtonLabelLabel.setText("okButtonLabel");
|
||||||
|
add(okButtonLabelLabel, "cell 0 2");
|
||||||
|
add(okButtonLabelField, "cell 1 2");
|
||||||
|
|
||||||
|
//---- fileNameLabelLabel ----
|
||||||
|
fileNameLabelLabel.setText("fileNameLabel");
|
||||||
|
add(fileNameLabelLabel, "cell 0 3");
|
||||||
|
add(fileNameLabelField, "cell 1 3");
|
||||||
|
|
||||||
|
//---- fileNameLabel ----
|
||||||
|
fileNameLabel.setText("fileName");
|
||||||
|
add(fileNameLabel, "cell 0 4");
|
||||||
|
add(fileNameField, "cell 1 4");
|
||||||
|
|
||||||
|
//---- folderLabel ----
|
||||||
|
folderLabel.setText("folder");
|
||||||
|
add(folderLabel, "cell 0 5");
|
||||||
|
add(folderField, "cell 1 5");
|
||||||
|
|
||||||
|
//---- saveAsItemLabel ----
|
||||||
|
saveAsItemLabel.setText("saveAsItem");
|
||||||
|
add(saveAsItemLabel, "cell 0 6");
|
||||||
|
add(saveAsItemField, "cell 1 6");
|
||||||
|
|
||||||
|
//---- defaultFolderLabel ----
|
||||||
|
defaultFolderLabel.setText("defaultFolder");
|
||||||
|
add(defaultFolderLabel, "cell 0 7");
|
||||||
|
add(defaultFolderField, "cell 1 7");
|
||||||
|
|
||||||
|
//---- defaultExtensionLabel ----
|
||||||
|
defaultExtensionLabel.setText("defaultExtension");
|
||||||
|
add(defaultExtensionLabel, "cell 0 8");
|
||||||
|
add(defaultExtensionField, "cell 1 8");
|
||||||
|
|
||||||
|
//---- fileTypesLabel ----
|
||||||
|
fileTypesLabel.setText("fileTypes");
|
||||||
|
add(fileTypesLabel, "cell 0 9");
|
||||||
|
|
||||||
|
//---- fileTypesField ----
|
||||||
|
fileTypesField.setEditable(true);
|
||||||
|
fileTypesField.setModel(new DefaultComboBoxModel<>(new String[] {
|
||||||
|
"Text Files,*.txt",
|
||||||
|
"All Files,*.*",
|
||||||
|
"Text Files,*.txt,PDF Files,*.pdf,All Files,*.*",
|
||||||
|
"Text and PDF Files,*.txt;*.pdf"
|
||||||
|
}));
|
||||||
|
add(fileTypesField, "cell 1 9");
|
||||||
|
|
||||||
|
//---- fileTypeIndexLabel ----
|
||||||
|
fileTypeIndexLabel.setText("fileTypeIndex");
|
||||||
|
add(fileTypeIndexLabel, "cell 0 10");
|
||||||
|
|
||||||
|
//---- fileTypeIndexSlider ----
|
||||||
|
fileTypeIndexSlider.setMaximum(10);
|
||||||
|
fileTypeIndexSlider.setMajorTickSpacing(1);
|
||||||
|
fileTypeIndexSlider.setValue(0);
|
||||||
|
fileTypeIndexSlider.setPaintLabels(true);
|
||||||
|
fileTypeIndexSlider.setSnapToTicks(true);
|
||||||
|
add(fileTypeIndexSlider, "cell 1 10");
|
||||||
|
|
||||||
|
//---- openButton ----
|
||||||
|
openButton.setText("Open...");
|
||||||
|
openButton.addActionListener(e -> open());
|
||||||
|
add(openButton, "cell 0 11 3 1");
|
||||||
|
|
||||||
|
//---- saveButton ----
|
||||||
|
saveButton.setText("Save...");
|
||||||
|
saveButton.addActionListener(e -> save());
|
||||||
|
add(saveButton, "cell 0 11 3 1");
|
||||||
|
|
||||||
|
//---- openDirectButton ----
|
||||||
|
openDirectButton.setText("Open (no-thread)...");
|
||||||
|
openDirectButton.addActionListener(e -> openDirect());
|
||||||
|
add(openDirectButton, "cell 0 11 3 1");
|
||||||
|
|
||||||
|
//---- saveDirectButton ----
|
||||||
|
saveDirectButton.setText("Save (no-thread)...");
|
||||||
|
saveDirectButton.addActionListener(e -> saveDirect());
|
||||||
|
add(saveDirectButton, "cell 0 11 3 1");
|
||||||
|
|
||||||
|
//---- showMessageDialogOnOKCheckBox ----
|
||||||
|
showMessageDialogOnOKCheckBox.setText("show message dialog on OK");
|
||||||
|
add(showMessageDialogOnOKCheckBox, "cell 0 11 3 1");
|
||||||
|
add(hSpacer1, "cell 0 11 3 1,growx");
|
||||||
|
|
||||||
|
//---- messageDialogButton ----
|
||||||
|
messageDialogButton.setText("MessageDialog...");
|
||||||
|
messageDialogButton.addActionListener(e -> messageDialog());
|
||||||
|
add(messageDialogButton, "cell 0 11 3 1,alignx right,growx 0");
|
||||||
|
|
||||||
|
//---- messageBoxButton ----
|
||||||
|
messageBoxButton.setText("MessageBox...");
|
||||||
|
messageBoxButton.addActionListener(e -> messageBox());
|
||||||
|
add(messageBoxButton, "cell 0 11 3 1");
|
||||||
|
|
||||||
|
//======== filesScrollPane ========
|
||||||
|
{
|
||||||
|
|
||||||
|
//---- filesField ----
|
||||||
|
filesField.setRows(8);
|
||||||
|
filesScrollPane.setViewportView(filesField);
|
||||||
|
}
|
||||||
|
add(filesScrollPane, "cell 0 12 3 1,growx");
|
||||||
|
|
||||||
|
//---- ownerButtonGroup ----
|
||||||
|
ButtonGroup ownerButtonGroup = new ButtonGroup();
|
||||||
|
ownerButtonGroup.add(ownerFrameRadioButton);
|
||||||
|
ownerButtonGroup.add(ownerDialogRadioButton);
|
||||||
|
ownerButtonGroup.add(ownerNullRadioButton);
|
||||||
|
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||||
|
}
|
||||||
|
|
||||||
|
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||||
|
private JRadioButton ownerFrameRadioButton;
|
||||||
|
private JRadioButton ownerDialogRadioButton;
|
||||||
|
private JRadioButton ownerNullRadioButton;
|
||||||
|
private JTextField titleField;
|
||||||
|
private FlatTriStateCheckBox overwritePromptCheckBox;
|
||||||
|
private FlatTriStateCheckBox pathMustExistCheckBox;
|
||||||
|
private FlatTriStateCheckBox noDereferenceLinksCheckBox;
|
||||||
|
private FlatTriStateCheckBox strictFileTypesCheckBox;
|
||||||
|
private FlatTriStateCheckBox fileMustExistCheckBox;
|
||||||
|
private FlatTriStateCheckBox okButtonNeedsInteractionCheckBox;
|
||||||
|
private FlatTriStateCheckBox noChangeDirCheckBox;
|
||||||
|
private FlatTriStateCheckBox createPromptCheckBox;
|
||||||
|
private FlatTriStateCheckBox dontAddToRecentCheckBox;
|
||||||
|
private FlatTriStateCheckBox pickFoldersCheckBox;
|
||||||
|
private FlatTriStateCheckBox shareAwareCheckBox;
|
||||||
|
private FlatTriStateCheckBox forceShowHiddenCheckBox;
|
||||||
|
private FlatTriStateCheckBox forceFileSystemCheckBox;
|
||||||
|
private FlatTriStateCheckBox noReadOnlyReturnCheckBox;
|
||||||
|
private FlatTriStateCheckBox defaultNoMiniModeCheckBox;
|
||||||
|
private FlatTriStateCheckBox allNonStorageItemsCheckBox;
|
||||||
|
private FlatTriStateCheckBox noTestFileCreateCheckBox;
|
||||||
|
private FlatTriStateCheckBox forcePreviewPaneonCheckBox;
|
||||||
|
private FlatTriStateCheckBox noValidateCheckBox;
|
||||||
|
private FlatTriStateCheckBox hideMruPlacesCheckBox;
|
||||||
|
private FlatTriStateCheckBox supportStreamableItemsCheckBox;
|
||||||
|
private FlatTriStateCheckBox allowMultiSelectCheckBox;
|
||||||
|
private FlatTriStateCheckBox hidePinnedPlacesCheckBox;
|
||||||
|
private JTextArea messageField;
|
||||||
|
private JTextField buttonsField;
|
||||||
|
private JTextField okButtonLabelField;
|
||||||
|
private JTextField fileNameLabelField;
|
||||||
|
private JTextField fileNameField;
|
||||||
|
private JTextField folderField;
|
||||||
|
private JTextField saveAsItemField;
|
||||||
|
private JTextField defaultFolderField;
|
||||||
|
private JTextField defaultExtensionField;
|
||||||
|
private JComboBox<String> fileTypesField;
|
||||||
|
private JSlider fileTypeIndexSlider;
|
||||||
|
private JCheckBox showMessageDialogOnOKCheckBox;
|
||||||
|
private JTextArea filesField;
|
||||||
|
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||||
|
}
|
||||||
@@ -0,0 +1,550 @@
|
|||||||
|
JFDML JFormDesigner: "8.3" encoding: "UTF-8"
|
||||||
|
|
||||||
|
new FormModel {
|
||||||
|
contentType: "form/swing"
|
||||||
|
root: new FormRoot {
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.defaultVariableLocal": true
|
||||||
|
}
|
||||||
|
add( new FormContainer( "com.formdev.flatlaf.testing.FlatTestPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "ltr,insets dialog,hidemode 3"
|
||||||
|
"$columnConstraints": "[left][grow,fill][fill]"
|
||||||
|
"$rowConstraints": "[][][][][][][][][][][][][grow,fill]"
|
||||||
|
} ) {
|
||||||
|
name: "this"
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "ownerLabel"
|
||||||
|
"text": "owner"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerFrameRadioButton"
|
||||||
|
"text": "JFrame"
|
||||||
|
"selected": true
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerDialogRadioButton"
|
||||||
|
"text": "JDialog"
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JRadioButton" ) {
|
||||||
|
name: "ownerNullRadioButton"
|
||||||
|
"text": "null"
|
||||||
|
"$buttonGroup": new FormReference( "ownerButtonGroup" )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
|
||||||
|
name: "ownerSpacer"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0,growx"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "titleLabel"
|
||||||
|
"text": "title"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "titleField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 1"
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "insets 2,hidemode 3"
|
||||||
|
"$columnConstraints": "[left]para[left]para[left]"
|
||||||
|
"$rowConstraints": "[]0[]0[]0[][]0[]0[]0[]0[grow]"
|
||||||
|
} ) {
|
||||||
|
name: "panel1"
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "overwritePromptCheckBox"
|
||||||
|
"text": "overwritePrompt"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "pathMustExistCheckBox"
|
||||||
|
"text": "pathMustExist"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "noDereferenceLinksCheckBox"
|
||||||
|
"text": "noDereferenceLinks"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "strictFileTypesCheckBox"
|
||||||
|
"text": "strictFileTypes"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "fileMustExistCheckBox"
|
||||||
|
"text": "fileMustExist"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "okButtonNeedsInteractionCheckBox"
|
||||||
|
"text": "okButtonNeedsInteraction"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "noChangeDirCheckBox"
|
||||||
|
"text": "noChangeDir"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "createPromptCheckBox"
|
||||||
|
"text": "createPrompt"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "dontAddToRecentCheckBox"
|
||||||
|
"text": "dontAddToRecent"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "pickFoldersCheckBox"
|
||||||
|
"text": "pickFolders"
|
||||||
|
"font": new com.jformdesigner.model.SwingDerivedFont( null, 1, 0, false )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "shareAwareCheckBox"
|
||||||
|
"text": "shareAware"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "forceShowHiddenCheckBox"
|
||||||
|
"text": "forceShowHidden"
|
||||||
|
"font": new com.jformdesigner.model.SwingDerivedFont( null, 1, 0, false )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "forceFileSystemCheckBox"
|
||||||
|
"text": "forceFileSystem"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "noReadOnlyReturnCheckBox"
|
||||||
|
"text": "noReadOnlyReturn"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "defaultNoMiniModeCheckBox"
|
||||||
|
"text": "defaultNoMiniMode"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "allNonStorageItemsCheckBox"
|
||||||
|
"text": "allNonStorageItems"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "noTestFileCreateCheckBox"
|
||||||
|
"text": "noTestFileCreate"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "forcePreviewPaneonCheckBox"
|
||||||
|
"text": "forcePreviewPaneon"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "noValidateCheckBox"
|
||||||
|
"text": "noValidate"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "hideMruPlacesCheckBox"
|
||||||
|
"text": "hideMruPlaces"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "supportStreamableItemsCheckBox"
|
||||||
|
"text": "supportStreamableItems"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "allowMultiSelectCheckBox"
|
||||||
|
"text": "allowMultiSelect"
|
||||||
|
"font": new com.jformdesigner.model.SwingDerivedFont( null, 1, 0, false )
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTriStateCheckBox" ) {
|
||||||
|
name: "hidePinnedPlacesCheckBox"
|
||||||
|
"text": "hidePinnedPlaces"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 7"
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
|
"$layoutConstraints": "hidemode 3"
|
||||||
|
"$columnConstraints": "[fill][grow,fill]"
|
||||||
|
"$rowConstraints": "[grow,fill][]"
|
||||||
|
} ) {
|
||||||
|
name: "messageDialogPanel"
|
||||||
|
"border": new javax.swing.border.TitledBorder( "MessageDialog" )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "messageLabel"
|
||||||
|
"text": "Message"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 0,aligny top,growy 0"
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||||
|
name: "messageScrollPane"
|
||||||
|
add( new FormComponent( "javax.swing.JTextArea" ) {
|
||||||
|
name: "messageField"
|
||||||
|
"columns": 40
|
||||||
|
"rows": 4
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "buttonsLabel"
|
||||||
|
"text": "Buttons:"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "buttonsField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 1"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8 3 1,grow"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 1 1 10,growy"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "okButtonLabelLabel"
|
||||||
|
"text": "okButtonLabel"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "okButtonLabelField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 2"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "fileNameLabelLabel"
|
||||||
|
"text": "fileNameLabel"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "fileNameLabelField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "fileNameLabel"
|
||||||
|
"text": "fileName"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "fileNameField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "folderLabel"
|
||||||
|
"text": "folder"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "folderField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 5"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "saveAsItemLabel"
|
||||||
|
"text": "saveAsItem"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "saveAsItemField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 6"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "defaultFolderLabel"
|
||||||
|
"text": "defaultFolder"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 7"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "defaultFolderField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 7"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "defaultExtensionLabel"
|
||||||
|
"text": "defaultExtension"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 8"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||||
|
name: "defaultExtensionField"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 8"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "fileTypesLabel"
|
||||||
|
"text": "fileTypes"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 9"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JComboBox" ) {
|
||||||
|
name: "fileTypesField"
|
||||||
|
"editable": true
|
||||||
|
"model": new javax.swing.DefaultComboBoxModel {
|
||||||
|
selectedItem: "Text Files,*.txt"
|
||||||
|
addElement( "Text Files,*.txt" )
|
||||||
|
addElement( "All Files,*.*" )
|
||||||
|
addElement( "Text Files,*.txt,PDF Files,*.pdf,All Files,*.*" )
|
||||||
|
addElement( "Text and PDF Files,*.txt;*.pdf" )
|
||||||
|
}
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 9"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||||
|
name: "fileTypeIndexLabel"
|
||||||
|
"text": "fileTypeIndex"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 10"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JSlider" ) {
|
||||||
|
name: "fileTypeIndexSlider"
|
||||||
|
"maximum": 10
|
||||||
|
"majorTickSpacing": 1
|
||||||
|
"value": 0
|
||||||
|
"paintLabels": true
|
||||||
|
"snapToTicks": true
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 1 10"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "openButton"
|
||||||
|
"text": "Open..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "open", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "saveButton"
|
||||||
|
"text": "Save..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "save", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "openDirectButton"
|
||||||
|
"text": "Open (no-thread)..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "openDirect", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "saveDirectButton"
|
||||||
|
"text": "Save (no-thread)..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "saveDirect", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "showMessageDialogOnOKCheckBox"
|
||||||
|
"text": "show message dialog on OK"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.jformdesigner.designer.wrapper.HSpacer" ) {
|
||||||
|
name: "hSpacer1"
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1,growx"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "messageDialogButton"
|
||||||
|
"text": "MessageDialog..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "messageDialog", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1,alignx right,growx 0"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JButton" ) {
|
||||||
|
name: "messageBoxButton"
|
||||||
|
"text": "MessageBox..."
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "messageBox", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 11 3 1"
|
||||||
|
} )
|
||||||
|
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
|
||||||
|
name: "filesScrollPane"
|
||||||
|
add( new FormComponent( "javax.swing.JTextArea" ) {
|
||||||
|
name: "filesField"
|
||||||
|
"rows": 8
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 12 3 1,growx"
|
||||||
|
} )
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 0 )
|
||||||
|
"size": new java.awt.Dimension( 890, 630 )
|
||||||
|
} )
|
||||||
|
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||||
|
name: "ownerButtonGroup"
|
||||||
|
}, new FormLayoutConstraints( null ) {
|
||||||
|
"location": new java.awt.Point( 0, 640 )
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -245,6 +245,9 @@ public class FlatTestFrame
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
|
|
||||||
FlatUIDefaultsInspector.hide();
|
FlatUIDefaultsInspector.hide();
|
||||||
|
|
||||||
|
if( getDefaultCloseOperation() == JFrame.EXIT_ON_CLOSE )
|
||||||
|
System.exit( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTitle() {
|
private void updateTitle() {
|
||||||
|
|||||||
@@ -74,6 +74,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;
|
||||||
|
|
||||||
@@ -97,6 +98,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;
|
||||||
@@ -228,48 +231,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 =
|
||||||
@@ -281,18 +281,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() {
|
||||||
@@ -303,7 +322,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
|
||||||
@@ -391,6 +418,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() );
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ fifesoft-autocomplete = "com.fifesoft:autocomplete:3.3.1"
|
|||||||
# flatlaf-testing
|
# flatlaf-testing
|
||||||
glazedlists = "com.glazedlists:glazedlists:1.11.0"
|
glazedlists = "com.glazedlists:glazedlists:1.11.0"
|
||||||
netbeans-api-awt = "org.netbeans.api:org-openide-awt:RELEASE112"
|
netbeans-api-awt = "org.netbeans.api:org-openide-awt:RELEASE112"
|
||||||
|
nativejfilechooser = "li.flor:native-j-file-chooser:1.6.4"
|
||||||
|
|
||||||
# flatlaf-natives-jna
|
# flatlaf-natives-jna
|
||||||
jna = "net.java.dev.jna:jna:5.15.0"
|
jna = "net.java.dev.jna:jna:5.15.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user