Compare commits
131 Commits
styling-ty
...
2.0-rc1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efd8cf8236 | ||
|
|
8dbfc6d5d6 | ||
|
|
ef343397d4 | ||
|
|
cae02d31db | ||
|
|
96c78cbc16 | ||
|
|
f8c769644d | ||
|
|
0bd1e413b0 | ||
|
|
07c9ad484a | ||
|
|
5fd5b1206e | ||
|
|
8e107647bd | ||
|
|
12b7389376 | ||
|
|
45332c8126 | ||
|
|
02a9d4e31d | ||
|
|
a4377e81cb | ||
|
|
8d2ed3faf6 | ||
|
|
e7dacb8fef | ||
|
|
60e2ffac5f | ||
|
|
73c37b2018 | ||
|
|
1b3cc223da | ||
|
|
51be7ad832 | ||
|
|
f93d035e4e | ||
|
|
a3885d7a48 | ||
|
|
bbf2331766 | ||
|
|
2164bd363b | ||
|
|
6205e18c45 | ||
|
|
959b3e46fa | ||
|
|
09d8d09aad | ||
|
|
70336e31c7 | ||
|
|
600e0f3d67 | ||
|
|
023e356057 | ||
|
|
27786ec00a | ||
|
|
e52e72c5a8 | ||
|
|
802dd08ce7 | ||
|
|
568ec5a1a2 | ||
|
|
035d196392 | ||
|
|
dd3ffc64b9 | ||
|
|
c9a38f0a13 | ||
|
|
78461a9d5a | ||
|
|
79b8fb910a | ||
|
|
405e3df1f0 | ||
|
|
f7126d154f | ||
|
|
d8df8c9631 | ||
|
|
37b35f9063 | ||
|
|
f61a7288eb | ||
|
|
47a1122f04 | ||
|
|
e1bfabbce5 | ||
|
|
9708fec0e0 | ||
|
|
7f4efaf0a3 | ||
|
|
269eb0ba29 | ||
|
|
428c6b7813 | ||
|
|
db2452a4ec | ||
|
|
7dac3825d7 | ||
|
|
7c99872278 | ||
|
|
64c7318cfc | ||
|
|
a9d6483829 | ||
|
|
13a6b92e47 | ||
|
|
9ba008002b | ||
|
|
8914cf78a1 | ||
|
|
d360375b4f | ||
|
|
1caab194af | ||
|
|
31754eba5d | ||
|
|
3cfa16b8b7 | ||
|
|
f80d2bacf4 | ||
|
|
5df3717d94 | ||
|
|
68897f04a2 | ||
|
|
4cb6aeae36 | ||
|
|
0a765a35bf | ||
|
|
6c0b122fbc | ||
|
|
4da2bd90cb | ||
|
|
f0275192c6 | ||
|
|
df905a1d73 | ||
|
|
ad8ad06f44 | ||
|
|
d6b9e2df62 | ||
|
|
5c9b36556f | ||
|
|
80a8348a99 | ||
|
|
005c9f471e | ||
|
|
b40532a830 | ||
|
|
fc7a4408e9 | ||
|
|
93b5f0081d | ||
|
|
ce049ea3ee | ||
|
|
fcc39b2db5 | ||
|
|
cb70fb4e82 | ||
|
|
2593a43d72 | ||
|
|
e44ff5b72a | ||
|
|
22cb1b50a6 | ||
|
|
a42c413705 | ||
|
|
d59d38dc7c | ||
|
|
77582be7fd | ||
|
|
0cb50355b7 | ||
|
|
a2d66e91ff | ||
|
|
ccdb981917 | ||
|
|
d80b581ace | ||
|
|
53efb6711d | ||
|
|
1de6e875f9 | ||
|
|
95a15c3cf8 | ||
|
|
ab320684f5 | ||
|
|
a284b69a1e | ||
|
|
b590f41254 | ||
|
|
a97076ead5 | ||
|
|
0b6df8be1c | ||
|
|
150bab0b57 | ||
|
|
d3355eda65 | ||
|
|
fbf10e553d | ||
|
|
fb37be5734 | ||
|
|
54e6cefa67 | ||
|
|
33b25c1129 | ||
|
|
44d8545c09 | ||
|
|
7a2808243c | ||
|
|
1be84de26b | ||
|
|
78e37f7ab4 | ||
|
|
6b880af447 | ||
|
|
f742f83834 | ||
|
|
e6e4e53a73 | ||
|
|
7c594ba7a9 | ||
|
|
d34619824c | ||
|
|
80297f113f | ||
|
|
80f51bfe1e | ||
|
|
587f431ef4 | ||
|
|
e560f9cbd6 | ||
|
|
80235d53f4 | ||
|
|
892b9a732e | ||
|
|
d8a0a015e4 | ||
|
|
e60e3b9fae | ||
|
|
6715f01b8c | ||
|
|
465af9bc41 | ||
|
|
435cf05f9f | ||
|
|
943e211cf1 | ||
|
|
ad0a13004e | ||
|
|
04bb6a5275 | ||
|
|
d3c917eac1 | ||
|
|
4c13271a5b |
3
.github/workflows/ci.yml
vendored
@@ -34,6 +34,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: gradle/wrapper-validation-action@v1
|
||||
if: matrix.java == '1.8'
|
||||
|
||||
- name: Setup Java ${{ matrix.java }}
|
||||
uses: actions/setup-java@v1
|
||||
@@ -72,7 +73,7 @@ jobs:
|
||||
needs: build
|
||||
if: |
|
||||
github.event_name == 'push' &&
|
||||
github.ref == 'refs/heads/main' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith( github.ref, 'refs/heads/develop-' )) &&
|
||||
github.repository == 'JFormDesigner/FlatLaf'
|
||||
|
||||
steps:
|
||||
|
||||
112
CHANGELOG.md
@@ -1,7 +1,7 @@
|
||||
FlatLaf Change Log
|
||||
==================
|
||||
|
||||
## 2.0-SNAPSHOT
|
||||
## 2.0-rc1
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
@@ -12,9 +12,34 @@ FlatLaf Change Log
|
||||
- Style classes allow defining style rules at a single place (in UI defaults)
|
||||
and use them in any component. (PR #388)\
|
||||
E.g.: `mySlider.putClientProperty( "FlatLaf.styleClass", "myclass" );`
|
||||
- TextField, FormattedTextField and PasswordField: Support leading and trailing
|
||||
icons (set client property `JTextField.leadingIcon` or
|
||||
`JTextField.trailingIcon` to an `Icon`). (PR #378; issue #368)
|
||||
- Typography defines several font styles for headers and various text sizes,
|
||||
which makes it easy to use consistent font styles across the application. (PR
|
||||
#396)
|
||||
- Native window decorations (Windows 10/11 only):
|
||||
- Unified backgrounds for window title bar is now enabled by default (window
|
||||
title bar has now same background color as window content). Bottom separator
|
||||
for menu bars is no longer painted (if unified background is enabled).
|
||||
- Show Windows 11 snap layouts menu when hovering the mouse over the maximize
|
||||
button. (issues #397 and #407)
|
||||
- Possibility to hide window title bar icon (for single window set client
|
||||
property `JRootPane.titleBarShowIcon` to `false`; for all windows set UI
|
||||
value `TitlePane.showIcon` to `false`).
|
||||
- OptionPane: Hide window title bar icon by default. Can be be made visibly by
|
||||
setting UI default `OptionPane.showIcon` to `true`. (issue #416)
|
||||
- No longer show the Java "duke/cup" icon if no window icon image is set.
|
||||
(issue #416)
|
||||
- TextField, FormattedTextField and PasswordField:
|
||||
- Support leading and trailing icons (set client property
|
||||
`JTextField.leadingIcon` or `JTextField.trailingIcon` to a
|
||||
`javax.swing.Icon`). (PR #378; issue #368)
|
||||
- Support leading and trailing components (set client property
|
||||
`JTextField.leadingComponent` or `JTextField.trailingComponent` to a
|
||||
`java.awt.Component`). (PR #386)
|
||||
- Support "clear" (or "cancel") button to empty text field. Only shown if text
|
||||
field is not empty, editable and enabled. (set client property
|
||||
`JTextField.showClearButton` to `true`). (PR #442)
|
||||
- PasswordField: Support reveal (or "eye") button to show password. (see UI
|
||||
value `PasswordField.showRevealButton`) (PR #442; issue #173)
|
||||
- TextComponents: Double/triple-click-and-drag now extends selection by whole
|
||||
words/lines.
|
||||
- Theming improvements: Reworks core themes to make it easier to create new
|
||||
@@ -44,25 +69,96 @@ FlatLaf Change Log
|
||||
incompatible changes in FlatLaf properties files.
|
||||
- Slider: Support specifying width of thumb border (see UI value
|
||||
`Slider.thumbBorderWidth`).
|
||||
- TabbedPane: Optionally paint selected tab as card. (PR #343)
|
||||
- MenuItem:
|
||||
- Paint the selected icon when the item is selected. (PR #415)
|
||||
- Vertically align text if icons have different widths. (issue #437)
|
||||
- Panel: Support painting background with rounded corners. (issue #367)
|
||||
- Added more color functions to class `ColorFunctions` for easy use in
|
||||
applications: `lighten()`, `darken()`, `saturate()`, `desaturate()`, `spin()`,
|
||||
`tint()`, `shade()` and `luma()`.
|
||||
- Support defining fonts in FlatLaf properties files. (issue #384)
|
||||
- Extras: Added class `FlatDesktop` for easy integration into macOS screen menu
|
||||
(About, Preferences and Quit) when using Java 8.
|
||||
- Added method `FlatLaf.registerCustomDefaultsSource(URL packageUrl)` for JPMS.
|
||||
(issue #325)
|
||||
- Extras:
|
||||
- Added class `FlatDesktop` for easy integration into macOS screen menu
|
||||
(About, Preferences and Quit) when using Java 8.
|
||||
- `FlatSVGIcon`: Support loading SVG from `URL` (for JPMS), `URI`, `File` or
|
||||
`InputStream`. (issues #419 and #325)
|
||||
- `FlatSVGUtils`: Support loading SVG from `URL` (for JPMS). (issue #325)
|
||||
- SwingX:
|
||||
- New "column control" icon for `JXTable` that scales and uses antialiasing.
|
||||
(issue #434)
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Native window decorations: Fixed `UnsatisfiedLinkError` on Windows 11 for ARM
|
||||
processors. (issue #443)
|
||||
- MenuBar: Do not fill background if non-opaque and having custom background
|
||||
color. (issue #409)
|
||||
- InternalFrame: Fill background to avoid that parent may shine through internal
|
||||
frame if it contains non-opaque components. (better fix for issue #274)
|
||||
- SwingX: Fixed `NullPointerException` in `FlatCaret` when using
|
||||
`org.jdesktop.swingx.prompt.PromptSupport.setPrompt()` on a text field and
|
||||
then switching theme.
|
||||
|
||||
|
||||
## 1.6.5
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- Linux: Fixed font problems when running on Oracle Java (OpenJDK is not
|
||||
affected):
|
||||
- oversized text if system font is "Inter" (issue #427)
|
||||
- missing text if system font is "Cantarell" (on Fedora)
|
||||
- MenuItem: Changed accelerator delimiter from `-` to `+`. (Windows and Linux).
|
||||
- ComboBox: Fixed occasional `StackOverflowError` when modifying combo box not
|
||||
on AWT thread. (issue #432)
|
||||
- macOS: Fixed `NullPointerException` when using AWT component
|
||||
`java.awt.Choice`. (issue #439)
|
||||
- Native window decorations: Do not exit application with `UnsatisfiedLinkError`
|
||||
in case that FlatLaf DLL cannot be executed because of restrictions on
|
||||
temporary directory. Instead, continue with default window decorations. (issue
|
||||
#436)
|
||||
|
||||
|
||||
## 1.6.4
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox: Fixed regression in FlatLaf 1.6.3 that makes selected item invisible
|
||||
in popup list if `DefaultListCellRenderer` is used as renderer. If using
|
||||
default renderer, it works. (issue #426)
|
||||
|
||||
|
||||
## 1.6.3
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox (not editable): Fixed regression in FlatLaf 1.6.2 that may display
|
||||
text in non-editable combo boxes in bold. (issue #423)
|
||||
- Tree: Fixed editing cell issue with custom cell renderer and cell editor that
|
||||
use same component for rendering and editing. (issue #385)
|
||||
|
||||
|
||||
## 1.6.2
|
||||
|
||||
#### Fixed bugs
|
||||
|
||||
- ComboBox (not editable): Fixed background painted outside of border if round
|
||||
edges are enabled (client property `JComponent.roundRect` is `true`). (similar
|
||||
to issue #382; regression since fixing #330 in FlatLaf 1.4)
|
||||
- Tree: Fixed editing cell issue with custom cell renderer and cell editor that
|
||||
use same component for rendering and editing. (issue #385)
|
||||
- ComboBox: Fixed `NullPointerException`, which may occur under special
|
||||
circumstances. (issue #408)
|
||||
- Table: Do not select text in cell editor when it gets focus (when
|
||||
`JTable.surrendersFocusOnKeystroke` is `true`) and
|
||||
`TextComponent.selectAllOnFocusPolicy` is `once` (the default) or `always`.
|
||||
(issue #395)
|
||||
- Linux: Fixed NPE when using `java.awt.TrayIcon`. (issue #405)
|
||||
- FileChooser: Workaround for crash on Windows with Java 17 32-bit (disabled
|
||||
Windows icons). Java 17 64-bit is not affected. (issue #403)
|
||||
- Native window decorations: Fixed layout loop, which may occur under special
|
||||
circumstances and slows down the application. (issue #420)
|
||||
|
||||
|
||||
## 1.6.1
|
||||
|
||||
@@ -114,6 +114,8 @@ Buzz
|
||||
Applications using FlatLaf
|
||||
--------------------------
|
||||
|
||||
-  [Jailer](https://github.com/Wisser/Jailer) 11.2 -
|
||||
database subsetting and relational data browsing tool
|
||||
- [Apache NetBeans](https://netbeans.apache.org/) 11.3 - IDE for Java, PHP, HTML
|
||||
and much more
|
||||
- [jclasslib bytecode viewer](https://github.com/ingokegel/jclasslib) 5.5
|
||||
@@ -141,6 +143,8 @@ Applications using FlatLaf
|
||||
[OpenStreetMap](https://www.openstreetmap.org/) (requires FlatLaf JOSM plugin)
|
||||
- [jAlbum](https://jalbum.net/) 21 (**commercial**) - creates photo album
|
||||
websites
|
||||
-  [PDF Studio](https://www.qoppa.com/pdfstudio/) 2021
|
||||
(**commercial**) - create, review and edit PDF documents
|
||||
- [XMLmind XML Editor](https://www.xmlmind.com/xmleditor/) 9.3 (**commercial**)
|
||||
- [Total Validator](https://www.totalvalidator.com/) 15 (**commercial**) -
|
||||
checks your website
|
||||
@@ -173,7 +177,7 @@ Applications using FlatLaf
|
||||
systems development platform
|
||||
- [JPass](https://github.com/gaborbata/jpass) - password manager with strong
|
||||
encryption
|
||||
- [Jes - Die Java-EÜR](https://www.jes-eur.de)
|
||||
- [Jes - Die Java-EÜR](https://www.jes-eur.de)
|
||||
- [Mapton](https://mapton.org/) 2.0
|
||||
([source code](https://github.com/trixon/mapton)) - some kind of map
|
||||
application (based on NetBeans platform)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
val releaseVersion = "1.6.1"
|
||||
val releaseVersion = "2.0-rc1"
|
||||
val developmentVersion = "2.0-SNAPSHOT"
|
||||
|
||||
version = if( java.lang.Boolean.getBoolean( "release" ) ) releaseVersion else developmentVersion
|
||||
|
||||
2151
compare1.txt
@@ -331,6 +331,24 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded";
|
||||
|
||||
/**
|
||||
* Specifies whether the window icon should be shown in the window title bar
|
||||
* (requires enabled window decorations).
|
||||
* <p>
|
||||
* Setting this shows/hides the windows icon
|
||||
* for the {@code JFrame} or {@code JDialog} that contains the root pane.
|
||||
* <p>
|
||||
* This client property has higher priority than UI default {@code TitlePane.showIcon}.
|
||||
* <p>
|
||||
* (requires Window 10)
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JRootPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TITLE_BAR_SHOW_ICON = "JRootPane.titleBarShowIcon";
|
||||
|
||||
/**
|
||||
* Background color of window title bar (requires enabled window decorations).
|
||||
* <p>
|
||||
@@ -375,6 +393,35 @@ public interface FlatClientProperties
|
||||
|
||||
//---- JTabbedPane --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specifies type of the selected tab.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong>
|
||||
* {@link #TABBED_PANE_TAB_TYPE_UNDERLINED} or
|
||||
* {@link #TABBED_PANE_TAB_TYPE_CARD}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE = "JTabbedPane.tabType";
|
||||
|
||||
/**
|
||||
* Paint the selected tab underlined.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_TYPE
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE_UNDERLINED = "underlined";
|
||||
|
||||
/**
|
||||
* Paint the selected tab as card.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_TYPE
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE_CARD = "card";
|
||||
|
||||
/**
|
||||
* Specifies whether separators are shown between tabs.
|
||||
* <p>
|
||||
@@ -716,9 +763,9 @@ public interface FlatClientProperties
|
||||
/**
|
||||
* Specifies a component that will be placed at the leading edge of the tabs area.
|
||||
* <p>
|
||||
* For top and bottom tab placement, the layed out component size will be
|
||||
* For top and bottom tab placement, the laid out component size will be
|
||||
* the preferred component width and the tab area height.<br>
|
||||
* For left and right tab placement, the layed out component size will be
|
||||
* For left and right tab placement, the laid out component size will be
|
||||
* the tab area width and the preferred component height.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
@@ -729,9 +776,9 @@ public interface FlatClientProperties
|
||||
/**
|
||||
* Specifies a component that will be placed at the trailing edge of the tabs area.
|
||||
* <p>
|
||||
* For top and bottom tab placement, the layed out component size will be
|
||||
* For top and bottom tab placement, the laid out component size will be
|
||||
* the available horizontal space (minimum is preferred component width) and the tab area height.<br>
|
||||
* For left and right tab placement, the layed out component size will be
|
||||
* For left and right tab placement, the laid out component size will be
|
||||
* the tab area width and the available vertical space (minimum is preferred component height).
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
@@ -816,6 +863,87 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TEXT_FIELD_TRAILING_ICON = "JTextField.trailingIcon";
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the leading edge of the text field.
|
||||
* <p>
|
||||
* The component will be positioned inside and aligned to the visible text field border.
|
||||
* There is no gap between the visible border and the component.
|
||||
* The laid out component size will be the preferred component width
|
||||
* and the inner text field height.
|
||||
* <p>
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #OUTLINE}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TEXT_FIELD_LEADING_COMPONENT = "JTextField.leadingComponent";
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||
* <p>
|
||||
* The component will be positioned inside and aligned to the visible text field border.
|
||||
* There is no gap between the visible border and the component.
|
||||
* The laid out component size will be the preferred component width
|
||||
* and the inner text field height.
|
||||
* <p>
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #OUTLINE}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link javax.swing.JComponent}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TEXT_FIELD_TRAILING_COMPONENT = "JTextField.trailingComponent";
|
||||
|
||||
/**
|
||||
* Specifies whether a "clear" (or "cancel") button is shown on the trailing side
|
||||
* if the text field is not empty, editable and enabled. Default is {@code false}.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TEXT_FIELD_SHOW_CLEAR_BUTTON = "JTextField.showClearButton";
|
||||
|
||||
/**
|
||||
* Specifies the callback that is invoked when a "clear" (or "cancel") button is clicked.
|
||||
* If a callback is specified than it is responsible for clearing the text field.
|
||||
* Without callback, the text field clears itself.
|
||||
* <p>
|
||||
* Either use a {@link java.lang.Runnable}:
|
||||
* <pre>{@code
|
||||
* myTextField.putClientProperty( "JTextField.clearCallback",
|
||||
* (Runnable) () -> {
|
||||
* // clear field here or cancel search
|
||||
* } );
|
||||
* }</pre>
|
||||
* Or use a {@link java.util.function.Consumer}<javax.swing.text.JTextComponent>
|
||||
* that receives the text field as parameter:
|
||||
* <pre>{@code
|
||||
* myTextField.putClientProperty( "JTextField.clearCallback",
|
||||
* (Consumer<JTextComponent>) textField -> {
|
||||
* // clear field here or cancel search
|
||||
* } );
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTextField} (and subclasses)<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Runnable}
|
||||
* or {@link java.util.function.Consumer}<javax.swing.text.JTextComponent>
|
||||
*
|
||||
* @see #TEXT_FIELD_SHOW_CLEAR_BUTTON
|
||||
* @since 2
|
||||
*/
|
||||
String TEXT_FIELD_CLEAR_CALLBACK = "JTextField.clearCallback";
|
||||
|
||||
//---- JToggleButton ------------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
@@ -51,6 +52,7 @@ import javax.swing.ImageIcon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.PopupFactory;
|
||||
import javax.swing.RootPaneContainer;
|
||||
@@ -392,6 +394,7 @@ public abstract class FlatLaf
|
||||
"EditorPane.inactiveBackground",
|
||||
"FormattedTextField.disabledBackground",
|
||||
"PasswordField.disabledBackground",
|
||||
"RootPane.background",
|
||||
"Spinner.disabledBackground",
|
||||
"TextArea.disabledBackground",
|
||||
"TextArea.inactiveBackground",
|
||||
@@ -410,7 +413,8 @@ public abstract class FlatLaf
|
||||
"Spinner.disabledForeground",
|
||||
"ToggleButton.disabledText" );
|
||||
putDefaults( defaults, defaults.getColor( "textText" ),
|
||||
"DesktopIcon.foreground" );
|
||||
"DesktopIcon.foreground",
|
||||
"RootPane.foreground" );
|
||||
|
||||
initFonts( defaults );
|
||||
initIconColors( defaults, isDark() );
|
||||
@@ -420,7 +424,7 @@ public abstract class FlatLaf
|
||||
// (using defaults.remove() to avoid that lazy value is resolved and icon loaded here)
|
||||
Object icon = defaults.remove( "InternalFrame.icon" );
|
||||
defaults.put( "InternalFrame.icon", icon );
|
||||
defaults.put( "TitlePane.icon", icon );
|
||||
defaults.put( "TitlePane.icon", icon ); // no longer used, but keep for compatibility
|
||||
|
||||
// get addons and sort them by priority
|
||||
ServiceLoader<FlatDefaultsAddon> addonLoader = ServiceLoader.load( FlatDefaultsAddon.class );
|
||||
@@ -533,13 +537,16 @@ public abstract class FlatLaf
|
||||
// use active value for all fonts to allow changing fonts in all components with:
|
||||
// UIManager.put( "defaultFont", myFont );
|
||||
// (this is similar as in Nimbus L&F)
|
||||
Object activeFont = new ActiveFont( null, -1, 0, 0, 0, 0 );
|
||||
Object activeFont = new ActiveFont( null, null, -1, 0, 0, 0, 0 );
|
||||
|
||||
// override fonts
|
||||
for( Object key : defaults.keySet() ) {
|
||||
if( key instanceof String && (((String)key).endsWith( ".font" ) || ((String)key).endsWith( "Font" )) )
|
||||
defaults.put( key, activeFont );
|
||||
}
|
||||
|
||||
// add fonts that are not set in BasicLookAndFeel
|
||||
defaults.put( "RootPane.font", activeFont );
|
||||
}
|
||||
|
||||
private void initDefaultFont( UIDefaults defaults ) {
|
||||
@@ -617,7 +624,7 @@ public abstract class FlatLaf
|
||||
|
||||
/** @since 1.1 */
|
||||
public static ActiveValue createActiveFontValue( float scaleFactor ) {
|
||||
return new ActiveFont( null, -1, 0, 0, 0, scaleFactor );
|
||||
return new ActiveFont( null, null, -1, 0, 0, 0, scaleFactor );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -751,6 +758,9 @@ public abstract class FlatLaf
|
||||
* and can therefore override all UI defaults.
|
||||
* <p>
|
||||
* Invoke this method before setting the look and feel.
|
||||
* <p>
|
||||
* If using Java modules, the package must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #registerCustomDefaultsSource(URL)}.
|
||||
*
|
||||
* @param packageName a package name (e.g. "com.myapp.resources")
|
||||
*/
|
||||
@@ -792,6 +802,32 @@ public abstract class FlatLaf
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a package where FlatLaf searches for properties files with custom UI defaults.
|
||||
* <p>
|
||||
* See {@link #registerCustomDefaultsSource(String)} for details.
|
||||
* <p>
|
||||
* This method is useful if using Java modules and the package containing the properties files
|
||||
* is not opened in {@code module-info.java}.
|
||||
* E.g. {@code FlatLaf.registerCustomDefaultsSource( MyApp.class.getResource( "/com/myapp/themes/" ) )}.
|
||||
*
|
||||
* @param packageUrl a package URL
|
||||
* @since 2
|
||||
*/
|
||||
public static void registerCustomDefaultsSource( URL packageUrl ) {
|
||||
if( customDefaultsSources == null )
|
||||
customDefaultsSources = new ArrayList<>();
|
||||
customDefaultsSources.add( packageUrl );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public static void unregisterCustomDefaultsSource( URL packageUrl ) {
|
||||
if( customDefaultsSources == null )
|
||||
return;
|
||||
|
||||
customDefaultsSources.remove( packageUrl );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a folder where FlatLaf searches for properties files with custom UI defaults.
|
||||
* <p>
|
||||
@@ -1001,12 +1037,23 @@ public abstract class FlatLaf
|
||||
|
||||
/**
|
||||
* Revalidate and repaint all displayable frames and dialogs.
|
||||
* <p>
|
||||
* Useful to update UI after changing {@code TitlePane.menuBarEmbedded}.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
public static void revalidateAndRepaintAllFramesAndDialogs() {
|
||||
for( Window w : Window.getWindows() ) {
|
||||
if( isDisplayableFrameOrDialog( w ) ) {
|
||||
// revalidate menu bar
|
||||
JMenuBar menuBar = (w instanceof JFrame)
|
||||
? ((JFrame)w).getJMenuBar()
|
||||
: (w instanceof JDialog
|
||||
? ((JDialog)w).getJMenuBar()
|
||||
: null);
|
||||
if( menuBar != null )
|
||||
menuBar.revalidate();
|
||||
|
||||
w.revalidate();
|
||||
w.repaint();
|
||||
}
|
||||
@@ -1015,6 +1062,9 @@ public abstract class FlatLaf
|
||||
|
||||
/**
|
||||
* Repaint all displayable frames and dialogs.
|
||||
* <p>
|
||||
* Useful to update UI after changing {@code TitlePane.unifiedBackground},
|
||||
* {@code MenuItem.selectionType} or {@code Component.hideMnemonics}.
|
||||
*
|
||||
* @since 1.1.2
|
||||
*/
|
||||
@@ -1191,6 +1241,7 @@ public abstract class FlatLaf
|
||||
static class ActiveFont
|
||||
implements ActiveValue
|
||||
{
|
||||
private final String baseFontKey;
|
||||
private final List<String> families;
|
||||
private final int style;
|
||||
private final int styleChange;
|
||||
@@ -1200,7 +1251,9 @@ public abstract class FlatLaf
|
||||
|
||||
// cache (scaled/derived) font
|
||||
private FontUIResource font;
|
||||
private Font lastDefaultFont;
|
||||
private Font lastBaseFont;
|
||||
|
||||
private boolean inCreateValue;
|
||||
|
||||
/**
|
||||
* @param families list of font families, or {@code null}
|
||||
@@ -1211,9 +1264,10 @@ public abstract class FlatLaf
|
||||
* @param relativeSize added to size of base font, or {@code 0}
|
||||
* @param scaleSize multiply size of base font, or {@code 0}
|
||||
*/
|
||||
ActiveFont( List<String> families, int style, int styleChange,
|
||||
ActiveFont( String baseFontKey, List<String> families, int style, int styleChange,
|
||||
int absoluteSize, int relativeSize, float scaleSize )
|
||||
{
|
||||
this.baseFontKey = baseFontKey;
|
||||
this.families = families;
|
||||
this.style = style;
|
||||
this.styleChange = styleChange;
|
||||
@@ -1224,16 +1278,30 @@ public abstract class FlatLaf
|
||||
|
||||
@Override
|
||||
public Object createValue( UIDefaults table ) {
|
||||
Font defaultFont = UIManager.getFont( "defaultFont" );
|
||||
if( inCreateValue )
|
||||
throw new IllegalStateException( "FlatLaf: endless recursion in font" );
|
||||
|
||||
// fallback (to avoid NPE in case that this is used in another Laf)
|
||||
if( defaultFont == null )
|
||||
defaultFont = UIManager.getFont( "Label.font" );
|
||||
Font baseFont = null;
|
||||
|
||||
if( lastDefaultFont != defaultFont ) {
|
||||
lastDefaultFont = defaultFont;
|
||||
inCreateValue = true;
|
||||
try {
|
||||
if( baseFontKey != null )
|
||||
baseFont = (Font) UIDefaultsLoader.lazyUIManagerGet( baseFontKey );
|
||||
|
||||
font = derive( defaultFont, fontSize -> UIScale.scale( fontSize ) );
|
||||
if( baseFont == null )
|
||||
baseFont = UIManager.getFont( "defaultFont" );
|
||||
|
||||
// fallback (to avoid NPE in case that this is used in another Laf)
|
||||
if( baseFont == null )
|
||||
baseFont = UIManager.getFont( "Label.font" );
|
||||
} finally {
|
||||
inCreateValue = false;
|
||||
}
|
||||
|
||||
if( lastBaseFont != baseFont ) {
|
||||
lastBaseFont = baseFont;
|
||||
|
||||
font = derive( baseFont, fontSize -> UIScale.scale( fontSize ) );
|
||||
}
|
||||
|
||||
return font;
|
||||
@@ -1271,9 +1339,19 @@ public abstract class FlatLaf
|
||||
}
|
||||
|
||||
// derive font
|
||||
if( newStyle != baseStyle || newSize != baseSize )
|
||||
if( newStyle != baseStyle || newSize != baseSize ) {
|
||||
// hack for font "Ubuntu Medium" on Linux, which curiously belongs
|
||||
// to family "Ubuntu Light" and using deriveFont() would create a light font
|
||||
if( "Ubuntu Medium".equalsIgnoreCase( baseFont.getName() ) &&
|
||||
"Ubuntu Light".equalsIgnoreCase( baseFont.getFamily() ) )
|
||||
{
|
||||
Font font = createCompositeFont( "Ubuntu Medium", newStyle, newSize );
|
||||
if( !isFallbackFont( font ) )
|
||||
return toUIResource( font );
|
||||
}
|
||||
|
||||
return toUIResource( baseFont.deriveFont( newStyle, newSize ) );
|
||||
else
|
||||
} else
|
||||
return toUIResource( baseFont );
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Toolkit;
|
||||
@@ -28,7 +29,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.swing.text.StyleContext;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
@@ -121,14 +122,25 @@ class LinuxFontPolicy
|
||||
for(;;) {
|
||||
Font font = createFont( family, style, size, dsize );
|
||||
|
||||
// if the font family does not match any font on the system, "Dialog" family is returned
|
||||
if( !"Dialog".equals( font.getFamily() ) || "Dialog".equals( family ) )
|
||||
if( Font.DIALOG.equals( family ) )
|
||||
return font;
|
||||
|
||||
// if the font family does not match any font on the system, "Dialog" family is returned
|
||||
if( !Font.DIALOG.equals( font.getFamily() ) ) {
|
||||
// check for font problems
|
||||
// - font height much larger than expected (e.g. font Inter; Oracle Java 8)
|
||||
// - character width is zero (e.g. font Cantarell; Fedora; Oracle Java 8)
|
||||
FontMetrics fm = StyleContext.getDefaultStyleContext().getFontMetrics( font );
|
||||
if( fm.getHeight() > size * 2 || fm.stringWidth( "a" ) == 0 )
|
||||
return createFont( Font.DIALOG, style, size, dsize );
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
// find last word in family
|
||||
int index = family.lastIndexOf( ' ' );
|
||||
if( index < 0 )
|
||||
return createFont( "Dialog", style, size, dsize );
|
||||
return createFont( Font.DIALOG, style, size, dsize );
|
||||
|
||||
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
|
||||
String lastWord = family.substring( index + 1 ).toLowerCase();
|
||||
|
||||
@@ -22,13 +22,12 @@ import java.awt.Font;
|
||||
import java.awt.Insets;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StreamTokenizer;
|
||||
import java.io.StringReader;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -56,6 +55,7 @@ import com.formdev.flatlaf.util.DerivedColor;
|
||||
import com.formdev.flatlaf.util.GrayFilter;
|
||||
import com.formdev.flatlaf.util.HSLColor;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.SoftCache;
|
||||
import com.formdev.flatlaf.util.StringUtils;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
@@ -80,11 +80,11 @@ class UIDefaultsLoader
|
||||
private static final String OPTIONAL_PREFIX = "?";
|
||||
private static final String WILDCARD_PREFIX = "*.";
|
||||
|
||||
private static final String KEY_VARIABLES = "FlatLaf.internal.variables";
|
||||
static final String KEY_VARIABLES = "FlatLaf.internal.variables";
|
||||
|
||||
private static int parseColorDepth;
|
||||
|
||||
private static final Cache<String, Object> fontCache = new Cache<>();
|
||||
private static final SoftCache<String, Object> fontCache = new SoftCache<>();
|
||||
|
||||
static void loadDefaultsFromProperties( Class<?> lookAndFeelClass, List<FlatDefaultsAddon> addons,
|
||||
Properties additionalDefaults, boolean dark, UIDefaults defaults )
|
||||
@@ -158,6 +158,18 @@ class UIDefaultsLoader
|
||||
properties.load( in );
|
||||
}
|
||||
}
|
||||
} else if( source instanceof URL ) {
|
||||
// load from package URL
|
||||
URL packageUrl = (URL) source;
|
||||
for( Class<?> lafClass : lafClasses ) {
|
||||
URL propertiesUrl = new URL( packageUrl + lafClass.getSimpleName() + ".properties" );
|
||||
|
||||
try( InputStream in = propertiesUrl.openStream() ) {
|
||||
properties.load( in );
|
||||
} catch( FileNotFoundException ex ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
} else if( source instanceof File ) {
|
||||
// load from folder
|
||||
File folder = (File) source;
|
||||
@@ -352,6 +364,12 @@ class UIDefaultsLoader
|
||||
if( resultValueType == null )
|
||||
resultValueType = tempResultValueType;
|
||||
|
||||
// do not parse styles here
|
||||
if( key.startsWith( "[style]" ) ) {
|
||||
resultValueType[0] = ValueType.STRING;
|
||||
return value;
|
||||
}
|
||||
|
||||
value = value.trim();
|
||||
|
||||
// null
|
||||
@@ -429,10 +447,7 @@ class UIDefaultsLoader
|
||||
// check whether value type is specified in the value
|
||||
if( value.startsWith( "#" ) )
|
||||
valueType = ValueType.COLOR;
|
||||
else if( value.startsWith( "\"" ) && value.indexOf( '"', 1 ) == value.length() - 1 ) {
|
||||
valueType = ValueType.STRING;
|
||||
value = value.substring( 1, value.length() - 1 );
|
||||
} else if( value.startsWith( TYPE_PREFIX ) ) {
|
||||
else if( value.startsWith( TYPE_PREFIX ) ) {
|
||||
int end = value.indexOf( TYPE_PREFIX_END );
|
||||
if( end != -1 ) {
|
||||
try {
|
||||
@@ -524,6 +539,12 @@ class UIDefaultsLoader
|
||||
case GRAYFILTER: return parseGrayFilter( value );
|
||||
case UNKNOWN:
|
||||
default:
|
||||
// string
|
||||
if( value.startsWith( "\"" ) && value.endsWith( "\"" ) ) {
|
||||
resultValueType[0] = ValueType.STRING;
|
||||
return value.substring( 1, value.length() - 1 );
|
||||
}
|
||||
|
||||
// colors
|
||||
Object color = parseColorOrFunction( value, resolver, false );
|
||||
if( color != null ) {
|
||||
@@ -567,17 +588,18 @@ class UIDefaultsLoader
|
||||
|
||||
private static Object parseBorder( String value, Function<String, String> resolver, List<ClassLoader> addonClassLoaders ) {
|
||||
if( value.indexOf( ',' ) >= 0 ) {
|
||||
// top,left,bottom,right[,lineColor[,lineThickness]]
|
||||
// top,left,bottom,right[,lineColor[,lineThickness[,arc]]]
|
||||
List<String> parts = splitFunctionParams( value, ',' );
|
||||
Insets insets = parseInsets( value );
|
||||
ColorUIResource lineColor = (parts.size() >= 5)
|
||||
? (ColorUIResource) parseColorOrFunction( resolver.apply( parts.get( 4 ) ), resolver, true )
|
||||
: null;
|
||||
float lineThickness = (parts.size() >= 6) ? parseFloat( parts.get( 5 ), true ) : 1f;
|
||||
float lineThickness = (parts.size() >= 6 && !parts.get( 5 ).isEmpty()) ? parseFloat( parts.get( 5 ), true ) : 1f;
|
||||
int arc = (parts.size() >= 7) ? parseInteger( parts.get( 6 ), true ) : 0;
|
||||
|
||||
return (LazyValue) t -> {
|
||||
return (lineColor != null)
|
||||
? new FlatLineBorder( insets, lineColor, lineThickness )
|
||||
? new FlatLineBorder( insets, lineColor, lineThickness, arc )
|
||||
: new FlatEmptyBorder( insets );
|
||||
};
|
||||
} else
|
||||
@@ -1039,7 +1061,7 @@ class UIDefaultsLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]]
|
||||
* Syntax: [normal] [bold|+bold|-bold] [italic|+italic|-italic] [<size>|+<incr>|-<decr>|<percent>%] [family[, family]] [$baseFontKey]
|
||||
*/
|
||||
private static Object parseFont( String value ) {
|
||||
Object font = fontCache.get( value );
|
||||
@@ -1052,6 +1074,7 @@ class UIDefaultsLoader
|
||||
int relativeSize = 0;
|
||||
float scaleSize = 0;
|
||||
List<String> families = null;
|
||||
String baseFontKey = null;
|
||||
|
||||
// use StreamTokenizer to split string because it supports quoted strings
|
||||
StreamTokenizer st = new StreamTokenizer( new StringReader( value ) );
|
||||
@@ -1101,6 +1124,12 @@ class UIDefaultsLoader
|
||||
scaleSize = parseInteger( param.substring( 0, param.length() - 1 ), true ) / 100f;
|
||||
else
|
||||
absoluteSize = parseInteger( param, true );
|
||||
} else if( firstChar == '$' ) {
|
||||
// reference to base font
|
||||
if( baseFontKey != null )
|
||||
throw new IllegalArgumentException( "baseFontKey specified more than once in '" + value + "'" );
|
||||
|
||||
baseFontKey = param.substring( 1 );
|
||||
} else {
|
||||
// font family
|
||||
if( families == null )
|
||||
@@ -1127,7 +1156,7 @@ class UIDefaultsLoader
|
||||
throw new IllegalArgumentException( "can not use '+italic' and '-italic' in '" + value + "'" );
|
||||
}
|
||||
|
||||
font = new FlatLaf.ActiveFont( families, style, styleChange, absoluteSize, relativeSize, scaleSize );
|
||||
font = new FlatLaf.ActiveFont( baseFontKey, families, style, styleChange, absoluteSize, relativeSize, scaleSize );
|
||||
fontCache.put( value, font );
|
||||
return font;
|
||||
}
|
||||
@@ -1280,7 +1309,7 @@ class UIDefaultsLoader
|
||||
* For use in LazyValue to get value for given key from UIManager and report error
|
||||
* if not found. If key is prefixed by '?', then no error is reported.
|
||||
*/
|
||||
private static Object lazyUIManagerGet( String uiKey ) {
|
||||
static Object lazyUIManagerGet( String uiKey ) {
|
||||
boolean optional = false;
|
||||
if( uiKey.startsWith( OPTIONAL_PREFIX ) ) {
|
||||
uiKey = uiKey.substring( OPTIONAL_PREFIX.length() );
|
||||
@@ -1296,43 +1325,4 @@ class UIDefaultsLoader
|
||||
private static void throwMissingParametersException( String value ) {
|
||||
throw new IllegalArgumentException( "missing parameters in function '" + value + "'" );
|
||||
}
|
||||
|
||||
//---- class Cache --------------------------------------------------------
|
||||
|
||||
private static class Cache<K,V>
|
||||
{
|
||||
private final Map<K, CacheReference<K,V>> map = new HashMap<>();
|
||||
private final ReferenceQueue<V> queue = new ReferenceQueue<>();
|
||||
|
||||
V get( K key ) {
|
||||
expungeStaleEntries();
|
||||
CacheReference<K,V> ref = map.get( key );
|
||||
return (ref != null) ? ref.get() : null;
|
||||
}
|
||||
|
||||
void put( K key, V value ) {
|
||||
expungeStaleEntries();
|
||||
map.put( key, new CacheReference<>( key, value, queue ) );
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
void expungeStaleEntries() {
|
||||
Reference<? extends V> reference;
|
||||
while( (reference = queue.poll()) != null )
|
||||
map.remove( ((CacheReference<K,V>)reference).key );
|
||||
}
|
||||
|
||||
//---- class CacheReference ----
|
||||
|
||||
private static class CacheReference<K,V>
|
||||
extends SoftReference<V>
|
||||
{
|
||||
final K key;
|
||||
|
||||
public CacheReference( K key, V value, ReferenceQueue<? super V> queue ) {
|
||||
super( value, queue );
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +47,16 @@ public class FlatClearIcon
|
||||
@Styleable protected Color clearIconHoverColor = UIManager.getColor( "SearchField.clearIconHoverColor" );
|
||||
@Styleable protected Color clearIconPressedColor = UIManager.getColor( "SearchField.clearIconPressedColor" );
|
||||
|
||||
private final boolean ignoreButtonState;
|
||||
|
||||
public FlatClearIcon() {
|
||||
this( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public FlatClearIcon( boolean ignoreButtonState ) {
|
||||
super( 16, 16, null );
|
||||
this.ignoreButtonState = ignoreButtonState;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@@ -63,7 +71,7 @@ public class FlatClearIcon
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
if( c instanceof AbstractButton ) {
|
||||
if( !ignoreButtonState && c instanceof AbstractButton ) {
|
||||
ButtonModel model = ((AbstractButton)c).getModel();
|
||||
if( model.isPressed() || model.isRollover() ) {
|
||||
/*
|
||||
|
||||
@@ -21,14 +21,16 @@ import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
|
||||
/**
|
||||
* "arrow" icon for {@link javax.swing.JMenuItem}.
|
||||
* "arrow" icon for {@link javax.swing.JMenuItem}, {@link javax.swing.JCheckBoxMenuItem}
|
||||
* and {@link javax.swing.JRadioButtonMenuItem}.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatMenuItemArrowIcon
|
||||
extends FlatMenuArrowIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
public FlatMenuItemArrowIcon() {
|
||||
super( 6, 10, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2021 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.icons;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
/**
|
||||
* "eye" icon for {@link javax.swing.JPasswordField}.
|
||||
*
|
||||
* @uiDefault PasswordField.revealIconColor Color
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 2
|
||||
*/
|
||||
public class FlatRevealIcon
|
||||
extends FlatAbstractIcon
|
||||
{
|
||||
public FlatRevealIcon() {
|
||||
super( 16, 16, UIManager.getColor( "PasswordField.revealIconColor" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintIcon( Component c, Graphics2D g ) {
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Ellipse2D.Float( 5.15f, 6.15f, 5.7f, 5.7f ), false );
|
||||
path.append( new Ellipse2D.Float( 6, 7, 4, 4 ), false );
|
||||
g.fill( path );
|
||||
|
||||
Path2D path2 = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path2.append( new Ellipse2D.Float( 2.15f, 4.15f, 11.7f, 11.7f ), false );
|
||||
path2.append( new Ellipse2D.Float( 3, 5, 10, 10 ), false );
|
||||
Area area = new Area( path2 );
|
||||
area.subtract( new Area( new Rectangle2D.Float( 0, 9.5f, 16, 16 ) ) );
|
||||
g.fill( area );
|
||||
}
|
||||
}
|
||||
@@ -45,8 +45,16 @@ public class FlatSearchIcon
|
||||
@Styleable protected Color searchIconHoverColor = UIManager.getColor( "SearchField.searchIconHoverColor" );
|
||||
@Styleable protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" );
|
||||
|
||||
private final boolean ignoreButtonState;
|
||||
|
||||
public FlatSearchIcon() {
|
||||
this( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public FlatSearchIcon( boolean ignoreButtonState ) {
|
||||
super( 16, 16, null );
|
||||
this.ignoreButtonState = ignoreButtonState;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@@ -70,8 +78,10 @@ public class FlatSearchIcon
|
||||
</svg>
|
||||
*/
|
||||
|
||||
g.setColor( FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor,
|
||||
null, searchIconHoverColor, searchIconPressedColor ) );
|
||||
g.setColor( ignoreButtonState
|
||||
? searchIconColor
|
||||
: FlatButtonUI.buttonStateColor( c, searchIconColor, searchIconColor,
|
||||
null, searchIconHoverColor, searchIconPressedColor ) );
|
||||
|
||||
// paint magnifier
|
||||
Area area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) );
|
||||
|
||||
@@ -30,6 +30,12 @@ public class FlatSearchWithHistoryIcon
|
||||
extends FlatSearchIcon
|
||||
{
|
||||
public FlatSearchWithHistoryIcon() {
|
||||
this( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public FlatSearchWithHistoryIcon( boolean ignoreButtonState ) {
|
||||
super( ignoreButtonState );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -263,7 +263,7 @@ public class FlatButtonUI
|
||||
case STYLE_CLASS:
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( b ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes applyStyle() from installUI()
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
b.updateUI();
|
||||
} else
|
||||
installStyle( b );
|
||||
|
||||
@@ -101,6 +101,9 @@ public class FlatCaret
|
||||
// adds selection highlights to the text component highlighter
|
||||
if( isSelectionVisible() ) {
|
||||
EventQueue.invokeLater( () -> {
|
||||
if( getComponent() == null )
|
||||
return; // was deinstalled
|
||||
|
||||
if( isSelectionVisible() ) {
|
||||
setSelectionVisible( false );
|
||||
setSelectionVisible( true );
|
||||
@@ -253,6 +256,9 @@ public class FlatCaret
|
||||
// select all
|
||||
if( c instanceof JFormattedTextField ) {
|
||||
EventQueue.invokeLater( () -> {
|
||||
if( getComponent() == null )
|
||||
return; // was deinstalled
|
||||
|
||||
select( 0, doc.getLength() );
|
||||
} );
|
||||
} else {
|
||||
|
||||
@@ -89,6 +89,7 @@ public class FlatCheckBoxMenuItemUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||
renderer = null;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@@ -98,8 +98,8 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
* @uiDefault ComboBox.focusedBackground Color optional
|
||||
* @uiDefault ComboBox.disabledBackground Color
|
||||
* @uiDefault ComboBox.disabledForeground Color
|
||||
* @uiDefault ComboBox.buttonBackground Color
|
||||
* @uiDefault ComboBox.buttonEditableBackground Color
|
||||
* @uiDefault ComboBox.buttonBackground Color optional
|
||||
* @uiDefault ComboBox.buttonEditableBackground Color optional
|
||||
* @uiDefault ComboBox.buttonFocusedBackground Color optional; defaults to ComboBox.focusedBackground
|
||||
* @uiDefault ComboBox.buttonSeparatorWidth int or float optional; defaults to Component.borderWidth
|
||||
* @uiDefault ComboBox.buttonSeparatorColor Color optional
|
||||
@@ -281,7 +281,10 @@ public class FlatComboBoxUI
|
||||
public void layoutContainer( Container parent ) {
|
||||
super.layoutContainer( parent );
|
||||
|
||||
if( arrowButton != null ) {
|
||||
// on macOS, a Swing combo box is used for AWT component java.awt.Choice
|
||||
// and the font may be (temporary) null
|
||||
|
||||
if( arrowButton != null && comboBox.getFont() != null ) {
|
||||
// limit button width to height of a raw combobox (without insets)
|
||||
FontMetrics fm = comboBox.getFontMetrics( comboBox.getFont() );
|
||||
int maxButtonWidth = fm.getHeight() + scale( padding.top ) + scale( padding.bottom );
|
||||
@@ -540,24 +543,27 @@ public class FlatComboBoxUI
|
||||
|
||||
// paint arrow button background
|
||||
if( enabled && !isCellRenderer ) {
|
||||
g2.setColor( paintButton
|
||||
Color buttonColor = paintButton
|
||||
? buttonEditableBackground
|
||||
: (buttonFocusedBackground != null || focusedBackground != null) && isPermanentFocusOwner( comboBox )
|
||||
? (buttonFocusedBackground != null ? buttonFocusedBackground : focusedBackground)
|
||||
: buttonBackground );
|
||||
Shape oldClip = g2.getClip();
|
||||
if( isLeftToRight )
|
||||
g2.clipRect( arrowX, 0, width - arrowX, height );
|
||||
else
|
||||
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
|
||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
|
||||
g2.setClip( oldClip );
|
||||
: buttonBackground;
|
||||
if( buttonColor != null ) {
|
||||
g2.setColor( buttonColor );
|
||||
Shape oldClip = g2.getClip();
|
||||
if( isLeftToRight )
|
||||
g2.clipRect( arrowX, 0, width - arrowX, height );
|
||||
else
|
||||
g2.clipRect( 0, 0, arrowX + arrowWidth, height );
|
||||
FlatUIUtils.paintComponentBackground( g2, 0, 0, width, height, focusWidth, arc );
|
||||
g2.setClip( oldClip );
|
||||
}
|
||||
}
|
||||
|
||||
// paint vertical line between value and arrow button
|
||||
if( paintButton ) {
|
||||
Color separatorColor = enabled ? buttonSeparatorColor : buttonDisabledSeparatorColor;
|
||||
if( separatorColor != null ) {
|
||||
if( separatorColor != null && buttonSeparatorWidth > 0 ) {
|
||||
g2.setColor( separatorColor );
|
||||
float lw = scale( buttonSeparatorWidth );
|
||||
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
||||
@@ -575,22 +581,6 @@ public class FlatComboBoxUI
|
||||
@Override
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public void paintCurrentValue( Graphics g, Rectangle bounds, boolean hasFocus ) {
|
||||
// apply clipping using rounded rectangle to avoid that renderer paints
|
||||
// outside of border if combobox uses larger arc for edges
|
||||
// (e.g. FlatClientProperties.COMPONENT_ROUND_RECT is true)
|
||||
FlatBorder border = FlatUIUtils.getOutsideFlatBorder( comboBox );
|
||||
if( border != null ) {
|
||||
int clipArc = border.getArc( comboBox ) - (border.getLineWidth( comboBox ) * 2);
|
||||
if( clipArc > 0 ) {
|
||||
int x = bounds.x;
|
||||
int width = bounds.width + bounds.height;
|
||||
if( !comboBox.getComponentOrientation().isLeftToRight() )
|
||||
x -= bounds.height;
|
||||
((Graphics2D)g).clip( FlatUIUtils.createComponentRectangle(
|
||||
x, bounds.y, width, bounds.height, scale( (float) clipArc ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
paddingBorder.uninstall();
|
||||
|
||||
ListCellRenderer<Object> renderer = comboBox.getRenderer();
|
||||
@@ -604,11 +594,20 @@ public class FlatComboBoxUI
|
||||
c.setBackground( getBackground( enabled ) );
|
||||
c.setForeground( getForeground( enabled ) );
|
||||
|
||||
// make renderer component temporary non-opaque to avoid that renderer paints
|
||||
// background outside of border if combobox uses larger arc for edges
|
||||
// (e.g. FlatClientProperties.COMPONENT_ROUND_RECT is true)
|
||||
if( c instanceof JComponent )
|
||||
((JComponent)c).setOpaque( false );
|
||||
|
||||
boolean shouldValidate = (c instanceof JPanel);
|
||||
|
||||
paddingBorder.install( c );
|
||||
currentValuePane.paintComponent( g, c, comboBox, bounds.x, bounds.y, bounds.width, bounds.height, shouldValidate );
|
||||
paddingBorder.uninstall();
|
||||
|
||||
if( c instanceof JComponent )
|
||||
((JComponent)c).setOpaque( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -813,9 +812,12 @@ public class FlatComboBoxUI
|
||||
// make opaque to avoid that background shines thru border (e.g. at 150% scaling)
|
||||
setOpaque( true );
|
||||
|
||||
// set popup border
|
||||
// use non-UIResource to avoid that it is overwritten when making
|
||||
// popup visible (see JPopupMenu.setInvoker()) in theme editor preview
|
||||
Border border = UIManager.getBorder( "PopupMenu.border" );
|
||||
if( border != null )
|
||||
setBorder( border );
|
||||
setBorder( FlatUIUtils.nonUIResource( border ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -829,6 +831,11 @@ public class FlatComboBoxUI
|
||||
void updateStyle() {
|
||||
if( popupBackground != null )
|
||||
list.setBackground( popupBackground );
|
||||
|
||||
// set popup background because it may shine thru when scaled (e.g. at 150%)
|
||||
// use non-UIResource to avoid that it is overwritten when making
|
||||
// popup visible (see JPopupMenu.setInvoker()) in theme editor preview
|
||||
setBackground( FlatUIUtils.nonUIResource( list.getBackground() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -915,7 +922,9 @@ public class FlatComboBoxUI
|
||||
this.padding = padding;
|
||||
}
|
||||
|
||||
void install( Component c ) {
|
||||
// using synchronized to avoid problems with code that modifies combo box
|
||||
// (model, selection, etc) not on AWT thread (which should be not done)
|
||||
synchronized void install( Component c ) {
|
||||
if( !(c instanceof JComponent) )
|
||||
return;
|
||||
|
||||
@@ -947,7 +956,7 @@ public class FlatComboBoxUI
|
||||
* there is no single place to uninstall it.
|
||||
* This is the reason why this method is called from various places.
|
||||
*/
|
||||
void uninstall() {
|
||||
synchronized void uninstall() {
|
||||
if( rendererComponent == null )
|
||||
return;
|
||||
|
||||
@@ -958,9 +967,9 @@ public class FlatComboBoxUI
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
synchronized public Insets getBorderInsets( Component c, Insets insets ) {
|
||||
Insets padding = scale( this.padding );
|
||||
if( rendererBorder != null ) {
|
||||
if( rendererBorder != null && !(rendererBorder instanceof CellPaddingBorder) ) {
|
||||
Insets insideInsets = rendererBorder.getBorderInsets( c );
|
||||
insets.top = Math.max( padding.top, insideInsets.top );
|
||||
insets.left = Math.max( padding.left, insideInsets.left );
|
||||
|
||||
@@ -44,8 +44,8 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
||||
* <!-- BasicEditorPaneUI -->
|
||||
*
|
||||
* @uiDefault EditorPane.font Font
|
||||
* @uiDefault EditorPane.background Color also used if not editable
|
||||
* @uiDefault EditorPane.foreground Color
|
||||
* @uiDefault EditorPane.background Color
|
||||
* @uiDefault EditorPane.foreground Color also used if not editable
|
||||
* @uiDefault EditorPane.caretForeground Color
|
||||
* @uiDefault EditorPane.selectionBackground Color
|
||||
* @uiDefault EditorPane.selectionForeground Color
|
||||
|
||||
@@ -262,12 +262,20 @@ public class FlatFileChooserUI
|
||||
|
||||
@Override
|
||||
public FileView getFileView( JFileChooser fc ) {
|
||||
return fileView;
|
||||
return doNotUseSystemIcons() ? super.getFileView( fc ) : fileView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearIconCache() {
|
||||
fileView.clearIconCache();
|
||||
if( doNotUseSystemIcons() )
|
||||
super.clearIconCache();
|
||||
else
|
||||
fileView.clearIconCache();
|
||||
}
|
||||
|
||||
private boolean doNotUseSystemIcons() {
|
||||
// Java 17 32bit craches on Windows when using system icons
|
||||
return SystemInfo.isWindows && SystemInfo.isJava_17_orLater && !SystemInfo.isX86_64;
|
||||
}
|
||||
|
||||
//---- class FlatFileView -------------------------------------------------
|
||||
|
||||
@@ -213,6 +213,13 @@ public class FlatInternalFrameTitlePane
|
||||
case "componentOrientation":
|
||||
applyComponentOrientation( frame.getComponentOrientation() );
|
||||
break;
|
||||
|
||||
case "opaque":
|
||||
// Do not invoke super.propertyChange() here because it always
|
||||
// invokes repaint(), which would cause endless repainting.
|
||||
// The opaque flag is temporary changed in FlatUIUtils.hasOpaqueBeenExplicitlySet(),
|
||||
// invoked from FlatInternalFrameUI.update().
|
||||
return;
|
||||
}
|
||||
|
||||
super.propertyChange( e );
|
||||
|
||||
@@ -179,6 +179,26 @@ public class FlatInternalFrameUI
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this, frame.getBorder() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Graphics g, JComponent c ) {
|
||||
// The internal frame actually should be opaque and fill its background,
|
||||
// but it must be non-opaque to allow translucent resize handles (outside of visual bounds).
|
||||
// To avoid that parent may shine through internal frame (e.g. if menu bar is non-opaque),
|
||||
// fill background excluding insets (translucent resize handles),
|
||||
// but only if opaque was not set explicitly by application to false.
|
||||
// If applications has set internal frame opacity to false, do not fill background (for compatibility).
|
||||
if( !c.isOpaque() && !FlatUIUtils.hasOpaqueBeenExplicitlySet( c ) ) {
|
||||
Insets insets = c.getInsets();
|
||||
|
||||
g.setColor( c.getBackground() );
|
||||
g.fillRect( insets.left, insets.top,
|
||||
c.getWidth() - insets.left - insets.right,
|
||||
c.getHeight() - insets.top - insets.bottom );
|
||||
}
|
||||
|
||||
super.update( g, c );
|
||||
}
|
||||
|
||||
//---- class FlatInternalFrameBorder --------------------------------------
|
||||
|
||||
public static class FlatInternalFrameBorder
|
||||
|
||||
@@ -122,7 +122,7 @@ public class FlatLabelUI
|
||||
JLabel label = (JLabel) e.getSource();
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( label ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes applyStyle() from installUI()
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
label.updateUI();
|
||||
} else
|
||||
installStyle( label );
|
||||
|
||||
@@ -37,15 +37,18 @@ public class FlatLineBorder
|
||||
{
|
||||
private final Color lineColor;
|
||||
private final float lineThickness;
|
||||
/** @since 2 */ private final int arc;
|
||||
|
||||
public FlatLineBorder( Insets insets, Color lineColor ) {
|
||||
this( insets, lineColor, 1f );
|
||||
this( insets, lineColor, 1f, 0 );
|
||||
}
|
||||
|
||||
public FlatLineBorder( Insets insets, Color lineColor, float lineThickness ) {
|
||||
/** @since 2 */
|
||||
public FlatLineBorder( Insets insets, Color lineColor, float lineThickness, int arc ) {
|
||||
super( insets );
|
||||
this.lineColor = lineColor;
|
||||
this.lineThickness = lineThickness;
|
||||
this.arc = arc;
|
||||
}
|
||||
|
||||
public Color getLineColor() {
|
||||
@@ -56,13 +59,18 @@ public class FlatLineBorder
|
||||
return lineThickness;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public int getArc() {
|
||||
return arc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
FlatUIUtils.paintOutlinedComponent( g2, x, y, width, height,
|
||||
0, 0, 0, scale( getLineThickness() ), 0, null, getLineColor(), null );
|
||||
0, 0, 0, scale( getLineThickness() ), scale( getArc() ), null, getLineColor(), null );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import javax.swing.plaf.ListUI;
|
||||
public class FlatListCellBorder
|
||||
extends FlatLineBorder
|
||||
{
|
||||
protected boolean showCellFocusIndicator = UIManager.getBoolean( "List.showCellFocusIndicator" );
|
||||
/** @since 2 */ protected boolean showCellFocusIndicator = UIManager.getBoolean( "List.showCellFocusIndicator" );
|
||||
|
||||
private Component c;
|
||||
|
||||
@@ -113,7 +113,7 @@ public class FlatListCellBorder
|
||||
|
||||
/**
|
||||
* Border for selected cell that uses margins and paints focus indicator border
|
||||
* if enabled (List.showCellFocusIndicator=true) and exactly one item is selected.
|
||||
* if enabled (List.showCellFocusIndicator=true) and multiple items are selected.
|
||||
*/
|
||||
public static class Selected
|
||||
extends FlatListCellBorder
|
||||
@@ -125,7 +125,7 @@ public class FlatListCellBorder
|
||||
if( !showCellFocusIndicator )
|
||||
return;
|
||||
|
||||
// paint focus indicator border only if exactly one item is selected
|
||||
// paint focus indicator border only if multiple items are selected
|
||||
JList<?> list = (JList<?>) SwingUtilities.getAncestorOfClass( JList.class, c );
|
||||
if( list != null && list.getMinSelectionIndex() == list.getMaxSelectionIndex() )
|
||||
return;
|
||||
|
||||
@@ -78,9 +78,9 @@ public class FlatListUI
|
||||
@Styleable protected Color selectionInactiveForeground;
|
||||
|
||||
// for FlatListCellBorder
|
||||
@Styleable protected Insets cellMargins;
|
||||
@Styleable protected Color cellFocusColor;
|
||||
@Styleable protected boolean showCellFocusIndicator;
|
||||
/** @since 2 */ @Styleable protected Insets cellMargins;
|
||||
/** @since 2 */ @Styleable protected Color cellFocusColor;
|
||||
/** @since 2 */ @Styleable protected Boolean showCellFocusIndicator;
|
||||
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ public class FlatMenuBarBorder
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
if( !showBottomSeparator( c ) )
|
||||
return;
|
||||
|
||||
float lineHeight = scale( (float) 1 );
|
||||
FlatUIUtils.paintFilledRectangle( g, borderColor, x, y + height - lineHeight, width, lineHeight );
|
||||
}
|
||||
@@ -68,4 +71,9 @@ public class FlatMenuBarBorder
|
||||
insets.right = scale( margin.right );
|
||||
return insets;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected boolean showBottomSeparator( Component c ) {
|
||||
return !FlatMenuBarUI.useUnifiedBackground( c );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Window;
|
||||
@@ -179,20 +180,22 @@ public class FlatMenuBarUI
|
||||
protected Color getBackground( JComponent c ) {
|
||||
Color background = c.getBackground();
|
||||
|
||||
// paint background if opaque or if having custom background color
|
||||
if( c.isOpaque() || !(background instanceof UIResource) )
|
||||
// paint background if opaque
|
||||
if( c.isOpaque() )
|
||||
return background;
|
||||
|
||||
// paint background if menu bar is not the "main" menu bar
|
||||
// do not paint background if non-opaque and having custom background color
|
||||
if( !(background instanceof UIResource) )
|
||||
return null;
|
||||
|
||||
// paint background if menu bar is not the "main" menu bar (e.g. in internal frame)
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( c );
|
||||
if( rootPane == null || !(rootPane.getParent() instanceof Window) || rootPane.getJMenuBar() != c )
|
||||
return background;
|
||||
|
||||
// use parent background for unified title pane
|
||||
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
|
||||
if( UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
||||
FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() ) )
|
||||
background = FlatUIUtils.getParentBackground( c );
|
||||
if( useUnifiedBackground( c ) )
|
||||
background = FlatUIUtils.getParentBackground( c );
|
||||
|
||||
// paint background in full screen mode
|
||||
if( FlatUIUtils.isFullScreen( rootPane ) )
|
||||
@@ -202,6 +205,22 @@ public class FlatMenuBarUI
|
||||
return FlatRootPaneUI.isMenuBarEmbedded( rootPane ) ? null : background;
|
||||
}
|
||||
|
||||
/**@since 2 */
|
||||
static boolean useUnifiedBackground( Component c ) {
|
||||
// check whether:
|
||||
// - TitlePane.unifiedBackground is true and
|
||||
// - menu bar is the "main" menu bar and
|
||||
// - window has custom decorations enabled
|
||||
|
||||
JRootPane rootPane;
|
||||
// (not storing value of "TitlePane.unifiedBackground" in class to allow changing at runtime)
|
||||
return UIManager.getBoolean( "TitlePane.unifiedBackground" ) &&
|
||||
(rootPane = SwingUtilities.getRootPane( c )) != null &&
|
||||
rootPane.getParent() instanceof Window &&
|
||||
rootPane.getJMenuBar() == c &&
|
||||
FlatNativeWindowBorder.hasCustomDecoration( (Window) rootPane.getParent() );
|
||||
}
|
||||
|
||||
//---- class TakeFocus ----------------------------------------------------
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.formdev.flatlaf.ui;
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
@@ -32,6 +33,7 @@ import java.awt.event.KeyEvent;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.util.Map;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.KeyStroke;
|
||||
@@ -39,6 +41,7 @@ import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
import javax.swing.text.View;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.icons.FlatCheckBoxMenuItemIcon;
|
||||
import com.formdev.flatlaf.icons.FlatMenuArrowIcon;
|
||||
@@ -52,12 +55,15 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
/**
|
||||
* Renderer for menu items.
|
||||
*
|
||||
* @uiDefault MenuItem.verticallyAlignText boolean
|
||||
* @uiDefault MenuItem.minimumWidth int
|
||||
* @uiDefault MenuItem.minimumIconSize Dimension
|
||||
* @uiDefault MenuItem.textAcceleratorGap int
|
||||
* @uiDefault MenuItem.textNoAcceleratorGap int
|
||||
* @uiDefault MenuItem.acceleratorArrowGap int
|
||||
* @uiDefault MenuItem.checkBackground Color
|
||||
* @uiDefault MenuItem.checkMargins Insets
|
||||
* @uiDefault MenuItem.selectionType String null (default) or underline
|
||||
* @uiDefault MenuItem.underlineSelectionBackground Color
|
||||
* @uiDefault MenuItem.underlineSelectionCheckBackground Color
|
||||
* @uiDefault MenuItem.underlineSelectionColor Color
|
||||
@@ -67,12 +73,15 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
*/
|
||||
public class FlatMenuItemRenderer
|
||||
{
|
||||
private static final String KEY_MAX_ICONS_WIDTH = "FlatLaf.internal.FlatMenuItemRenderer.maxIconWidth";
|
||||
|
||||
protected final JMenuItem menuItem;
|
||||
protected Icon checkIcon;
|
||||
protected Icon arrowIcon;
|
||||
protected final Font acceleratorFont;
|
||||
@Styleable protected Font acceleratorFont;
|
||||
protected final String acceleratorDelimiter;
|
||||
|
||||
/** @since 2 */ @Styleable protected boolean verticallyAlignText = FlatUIUtils.getUIBoolean( "MenuItem.verticallyAlignText", true );
|
||||
@Styleable protected int minimumWidth = UIManager.getInt( "MenuItem.minimumWidth" );
|
||||
@Styleable protected Dimension minimumIconSize;
|
||||
@Styleable protected int textAcceleratorGap = FlatUIUtils.getUIInt( "MenuItem.textAcceleratorGap", 28 );
|
||||
@@ -405,11 +414,10 @@ debug*/
|
||||
return;
|
||||
|
||||
// center because the real icon may be smaller than dimension in iconRect
|
||||
int x = iconRect.x + centerOffset( iconRect.width, icon.getIconWidth() );
|
||||
int y = iconRect.y + centerOffset( iconRect.height, icon.getIconHeight() );
|
||||
|
||||
// paint
|
||||
icon.paintIcon( menuItem, g, x, y );
|
||||
icon.paintIcon( menuItem, g, iconRect.x, y );
|
||||
}
|
||||
|
||||
protected static void paintText( Graphics g, JMenuItem menuItem,
|
||||
@@ -444,6 +452,10 @@ debug*/
|
||||
htmlView.paint( HiDPIUtils.createGraphicsTextYCorrection( (Graphics2D) g ), textRect );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if either the menu item is armed (mouse over item)
|
||||
* or it is a {@code JMenu} and selected (shows submenu).
|
||||
*/
|
||||
protected static boolean isArmedOrSelected( JMenuItem menuItem ) {
|
||||
return menuItem.isArmed() || (menuItem instanceof JMenu && menuItem.isSelected());
|
||||
}
|
||||
@@ -474,6 +486,12 @@ debug*/
|
||||
return pressedIcon;
|
||||
}
|
||||
|
||||
if( isArmedOrSelected( menuItem ) ) {
|
||||
Icon selectedIcon = menuItem.getSelectedIcon();
|
||||
if( selectedIcon != null )
|
||||
return selectedIcon;
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
@@ -560,6 +578,44 @@ debug*/
|
||||
shiftGlyph = 0x21E7,
|
||||
commandGlyph = 0x2318;
|
||||
|
||||
/**
|
||||
* Calculates the maximum width of all menu item icons in the popup.
|
||||
*/
|
||||
private int getMaxIconsWidth() {
|
||||
if( !verticallyAlignText )
|
||||
return 0;
|
||||
|
||||
Container parent = menuItem.getParent();
|
||||
if( !(parent instanceof JComponent) )
|
||||
return 0;
|
||||
|
||||
int maxWidth = FlatClientProperties.clientPropertyInt( (JComponent) parent, KEY_MAX_ICONS_WIDTH, -1 );
|
||||
if( maxWidth >= 0 )
|
||||
return maxWidth;
|
||||
|
||||
maxWidth = 0;
|
||||
|
||||
for( Component c : parent.getComponents() ) {
|
||||
if( !(c instanceof JMenuItem) )
|
||||
continue;
|
||||
|
||||
Icon icon = ((JMenuItem)c).getIcon();
|
||||
if( icon != null )
|
||||
maxWidth = Math.max( maxWidth, icon.getIconWidth() );
|
||||
}
|
||||
|
||||
((JComponent)parent).putClientProperty( KEY_MAX_ICONS_WIDTH, maxWidth );
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
static void clearClientProperties( Component c ) {
|
||||
if( !(c instanceof JComponent) )
|
||||
return;
|
||||
|
||||
JComponent jc = (JComponent) c;
|
||||
jc.putClientProperty( FlatMenuItemRenderer.KEY_MAX_ICONS_WIDTH, null );
|
||||
}
|
||||
|
||||
//---- class MinSizeIcon --------------------------------------------------
|
||||
|
||||
private class MinSizeIcon
|
||||
@@ -574,6 +630,7 @@ debug*/
|
||||
@Override
|
||||
public int getIconWidth() {
|
||||
int iconWidth = (delegate != null) ? delegate.getIconWidth() : 0;
|
||||
iconWidth = Math.max( iconWidth, getMaxIconsWidth() );
|
||||
return Math.max( iconWidth, scale( minimumIconSize.width ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ public class FlatMenuItemUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||
renderer = null;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ public class FlatMenuUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||
renderer = null;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@@ -235,7 +235,8 @@ public class FlatNativeWindowBorder
|
||||
}
|
||||
|
||||
static void setTitleBarHeightAndHitTestSpots( Window window, int titleBarHeight,
|
||||
List<Rectangle> hitTestSpots, Rectangle appIconBounds )
|
||||
List<Rectangle> hitTestSpots, Rectangle appIconBounds, Rectangle minimizeButtonBounds,
|
||||
Rectangle maximizeButtonBounds, Rectangle closeButtonBounds )
|
||||
{
|
||||
if( canUseJBRCustomDecorations ) {
|
||||
JBRCustomDecorations.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots );
|
||||
@@ -245,9 +246,8 @@ public class FlatNativeWindowBorder
|
||||
if( !isSupported() )
|
||||
return;
|
||||
|
||||
nativeProvider.setTitleBarHeight( window, titleBarHeight );
|
||||
nativeProvider.setTitleBarHitTestSpots( window, hitTestSpots );
|
||||
nativeProvider.setTitleBarAppIconBounds( window, appIconBounds );
|
||||
nativeProvider.updateTitleBarInfo( window, titleBarHeight, hitTestSpots,
|
||||
appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
||||
}
|
||||
|
||||
static boolean showWindow( Window window, int cmd ) {
|
||||
@@ -268,7 +268,7 @@ public class FlatNativeWindowBorder
|
||||
try {
|
||||
/*
|
||||
Class<?> cls = Class.forName( "com.formdev.flatlaf.natives.jna.windows.FlatWindowsNativeWindowBorder" );
|
||||
Method m = cls.getMethod( "getInstance" );
|
||||
java.lang.reflect.Method m = cls.getMethod( "getInstance" );
|
||||
setNativeProvider( (Provider) m.invoke( null ) );
|
||||
*/
|
||||
setNativeProvider( FlatWindowsNativeWindowBorder.getInstance() );
|
||||
@@ -292,9 +292,9 @@ public class FlatNativeWindowBorder
|
||||
{
|
||||
boolean hasCustomDecoration( Window window );
|
||||
void setHasCustomDecoration( Window window, boolean hasCustomDecoration );
|
||||
void setTitleBarHeight( Window window, int titleBarHeight );
|
||||
void setTitleBarHitTestSpots( Window window, List<Rectangle> hitTestSpots );
|
||||
void setTitleBarAppIconBounds( Window window, Rectangle appIconBounds );
|
||||
void updateTitleBarInfo( Window window, int titleBarHeight, List<Rectangle> hitTestSpots,
|
||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||
Rectangle closeButtonBounds );
|
||||
|
||||
// commands for showWindow(); values must match Win32 API
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
|
||||
|
||||
@@ -19,21 +19,23 @@ package com.formdev.flatlaf.ui;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Insets;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRootPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicHTML;
|
||||
import javax.swing.plaf.basic.BasicOptionPaneUI;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
@@ -79,6 +81,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* <!-- FlatOptionPaneUI -->
|
||||
*
|
||||
* @uiDefault OptionPane.showIcon boolean
|
||||
* @uiDefault OptionPane.iconMessageGap int
|
||||
* @uiDefault OptionPane.messagePadding int
|
||||
* @uiDefault OptionPane.maxCharactersPerLine int
|
||||
@@ -88,6 +91,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public class FlatOptionPaneUI
|
||||
extends BasicOptionPaneUI
|
||||
{
|
||||
/** @since 2 */ protected boolean showIcon;
|
||||
protected int iconMessageGap;
|
||||
protected int messagePadding;
|
||||
protected int maxCharactersPerLine;
|
||||
@@ -102,6 +106,7 @@ public class FlatOptionPaneUI
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
showIcon = UIManager.getBoolean( "OptionPane.showIcon" );
|
||||
iconMessageGap = UIManager.getInt( "OptionPane.iconMessageGap" );
|
||||
messagePadding = UIManager.getInt( "OptionPane.messagePadding" );
|
||||
maxCharactersPerLine = UIManager.getInt( "OptionPane.maxCharactersPerLine" );
|
||||
@@ -116,6 +121,24 @@ public class FlatOptionPaneUI
|
||||
updateChildPanels( optionPane );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PropertyChangeListener createPropertyChangeListener() {
|
||||
PropertyChangeListener superListener = super.createPropertyChangeListener();
|
||||
return e -> {
|
||||
superListener.propertyChange( e );
|
||||
|
||||
// hide window title bar icon
|
||||
// (only if showIcon is false, otherwise the default behavior is used)
|
||||
if( !showIcon && "ancestor".equals( e.getPropertyName() ) && e.getNewValue() != null ) {
|
||||
JRootPane rootPane = SwingUtilities.getRootPane( optionPane );
|
||||
if( rootPane != null &&
|
||||
rootPane.getContentPane().getComponentCount() > 0 &&
|
||||
rootPane.getContentPane().getComponent( 0 ) == optionPane )
|
||||
rootPane.putClientProperty( FlatClientProperties.TITLE_BAR_SHOW_ICON, false );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getMinimumOptionPaneSize() {
|
||||
return UIScale.scale( super.getMinimumOptionPaneSize() );
|
||||
@@ -205,7 +228,7 @@ public class FlatOptionPaneUI
|
||||
// use non-UIResource borders to avoid that they are replaced when switching LaF
|
||||
Border border = panel.getBorder();
|
||||
if( border instanceof UIResource )
|
||||
panel.setBorder( new NonUIResourceBorder( border ) );
|
||||
panel.setBorder( FlatUIUtils.nonUIResource( border ) );
|
||||
}
|
||||
|
||||
if( child instanceof Container )
|
||||
@@ -231,31 +254,4 @@ public class FlatOptionPaneUI
|
||||
protected boolean getSizeButtonsToSameWidth() {
|
||||
return sameSizeButtons;
|
||||
}
|
||||
|
||||
//---- class NonUIResourceBorder ------------------------------------------
|
||||
|
||||
private static class NonUIResourceBorder
|
||||
implements Border
|
||||
{
|
||||
private final Border delegate;
|
||||
|
||||
NonUIResourceBorder( Border delegate ) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
delegate.paintBorder( c, g, x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c ) {
|
||||
return delegate.getBorderInsets( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBorderOpaque() {
|
||||
return delegate.isBorderOpaque();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,18 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.basic.BasicPanelUI;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
/**
|
||||
* Provides the Flat LaF UI delegate for {@link javax.swing.JPanel}.
|
||||
@@ -27,15 +36,118 @@ import javax.swing.plaf.basic.BasicPanelUI;
|
||||
*
|
||||
* @uiDefault Panel.font Font unused
|
||||
* @uiDefault Panel.background Color only used if opaque
|
||||
* @uiDefault Panel.foreground Color
|
||||
* @uiDefault Panel.foreground Color unused
|
||||
* @uiDefault Panel.border Border
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatPanelUI
|
||||
extends BasicPanelUI
|
||||
implements StyleableUI
|
||||
{
|
||||
// only used via styling (not in UI defaults)
|
||||
/** @since 2 */ @Styleable protected int arc = -1;
|
||||
|
||||
private final boolean shared;
|
||||
private PropertyChangeListener propertyChangeListener;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return FlatUIUtils.createSharedUI( FlatPanelUI.class, FlatPanelUI::new );
|
||||
return FlatUIUtils.canUseSharedUI( c )
|
||||
? FlatUIUtils.createSharedUI( FlatPanelUI.class, () -> new FlatPanelUI( true ) )
|
||||
: new FlatPanelUI( false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected FlatPanelUI( boolean shared ) {
|
||||
this.shared = shared;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
propertyChangeListener = FlatStylingSupport.createPropertyChangeListener(
|
||||
c, () -> stylePropertyChange( (JPanel) c ), null );
|
||||
c.addPropertyChangeListener( propertyChangeListener );
|
||||
|
||||
installStyle( (JPanel) c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallUI( JComponent c ) {
|
||||
super.uninstallUI( c );
|
||||
|
||||
c.removePropertyChangeListener( propertyChangeListener );
|
||||
propertyChangeListener = null;
|
||||
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
private void stylePropertyChange( JPanel c ) {
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( c ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
c.updateUI();
|
||||
} else
|
||||
installStyle( c );
|
||||
c.revalidate();
|
||||
c.repaint();
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installStyle( JPanel c ) {
|
||||
try {
|
||||
applyStyle( c, FlatStylingSupport.getResolvedStyle( c, "Panel" ) );
|
||||
} catch( RuntimeException ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void applyStyle( JPanel c, Object style ) {
|
||||
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style,
|
||||
(key, value) -> applyStyleProperty( c, key, value ) );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected Object applyStyleProperty( JPanel c, String key, Object value ) {
|
||||
return FlatStylingSupport.applyToAnnotatedObjectOrComponent( this, c, key, value );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( Graphics g, JComponent c ) {
|
||||
// fill background
|
||||
if( c.isOpaque() ) {
|
||||
int width = c.getWidth();
|
||||
int height = c.getHeight();
|
||||
int arc = (this.arc >= 0)
|
||||
? this.arc
|
||||
: ((c.getBorder() instanceof FlatLineBorder)
|
||||
? ((FlatLineBorder)c.getBorder()).getArc()
|
||||
: 0);
|
||||
|
||||
// fill background with parent color to avoid garbage in rounded corners
|
||||
if( arc > 0 )
|
||||
FlatUIUtils.paintParentBackground( g, c );
|
||||
|
||||
g.setColor( c.getBackground() );
|
||||
if( arc > 0 ) {
|
||||
// fill rounded rectangle if having rounded corners
|
||||
Object[] oldRenderingHints = FlatUIUtils.setRenderingHints( g );
|
||||
FlatUIUtils.paintComponentBackground( (Graphics2D) g, 0, 0, width, height,
|
||||
0, UIScale.scale( arc ) );
|
||||
FlatUIUtils.resetRenderingHints( g, oldRenderingHints );
|
||||
} else
|
||||
g.fillRect( 0, 0, width, height );
|
||||
}
|
||||
|
||||
paint( g, c );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import javax.swing.Action;
|
||||
import javax.swing.ActionMap;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
@@ -73,18 +74,25 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* @uiDefault PasswordField.echoChar character
|
||||
* @uiDefault PasswordField.showCapsLock boolean
|
||||
* @uiDefault PasswordField.showRevealButton boolean
|
||||
* @uiDefault PasswordField.capsLockIcon Icon
|
||||
* @uiDefault PasswordField.revealIcon Icon
|
||||
*
|
||||
* @author Karl Tauber
|
||||
*/
|
||||
public class FlatPasswordFieldUI
|
||||
extends FlatTextFieldUI
|
||||
{
|
||||
private Character echoChar;
|
||||
|
||||
@Styleable protected boolean showCapsLock;
|
||||
/** @since 2 */ @Styleable protected boolean showRevealButton;
|
||||
protected Icon capsLockIcon;
|
||||
/** @since 2 */ protected Icon revealIcon;
|
||||
|
||||
private KeyListener capsLockListener;
|
||||
private boolean capsLockIconShared = true;
|
||||
private JToggleButton revealButton;
|
||||
|
||||
public static ComponentUI createUI( JComponent c ) {
|
||||
return new FlatPasswordFieldUI();
|
||||
@@ -95,17 +103,33 @@ public class FlatPasswordFieldUI
|
||||
return "PasswordField";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
installRevealButton();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallUI( JComponent c ) {
|
||||
uninstallRevealButton();
|
||||
|
||||
super.uninstallUI( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
String prefix = getPropertyPrefix();
|
||||
Character echoChar = (Character) UIManager.get( prefix + ".echoChar" );
|
||||
echoChar = (Character) UIManager.get( prefix + ".echoChar" );
|
||||
if( echoChar != null )
|
||||
LookAndFeel.installProperty( getComponent(), "echoChar", echoChar );
|
||||
|
||||
showCapsLock = UIManager.getBoolean( "PasswordField.showCapsLock" );
|
||||
showRevealButton = UIManager.getBoolean( "PasswordField.showRevealButton" );
|
||||
capsLockIcon = UIManager.getIcon( "PasswordField.capsLockIcon" );
|
||||
revealIcon = UIManager.getIcon( "PasswordField.revealIcon" );
|
||||
capsLockIconShared = true;
|
||||
}
|
||||
|
||||
@@ -114,6 +138,7 @@ public class FlatPasswordFieldUI
|
||||
super.uninstallDefaults();
|
||||
|
||||
capsLockIcon = null;
|
||||
revealIcon = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,6 +193,18 @@ public class FlatPasswordFieldUI
|
||||
return "PasswordField";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyStyle( Object style ) {
|
||||
boolean oldShowRevealButton = showRevealButton;
|
||||
|
||||
super.applyStyle( style );
|
||||
|
||||
if( showRevealButton != oldShowRevealButton ) {
|
||||
uninstallRevealButton();
|
||||
installRevealButton();
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@Override
|
||||
protected Object applyStyleProperty( String key, Object value ) {
|
||||
@@ -236,4 +273,39 @@ public class FlatPasswordFieldUI
|
||||
return FlatUIUtils.isPermanentFocusOwner( c ) &&
|
||||
Toolkit.getDefaultToolkit().getLockingKeyState( KeyEvent.VK_CAPS_LOCK );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installRevealButton() {
|
||||
JTextComponent c = getComponent();
|
||||
if( showRevealButton ) {
|
||||
revealButton = createRevealButton();
|
||||
installLayout();
|
||||
c.add( revealButton );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected JToggleButton createRevealButton() {
|
||||
JToggleButton button = new JToggleButton( revealIcon );
|
||||
prepareLeadingOrTrailingComponent( button );
|
||||
button.addActionListener( e -> {
|
||||
LookAndFeel.installProperty( getComponent(), "echoChar", button.isSelected()
|
||||
? '\0'
|
||||
: (echoChar != null ? echoChar : '*'));
|
||||
} );
|
||||
return button;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void uninstallRevealButton() {
|
||||
if( revealButton != null ) {
|
||||
getComponent().remove( revealButton );
|
||||
revealButton = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent[] getTrailingComponents() {
|
||||
return new JComponent[] { trailingComponent, revealButton, clearButton };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,10 @@ public class FlatPopupFactory
|
||||
popupWindow.getGraphicsConfiguration() == owner.getGraphicsConfiguration() )
|
||||
return popup;
|
||||
|
||||
// avoid endless loop (should newer happen; PopupFactory cache size is 5)
|
||||
if( ++count > 10 )
|
||||
return popup;
|
||||
|
||||
// remove contents component from popup window
|
||||
if( popupWindow instanceof JWindow )
|
||||
((JWindow)popupWindow).getContentPane().removeAll();
|
||||
@@ -128,10 +132,6 @@ public class FlatPopupFactory
|
||||
// dispose unused popup
|
||||
// (do not invoke popup.hide() because this would cache the popup window)
|
||||
popupWindow.dispose();
|
||||
|
||||
// avoid endless loop (should newer happen; PopupFactory cache size is 5)
|
||||
if( ++count > 10 )
|
||||
return popup;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.LayoutManager;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicPopupMenuUI;
|
||||
import javax.swing.plaf.basic.DefaultMenuLayout;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
|
||||
@@ -64,6 +70,15 @@ public class FlatPopupMenuUI
|
||||
borderShared = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installDefaults() {
|
||||
super.installDefaults();
|
||||
|
||||
LayoutManager layout = popupMenu.getLayout();
|
||||
if( layout == null || layout instanceof UIResource )
|
||||
popupMenu.setLayout( new FlatMenuLayout( popupMenu, BoxLayout.Y_AXIS ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installListeners() {
|
||||
super.installListeners();
|
||||
@@ -106,4 +121,21 @@ public class FlatPopupMenuUI
|
||||
public Map<String, Class<?>> getStyleableInfos( JComponent c ) {
|
||||
return FlatStylingSupport.getAnnotatedStyleableInfos( this, popupMenu.getBorder() );
|
||||
}
|
||||
|
||||
//---- class FlatMenuLayout -----------------------------------------------
|
||||
|
||||
protected static class FlatMenuLayout
|
||||
extends DefaultMenuLayout
|
||||
{
|
||||
public FlatMenuLayout( Container target, int axis ) {
|
||||
super( target, axis );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize( Container target ) {
|
||||
FlatMenuItemRenderer.clearClientProperties( target );
|
||||
|
||||
return super.preferredLayoutSize( target );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ public class FlatRadioButtonMenuItemUI
|
||||
protected void uninstallDefaults() {
|
||||
super.uninstallDefaults();
|
||||
|
||||
FlatMenuItemRenderer.clearClientProperties( menuItem.getParent() );
|
||||
renderer = null;
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ public class FlatRadioButtonUI
|
||||
case FlatClientProperties.STYLE_CLASS:
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( b ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes applyStyle() from installUI()
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
b.updateUI();
|
||||
} else
|
||||
installStyle( b );
|
||||
|
||||
@@ -66,6 +66,9 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* <!-- FlatWindowResizer -->
|
||||
*
|
||||
* @uiDefault RootPane.font Font unused
|
||||
* @uiDefault RootPane.background Color
|
||||
* @uiDefault RootPane.foreground Color unused
|
||||
* @uiDefault RootPane.borderDragThickness int
|
||||
* @uiDefault RootPane.cornerDragWidth int
|
||||
* @uiDefault RootPane.honorFrameMinimumSizeOnResize boolean
|
||||
@@ -126,8 +129,23 @@ public class FlatRootPaneUI
|
||||
protected void installDefaults( JRootPane c ) {
|
||||
super.installDefaults( c );
|
||||
|
||||
// Give the root pane useful background, foreground and font.
|
||||
// Background is used for title bar and menu bar if native window decorations
|
||||
// and unified background are enabled.
|
||||
// Foreground and font are usually not used, but set for completeness.
|
||||
// Not using LookAndFeel.installColorsAndFont() here because it will not work
|
||||
// because the properties are null by default but inherit non-null values from parent.
|
||||
if( !c.isBackgroundSet() || c.getBackground() instanceof UIResource )
|
||||
c.setBackground( UIManager.getColor( "RootPane.background" ) );
|
||||
if( !c.isForegroundSet() || c.getForeground() instanceof UIResource )
|
||||
c.setForeground( UIManager.getColor( "RootPane.foreground" ) );
|
||||
if( !c.isFontSet() || c.getFont() instanceof UIResource )
|
||||
c.setFont( UIManager.getFont( "RootPane.font" ) );
|
||||
|
||||
// Update background color of JFrame or JDialog parent to avoid bad border
|
||||
// on HiDPI screens when switching from light to dark Laf.
|
||||
// Window background color is also used in native window decorations
|
||||
// to fill background when window is initially shown or when resizing window.
|
||||
// The background of JFrame is initialized in JFrame.frameInit() and
|
||||
// the background of JDialog in JDialog.dialogInit(),
|
||||
// but it was not updated when switching Laf.
|
||||
@@ -313,6 +331,11 @@ public class FlatRootPaneUI
|
||||
}
|
||||
break;
|
||||
|
||||
case FlatClientProperties.TITLE_BAR_SHOW_ICON:
|
||||
if( titlePane != null )
|
||||
titlePane.updateIcon();
|
||||
break;
|
||||
|
||||
case FlatClientProperties.TITLE_BAR_BACKGROUND:
|
||||
case FlatClientProperties.TITLE_BAR_FOREGROUND:
|
||||
if( titlePane != null )
|
||||
|
||||
@@ -47,7 +47,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* <!-- BasicScrollBarUI -->
|
||||
*
|
||||
* @uiDefault ScrollBar.background Color
|
||||
* @uiDefault ScrollBar.foreground Color
|
||||
* @uiDefault ScrollBar.foreground Color unused
|
||||
* @uiDefault ScrollBar.track Color
|
||||
* @uiDefault ScrollBar.thumb Color
|
||||
* @uiDefault ScrollBar.width int
|
||||
|
||||
@@ -125,7 +125,7 @@ public class FlatSeparatorUI
|
||||
private void stylePropertyChange( JSeparator s ) {
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( s ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes applyStyle() from installUI()
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
s.updateUI();
|
||||
} else
|
||||
installStyle( s );
|
||||
|
||||
@@ -71,7 +71,7 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
||||
* @uiDefault Spinner.disabledBackground Color
|
||||
* @uiDefault Spinner.disabledForeground Color
|
||||
* @uiDefault Spinner.focusedBackground Color optional
|
||||
* @uiDefault Spinner.buttonBackground Color
|
||||
* @uiDefault Spinner.buttonBackground Color optional
|
||||
* @uiDefault Spinner.buttonSeparatorWidth int or float optional; defaults to Component.borderWidth
|
||||
* @uiDefault Spinner.buttonSeparatorColor Color optional
|
||||
* @uiDefault Spinner.buttonDisabledSeparatorColor Color optional
|
||||
@@ -385,7 +385,7 @@ public class FlatSpinnerUI
|
||||
boolean isLeftToRight = spinner.getComponentOrientation().isLeftToRight();
|
||||
|
||||
// paint arrow buttons background
|
||||
if( enabled ) {
|
||||
if( enabled && buttonBackground != null ) {
|
||||
g2.setColor( buttonBackground );
|
||||
Shape oldClip = g2.getClip();
|
||||
if( isLeftToRight )
|
||||
@@ -398,7 +398,7 @@ public class FlatSpinnerUI
|
||||
|
||||
// paint vertical line between value and arrow buttons
|
||||
Color separatorColor = enabled ? buttonSeparatorColor : buttonDisabledSeparatorColor;
|
||||
if( separatorColor != null ) {
|
||||
if( separatorColor != null && buttonSeparatorWidth > 0 ) {
|
||||
g2.setColor( separatorColor );
|
||||
float lw = scale( buttonSeparatorWidth );
|
||||
float lx = isLeftToRight ? arrowX : arrowX + arrowWidth - lw;
|
||||
|
||||
@@ -40,6 +40,8 @@ import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.ContainerEvent;
|
||||
import java.awt.event.ContainerListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
@@ -134,12 +136,15 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TabbedPane.maximumTabWidth int optional
|
||||
* @uiDefault TabbedPane.tabHeight int
|
||||
* @uiDefault TabbedPane.tabSelectionHeight int
|
||||
* @uiDefault TabbedPane.cardTabSelectionHeight int
|
||||
* @uiDefault TabbedPane.contentSeparatorHeight int
|
||||
* @uiDefault TabbedPane.showTabSeparators boolean
|
||||
* @uiDefault TabbedPane.tabSeparatorsFullHeight boolean
|
||||
* @uiDefault TabbedPane.hasFullBorder boolean
|
||||
* @uiDefault TabbedPane.activeTabBorder boolean
|
||||
*
|
||||
* @uiDefault TabbedPane.tabLayoutPolicy String wrap (default) or scroll
|
||||
* @uiDefault TabbedPane.tabType String underlined (default) or card
|
||||
* @uiDefault TabbedPane.tabsPopupPolicy String never or asNeeded (default)
|
||||
* @uiDefault TabbedPane.scrollButtonsPolicy String never, asNeeded or asNeededSingle (default)
|
||||
* @uiDefault TabbedPane.scrollButtonsPlacement String both (default) or trailing
|
||||
@@ -165,6 +170,10 @@ public class FlatTabbedPaneUI
|
||||
extends BasicTabbedPaneUI
|
||||
implements StyleableUI
|
||||
{
|
||||
// tab type
|
||||
/** @since 2 */ protected static final int TAB_TYPE_UNDERLINED = 0;
|
||||
/** @since 2 */ protected static final int TAB_TYPE_CARD = 1;
|
||||
|
||||
// tabs popup policy / scroll arrows policy
|
||||
protected static final int NEVER = 0;
|
||||
// protected static final int ALWAYS = 1;
|
||||
@@ -200,12 +209,14 @@ public class FlatTabbedPaneUI
|
||||
@Styleable protected int maximumTabWidth;
|
||||
@Styleable protected int tabHeight;
|
||||
@Styleable protected int tabSelectionHeight;
|
||||
/** @since 2 */ @Styleable protected int cardTabSelectionHeight;
|
||||
@Styleable protected int contentSeparatorHeight;
|
||||
@Styleable protected boolean showTabSeparators;
|
||||
@Styleable protected boolean tabSeparatorsFullHeight;
|
||||
@Styleable protected boolean hasFullBorder;
|
||||
@Styleable protected boolean tabsOpaque = true;
|
||||
|
||||
@Styleable(type=String.class) private int tabType;
|
||||
@Styleable(type=String.class) private int tabsPopupPolicy;
|
||||
@Styleable(type=String.class) private int scrollButtonsPolicy;
|
||||
@Styleable(type=String.class) private int scrollButtonsPlacement;
|
||||
@@ -318,12 +329,14 @@ public class FlatTabbedPaneUI
|
||||
maximumTabWidth = UIManager.getInt( "TabbedPane.maximumTabWidth" );
|
||||
tabHeight = UIManager.getInt( "TabbedPane.tabHeight" );
|
||||
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
|
||||
cardTabSelectionHeight = UIManager.getInt( "TabbedPane.cardTabSelectionHeight" );
|
||||
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
|
||||
showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" );
|
||||
tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" );
|
||||
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
|
||||
tabsOpaque = UIManager.getBoolean( "TabbedPane.tabsOpaque" );
|
||||
|
||||
tabType = parseTabType( UIManager.getString( "TabbedPane.tabType" ) );
|
||||
tabsPopupPolicy = parseTabsPopupPolicy( UIManager.getString( "TabbedPane.tabsPopupPolicy" ) );
|
||||
scrollButtonsPolicy = parseScrollButtonsPolicy( UIManager.getString( "TabbedPane.scrollButtonsPolicy" ) );
|
||||
scrollButtonsPlacement = parseScrollButtonsPlacement( UIManager.getString( "TabbedPane.scrollButtonsPlacement" ) );
|
||||
@@ -560,6 +573,13 @@ public class FlatTabbedPaneUI
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FocusListener createFocusListener() {
|
||||
Handler handler = getHandler();
|
||||
handler.focusDelegate = super.createFocusListener();
|
||||
return handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LayoutManager createLayoutManager() {
|
||||
if( tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT )
|
||||
@@ -618,6 +638,7 @@ public class FlatTabbedPaneUI
|
||||
|
||||
if( value instanceof String ) {
|
||||
switch( key ) {
|
||||
case "tabType": value = parseTabType( (String) value ); break;
|
||||
case "tabsPopupPolicy": value = parseTabsPopupPolicy( (String) value ); break;
|
||||
case "scrollButtonsPolicy": value = parseScrollButtonsPolicy( (String) value ); break;
|
||||
case "scrollButtonsPlacement": value = parseScrollButtonsPlacement( (String) value ); break;
|
||||
@@ -707,8 +728,25 @@ public class FlatTabbedPaneUI
|
||||
return;
|
||||
|
||||
Rectangle r = getTabBounds( tabPane, tabIndex );
|
||||
if( r != null )
|
||||
tabPane.repaint( r );
|
||||
if( r == null )
|
||||
return;
|
||||
|
||||
// increase size of repaint region to include part of content border
|
||||
if( contentSeparatorHeight > 0 &&
|
||||
getTabType() == TAB_TYPE_CARD &&
|
||||
clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_CONTENT_SEPARATOR, true ) )
|
||||
{
|
||||
int sh = scale( contentSeparatorHeight );
|
||||
switch( tabPane.getTabPlacement() ) {
|
||||
default:
|
||||
case TOP: r.height += sh; break;
|
||||
case BOTTOM: r.height += sh; r.y -= sh; break;
|
||||
case LEFT: r.width += sh; break;
|
||||
case RIGHT: r.width += sh; r.x -= sh; break;
|
||||
}
|
||||
}
|
||||
|
||||
tabPane.repaint( r );
|
||||
}
|
||||
|
||||
private boolean inCalculateEqual;
|
||||
@@ -1045,16 +1083,21 @@ public class FlatTabbedPaneUI
|
||||
int x, int y, int w, int h, boolean isSelected )
|
||||
{
|
||||
// paint tab background
|
||||
Color background = getTabBackground( tabPlacement, tabIndex, isSelected );
|
||||
g.setColor( FlatUIUtils.deriveColor( background, tabPane.getBackground() ) );
|
||||
g.fillRect( x, y, w, h );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected Color getTabBackground( int tabPlacement, int tabIndex, boolean isSelected ) {
|
||||
boolean enabled = tabPane.isEnabled();
|
||||
Color background = enabled && tabPane.isEnabledAt( tabIndex ) && getRolloverTab() == tabIndex
|
||||
return enabled && tabPane.isEnabledAt( tabIndex ) && getRolloverTab() == tabIndex
|
||||
? hoverColor
|
||||
: (enabled && isSelected && FlatUIUtils.isPermanentFocusOwner( tabPane )
|
||||
? focusColor
|
||||
: (selectedBackground != null && enabled && isSelected
|
||||
? selectedBackground
|
||||
: tabPane.getBackgroundAt( tabIndex )));
|
||||
g.setColor( FlatUIUtils.deriveColor( background, tabPane.getBackground() ) );
|
||||
g.fillRect( x, y, w, h );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1064,7 +1107,62 @@ public class FlatTabbedPaneUI
|
||||
// paint tab separators
|
||||
if( clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators ) &&
|
||||
!isLastInRun( tabIndex ) )
|
||||
paintTabSeparator( g, tabPlacement, x, y, w, h );
|
||||
{
|
||||
if( getTabType() == TAB_TYPE_CARD ) {
|
||||
// some separators need to be omitted if selected tab is painted as card
|
||||
int selectedIndex = tabPane.getSelectedIndex();
|
||||
if( tabIndex != selectedIndex - 1 && tabIndex != selectedIndex )
|
||||
paintTabSeparator( g, tabPlacement, x, y, w, h );
|
||||
} else
|
||||
paintTabSeparator( g, tabPlacement, x, y, w, h );
|
||||
}
|
||||
|
||||
// paint active tab border
|
||||
if( isSelected && getTabType() == TAB_TYPE_CARD )
|
||||
paintCardTabBorder( g, tabPlacement, tabIndex, x, y, w, h );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void paintCardTabBorder( Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h ) {
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
|
||||
float borderWidth = scale( (float) contentSeparatorHeight );
|
||||
g.setColor( (tabSeparatorColor != null) ? tabSeparatorColor : contentAreaColor );
|
||||
|
||||
switch( tabPlacement ) {
|
||||
default:
|
||||
case TOP:
|
||||
case BOTTOM:
|
||||
// paint left and right tab border
|
||||
g2.fill( new Rectangle2D.Float( x, y, borderWidth, h ) );
|
||||
g2.fill( new Rectangle2D.Float( x + w - borderWidth, y, borderWidth, h ) );
|
||||
break;
|
||||
case LEFT:
|
||||
case RIGHT:
|
||||
// paint top and bottom tab border
|
||||
g2.fill( new Rectangle2D.Float( x, y, w, borderWidth ) );
|
||||
g2.fill( new Rectangle2D.Float( x, y + h - borderWidth, w, borderWidth ) );
|
||||
break;
|
||||
}
|
||||
|
||||
if( cardTabSelectionHeight <= 0 ) {
|
||||
// if there is no tab selection indicator, paint a top border as well
|
||||
switch( tabPlacement ) {
|
||||
default:
|
||||
case TOP:
|
||||
g2.fill( new Rectangle2D.Float( x, y, w, borderWidth ) );
|
||||
break;
|
||||
case BOTTOM:
|
||||
g2.fill( new Rectangle2D.Float( x, y + h - borderWidth, w, borderWidth ) );
|
||||
break;
|
||||
case LEFT:
|
||||
g2.fill( new Rectangle2D.Float( x, y, borderWidth, h ) );
|
||||
break;
|
||||
case RIGHT:
|
||||
g2.fill( new Rectangle2D.Float( x + w - borderWidth, y, borderWidth, h ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintTabCloseButton( Graphics g, int tabIndex, int x, int y, int w, int h ) {
|
||||
@@ -1110,26 +1208,30 @@ public class FlatTabbedPaneUI
|
||||
g.setColor( tabPane.isEnabled() ? underlineColor : disabledUnderlineColor );
|
||||
|
||||
// paint underline selection
|
||||
boolean atBottom = (getTabType() != TAB_TYPE_CARD);
|
||||
Insets contentInsets = getContentBorderInsets( tabPlacement );
|
||||
int tabSelectionHeight = scale( this.tabSelectionHeight );
|
||||
int tabSelectionHeight = scale( atBottom ? this.tabSelectionHeight : cardTabSelectionHeight );
|
||||
int sx, sy;
|
||||
switch( tabPlacement ) {
|
||||
case TOP:
|
||||
default:
|
||||
int sy = y + h + contentInsets.top - tabSelectionHeight;
|
||||
sy = atBottom ? (y + h + contentInsets.top - tabSelectionHeight) : y;
|
||||
g.fillRect( x, sy, w, tabSelectionHeight );
|
||||
break;
|
||||
|
||||
case BOTTOM:
|
||||
g.fillRect( x, y - contentInsets.bottom, w, tabSelectionHeight );
|
||||
sy = atBottom ? (y - contentInsets.bottom) : (y + h - tabSelectionHeight);
|
||||
g.fillRect( x, sy, w, tabSelectionHeight );
|
||||
break;
|
||||
|
||||
case LEFT:
|
||||
int sx = x + w + contentInsets.left - tabSelectionHeight;
|
||||
sx = atBottom ? (x + w + contentInsets.left - tabSelectionHeight) : x;
|
||||
g.fillRect( sx, y, tabSelectionHeight, h );
|
||||
break;
|
||||
|
||||
case RIGHT:
|
||||
g.fillRect( x - contentInsets.right, y, tabSelectionHeight, h );
|
||||
sx = atBottom ? (x - contentInsets.right) : (x + w - tabSelectionHeight);
|
||||
g.fillRect( sx, y, tabSelectionHeight, h );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1141,6 +1243,7 @@ public class FlatTabbedPaneUI
|
||||
* - paint full border (if enabled)
|
||||
* - not invoking paintContentBorder*Edge() methods
|
||||
* - repaint selection
|
||||
* - painting active tab border style
|
||||
*/
|
||||
@Override
|
||||
protected void paintContentBorder( Graphics g, int tabPlacement, int selectedIndex ) {
|
||||
@@ -1189,12 +1292,49 @@ public class FlatTabbedPaneUI
|
||||
Insets ci = new Insets( 0, 0, 0, 0 );
|
||||
rotateInsets( hasFullBorder ? new Insets( sh, sh, sh, sh ) : new Insets( sh, 0, 0, 0 ), ci, tabPlacement );
|
||||
|
||||
// paint content separator or full border
|
||||
g.setColor( contentAreaColor );
|
||||
// create path for content separator or full border
|
||||
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||
path.append( new Rectangle2D.Float( x, y, w, h ), false );
|
||||
path.append( new Rectangle2D.Float( x + (ci.left / 100f), y + (ci.top / 100f),
|
||||
w - (ci.left / 100f) - (ci.right / 100f), h - (ci.top / 100f) - (ci.bottom / 100f) ), false );
|
||||
|
||||
// add gap for selected tab to path
|
||||
if( getTabType() == TAB_TYPE_CARD ) {
|
||||
float csh = scale( (float) contentSeparatorHeight );
|
||||
|
||||
Rectangle tabRect = getTabBounds( tabPane, selectedIndex );
|
||||
Rectangle2D.Float innerTabRect = new Rectangle2D.Float( tabRect.x + csh, tabRect.y + csh,
|
||||
tabRect.width - (csh * 2), tabRect.height - (csh * 2) );
|
||||
|
||||
// Ensure that the separator outside the tabViewport is present (doesn't get cutoff by the active tab)
|
||||
// If left unsolved the active tab is "visible" in the separator (the gap) even when outside the viewport
|
||||
if( tabViewport != null )
|
||||
Rectangle2D.intersect( tabViewport.getBounds(), innerTabRect, innerTabRect );
|
||||
|
||||
Rectangle2D.Float gap = null;
|
||||
if( isHorizontalTabPlacement() ) {
|
||||
if( innerTabRect.width > 0 ) {
|
||||
float y2 = (tabPlacement == TOP) ? y : y + h - csh;
|
||||
gap = new Rectangle2D.Float( innerTabRect.x, y2, innerTabRect.width, csh );
|
||||
}
|
||||
} else {
|
||||
if( innerTabRect.height > 0 ) {
|
||||
float x2 = (tabPlacement == LEFT) ? x : x + w - csh;
|
||||
gap = new Rectangle2D.Float( x2, innerTabRect.y, csh, innerTabRect.height );
|
||||
}
|
||||
}
|
||||
|
||||
if( gap != null ) {
|
||||
path.append( gap, false );
|
||||
|
||||
// fill gap in case that the tab is colored (e.g. focused or hover)
|
||||
g.setColor( getTabBackground( tabPlacement, selectedIndex, true ) );
|
||||
((Graphics2D)g).fill( gap );
|
||||
}
|
||||
}
|
||||
|
||||
// paint content separator or full border
|
||||
g.setColor( contentAreaColor );
|
||||
((Graphics2D)g).fill( path );
|
||||
|
||||
// repaint selection in scroll-tab-layout because it may be painted before
|
||||
@@ -1399,6 +1539,15 @@ public class FlatTabbedPaneUI
|
||||
clientPropertyBoolean( tabPane, TABBED_PANE_HIDE_TAB_AREA_WITH_ONE_TAB, hideTabAreaWithOneTab );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected int getTabType() {
|
||||
Object value = tabPane.getClientProperty( TABBED_PANE_TAB_TYPE );
|
||||
|
||||
return (value instanceof String)
|
||||
? parseTabType( (String) value )
|
||||
: tabType;
|
||||
}
|
||||
|
||||
protected int getTabsPopupPolicy() {
|
||||
Object value = tabPane.getClientProperty( TABBED_PANE_TABS_POPUP_POLICY );
|
||||
|
||||
@@ -1451,6 +1600,18 @@ public class FlatTabbedPaneUI
|
||||
: tabWidthMode;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected static int parseTabType( String str ) {
|
||||
if( str == null )
|
||||
return TAB_TYPE_UNDERLINED;
|
||||
|
||||
switch( str ) {
|
||||
default:
|
||||
case TABBED_PANE_TAB_TYPE_UNDERLINED: return TAB_TYPE_UNDERLINED;
|
||||
case TABBED_PANE_TAB_TYPE_CARD: return TAB_TYPE_CARD;
|
||||
}
|
||||
}
|
||||
|
||||
protected static int parseTabsPopupPolicy( String str ) {
|
||||
if( str == null )
|
||||
return AS_NEEDED;
|
||||
@@ -2264,11 +2425,12 @@ public class FlatTabbedPaneUI
|
||||
|
||||
private class Handler
|
||||
implements MouseListener, MouseMotionListener, PropertyChangeListener,
|
||||
ChangeListener, ComponentListener, ContainerListener
|
||||
ChangeListener, ComponentListener, ContainerListener, FocusListener
|
||||
{
|
||||
MouseListener mouseDelegate;
|
||||
PropertyChangeListener propertyChangeDelegate;
|
||||
ChangeListener changeDelegate;
|
||||
FocusListener focusDelegate;
|
||||
|
||||
private final PropertyChangeListener contentListener = this::contentPropertyChange;
|
||||
|
||||
@@ -2438,6 +2600,10 @@ public class FlatTabbedPaneUI
|
||||
break;
|
||||
|
||||
case TABBED_PANE_SHOW_TAB_SEPARATORS:
|
||||
case TABBED_PANE_TAB_TYPE:
|
||||
tabPane.repaint();
|
||||
break;
|
||||
|
||||
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
|
||||
case TABBED_PANE_HAS_FULL_BORDER:
|
||||
case TABBED_PANE_HIDE_TAB_AREA_WITH_ONE_TAB:
|
||||
@@ -2536,6 +2702,20 @@ public class FlatTabbedPaneUI
|
||||
if( !(c instanceof UIResource) )
|
||||
c.removePropertyChangeListener( contentListener );
|
||||
}
|
||||
|
||||
//---- interface FocusListener ----
|
||||
|
||||
@Override
|
||||
public void focusGained( FocusEvent e ) {
|
||||
focusDelegate.focusGained( e );
|
||||
repaintTab( tabPane.getSelectedIndex() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost( FocusEvent e ) {
|
||||
focusDelegate.focusLost( e );
|
||||
repaintTab( tabPane.getSelectedIndex() );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatTabbedPaneLayout -----------------------------------------
|
||||
|
||||
@@ -37,7 +37,7 @@ import javax.swing.plaf.TableUI;
|
||||
public class FlatTableCellBorder
|
||||
extends FlatLineBorder
|
||||
{
|
||||
protected boolean showCellFocusIndicator = UIManager.getBoolean( "Table.showCellFocusIndicator" );
|
||||
/** @since 2 */ protected boolean showCellFocusIndicator = UIManager.getBoolean( "Table.showCellFocusIndicator" );
|
||||
|
||||
private Component c;
|
||||
|
||||
|
||||
@@ -141,8 +141,8 @@ public class FlatTableHeaderBorder
|
||||
protected boolean hideTrailingVerticalLine( JTableHeader header ) {
|
||||
if( header.getUI() instanceof FlatTableHeaderUI ) {
|
||||
FlatTableHeaderUI ui = (FlatTableHeaderUI) header.getUI();
|
||||
if( ui.showTrailingVerticalLine )
|
||||
return false;
|
||||
if( ui.showTrailingVerticalLine != null )
|
||||
return !ui.showTrailingVerticalLine;
|
||||
}
|
||||
|
||||
if( showTrailingVerticalLine )
|
||||
|
||||
@@ -84,14 +84,14 @@ public class FlatTableHeaderUI
|
||||
@Styleable(type=String.class) protected int sortIconPosition;
|
||||
|
||||
// for FlatTableHeaderBorder
|
||||
@Styleable protected Insets cellMargins;
|
||||
@Styleable protected Color separatorColor;
|
||||
/** @since 2 */ @Styleable protected boolean showTrailingVerticalLine;
|
||||
/** @since 2 */ @Styleable protected Insets cellMargins;
|
||||
/** @since 2 */ @Styleable protected Color separatorColor;
|
||||
/** @since 2 */ @Styleable protected Boolean showTrailingVerticalLine;
|
||||
|
||||
// for FlatAscendingSortIcon and FlatDescendingSortIcon
|
||||
// (needs to be public because icon classes are in another package)
|
||||
@Styleable public String arrowType;
|
||||
@Styleable public Color sortIconColor;
|
||||
/** @since 2 */ @Styleable public String arrowType;
|
||||
/** @since 2 */ @Styleable public Color sortIconColor;
|
||||
|
||||
private PropertyChangeListener propertyChangeListener;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
@@ -108,9 +108,9 @@ public class FlatTableUI
|
||||
@Styleable protected Color selectionInactiveForeground;
|
||||
|
||||
// for FlatTableCellBorder
|
||||
@Styleable protected Insets cellMargins;
|
||||
@Styleable protected Color cellFocusColor;
|
||||
@Styleable protected boolean showCellFocusIndicator;
|
||||
/** @since 2 */ @Styleable protected Insets cellMargins;
|
||||
/** @since 2 */ @Styleable protected Color cellFocusColor;
|
||||
/** @since 2 */ @Styleable protected Boolean showCellFocusIndicator;
|
||||
|
||||
private boolean oldShowHorizontalLines;
|
||||
private boolean oldShowVerticalLines;
|
||||
|
||||
@@ -19,29 +19,40 @@ package com.formdev.flatlaf.ui;
|
||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||
import static com.formdev.flatlaf.util.UIScale.scale;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.LayoutManager2;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.JToolBar;
|
||||
import javax.swing.LookAndFeel;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicTextFieldUI;
|
||||
import javax.swing.text.Caret;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
|
||||
@@ -94,6 +105,12 @@ public class FlatTextFieldUI
|
||||
|
||||
/** @since 2 */ @Styleable protected Icon leadingIcon;
|
||||
/** @since 2 */ @Styleable protected Icon trailingIcon;
|
||||
/** @since 2 */ protected JComponent leadingComponent;
|
||||
/** @since 2 */ protected JComponent trailingComponent;
|
||||
/** @since 2 */ protected JComponent clearButton;
|
||||
|
||||
// only used via styling (not in UI defaults, but has likewise client properties)
|
||||
/** @since 2 */ @Styleable protected boolean showClearButton;
|
||||
|
||||
private Color oldDisabledBackground;
|
||||
private Color oldInactiveBackground;
|
||||
@@ -101,6 +118,7 @@ public class FlatTextFieldUI
|
||||
private Insets defaultMargin;
|
||||
|
||||
private FocusListener focusListener;
|
||||
private DocumentListener documentListener;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
private AtomicBoolean borderShared;
|
||||
|
||||
@@ -115,11 +133,19 @@ public class FlatTextFieldUI
|
||||
leadingIcon = clientProperty( c, TEXT_FIELD_LEADING_ICON, null, Icon.class );
|
||||
trailingIcon = clientProperty( c, TEXT_FIELD_TRAILING_ICON, null, Icon.class );
|
||||
|
||||
installLeadingComponent();
|
||||
installTrailingComponent();
|
||||
installClearButton();
|
||||
|
||||
installStyle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallUI( JComponent c ) {
|
||||
uninstallLeadingComponent();
|
||||
uninstallTrailingComponent();
|
||||
uninstallClearButton();
|
||||
|
||||
super.uninstallUI( c );
|
||||
|
||||
leadingIcon = null;
|
||||
@@ -181,6 +207,11 @@ public class FlatTextFieldUI
|
||||
|
||||
getComponent().removeFocusListener( focusListener );
|
||||
focusListener = null;
|
||||
|
||||
if( documentListener != null ) {
|
||||
getComponent().getDocument().removeDocumentListener( documentListener );
|
||||
documentListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -225,9 +256,61 @@ public class FlatTextFieldUI
|
||||
trailingIcon = (e.getNewValue() instanceof Icon) ? (Icon) e.getNewValue() : null;
|
||||
c.repaint();
|
||||
break;
|
||||
|
||||
case TEXT_FIELD_LEADING_COMPONENT:
|
||||
uninstallLeadingComponent();
|
||||
installLeadingComponent();
|
||||
c.revalidate();
|
||||
c.repaint();
|
||||
break;
|
||||
|
||||
case TEXT_FIELD_TRAILING_COMPONENT:
|
||||
uninstallTrailingComponent();
|
||||
installTrailingComponent();
|
||||
c.revalidate();
|
||||
c.repaint();
|
||||
break;
|
||||
|
||||
case TEXT_FIELD_SHOW_CLEAR_BUTTON:
|
||||
uninstallClearButton();
|
||||
installClearButton();
|
||||
c.revalidate();
|
||||
c.repaint();
|
||||
break;
|
||||
|
||||
case "enabled":
|
||||
case "editable":
|
||||
updateClearButton();
|
||||
break;
|
||||
|
||||
case "document":
|
||||
if( documentListener != null ) {
|
||||
if( e.getOldValue() instanceof Document )
|
||||
((Document)e.getOldValue()).removeDocumentListener( documentListener );
|
||||
if( e.getNewValue() instanceof Document )
|
||||
((Document)e.getNewValue()).addDocumentListener( documentListener );
|
||||
|
||||
updateClearButton();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installDocumentListener() {
|
||||
if( documentListener != null )
|
||||
return;
|
||||
|
||||
documentListener = new FlatDocumentListener();
|
||||
getComponent().getDocument().addDocumentListener( documentListener );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void documentChanged( DocumentEvent e ) {
|
||||
if( clearButton != null )
|
||||
updateClearButton();
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installStyle() {
|
||||
try {
|
||||
@@ -246,10 +329,15 @@ public class FlatTextFieldUI
|
||||
protected void applyStyle( Object style ) {
|
||||
oldDisabledBackground = disabledBackground;
|
||||
oldInactiveBackground = inactiveBackground;
|
||||
boolean oldShowClearButton = showClearButton;
|
||||
|
||||
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||
|
||||
updateBackground();
|
||||
if( showClearButton != oldShowClearButton ) {
|
||||
uninstallClearButton();
|
||||
installClearButton();
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@@ -444,6 +532,16 @@ debug*/
|
||||
// add width of leading and trailing icons
|
||||
size.width += getLeadingIconWidth() + getTrailingIconWidth();
|
||||
|
||||
// add width of leading and trailing components
|
||||
for( JComponent comp : getLeadingComponents() ) {
|
||||
if( comp != null && comp.isVisible() )
|
||||
size.width += comp.getPreferredSize().width;
|
||||
}
|
||||
for( JComponent comp : getTrailingComponents() ) {
|
||||
if( comp != null && comp.isVisible() )
|
||||
size.width += comp.getPreferredSize().width;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -510,7 +608,8 @@ debug*/
|
||||
/**
|
||||
* Returns the rectangle used to paint leading and trailing icons.
|
||||
* It invokes {@code super.getVisibleEditorRect()} and reduces left and/or
|
||||
* right margin if the text field has leading or trailing icons.
|
||||
* right margin if the text field has leading or trailing icons or components.
|
||||
* Also the preferred widths of leading and trailing components are removed.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
@@ -519,10 +618,31 @@ debug*/
|
||||
if( r == null )
|
||||
return null;
|
||||
|
||||
// if a leading/trailing icon is shown, then the left/right margin is reduced
|
||||
// to the top margin, which places the icon nicely centered on left/right side
|
||||
boolean ltr = isLeftToRight();
|
||||
if( ltr ? hasLeadingIcon() : hasTrailingIcon() ) {
|
||||
|
||||
// remove width of leading/trailing components
|
||||
JComponent[] leftComponents = ltr ? getLeadingComponents() : getTrailingComponents();
|
||||
JComponent[] rightComponents = ltr ? getTrailingComponents() : getLeadingComponents();
|
||||
boolean leftVisible = false;
|
||||
boolean rightVisible = false;
|
||||
for( JComponent leftComponent : leftComponents ) {
|
||||
if( leftComponent != null && leftComponent.isVisible() ) {
|
||||
int w = leftComponent.getPreferredSize().width;
|
||||
r.x += w;
|
||||
r.width -= w;
|
||||
leftVisible = true;
|
||||
}
|
||||
}
|
||||
for( JComponent rightComponent : rightComponents ) {
|
||||
if( rightComponent != null && rightComponent.isVisible() ) {
|
||||
r.width -= rightComponent.getPreferredSize().width;
|
||||
rightVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if a leading/trailing icons (or components) are shown, then the left/right margins are reduced
|
||||
// to the top margin, which places the icon nicely centered on left/right side
|
||||
if( leftVisible || (ltr ? hasLeadingIcon() : hasTrailingIcon()) ) {
|
||||
// reduce left margin
|
||||
Insets margin = getComponent().getMargin();
|
||||
int newLeftMargin = Math.min( margin.left, margin.top );
|
||||
@@ -532,7 +652,7 @@ debug*/
|
||||
r.width += diff;
|
||||
}
|
||||
}
|
||||
if( ltr ? hasTrailingIcon() : hasLeadingIcon() ) {
|
||||
if( rightVisible || (ltr ? hasTrailingIcon() : hasLeadingIcon()) ) {
|
||||
// reduce right margin
|
||||
Insets margin = getComponent().getMargin();
|
||||
int newRightMargin = Math.min( margin.right, margin.top );
|
||||
@@ -540,6 +660,10 @@ debug*/
|
||||
r.width += scale( margin.right - newRightMargin );
|
||||
}
|
||||
|
||||
// make sure that width and height are not negative
|
||||
r.width = Math.max( r.width, 0 );
|
||||
r.height = Math.max( r.height, 0 );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -578,4 +702,259 @@ debug*/
|
||||
if( caret instanceof FlatCaret )
|
||||
((FlatCaret)caret).scrollCaretToVisible();
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installLeadingComponent() {
|
||||
JTextComponent c = getComponent();
|
||||
leadingComponent = clientProperty( c, TEXT_FIELD_LEADING_COMPONENT, null, JComponent.class );
|
||||
if( leadingComponent != null ) {
|
||||
prepareLeadingOrTrailingComponent( leadingComponent );
|
||||
installLayout();
|
||||
c.add( leadingComponent );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installTrailingComponent() {
|
||||
JTextComponent c = getComponent();
|
||||
trailingComponent = clientProperty( c, TEXT_FIELD_TRAILING_COMPONENT, null, JComponent.class );
|
||||
if( trailingComponent != null ) {
|
||||
prepareLeadingOrTrailingComponent( trailingComponent );
|
||||
installLayout();
|
||||
c.add( trailingComponent );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void uninstallLeadingComponent() {
|
||||
if( leadingComponent != null ) {
|
||||
getComponent().remove( leadingComponent );
|
||||
leadingComponent = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void uninstallTrailingComponent() {
|
||||
if( trailingComponent != null ) {
|
||||
getComponent().remove( trailingComponent );
|
||||
trailingComponent = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installClearButton() {
|
||||
JTextComponent c = getComponent();
|
||||
if( clientPropertyBoolean( c, TEXT_FIELD_SHOW_CLEAR_BUTTON, showClearButton ) ) {
|
||||
clearButton = createClearButton();
|
||||
updateClearButton();
|
||||
installDocumentListener();
|
||||
installLayout();
|
||||
c.add( clearButton );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void uninstallClearButton() {
|
||||
if( clearButton != null ) {
|
||||
getComponent().remove( clearButton );
|
||||
clearButton = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected JComponent createClearButton() {
|
||||
JButton button = new JButton();
|
||||
button.putClientProperty( STYLE_CLASS, "clearButton" );
|
||||
button.putClientProperty( BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON );
|
||||
button.setCursor( Cursor.getDefaultCursor() );
|
||||
button.addActionListener( e -> clearButtonClicked() );
|
||||
return button;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@SuppressWarnings( "unchecked" )
|
||||
protected void clearButtonClicked() {
|
||||
JTextComponent c = getComponent();
|
||||
Object callback = c.getClientProperty( TEXT_FIELD_CLEAR_CALLBACK );
|
||||
if( callback instanceof Runnable )
|
||||
((Runnable)callback).run();
|
||||
else if( callback instanceof Consumer )
|
||||
((Consumer<JTextComponent>)callback).accept( c );
|
||||
else
|
||||
c.setText( "" );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void updateClearButton() {
|
||||
if( clearButton == null )
|
||||
return;
|
||||
|
||||
JTextComponent c = getComponent();
|
||||
boolean visible = c.isEnabled() && c.isEditable() && c.getDocument().getLength() > 0;
|
||||
if( visible != clearButton.isVisible() ) {
|
||||
clearButton.setVisible( visible );
|
||||
c.revalidate();
|
||||
c.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns components placed at the leading side of the text field.
|
||||
* The returned array may contain {@code null}.
|
||||
* The default implementation returns {@link #leadingComponent}.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
protected JComponent[] getLeadingComponents() {
|
||||
return new JComponent[] { leadingComponent };
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns components placed at the trailing side of the text field.
|
||||
* The returned array may contain {@code null}.
|
||||
* The default implementation returns {@link #trailingComponent} and {@link #clearButton}.
|
||||
* <p>
|
||||
* <strong>Note</strong>: The components in the array must be in reverse (visual) order.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
protected JComponent[] getTrailingComponents() {
|
||||
return new JComponent[] { trailingComponent, clearButton };
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void prepareLeadingOrTrailingComponent( JComponent c ) {
|
||||
c.putClientProperty( STYLE_CLASS, "inTextField" );
|
||||
c.setCursor( Cursor.getDefaultCursor() );
|
||||
|
||||
if( c instanceof JButton || c instanceof JToggleButton )
|
||||
c.putClientProperty( BUTTON_TYPE, BUTTON_TYPE_TOOLBAR_BUTTON );
|
||||
else if( c instanceof JToolBar ) {
|
||||
for( Component child : c.getComponents() ) {
|
||||
if( child instanceof JComponent )
|
||||
((JComponent)child).putClientProperty( STYLE_CLASS, "inTextField" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installLayout() {
|
||||
JTextComponent c = getComponent();
|
||||
LayoutManager oldLayout = c.getLayout();
|
||||
if( !(oldLayout instanceof FlatTextFieldLayout) )
|
||||
c.setLayout( new FlatTextFieldLayout( oldLayout ) );
|
||||
}
|
||||
|
||||
//---- class FlatTextFieldLayout ------------------------------------------
|
||||
|
||||
private class FlatTextFieldLayout
|
||||
implements LayoutManager2, UIResource
|
||||
{
|
||||
private final LayoutManager delegate;
|
||||
|
||||
FlatTextFieldLayout( LayoutManager delegate ) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLayoutComponent( String name, Component comp ) {
|
||||
if( delegate != null )
|
||||
delegate.addLayoutComponent( name, comp );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeLayoutComponent( Component comp ) {
|
||||
if( delegate != null )
|
||||
delegate.removeLayoutComponent( comp );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension preferredLayoutSize( Container parent ) {
|
||||
return (delegate != null) ? delegate.preferredLayoutSize( parent ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension minimumLayoutSize( Container parent ) {
|
||||
return (delegate != null) ? delegate.minimumLayoutSize( parent ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void layoutContainer( Container parent ) {
|
||||
if( delegate != null )
|
||||
delegate.layoutContainer( parent );
|
||||
|
||||
int ow = FlatUIUtils.getBorderFocusAndLineWidth( getComponent() );
|
||||
int h = parent.getHeight() - ow - ow;
|
||||
boolean ltr = isLeftToRight();
|
||||
JComponent[] leftComponents = ltr ? getLeadingComponents() : getTrailingComponents();
|
||||
JComponent[] rightComponents = ltr ? getTrailingComponents() : getLeadingComponents();
|
||||
|
||||
// layout left components
|
||||
int x = ow;
|
||||
for( JComponent leftComponent : leftComponents ) {
|
||||
if( leftComponent != null && leftComponent.isVisible() ) {
|
||||
int cw = leftComponent.getPreferredSize().width;
|
||||
leftComponent.setBounds( x, ow, cw, h );
|
||||
x += cw;
|
||||
}
|
||||
}
|
||||
|
||||
// layout right components
|
||||
x = parent.getWidth() - ow;
|
||||
for( JComponent rightComponent : rightComponents ) {
|
||||
if( rightComponent != null && rightComponent.isVisible() ) {
|
||||
int cw = rightComponent.getPreferredSize().width;
|
||||
x -= cw;
|
||||
rightComponent.setBounds( x, ow, cw, h );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLayoutComponent( Component comp, Object constraints ) {
|
||||
if( delegate instanceof LayoutManager2 )
|
||||
((LayoutManager2)delegate).addLayoutComponent( comp, constraints );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension maximumLayoutSize( Container target ) {
|
||||
return (delegate instanceof LayoutManager2) ? ((LayoutManager2)delegate).maximumLayoutSize( target ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getLayoutAlignmentX( Container target ) {
|
||||
return (delegate instanceof LayoutManager2) ? ((LayoutManager2)delegate).getLayoutAlignmentX( target ) : 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getLayoutAlignmentY( Container target ) {
|
||||
return (delegate instanceof LayoutManager2) ? ((LayoutManager2)delegate).getLayoutAlignmentY( target ) : 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateLayout( Container target ) {
|
||||
if( delegate instanceof LayoutManager2 )
|
||||
((LayoutManager2)delegate).invalidateLayout( target );
|
||||
}
|
||||
}
|
||||
//---- class FlatDocumentListener -----------------------------------------
|
||||
|
||||
private class FlatDocumentListener
|
||||
implements DocumentListener
|
||||
{
|
||||
@Override
|
||||
public void insertUpdate( DocumentEvent e ) {
|
||||
documentChanged( e );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate( DocumentEvent e ) {
|
||||
documentChanged( e );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate( DocumentEvent e ) {
|
||||
documentChanged( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,8 +50,6 @@ import javax.accessibility.AccessibleContext;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
@@ -66,7 +64,6 @@ import javax.swing.border.Border;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatSystemProperties;
|
||||
import com.formdev.flatlaf.ui.FlatNativeWindowBorder.WindowTopBorder;
|
||||
import com.formdev.flatlaf.util.ScaledImageIcon;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
@@ -80,6 +77,8 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TitlePane.embeddedForeground Color
|
||||
* @uiDefault TitlePane.borderColor Color optional
|
||||
* @uiDefault TitlePane.unifiedBackground boolean
|
||||
* @uiDefault TitlePane.showIcon boolean
|
||||
* @uiDefault TitlePane.noIconLeftGap int
|
||||
* @uiDefault TitlePane.iconSize Dimension
|
||||
* @uiDefault TitlePane.iconMargins Insets
|
||||
* @uiDefault TitlePane.titleMargins Insets
|
||||
@@ -88,7 +87,6 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TitlePane.centerTitle boolean
|
||||
* @uiDefault TitlePane.centerTitleIfMenuBarEmbedded boolean
|
||||
* @uiDefault TitlePane.menuBarTitleGap int
|
||||
* @uiDefault TitlePane.icon Icon
|
||||
* @uiDefault TitlePane.closeIcon Icon
|
||||
* @uiDefault TitlePane.iconifyIcon Icon
|
||||
* @uiDefault TitlePane.maximizeIcon Icon
|
||||
@@ -106,6 +104,8 @@ public class FlatTitlePane
|
||||
protected final Color embeddedForeground = UIManager.getColor( "TitlePane.embeddedForeground" );
|
||||
protected final Color borderColor = UIManager.getColor( "TitlePane.borderColor" );
|
||||
|
||||
/** @since 2 */ protected final boolean showIcon = FlatUIUtils.getUIBoolean( "TitlePane.showIcon", true );
|
||||
/** @since 2 */ protected final int noIconLeftGap = FlatUIUtils.getUIInt( "TitlePane.noIconLeftGap", 8 );
|
||||
protected final Dimension iconSize = UIManager.getDimension( "TitlePane.iconSize" );
|
||||
protected final int buttonMaximizedHeight = UIManager.getInt( "TitlePane.buttonMaximizedHeight" );
|
||||
protected final boolean centerTitle = UIManager.getBoolean( "TitlePane.centerTitle" );
|
||||
@@ -224,6 +224,11 @@ public class FlatTitlePane
|
||||
restoreButton = createButton( "TitlePane.restoreIcon", "Restore", e -> restore() );
|
||||
closeButton = createButton( "TitlePane.closeIcon", "Close", e -> close() );
|
||||
|
||||
// initially hide buttons that are only supported in frames
|
||||
iconifyButton.setVisible( false );
|
||||
maximizeButton.setVisible( false );
|
||||
restoreButton.setVisible( false );
|
||||
|
||||
buttonPanel = new JPanel() {
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
@@ -243,11 +248,9 @@ public class FlatTitlePane
|
||||
if( rootPane.getWindowDecorationStyle() == JRootPane.FRAME ) {
|
||||
// JRootPane.FRAME works only for frames (and not for dialogs)
|
||||
// but at this time the owner window type is unknown (not yet added)
|
||||
// so we add the iconify/maximize/restore buttons and they are hidden
|
||||
// so we add the iconify/maximize/restore buttons and they are shown
|
||||
// later in frameStateChanged(), which is invoked from addNotify()
|
||||
|
||||
restoreButton.setVisible( false );
|
||||
|
||||
buttonPanel.add( iconifyButton );
|
||||
buttonPanel.add( maximizeButton );
|
||||
buttonPanel.add( restoreButton );
|
||||
@@ -337,36 +340,27 @@ public class FlatTitlePane
|
||||
|
||||
protected void updateIcon() {
|
||||
// get window images
|
||||
List<Image> images = window.getIconImages();
|
||||
if( images.isEmpty() ) {
|
||||
// search in owners
|
||||
for( Window owner = window.getOwner(); owner != null; owner = owner.getOwner() ) {
|
||||
images = owner.getIconImages();
|
||||
if( !images.isEmpty() )
|
||||
break;
|
||||
List<Image> images = null;
|
||||
if( clientPropertyBoolean( rootPane, TITLE_BAR_SHOW_ICON, showIcon ) ) {
|
||||
images = window.getIconImages();
|
||||
if( images.isEmpty() ) {
|
||||
// search in owners
|
||||
for( Window owner = window.getOwner(); owner != null; owner = owner.getOwner() ) {
|
||||
images = owner.getIconImages();
|
||||
if( !images.isEmpty() )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasIcon = true;
|
||||
boolean hasIcon = (images != null && !images.isEmpty());
|
||||
|
||||
// set icon
|
||||
if( !images.isEmpty() )
|
||||
iconLabel.setIcon( new FlatTitlePaneIcon( images, iconSize ) );
|
||||
else {
|
||||
// no icon set on window --> use default icon
|
||||
Icon defaultIcon = UIManager.getIcon( "TitlePane.icon" );
|
||||
if( defaultIcon != null && (defaultIcon.getIconWidth() == 0 || defaultIcon.getIconHeight() == 0) )
|
||||
defaultIcon = null;
|
||||
if( defaultIcon != null ) {
|
||||
if( defaultIcon instanceof ImageIcon )
|
||||
defaultIcon = new ScaledImageIcon( (ImageIcon) defaultIcon, iconSize.width, iconSize.height );
|
||||
iconLabel.setIcon( defaultIcon );
|
||||
} else
|
||||
hasIcon = false;
|
||||
}
|
||||
iconLabel.setIcon( hasIcon ? new FlatTitlePaneIcon( images, iconSize ) : null );
|
||||
|
||||
// show/hide icon
|
||||
iconLabel.setVisible( hasIcon );
|
||||
leftPanel.setBorder( hasIcon ? null : FlatUIUtils.nonUIResource( new FlatEmptyBorder( 0, noIconLeftGap, 0, 0 ) ) );
|
||||
|
||||
updateNativeTitleBarHeightAndHitTestSpotsLater();
|
||||
}
|
||||
@@ -508,7 +502,7 @@ public class FlatTitlePane
|
||||
|
||||
protected void menuBarLayouted() {
|
||||
updateNativeTitleBarHeightAndHitTestSpotsLater();
|
||||
revalidate();
|
||||
doLayout();
|
||||
}
|
||||
|
||||
/*debug
|
||||
@@ -521,17 +515,23 @@ public class FlatTitlePane
|
||||
g.drawLine( 0, debugTitleBarHeight, getWidth(), debugTitleBarHeight );
|
||||
}
|
||||
if( debugHitTestSpots != null ) {
|
||||
g.setColor( Color.red );
|
||||
Point offset = SwingUtilities.convertPoint( this, 0, 0, window );
|
||||
for( Rectangle r : debugHitTestSpots )
|
||||
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
||||
}
|
||||
if( debugAppIconBounds != null ) {
|
||||
g.setColor( Color.blue);
|
||||
Point offset = SwingUtilities.convertPoint( this, 0, 0, window );
|
||||
Rectangle r = debugAppIconBounds;
|
||||
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
||||
paintRect( g, Color.red, r );
|
||||
}
|
||||
paintRect( g, Color.cyan, debugCloseButtonBounds );
|
||||
paintRect( g, Color.blue, debugAppIconBounds );
|
||||
paintRect( g, Color.blue, debugMinimizeButtonBounds );
|
||||
paintRect( g, Color.magenta, debugMaximizeButtonBounds );
|
||||
paintRect( g, Color.cyan, debugCloseButtonBounds );
|
||||
}
|
||||
|
||||
private void paintRect( Graphics g, Color color, Rectangle r ) {
|
||||
if( r == null )
|
||||
return;
|
||||
|
||||
g.setColor( color );
|
||||
Point offset = SwingUtilities.convertPoint( this, 0, 0, window );
|
||||
g.drawRect( r.x - offset.x, r.y - offset.y, r.width - 1, r.height - 1 );
|
||||
}
|
||||
debug*/
|
||||
|
||||
@@ -702,9 +702,15 @@ debug*/
|
||||
return window != null && FlatNativeWindowBorder.hasCustomDecoration( window );
|
||||
}
|
||||
|
||||
// used to invoke updateNativeTitleBarHeightAndHitTestSpots() only once from latest invokeLater()
|
||||
private int laterCounter;
|
||||
|
||||
protected void updateNativeTitleBarHeightAndHitTestSpotsLater() {
|
||||
laterCounter++;
|
||||
EventQueue.invokeLater( () -> {
|
||||
updateNativeTitleBarHeightAndHitTestSpots();
|
||||
laterCounter--;
|
||||
if( laterCounter == 0 )
|
||||
updateNativeTitleBarHeightAndHitTestSpots();
|
||||
} );
|
||||
}
|
||||
|
||||
@@ -722,8 +728,9 @@ debug*/
|
||||
|
||||
List<Rectangle> hitTestSpots = new ArrayList<>();
|
||||
Rectangle appIconBounds = null;
|
||||
|
||||
if( iconLabel.isVisible() ) {
|
||||
// compute real icon size (without insets; 1px wider for easier hitting)
|
||||
// compute real icon size (without insets; 1px larger for easier hitting)
|
||||
Point location = SwingUtilities.convertPoint( iconLabel, 0, 0, window );
|
||||
Insets iconInsets = iconLabel.getInsets();
|
||||
Rectangle iconBounds = new Rectangle(
|
||||
@@ -759,7 +766,7 @@ debug*/
|
||||
|
||||
JMenuBar menuBar = rootPane.getJMenuBar();
|
||||
if( hasVisibleEmbeddedMenuBar( menuBar ) ) {
|
||||
r = getNativeHitTestSpot( menuBarPlaceholder );
|
||||
r = getNativeHitTestSpot( menuBar );
|
||||
if( r != null ) {
|
||||
Component horizontalGlue = findHorizontalGlue( menuBar );
|
||||
if( horizontalGlue != null ) {
|
||||
@@ -768,18 +775,18 @@ debug*/
|
||||
// the glue component area can used to move the window.
|
||||
|
||||
Point glueLocation = SwingUtilities.convertPoint( horizontalGlue, 0, 0, window );
|
||||
int x2 = glueLocation.x + horizontalGlue.getWidth();
|
||||
Rectangle r2;
|
||||
if( getComponentOrientation().isLeftToRight() ) {
|
||||
int trailingWidth = (r.x + r.width - HIT_TEST_SPOT_GROW) - glueLocation.x;
|
||||
r.width -= trailingWidth;
|
||||
r2 = new Rectangle( glueLocation.x + horizontalGlue.getWidth(), r.y, trailingWidth, r.height );
|
||||
r2 = new Rectangle( x2, r.y, (r.x + r.width) - x2, r.height );
|
||||
|
||||
r.width = glueLocation.x - r.x;
|
||||
} else {
|
||||
int leadingWidth = (glueLocation.x + horizontalGlue.getWidth()) - (r.x + HIT_TEST_SPOT_GROW);
|
||||
r.x += leadingWidth;
|
||||
r.width -= leadingWidth;
|
||||
r2 = new Rectangle( glueLocation.x -leadingWidth, r.y, leadingWidth, r.height );
|
||||
r2 = new Rectangle( r.x, r.y, glueLocation.x - r.x, r.height );
|
||||
|
||||
r.width = (r.x + r.width) - x2;
|
||||
r.x = x2;
|
||||
}
|
||||
r2.grow( HIT_TEST_SPOT_GROW, HIT_TEST_SPOT_GROW );
|
||||
hitTestSpots.add( r2 );
|
||||
}
|
||||
|
||||
@@ -787,16 +794,30 @@ debug*/
|
||||
}
|
||||
}
|
||||
|
||||
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight, hitTestSpots, appIconBounds );
|
||||
Rectangle minimizeButtonBounds = boundsInWindow( iconifyButton );
|
||||
Rectangle maximizeButtonBounds = boundsInWindow( maximizeButton.isVisible() ? maximizeButton : restoreButton );
|
||||
Rectangle closeButtonBounds = boundsInWindow( closeButton );
|
||||
|
||||
FlatNativeWindowBorder.setTitleBarHeightAndHitTestSpots( window, titleBarHeight,
|
||||
hitTestSpots, appIconBounds, minimizeButtonBounds, maximizeButtonBounds, closeButtonBounds );
|
||||
|
||||
/*debug
|
||||
debugTitleBarHeight = titleBarHeight;
|
||||
debugHitTestSpots = hitTestSpots;
|
||||
debugAppIconBounds = appIconBounds;
|
||||
debugMinimizeButtonBounds = minimizeButtonBounds;
|
||||
debugMaximizeButtonBounds = maximizeButtonBounds;
|
||||
debugCloseButtonBounds = closeButtonBounds;
|
||||
repaint();
|
||||
debug*/
|
||||
}
|
||||
|
||||
private Rectangle boundsInWindow( JComponent c ) {
|
||||
return c.isShowing()
|
||||
? SwingUtilities.convertRectangle( c.getParent(), c.getBounds(), window )
|
||||
: null;
|
||||
}
|
||||
|
||||
protected Rectangle getNativeHitTestSpot( JComponent c ) {
|
||||
Dimension size = c.getSize();
|
||||
if( size.width <= 0 || size.height <= 0 )
|
||||
@@ -804,17 +825,16 @@ debug*/
|
||||
|
||||
Point location = SwingUtilities.convertPoint( c, 0, 0, window );
|
||||
Rectangle r = new Rectangle( location, size );
|
||||
// slightly increase rectangle so that component receives mouseExit events
|
||||
r.grow( HIT_TEST_SPOT_GROW, HIT_TEST_SPOT_GROW );
|
||||
return r;
|
||||
}
|
||||
|
||||
private static final int HIT_TEST_SPOT_GROW = 2;
|
||||
|
||||
/*debug
|
||||
private int debugTitleBarHeight;
|
||||
private List<Rectangle> debugHitTestSpots;
|
||||
private Rectangle debugAppIconBounds;
|
||||
private Rectangle debugMinimizeButtonBounds;
|
||||
private Rectangle debugMaximizeButtonBounds;
|
||||
private Rectangle debugCloseButtonBounds;
|
||||
debug*/
|
||||
|
||||
//---- class FlatTitlePaneBorder ------------------------------------------
|
||||
@@ -846,7 +866,7 @@ debug*/
|
||||
Border menuBarBorder = getMenuBarBorder();
|
||||
if( menuBarBorder != null ) {
|
||||
// if menu bar is embedded, paint menu bar border
|
||||
menuBarBorder.paintBorder( c, g, x, y, width, height );
|
||||
menuBarBorder.paintBorder( rootPane.getJMenuBar(), g, x, y, width, height );
|
||||
} else if( borderColor != null && (rootPane.getJMenuBar() == null || !rootPane.getJMenuBar().isVisible()) ) {
|
||||
// paint border between title pane and content if border color is specified
|
||||
float lineHeight = UIScale.scale( (float) 1 );
|
||||
|
||||
@@ -121,7 +121,7 @@ public class FlatToolBarSeparatorUI
|
||||
private void stylePropertyChange( JSeparator s ) {
|
||||
if( shared && FlatStylingSupport.hasStyleProperty( s ) ) {
|
||||
// unshare component UI if necessary
|
||||
// updateUI() invokes applyStyle() from installUI()
|
||||
// updateUI() invokes installStyle() from installUI()
|
||||
s.updateUI();
|
||||
} else
|
||||
installStyle( s );
|
||||
|
||||
@@ -52,6 +52,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* @uiDefault Tree.font Font
|
||||
* @uiDefault Tree.background Color
|
||||
* @uiDefault Tree.foreground Color unused
|
||||
* @uiDefault Tree.hash Color
|
||||
* @uiDefault Tree.dropLineColor Color
|
||||
* @uiDefault Tree.expandedIcon Icon
|
||||
@@ -136,12 +137,12 @@ public class FlatTreeUI
|
||||
|
||||
// for icons
|
||||
// (needs to be public because icon classes are in another package)
|
||||
@Styleable(dot=true) public String iconArrowType;
|
||||
@Styleable(dot=true) public Color iconExpandedColor;
|
||||
@Styleable(dot=true) public Color iconCollapsedColor;
|
||||
@Styleable(dot=true) public Color iconLeafColor;
|
||||
@Styleable(dot=true) public Color iconClosedColor;
|
||||
@Styleable(dot=true) public Color iconOpenColor;
|
||||
/** @since 2 */ @Styleable(dot=true) public String iconArrowType;
|
||||
/** @since 2 */ @Styleable(dot=true) public Color iconExpandedColor;
|
||||
/** @since 2 */ @Styleable(dot=true) public Color iconCollapsedColor;
|
||||
/** @since 2 */ @Styleable(dot=true) public Color iconLeafColor;
|
||||
/** @since 2 */ @Styleable(dot=true) public Color iconClosedColor;
|
||||
/** @since 2 */ @Styleable(dot=true) public Color iconOpenColor;
|
||||
|
||||
// only used via styling (not in UI defaults, but has likewise client properties)
|
||||
/** @since 2 */ @Styleable protected boolean paintSelection = true;
|
||||
|
||||
@@ -188,6 +188,11 @@ public class FlatUIUtils
|
||||
return (font instanceof UIResource) ? font.deriveFont( font.getStyle() ) : font;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
public static Border nonUIResource( Border border ) {
|
||||
return (border instanceof UIResource) ? new NonUIResourceBorder( border ) : border;
|
||||
}
|
||||
|
||||
public static int minimumWidth( JComponent c, int minimumWidth ) {
|
||||
return FlatClientProperties.clientPropertyInt( c, FlatClientProperties.MINIMUM_WIDTH, minimumWidth );
|
||||
}
|
||||
@@ -273,6 +278,32 @@ public class FlatUIUtils
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scaled line thickness used to compute the border insets.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public static float getBorderLineWidth( JComponent c ) {
|
||||
FlatBorder border = getOutsideFlatBorder( c );
|
||||
return (border != null)
|
||||
? UIScale.scale( (float) border.getLineWidth( c ) )
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scaled thickness of the border.
|
||||
* This includes the outer focus border and the actual component border.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public static int getBorderFocusAndLineWidth( JComponent c ) {
|
||||
FlatBorder border = getOutsideFlatBorder( c );
|
||||
return (border != null)
|
||||
? Math.round( UIScale.scale( (float) border.getFocusWidth( c ) )
|
||||
+ UIScale.scale( (float) border.getLineWidth( c ) ) )
|
||||
: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scaled arc diameter of the border for the given component.
|
||||
*/
|
||||
@@ -982,4 +1013,31 @@ debug*/
|
||||
repaintComponent.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
//---- class NonUIResourceBorder ------------------------------------------
|
||||
|
||||
private static class NonUIResourceBorder
|
||||
implements Border
|
||||
{
|
||||
private final Border delegate;
|
||||
|
||||
NonUIResourceBorder( Border delegate ) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
delegate.paintBorder( c, g, x, y, width, height );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets( Component c ) {
|
||||
return delegate.getBorderInsets( c );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBorderOpaque() {
|
||||
return delegate.isBorderOpaque();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,10 @@ import com.formdev.flatlaf.util.SystemInfo;
|
||||
// https://github.com/oberth/custom-chrome
|
||||
// https://github.com/rossy/borderless-window
|
||||
//
|
||||
// Windows 11
|
||||
// https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/apply-snap-layout-menu
|
||||
// https://github.com/dotnet/wpf/issues/4825#issuecomment-930442736
|
||||
//
|
||||
|
||||
/**
|
||||
* Native window border support for Windows 10 when using custom decorations.
|
||||
@@ -86,6 +90,10 @@ class FlatWindowsNativeWindowBorder
|
||||
if( !SystemInfo.isWindows_10_orLater )
|
||||
return null;
|
||||
|
||||
// requires x86 architecture
|
||||
if( !SystemInfo.isX86 && !SystemInfo.isX86_64 )
|
||||
return null;
|
||||
|
||||
// load native library
|
||||
if( nativeLibrary == null ) {
|
||||
if( !SystemInfo.isJava_9_orLater ) {
|
||||
@@ -163,11 +171,18 @@ class FlatWindowsNativeWindowBorder
|
||||
return;
|
||||
|
||||
// install
|
||||
WndProc wndProc = new WndProc( window );
|
||||
if( wndProc.hwnd == 0 )
|
||||
return;
|
||||
try {
|
||||
WndProc wndProc = new WndProc( window );
|
||||
if( wndProc.hwnd == 0 )
|
||||
return;
|
||||
|
||||
windowsMap.put( window, wndProc );
|
||||
windowsMap.put( window, wndProc );
|
||||
} catch( UnsatisfiedLinkError ex ) {
|
||||
// catch for the case that the operating system prevents execution of DLL
|
||||
// (e.g. if DLLs in temp folder are restricted)
|
||||
// --> continue application without custom decorations
|
||||
LoggingFacade.INSTANCE.logSevere( null, ex );
|
||||
}
|
||||
}
|
||||
|
||||
private void uninstall( Window window ) {
|
||||
@@ -177,30 +192,24 @@ class FlatWindowsNativeWindowBorder
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitleBarHeight( Window window, int titleBarHeight ) {
|
||||
public void updateTitleBarInfo( Window window, int titleBarHeight, List<Rectangle> hitTestSpots,
|
||||
Rectangle appIconBounds, Rectangle minimizeButtonBounds, Rectangle maximizeButtonBounds,
|
||||
Rectangle closeButtonBounds )
|
||||
{
|
||||
WndProc wndProc = windowsMap.get( window );
|
||||
if( wndProc == null )
|
||||
return;
|
||||
|
||||
wndProc.titleBarHeight = titleBarHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitleBarHitTestSpots( Window window, List<Rectangle> hitTestSpots ) {
|
||||
WndProc wndProc = windowsMap.get( window );
|
||||
if( wndProc == null )
|
||||
return;
|
||||
|
||||
wndProc.hitTestSpots = hitTestSpots.toArray( new Rectangle[hitTestSpots.size()] );
|
||||
wndProc.appIconBounds = cloneRectange( appIconBounds );
|
||||
wndProc.minimizeButtonBounds = cloneRectange( minimizeButtonBounds );
|
||||
wndProc.maximizeButtonBounds = cloneRectange( maximizeButtonBounds );
|
||||
wndProc.closeButtonBounds = cloneRectange( closeButtonBounds );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitleBarAppIconBounds( Window window, Rectangle appIconBounds ) {
|
||||
WndProc wndProc = windowsMap.get( window );
|
||||
if( wndProc == null )
|
||||
return;
|
||||
|
||||
wndProc.appIconBounds = (appIconBounds != null) ? new Rectangle( appIconBounds ) : null;
|
||||
private static Rectangle cloneRectange( Rectangle rect ) {
|
||||
return (rect != null) ? new Rectangle( rect ) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -303,14 +312,21 @@ class FlatWindowsNativeWindowBorder
|
||||
HTCLIENT = 1,
|
||||
HTCAPTION = 2,
|
||||
HTSYSMENU = 3,
|
||||
HTTOP = 12;
|
||||
HTMINBUTTON = 8,
|
||||
HTMAXBUTTON = 9,
|
||||
HTTOP = 12,
|
||||
HTCLOSE = 20;
|
||||
|
||||
private Window window;
|
||||
private final long hwnd;
|
||||
|
||||
// Swing coordinates/values may be scaled on a HiDPI screen
|
||||
private int titleBarHeight;
|
||||
private Rectangle[] hitTestSpots;
|
||||
private Rectangle appIconBounds;
|
||||
private Rectangle minimizeButtonBounds;
|
||||
private Rectangle maximizeButtonBounds;
|
||||
private Rectangle closeButtonBounds;
|
||||
|
||||
WndProc( Window window ) {
|
||||
this.window = window;
|
||||
@@ -355,7 +371,7 @@ class FlatWindowsNativeWindowBorder
|
||||
|
||||
// invoked from native code
|
||||
private int onNcHitTest( int x, int y, boolean isOnResizeBorder ) {
|
||||
// scale-down mouse x/y
|
||||
// scale-down mouse x/y because Swing coordinates/values may be scaled on a HiDPI screen
|
||||
Point pt = scaleDown( x, y );
|
||||
int sx = pt.x;
|
||||
int sy = pt.y;
|
||||
@@ -363,9 +379,26 @@ class FlatWindowsNativeWindowBorder
|
||||
// return HTSYSMENU if mouse is over application icon
|
||||
// - left-click on HTSYSMENU area shows system menu
|
||||
// - double-left-click sends WM_CLOSE
|
||||
if( appIconBounds != null && appIconBounds.contains( sx, sy ) )
|
||||
if( contains( appIconBounds, sx, sy ) )
|
||||
return HTSYSMENU;
|
||||
|
||||
// return HTMINBUTTON if mouse is over minimize button
|
||||
// - hovering mouse over HTMINBUTTON area shows tooltip on Windows 10/11
|
||||
if( contains( minimizeButtonBounds, sx, sy ) )
|
||||
return HTMINBUTTON;
|
||||
|
||||
// return HTMAXBUTTON if mouse is over maximize/restore button
|
||||
// - hovering mouse over HTMAXBUTTON area shows tooltip on Windows 10
|
||||
// - hovering mouse over HTMAXBUTTON area shows snap layouts menu on Windows 11
|
||||
// https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/apply-snap-layout-menu
|
||||
if( contains( maximizeButtonBounds, sx, sy ) )
|
||||
return HTMAXBUTTON;
|
||||
|
||||
// return HTCLOSE if mouse is over close button
|
||||
// - hovering mouse over HTCLOSE area shows tooltip on Windows 10/11
|
||||
if( contains( closeButtonBounds, sx, sy ) )
|
||||
return HTCLOSE;
|
||||
|
||||
boolean isOnTitleBar = (sy < titleBarHeight);
|
||||
|
||||
if( isOnTitleBar ) {
|
||||
@@ -382,6 +415,10 @@ class FlatWindowsNativeWindowBorder
|
||||
return isOnResizeBorder ? HTTOP : HTCLIENT;
|
||||
}
|
||||
|
||||
private boolean contains( Rectangle rect, int x, int y ) {
|
||||
return (rect != null && rect.contains( x, y ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales down in the same way as AWT.
|
||||
* See AwtWin32GraphicsDevice::ScaleDownX() and ::ScaleDownY()
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2021 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.util;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.ReferenceQueue;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* A simple cache (map) that uses soft references for the values.
|
||||
*
|
||||
* @author Karl Tauber
|
||||
* @since 2
|
||||
*/
|
||||
public class SoftCache<K,V>
|
||||
implements Map<K, V>
|
||||
{
|
||||
private final Map<K, CacheReference<K,V>> map;
|
||||
private final ReferenceQueue<V> queue = new ReferenceQueue<>();
|
||||
|
||||
public SoftCache() {
|
||||
map = new HashMap<>();
|
||||
}
|
||||
|
||||
public SoftCache( int initialCapacity ) {
|
||||
map = new HashMap<>( initialCapacity );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
expungeStaleEntries();
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
expungeStaleEntries();
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey( Object key ) {
|
||||
expungeStaleEntries();
|
||||
return map.containsKey( key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Throws {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public boolean containsValue( Object value ) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get( Object key ) {
|
||||
expungeStaleEntries();
|
||||
return getRef( map.get( key ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put( K key, V value ) {
|
||||
expungeStaleEntries();
|
||||
return getRef( map.put( key, new CacheReference<>( key, value, queue ) ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove( Object key ) {
|
||||
expungeStaleEntries();
|
||||
return getRef( map.remove( key ) );
|
||||
}
|
||||
|
||||
private V getRef( CacheReference<K,V> ref ) {
|
||||
return (ref != null) ? ref.get() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll( Map<? extends K, ? extends V> m ) {
|
||||
expungeStaleEntries();
|
||||
for( Entry<? extends K, ? extends V> e : m.entrySet() )
|
||||
put( e.getKey(), e.getValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
map.clear();
|
||||
expungeStaleEntries();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
expungeStaleEntries();
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Throws {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Throws {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Throws {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public void forEach( BiConsumer<? super K, ? super V> action ) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Not supported. Throws {@link UnsupportedOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public void replaceAll( BiFunction<? super K, ? super V, ? extends V> function ) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
private void expungeStaleEntries() {
|
||||
Reference<? extends V> reference;
|
||||
while( (reference = queue.poll()) != null )
|
||||
map.remove( ((CacheReference<K,V>)reference).key );
|
||||
}
|
||||
|
||||
//---- class CacheReference ----
|
||||
|
||||
private static class CacheReference<K,V>
|
||||
extends SoftReference<V>
|
||||
{
|
||||
// needed to remove reference from map in expungeStaleEntries()
|
||||
final K key;
|
||||
|
||||
CacheReference( K key, V value, ReferenceQueue<? super V> queue ) {
|
||||
super( value, queue );
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,13 +39,16 @@ public class SystemInfo
|
||||
public static final boolean isMacOS_10_15_Catalina_orLater;
|
||||
|
||||
// OS architecture
|
||||
/** @since 2 */ public static final boolean isX86;
|
||||
/** @since 1.1 */ public static final boolean isX86_64;
|
||||
/** @since 2 */ public static final boolean isAARCH64;
|
||||
|
||||
// Java versions
|
||||
public static final long javaVersion;
|
||||
public static final boolean isJava_9_orLater;
|
||||
public static final boolean isJava_11_orLater;
|
||||
public static final boolean isJava_15_orLater;
|
||||
/** @since 2 */ public static final boolean isJava_17_orLater;
|
||||
|
||||
// Java VMs
|
||||
public static final boolean isJetBrainsJVM;
|
||||
@@ -75,13 +78,16 @@ public class SystemInfo
|
||||
|
||||
// OS architecture
|
||||
String osArch = System.getProperty( "os.arch" );
|
||||
isX86 = osArch.equals( "x86" );
|
||||
isX86_64 = osArch.equals( "amd64" ) || osArch.equals( "x86_64" );
|
||||
isAARCH64 = osArch.equals( "aarch64" );
|
||||
|
||||
// Java versions
|
||||
javaVersion = scanVersion( System.getProperty( "java.version" ) );
|
||||
isJava_9_orLater = (javaVersion >= toVersion( 9, 0, 0, 0 ));
|
||||
isJava_11_orLater = (javaVersion >= toVersion( 11, 0, 0, 0 ));
|
||||
isJava_15_orLater = (javaVersion >= toVersion( 15, 0, 0, 0 ));
|
||||
isJava_17_orLater = (javaVersion >= toVersion( 17, 0, 0, 0 ));
|
||||
|
||||
// Java VMs
|
||||
isJetBrainsJVM = System.getProperty( "java.vm.vendor", "Unknown" )
|
||||
|
||||
@@ -355,3 +355,19 @@ ToolTip.background = shade(@background,50%)
|
||||
#---- Tree ----
|
||||
|
||||
Tree.hash = lighten($Tree.background,5%)
|
||||
|
||||
|
||||
|
||||
#---- Styles ------------------------------------------------------------------
|
||||
|
||||
#---- inTextField ----
|
||||
# for leading/trailing components in text fields
|
||||
|
||||
[style]Button.inTextField = \
|
||||
focusable: false; \
|
||||
toolbar.margin: 1,1,1,1; \
|
||||
toolbar.spacingInsets: 1,1,1,1; \
|
||||
background: $TextField.background; \
|
||||
toolbar.hoverBackground: lighten($TextField.background,4%,derived); \
|
||||
toolbar.pressedBackground: lighten($TextField.background,6%,derived); \
|
||||
toolbar.selectedBackground: lighten($TextField.background,12%,derived)
|
||||
|
||||
@@ -26,6 +26,68 @@
|
||||
# Instead copy and modify only those properties that you need to alter.
|
||||
#
|
||||
|
||||
#---- typography / fonts ----
|
||||
|
||||
# headings
|
||||
h00.font = +24
|
||||
h0.font = +18
|
||||
h1.font = +12 $semibold.font
|
||||
h2.font = +6 $semibold.font
|
||||
h3.font = +3 $semibold.font
|
||||
h4.font = bold
|
||||
|
||||
h1.regular.font = +12
|
||||
h2.regular.font = +6
|
||||
h3.regular.font = +3
|
||||
|
||||
# text
|
||||
large.font = +2
|
||||
medium.font = -1
|
||||
small.font = -2
|
||||
mini.font = -3
|
||||
|
||||
# default font
|
||||
#defaultFont = ...
|
||||
|
||||
# font weights
|
||||
# Windows
|
||||
[win]light.font = "Segoe UI Light"
|
||||
[win]semibold.font = "Segoe UI Semibold"
|
||||
# macOS
|
||||
[mac]light.font = "HelveticaNeue-Thin"
|
||||
[mac]semibold.font = "HelveticaNeue-Medium"
|
||||
# Linux
|
||||
[linux]light.font = "Lato Light", "Ubuntu Light", "Cantarell Light"
|
||||
[linux]semibold.font = "Lato Semibold", "Ubuntu Medium", "Montserrat SemiBold"
|
||||
# fallback for unknown platform
|
||||
light.font = +0
|
||||
semibold.font = +0
|
||||
|
||||
# monospaced
|
||||
[win]monospaced.font = Consolas, "Courier New", Monospaced
|
||||
[mac]monospaced.font = Menlo, Monospaced
|
||||
[linux]monospaced.font = "Liberation Mono", "Ubuntu Mono", Monospaced
|
||||
monospaced.font = Monospaced
|
||||
|
||||
# styles
|
||||
[style].h00 = font: $h00.font
|
||||
[style].h0 = font: $h0.font
|
||||
[style].h1 = font: $h1.font
|
||||
[style].h2 = font: $h2.font
|
||||
[style].h3 = font: $h3.font
|
||||
[style].h4 = font: $h4.font
|
||||
[style].h1.regular = font: $h1.regular.font
|
||||
[style].h2.regular = font: $h2.regular.font
|
||||
[style].h3.regular = font: $h3.regular.font
|
||||
[style].large = font: $large.font
|
||||
[style].medium = font: $medium.font
|
||||
[style].small = font: $small.font
|
||||
[style].mini = font: $mini.font
|
||||
[style].light = font: $light.font
|
||||
[style].semibold = font: $semibold.font
|
||||
[style].monospaced = font: $monospaced.font
|
||||
|
||||
|
||||
#---- UI delegates ----
|
||||
|
||||
ButtonUI = com.formdev.flatlaf.ui.FlatButtonUI
|
||||
@@ -165,6 +227,7 @@ Button.defaultButtonFollowsFocus = false
|
||||
Button.borderWidth = 1
|
||||
Button.default.borderWidth = 1
|
||||
|
||||
# for buttons in toolbars
|
||||
Button.toolbar.margin = 3,3,3,3
|
||||
Button.toolbar.spacingInsets = 1,2,1,2
|
||||
|
||||
@@ -368,6 +431,7 @@ MenuItem.checkIcon = null
|
||||
MenuItem.margin = @menuItemMargin
|
||||
MenuItem.opaque = false
|
||||
MenuItem.borderPainted = true
|
||||
MenuItem.verticallyAlignText = true
|
||||
MenuItem.background = @menuBackground
|
||||
MenuItem.checkBackground = @menuCheckBackground
|
||||
MenuItem.checkMargins = 2,2,2,2
|
||||
@@ -377,7 +441,7 @@ MenuItem.iconTextGap = 6
|
||||
MenuItem.textAcceleratorGap = 24
|
||||
MenuItem.textNoAcceleratorGap = 6
|
||||
MenuItem.acceleratorArrowGap = 2
|
||||
MenuItem.acceleratorDelimiter = -
|
||||
MenuItem.acceleratorDelimiter = +
|
||||
[mac]MenuItem.acceleratorDelimiter =
|
||||
|
||||
# for MenuItem.selectionType = underline
|
||||
@@ -394,6 +458,7 @@ OptionPane.messageAreaBorder = 0,0,0,0
|
||||
OptionPane.buttonAreaBorder = 12,0,0,0
|
||||
OptionPane.messageForeground = null
|
||||
|
||||
OptionPane.showIcon = false
|
||||
OptionPane.maxCharactersPerLine = 80
|
||||
OptionPane.iconMessageGap = 16
|
||||
OptionPane.messagePadding = 3
|
||||
@@ -419,7 +484,10 @@ PasswordField.placeholderForeground = @disabledForeground
|
||||
PasswordField.iconTextGap = 4
|
||||
PasswordField.echoChar = \u2022
|
||||
PasswordField.showCapsLock = true
|
||||
PasswordField.showRevealButton = false
|
||||
PasswordField.capsLockIcon = com.formdev.flatlaf.icons.FlatCapsLockIcon
|
||||
PasswordField.revealIcon = com.formdev.flatlaf.icons.FlatRevealIcon
|
||||
PasswordField.revealIconColor = lazy(Actions.Grey)
|
||||
|
||||
|
||||
#---- Popup ----
|
||||
@@ -587,6 +655,7 @@ SplitPaneDivider.gripGap = 2
|
||||
|
||||
TabbedPane.tabHeight = 32
|
||||
TabbedPane.tabSelectionHeight = 3
|
||||
TabbedPane.cardTabSelectionHeight = 2
|
||||
TabbedPane.contentSeparatorHeight = 1
|
||||
TabbedPane.showTabSeparators = false
|
||||
TabbedPane.tabSeparatorsFullHeight = false
|
||||
@@ -608,6 +677,9 @@ TabbedPane.tabAlignment = center
|
||||
# allowed values: preferred, equal or compact
|
||||
TabbedPane.tabWidthMode = preferred
|
||||
|
||||
# allowed values: underlined or card
|
||||
TabbedPane.tabType = underlined
|
||||
|
||||
# allowed values: chevron or triangle
|
||||
TabbedPane.arrowType = chevron
|
||||
TabbedPane.buttonInsets = 2,1,2,1
|
||||
@@ -709,7 +781,9 @@ TitledBorder.border = 1,1,1,1,$Separator.foreground
|
||||
|
||||
TitlePane.useWindowDecorations = true
|
||||
TitlePane.menuBarEmbedded = true
|
||||
TitlePane.unifiedBackground = false
|
||||
TitlePane.unifiedBackground = true
|
||||
TitlePane.showIcon = true
|
||||
TitlePane.noIconLeftGap = 8
|
||||
TitlePane.iconSize = 16,16
|
||||
TitlePane.iconMargins = 3,8,3,8
|
||||
TitlePane.titleMargins = 3,0,3,0
|
||||
@@ -819,3 +893,33 @@ Tree.icon.collapsedColor = @icon
|
||||
Tree.icon.leafColor = @icon
|
||||
Tree.icon.closedColor = @icon
|
||||
Tree.icon.openColor = @icon
|
||||
|
||||
|
||||
|
||||
#---- Styles ------------------------------------------------------------------
|
||||
|
||||
#---- inTextField ----
|
||||
# for leading/trailing components in text fields
|
||||
|
||||
[style]ToggleButton.inTextField = $[style]Button.inTextField
|
||||
|
||||
[style]ToolBar.inTextField = \
|
||||
floatable: false; \
|
||||
opaque: false; \
|
||||
borderMargins: 0,0,0,0
|
||||
|
||||
[style]ToolBarSeparator.inTextField = \
|
||||
separatorWidth: 3
|
||||
|
||||
|
||||
#---- clearButton ----
|
||||
# for clear/cancel button in text fields
|
||||
|
||||
[style]Button.clearButton = \
|
||||
icon: com.formdev.flatlaf.icons.FlatClearIcon; \
|
||||
focusable: false; \
|
||||
toolbar.margin: 1,1,1,1; \
|
||||
toolbar.spacingInsets: 1,1,1,1; \
|
||||
background: $TextField.background; \
|
||||
toolbar.hoverBackground: $TextField.background; \
|
||||
toolbar.pressedBackground: $TextField.background
|
||||
|
||||
@@ -362,3 +362,19 @@ ToolTip.background = lighten(@background,3%)
|
||||
#---- Tree ----
|
||||
|
||||
Tree.hash = darken($Tree.background,10%)
|
||||
|
||||
|
||||
|
||||
#---- Styles ------------------------------------------------------------------
|
||||
|
||||
#---- inTextField ----
|
||||
# for leading/trailing components in text fields
|
||||
|
||||
[style]Button.inTextField = \
|
||||
focusable: false; \
|
||||
toolbar.margin: 1,1,1,1; \
|
||||
toolbar.spacingInsets: 1,1,1,1; \
|
||||
background: $TextField.background; \
|
||||
toolbar.hoverBackground: darken($TextField.background,4%,derived); \
|
||||
toolbar.pressedBackground: darken($TextField.background,8%,derived); \
|
||||
toolbar.selectedBackground: darken($TextField.background,12%,derived)
|
||||
|
||||
@@ -150,6 +150,7 @@ ToggleButton.endBackground = $ToggleButton.background
|
||||
[Gruvbox_Dark_Soft]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||
[Gruvbox_Dark_Soft]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
||||
|
||||
[Hiberbee_Dark]TabbedPane.focusColor = #5A5A5A
|
||||
[Hiberbee_Dark]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||
[Hiberbee_Dark]ToggleButton.selectedBackground = $ToggleButton.selectedBackground
|
||||
[Hiberbee_Dark]ToggleButton.toolbar.selectedBackground = $ToggleButton.toolbar.selectedBackground
|
||||
@@ -210,11 +211,17 @@ ToggleButton.endBackground = $ToggleButton.background
|
||||
[GitHub_Contrast]ProgressBar.selectionBackground = #222
|
||||
[GitHub_Contrast]ProgressBar.selectionForeground = #222
|
||||
|
||||
[Light_Owl]List.selectionInactiveForeground = lazy(List.foreground)
|
||||
[Light_Owl]ProgressBar.selectionBackground = #111
|
||||
[Light_Owl]ProgressBar.selectionForeground = #fff
|
||||
[Light_Owl]TabbedPane.selectedForeground = lazy(TabbedPane.foreground)
|
||||
[Light_Owl]Table.selectionForeground = lazy(Table.foreground)
|
||||
|
||||
[Light_Owl_Contrast]List.selectionInactiveForeground = lazy(List.foreground)
|
||||
[Light_Owl_Contrast]ProgressBar.selectionBackground = #111
|
||||
[Light_Owl_Contrast]ProgressBar.selectionForeground = #fff
|
||||
[Light_Owl_Contrast]TabbedPane.selectedForeground = lazy(TabbedPane.foreground)
|
||||
[Light_Owl_Contrast]Table.selectionForeground = lazy(Table.foreground)
|
||||
|
||||
[Material_Lighter]ProgressBar.selectionBackground = #222
|
||||
[Material_Lighter]ProgressBar.selectionForeground = #fff
|
||||
|
||||
@@ -22,8 +22,12 @@ import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.UIDefaults.ActiveValue;
|
||||
import javax.swing.UIDefaults.LazyValue;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||
import com.formdev.flatlaf.ui.FlatLineBorder;
|
||||
|
||||
/**
|
||||
* @author Karl Tauber
|
||||
@@ -46,8 +50,8 @@ public class TestUIDefaultsLoader
|
||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", null ) );
|
||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummyWidth", "1.23", null ) );
|
||||
|
||||
assertEquals( new Insets( 2,2,2,2 ), UIDefaultsLoader.parseValue( "dummyInsets", "2,2,2,2", null ) );
|
||||
assertEquals( new Dimension( 2,2 ), UIDefaultsLoader.parseValue( "dummySize", "2,2", null ) );
|
||||
assertEquals( new Insets( 1,2,3,4 ), UIDefaultsLoader.parseValue( "dummyInsets", "1,2,3,4", null ) );
|
||||
assertEquals( new Dimension( 1,2 ), UIDefaultsLoader.parseValue( "dummySize", "1,2", null ) );
|
||||
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummy", "#f00", null ) );
|
||||
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummyColor", "#f00", null ) );
|
||||
}
|
||||
@@ -70,11 +74,35 @@ public class TestUIDefaultsLoader
|
||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", float.class ) );
|
||||
assertEquals( 1.23f, UIDefaultsLoader.parseValue( "dummy", "1.23", Float.class ) );
|
||||
|
||||
assertEquals( new Insets( 2,2,2,2 ), UIDefaultsLoader.parseValue( "dummy", "2,2,2,2", Insets.class ) );
|
||||
assertEquals( new Dimension( 2,2 ), UIDefaultsLoader.parseValue( "dummy", "2,2", Dimension.class ) );
|
||||
assertEquals( new Insets( 1,2,3,4 ), UIDefaultsLoader.parseValue( "dummy", "1,2,3,4", Insets.class ) );
|
||||
assertEquals( new Dimension( 1,2 ), UIDefaultsLoader.parseValue( "dummy", "1,2", Dimension.class ) );
|
||||
assertEquals( new Color( 0xff0000 ), UIDefaultsLoader.parseValue( "dummy", "#f00", Color.class ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseBorders() {
|
||||
Insets insets = new Insets( 1,2,3,4 );
|
||||
assertBorderEquals( new FlatEmptyBorder( insets ), "1,2,3,4" );
|
||||
assertBorderEquals( new FlatLineBorder( insets, Color.red ), "1,2,3,4,#f00" );
|
||||
assertBorderEquals( new FlatLineBorder( insets, Color.red, 2.5f, 0 ), "1,2,3,4,#f00,2.5" );
|
||||
assertBorderEquals( new FlatLineBorder( insets, Color.red, 2.5f, 6 ), "1,2,3,4,#f00,2.5,6" );
|
||||
assertBorderEquals( new FlatLineBorder( insets, Color.red, 1, 6 ), "1,2,3,4,#f00,,6" );
|
||||
}
|
||||
|
||||
private void assertBorderEquals( Border expected, String actualStyle ) {
|
||||
Border actual = (Border) ((LazyValue)UIDefaultsLoader.parseValue( "dummyBorder", actualStyle, null )).createValue( null );
|
||||
assertEquals( expected.getClass(), actual.getClass() );
|
||||
if( expected instanceof FlatEmptyBorder )
|
||||
assertEquals( ((FlatEmptyBorder)actual).getBorderInsets(), ((FlatEmptyBorder)expected).getBorderInsets() );
|
||||
if( expected instanceof FlatLineBorder ) {
|
||||
FlatLineBorder a = (FlatLineBorder) actual;
|
||||
FlatLineBorder e = (FlatLineBorder) expected;
|
||||
assertEquals( a.getLineColor(), e.getLineColor() );
|
||||
assertEquals( a.getLineThickness(), e.getLineThickness() );
|
||||
assertEquals( a.getArc(), e.getArc() );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseFonts() {
|
||||
// style
|
||||
|
||||
@@ -61,6 +61,7 @@ public class TestFlatStyleClasses
|
||||
UIManager.put( "[style]MenuItem.test", "foreground: #000011" );
|
||||
UIManager.put( "[style]CheckBoxMenuItem.test", "foreground: #000012" );
|
||||
UIManager.put( "[style]RadioButtonMenuItem.test", "foreground: #000013" );
|
||||
UIManager.put( "[style]Panel.test", "foreground: #000034" );
|
||||
UIManager.put( "[style]PasswordField.test", "foreground: #000014" );
|
||||
UIManager.put( "[style]PopupMenu.test", "foreground: #000015" );
|
||||
UIManager.put( "[style]PopupMenuSeparator.test", "foreground: #000016" );
|
||||
@@ -278,6 +279,14 @@ public class TestFlatStyleClasses
|
||||
assertEquals( new Color( 0x000013 ), c.getForeground() );
|
||||
}
|
||||
|
||||
@Test
|
||||
void panel() {
|
||||
JPanel c = new JPanel();
|
||||
c.putClientProperty( FlatClientProperties.STYLE_CLASS, "test" );
|
||||
assertEquals( Color.magenta, c.getBackground() );
|
||||
assertEquals( new Color( 0x000034 ), c.getForeground() );
|
||||
}
|
||||
|
||||
@Test
|
||||
void passwordField() {
|
||||
JPasswordField c = new JPasswordField();
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static com.formdev.flatlaf.ui.TestUtils.assertMapEquals;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Insets;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@@ -257,7 +258,7 @@ public class TestFlatStyleableInfo
|
||||
// FlatListCellBorder
|
||||
"cellMargins", Insets.class,
|
||||
"cellFocusColor", Color.class,
|
||||
"showCellFocusIndicator", boolean.class
|
||||
"showCellFocusIndicator", Boolean.class
|
||||
);
|
||||
|
||||
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
||||
@@ -301,7 +302,6 @@ public class TestFlatStyleableInfo
|
||||
|
||||
Map<String, Class<?>> expected = new LinkedHashMap<>();
|
||||
menuItem( expected );
|
||||
menuItem_arrowIcon( expected );
|
||||
|
||||
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
||||
}
|
||||
@@ -314,7 +314,6 @@ public class TestFlatStyleableInfo
|
||||
Map<String, Class<?>> expected = new LinkedHashMap<>();
|
||||
menuItem( expected );
|
||||
menuItem_checkIcon( expected );
|
||||
menuItem_arrowIcon( expected );
|
||||
|
||||
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
||||
}
|
||||
@@ -327,7 +326,6 @@ public class TestFlatStyleableInfo
|
||||
Map<String, Class<?>> expected = new LinkedHashMap<>();
|
||||
menuItem( expected );
|
||||
menuItem_checkIcon( expected );
|
||||
menuItem_arrowIcon( expected );
|
||||
|
||||
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
||||
}
|
||||
@@ -338,7 +336,8 @@ public class TestFlatStyleableInfo
|
||||
"selectionForeground", Color.class,
|
||||
"disabledForeground", Color.class,
|
||||
"acceleratorForeground", Color.class,
|
||||
"acceleratorSelectionForeground", Color.class
|
||||
"acceleratorSelectionForeground", Color.class,
|
||||
"acceleratorFont", Font.class
|
||||
);
|
||||
|
||||
menuItemRenderer( expected );
|
||||
@@ -346,6 +345,7 @@ public class TestFlatStyleableInfo
|
||||
|
||||
private void menuItemRenderer( Map<String, Class<?>> expected ) {
|
||||
expectedMap( expected,
|
||||
"verticallyAlignText", boolean.class,
|
||||
"minimumWidth", int.class,
|
||||
"minimumIconSize", Dimension.class,
|
||||
"textAcceleratorGap", int.class,
|
||||
@@ -379,6 +379,18 @@ public class TestFlatStyleableInfo
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void panel() {
|
||||
JPanel c = new JPanel();
|
||||
FlatPanelUI ui = (FlatPanelUI) c.getUI();
|
||||
|
||||
Map<String, Class<?>> expected = expectedMap(
|
||||
"arc", int.class
|
||||
);
|
||||
|
||||
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
void passwordField() {
|
||||
JPasswordField c = new JPasswordField();
|
||||
@@ -386,7 +398,8 @@ public class TestFlatStyleableInfo
|
||||
|
||||
Map<String, Class<?>> expected = new LinkedHashMap<>();
|
||||
expectedMap( expected,
|
||||
"showCapsLock", boolean.class
|
||||
"showCapsLock", boolean.class,
|
||||
"showRevealButton", boolean.class
|
||||
);
|
||||
|
||||
// FlatPasswordFieldUI extends FlatTextFieldUI
|
||||
@@ -685,12 +698,14 @@ public class TestFlatStyleableInfo
|
||||
"maximumTabWidth", int.class,
|
||||
"tabHeight", int.class,
|
||||
"tabSelectionHeight", int.class,
|
||||
"cardTabSelectionHeight", int.class,
|
||||
"contentSeparatorHeight", int.class,
|
||||
"showTabSeparators", boolean.class,
|
||||
"tabSeparatorsFullHeight", boolean.class,
|
||||
"hasFullBorder", boolean.class,
|
||||
"tabsOpaque", boolean.class,
|
||||
|
||||
"tabType", String.class,
|
||||
"tabsPopupPolicy", String.class,
|
||||
"scrollButtonsPolicy", String.class,
|
||||
"scrollButtonsPlacement", String.class,
|
||||
@@ -745,7 +760,7 @@ public class TestFlatStyleableInfo
|
||||
// FlatTableCellBorder
|
||||
"cellMargins", Insets.class,
|
||||
"cellFocusColor", Color.class,
|
||||
"showCellFocusIndicator", boolean.class
|
||||
"showCellFocusIndicator", Boolean.class
|
||||
);
|
||||
|
||||
assertMapEquals( expected, ui.getStyleableInfos( c ) );
|
||||
@@ -764,7 +779,7 @@ public class TestFlatStyleableInfo
|
||||
// FlatTableHeaderBorder
|
||||
"cellMargins", Insets.class,
|
||||
"separatorColor", Color.class,
|
||||
"showTrailingVerticalLine", boolean.class,
|
||||
"showTrailingVerticalLine", Boolean.class,
|
||||
|
||||
// FlatAscendingSortIcon and FlatDescendingSortIcon
|
||||
"arrowType", String.class,
|
||||
@@ -809,7 +824,8 @@ public class TestFlatStyleableInfo
|
||||
"focusedBackground", Color.class,
|
||||
"iconTextGap", int.class,
|
||||
"leadingIcon", Icon.class,
|
||||
"trailingIcon", Icon.class
|
||||
"trailingIcon", Icon.class,
|
||||
"showClearButton", boolean.class
|
||||
);
|
||||
|
||||
// border
|
||||
@@ -1132,17 +1148,6 @@ public class TestFlatStyleableInfo
|
||||
assertMapEquals( expected, icon.getStyleableInfos() );
|
||||
}
|
||||
|
||||
@Test
|
||||
void flatMenuItemArrowIcon() {
|
||||
FlatMenuItemArrowIcon icon = new FlatMenuItemArrowIcon();
|
||||
|
||||
// FlatMenuItemArrowIcon extends FlatMenuArrowIcon
|
||||
Map<String, Class<?>> expected = new LinkedHashMap<>();
|
||||
flatMenuArrowIcon( expected );
|
||||
|
||||
assertMapEquals( expected, icon.getStyleableInfos() );
|
||||
}
|
||||
|
||||
private void flatMenuArrowIcon( Map<String, Class<?>> expected ) {
|
||||
expectedMap( expected,
|
||||
"arrowType", String.class,
|
||||
|
||||
@@ -261,6 +261,7 @@ public class TestFlatStyling
|
||||
|
||||
// AbstractButton properties
|
||||
ui.applyStyle( b, "margin: 2,2,2,2" );
|
||||
ui.applyStyle( b, "iconTextGap: 4" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -312,6 +313,9 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "foreground: #fff" );
|
||||
ui.applyStyle( "border: 2,2,2,2,#f00" );
|
||||
ui.applyStyle( "font: italic 12 monospaced" );
|
||||
|
||||
// JComboBox properties
|
||||
ui.applyStyle( "maximumRowCount: 20" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -335,6 +339,7 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "selectionColor: #fff" );
|
||||
ui.applyStyle( "selectedTextColor: #fff" );
|
||||
ui.applyStyle( "disabledTextColor: #fff" );
|
||||
ui.applyStyle( "margin: 2,2,2,2" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -450,7 +455,6 @@ public class TestFlatStyling
|
||||
|
||||
Consumer<String> applyStyle = style -> ui.applyStyle( style );
|
||||
menuItem( applyStyle );
|
||||
menuItem_arrowIcon( applyStyle );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -461,7 +465,6 @@ public class TestFlatStyling
|
||||
Consumer<String> applyStyle = style -> ui.applyStyle( style );
|
||||
menuItem( applyStyle );
|
||||
menuItem_checkIcon( applyStyle );
|
||||
menuItem_arrowIcon( applyStyle );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -472,7 +475,6 @@ public class TestFlatStyling
|
||||
Consumer<String> applyStyle = style -> ui.applyStyle( style );
|
||||
menuItem( applyStyle );
|
||||
menuItem_checkIcon( applyStyle );
|
||||
menuItem_arrowIcon( applyStyle );
|
||||
}
|
||||
|
||||
private void menuItem( Consumer<String> applyStyle ) {
|
||||
@@ -481,6 +483,7 @@ public class TestFlatStyling
|
||||
applyStyle.accept( "disabledForeground: #fff" );
|
||||
applyStyle.accept( "acceleratorForeground: #fff" );
|
||||
applyStyle.accept( "acceleratorSelectionForeground: #fff" );
|
||||
applyStyle.accept( "acceleratorFont: italic 12 monospaced" );
|
||||
|
||||
menuItemRenderer( applyStyle );
|
||||
|
||||
@@ -492,9 +495,11 @@ public class TestFlatStyling
|
||||
|
||||
// AbstractButton properties
|
||||
applyStyle.accept( "margin: 2,2,2,2" );
|
||||
applyStyle.accept( "iconTextGap: 4" );
|
||||
}
|
||||
|
||||
private void menuItemRenderer( Consumer<String> applyStyle ) {
|
||||
applyStyle.accept( "verticallyAlignText: false" );
|
||||
applyStyle.accept( "minimumWidth: 10" );
|
||||
applyStyle.accept( "minimumIconSize: 16,16" );
|
||||
applyStyle.accept( "textAcceleratorGap: 28" );
|
||||
@@ -523,6 +528,20 @@ public class TestFlatStyling
|
||||
applyStyle.accept( "selectionForeground: #fff" );
|
||||
}
|
||||
|
||||
@Test
|
||||
void panel() {
|
||||
JPanel c = new JPanel();
|
||||
FlatPanelUI ui = (FlatPanelUI) c.getUI();
|
||||
|
||||
ui.applyStyle( c, "arc: 8" );
|
||||
|
||||
// JComponent properties
|
||||
ui.applyStyle( c, "background: #fff" );
|
||||
ui.applyStyle( c, "foreground: #fff" );
|
||||
ui.applyStyle( c, "border: 2,2,2,2,#f00" );
|
||||
ui.applyStyle( c, "font: italic 12 monospaced" );
|
||||
}
|
||||
|
||||
@Test
|
||||
void passwordField() {
|
||||
JPasswordField c = new JPasswordField();
|
||||
@@ -532,6 +551,7 @@ public class TestFlatStyling
|
||||
textField( ui );
|
||||
|
||||
ui.applyStyle( "showCapsLock: true" );
|
||||
ui.applyStyle( "showRevealButton: true" );
|
||||
|
||||
// capsLockIcon
|
||||
ui.applyStyle( "capsLockIconColor: #fff" );
|
||||
@@ -605,6 +625,7 @@ public class TestFlatStyling
|
||||
|
||||
// AbstractButton properties
|
||||
ui.applyStyle( b, "margin: 2,2,2,2" );
|
||||
ui.applyStyle( b, "iconTextGap: 4" );
|
||||
|
||||
//---- icon ----
|
||||
|
||||
@@ -701,6 +722,7 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "background: #fff" );
|
||||
ui.applyStyle( "foreground: #fff" );
|
||||
ui.applyStyle( "border: 2,2,2,2,#f00" );
|
||||
ui.applyStyle( "viewportBorder: 2,2,2,2,#f00" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -750,6 +772,8 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "foreground: #fff" );
|
||||
ui.applyStyle( "border: 2,2,2,2,#f00" );
|
||||
ui.applyStyle( "font: italic 12 monospaced" );
|
||||
|
||||
// JSlider properties
|
||||
ui.applyStyle( "minimum: 0" );
|
||||
ui.applyStyle( "maximum: 50" );
|
||||
ui.applyStyle( "value: 20" );
|
||||
@@ -761,12 +785,6 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "paintTicks: true" );
|
||||
ui.applyStyle( "paintTrack: true" );
|
||||
ui.applyStyle( "snapToTicks: true" );
|
||||
|
||||
// JSlider properties
|
||||
ui.applyStyle( "paintLabels: true" );
|
||||
ui.applyStyle( "paintTicks: true" );
|
||||
ui.applyStyle( "paintTrack: true" );
|
||||
ui.applyStyle( "snapToTicks: true" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -849,12 +867,14 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "maximumTabWidth: 100" );
|
||||
ui.applyStyle( "tabHeight: 30" );
|
||||
ui.applyStyle( "tabSelectionHeight: 3" );
|
||||
ui.applyStyle( "cardTabSelectionHeight: 2" );
|
||||
ui.applyStyle( "contentSeparatorHeight: 1" );
|
||||
ui.applyStyle( "showTabSeparators: false" );
|
||||
ui.applyStyle( "tabSeparatorsFullHeight: false" );
|
||||
ui.applyStyle( "hasFullBorder: false" );
|
||||
ui.applyStyle( "tabsOpaque: false" );
|
||||
|
||||
ui.applyStyle( "tabType: card" );
|
||||
ui.applyStyle( "tabsPopupPolicy: asNeeded" );
|
||||
ui.applyStyle( "scrollButtonsPolicy: asNeeded" );
|
||||
ui.applyStyle( "scrollButtonsPlacement: both" );
|
||||
@@ -916,7 +936,6 @@ public class TestFlatStyling
|
||||
// JComponent properties
|
||||
ui.applyStyle( "background: #fff" );
|
||||
ui.applyStyle( "foreground: #fff" );
|
||||
ui.applyStyle( "border: 2,2,2,2,#f00" );
|
||||
ui.applyStyle( "font: italic 12 monospaced" );
|
||||
|
||||
// JTable properties
|
||||
@@ -948,7 +967,6 @@ public class TestFlatStyling
|
||||
// JComponent properties
|
||||
ui.applyStyle( "background: #fff" );
|
||||
ui.applyStyle( "foreground: #fff" );
|
||||
ui.applyStyle( "border: 2,2,2,2,#f00" );
|
||||
ui.applyStyle( "font: italic 12 monospaced" );
|
||||
}
|
||||
|
||||
@@ -973,6 +991,7 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "selectionColor: #fff" );
|
||||
ui.applyStyle( "selectedTextColor: #fff" );
|
||||
ui.applyStyle( "disabledTextColor: #fff" );
|
||||
ui.applyStyle( "margin: 2,2,2,2" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -993,6 +1012,8 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "leadingIcon: com.formdev.flatlaf.icons.FlatSearchIcon" );
|
||||
ui.applyStyle( "trailingIcon: com.formdev.flatlaf.icons.FlatClearIcon" );
|
||||
|
||||
ui.applyStyle( "showClearButton: true" );
|
||||
|
||||
// border
|
||||
flatTextBorder( style -> ui.applyStyle( style ) );
|
||||
|
||||
@@ -1007,6 +1028,7 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "selectionColor: #fff" );
|
||||
ui.applyStyle( "selectedTextColor: #fff" );
|
||||
ui.applyStyle( "disabledTextColor: #fff" );
|
||||
ui.applyStyle( "margin: 2,2,2,2" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1030,6 +1052,7 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "selectionColor: #fff" );
|
||||
ui.applyStyle( "selectedTextColor: #fff" );
|
||||
ui.applyStyle( "disabledTextColor: #fff" );
|
||||
ui.applyStyle( "margin: 2,2,2,2" );
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1340,18 +1363,6 @@ public class TestFlatStyling
|
||||
void flatMenuArrowIcon() {
|
||||
FlatMenuArrowIcon icon = new FlatMenuArrowIcon();
|
||||
|
||||
flatMenuArrowIcon( icon );
|
||||
}
|
||||
|
||||
@Test
|
||||
void flatMenuItemArrowIcon() {
|
||||
FlatMenuItemArrowIcon icon = new FlatMenuItemArrowIcon();
|
||||
|
||||
// FlatMenuItemArrowIcon extends FlatMenuArrowIcon
|
||||
flatMenuArrowIcon( icon );
|
||||
}
|
||||
|
||||
private void flatMenuArrowIcon( FlatMenuArrowIcon icon ) {
|
||||
icon.applyStyleProperty( "arrowType", "chevron" );
|
||||
icon.applyStyleProperty( "arrowColor", Color.WHITE );
|
||||
icon.applyStyleProperty( "disabledArrowColor", Color.WHITE );
|
||||
|
||||
@@ -30,7 +30,7 @@ import com.formdev.flatlaf.FlatSystemProperties;
|
||||
*/
|
||||
public class TestUtils
|
||||
{
|
||||
public static final float[] FACTORS = new float[] { 1f, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 2.75f, 3f, 3.25f, 3.5f, 3.75f, 4f, 5f, 6f };
|
||||
public static final float[] FACTORS = new float[] { 1f }; //, 1.25f, 1.5f, 1.75f, 2f, 2.25f, 2.5f, 2.75f, 3f, 3.25f, 3.5f, 3.75f, 4f, 5f, 6f };
|
||||
|
||||
public static void setup( boolean withFocus ) {
|
||||
System.setProperty( FlatSystemProperties.UI_SCALE, "1x" );
|
||||
|
||||
@@ -22,6 +22,11 @@ import javax.swing.text.DefaultEditorKit;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.extras.FlatSVGIcon;
|
||||
import com.formdev.flatlaf.icons.FlatSearchIcon;
|
||||
import com.formdev.flatlaf.icons.FlatSearchWithHistoryIcon;
|
||||
import net.miginfocom.layout.AC;
|
||||
import net.miginfocom.layout.BoundSize;
|
||||
import net.miginfocom.layout.ConstraintParser;
|
||||
import net.miginfocom.layout.DimConstraint;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
@@ -32,6 +37,51 @@ class BasicComponentsPanel
|
||||
{
|
||||
BasicComponentsPanel() {
|
||||
initComponents();
|
||||
|
||||
// show reveal button for password field
|
||||
// to enable this for all password fields use:
|
||||
// UIManager.put( "PasswordField.showRevealButton", true );
|
||||
passwordField1.putClientProperty( FlatClientProperties.STYLE, "showRevealButton: true" );
|
||||
|
||||
// search history button
|
||||
JButton searchHistoryButton = new JButton( new FlatSearchWithHistoryIcon( true ) );
|
||||
searchHistoryButton.setToolTipText( "Search History" );
|
||||
searchHistoryButton.addActionListener( e -> {
|
||||
JPopupMenu popupMenu = new JPopupMenu();
|
||||
popupMenu.add( "(empty)" );
|
||||
popupMenu.show( searchHistoryButton, 0, searchHistoryButton.getHeight() );
|
||||
} );
|
||||
compsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_LEADING_COMPONENT, searchHistoryButton );
|
||||
|
||||
// match case button
|
||||
JToggleButton matchCaseButton = new JToggleButton( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/matchCase.svg" ) );
|
||||
matchCaseButton.setRolloverIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/matchCaseHovered.svg" ) );
|
||||
matchCaseButton.setSelectedIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/matchCaseSelected.svg" ) );
|
||||
matchCaseButton.setToolTipText( "Match Case" );
|
||||
|
||||
// whole words button
|
||||
JToggleButton wordsButton = new JToggleButton( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/words.svg" ) );
|
||||
wordsButton.setRolloverIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/wordsHovered.svg" ) );
|
||||
wordsButton.setSelectedIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/wordsSelected.svg" ) );
|
||||
wordsButton.setToolTipText( "Whole Words" );
|
||||
|
||||
// regex button
|
||||
JToggleButton regexButton = new JToggleButton( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/regex.svg" ) );
|
||||
regexButton.setRolloverIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/regexHovered.svg" ) );
|
||||
regexButton.setSelectedIcon( new FlatSVGIcon( "com/formdev/flatlaf/demo/icons/regexSelected.svg" ) );
|
||||
regexButton.setToolTipText( "Regular Expression" );
|
||||
|
||||
// search toolbar
|
||||
JToolBar searchToolbar = new JToolBar();
|
||||
searchToolbar.add( matchCaseButton );
|
||||
searchToolbar.add( wordsButton );
|
||||
searchToolbar.addSeparator();
|
||||
searchToolbar.add( regexButton );
|
||||
compsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_TRAILING_COMPONENT, searchToolbar );
|
||||
|
||||
// show clear button (if text field is not empty)
|
||||
compsTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_SHOW_CLEAR_BUTTON, true );
|
||||
clearTextField.putClientProperty( FlatClientProperties.TEXT_FIELD_SHOW_CLEAR_BUTTON, true );
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
@@ -83,7 +133,7 @@ class BasicComponentsPanel
|
||||
JFormattedTextField formattedTextField4 = new JFormattedTextField();
|
||||
JFormattedTextField formattedTextField5 = new JFormattedTextField();
|
||||
JLabel passwordFieldLabel = new JLabel();
|
||||
JPasswordField passwordField1 = new JPasswordField();
|
||||
passwordField1 = new JPasswordField();
|
||||
JPasswordField passwordField2 = new JPasswordField();
|
||||
JPasswordField passwordField3 = new JPasswordField();
|
||||
JPasswordField passwordField4 = new JPasswordField();
|
||||
@@ -130,6 +180,25 @@ class BasicComponentsPanel
|
||||
JTextField leadingIconTextField = new JTextField();
|
||||
JTextField trailingIconTextField = new JTextField();
|
||||
JTextField iconsTextField = new JTextField();
|
||||
JLabel compsLabel = new JLabel();
|
||||
compsTextField = new JTextField();
|
||||
clearTextField = new JTextField();
|
||||
JLabel fontsLabel = new JLabel();
|
||||
JLabel h00Label = new JLabel();
|
||||
JLabel h0Label = new JLabel();
|
||||
JLabel h1Label = new JLabel();
|
||||
JLabel h2Label = new JLabel();
|
||||
JLabel h3Label = new JLabel();
|
||||
JLabel h4Label = new JLabel();
|
||||
JLabel lightLabel = new JLabel();
|
||||
JLabel semiboldLabel = new JLabel();
|
||||
JLabel fontZoomLabel = new JLabel();
|
||||
JLabel largeLabel = new JLabel();
|
||||
JLabel defaultLabel = new JLabel();
|
||||
JLabel mediumLabel = new JLabel();
|
||||
JLabel smallLabel = new JLabel();
|
||||
JLabel miniLabel = new JLabel();
|
||||
JLabel monospacedLabel = new JLabel();
|
||||
JPopupMenu popupMenu1 = new JPopupMenu();
|
||||
JMenuItem cutMenuItem = new JMenuItem();
|
||||
JMenuItem copyMenuItem = new JMenuItem();
|
||||
@@ -160,6 +229,9 @@ class BasicComponentsPanel
|
||||
"[]para" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]" +
|
||||
"[]0" +
|
||||
"[]"));
|
||||
|
||||
//---- labelLabel ----
|
||||
@@ -667,6 +739,94 @@ class BasicComponentsPanel
|
||||
iconsTextField.setText("text");
|
||||
add(iconsTextField, "cell 3 14,growx");
|
||||
|
||||
//---- compsLabel ----
|
||||
compsLabel.setText("Leading/trailing comp.:");
|
||||
add(compsLabel, "cell 0 15");
|
||||
add(compsTextField, "cell 1 15 2 1,growx");
|
||||
|
||||
//---- clearTextField ----
|
||||
clearTextField.setText("clear me");
|
||||
add(clearTextField, "cell 3 15,growx");
|
||||
|
||||
//---- fontsLabel ----
|
||||
fontsLabel.setText("Typography / Fonts:");
|
||||
add(fontsLabel, "cell 0 16");
|
||||
|
||||
//---- h00Label ----
|
||||
h00Label.setText("H00");
|
||||
h00Label.putClientProperty("FlatLaf.styleClass", "h00");
|
||||
add(h00Label, "cell 1 16 5 1");
|
||||
|
||||
//---- h0Label ----
|
||||
h0Label.setText("H0");
|
||||
h0Label.putClientProperty("FlatLaf.styleClass", "h0");
|
||||
add(h0Label, "cell 1 16 5 1");
|
||||
|
||||
//---- h1Label ----
|
||||
h1Label.setText("H1");
|
||||
h1Label.putClientProperty("FlatLaf.styleClass", "h1");
|
||||
add(h1Label, "cell 1 16 5 1");
|
||||
|
||||
//---- h2Label ----
|
||||
h2Label.setText("H2");
|
||||
h2Label.putClientProperty("FlatLaf.styleClass", "h2");
|
||||
add(h2Label, "cell 1 16 5 1");
|
||||
|
||||
//---- h3Label ----
|
||||
h3Label.setText("H3");
|
||||
h3Label.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
add(h3Label, "cell 1 16 5 1");
|
||||
|
||||
//---- h4Label ----
|
||||
h4Label.setText("H4");
|
||||
h4Label.putClientProperty("FlatLaf.styleClass", "h4");
|
||||
add(h4Label, "cell 1 16 5 1");
|
||||
|
||||
//---- lightLabel ----
|
||||
lightLabel.setText("light");
|
||||
lightLabel.putClientProperty("FlatLaf.style", "font: 200% $light.font");
|
||||
add(lightLabel, "cell 1 16 5 1,gapx 30");
|
||||
|
||||
//---- semiboldLabel ----
|
||||
semiboldLabel.setText("semibold");
|
||||
semiboldLabel.putClientProperty("FlatLaf.style", "font: 200% $semibold.font");
|
||||
add(semiboldLabel, "cell 1 16 5 1");
|
||||
|
||||
//---- fontZoomLabel ----
|
||||
fontZoomLabel.setText("(200%)");
|
||||
fontZoomLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
fontZoomLabel.setEnabled(false);
|
||||
add(fontZoomLabel, "cell 1 16 5 1");
|
||||
|
||||
//---- largeLabel ----
|
||||
largeLabel.setText("large");
|
||||
largeLabel.putClientProperty("FlatLaf.styleClass", "large");
|
||||
add(largeLabel, "cell 1 17 5 1");
|
||||
|
||||
//---- defaultLabel ----
|
||||
defaultLabel.setText("default");
|
||||
add(defaultLabel, "cell 1 17 5 1");
|
||||
|
||||
//---- mediumLabel ----
|
||||
mediumLabel.setText("medium");
|
||||
mediumLabel.putClientProperty("FlatLaf.styleClass", "medium");
|
||||
add(mediumLabel, "cell 1 17 5 1");
|
||||
|
||||
//---- smallLabel ----
|
||||
smallLabel.setText("small");
|
||||
smallLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
add(smallLabel, "cell 1 17 5 1");
|
||||
|
||||
//---- miniLabel ----
|
||||
miniLabel.setText("mini");
|
||||
miniLabel.putClientProperty("FlatLaf.styleClass", "mini");
|
||||
add(miniLabel, "cell 1 17 5 1");
|
||||
|
||||
//---- monospacedLabel ----
|
||||
monospacedLabel.setText("monospaced");
|
||||
monospacedLabel.putClientProperty("FlatLaf.styleClass", "monospaced");
|
||||
add(monospacedLabel, "cell 1 17 5 1,gapx 30");
|
||||
|
||||
//======== popupMenu1 ========
|
||||
{
|
||||
|
||||
@@ -705,40 +865,61 @@ class BasicComponentsPanel
|
||||
if( FlatLafDemo.screenshotsMode ) {
|
||||
// hide some components
|
||||
Component[] hiddenComponents = {
|
||||
labelLabel, label1, label2,
|
||||
button13, button14, button15, button16, comboBox5, comboBox6,
|
||||
textField6, passwordField5,
|
||||
|
||||
textFieldLabel, textField2, textField4, textField6,
|
||||
formattedTextFieldLabel, formattedTextField1, formattedTextField2, formattedTextField3, formattedTextField4, formattedTextField5,
|
||||
passwordFieldLabel, passwordField1, passwordField2, passwordField3, passwordField4, passwordField5,
|
||||
textAreaLabel, scrollPane1, scrollPane2, scrollPane3, scrollPane4, textArea5,
|
||||
editorPaneLabel, scrollPane5, scrollPane6, scrollPane7, scrollPane8, editorPane5,
|
||||
textPaneLabel, scrollPane9, scrollPane10, scrollPane11, scrollPane12, textPane5,
|
||||
|
||||
errorHintsLabel, errorHintsTextField, errorHintsComboBox, errorHintsSpinner,
|
||||
warningHintsLabel, warningHintsTextField, warningHintsComboBox, warningHintsSpinner,
|
||||
|
||||
fontZoomLabel,
|
||||
};
|
||||
for( Component c : hiddenComponents )
|
||||
c.setVisible( false );
|
||||
|
||||
// move leading/trailing icon fields and password fields some rows up
|
||||
Component[] formattedTextFields = { formattedTextFieldLabel, formattedTextField1, formattedTextField2, formattedTextField3, formattedTextField4 };
|
||||
Component[] passwordFields = { passwordFieldLabel, passwordField1, passwordField2, passwordField3, passwordField4 };
|
||||
Component[] iconsFields = { iconsLabel, leadingIconTextField, trailingIconTextField, iconsTextField };
|
||||
// update layout (change row gaps to zero)
|
||||
MigLayout layout = (MigLayout) getLayout();
|
||||
for( int i = 0; i < iconsFields.length; i++ ) {
|
||||
Object cons = layout.getComponentConstraints( passwordFields[i] );
|
||||
layout.setComponentConstraints( iconsFields[i], cons );
|
||||
}
|
||||
for( int i = 0; i < passwordFields.length; i++ ) {
|
||||
Object cons = layout.getComponentConstraints( formattedTextFields[i] );
|
||||
layout.setComponentConstraints( passwordFields[i], cons );
|
||||
}
|
||||
Object rowCons = layout.getRowConstraints();
|
||||
AC ac = (rowCons instanceof String)
|
||||
? ConstraintParser.parseColumnConstraints( (String) rowCons )
|
||||
: (AC) rowCons;
|
||||
BoundSize zeroGap = ConstraintParser.parseBoundSize( "0", true, true );
|
||||
DimConstraint[] rows = ac.getConstaints();
|
||||
rows[6].setGapBefore( zeroGap );
|
||||
rows[7].setGapBefore( zeroGap );
|
||||
rows[8].setGapBefore( zeroGap );
|
||||
rows[9].setGapBefore( zeroGap );
|
||||
rows[10].setGapBefore( zeroGap );
|
||||
rows[11].setGapBefore( zeroGap );
|
||||
rows[11].setGapAfter( zeroGap );
|
||||
rows[12].setGapBefore( zeroGap );
|
||||
rows[13].setGapBefore( zeroGap );
|
||||
rows[16].setGapBefore( zeroGap );
|
||||
layout.setRowConstraints( ac );
|
||||
|
||||
// move two text field into same row as spinners
|
||||
spinnerLabel.setText( "JSpinner / JTextField:" );
|
||||
layout.setComponentConstraints( textField1, "cell 3 5,growx" );
|
||||
layout.setComponentConstraints( textField3, "cell 4 5,growx" );
|
||||
|
||||
// make "Not editable disabled" combobox smaller
|
||||
Object cons = layout.getComponentConstraints( comboBox4 );
|
||||
layout.setComponentConstraints( comboBox4, cons + ",width 50:50" );
|
||||
|
||||
revalidate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private JPasswordField passwordField1;
|
||||
private JTextField compsTextField;
|
||||
private JTextField clearTextField;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.4.0.360" Java: "16" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.5.0.404" Java: "17" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -9,7 +9,7 @@ new FormModel {
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[][sizegroup 1][sizegroup 1][sizegroup 1][][]"
|
||||
"$rowConstraints": "[][][][][][][][][][][][]para[][][]"
|
||||
"$rowConstraints": "[][][][][][][][][][][][]para[][][][][]0[]"
|
||||
} ) {
|
||||
name: "this"
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
@@ -375,6 +375,9 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JPasswordField" ) {
|
||||
name: "passwordField1"
|
||||
"text": "Editable"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 8,growx"
|
||||
} )
|
||||
@@ -671,9 +674,143 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 14,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "compsLabel"
|
||||
"text": "Leading/trailing comp.:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 15"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "compsTextField"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 15 2 1,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
name: "clearTextField"
|
||||
"text": "clear me"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 15,growx"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fontsLabel"
|
||||
"text": "Typography / Fonts:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 16"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h00Label"
|
||||
"text": "H00"
|
||||
"$client.FlatLaf.styleClass": "h00"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h0Label"
|
||||
"text": "H0"
|
||||
"$client.FlatLaf.styleClass": "h0"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h1Label"
|
||||
"text": "H1"
|
||||
"$client.FlatLaf.styleClass": "h1"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h2Label"
|
||||
"text": "H2"
|
||||
"$client.FlatLaf.styleClass": "h2"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h3Label"
|
||||
"text": "H3"
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "h4Label"
|
||||
"text": "H4"
|
||||
"$client.FlatLaf.styleClass": "h4"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "lightLabel"
|
||||
"text": "light"
|
||||
"$client.FlatLaf.style": "font: 200% $light.font"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1,gapx 30"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "semiboldLabel"
|
||||
"text": "semibold"
|
||||
"$client.FlatLaf.style": "font: 200% $semibold.font"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "fontZoomLabel"
|
||||
"text": "(200%)"
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
"enabled": false
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 16 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "largeLabel"
|
||||
"text": "large"
|
||||
"$client.FlatLaf.styleClass": "large"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 17 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "defaultLabel"
|
||||
"text": "default"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 17 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "mediumLabel"
|
||||
"text": "medium"
|
||||
"$client.FlatLaf.styleClass": "medium"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 17 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "smallLabel"
|
||||
"text": "small"
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 17 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "miniLabel"
|
||||
"text": "mini"
|
||||
"$client.FlatLaf.styleClass": "mini"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 17 5 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "monospacedLabel"
|
||||
"text": "monospaced"
|
||||
"$client.FlatLaf.styleClass": "monospaced"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 17 5 1,gapx 30"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 920, 480 )
|
||||
"size": new java.awt.Dimension( 920, 550 )
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPopupMenu", new FormLayoutManager( class javax.swing.JPopupMenu ) ) {
|
||||
name: "popupMenu1"
|
||||
@@ -693,7 +830,7 @@ new FormModel {
|
||||
"mnemonic": 80
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 500 )
|
||||
"location": new java.awt.Point( 0, 570 )
|
||||
"size": new java.awt.Dimension( 91, 87 )
|
||||
} )
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.prefs.Preferences;
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.DefaultEditorKit;
|
||||
import javax.swing.text.StyleContext;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatDarculaLaf;
|
||||
import com.formdev.flatlaf.FlatDarkLaf;
|
||||
import com.formdev.flatlaf.FlatIntelliJLaf;
|
||||
@@ -50,7 +51,6 @@ import com.formdev.flatlaf.ui.JBRCustomDecorations;
|
||||
import com.formdev.flatlaf.util.ColorFunctions;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import net.miginfocom.layout.ConstraintParser;
|
||||
import net.miginfocom.layout.LC;
|
||||
import net.miginfocom.layout.UnitValue;
|
||||
@@ -160,8 +160,7 @@ class DemoFrame
|
||||
|
||||
private void aboutActionPerformed() {
|
||||
JLabel titleLabel = new JLabel( "FlatLaf Demo" );
|
||||
Font titleFont = titleLabel.getFont();
|
||||
titleLabel.setFont( titleFont.deriveFont( (float) titleFont.getSize() + UIScale.scale( 6 ) ) );
|
||||
titleLabel.putClientProperty( FlatClientProperties.STYLE_CLASS, "h1" );
|
||||
|
||||
String link = "https://www.formdev.com/flatlaf/";
|
||||
JLabel linkLabel = new JLabel( "<html><a href=\"#\">" + link + "</a></html>" );
|
||||
@@ -216,6 +215,7 @@ class DemoFrame
|
||||
|
||||
menuBarEmbeddedCheckBoxMenuItem.setEnabled( windowDecorations );
|
||||
unifiedTitleBarMenuItem.setEnabled( windowDecorations );
|
||||
showTitleBarIconMenuItem.setEnabled( windowDecorations );
|
||||
}
|
||||
|
||||
private void menuBarEmbeddedChanged() {
|
||||
@@ -228,6 +228,16 @@ class DemoFrame
|
||||
FlatLaf.repaintAllFramesAndDialogs();
|
||||
}
|
||||
|
||||
private void showTitleBarIcon() {
|
||||
boolean showIcon = showTitleBarIconMenuItem.isSelected();
|
||||
|
||||
// for main frame (because already created)
|
||||
getRootPane().putClientProperty( FlatClientProperties.TITLE_BAR_SHOW_ICON, showIcon );
|
||||
|
||||
// for other not yet created frames/dialogs
|
||||
UIManager.put( "TitlePane.showIcon", showIcon );
|
||||
}
|
||||
|
||||
private void underlineMenuSelection() {
|
||||
UIManager.put( "MenuItem.selectionType", underlineMenuSelectionMenuItem.isSelected() ? "underline" : null );
|
||||
}
|
||||
@@ -467,6 +477,7 @@ class DemoFrame
|
||||
windowDecorationsCheckBoxMenuItem = new JCheckBoxMenuItem();
|
||||
menuBarEmbeddedCheckBoxMenuItem = new JCheckBoxMenuItem();
|
||||
unifiedTitleBarMenuItem = new JCheckBoxMenuItem();
|
||||
showTitleBarIconMenuItem = new JCheckBoxMenuItem();
|
||||
underlineMenuSelectionMenuItem = new JCheckBoxMenuItem();
|
||||
alwaysShowMnemonicsMenuItem = new JCheckBoxMenuItem();
|
||||
animatedLafChangeMenuItem = new JCheckBoxMenuItem();
|
||||
@@ -718,13 +729,11 @@ class DemoFrame
|
||||
|
||||
//---- windowDecorationsCheckBoxMenuItem ----
|
||||
windowDecorationsCheckBoxMenuItem.setText("Window decorations");
|
||||
windowDecorationsCheckBoxMenuItem.setSelected(true);
|
||||
windowDecorationsCheckBoxMenuItem.addActionListener(e -> windowDecorationsChanged());
|
||||
optionsMenu.add(windowDecorationsCheckBoxMenuItem);
|
||||
|
||||
//---- menuBarEmbeddedCheckBoxMenuItem ----
|
||||
menuBarEmbeddedCheckBoxMenuItem.setText("Embedded menu bar");
|
||||
menuBarEmbeddedCheckBoxMenuItem.setSelected(true);
|
||||
menuBarEmbeddedCheckBoxMenuItem.addActionListener(e -> menuBarEmbeddedChanged());
|
||||
optionsMenu.add(menuBarEmbeddedCheckBoxMenuItem);
|
||||
|
||||
@@ -733,6 +742,11 @@ class DemoFrame
|
||||
unifiedTitleBarMenuItem.addActionListener(e -> unifiedTitleBar());
|
||||
optionsMenu.add(unifiedTitleBarMenuItem);
|
||||
|
||||
//---- showTitleBarIconMenuItem ----
|
||||
showTitleBarIconMenuItem.setText("Show window title bar icon");
|
||||
showTitleBarIconMenuItem.addActionListener(e -> showTitleBarIcon());
|
||||
optionsMenu.add(showTitleBarIconMenuItem);
|
||||
|
||||
//---- underlineMenuSelectionMenuItem ----
|
||||
underlineMenuSelectionMenuItem.setText("Use underline menu selection");
|
||||
underlineMenuSelectionMenuItem.addActionListener(e -> underlineMenuSelection());
|
||||
@@ -876,6 +890,11 @@ class DemoFrame
|
||||
pasteMenuItem.addActionListener( new DefaultEditorKit.PasteAction() );
|
||||
|
||||
if( FlatLaf.supportsNativeWindowDecorations() ) {
|
||||
windowDecorationsCheckBoxMenuItem.setSelected( FlatLaf.isUseNativeWindowDecorations() );
|
||||
menuBarEmbeddedCheckBoxMenuItem.setSelected( UIManager.getBoolean( "TitlePane.menuBarEmbedded" ) );
|
||||
unifiedTitleBarMenuItem.setSelected( UIManager.getBoolean( "TitlePane.unifiedBackground" ) );
|
||||
showTitleBarIconMenuItem.setSelected( UIManager.getBoolean( "TitlePane.showIcon" ) );
|
||||
|
||||
if( JBRCustomDecorations.isSupported() ) {
|
||||
// If the JetBrains Runtime is used, it forces the use of it's own custom
|
||||
// window decoration, which can not disabled.
|
||||
@@ -885,6 +904,7 @@ class DemoFrame
|
||||
unsupported( windowDecorationsCheckBoxMenuItem );
|
||||
unsupported( menuBarEmbeddedCheckBoxMenuItem );
|
||||
unsupported( unifiedTitleBarMenuItem );
|
||||
unsupported( showTitleBarIconMenuItem );
|
||||
}
|
||||
|
||||
if( SystemInfo.isMacOS )
|
||||
@@ -917,6 +937,7 @@ class DemoFrame
|
||||
private JCheckBoxMenuItem windowDecorationsCheckBoxMenuItem;
|
||||
private JCheckBoxMenuItem menuBarEmbeddedCheckBoxMenuItem;
|
||||
private JCheckBoxMenuItem unifiedTitleBarMenuItem;
|
||||
private JCheckBoxMenuItem showTitleBarIconMenuItem;
|
||||
private JCheckBoxMenuItem underlineMenuSelectionMenuItem;
|
||||
private JCheckBoxMenuItem alwaysShowMnemonicsMenuItem;
|
||||
private JCheckBoxMenuItem animatedLafChangeMenuItem;
|
||||
|
||||
@@ -354,7 +354,6 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "windowDecorationsCheckBoxMenuItem"
|
||||
"text": "Window decorations"
|
||||
"selected": true
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -363,7 +362,6 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "menuBarEmbeddedCheckBoxMenuItem"
|
||||
"text": "Embedded menu bar"
|
||||
"selected": true
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
@@ -377,6 +375,14 @@ new FormModel {
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "unifiedTitleBar", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "showTitleBarIconMenuItem"
|
||||
"text": "Show window title bar icon"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTitleBarIcon", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBoxMenuItem" ) {
|
||||
name: "underlineMenuSelectionMenuItem"
|
||||
"text": "Use underline menu selection"
|
||||
|
||||
@@ -71,8 +71,11 @@ public class FlatLafDemo
|
||||
// create frame
|
||||
DemoFrame frame = new DemoFrame();
|
||||
|
||||
if( FlatLafDemo.screenshotsMode )
|
||||
frame.setPreferredSize( new Dimension( 1660, 840 ) );
|
||||
if( FlatLafDemo.screenshotsMode ) {
|
||||
frame.setPreferredSize( SystemInfo.isJava_9_orLater
|
||||
? new Dimension( 830, 440 )
|
||||
: new Dimension( 1660, 880 ) );
|
||||
}
|
||||
|
||||
// show frame
|
||||
frame.pack();
|
||||
|
||||
@@ -18,11 +18,15 @@ package com.formdev.flatlaf.demo;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.ui.FlatDropShadowBorder;
|
||||
import com.formdev.flatlaf.ui.FlatPopupMenuBorder;
|
||||
import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import net.miginfocom.swing.*;
|
||||
@@ -87,6 +91,9 @@ class HintManager
|
||||
|
||||
initComponents();
|
||||
|
||||
setOpaque( false );
|
||||
updateBalloonBorder();
|
||||
|
||||
hintLabel.setText( "<html>" + hint.message + "</html>" );
|
||||
|
||||
// grab all mouse events to avoid that components overlapped
|
||||
@@ -98,8 +105,28 @@ class HintManager
|
||||
public void updateUI() {
|
||||
super.updateUI();
|
||||
|
||||
setBackground( UIManager.getColor( "HintPanel.backgroundColor" ) );
|
||||
setBorder( new FlatPopupMenuBorder() );
|
||||
if( UIManager.getLookAndFeel() instanceof FlatLaf )
|
||||
setBackground( UIManager.getColor( "HintPanel.backgroundColor" ) );
|
||||
else {
|
||||
// using nonUIResource() because otherwise Nimbus does not fill the background
|
||||
setBackground( FlatUIUtils.nonUIResource( UIManager.getColor( "info" ) ) );
|
||||
}
|
||||
|
||||
if( hint != null )
|
||||
updateBalloonBorder();
|
||||
}
|
||||
|
||||
private void updateBalloonBorder() {
|
||||
int direction;
|
||||
switch( hint.position ) {
|
||||
case SwingConstants.LEFT: direction = SwingConstants.RIGHT; break;
|
||||
case SwingConstants.TOP: direction = SwingConstants.BOTTOM; break;
|
||||
case SwingConstants.RIGHT: direction = SwingConstants.LEFT; break;
|
||||
case SwingConstants.BOTTOM: direction = SwingConstants.TOP; break;
|
||||
default: throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
setBorder( new BalloonBorder( direction, FlatUIUtils.getUIColor( "PopupMenu.borderColor", Color.gray ) ) );
|
||||
}
|
||||
|
||||
void showHint() {
|
||||
@@ -115,11 +142,6 @@ class HintManager
|
||||
public void updateUI() {
|
||||
super.updateUI();
|
||||
|
||||
setBorder( new FlatDropShadowBorder(
|
||||
UIManager.getColor( "Popup.dropShadowColor" ),
|
||||
UIManager.getInsets( "Popup.dropShadowInsets" ),
|
||||
FlatUIUtils.getUIFloat( "Popup.dropShadowOpacity", 0.5f ) ) );
|
||||
|
||||
// use invokeLater because at this time the UI delegates
|
||||
// of child components are not yet updated
|
||||
EventQueue.invokeLater( () -> {
|
||||
@@ -216,4 +238,127 @@ class HintManager
|
||||
private JButton gotItButton;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
|
||||
//---- class BalloonBorder ------------------------------------------------
|
||||
|
||||
private static class BalloonBorder
|
||||
extends FlatEmptyBorder
|
||||
{
|
||||
private static int ARC = 8;
|
||||
private static int ARROW_XY = 16;
|
||||
private static int ARROW_SIZE = 8;
|
||||
private static int SHADOW_SIZE = 6;
|
||||
private static int SHADOW_TOP_SIZE = 3;
|
||||
private static int SHADOW_SIZE2 = SHADOW_SIZE + 2;
|
||||
|
||||
private final int direction;
|
||||
private final Color borderColor;
|
||||
|
||||
private final Border shadowBorder;
|
||||
|
||||
public BalloonBorder( int direction, Color borderColor ) {
|
||||
super( 1 + SHADOW_TOP_SIZE, 1 + SHADOW_SIZE, 1 + SHADOW_SIZE, 1 + SHADOW_SIZE );
|
||||
|
||||
this.direction = direction;
|
||||
this.borderColor = borderColor;
|
||||
|
||||
switch( direction ) {
|
||||
case SwingConstants.LEFT: left += ARROW_SIZE; break;
|
||||
case SwingConstants.TOP: top += ARROW_SIZE; break;
|
||||
case SwingConstants.RIGHT: right += ARROW_SIZE; break;
|
||||
case SwingConstants.BOTTOM: bottom += ARROW_SIZE; break;
|
||||
}
|
||||
|
||||
shadowBorder = UIManager.getLookAndFeel() instanceof FlatLaf
|
||||
? new FlatDropShadowBorder(
|
||||
UIManager.getColor( "Popup.dropShadowColor" ),
|
||||
new Insets( SHADOW_SIZE2, SHADOW_SIZE2, SHADOW_SIZE2, SHADOW_SIZE2 ),
|
||||
FlatUIUtils.getUIFloat( "Popup.dropShadowOpacity", 0.5f ) )
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
try {
|
||||
FlatUIUtils.setRenderingHints( g2 );
|
||||
g2.translate( x, y );
|
||||
|
||||
// shadow coordinates
|
||||
int sx = 0;
|
||||
int sy = 0;
|
||||
int sw = width;
|
||||
int sh = height;
|
||||
int arrowSize = UIScale.scale( ARROW_SIZE );
|
||||
switch( direction ) {
|
||||
case SwingConstants.LEFT: sx += arrowSize; sw -= arrowSize; break;
|
||||
case SwingConstants.TOP: sy += arrowSize; sh -= arrowSize; break;
|
||||
case SwingConstants.RIGHT: sw -= arrowSize; break;
|
||||
case SwingConstants.BOTTOM: sh -= arrowSize; break;
|
||||
}
|
||||
|
||||
// paint shadow
|
||||
if( shadowBorder != null )
|
||||
shadowBorder.paintBorder( c, g2, sx, sy, sw, sh );
|
||||
|
||||
// create balloon shape
|
||||
int bx = UIScale.scale( SHADOW_SIZE );
|
||||
int by = UIScale.scale( SHADOW_TOP_SIZE );
|
||||
int bw = width - UIScale.scale( SHADOW_SIZE + SHADOW_SIZE );
|
||||
int bh = height - UIScale.scale( SHADOW_TOP_SIZE + SHADOW_SIZE );
|
||||
g2.translate( bx, by );
|
||||
Shape shape = createBalloonShape( bw, bh );
|
||||
|
||||
// fill balloon background
|
||||
g2.setColor( c.getBackground() );
|
||||
g2.fill( shape );
|
||||
|
||||
// paint balloon border
|
||||
g2.setColor( borderColor );
|
||||
g2.setStroke( new BasicStroke( UIScale.scale( 1f ) ) );
|
||||
g2.draw( shape );
|
||||
} finally {
|
||||
g2.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private Shape createBalloonShape( int width, int height ) {
|
||||
int arc = UIScale.scale( ARC );
|
||||
int xy = UIScale.scale( ARROW_XY );
|
||||
int awh = UIScale.scale( ARROW_SIZE );
|
||||
|
||||
Shape rect;
|
||||
Shape arrow;
|
||||
switch( direction ) {
|
||||
case SwingConstants.LEFT:
|
||||
rect = new RoundRectangle2D.Float( awh, 0, width - 1 - awh, height - 1, arc, arc );
|
||||
arrow = FlatUIUtils.createPath( awh,xy, 0,xy+awh, awh,xy+awh+awh );
|
||||
break;
|
||||
|
||||
case SwingConstants.TOP:
|
||||
rect = new RoundRectangle2D.Float( 0, awh, width - 1, height - 1 - awh, arc, arc );
|
||||
arrow = FlatUIUtils.createPath( xy,awh, xy+awh,0, xy+awh+awh,awh );
|
||||
break;
|
||||
|
||||
case SwingConstants.RIGHT:
|
||||
rect = new RoundRectangle2D.Float( 0, 0, width - 1 - awh, height - 1, arc, arc );
|
||||
int x = width - 1 - awh;
|
||||
arrow = FlatUIUtils.createPath( x,xy, x+awh,xy+awh, x,xy+awh+awh );
|
||||
break;
|
||||
|
||||
case SwingConstants.BOTTOM:
|
||||
rect = new RoundRectangle2D.Float( 0, 0, width - 1, height - 1 - awh, arc, arc );
|
||||
int y = height - 1 - awh;
|
||||
arrow = FlatUIUtils.createPath( xy,y, xy+awh,y+awh, xy+awh+awh,y );
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
Area area = new Area( rect );
|
||||
area.add( new Area( arrow ) );
|
||||
return area;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import net.miginfocom.swing.*;
|
||||
|
||||
/**
|
||||
@@ -44,6 +45,29 @@ class OptionPanePanel
|
||||
"OK",
|
||||
"Cancel",
|
||||
} );
|
||||
|
||||
if( FlatLaf.supportsNativeWindowDecorations() ) {
|
||||
updateShowTitleBarIcon();
|
||||
|
||||
UIManager.getDefaults().addPropertyChangeListener( e -> {
|
||||
switch( e.getPropertyName() ) {
|
||||
case "TitlePane.showIcon":
|
||||
case "TitlePane.useWindowDecorations":
|
||||
updateShowTitleBarIcon();
|
||||
break;
|
||||
}
|
||||
} );
|
||||
} else
|
||||
showTitleBarIconCheckBox.setEnabled( false );
|
||||
}
|
||||
|
||||
private void updateShowTitleBarIcon() {
|
||||
showTitleBarIconCheckBox.setEnabled( UIManager.getBoolean( "TitlePane.showIcon" ) &&
|
||||
FlatLaf.isUseNativeWindowDecorations() );
|
||||
}
|
||||
|
||||
private void showTitleBarIcon() {
|
||||
UIManager.put( "OptionPane.showIcon", showTitleBarIconCheckBox.isSelected() );
|
||||
}
|
||||
|
||||
private void initComponents() {
|
||||
@@ -54,6 +78,7 @@ class OptionPanePanel
|
||||
JPanel panel1 = new JPanel();
|
||||
JOptionPane plainOptionPane = new JOptionPane();
|
||||
plainShowDialogLabel = new OptionPanePanel.ShowDialogLinkLabel();
|
||||
showTitleBarIconCheckBox = new JCheckBox();
|
||||
JLabel errorLabel = new JLabel();
|
||||
JPanel panel2 = new JPanel();
|
||||
JOptionPane errorOptionPane = new JOptionPane();
|
||||
@@ -93,7 +118,7 @@ class OptionPanePanel
|
||||
//======== panel9 ========
|
||||
{
|
||||
panel9.setLayout(new MigLayout(
|
||||
"flowy,insets dialog,hidemode 3",
|
||||
"insets dialog,hidemode 3",
|
||||
// columns
|
||||
"[]" +
|
||||
"[]" +
|
||||
@@ -126,7 +151,12 @@ class OptionPanePanel
|
||||
//---- plainShowDialogLabel ----
|
||||
plainShowDialogLabel.setOptionPane(plainOptionPane);
|
||||
plainShowDialogLabel.setTitleLabel(plainLabel);
|
||||
panel9.add(plainShowDialogLabel, "cell 2 0");
|
||||
panel9.add(plainShowDialogLabel, "cell 1 0");
|
||||
|
||||
//---- showTitleBarIconCheckBox ----
|
||||
showTitleBarIconCheckBox.setText("Show window title bar icon");
|
||||
showTitleBarIconCheckBox.addActionListener(e -> showTitleBarIcon());
|
||||
panel9.add(showTitleBarIconCheckBox, "cell 2 0");
|
||||
|
||||
//---- errorLabel ----
|
||||
errorLabel.setText("Error");
|
||||
@@ -148,7 +178,7 @@ class OptionPanePanel
|
||||
//---- errorShowDialogLabel ----
|
||||
errorShowDialogLabel.setTitleLabel(errorLabel);
|
||||
errorShowDialogLabel.setOptionPane(errorOptionPane);
|
||||
panel9.add(errorShowDialogLabel, "cell 2 1");
|
||||
panel9.add(errorShowDialogLabel, "cell 1 1");
|
||||
|
||||
//---- informationLabel ----
|
||||
informationLabel.setText("Information");
|
||||
@@ -170,7 +200,7 @@ class OptionPanePanel
|
||||
//---- informationShowDialogLabel ----
|
||||
informationShowDialogLabel.setOptionPane(informationOptionPane);
|
||||
informationShowDialogLabel.setTitleLabel(informationLabel);
|
||||
panel9.add(informationShowDialogLabel, "cell 2 2");
|
||||
panel9.add(informationShowDialogLabel, "cell 1 2");
|
||||
|
||||
//---- questionLabel ----
|
||||
questionLabel.setText("Question");
|
||||
@@ -214,7 +244,7 @@ class OptionPanePanel
|
||||
//---- warningShowDialogLabel ----
|
||||
warningShowDialogLabel.setOptionPane(warningOptionPane);
|
||||
warningShowDialogLabel.setTitleLabel(warningLabel);
|
||||
panel9.add(warningShowDialogLabel, "cell 2 4");
|
||||
panel9.add(warningShowDialogLabel, "cell 1 4");
|
||||
|
||||
//---- inputLabel ----
|
||||
inputLabel.setText("Input");
|
||||
@@ -236,7 +266,7 @@ class OptionPanePanel
|
||||
//---- inputShowDialogLabel ----
|
||||
inputShowDialogLabel.setOptionPane(inputOptionPane);
|
||||
inputShowDialogLabel.setTitleLabel(inputLabel);
|
||||
panel9.add(inputShowDialogLabel, "cell 2 5");
|
||||
panel9.add(inputShowDialogLabel, "cell 1 5");
|
||||
|
||||
//---- inputIconLabel ----
|
||||
inputIconLabel.setText("Input + icon");
|
||||
@@ -259,7 +289,7 @@ class OptionPanePanel
|
||||
//---- inputIconShowDialogLabel ----
|
||||
inputIconShowDialogLabel.setTitleLabel(inputIconLabel);
|
||||
inputIconShowDialogLabel.setOptionPane(inputIconOptionPane);
|
||||
panel9.add(inputIconShowDialogLabel, "cell 2 6");
|
||||
panel9.add(inputIconShowDialogLabel, "cell 1 6");
|
||||
|
||||
//---- customLabel ----
|
||||
customLabel.setText("Custom");
|
||||
@@ -279,7 +309,7 @@ class OptionPanePanel
|
||||
//---- customShowDialogLabel ----
|
||||
customShowDialogLabel.setOptionPane(customOptionPane);
|
||||
customShowDialogLabel.setTitleLabel(customLabel);
|
||||
panel9.add(customShowDialogLabel, "cell 2 7");
|
||||
panel9.add(customShowDialogLabel, "cell 1 7");
|
||||
}
|
||||
scrollPane1.setViewportView(panel9);
|
||||
}
|
||||
@@ -289,6 +319,7 @@ class OptionPanePanel
|
||||
|
||||
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
|
||||
private OptionPanePanel.ShowDialogLinkLabel plainShowDialogLabel;
|
||||
private JCheckBox showTitleBarIconCheckBox;
|
||||
private OptionPanePanel.ShowDialogLinkLabel errorShowDialogLabel;
|
||||
private OptionPanePanel.ShowDialogLinkLabel informationShowDialogLabel;
|
||||
private JOptionPane customOptionPane;
|
||||
@@ -304,6 +335,7 @@ class OptionPanePanel
|
||||
|
||||
ShowDialogLinkLabel() {
|
||||
setText( "<html><a href=\"#\">Show dialog</a></html>" );
|
||||
setCursor( Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ) );
|
||||
|
||||
addMouseListener( new MouseAdapter() {
|
||||
@Override
|
||||
|
||||
@@ -12,7 +12,7 @@ new FormModel {
|
||||
name: "scrollPane1"
|
||||
"border": new javax.swing.border.EmptyBorder( 0, 0, 0, 0 )
|
||||
add( new FormContainer( "com.formdev.flatlaf.demo.ScrollablePanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "flowy,insets dialog,hidemode 3"
|
||||
"$layoutConstraints": "insets dialog,hidemode 3"
|
||||
"$columnConstraints": "[][][fill]"
|
||||
"$rowConstraints": "[top][top][top][top][top][top][top][top]"
|
||||
} ) {
|
||||
@@ -42,6 +42,16 @@ new FormModel {
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showTitleBarIconCheckBox"
|
||||
"text": "Show window title bar icon"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTitleBarIcon", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 0"
|
||||
} )
|
||||
@@ -73,7 +83,7 @@ new FormModel {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1"
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "informationLabel"
|
||||
@@ -103,7 +113,7 @@ new FormModel {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 2"
|
||||
"value": "cell 1 2"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "questionLabel"
|
||||
@@ -157,7 +167,7 @@ new FormModel {
|
||||
"optionPane": new FormReference( "warningOptionPane" )
|
||||
"titleLabel": new FormReference( "warningLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 4"
|
||||
"value": "cell 1 4"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "inputLabel"
|
||||
@@ -184,7 +194,7 @@ new FormModel {
|
||||
"optionPane": new FormReference( "inputOptionPane" )
|
||||
"titleLabel": new FormReference( "inputLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 5"
|
||||
"value": "cell 1 5"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "inputIconLabel"
|
||||
@@ -212,7 +222,7 @@ new FormModel {
|
||||
"titleLabel": new FormReference( "inputIconLabel" )
|
||||
"optionPane": new FormReference( "inputIconOptionPane" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 6"
|
||||
"value": "cell 1 6"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "customLabel"
|
||||
@@ -240,7 +250,7 @@ new FormModel {
|
||||
"optionPane": new FormReference( "customOptionPane" )
|
||||
"titleLabel": new FormReference( "customLabel" )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 7"
|
||||
"value": "cell 1 7"
|
||||
} )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||
@@ -248,7 +258,7 @@ new FormModel {
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 840, 900 )
|
||||
"size": new java.awt.Dimension( 955, 900 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,6 +303,11 @@ class TabsPanel
|
||||
putTabbedPanesClientProperty( TABBED_PANE_SCROLL_BUTTONS_PLACEMENT, scrollButtonsPlacement );
|
||||
}
|
||||
|
||||
private void tabTypeChanged() {
|
||||
String tabType = cardTabTypeButton.isSelected() ? TABBED_PANE_TAB_TYPE_CARD : null;
|
||||
putTabbedPanesClientProperty( TABBED_PANE_TAB_TYPE, tabType );
|
||||
}
|
||||
|
||||
private void showTabSeparatorsChanged() {
|
||||
Boolean showTabSeparators = showTabSeparatorsCheckBox.isSelected() ? true : null;
|
||||
putTabbedPanesClientProperty( TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators );
|
||||
@@ -396,11 +401,15 @@ class TabsPanel
|
||||
scrollButtonsPlacementToolBar = new JToolBar();
|
||||
scrollBothButton = new JToggleButton();
|
||||
scrollTrailingButton = new JToggleButton();
|
||||
showTabSeparatorsCheckBox = new JCheckBox();
|
||||
tabsPopupPolicyLabel = new JLabel();
|
||||
tabsPopupPolicyToolBar = new JToolBar();
|
||||
popupAsNeededButton = new JToggleButton();
|
||||
popupNeverButton = new JToggleButton();
|
||||
showTabSeparatorsCheckBox = new JCheckBox();
|
||||
tabTypeLabel = new JLabel();
|
||||
tabTypeToolBar = new JToolBar();
|
||||
underlinedTabTypeButton = new JToggleButton();
|
||||
cardTabTypeButton = new JToggleButton();
|
||||
|
||||
//======== this ========
|
||||
setName("this");
|
||||
@@ -435,7 +444,7 @@ class TabsPanel
|
||||
|
||||
//---- tabPlacementLabel ----
|
||||
tabPlacementLabel.setText("Tab placement");
|
||||
tabPlacementLabel.setFont(tabPlacementLabel.getFont().deriveFont(tabPlacementLabel.getFont().getSize() + 4f));
|
||||
tabPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabPlacementLabel.setName("tabPlacementLabel");
|
||||
panel1.add(tabPlacementLabel, "cell 0 0");
|
||||
|
||||
@@ -448,28 +457,28 @@ class TabsPanel
|
||||
//---- topPlacementButton ----
|
||||
topPlacementButton.setText("top");
|
||||
topPlacementButton.setSelected(true);
|
||||
topPlacementButton.setFont(topPlacementButton.getFont().deriveFont(topPlacementButton.getFont().getSize() - 2f));
|
||||
topPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
topPlacementButton.setName("topPlacementButton");
|
||||
topPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(topPlacementButton);
|
||||
|
||||
//---- bottomPlacementButton ----
|
||||
bottomPlacementButton.setText("bottom");
|
||||
bottomPlacementButton.setFont(bottomPlacementButton.getFont().deriveFont(bottomPlacementButton.getFont().getSize() - 2f));
|
||||
bottomPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
bottomPlacementButton.setName("bottomPlacementButton");
|
||||
bottomPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(bottomPlacementButton);
|
||||
|
||||
//---- leftPlacementButton ----
|
||||
leftPlacementButton.setText("left");
|
||||
leftPlacementButton.setFont(leftPlacementButton.getFont().deriveFont(leftPlacementButton.getFont().getSize() - 2f));
|
||||
leftPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
leftPlacementButton.setName("leftPlacementButton");
|
||||
leftPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(leftPlacementButton);
|
||||
|
||||
//---- rightPlacementButton ----
|
||||
rightPlacementButton.setText("right");
|
||||
rightPlacementButton.setFont(rightPlacementButton.getFont().deriveFont(rightPlacementButton.getFont().getSize() - 2f));
|
||||
rightPlacementButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
rightPlacementButton.setName("rightPlacementButton");
|
||||
rightPlacementButton.addActionListener(e -> tabPlacementChanged());
|
||||
tabPlacementToolBar.add(rightPlacementButton);
|
||||
@@ -477,14 +486,14 @@ class TabsPanel
|
||||
|
||||
//---- scrollButton ----
|
||||
scrollButton.setText("scroll");
|
||||
scrollButton.setFont(scrollButton.getFont().deriveFont(scrollButton.getFont().getSize() - 2f));
|
||||
scrollButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollButton.setName("scrollButton");
|
||||
scrollButton.addActionListener(e -> scrollChanged());
|
||||
tabPlacementToolBar.add(scrollButton);
|
||||
|
||||
//---- borderButton ----
|
||||
borderButton.setText("border");
|
||||
borderButton.setFont(borderButton.getFont().deriveFont(borderButton.getFont().getSize() - 2f));
|
||||
borderButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
borderButton.setName("borderButton");
|
||||
borderButton.addActionListener(e -> borderChanged());
|
||||
tabPlacementToolBar.add(borderButton);
|
||||
@@ -499,7 +508,7 @@ class TabsPanel
|
||||
|
||||
//---- tabLayoutLabel ----
|
||||
tabLayoutLabel.setText("Tab layout");
|
||||
tabLayoutLabel.setFont(tabLayoutLabel.getFont().deriveFont(tabLayoutLabel.getFont().getSize() + 4f));
|
||||
tabLayoutLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabLayoutLabel.setName("tabLayoutLabel");
|
||||
panel1.add(tabLayoutLabel, "cell 0 2");
|
||||
|
||||
@@ -511,15 +520,15 @@ class TabsPanel
|
||||
|
||||
//---- scrollTabLayoutButton ----
|
||||
scrollTabLayoutButton.setText("scroll");
|
||||
scrollTabLayoutButton.setFont(scrollTabLayoutButton.getFont().deriveFont(scrollTabLayoutButton.getFont().getSize() - 2f));
|
||||
scrollTabLayoutButton.setSelected(true);
|
||||
scrollTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollTabLayoutButton.setName("scrollTabLayoutButton");
|
||||
scrollTabLayoutButton.addActionListener(e -> tabLayoutChanged());
|
||||
tabLayoutToolBar.add(scrollTabLayoutButton);
|
||||
|
||||
//---- wrapTabLayoutButton ----
|
||||
wrapTabLayoutButton.setText("wrap");
|
||||
wrapTabLayoutButton.setFont(wrapTabLayoutButton.getFont().deriveFont(wrapTabLayoutButton.getFont().getSize() - 2f));
|
||||
wrapTabLayoutButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
wrapTabLayoutButton.setName("wrapTabLayoutButton");
|
||||
wrapTabLayoutButton.addActionListener(e -> tabLayoutChanged());
|
||||
tabLayoutToolBar.add(wrapTabLayoutButton);
|
||||
@@ -529,14 +538,14 @@ class TabsPanel
|
||||
//---- scrollLayoutNoteLabel ----
|
||||
scrollLayoutNoteLabel.setText("(use mouse wheel to scroll; arrow button shows hidden tabs)");
|
||||
scrollLayoutNoteLabel.setEnabled(false);
|
||||
scrollLayoutNoteLabel.setFont(scrollLayoutNoteLabel.getFont().deriveFont(scrollLayoutNoteLabel.getFont().getSize() - 2f));
|
||||
scrollLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollLayoutNoteLabel.setName("scrollLayoutNoteLabel");
|
||||
panel1.add(scrollLayoutNoteLabel, "cell 0 3");
|
||||
|
||||
//---- wrapLayoutNoteLabel ----
|
||||
wrapLayoutNoteLabel.setText("(probably better to use scroll layout?)");
|
||||
wrapLayoutNoteLabel.setEnabled(false);
|
||||
wrapLayoutNoteLabel.setFont(wrapLayoutNoteLabel.getFont().deriveFont(wrapLayoutNoteLabel.getFont().getSize() - 2f));
|
||||
wrapLayoutNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
wrapLayoutNoteLabel.setName("wrapLayoutNoteLabel");
|
||||
panel1.add(wrapLayoutNoteLabel, "cell 0 3");
|
||||
|
||||
@@ -554,7 +563,7 @@ class TabsPanel
|
||||
|
||||
//---- closableTabsLabel ----
|
||||
closableTabsLabel.setText("Closable tabs");
|
||||
closableTabsLabel.setFont(closableTabsLabel.getFont().deriveFont(closableTabsLabel.getFont().getSize() + 4f));
|
||||
closableTabsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
closableTabsLabel.setName("closableTabsLabel");
|
||||
panel1.add(closableTabsLabel, "cell 0 5");
|
||||
|
||||
@@ -566,22 +575,22 @@ class TabsPanel
|
||||
|
||||
//---- squareCloseButton ----
|
||||
squareCloseButton.setText("square");
|
||||
squareCloseButton.setFont(squareCloseButton.getFont().deriveFont(squareCloseButton.getFont().getSize() - 2f));
|
||||
squareCloseButton.setSelected(true);
|
||||
squareCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
squareCloseButton.setName("squareCloseButton");
|
||||
squareCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||
closableTabsToolBar.add(squareCloseButton);
|
||||
|
||||
//---- circleCloseButton ----
|
||||
circleCloseButton.setText("circle");
|
||||
circleCloseButton.setFont(circleCloseButton.getFont().deriveFont(circleCloseButton.getFont().getSize() - 2f));
|
||||
circleCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
circleCloseButton.setName("circleCloseButton");
|
||||
circleCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||
closableTabsToolBar.add(circleCloseButton);
|
||||
|
||||
//---- redCrossCloseButton ----
|
||||
redCrossCloseButton.setText("red cross");
|
||||
redCrossCloseButton.setFont(redCrossCloseButton.getFont().deriveFont(redCrossCloseButton.getFont().getSize() - 2f));
|
||||
redCrossCloseButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
redCrossCloseButton.setName("redCrossCloseButton");
|
||||
redCrossCloseButton.addActionListener(e -> closeButtonStyleChanged());
|
||||
closableTabsToolBar.add(redCrossCloseButton);
|
||||
@@ -596,7 +605,7 @@ class TabsPanel
|
||||
|
||||
//---- tabAreaComponentsLabel ----
|
||||
tabAreaComponentsLabel.setText("Custom tab area components");
|
||||
tabAreaComponentsLabel.setFont(tabAreaComponentsLabel.getFont().deriveFont(tabAreaComponentsLabel.getFont().getSize() + 4f));
|
||||
tabAreaComponentsLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabAreaComponentsLabel.setName("tabAreaComponentsLabel");
|
||||
panel1.add(tabAreaComponentsLabel, "cell 0 7");
|
||||
|
||||
@@ -608,16 +617,16 @@ class TabsPanel
|
||||
|
||||
//---- leadingComponentButton ----
|
||||
leadingComponentButton.setText("leading");
|
||||
leadingComponentButton.setFont(leadingComponentButton.getFont().deriveFont(leadingComponentButton.getFont().getSize() - 2f));
|
||||
leadingComponentButton.setSelected(true);
|
||||
leadingComponentButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
leadingComponentButton.setName("leadingComponentButton");
|
||||
leadingComponentButton.addActionListener(e -> customComponentsChanged());
|
||||
tabAreaComponentsToolBar.add(leadingComponentButton);
|
||||
|
||||
//---- trailingComponentButton ----
|
||||
trailingComponentButton.setText("trailing");
|
||||
trailingComponentButton.setFont(trailingComponentButton.getFont().deriveFont(trailingComponentButton.getFont().getSize() - 2f));
|
||||
trailingComponentButton.setSelected(true);
|
||||
trailingComponentButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
trailingComponentButton.setName("trailingComponentButton");
|
||||
trailingComponentButton.addActionListener(e -> customComponentsChanged());
|
||||
tabAreaComponentsToolBar.add(trailingComponentButton);
|
||||
@@ -655,14 +664,14 @@ class TabsPanel
|
||||
|
||||
//---- tabIconPlacementLabel ----
|
||||
tabIconPlacementLabel.setText("Tab icon placement");
|
||||
tabIconPlacementLabel.setFont(tabIconPlacementLabel.getFont().deriveFont(tabIconPlacementLabel.getFont().getSize() + 4f));
|
||||
tabIconPlacementLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabIconPlacementLabel.setName("tabIconPlacementLabel");
|
||||
panel2.add(tabIconPlacementLabel, "cell 0 0");
|
||||
|
||||
//---- tabIconPlacementNodeLabel ----
|
||||
tabIconPlacementNodeLabel.setText("(top/bottom/leading/trailing)");
|
||||
tabIconPlacementNodeLabel.setEnabled(false);
|
||||
tabIconPlacementNodeLabel.setFont(tabIconPlacementNodeLabel.getFont().deriveFont(tabIconPlacementNodeLabel.getFont().getSize() - 2f));
|
||||
tabIconPlacementNodeLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabIconPlacementNodeLabel.setName("tabIconPlacementNodeLabel");
|
||||
panel2.add(tabIconPlacementNodeLabel, "cell 0 1");
|
||||
|
||||
@@ -692,14 +701,14 @@ class TabsPanel
|
||||
|
||||
//---- tabAreaAlignmentLabel ----
|
||||
tabAreaAlignmentLabel.setText("Tab area alignment");
|
||||
tabAreaAlignmentLabel.setFont(tabAreaAlignmentLabel.getFont().deriveFont(tabAreaAlignmentLabel.getFont().getSize() + 4f));
|
||||
tabAreaAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabAreaAlignmentLabel.setName("tabAreaAlignmentLabel");
|
||||
panel2.add(tabAreaAlignmentLabel, "cell 0 6");
|
||||
|
||||
//---- tabAreaAlignmentNoteLabel ----
|
||||
tabAreaAlignmentNoteLabel.setText("(leading/center/trailing/fill)");
|
||||
tabAreaAlignmentNoteLabel.setEnabled(false);
|
||||
tabAreaAlignmentNoteLabel.setFont(tabAreaAlignmentNoteLabel.getFont().deriveFont(tabAreaAlignmentNoteLabel.getFont().getSize() - 2f));
|
||||
tabAreaAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabAreaAlignmentNoteLabel.setName("tabAreaAlignmentNoteLabel");
|
||||
panel2.add(tabAreaAlignmentNoteLabel, "cell 0 7");
|
||||
|
||||
@@ -750,14 +759,14 @@ class TabsPanel
|
||||
|
||||
//---- tabWidthModeLabel ----
|
||||
tabWidthModeLabel.setText("Tab width mode");
|
||||
tabWidthModeLabel.setFont(tabWidthModeLabel.getFont().deriveFont(tabWidthModeLabel.getFont().getSize() + 4f));
|
||||
tabWidthModeLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabWidthModeLabel.setName("tabWidthModeLabel");
|
||||
panel3.add(tabWidthModeLabel, "cell 0 0");
|
||||
|
||||
//---- tabWidthModeNoteLabel ----
|
||||
tabWidthModeNoteLabel.setText("(preferred/equal/compact)");
|
||||
tabWidthModeNoteLabel.setFont(tabWidthModeNoteLabel.getFont().deriveFont(tabWidthModeNoteLabel.getFont().getSize() - 2f));
|
||||
tabWidthModeNoteLabel.setEnabled(false);
|
||||
tabWidthModeNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabWidthModeNoteLabel.setName("tabWidthModeNoteLabel");
|
||||
panel3.add(tabWidthModeNoteLabel, "cell 0 1");
|
||||
|
||||
@@ -781,7 +790,7 @@ class TabsPanel
|
||||
|
||||
//---- minMaxTabWidthLabel ----
|
||||
minMaxTabWidthLabel.setText("Minimum/maximum tab width");
|
||||
minMaxTabWidthLabel.setFont(minMaxTabWidthLabel.getFont().deriveFont(minMaxTabWidthLabel.getFont().getSize() + 4f));
|
||||
minMaxTabWidthLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
minMaxTabWidthLabel.setName("minMaxTabWidthLabel");
|
||||
panel3.add(minMaxTabWidthLabel, "cell 0 5");
|
||||
|
||||
@@ -799,7 +808,7 @@ class TabsPanel
|
||||
|
||||
//---- tabAlignmentLabel ----
|
||||
tabAlignmentLabel.setText("Tab title alignment");
|
||||
tabAlignmentLabel.setFont(tabAlignmentLabel.getFont().deriveFont(tabAlignmentLabel.getFont().getSize() + 4f));
|
||||
tabAlignmentLabel.putClientProperty("FlatLaf.styleClass", "h3");
|
||||
tabAlignmentLabel.setName("tabAlignmentLabel");
|
||||
panel3.add(tabAlignmentLabel, "cell 0 8");
|
||||
|
||||
@@ -820,14 +829,14 @@ class TabsPanel
|
||||
//---- tabAlignmentNoteLabel ----
|
||||
tabAlignmentNoteLabel.setText("(leading/center/trailing)");
|
||||
tabAlignmentNoteLabel.setEnabled(false);
|
||||
tabAlignmentNoteLabel.setFont(tabAlignmentNoteLabel.getFont().deriveFont(tabAlignmentNoteLabel.getFont().getSize() - 2f));
|
||||
tabAlignmentNoteLabel.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabAlignmentNoteLabel.setName("tabAlignmentNoteLabel");
|
||||
panel5.add(tabAlignmentNoteLabel, "cell 0 0");
|
||||
|
||||
//---- tabAlignmentNoteLabel2 ----
|
||||
tabAlignmentNoteLabel2.setText("(trailing)");
|
||||
tabAlignmentNoteLabel2.setEnabled(false);
|
||||
tabAlignmentNoteLabel2.setFont(tabAlignmentNoteLabel2.getFont().deriveFont(tabAlignmentNoteLabel2.getFont().getSize() - 2f));
|
||||
tabAlignmentNoteLabel2.putClientProperty("FlatLaf.styleClass", "small");
|
||||
tabAlignmentNoteLabel2.setName("tabAlignmentNoteLabel2");
|
||||
panel5.add(tabAlignmentNoteLabel2, "cell 1 0,alignx right,growx 0");
|
||||
|
||||
@@ -873,7 +882,8 @@ class TabsPanel
|
||||
"[]" +
|
||||
"[fill]para" +
|
||||
"[fill]" +
|
||||
"[fill]para",
|
||||
"[fill]para" +
|
||||
"[fill]",
|
||||
// rows
|
||||
"[]" +
|
||||
"[center]"));
|
||||
@@ -891,22 +901,22 @@ class TabsPanel
|
||||
|
||||
//---- scrollAsNeededSingleButton ----
|
||||
scrollAsNeededSingleButton.setText("asNeededSingle");
|
||||
scrollAsNeededSingleButton.setFont(scrollAsNeededSingleButton.getFont().deriveFont(scrollAsNeededSingleButton.getFont().getSize() - 2f));
|
||||
scrollAsNeededSingleButton.setSelected(true);
|
||||
scrollAsNeededSingleButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollAsNeededSingleButton.setName("scrollAsNeededSingleButton");
|
||||
scrollAsNeededSingleButton.addActionListener(e -> scrollButtonsPolicyChanged());
|
||||
scrollButtonsPolicyToolBar.add(scrollAsNeededSingleButton);
|
||||
|
||||
//---- scrollAsNeededButton ----
|
||||
scrollAsNeededButton.setText("asNeeded");
|
||||
scrollAsNeededButton.setFont(scrollAsNeededButton.getFont().deriveFont(scrollAsNeededButton.getFont().getSize() - 2f));
|
||||
scrollAsNeededButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollAsNeededButton.setName("scrollAsNeededButton");
|
||||
scrollAsNeededButton.addActionListener(e -> scrollButtonsPolicyChanged());
|
||||
scrollButtonsPolicyToolBar.add(scrollAsNeededButton);
|
||||
|
||||
//---- scrollNeverButton ----
|
||||
scrollNeverButton.setText("never");
|
||||
scrollNeverButton.setFont(scrollNeverButton.getFont().deriveFont(scrollNeverButton.getFont().getSize() - 2f));
|
||||
scrollNeverButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollNeverButton.setName("scrollNeverButton");
|
||||
scrollNeverButton.addActionListener(e -> scrollButtonsPolicyChanged());
|
||||
scrollButtonsPolicyToolBar.add(scrollNeverButton);
|
||||
@@ -926,21 +936,27 @@ class TabsPanel
|
||||
|
||||
//---- scrollBothButton ----
|
||||
scrollBothButton.setText("both");
|
||||
scrollBothButton.setFont(scrollBothButton.getFont().deriveFont(scrollBothButton.getFont().getSize() - 2f));
|
||||
scrollBothButton.setSelected(true);
|
||||
scrollBothButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollBothButton.setName("scrollBothButton");
|
||||
scrollBothButton.addActionListener(e -> scrollButtonsPlacementChanged());
|
||||
scrollButtonsPlacementToolBar.add(scrollBothButton);
|
||||
|
||||
//---- scrollTrailingButton ----
|
||||
scrollTrailingButton.setText("trailing");
|
||||
scrollTrailingButton.setFont(scrollTrailingButton.getFont().deriveFont(scrollTrailingButton.getFont().getSize() - 2f));
|
||||
scrollTrailingButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
scrollTrailingButton.setName("scrollTrailingButton");
|
||||
scrollTrailingButton.addActionListener(e -> scrollButtonsPlacementChanged());
|
||||
scrollButtonsPlacementToolBar.add(scrollTrailingButton);
|
||||
}
|
||||
panel4.add(scrollButtonsPlacementToolBar, "cell 3 0");
|
||||
|
||||
//---- showTabSeparatorsCheckBox ----
|
||||
showTabSeparatorsCheckBox.setText("Show tab separators");
|
||||
showTabSeparatorsCheckBox.setName("showTabSeparatorsCheckBox");
|
||||
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
|
||||
panel4.add(showTabSeparatorsCheckBox, "cell 4 0");
|
||||
|
||||
//---- tabsPopupPolicyLabel ----
|
||||
tabsPopupPolicyLabel.setText("Tabs popup policy:");
|
||||
tabsPopupPolicyLabel.setName("tabsPopupPolicyLabel");
|
||||
@@ -954,26 +970,47 @@ class TabsPanel
|
||||
|
||||
//---- popupAsNeededButton ----
|
||||
popupAsNeededButton.setText("asNeeded");
|
||||
popupAsNeededButton.setFont(popupAsNeededButton.getFont().deriveFont(popupAsNeededButton.getFont().getSize() - 2f));
|
||||
popupAsNeededButton.setSelected(true);
|
||||
popupAsNeededButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
popupAsNeededButton.setName("popupAsNeededButton");
|
||||
popupAsNeededButton.addActionListener(e -> tabsPopupPolicyChanged());
|
||||
tabsPopupPolicyToolBar.add(popupAsNeededButton);
|
||||
|
||||
//---- popupNeverButton ----
|
||||
popupNeverButton.setText("never");
|
||||
popupNeverButton.setFont(popupNeverButton.getFont().deriveFont(popupNeverButton.getFont().getSize() - 2f));
|
||||
popupNeverButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
popupNeverButton.setName("popupNeverButton");
|
||||
popupNeverButton.addActionListener(e -> tabsPopupPolicyChanged());
|
||||
tabsPopupPolicyToolBar.add(popupNeverButton);
|
||||
}
|
||||
panel4.add(tabsPopupPolicyToolBar, "cell 1 1");
|
||||
|
||||
//---- showTabSeparatorsCheckBox ----
|
||||
showTabSeparatorsCheckBox.setText("Show tab separators");
|
||||
showTabSeparatorsCheckBox.setName("showTabSeparatorsCheckBox");
|
||||
showTabSeparatorsCheckBox.addActionListener(e -> showTabSeparatorsChanged());
|
||||
panel4.add(showTabSeparatorsCheckBox, "cell 2 1 2 1");
|
||||
//---- tabTypeLabel ----
|
||||
tabTypeLabel.setText("Tab type:");
|
||||
tabTypeLabel.setName("tabTypeLabel");
|
||||
panel4.add(tabTypeLabel, "cell 2 1");
|
||||
|
||||
//======== tabTypeToolBar ========
|
||||
{
|
||||
tabTypeToolBar.setFloatable(false);
|
||||
tabTypeToolBar.setName("tabTypeToolBar");
|
||||
|
||||
//---- underlinedTabTypeButton ----
|
||||
underlinedTabTypeButton.setText("underlined");
|
||||
underlinedTabTypeButton.setSelected(true);
|
||||
underlinedTabTypeButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
underlinedTabTypeButton.setName("underlinedTabTypeButton");
|
||||
underlinedTabTypeButton.addActionListener(e -> tabTypeChanged());
|
||||
tabTypeToolBar.add(underlinedTabTypeButton);
|
||||
|
||||
//---- cardTabTypeButton ----
|
||||
cardTabTypeButton.setText("card");
|
||||
cardTabTypeButton.putClientProperty("FlatLaf.styleClass", "small");
|
||||
cardTabTypeButton.setName("cardTabTypeButton");
|
||||
cardTabTypeButton.addActionListener(e -> tabTypeChanged());
|
||||
tabTypeToolBar.add(cardTabTypeButton);
|
||||
}
|
||||
panel4.add(tabTypeToolBar, "cell 3 1");
|
||||
}
|
||||
add(panel4, "cell 0 2 3 1");
|
||||
|
||||
@@ -1010,6 +1047,11 @@ class TabsPanel
|
||||
ButtonGroup tabsPopupPolicyButtonGroup = new ButtonGroup();
|
||||
tabsPopupPolicyButtonGroup.add(popupAsNeededButton);
|
||||
tabsPopupPolicyButtonGroup.add(popupNeverButton);
|
||||
|
||||
//---- tabTypeButtonGroup ----
|
||||
ButtonGroup tabTypeButtonGroup = new ButtonGroup();
|
||||
tabTypeButtonGroup.add(underlinedTabTypeButton);
|
||||
tabTypeButtonGroup.add(cardTabTypeButton);
|
||||
// JFormDesigner - End of component initialization //GEN-END:initComponents
|
||||
|
||||
if( FlatLafDemo.screenshotsMode ) {
|
||||
@@ -1089,10 +1131,14 @@ class TabsPanel
|
||||
private JToolBar scrollButtonsPlacementToolBar;
|
||||
private JToggleButton scrollBothButton;
|
||||
private JToggleButton scrollTrailingButton;
|
||||
private JCheckBox showTabSeparatorsCheckBox;
|
||||
private JLabel tabsPopupPolicyLabel;
|
||||
private JToolBar tabsPopupPolicyToolBar;
|
||||
private JToggleButton popupAsNeededButton;
|
||||
private JToggleButton popupNeverButton;
|
||||
private JCheckBox showTabSeparatorsCheckBox;
|
||||
private JLabel tabTypeLabel;
|
||||
private JToolBar tabTypeToolBar;
|
||||
private JToggleButton underlinedTabTypeButton;
|
||||
private JToggleButton cardTabTypeButton;
|
||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
JFDML JFormDesigner: "7.0.2.0.298" Java: "15" encoding: "UTF-8"
|
||||
JFDML JFormDesigner: "7.0.5.0.382" Java: "16" encoding: "UTF-8"
|
||||
|
||||
new FormModel {
|
||||
contentType: "form/swing"
|
||||
@@ -22,7 +22,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabPlacementLabel"
|
||||
"text": "Tab placement"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -38,28 +38,28 @@ new FormModel {
|
||||
"text": "top"
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "tabPlacementButtonGroup" )
|
||||
"font": &SwingDerivedFont0 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabPlacementChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "bottomPlacementButton"
|
||||
"text": "bottom"
|
||||
"$buttonGroup": new FormReference( "tabPlacementButtonGroup" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabPlacementChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "leftPlacementButton"
|
||||
"text": "left"
|
||||
"$buttonGroup": new FormReference( "tabPlacementButtonGroup" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabPlacementChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "rightPlacementButton"
|
||||
"text": "right"
|
||||
"$buttonGroup": new FormReference( "tabPlacementButtonGroup" )
|
||||
"font": #SwingDerivedFont0
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabPlacementChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToolBar$Separator" ) {
|
||||
@@ -68,13 +68,13 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollButton"
|
||||
"text": "scroll"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "borderButton"
|
||||
"text": "border"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "borderChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -88,7 +88,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabLayoutLabel"
|
||||
"text": "Tab layout"
|
||||
"font": &SwingDerivedFont1 new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -103,15 +103,15 @@ new FormModel {
|
||||
name: "scrollTabLayoutButton"
|
||||
"text": "scroll"
|
||||
"$buttonGroup": new FormReference( "tabLayoutButtonGroup" )
|
||||
"font": &SwingDerivedFont2 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"selected": true
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabLayoutChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "wrapTabLayoutButton"
|
||||
"text": "wrap"
|
||||
"$buttonGroup": new FormReference( "tabLayoutButtonGroup" )
|
||||
"font": #SwingDerivedFont2
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabLayoutChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -121,7 +121,7 @@ new FormModel {
|
||||
name: "scrollLayoutNoteLabel"
|
||||
"text": "(use mouse wheel to scroll; arrow button shows hidden tabs)"
|
||||
"enabled": false
|
||||
"font": &SwingDerivedFont3 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
@@ -129,7 +129,7 @@ new FormModel {
|
||||
name: "wrapLayoutNoteLabel"
|
||||
"text": "(probably better to use scroll layout?)"
|
||||
"enabled": false
|
||||
"font": #SwingDerivedFont3
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 3"
|
||||
} )
|
||||
@@ -146,7 +146,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "closableTabsLabel"
|
||||
"text": "Closable tabs"
|
||||
"font": #SwingDerivedFont1
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -160,23 +160,23 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "squareCloseButton"
|
||||
"text": "square"
|
||||
"font": &SwingDerivedFont4 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$buttonGroup": new FormReference( "closableTabsButtonGroup" )
|
||||
"selected": true
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "closeButtonStyleChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "circleCloseButton"
|
||||
"text": "circle"
|
||||
"font": #SwingDerivedFont4
|
||||
"$buttonGroup": new FormReference( "closableTabsButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "closeButtonStyleChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "redCrossCloseButton"
|
||||
"text": "red cross"
|
||||
"font": #SwingDerivedFont4
|
||||
"$buttonGroup": new FormReference( "closableTabsButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "closeButtonStyleChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -190,7 +190,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabAreaComponentsLabel"
|
||||
"text": "Custom tab area components"
|
||||
"font": #SwingDerivedFont1
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -204,15 +204,15 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "leadingComponentButton"
|
||||
"text": "leading"
|
||||
"font": &SwingDerivedFont5 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"selected": true
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "customComponentsChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "trailingComponentButton"
|
||||
"text": "trailing"
|
||||
"font": #SwingDerivedFont5
|
||||
"selected": true
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "customComponentsChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -238,7 +238,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabIconPlacementLabel"
|
||||
"text": "Tab icon placement"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -249,7 +249,7 @@ new FormModel {
|
||||
name: "tabIconPlacementNodeLabel"
|
||||
"text": "(top/bottom/leading/trailing)"
|
||||
"enabled": false
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -279,7 +279,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabAreaAlignmentLabel"
|
||||
"text": "Tab area alignment"
|
||||
"font": &SwingDerivedFont6 new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -290,7 +290,7 @@ new FormModel {
|
||||
name: "tabAreaAlignmentNoteLabel"
|
||||
"text": "(leading/center/trailing/fill)"
|
||||
"enabled": false
|
||||
"font": &SwingDerivedFont7 new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -332,7 +332,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabWidthModeLabel"
|
||||
"text": "Tab width mode"
|
||||
"font": #SwingDerivedFont6
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -342,8 +342,8 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabWidthModeNoteLabel"
|
||||
"text": "(preferred/equal/compact)"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, -2, false )
|
||||
"enabled": false
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -368,7 +368,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "minMaxTabWidthLabel"
|
||||
"text": "Minimum/maximum tab width"
|
||||
"font": new com.jformdesigner.model.SwingDerivedFont( null, 0, 4, false )
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -388,7 +388,7 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabAlignmentLabel"
|
||||
"text": "Tab title alignment"
|
||||
"font": #SwingDerivedFont6
|
||||
"$client.FlatLaf.styleClass": "h3"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -405,7 +405,7 @@ new FormModel {
|
||||
name: "tabAlignmentNoteLabel"
|
||||
"text": "(leading/center/trailing)"
|
||||
"enabled": false
|
||||
"font": #SwingDerivedFont7
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -416,7 +416,7 @@ new FormModel {
|
||||
name: "tabAlignmentNoteLabel2"
|
||||
"text": "(trailing)"
|
||||
"enabled": false
|
||||
"font": #SwingDerivedFont7
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": true
|
||||
}
|
||||
@@ -457,7 +457,7 @@ new FormModel {
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||
"$layoutConstraints": "insets 0,hidemode 3"
|
||||
"$columnConstraints": "[][fill]para[fill][fill]para"
|
||||
"$columnConstraints": "[][fill]para[fill][fill]para[fill]"
|
||||
"$rowConstraints": "[][center]"
|
||||
} ) {
|
||||
name: "panel4"
|
||||
@@ -477,23 +477,23 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollAsNeededSingleButton"
|
||||
"text": "asNeededSingle"
|
||||
"font": #SwingDerivedFont2
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "scrollButtonsPolicyButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollButtonsPolicyChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollAsNeededButton"
|
||||
"text": "asNeeded"
|
||||
"font": #SwingDerivedFont2
|
||||
"$buttonGroup": new FormReference( "scrollButtonsPolicyButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollButtonsPolicyChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollNeverButton"
|
||||
"text": "never"
|
||||
"font": #SwingDerivedFont2
|
||||
"$buttonGroup": new FormReference( "scrollButtonsPolicyButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollButtonsPolicyChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
@@ -512,21 +512,31 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollBothButton"
|
||||
"text": "both"
|
||||
"font": #SwingDerivedFont2
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "scrollButtonsPlacementButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollButtonsPlacementChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "scrollTrailingButton"
|
||||
"text": "trailing"
|
||||
"font": #SwingDerivedFont2
|
||||
"$buttonGroup": new FormReference( "scrollButtonsPlacementButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "scrollButtonsPlacementChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showTabSeparatorsCheckBox"
|
||||
"text": "Show tab separators"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 4 0"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabsPopupPolicyLabel"
|
||||
"text": "Tabs popup policy:"
|
||||
@@ -540,37 +550,54 @@ new FormModel {
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "popupAsNeededButton"
|
||||
"text": "asNeeded"
|
||||
"font": #SwingDerivedFont2
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "tabsPopupPolicyButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabsPopupPolicyChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "popupNeverButton"
|
||||
"text": "never"
|
||||
"font": #SwingDerivedFont2
|
||||
"$buttonGroup": new FormReference( "tabsPopupPolicyButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabsPopupPolicyChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 1 1"
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||
name: "showTabSeparatorsCheckBox"
|
||||
"text": "Show tab separators"
|
||||
auxiliary() {
|
||||
"JavaCodeGenerator.variableLocal": false
|
||||
}
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "showTabSeparatorsChanged", false ) )
|
||||
add( new FormComponent( "javax.swing.JLabel" ) {
|
||||
name: "tabTypeLabel"
|
||||
"text": "Tab type:"
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 2 1 2 1"
|
||||
"value": "cell 2 1"
|
||||
} )
|
||||
add( new FormContainer( "javax.swing.JToolBar", new FormLayoutManager( class javax.swing.JToolBar ) ) {
|
||||
name: "tabTypeToolBar"
|
||||
"floatable": false
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "underlinedTabTypeButton"
|
||||
"text": "underlined"
|
||||
"selected": true
|
||||
"$buttonGroup": new FormReference( "tabTypeButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabTypeChanged", false ) )
|
||||
} )
|
||||
add( new FormComponent( "javax.swing.JToggleButton" ) {
|
||||
name: "cardTabTypeButton"
|
||||
"text": "card"
|
||||
"$buttonGroup": new FormReference( "tabTypeButtonGroup" )
|
||||
"$client.FlatLaf.styleClass": "small"
|
||||
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabTypeChanged", false ) )
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 3 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||
"value": "cell 0 2 3 1"
|
||||
} )
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 0 )
|
||||
"size": new java.awt.Dimension( 1075, 895 )
|
||||
"size": new java.awt.Dimension( 1145, 895 )
|
||||
} )
|
||||
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||
name: "tabPlacementButtonGroup"
|
||||
@@ -602,5 +629,10 @@ new FormModel {
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 200, 1020 )
|
||||
} )
|
||||
add( new FormNonVisual( "javax.swing.ButtonGroup" ) {
|
||||
name: "tabTypeButtonGroup"
|
||||
}, new FormLayoutConstraints( null ) {
|
||||
"location": new java.awt.Point( 0, 1072 )
|
||||
} )
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="matchCase">
|
||||
<g id="Cc">
|
||||
<path d="M8.77476 11.8297C8.32279 12.2816 7.83717 12.623 7.31789 12.8538C6.80823 13.075 6.19279 13.1856 5.47157 13.1856C4.17337 13.1856 3.10116 12.7144 2.25492 11.772C1.41831 10.8296 1 9.5939 1 8.06491V7.93509C1 6.4061 1.42792 5.17041 2.28377 4.22802C3.13962 3.27601 4.23588 2.8 5.57254 2.8C6.81304 2.8 7.8564 3.18465 8.70263 3.95395L7.72178 5.64161C7.01979 5.0454 6.3178 4.7473 5.61581 4.7473C4.89459 4.7473 4.30319 5.03098 3.84161 5.59834C3.38964 6.1657 3.16366 6.935 3.16366 7.90624V8.05049C3.16366 9.04096 3.38964 9.81988 3.84161 10.3872C4.29357 10.9546 4.88978 11.2383 5.63024 11.2383C6.35146 11.2383 7.06787 10.9306 7.77947 10.3151L8.77476 11.8297Z" fill="#7F8B91" fill-opacity="0.5"/>
|
||||
<path d="M15.6304 12.1182C15.2842 12.474 14.914 12.7432 14.5197 12.9259C14.135 13.1086 13.6542 13.2 13.0773 13.2C12.0483 13.2 11.2021 12.8346 10.5386 12.1037C9.87504 11.3633 9.54327 10.4209 9.54327 9.27656V9.11789C9.54327 7.97356 9.87984 7.03116 10.553 6.29071C11.2261 5.55025 12.0772 5.18003 13.1061 5.18003C14.135 5.18003 14.962 5.50217 15.5871 6.14646L14.6639 7.67545C14.1927 7.22349 13.6927 6.9975 13.1638 6.9975C12.7022 6.9975 12.3224 7.18983 12.0243 7.57448C11.7262 7.95913 11.5771 8.46398 11.5771 9.08904V9.26214C11.5771 9.90643 11.7262 10.4209 12.0243 10.8055C12.332 11.1902 12.7359 11.3825 13.2359 11.3825C13.736 11.3825 14.236 11.1565 14.7361 10.7046L15.6304 12.1182Z" fill="#7F8B91" fill-opacity="0.5"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,9 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="matchCaseHovered">
|
||||
<g id="Cc">
|
||||
<path d="M8.77476 11.8297C8.32279 12.2816 7.83717 12.623 7.31789 12.8538C6.80823 13.075 6.19279 13.1856 5.47157 13.1856C4.17337 13.1856 3.10116 12.7144 2.25492 11.772C1.41831 10.8296 1 9.5939 1 8.06491V7.93509C1 6.4061 1.42792 5.17041 2.28377 4.22802C3.13962 3.27601 4.23588 2.8 5.57254 2.8C6.81304 2.8 7.8564 3.18465 8.70263 3.95395L7.72178 5.64161C7.01979 5.0454 6.3178 4.7473 5.61581 4.7473C4.89459 4.7473 4.30319 5.03098 3.84161 5.59834C3.38964 6.1657 3.16366 6.935 3.16366 7.90624V8.05049C3.16366 9.04096 3.38964 9.81988 3.84161 10.3872C4.29357 10.9546 4.88978 11.2383 5.63024 11.2383C6.35146 11.2383 7.06787 10.9306 7.77947 10.3151L8.77476 11.8297Z" fill="#7F8B91" fill-opacity="0.9"/>
|
||||
<path d="M15.6304 12.1182C15.2842 12.474 14.914 12.7432 14.5197 12.9259C14.135 13.1086 13.6542 13.2 13.0773 13.2C12.0483 13.2 11.2021 12.8346 10.5386 12.1037C9.87504 11.3633 9.54327 10.4209 9.54327 9.27656V9.11789C9.54327 7.97356 9.87984 7.03116 10.553 6.29071C11.2261 5.55025 12.0772 5.18003 13.1061 5.18003C14.135 5.18003 14.962 5.50217 15.5871 6.14646L14.6639 7.67545C14.1927 7.22349 13.6927 6.9975 13.1638 6.9975C12.7022 6.9975 12.3224 7.18983 12.0243 7.57448C11.7262 7.95913 11.5771 8.46398 11.5771 9.08904V9.26214C11.5771 9.90643 11.7262 10.4209 12.0243 10.8055C12.332 11.1902 12.7359 11.3825 13.2359 11.3825C13.736 11.3825 14.236 11.1565 14.7361 10.7046L15.6304 12.1182Z" fill="#7F8B91" fill-opacity="0.9"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,9 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="matchCaseSelected">
|
||||
<g id="Cc">
|
||||
<path d="M8.77476 11.8297C8.32279 12.2816 7.83717 12.623 7.31789 12.8538C6.80823 13.075 6.19279 13.1856 5.47157 13.1856C4.17337 13.1856 3.10116 12.7144 2.25492 11.772C1.41831 10.8296 1 9.5939 1 8.06491V7.93509C1 6.4061 1.42792 5.17041 2.28377 4.22802C3.13962 3.276 4.23588 2.8 5.57254 2.8C6.81304 2.8 7.8564 3.18465 8.70263 3.95395L7.72178 5.64161C7.01979 5.0454 6.3178 4.74729 5.61581 4.74729C4.89459 4.74729 4.30319 5.03097 3.84161 5.59833C3.38964 6.16569 3.16366 6.935 3.16366 7.90624V8.05048C3.16366 9.04096 3.38964 9.81988 3.84161 10.3872C4.29357 10.9546 4.88978 11.2383 5.63024 11.2383C6.35146 11.2383 7.06787 10.9306 7.77947 10.3151L8.77476 11.8297Z" fill="#40B6E0"/>
|
||||
<path d="M15.6304 12.1182C15.2842 12.474 14.914 12.7432 14.5197 12.9259C14.135 13.1086 13.6542 13.2 13.0773 13.2C12.0483 13.2 11.2021 12.8346 10.5386 12.1037C9.87504 11.3633 9.54327 10.4209 9.54327 9.27656V9.11789C9.54327 7.97355 9.87984 7.03116 10.553 6.29071C11.2261 5.55025 12.0772 5.18003 13.1061 5.18003C14.135 5.18003 14.962 5.50217 15.5871 6.14646L14.6639 7.67545C14.1927 7.22348 13.6927 6.9975 13.1638 6.9975C12.7022 6.9975 12.3224 7.18983 12.0243 7.57448C11.7262 7.95913 11.5771 8.46398 11.5771 9.08904V9.26213C11.5771 9.90643 11.7262 10.4209 12.0243 10.8055C12.332 11.1902 12.7359 11.3825 13.2359 11.3825C13.736 11.3825 14.236 11.1565 14.7361 10.7046L15.6304 12.1182Z" fill="#40B6E0"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,7 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-opacity=".5" fill-rule="evenodd">
|
||||
<rect width="2" height="2" x="3" y="11" fill="#7F8B91"/>
|
||||
<path fill="#7F8B91" d="M9.8339746,5.61435935 L12.0980762,4.30717968 L12.8980762,5.69282032 L10.6339746,7 L12.8980762,8.30717968 L12.0980762,9.69282032 L9.8339746,8.38564065 L9.8339746,11 L8.2339746,11 L8.2339746,8.38564065 L5.96987298,9.69282032 L5.16987298,8.30717968 L7.4339746,7 L5.16987298,5.69282032 L5.96987298,4.30717968 L8.2339746,5.61435935 L8.2339746,3 L9.8339746,3 L9.8339746,5.61435935 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 770 B |
@@ -0,0 +1,7 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-opacity=".9" fill-rule="evenodd">
|
||||
<rect width="2" height="2" x="3" y="11" fill="#7F8B91"/>
|
||||
<path fill="#7F8B91" d="M9.8339746,5.61435935 L12.0980762,4.30717968 L12.8980762,5.69282032 L10.6339746,7 L12.8980762,8.30717968 L12.0980762,9.69282032 L9.8339746,8.38564065 L9.8339746,11 L8.2339746,11 L8.2339746,8.38564065 L5.96987298,9.69282032 L5.16987298,8.30717968 L7.4339746,7 L5.16987298,5.69282032 L5.96987298,4.30717968 L8.2339746,5.61435935 L8.2339746,3 L9.8339746,3 L9.8339746,5.61435935 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 770 B |
@@ -0,0 +1,7 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<rect width="2" height="2" x="3" y="11" fill="#40B6E0"/>
|
||||
<path fill="#40B6E0" d="M9.8339746,5.61435935 L12.0980762,4.30717968 L12.8980762,5.69282032 L10.6339746,7 L12.8980762,8.30717968 L12.0980762,9.69282032 L9.8339746,8.38564065 L9.8339746,11 L8.2339746,11 L8.2339746,8.38564065 L5.96987298,9.69282032 L5.16987298,8.30717968 L7.4339746,7 L5.16987298,5.69282032 L5.96987298,4.30717968 L8.2339746,5.61435935 L8.2339746,3 L9.8339746,3 L9.8339746,5.61435935 Z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 752 B |
@@ -0,0 +1,6 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="words">
|
||||
<path id="W" d="M14.5213 3.01418L11.6986 13H9.82624L8.01064 6.68794L6.19504 13H4.3227L1.5 3.01418H3.67021L5.3156 9.53901L7.14539 3H8.93262L10.7482 9.53901L12.4078 3.01418H14.5213Z" fill="#7F8B91" fill-opacity="0.5"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 487 B |
@@ -0,0 +1,6 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="wordsHovered">
|
||||
<path id="W" d="M14.5213 3.01418L11.6986 13H9.82624L8.01064 6.68794L6.19504 13H4.3227L1.5 3.01418H3.67021L5.3156 9.53901L7.14539 3H8.93262L10.7482 9.53901L12.4078 3.01418H14.5213Z" fill="#7F8B91" fill-opacity="0.9"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 494 B |
@@ -0,0 +1,6 @@
|
||||
<!-- Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -->
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="wordsSelected">
|
||||
<path id="W" d="M14.5213 3.01418L11.6986 13H9.82624L8.01064 6.68794L6.19504 13H4.3227L1.5 3.01418H3.67021L5.3156 9.53901L7.14539 3H8.93262L10.7482 9.53901L12.4078 3.01418H14.5213Z" fill="#40B6E0"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 476 B |
@@ -145,7 +145,7 @@
|
||||
"license": "MIT",
|
||||
"licenseFile": "Hiberbee.LICENSE.txt",
|
||||
"sourceCodeUrl": "https://github.com/Hiberbee/code-highlight-themes",
|
||||
"sourceCodePath": "blob/master/src/main/resources/HiberbeeDark.theme.json"
|
||||
"sourceCodePath": "blob/latest/src/main/resources/HiberbeeDark.theme.json"
|
||||
},
|
||||
"HighContrast.theme.json": {
|
||||
"name": "High contrast",
|
||||
@@ -184,7 +184,7 @@
|
||||
"license": "MIT",
|
||||
"licenseFile": "nord.LICENSE.txt",
|
||||
"sourceCodeUrl": "https://github.com/arcticicestudio/nord-jetbrains",
|
||||
"sourceCodePath": "blob/develop/src/nord.theme.json"
|
||||
"sourceCodePath": "blob/main/src/nord.theme.json"
|
||||
},
|
||||
"one_dark.theme.json": {
|
||||
"name": "One Dark",
|
||||
|
||||
@@ -22,7 +22,7 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
implementation( project( ":flatlaf-core" ) )
|
||||
implementation( "com.formdev:svgSalamander:1.1.2.4" )
|
||||
implementation( "com.formdev:svgSalamander:1.1.3" )
|
||||
}
|
||||
|
||||
flatlafModuleInfo {
|
||||
|
||||
@@ -474,9 +474,9 @@ public class FlatInspector
|
||||
if( c instanceof JComponent )
|
||||
appendRow( buf, "Border", toString( ((JComponent)c).getBorder(), classHierarchy ) );
|
||||
|
||||
appendRow( buf, "Background", toString( c.getBackground() ) );
|
||||
appendRow( buf, "Foreground", toString( c.getForeground() ) );
|
||||
appendRow( buf, "Font", toString( c.getFont() ) );
|
||||
appendRow( buf, "Background", toString( c.getBackground() ) + (c.isBackgroundSet() ? "" : " NOT SET") );
|
||||
appendRow( buf, "Foreground", toString( c.getForeground() ) + (c.isBackgroundSet() ? "" : " NOT SET") );
|
||||
appendRow( buf, "Font", toString( c.getFont() ) + (c.isFontSet() ? "" : " NOT SET") );
|
||||
|
||||
if( c instanceof JComponent ) {
|
||||
try {
|
||||
|
||||
@@ -27,6 +27,10 @@ import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RGBImageFilter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
@@ -44,6 +48,7 @@ import com.formdev.flatlaf.util.Graphics2DProxy;
|
||||
import com.formdev.flatlaf.util.GrayFilter;
|
||||
import com.formdev.flatlaf.util.LoggingFacade;
|
||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||
import com.formdev.flatlaf.util.SoftCache;
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
import com.kitfox.svg.SVGDiagram;
|
||||
import com.kitfox.svg.SVGException;
|
||||
@@ -58,8 +63,12 @@ public class FlatSVGIcon
|
||||
extends ImageIcon
|
||||
implements DisabledIconProvider
|
||||
{
|
||||
// cache that uses soft references for values, which allows freeing SVG diagrams if no longer used
|
||||
private static final SoftCache<URI, SVGDiagram> svgCache = new SoftCache<>();
|
||||
|
||||
// use own SVG universe so that it can not be cleared from anywhere
|
||||
private static final SVGUniverse svgUniverse = new SVGUniverse();
|
||||
private static int streamNumber;
|
||||
|
||||
private final String name;
|
||||
private final int width;
|
||||
@@ -67,23 +76,30 @@ public class FlatSVGIcon
|
||||
private final float scale;
|
||||
private final boolean disabled;
|
||||
private final ClassLoader classLoader;
|
||||
private final URI uri;
|
||||
|
||||
private ColorFilter colorFilter;
|
||||
|
||||
private SVGDiagram diagram;
|
||||
private boolean dark;
|
||||
private boolean loadFailed;
|
||||
|
||||
/**
|
||||
* Creates an SVG icon from the given resource name.
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name ) {
|
||||
this( name, -1, -1, 1, false, null );
|
||||
this( name, -1, -1, 1, false, null, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,27 +108,37 @@ public class FlatSVGIcon
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @param classLoader the class loader used to load the SVG resource
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name, ClassLoader classLoader ) {
|
||||
this( name, -1, -1, 1, false, classLoader );
|
||||
this( name, -1, -1, 1, false, classLoader, null );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SVG icon from the given resource name with the given width and height.
|
||||
* <p>
|
||||
* The icon is scaled if the given size is different to the size specified in the SVG file.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @param width the width of the icon
|
||||
* @param height the height of the icon
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name, int width, int height ) {
|
||||
this( name, width, height, 1, false, null );
|
||||
this( name, width, height, 1, false, null, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,15 +146,20 @@ public class FlatSVGIcon
|
||||
* The SVG file is loaded from the given class loader.
|
||||
* <p>
|
||||
* The icon is scaled if the given size is different to the size specified in the SVG file.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @param width the width of the icon
|
||||
* @param height the height of the icon
|
||||
* @param classLoader the class loader used to load the SVG resource
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name, int width, int height, ClassLoader classLoader ) {
|
||||
this( name, width, height, 1, false, classLoader );
|
||||
this( name, width, height, 1, false, classLoader, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,13 +168,18 @@ public class FlatSVGIcon
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as base icon size, which is multiplied
|
||||
* by the given scale factor.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @param scale the amount by which the icon size is scaled
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name, float scale ) {
|
||||
this( name, -1, -1, scale, false, null );
|
||||
this( name, -1, -1, scale, false, null, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,23 +189,107 @@ public class FlatSVGIcon
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as base icon size, which is multiplied
|
||||
* by the given scale factor.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the icon must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #FlatSVGIcon(URL)}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param name the name of the SVG resource (a '/'-separated path)
|
||||
* @param name the name of the SVG resource (a '/'-separated path; e.g. {@code "com/myapp/myicon.svg"})
|
||||
* @param scale the amount by which the icon size is scaled
|
||||
* @param classLoader the class loader used to load the SVG resource
|
||||
* @see ClassLoader#getResource(String)
|
||||
*/
|
||||
public FlatSVGIcon( String name, float scale, ClassLoader classLoader ) {
|
||||
this( name, -1, -1, scale, false, classLoader );
|
||||
this( name, -1, -1, scale, false, classLoader, null );
|
||||
}
|
||||
|
||||
protected FlatSVGIcon( String name, int width, int height, float scale, boolean disabled, ClassLoader classLoader ) {
|
||||
/**
|
||||
* Creates an SVG icon from the given URL.
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* This method is useful if using Java modules and the package containing the icon
|
||||
* is not opened in {@code module-info.java}.
|
||||
* E.g. {@code new FlatSVGIcon( getClass().getResource( "/com/myapp/myicon.svg" ) )}.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param url the URL of the SVG resource
|
||||
* @see ClassLoader#getResource(String)
|
||||
* @since 2
|
||||
*/
|
||||
public FlatSVGIcon( URL url ) {
|
||||
this( null, -1, -1, 1, false, null, url2uri( url ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SVG icon from the given URI.
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param uri the URI of the SVG resource
|
||||
* @see ClassLoader#getResource(String)
|
||||
* @since 2
|
||||
*/
|
||||
public FlatSVGIcon( URI uri ) {
|
||||
this( null, -1, -1, 1, false, null, uri );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SVG icon from the given file.
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* This is cheap operation because the icon is only loaded when used.
|
||||
*
|
||||
* @param file the SVG file
|
||||
* @since 2
|
||||
*/
|
||||
public FlatSVGIcon( File file ) {
|
||||
this( null, -1, -1, 1, false, null, file.toURI() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SVG icon from the given input stream.
|
||||
* <p>
|
||||
* The SVG attributes {@code width} and {@code height} (or {@code viewBox})
|
||||
* in the tag {@code <svg>} are used as icon size.
|
||||
* <p>
|
||||
* The input stream is loaded, parsed and closed immediately.
|
||||
*
|
||||
* @param in the input stream for reading a SVG resource
|
||||
* @throws IOException if an I/O exception occurs
|
||||
* @since 2
|
||||
*/
|
||||
public FlatSVGIcon( InputStream in ) throws IOException {
|
||||
this( null, -1, -1, 1, false, null, loadFromStream( in ) );
|
||||
|
||||
// since the input stream is already loaded and parsed,
|
||||
// get diagram here and remove it from cache
|
||||
update();
|
||||
svgCache.remove( uri );
|
||||
}
|
||||
|
||||
private static URI loadFromStream( InputStream in ) throws IOException {
|
||||
try( InputStream in2 = in ) {
|
||||
return svgUniverse.loadSVG( in2, "/flatlaf-stream-" + (streamNumber++) );
|
||||
}
|
||||
}
|
||||
|
||||
protected FlatSVGIcon( String name, int width, int height, float scale, boolean disabled, ClassLoader classLoader, URI uri ) {
|
||||
this.name = name;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.scale = scale;
|
||||
this.disabled = disabled;
|
||||
this.classLoader = classLoader;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,7 +368,7 @@ public class FlatSVGIcon
|
||||
if( width == this.width && height == this.height )
|
||||
return this;
|
||||
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader );
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader, uri );
|
||||
icon.colorFilter = colorFilter;
|
||||
icon.diagram = diagram;
|
||||
icon.dark = dark;
|
||||
@@ -267,7 +387,7 @@ public class FlatSVGIcon
|
||||
if( scale == this.scale )
|
||||
return this;
|
||||
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader );
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, disabled, classLoader, uri );
|
||||
icon.colorFilter = colorFilter;
|
||||
icon.diagram = diagram;
|
||||
icon.dark = dark;
|
||||
@@ -286,7 +406,7 @@ public class FlatSVGIcon
|
||||
if( disabled )
|
||||
return this;
|
||||
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, true, classLoader );
|
||||
FlatSVGIcon icon = new FlatSVGIcon( name, width, height, scale, true, classLoader, uri );
|
||||
icon.colorFilter = colorFilter;
|
||||
icon.diagram = diagram;
|
||||
icon.dark = dark;
|
||||
@@ -324,20 +444,56 @@ public class FlatSVGIcon
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if( loadFailed )
|
||||
return;
|
||||
|
||||
if( dark == isDarkLaf() && diagram != null )
|
||||
return;
|
||||
|
||||
dark = isDarkLaf();
|
||||
URL url = getIconURL( name, dark );
|
||||
if( url == null & dark )
|
||||
url = getIconURL( name, false );
|
||||
|
||||
// load/get image
|
||||
try {
|
||||
diagram = svgUniverse.getDiagram( url.toURI() );
|
||||
} catch( URISyntaxException ex ) {
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to load SVG icon '" + url + "'.", ex );
|
||||
// SVGs already loaded via url or input stream can not have light/dark variants
|
||||
if( uri != null && diagram != null )
|
||||
return;
|
||||
|
||||
URI uri = this.uri;
|
||||
if( uri == null ) {
|
||||
URL url = getIconURL( name, dark );
|
||||
if( url == null & dark )
|
||||
url = getIconURL( name, false );
|
||||
|
||||
if( url == null ) {
|
||||
loadFailed = true;
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatSVGIcon: resource '" + name + "' not found (if using Java modules, check whether icon package is opened in module-info.java)", null );
|
||||
return;
|
||||
}
|
||||
|
||||
uri = url2uri( url );
|
||||
}
|
||||
|
||||
diagram = loadSVG( uri );
|
||||
loadFailed = (diagram == null);
|
||||
}
|
||||
|
||||
static SVGDiagram loadSVG( URI uri ) {
|
||||
// get from our cache
|
||||
SVGDiagram diagram = svgCache.get( uri );
|
||||
if( diagram != null )
|
||||
return diagram;
|
||||
|
||||
// load/get SVG diagram
|
||||
diagram = svgUniverse.getDiagram( uri );
|
||||
|
||||
if( diagram == null ) {
|
||||
LoggingFacade.INSTANCE.logSevere( "FlatSVGIcon: failed to load '" + uri + "'", null );
|
||||
return null;
|
||||
}
|
||||
|
||||
// add to our (soft) cache and remove from SVGUniverse (hard) cache
|
||||
svgCache.put( uri, diagram );
|
||||
svgUniverse.removeDocument( uri );
|
||||
|
||||
return diagram;
|
||||
}
|
||||
|
||||
private URL getIconURL( String name, boolean dark ) {
|
||||
@@ -487,6 +643,14 @@ public class FlatSVGIcon
|
||||
return MultiResolutionImageSupport.create( 0, dimensions, producer );
|
||||
}
|
||||
|
||||
static URI url2uri( URL url ) {
|
||||
try {
|
||||
return url.toURI();
|
||||
} catch( URISyntaxException ex ) {
|
||||
throw new IllegalArgumentException( ex );
|
||||
}
|
||||
}
|
||||
|
||||
private static Boolean darkLaf;
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -29,7 +28,6 @@ import java.util.List;
|
||||
import javax.swing.JWindow;
|
||||
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
|
||||
import com.formdev.flatlaf.util.SystemInfo;
|
||||
import com.kitfox.svg.SVGCache;
|
||||
import com.kitfox.svg.SVGDiagram;
|
||||
import com.kitfox.svg.SVGException;
|
||||
|
||||
@@ -50,6 +48,9 @@ public class FlatSVGUtils
|
||||
* for requested sizes from SVG.
|
||||
* This has the advantage that only images for used sizes are created.
|
||||
* Also if unusual sizes are requested (e.g. 18x18), then they are created from SVG.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #createWindowIconImages(URL)}.
|
||||
*
|
||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||
* @return list of icon images with different sizes (16x16, 20x20, 24x24, 28x28, 32x32, 48x48 and 64x64)
|
||||
@@ -57,7 +58,32 @@ public class FlatSVGUtils
|
||||
* @see JWindow#setIconImages(List)
|
||||
*/
|
||||
public static List<Image> createWindowIconImages( String svgName ) {
|
||||
SVGDiagram diagram = loadSVG( svgName );
|
||||
return createWindowIconImages( getResource( svgName ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates from the given SVG a list of icon images with different sizes that
|
||||
* can be used for windows headers. The SVG should have a size of 16x16,
|
||||
* otherwise it is scaled.
|
||||
* <p>
|
||||
* If running on Windows in Java 9 or later and multi-resolution image support is available,
|
||||
* then a single multi-resolution image is returned that creates images on demand
|
||||
* for requested sizes from SVG.
|
||||
* This has the advantage that only images for used sizes are created.
|
||||
* Also if unusual sizes are requested (e.g. 18x18), then they are created from SVG.
|
||||
* <p>
|
||||
* This method is useful if using Java modules and the package containing the SVG
|
||||
* is not opened in {@code module-info.java}.
|
||||
* E.g. {@code createWindowIconImages( getClass().getResource( "/com/myapp/myicon.svg" ) )}.
|
||||
*
|
||||
* @param svgUrl the URL of the SVG resource
|
||||
* @return list of icon images with different sizes (16x16, 20x20, 24x24, 28x28, 32x32, 48x48 and 64x64)
|
||||
* @throws RuntimeException if failed to load or render SVG file
|
||||
* @see JWindow#setIconImages(List)
|
||||
* @since 2
|
||||
*/
|
||||
public static List<Image> createWindowIconImages( URL svgUrl ) {
|
||||
SVGDiagram diagram = loadSVG( svgUrl );
|
||||
|
||||
if( SystemInfo.isWindows && MultiResolutionImageSupport.isAvailable() ) {
|
||||
// use a multi-resolution image that creates images on demand for requested sizes
|
||||
@@ -93,6 +119,9 @@ public class FlatSVGUtils
|
||||
|
||||
/**
|
||||
* Creates a buffered image and renders the given SVG into it.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #svg2image(URL, int, int)}.
|
||||
*
|
||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||
* @param width the width of the image
|
||||
@@ -101,11 +130,32 @@ public class FlatSVGUtils
|
||||
* @throws RuntimeException if failed to load or render SVG file
|
||||
*/
|
||||
public static BufferedImage svg2image( String svgName, int width, int height ) {
|
||||
return svg2image( loadSVG( svgName ), width, height );
|
||||
return svg2image( getResource( svgName ), width, height );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a buffered image and renders the given SVG into it.
|
||||
* <p>
|
||||
* This method is useful if using Java modules and the package containing the SVG
|
||||
* is not opened in {@code module-info.java}.
|
||||
* E.g. {@code svg2image( getClass().getResource( "/com/myapp/myicon.svg" ), 24, 24 )}.
|
||||
*
|
||||
* @param svgUrl the URL of the SVG resource
|
||||
* @param width the width of the image
|
||||
* @param height the height of the image
|
||||
* @return the image
|
||||
* @throws RuntimeException if failed to load or render SVG file
|
||||
* @since 2
|
||||
*/
|
||||
public static BufferedImage svg2image( URL svgUrl, int width, int height ) {
|
||||
return svg2image( loadSVG( svgUrl ), width, height );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a buffered image and renders the given SVG into it.
|
||||
* <p>
|
||||
* If using Java modules, the package containing the SVG must be opened in {@code module-info.java}.
|
||||
* Otherwise use {@link #svg2image(URL, float)}.
|
||||
*
|
||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||
* @param scaleFactor the amount by which the SVG size is scaled
|
||||
@@ -113,7 +163,24 @@ public class FlatSVGUtils
|
||||
* @throws RuntimeException if failed to load or render SVG file
|
||||
*/
|
||||
public static BufferedImage svg2image( String svgName, float scaleFactor ) {
|
||||
SVGDiagram diagram = loadSVG( svgName );
|
||||
return svg2image( getResource( svgName ), scaleFactor );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a buffered image and renders the given SVG into it.
|
||||
* <p>
|
||||
* This method is useful if using Java modules and the package containing the SVG
|
||||
* is not opened in {@code module-info.java}.
|
||||
* E.g. {@code svg2image( getClass().getResource( "/com/myapp/myicon.svg" ), 1.5f )}.
|
||||
*
|
||||
* @param svgUrl the URL of the SVG resource
|
||||
* @param scaleFactor the amount by which the SVG size is scaled
|
||||
* @return the image
|
||||
* @throws RuntimeException if failed to load or render SVG file
|
||||
* @since 2
|
||||
*/
|
||||
public static BufferedImage svg2image( URL svgUrl, float scaleFactor ) {
|
||||
SVGDiagram diagram = loadSVG( svgUrl );
|
||||
int width = (int) (diagram.getWidth() * scaleFactor);
|
||||
int height = (int) (diagram.getHeight() * scaleFactor);
|
||||
return svg2image( diagram, width, height );
|
||||
@@ -155,19 +222,11 @@ public class FlatSVGUtils
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a SVG file.
|
||||
*
|
||||
* @param svgName the name of the SVG resource (a '/'-separated path)
|
||||
* @return the SVG diagram
|
||||
* @throws RuntimeException if failed to load SVG file
|
||||
*/
|
||||
private static SVGDiagram loadSVG( String svgName ) {
|
||||
try {
|
||||
URL url = FlatSVGUtils.class.getResource( svgName );
|
||||
return SVGCache.getSVGUniverse().getDiagram( url.toURI() );
|
||||
} catch( URISyntaxException ex ) {
|
||||
throw new RuntimeException( ex );
|
||||
}
|
||||
private static URL getResource( String svgName ) {
|
||||
return FlatSVGUtils.class.getResource( svgName );
|
||||
}
|
||||
|
||||
private static SVGDiagram loadSVG( URL url ) {
|
||||
return FlatSVGIcon.loadSVG( FlatSVGIcon.url2uri( url ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.extras.components.FlatTextField;
|
||||
import com.formdev.flatlaf.icons.FlatAbstractIcon;
|
||||
import com.formdev.flatlaf.ui.FlatBorder;
|
||||
import com.formdev.flatlaf.ui.FlatEmptyBorder;
|
||||
@@ -557,7 +558,7 @@ public class FlatUIDefaultsInspector
|
||||
panel = new JPanel();
|
||||
filterPanel = new JPanel();
|
||||
flterLabel = new JLabel();
|
||||
filterField = new JTextField();
|
||||
filterField = new FlatTextField();
|
||||
valueTypeLabel = new JLabel();
|
||||
valueTypeField = new JComboBox<>();
|
||||
scrollPane = new JScrollPane();
|
||||
@@ -588,7 +589,8 @@ public class FlatUIDefaultsInspector
|
||||
new Insets(0, 0, 0, 10), 0, 0));
|
||||
|
||||
//---- filterField ----
|
||||
filterField.putClientProperty("JTextField.placeholderText", "enter one or more filter strings, separated by space characters");
|
||||
filterField.setPlaceholderText("enter one or more filter strings, separated by space characters");
|
||||
filterField.setShowClearButton(true);
|
||||
filterPanel.add(filterField, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0,
|
||||
GridBagConstraints.CENTER, GridBagConstraints.BOTH,
|
||||
new Insets(0, 0, 0, 10), 0, 0));
|
||||
@@ -667,7 +669,7 @@ public class FlatUIDefaultsInspector
|
||||
private JPanel panel;
|
||||
private JPanel filterPanel;
|
||||
private JLabel flterLabel;
|
||||
private JTextField filterField;
|
||||
private FlatTextField filterField;
|
||||
private JLabel valueTypeLabel;
|
||||
private JComboBox<String> valueTypeField;
|
||||
private JScrollPane scrollPane;
|
||||
@@ -1000,6 +1002,9 @@ public class FlatUIDefaultsInspector
|
||||
{
|
||||
private Item item;
|
||||
|
||||
// used instead of getBackground() because this did not work in some 3rd party Lafs
|
||||
private Color valueColor;
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent( JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column )
|
||||
@@ -1023,7 +1028,7 @@ public class FlatUIDefaultsInspector
|
||||
if( item.value instanceof Color ) {
|
||||
Color color = (item.info instanceof Color[]) ? ((Color[])item.info)[0] : (Color) item.value;
|
||||
boolean isDark = new HSLColor( color ).getLuminance() < 70 && color.getAlpha() >= 128;
|
||||
setBackground( color );
|
||||
valueColor = color;
|
||||
setForeground( isDark ? Color.white : Color.black );
|
||||
} else if( item.value instanceof Icon ) {
|
||||
Icon icon = (Icon) item.value;
|
||||
@@ -1048,7 +1053,7 @@ public class FlatUIDefaultsInspector
|
||||
if( item.value instanceof Color ) {
|
||||
int width = getWidth();
|
||||
int height = getHeight();
|
||||
Color background = getBackground();
|
||||
Color background = valueColor;
|
||||
|
||||
// paint color
|
||||
fillRect( g, background, 0, 0, width, height );
|
||||
|
||||
@@ -20,9 +20,10 @@ new FormModel {
|
||||
"labelFor": new FormReference( "filterField" )
|
||||
"displayedMnemonic": 70
|
||||
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) )
|
||||
add( new FormComponent( "javax.swing.JTextField" ) {
|
||||
add( new FormComponent( "com.formdev.flatlaf.extras.components.FlatTextField" ) {
|
||||
name: "filterField"
|
||||
"$client.JTextField.placeholderText": "enter one or more filter strings, separated by space characters"
|
||||
"placeholderText": "enter one or more filter strings, separated by space characters"
|
||||
"showClearButton": true
|
||||
}, new FormLayoutConstraints( class com.jformdesigner.runtime.GridBagConstraintsEx ) {
|
||||
"gridx": 1
|
||||
} )
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import com.formdev.flatlaf.extras.components.FlatTextField.SelectAllOnFocusPolicy;
|
||||
|
||||
@@ -85,6 +86,84 @@ public class FlatFormattedTextField
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a component that will be placed at the leading edge of the text field.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public JComponent getLeadingComponent() {
|
||||
return (JComponent) getClientProperty( TEXT_FIELD_LEADING_COMPONENT );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the leading edge of the text field.
|
||||
* <p>
|
||||
* The component will be positioned inside and aligned to the visible text field border.
|
||||
* There is no gap between the visible border and the component.
|
||||
* The laid out component size will be the preferred component width
|
||||
* and the inner text field height.
|
||||
* <p>
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #setOutline(Object)}.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setLeadingComponent( JComponent leadingComponent ) {
|
||||
putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a component that will be placed at the trailing edge of the text field.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public JComponent getTrailingComponent() {
|
||||
return (JComponent) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||
* <p>
|
||||
* The component will be positioned inside and aligned to the visible text field border.
|
||||
* There is no gap between the visible border and the component.
|
||||
* The laid out component size will be the preferred component width
|
||||
* and the inner text field height.
|
||||
* <p>
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #setOutline(Object)}.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setTrailingComponent( JComponent trailingComponent ) {
|
||||
putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether a "clear" (or "cancel") button is shown.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public boolean isShowClearButton() {
|
||||
return getClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies whether a "clear" (or "cancel") button is shown on the trailing side
|
||||
* if the text field is not empty, editable and enabled.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setShowClearButton( boolean showClearButton ) {
|
||||
putClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, showClearButton, false );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether all text is selected when the text component gains focus.
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.formdev.flatlaf.extras.components;
|
||||
|
||||
import static com.formdev.flatlaf.FlatClientProperties.STYLE_CLASS;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
/**
|
||||
@@ -26,6 +27,24 @@ import javax.swing.JLabel;
|
||||
*/
|
||||
public class FlatLabel
|
||||
extends JLabel
|
||||
implements FlatStyleableComponent
|
||||
implements FlatComponentExtension, FlatStyleableComponent
|
||||
{
|
||||
// NOTE: enum names must be equal to typography/font styles
|
||||
public enum LabelType { h00, h0, h1, h2, h3, h4, large, regular, medium, small, mini, monospaced }
|
||||
|
||||
/**
|
||||
* Returns type of the label.
|
||||
*/
|
||||
public LabelType getLabelType() {
|
||||
return getClientPropertyEnumString( STYLE_CLASS, LabelType.class, null, LabelType.regular );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies type of the label.
|
||||
*/
|
||||
public void setLabelType( LabelType labelType ) {
|
||||
if( labelType == LabelType.regular )
|
||||
labelType = null;
|
||||
putClientPropertyEnumString( STYLE_CLASS, labelType );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPasswordField;
|
||||
import com.formdev.flatlaf.extras.components.FlatTextField.SelectAllOnFocusPolicy;
|
||||
|
||||
@@ -85,6 +86,84 @@ public class FlatPasswordField
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a component that will be placed at the leading edge of the text field.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public JComponent getLeadingComponent() {
|
||||
return (JComponent) getClientProperty( TEXT_FIELD_LEADING_COMPONENT );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the leading edge of the text field.
|
||||
* <p>
|
||||
* The component will be positioned inside and aligned to the visible text field border.
|
||||
* There is no gap between the visible border and the component.
|
||||
* The laid out component size will be the preferred component width
|
||||
* and the inner text field height.
|
||||
* <p>
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #setOutline(Object)}.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setLeadingComponent( JComponent leadingComponent ) {
|
||||
putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a component that will be placed at the trailing edge of the text field.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public JComponent getTrailingComponent() {
|
||||
return (JComponent) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||
* <p>
|
||||
* The component will be positioned inside and aligned to the visible text field border.
|
||||
* There is no gap between the visible border and the component.
|
||||
* The laid out component size will be the preferred component width
|
||||
* and the inner text field height.
|
||||
* <p>
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #setOutline(Object)}.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setTrailingComponent( JComponent trailingComponent ) {
|
||||
putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether a "clear" (or "cancel") button is shown.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public boolean isShowClearButton() {
|
||||
return getClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies whether a "clear" (or "cancel") button is shown on the trailing side
|
||||
* if the text field is not empty, editable and enabled.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setShowClearButton( boolean showClearButton ) {
|
||||
putClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, showClearButton, false );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether all text is selected when the text component gains focus.
|
||||
*/
|
||||
|
||||
@@ -363,6 +363,29 @@ public class FlatTabbedPane
|
||||
}
|
||||
|
||||
|
||||
// NOTE: enum names must be equal to allowed strings
|
||||
/** @since 2 */ public enum TabType { underlined, card };
|
||||
|
||||
/**
|
||||
* Returns type of selected tab.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public TabType getTabType() {
|
||||
return getClientPropertyEnumString( TABBED_PANE_TAB_TYPE, TabType.class,
|
||||
"TabbedPane.tabType", TabType.underlined );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies type of selected tab.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setTabType( TabType tabType ) {
|
||||
putClientPropertyEnumString( TABBED_PANE_TAB_TYPE, tabType );
|
||||
}
|
||||
|
||||
|
||||
// NOTE: enum names must be equal to allowed strings
|
||||
public enum TabsPopupPolicy { never, asNeeded };
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Insets;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
/**
|
||||
@@ -84,6 +85,84 @@ public class FlatTextField
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a component that will be placed at the leading edge of the text field.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public JComponent getLeadingComponent() {
|
||||
return (JComponent) getClientProperty( TEXT_FIELD_LEADING_COMPONENT );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the leading edge of the text field.
|
||||
* <p>
|
||||
* The component will be positioned inside and aligned to the visible text field border.
|
||||
* There is no gap between the visible border and the component.
|
||||
* The laid out component size will be the preferred component width
|
||||
* and the inner text field height.
|
||||
* <p>
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #setOutline(Object)}.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setLeadingComponent( JComponent leadingComponent ) {
|
||||
putClientProperty( TEXT_FIELD_LEADING_COMPONENT, leadingComponent );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a component that will be placed at the trailing edge of the text field.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public JComponent getTrailingComponent() {
|
||||
return (JComponent) getClientProperty( TEXT_FIELD_TRAILING_COMPONENT );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a component that will be placed at the trailing edge of the text field.
|
||||
* <p>
|
||||
* The component will be positioned inside and aligned to the visible text field border.
|
||||
* There is no gap between the visible border and the component.
|
||||
* The laid out component size will be the preferred component width
|
||||
* and the inner text field height.
|
||||
* <p>
|
||||
* The component should be not opaque because the text field border is painted
|
||||
* slightly inside the usually visible border in some cases.
|
||||
* E.g. when focused (in some themes) or when an outline color is specified
|
||||
* (see {@link #setOutline(Object)}.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setTrailingComponent( JComponent trailingComponent ) {
|
||||
putClientProperty( TEXT_FIELD_TRAILING_COMPONENT, trailingComponent );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether a "clear" (or "cancel") button is shown.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public boolean isShowClearButton() {
|
||||
return getClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies whether a "clear" (or "cancel") button is shown on the trailing side
|
||||
* if the text field is not empty, editable and enabled.
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
public void setShowClearButton( boolean showClearButton ) {
|
||||
putClientPropertyBoolean( TEXT_FIELD_SHOW_CLEAR_BUTTON, showClearButton, false );
|
||||
}
|
||||
|
||||
|
||||
// NOTE: enum names must be equal to allowed strings
|
||||
public enum SelectAllOnFocusPolicy { never, once, always };
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
"nonEditableBackground": "secondaryBackground"
|
||||
},
|
||||
"CompletionPopup": {
|
||||
"selectionBackground": "selectionBackground",
|
||||
"selectionBackground": "selectionInactiveBackground",
|
||||
"selectionInactiveBackground": "selectionInactiveBackground",
|
||||
"matchForeground": "accentColor"
|
||||
},
|
||||
@@ -256,10 +256,8 @@
|
||||
"selectionInactiveBackground": "selectionInactiveBackground"
|
||||
},
|
||||
"ValidationTooltip": {
|
||||
"errorBackground": "#ff5554",
|
||||
"errorBorderColor": "#ff5554",
|
||||
"warningBorderColor": "#ffb86c",
|
||||
"warningBackground": "#ffb86c"
|
||||
"errorBackground": "#4c273c",
|
||||
"warningBackground": "#4f4b41"
|
||||
},
|
||||
"VersionControl": {
|
||||
"FileHistory": {
|
||||
@@ -330,4 +328,4 @@
|
||||
"Checkbox.Focus.Thin.Default.Dark": "#bd93f9"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,309 +5,350 @@
|
||||
"editorScheme": "/colors/Dark.xml",
|
||||
"colors": {
|
||||
"black": "#000000",
|
||||
"consoleBackground": "#191919",
|
||||
"editorBackground": "#212121",
|
||||
"panelBackground": "#333333",
|
||||
"textColor": "#F9F6EF",
|
||||
"border": "#3c3c3c",
|
||||
"editorDarkerBg": "#2D2B29",
|
||||
"shortcutForeground": "#2d2b29",
|
||||
"editorBg": "#1B1A19",
|
||||
"consoleBackground": "#171615",
|
||||
"editorPaneBg": "#333231",
|
||||
"panelBackground": "#333231",
|
||||
"textColor": "#f9f6ef",
|
||||
"textColorTransparent": "#f9f6ef7f",
|
||||
"border": "#4d4c4b",
|
||||
"redMac": "#fb3b45",
|
||||
"redWin": "#ef6950",
|
||||
"redMonokaiPro": "#ff6188",
|
||||
"blueWinPalette": "#409AE1",
|
||||
"blue": "#78dce8",
|
||||
"deepBlue": "#3199b3",
|
||||
"orangeMonokaiPro": "#fc9867",
|
||||
"greenMonokaiPro": "#a9dc76",
|
||||
"yellowWinPalette": "#ffc83d",
|
||||
"yellowMac": "#faaa1f",
|
||||
"yellow": "#FFB900",
|
||||
"purpleWinPalette": "#b4a0ff",
|
||||
"purpleMonokaiPro": "#ab9df2",
|
||||
"greenWinPalette": "#40c5af",
|
||||
"greyWinPalette": "#b2b2b2",
|
||||
"panelText": "#a6a6a6",
|
||||
"desaturatedBlue": "#1e282d",
|
||||
"panelText": "#acacac",
|
||||
"desaturatedOrange": "#8049117f",
|
||||
"green": "#5B8021",
|
||||
"greyDot15": "#d8d8d8",
|
||||
"greyDot20": "#cccccc",
|
||||
"green": "#92d923",
|
||||
"greyDot15": "#f9f6ef",
|
||||
"greyDot20": "#c0c0c0",
|
||||
"greyDot25": "#bfbfbf",
|
||||
"greyDot33": "#aaaaaa",
|
||||
"greyDot50": "#7d7d7d",
|
||||
"greyDot60": "#666666",
|
||||
"greyDot65": "#5a5a5a",
|
||||
"greyDot70": "#4d4d4d",
|
||||
"greyDot75": "#434343",
|
||||
"greyDot80": "#323232",
|
||||
"greyDot85": "#252525",
|
||||
"greyDot90": "#1f2021",
|
||||
"greyDot70": "#4d4c4b",
|
||||
"greyDot75": "#434241",
|
||||
"greyDot80": "#333231",
|
||||
"greyDot85": "#2d2b29",
|
||||
"greyDot90": "#1f1e1d",
|
||||
"greyDot95": "#242220",
|
||||
"greyDot100": "#181615",
|
||||
"lightBlue": "#70D7FF",
|
||||
"navyDot85": "#191d21",
|
||||
"navyDot90": "#1f2021",
|
||||
"red": "#800040",
|
||||
"transparentGreen": "#5B80217f",
|
||||
"transparentRed": "#8000407f",
|
||||
"transparentViolet": "#9478F67f",
|
||||
"transparentYellow": "#8066357f",
|
||||
"yellow": "#806635"
|
||||
},
|
||||
"icons": {
|
||||
"ColorPalette": {
|
||||
"Actions.Blue": "#57D1EB",
|
||||
"Actions.Green": "#92D923",
|
||||
"Actions.Grey": "#afafaf",
|
||||
"Actions.GreyInline": "#7f7f7f",
|
||||
"Actions.GreyInline.Dark": "#646464",
|
||||
"Actions.Red": "#ff6188",
|
||||
"Actions.Yellow": "#FFC83C",
|
||||
"Objects.BlackText": "#7d7d7d",
|
||||
"Objects.Blue": "#57D1EB",
|
||||
"Objects.Green": "#92D923",
|
||||
"Objects.GreenAndroid": "#92D923",
|
||||
"Objects.Grey": "#7f7f7f",
|
||||
"Objects.Pink": "#ffa9ca",
|
||||
"Objects.Purple": "#9380FF",
|
||||
"Objects.Red": "#ed005c",
|
||||
"Objects.RedStatus": "#EC5F5D",
|
||||
"Objects.Yellow": "#FFC83C",
|
||||
"Objects.YellowDark": "#FD971F"
|
||||
}
|
||||
"transparentRed": "#F250227f",
|
||||
"transparentViolet": "#242221ff",
|
||||
"transparentYellow": "#FFB9007f"
|
||||
},
|
||||
"ui": {
|
||||
"*": {
|
||||
"arc": "3",
|
||||
"shadow": "greyDot75",
|
||||
"background": "greyDot80",
|
||||
"borderColor": "greyDot70",
|
||||
"caretForeground": "yellowMac",
|
||||
"color": "greyDot50",
|
||||
"foreground": "greyDot20",
|
||||
"hoverBackground": "greyDot70",
|
||||
"selectedBackground": "greyDot85",
|
||||
"selectedForeground": "greyDot15",
|
||||
"selectedInactiveBackground": "greyDot70",
|
||||
"selectionBackground": "navyDot85",
|
||||
"selectionForeground": "yellowMac",
|
||||
"separatorColor": "greyDot75",
|
||||
"arc": 5,
|
||||
"background": "panelBackground",
|
||||
"borderColor": "border",
|
||||
"caretForeground": "yellow",
|
||||
"color": "greyDot60",
|
||||
"foreground": "textColor",
|
||||
"hoverBackground": "greyDot85",
|
||||
"selectedBackground": "greyDot90",
|
||||
"selectedForeground": "textColor",
|
||||
"selectedInactiveBackground": "greyDot75",
|
||||
"selectionBackground": "greyDot95",
|
||||
"selectionForeground": "yellow",
|
||||
"separatorColor": "border",
|
||||
"underlineHeight": 1
|
||||
},
|
||||
"ActionButton": {
|
||||
"hoverBorderColor": "greyDot50",
|
||||
"pressedBackground": "greyDot65",
|
||||
"pressedBorderColor": "greyDot50"
|
||||
"pressedBackground": "greyDot95",
|
||||
"hoverBorderColor": "greyDot65",
|
||||
"pressedBorderColor": "greyDot60"
|
||||
},
|
||||
"Borders": {
|
||||
"ContrastBorderColor": "greyDot65",
|
||||
"ContrastBorderColor": "greyDot60",
|
||||
"color": "border"
|
||||
},
|
||||
"Button.default.endBackground": "greyDot80",
|
||||
"Button.default.endBorderColor": "greyDot65",
|
||||
"Button.default.focusColor": "greyDot80",
|
||||
"Button.default.focusedBorderColor": "greyDot15",
|
||||
"Button.default.foreground": "greyDot15",
|
||||
"Button.default.startBackground": "greyDot80",
|
||||
"Button.default.startBorderColor": "greyDot65",
|
||||
"Button.endBackground": "greyDot80",
|
||||
"Button.endBorderColor": "greyDot65",
|
||||
"Button.focusedBorderColor": "yellowMac",
|
||||
"Button.startBackground": "greyDot80",
|
||||
"Button.startBorderColor": "greyDot65",
|
||||
"CheckBox.disabledText": "greyDot33",
|
||||
"CheckBox.select": "greyDot50",
|
||||
"CheckBoxMenuItem.disabledBackground": "greyDot80",
|
||||
"ComboBox.ArrowButton.disabledIconColor": "greyDot50",
|
||||
"ComboBox.ArrowButton.iconColor": "yellowMac",
|
||||
"ComboBox.ArrowButton.nonEditableBackground": "greyDot70",
|
||||
"ComboBox.modifiedItemForeground": "yellowMac",
|
||||
"ComboBox.disabledForeground": "greyDot80",
|
||||
"ComboBox.nonEditableBackground": "greyDot75",
|
||||
"ComboPopup.border": "1,1,1,1,4d4d4d",
|
||||
"CompletionPopup": {
|
||||
"nonFocusedMask": "#34343434",
|
||||
"selectionBackground": "navyDot85",
|
||||
"Button": {
|
||||
"arc": 5,
|
||||
"default": {
|
||||
"endBackground": "greyDot80",
|
||||
"endBorderColor": "greyDot70",
|
||||
"focusColor": "greyDot60",
|
||||
"focusedBorderColor": "greyDot50",
|
||||
"foreground": "greyDot33",
|
||||
"startBackground": "greyDot80",
|
||||
"startBorderColor": "greyDot70"
|
||||
},
|
||||
"shadowWidth": 1,
|
||||
"endBackground": "greyDot80",
|
||||
"endBorderColor": "greyDot70",
|
||||
"focusedBorderColor": "greyDot50",
|
||||
"foreground": "greyDot20",
|
||||
"matchForeground": "yellowMac"
|
||||
"disabledBorderColor": "greyDot75",
|
||||
"startBackground": "greyDot80",
|
||||
"startBorderColor": "greyDot70"
|
||||
},
|
||||
"CheckBox.disabledText": "greyDot50",
|
||||
"CheckBox.foreground": "greyDot33",
|
||||
"CheckBox.select": "greyDot50",
|
||||
"CheckBoxMenuItem.background": "greyDot80",
|
||||
"CheckBoxMenuItem.disabledBackground": "greyDot80",
|
||||
"CheckBoxMenuItem.disabledForeground": "greyDot50",
|
||||
"CheckBoxMenuItem.foreground": "greyDot20",
|
||||
"ColorChooser.background": "greyDot80",
|
||||
"ComboBox": {
|
||||
"ArrowButton": {
|
||||
"disabledIconColor": "textColorTransparent",
|
||||
"iconColor": "yellow",
|
||||
"nonEditableBackground": "greyDot65"
|
||||
},
|
||||
"background": "greyDot80",
|
||||
"disabledForeground": "greyDot50",
|
||||
"foreground": "greyDot20",
|
||||
"modifiedItemForeground": "yellow",
|
||||
"nonEditableBackground": "greyDot75",
|
||||
"selectionBackground": "greyDot95"
|
||||
},
|
||||
"CompletionPopup": {
|
||||
"foreground": "greyDot20",
|
||||
"matchForeground": "yellow",
|
||||
"selectionBackground": "greyDot95",
|
||||
"selectionInactiveBackground": "greyDot85"
|
||||
},
|
||||
"Component": {
|
||||
"arc": "3",
|
||||
"disabledBorderColor": "greyDot70",
|
||||
"arc": "4",
|
||||
"iconColor": "yellow",
|
||||
"disabledBorderColor": "greyDot75",
|
||||
"infoForeground": "greyDot50",
|
||||
"errorFocusColor": "#F65F87",
|
||||
"focusColor": "greyDot50",
|
||||
"focusWidth": "0",
|
||||
"focusedBorderColor": "greyDot50",
|
||||
"hoverIconColor": "yellowMac",
|
||||
"errorFocusColor": "red",
|
||||
"focusColor": "greyDot60",
|
||||
"focusWidth": 0,
|
||||
"focusedBorderColor": "greyDot65",
|
||||
"inactiveErrorFocusColor": "transparentRed",
|
||||
"inactiveWarningFocusColor": "transparentYellow",
|
||||
"warningFocusColor": "yellow"
|
||||
},
|
||||
"Debugger.Variables.changedValueForeground": "yellowMac",
|
||||
"Debugger.Variables.changedValueForeground": "yellow",
|
||||
"Debugger.Variables.evaluatingExpressionForeground": "lightBlue",
|
||||
"DefaultTabs.underlineColor": "yellowMac",
|
||||
"DefaultTabs.borderColor": "border",
|
||||
"DefaultTabs.inactiveUnderlineColor": "border",
|
||||
"DefaultTabs.underlineColor": "yellow",
|
||||
"DefaultTabs.underlineHeight": 1,
|
||||
"DefaultTabs.underlinedTabBackground": "greyDot75",
|
||||
"DefaultTabs.underlinedTabForeground": "lightBlue",
|
||||
"DefaultTabs.underlinedTabForeground": "yellow",
|
||||
"DragAndDrop.areaBackground": "greyDot75",
|
||||
"DragAndDrop.areaForeground": "greyDot25",
|
||||
"Editor.background": "greyDot90",
|
||||
"EditorPane.inactiveBackground": "greyDot85",
|
||||
"EditorPane.inactiveForeground": "greyDot50",
|
||||
"EditorTabs.underlineHeight": 1,
|
||||
"FileColor.Blue": "#23282d",
|
||||
"FileColor.Green": "#232d28",
|
||||
"FileColor.Orange": "#2d2823",
|
||||
"FileColor.Rose": "#2d2323",
|
||||
"FileColor.Violet": "#2D232D",
|
||||
"FileColor.Yellow": "#2d2d23",
|
||||
"FormattedTextField.inactiveBackground": "greyDot80",
|
||||
"FormattedTextField.background": "greyDot75",
|
||||
"GutterTooltip.infoForeground": "greyDot50",
|
||||
"Editor": {
|
||||
"background": "editorPaneBg",
|
||||
"foreground": "textColor",
|
||||
"shortcutForeground": "greyDot20"
|
||||
},
|
||||
"EditorPane": {
|
||||
"background": "editorPaneBg",
|
||||
"inactiveBackground": "editorDarkerBg",
|
||||
"inactiveForeground": "greyDot50",
|
||||
"selectionBackground": "editorBg",
|
||||
"selectionForeground": "textColor"
|
||||
},
|
||||
"EditorTabs": {
|
||||
"underlineHeight": 1,
|
||||
"borderColor": "editorDarkerBg",
|
||||
"hoverBackground": "editorBg",
|
||||
"background": "editorPaneBg",
|
||||
"inactiveUnderlineColor": "editorPaneBg",
|
||||
"underlinedTabForeground": "textColor"
|
||||
},
|
||||
"EditorTabs.inactiveColoredFileBackground": true,
|
||||
"FileColor": {
|
||||
"Blue": "#23282d",
|
||||
"Green": "#232d28",
|
||||
"Orange": "#2d2823",
|
||||
"Rose": "#2d2323",
|
||||
"Violet": "#2D232D",
|
||||
"Yellow": "#2d2d23"
|
||||
},
|
||||
"FormattedTextField": {
|
||||
"foreground": "textColor",
|
||||
"selectionBackground": "greyDot95",
|
||||
"inactiveBackground": "greyDot80",
|
||||
"inactiveForeground": "greyDot33",
|
||||
"background": "greyDot75"
|
||||
},
|
||||
"GutterTooltip": {
|
||||
"infoForeground": "greyDot33",
|
||||
"lineSeparatorColor": "greyDot70"
|
||||
},
|
||||
"InformationHint.borderColor": "greyDot75",
|
||||
"InplaceRefactoringPopup.borderColor": "greyDot75",
|
||||
"Label": {
|
||||
"foreground": "greyDot25",
|
||||
"disabledForeground": "greyDot33",
|
||||
"disabledText": "greyDot33",
|
||||
"foreground": "greyDot20",
|
||||
"infoForeground": "greyDot50"
|
||||
},
|
||||
"Link.activeForeground": "lightBlue",
|
||||
"Link.hoverForeground": "yellowMac",
|
||||
"Link.pressedForeground": "lightBlue",
|
||||
"Link.visitedForeground": "greyDot25",
|
||||
"Link.hoverForeground": "yellow",
|
||||
"MemoryIndicator.allocatedBackground": "green",
|
||||
"MemoryIndicator.usedBackground": "red",
|
||||
"Menu": {
|
||||
"background": "greyDot80",
|
||||
"disabledForeground": "greyDot70",
|
||||
"separatorColor": "greyDot75",
|
||||
"foreground": "textColor",
|
||||
"borderColor": "greyDot70",
|
||||
"acceleratorForeground": "greyDot25"
|
||||
"acceleratorForeground": "greyDot33"
|
||||
},
|
||||
"Notification.MoreButton.innerBorderColor": "greyDot65",
|
||||
"Notification.ToolWindow.errorBackground": "greyDot85",
|
||||
"Notification.ToolWindow.errorBorderColor": "#ed005c",
|
||||
"Notification.ToolWindow.errorForeground": "#F65F87",
|
||||
"Notification.ToolWindow.informativeBackground": "greyDot85",
|
||||
"Notification.ToolWindow.errorBackground": "greyDot95",
|
||||
"Notification.ToolWindow.errorBorderColor": "red",
|
||||
"Notification.ToolWindow.errorForeground": "#EE7762",
|
||||
"Notification.ToolWindow.informativeBackground": "greyDot95",
|
||||
"Notification.ToolWindow.informativeBorderColor": "#92D923",
|
||||
"Notification.ToolWindow.informativeForeground": "#92D923",
|
||||
"Notification.ToolWindow.warningBackground": "greyDot85",
|
||||
"Notification.ToolWindow.warningBorderColor": "yellowMac",
|
||||
"Notification.ToolWindow.warningForeground": "yellowMac",
|
||||
"Notification.background": "greyDot85",
|
||||
"Notification.errorBackground": "greyDot85",
|
||||
"Notification.errorBorderColor": "#ed005c",
|
||||
"Notification.errorForeground": "#F65F87",
|
||||
"Notification.ToolWindow.warningBackground": "greyDot95",
|
||||
"Notification.ToolWindow.warningBorderColor": "yellow",
|
||||
"Notification.ToolWindow.warningForeground": "yellow",
|
||||
"Notification.background": "greyDot95",
|
||||
"Notification.errorBackground": "greyDot95",
|
||||
"Notification.errorBorderColor": "red",
|
||||
"Notification.errorForeground": "#EE7762",
|
||||
"OptionPane": {
|
||||
"background": "greyDot80",
|
||||
"background": "editorPaneBg",
|
||||
"foreground": "greyDot20"
|
||||
},
|
||||
"Panel": {
|
||||
"background": "greyDot80",
|
||||
"foreground": "greyDot20"
|
||||
"background": "editorPaneBg",
|
||||
"foreground": "textColor"
|
||||
},
|
||||
"Panel.foreground": "greyDot20",
|
||||
"ParameterInfo.background": "greyDot85",
|
||||
"ParameterInfo.foreground": "greyDot25",
|
||||
"ParameterInfo.borderColor": "greyDot75",
|
||||
"ParameterInfo.currentOverloadBackground": "greyDot65",
|
||||
"ParameterInfo.currentParameterForeground": "yellowMac",
|
||||
"ParameterInfo.currentParameterForeground": "yellow",
|
||||
"ParameterInfo.foreground": "greyDot25",
|
||||
"ParameterInfo.infoForeground": "greyDot33",
|
||||
"ParameterInfo.lineSeparatorColor": "greyDot75",
|
||||
"PasswordField.background": "greyDot75",
|
||||
"Plugins.Button.installBackground": "greyDot80",
|
||||
"Plugins.Button.installBorderColor": "greyDot65",
|
||||
"Plugins.Button.installBorderColor": "greyDot60",
|
||||
"Plugins.Button.installFillBackground": "greyDot80",
|
||||
"Plugins.Button.installFillForeground": "greyDot25",
|
||||
"Plugins.Button.installForeground": "yellowMac",
|
||||
"Plugins.Button.installForeground": "yellow",
|
||||
"Plugins.SearchField.background": "greyDot75",
|
||||
"Plugins.SectionHeader.background": "greyDot75",
|
||||
"Plugins.Tab.hoverBackground": "navyDot85",
|
||||
"Plugins.Tab.selectedBackground": "greyDot85",
|
||||
"Plugins.background": "greyDot80",
|
||||
"Plugins.Tab.hoverBackground": "editorBg",
|
||||
"Plugins.Tab.selectedBackground": "editorPaneBg",
|
||||
"Plugins.background": "editorPaneBg",
|
||||
"Plugins.lightSelectionBackground": "#242220",
|
||||
"Plugins.disabledForeground": "greyDot50",
|
||||
"Plugins.lightSelectionBackground": "navyDot85",
|
||||
"Plugins.tagBackground": "greyDot85",
|
||||
"Plugins.tagBackground": "editorBg",
|
||||
"Plugins.tagForeground": "greyDot33",
|
||||
"Plugins.hoverBackground": "editorBg",
|
||||
"Popup.Advertiser.background": "greyDot85",
|
||||
"Popup.Advertiser.foreground": "greyDot50",
|
||||
"Popup.Header.activeBackground": "greyDot75",
|
||||
"Popup.Header.inactiveBackground": "greyDot85",
|
||||
"Popup.paintBorder": true,
|
||||
"Popup.paintBorder": false,
|
||||
"PopupMenu.background": "greyDot80",
|
||||
"PopupMenuSeparator.stripeWidth": 1,
|
||||
"ProgressBar.failedColor": "#ed005c",
|
||||
"ProgressBar.failedColor": "red",
|
||||
"ProgressBar.failedEndColor": "greyDot75",
|
||||
"ProgressBar.indeterminateStartColor": "yellowMac",
|
||||
"ProgressBar.indeterminateEndColor": "#FD971F",
|
||||
"ProgressBar.passedColor": "#92D923",
|
||||
"ProgressBar.indeterminateStartColor": "yellow",
|
||||
"ProgressBar.passedColor": "green",
|
||||
"ProgressBar.passedEndColor": "greyDot75",
|
||||
"ProgressBar.progressColor": "yellowMac",
|
||||
"ProgressBar.progressColor": "yellow",
|
||||
"ProgressBar.trackColor": "greyDot75",
|
||||
"RadioButton.background": "greyDot80",
|
||||
"RadioButton.disabledText": "greyDot70",
|
||||
"RadioButtonMenuItem.disabledBackground": "greyDot80",
|
||||
"ScrollPane.background": "greyDot80",
|
||||
"SearchEverywhere.Advertiser.foreground": "greyDot50",
|
||||
"SearchEverywhere.List.separatorForeground": "greyDot50",
|
||||
"SearchEverywhere.SearchField.infoForeground": "greyDot33",
|
||||
"SearchEverywhere.SearchField.background": "greyDot75",
|
||||
"SearchEverywhere.Header.background": "greyDot80",
|
||||
"SearchEverywhere.Tab.selectedBackground": "greyDot85",
|
||||
"SearchEverywhere.Tab.selectedForeground": "lightBlue",
|
||||
"SearchMatch.endBackground": "yellowMac",
|
||||
"SearchMatch.startBackground": "yellowMac",
|
||||
"SearchEverywhere.List.separatorForeground": "greyDot50",
|
||||
"SearchEverywhere.SearchField.background": "greyDot75",
|
||||
"SearchEverywhere.SearchField.infoForeground": "greyDot33",
|
||||
"SearchEverywhere.Tab.selectedBackground": "greyDot95",
|
||||
"SearchEverywhere.Tab.selectedForeground": "yellow",
|
||||
"SearchMatch.endBackground": "yellow",
|
||||
"SearchMatch.startBackground": "yellow",
|
||||
"SidePanel.background": "greyDot85",
|
||||
"SpeedSearch.errorForeground": "#F65F87",
|
||||
"SpeedSearch.foreground": "yellowMac",
|
||||
"SplitPane.highlight": "yellowMac",
|
||||
"PopupMenu.translucentBackground": "greyDot50",
|
||||
"TabbedPane.disabledUnderlineColor": "greyDot65",
|
||||
"TabbedPane.focusColor": "greyDot65",
|
||||
"SpeedSearch.errorForeground": "red",
|
||||
"SpeedSearch.foreground": "yellow",
|
||||
"SplitPane.highlight": "yellow",
|
||||
"TabbedPane.disabledUnderlineColor": "editorPaneBg",
|
||||
"TabbedPane.focus": "greyDot75",
|
||||
"TabbedPane.focusColor": "greyDot33",
|
||||
"TabbedPane.tabSelectionHeight": 1,
|
||||
"TabbedPane.underlineColor": "yellowMac",
|
||||
"TabbedPane.underlineColor": "yellow",
|
||||
"Table.dropLineColor": "greyDot75",
|
||||
"Table.dropLineShortColor": "greyDot70",
|
||||
"Table.focusCellBackground": "greyDot85",
|
||||
"Table.focusCellForeground": "yellowMac",
|
||||
"Table.sortIconColor": "yellowMac",
|
||||
"Table.focusCellForeground": "yellow",
|
||||
"Table.sortIconColor": "yellow",
|
||||
"Table.stripeColor": "greyDot75",
|
||||
"TableHeader.background": "greyDot85",
|
||||
"TableHeader.bottomSeparatorColor": "greyDot65",
|
||||
"TextArea.background": "greyDot75",
|
||||
"TextArea.caretForeground": "yellowMac",
|
||||
"TextArea.caretForeground": "yellow",
|
||||
"TextArea.inactiveBackground": "greyDot80",
|
||||
"TextArea.selectionBackground": "greyDot95",
|
||||
"TextField.background": "greyDot75",
|
||||
"TextField.foreground": "greyDot25",
|
||||
"TextField.caretForeground": "yellowMac",
|
||||
"TextField.highlight": "greyDot15",
|
||||
"TextField.caretForeground": "yellow",
|
||||
"TextField.foreground": "greyDot33",
|
||||
"TextField.highlight": "yellow",
|
||||
"TextField.inactiveForeground": "greyDot33",
|
||||
"TextPane.inactiveBackground": "greyDot80",
|
||||
"TextPane.inactiveForeground": "greyDot50",
|
||||
"TitlePane.background": "greyDot85",
|
||||
"ToggleButton.buttonColor": "greyDot65",
|
||||
"ToggleButton.offBackground": "greyDot75",
|
||||
"ToggleButton.offForeground": "greyDot25",
|
||||
"ToggleButton.onBackground": "yellowMac",
|
||||
"ToggleButton.onBackground": "yellow",
|
||||
"ToggleButton.onForeground": "greyDot80",
|
||||
"ToolBar.borderHandleColor": "greyDot65",
|
||||
"ToolTip.Actions.background": "greyDot80",
|
||||
"ToolTip.Actions.infoForeground": "greyDot50",
|
||||
"ToolTip.background": "greyDot75",
|
||||
"ToolTip.background": "greyDot80",
|
||||
"ToolTip.borderColor": "border",
|
||||
"ToolTip.infoForeground": "greyDot50",
|
||||
"ToolWindow.Button.hoverBackground": "greyDot65",
|
||||
"ToolWindow.Button.selectedBackground": "greyDot85",
|
||||
"ToolWindow.Button.selectedForeground": "lightBlue",
|
||||
"ToolWindow.Button.hoverBackground": "greyDot95",
|
||||
"ToolWindow.Button.selectedBackground": "greyDot95",
|
||||
"ToolWindow.Button.selectedForeground": "yellow",
|
||||
"ToolWindow.Header.background": "greyDot85",
|
||||
"ToolWindow.Header.inactiveBackground": "greyDot80",
|
||||
"ToolWindow.HeaderTab.hoverBackground": "greyDot65",
|
||||
"ToolWindow.HeaderTab.hoverInactiveBackground": "greyDot85",
|
||||
"ToolWindow.HeaderTab.inactiveUnderlineColor": "greyDot75",
|
||||
"ToolWindow.HeaderTab.underlineColor": "yellowMac",
|
||||
"ToolWindow.Header.inactiveBackground": "editorPaneBg",
|
||||
"ToolWindow.HeaderTab.hoverBackground": "consoleBackground",
|
||||
"ToolWindow.HeaderTab.hoverInactiveBackground": "editorBg",
|
||||
"ToolWindow.HeaderTab.underlineColor": "yellow",
|
||||
"ToolWindow.HeaderTab.underlineHeight": 1,
|
||||
"ToolWindow.HeaderTab.underlinedTabBackground": "greyDot90",
|
||||
"ToolWindow.HeaderTab.underlinedTabInactiveBackground": "greyDot75",
|
||||
"Tooltip.separatorColor": "border",
|
||||
"Tree.background": "greyDot85",
|
||||
"Tree.foreground": "greyDot15",
|
||||
"Tree.modifiedItemForeground": "yellowMac",
|
||||
"ValidationTooltip.errorBackground": "greyDot85",
|
||||
"ValidationTooltip.errorBorderColor": "#ed005c",
|
||||
"ValidationTooltip.warningBackground": "greyDot85",
|
||||
"ValidationTooltip.warningBorderColor": "yellowMac",
|
||||
"VersionControl.FileHistory.Commit.selectedBranchBackground": "greyDot70",
|
||||
"Tree.foreground": "textColor",
|
||||
"Tree.hoverBackground": "greyDot95",
|
||||
"Tree.modifiedItemForeground": "yellow",
|
||||
"Tree.selectionBackground": "greyDot95",
|
||||
"Tree.selectionInactiveBackground": "greyDot95",
|
||||
"ValidationTooltip.errorBackground": "greyDot95",
|
||||
"ValidationTooltip.errorBorderColor": "red",
|
||||
"ValidationTooltip.warningBackground": "greyDot95",
|
||||
"ValidationTooltip.warningBorderColor": "yellow",
|
||||
"VersionControl.FileHistory.Commit.selectedBranchBackground": "greyDot95",
|
||||
"VersionControl.Log.Commit.currentBranchBackground": "greyDot85",
|
||||
"VersionControl.Log.Commit.hoveredBackground": "greyDot95",
|
||||
"VersionControl.Log.Commit.unmatchedForeground": "greyDot25",
|
||||
"WelcomeScreen.Projects.selectionBackground": "navyDot85",
|
||||
"WelcomeScreen.Projects.selectionInactiveBackground": "navyDot90",
|
||||
"WelcomeScreen.separatorColor": "greyDot65",
|
||||
"Window.border": "1,1,1,1,4d4d4d"
|
||||
"WelcomeScreen.Details.background": "greyDot80",
|
||||
"WelcomeScreen.Projects.background": "greyDot85",
|
||||
"WelcomeScreen.Projects.selectionBackground": "greyDot95",
|
||||
"WelcomeScreen.SidePanel.background": "greyDot80",
|
||||
"WelcomeScreen.background": "greyDot80",
|
||||
"WelcomeScreen.borderColor": "border",
|
||||
"WelcomeScreen.separatorColor": "border",
|
||||
"Window.border": "0,0,0,0,4d4d4d"
|
||||
}
|
||||
}
|
||||
|
||||