SwingX: JXTaskPaneContainer and JXTaskPane support (#8)

This commit is contained in:
Karl Tauber
2019-10-18 09:37:35 +02:00
parent 7c77b857f6
commit 212ff012d6
9 changed files with 590 additions and 11 deletions

View File

@@ -157,7 +157,7 @@ public class FlatArrowButton
g.translate( -x, -y );
}
public static Shape createArrowShape( int direction, boolean chevron, int w, int h ) {
public static Shape createArrowShape( int direction, boolean chevron, float w, float h ) {
switch( direction ) {
case NORTH: return FlatUIUtils.createPath( !chevron, 0,h, (w / 2f),0, w,h );
case SOUTH: return FlatUIUtils.createPath( !chevron, 0,0, (w / 2f),h, w,0 );

View File

@@ -165,21 +165,52 @@ public class FlatUIUtils
}
private static Shape createOutlinePath( float x, float y, float width, float height, float arc ) {
if( arc <= 0 )
return createRoundRectanglePath( x, y, width, height, arc, arc, arc, arc );
}
/**
* Creates a not-filled rounded rectangle shape and allows specifying the line width and the radius or each corner.
*/
public static Path2D createRoundRectangle( float x, float y, float width, float height,
float lineWidth, float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
{
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( createRoundRectanglePath( x, y, width, height, arcTopLeft, arcTopRight, arcBottomLeft, arcBottomRight ), false );
path.append( createRoundRectanglePath( x + lineWidth, y + lineWidth, width - (lineWidth * 2), height - (lineWidth * 2),
arcTopLeft - lineWidth, arcTopRight - lineWidth, arcBottomLeft - lineWidth, arcBottomRight - lineWidth ), false );
return path;
}
/**
* Creates a filled rounded rectangle shape and allows specifying the radius or each corner.
*/
public static Shape createRoundRectanglePath( float x, float y, float width, float height,
float arcTopLeft, float arcTopRight, float arcBottomLeft, float arcBottomRight )
{
if( arcTopLeft <= 0 && arcTopRight <= 0 && arcBottomLeft <= 0 && arcBottomRight <= 0 )
return new Rectangle2D.Float( x, y, width, height );
if( arcTopLeft < 0 )
arcTopLeft = 0;
if( arcTopRight < 0 )
arcTopRight = 0;
if( arcBottomLeft < 0 )
arcBottomLeft = 0;
if( arcBottomRight < 0 )
arcBottomRight = 0;
float x2 = x + width;
float y2 = y + height;
Path2D rect = new Path2D.Float();
rect.moveTo( x2 - arc, y );
rect.quadTo( x2, y, x2, y + arc );
rect.lineTo( x2, y2 - arc );
rect.quadTo( x2, y2, x2 - arc, y2 );
rect.lineTo( x + arc, y2 );
rect.quadTo( x, y2, x, y2 - arc );
rect.lineTo( x, y + arc );
rect.quadTo( x, y, x + arc, y );
rect.moveTo( x2 - arcTopRight, y );
rect.quadTo( x2, y, x2, y + arcTopRight );
rect.lineTo( x2, y2 - arcBottomRight );
rect.quadTo( x2, y2, x2 - arcBottomRight, y2 );
rect.lineTo( x + arcBottomLeft, y2 );
rect.quadTo( x, y2, x, y2 - arcBottomLeft );
rect.lineTo( x, y + arcTopLeft );
rect.quadTo( x, y, x + arcTopLeft, y );
rect.closePath();
return rect;

View File

@@ -0,0 +1,274 @@
/*
* Copyright 2019 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
*
* http://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.swingx.ui;
import static com.formdev.flatlaf.util.UIScale.scale;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Shape;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
import org.jdesktop.swingx.JXTaskPane;
import org.jdesktop.swingx.plaf.basic.BasicTaskPaneUI;
import com.formdev.flatlaf.ui.FlatArrowButton;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.util.UIScale;
/**
* Provides the Flat LaF UI delegate for {@link org.jdesktop.swingx.JXTaskPane}.
*
* @author Karl Tauber
*/
public class FlatTaskPaneUI
extends BasicTaskPaneUI
{
private Color background;
public static ComponentUI createUI( JComponent c ) {
return new FlatTaskPaneUI();
}
@Override
protected void installDefaults() {
if( group.getContentPane() instanceof JComponent ) {
// remove default SwingX content border, which may be still set when switching LaF
JComponent content = (JComponent) group.getContentPane();
Border contentBorder = content.getBorder();
if( contentBorder instanceof CompoundBorder &&
((CompoundBorder)contentBorder).getOutsideBorder() instanceof BasicTaskPaneUI.ContentPaneBorder &&
((CompoundBorder)contentBorder).getInsideBorder() instanceof EmptyBorder )
{
content.setBorder( null );
}
// set non-UIResource color to background to avoid that it is lost when switching LaF
background = UIManager.getColor( "TaskPane.background" );
Color bg = content.getBackground();
if( bg == null || bg instanceof UIResource ) {
content.setBackground( new Color( background.getRGB(), true ) );
}
}
roundHeight = FlatUIUtils.getUIInt( "TaskPane.roundHeight", UIManager.getInt( "Component.arc" ) );
super.installDefaults();
}
@Override
public void uninstallUI( JComponent c ) {
if( group.getContentPane() instanceof JComponent ) {
// uninstall our content border, because it does not implement UIResource,
// to alloy other LaF to install its own border
JComponent content = (JComponent) group.getContentPane();
if( content.getBorder() instanceof FlatContentPaneBorder )
content.setBorder( null );
// replace our non-UIResouce background with UIResouce background
// to allow next LaF to overwrite it
if( background.equals( content.getBackground() ) )
content.setBackground( background );
background = null;
}
super.uninstallUI( c );
}
@Override
protected int getTitleHeight( Component c ) {
return Math.max( super.getTitleHeight( c ), UIScale.scale( titleHeight ) );
}
@Override
protected int getRoundHeight() {
return UIScale.scale( roundHeight );
}
@Override
protected Border createPaneBorder() {
return new FlatPaneBorder();
}
@Override
protected Border createContentPaneBorder() {
return new FlatContentPaneBorder( UIManager.getColor( "TaskPane.borderColor" ),
UIManager.getInsets( "TaskPane.contentInsets" ) );
}
//---- class FlatContentPaneBorder ----------------------------------------
/**
* The content pane border.
*/
private static class FlatContentPaneBorder
extends EmptyBorder
{
Color color;
FlatContentPaneBorder( Color color, Insets insets ) {
super( insets );
this.color = color;
// add space for the line border
left++;
right++;
bottom++;
}
@Override
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
if( color == null )
return;
FlatUIUtils.setRenderingHints( (Graphics2D) g );
g.setColor( color );
float lineWidth = UIScale.scale( 1f );
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( new Rectangle2D.Float( x, y, width, height ), false );
path.append( new Rectangle2D.Float( x + lineWidth, y, width - (lineWidth * 2), height - lineWidth ), false );
((Graphics2D)g).fill( path );
}
@Override
public Insets getBorderInsets() {
return new Insets( scale( top ), scale( left ), scale( bottom ), scale( right ) );
}
@Override
public Insets getBorderInsets( Component c, Insets insets ) {
insets.left = scale( left );
insets.top = scale( top );
insets.right = scale( right );
insets.bottom = scale( bottom );
return insets;
}
}
//---- class FlatPaneBorder -----------------------------------------------
private class FlatPaneBorder
extends PaneBorder
{
@Override
public void paintBorder( Component c, Graphics g, int x, int y, int width, int height ) {
FlatUIUtils.setRenderingHints( (Graphics2D) g );
super.paintBorder( c, g, x, y, width, height );
}
@Override
protected void paintTitleBackground( JXTaskPane group, Graphics g ) {
int width = group.getWidth();
int height = getTitleHeight( group ) ;
float arc = UIScale.scale( (float) roundHeight );
float lineWidth = UIScale.scale( 1f );
// paint background
g.setColor( group.isSpecial() ? specialTitleBackground : titleBackgroundGradientStart );
((Graphics2D)g).fill( FlatUIUtils.createRoundRectanglePath( lineWidth, lineWidth,
width - (lineWidth * 2), height - (lineWidth * 2), arc - lineWidth, arc - lineWidth, 0, 0 ) );
// paint border
if( borderColor != null ) {
g.setColor( borderColor );
((Graphics2D)g).fill( FlatUIUtils.createRoundRectangle( 0, 0, width, height, lineWidth, arc, arc, 0, 0 ) );
}
}
@Override
protected void paintExpandedControls( JXTaskPane group, Graphics g, int x, int y, int width, int height ) {
g.setColor( getPaintColor( group ) );
paintChevronControls( group, g, x, y, width, height );
}
@Override
protected void paintChevronControls( JXTaskPane group, Graphics g, int x, int y, int width, int height ) {
Graphics2D g2 = (Graphics2D) g;
// scale chevron size
float cw = scale( 6f );
float ch = scale( 3f );
// create arrow shape
int direction = group.isCollapsed() ? SwingConstants.SOUTH : SwingConstants.NORTH;
Shape arrowShape = FlatArrowButton.createArrowShape( direction, true, cw, ch );
// fix position of controls
x = group.getComponentOrientation().isLeftToRight() ? (group.getWidth() - width - y) : y;
// compute chevron position
int cx = (int) (x + width / 2 - cw / 2);
int cy = (int) (y + (height / 2 - ch));
float offset = ch + UIScale.scale( 1f );
// set stroke with scaled width
g2.setStroke( new BasicStroke( scale( 1f ) ) );
// paint
g2.translate( cx, cy );
g2.draw( arrowShape );
g2.translate( 0, offset );
g2.draw( arrowShape );
g2.translate( -cx, -(cy + offset) );
}
@Override
protected void paintTitle( JXTaskPane group, Graphics g, Color textColor,
int x, int y, int width, int height )
{
// scale title position
int titleX = UIScale.scale( 3 );
int titleWidth = group.getWidth() - getTitleHeight(group) - titleX;
if( !group.getComponentOrientation().isLeftToRight() ) {
// right-to-left
titleX = group.getWidth() - titleX - titleWidth;
}
super.paintTitle( group, g, textColor, titleX, y, titleWidth, height );
}
@Override
protected void paintFocus( Graphics g, Color paintColor, int x, int y, int width, int height ) {
// scale focus rectangle
int sx = UIScale.scale( x );
int sy = UIScale.scale( y );
int swidth = width - (sx - x) * 2;
int sheight = height - (sy - y) * 2;
super.paintFocus( g, paintColor, sx, sy, swidth, sheight );
}
@Override
protected boolean isMouseOverBorder() {
return true;
}
}
}

View File

@@ -19,3 +19,23 @@
Hyperlink.linkColor=589df6
Hyperlink.visitedColor=@@Hyperlink.linkColor
Hyperlink.disabledText=@disabledText
#---- TaskPaneContainer ----
TaskPaneContainer.background=3E434C
TaskPaneContainer.border=10,10,10,10
#---- TaskPane ----
TaskPane.background=@background
TaskPane.borderColor=@@Button.borderColor
TaskPane.contentInsets=10,10,10,10
TaskPane.titleBackgroundGradientStart=4c5052
TaskPane.titleForeground=@foreground
TaskPane.titleOver=888888
TaskPane.specialTitleBackground=afafaf
TaskPane.specialTitleForeground=222222
TaskPane.specialTitleOver=666666

View File

@@ -17,3 +17,4 @@
#---- UI delegates ----
HyperlinkUI=com.formdev.flatlaf.swingx.ui.FlatHyperlinkUI
swingx/TaskPaneUI=com.formdev.flatlaf.swingx.ui.FlatTaskPaneUI

View File

@@ -19,3 +19,23 @@
Hyperlink.linkColor=4a78c2
Hyperlink.visitedColor=@@Hyperlink.linkColor
Hyperlink.disabledText=@disabledText
#---- TaskPaneContainer ----
TaskPaneContainer.background=E6EBF0
TaskPaneContainer.border=10,10,10,10
#---- TaskPane ----
TaskPane.background=@background
TaskPane.borderColor=@@Button.borderColor
TaskPane.contentInsets=10,10,10,10
TaskPane.titleBackgroundGradientStart=dfdfdf
TaskPane.titleForeground=222222
TaskPane.titleOver=666666
TaskPane.specialTitleBackground=afafaf
TaskPane.specialTitleForeground=222222
TaskPane.specialTitleOver=666666

View File

@@ -16,6 +16,7 @@
package com.formdev.flatlaf.swingx;
import java.awt.*;
import javax.swing.*;
import net.miginfocom.swing.*;
import org.jdesktop.swingx.*;
@@ -41,6 +42,23 @@ public class FlatSwingXTest
JLabel hyperlinkLabel = new JLabel();
JXHyperlink xHyperlink1 = new JXHyperlink();
JXHyperlink xHyperlink2 = new JXHyperlink();
JPanel panel1 = new JPanel();
JLabel taskPaneContainerLabel = new JLabel();
JLabel taskPaneLabel = new JLabel();
JScrollPane scrollPane1 = new JScrollPane();
JXTaskPaneContainer xTaskPaneContainer1 = new JXTaskPaneContainer();
JXTaskPane xTaskPane3 = new JXTaskPane();
JXHyperlink xHyperlink3 = new JXHyperlink();
JXHyperlink xHyperlink4 = new JXHyperlink();
JXHyperlink xHyperlink5 = new JXHyperlink();
JXTaskPane xTaskPane4 = new JXTaskPane();
JXHyperlink xHyperlink6 = new JXHyperlink();
JXHyperlink xHyperlink7 = new JXHyperlink();
JXTaskPane xTaskPane5 = new JXTaskPane();
JXHyperlink xHyperlink8 = new JXHyperlink();
JXTaskPane xTaskPane6 = new JXTaskPane();
JXHyperlink xHyperlink9 = new JXHyperlink();
JXHyperlink xHyperlink10 = new JXHyperlink();
//======== this ========
setLayout(new MigLayout(
@@ -50,6 +68,7 @@ public class FlatSwingXTest
"[]" +
"[]",
// rows
"[]" +
"[]"));
//---- hyperlinkLabel ----
@@ -64,6 +83,99 @@ public class FlatSwingXTest
xHyperlink2.setText("disabled");
xHyperlink2.setEnabled(false);
add(xHyperlink2, "cell 2 0");
//======== panel1 ========
{
panel1.setLayout(new MigLayout(
"ltr,insets 0,hidemode 3",
// columns
"[left]",
// rows
"[]" +
"[]"));
//---- taskPaneContainerLabel ----
taskPaneContainerLabel.setText("JXTaskPaneContainer:");
panel1.add(taskPaneContainerLabel, "cell 0 0");
//---- taskPaneLabel ----
taskPaneLabel.setText("JXTaskPane:");
panel1.add(taskPaneLabel, "cell 0 1");
}
add(panel1, "cell 0 1,aligny top,growy 0");
//======== scrollPane1 ========
{
//======== xTaskPaneContainer1 ========
{
//======== xTaskPane3 ========
{
xTaskPane3.setTitle("Basic Tasks");
Container xTaskPane3ContentPane = xTaskPane3.getContentPane();
//---- xHyperlink3 ----
xHyperlink3.setText("New");
xTaskPane3ContentPane.add(xHyperlink3);
//---- xHyperlink4 ----
xHyperlink4.setText("Open");
xTaskPane3ContentPane.add(xHyperlink4);
//---- xHyperlink5 ----
xHyperlink5.setText("Save");
xTaskPane3ContentPane.add(xHyperlink5);
}
xTaskPaneContainer1.add(xTaskPane3);
//======== xTaskPane4 ========
{
xTaskPane4.setTitle("Other Tasks");
xTaskPane4.setIcon(UIManager.getIcon("Tree.closedIcon"));
Container xTaskPane4ContentPane = xTaskPane4.getContentPane();
//---- xHyperlink6 ----
xHyperlink6.setText("Duplicate");
xTaskPane4ContentPane.add(xHyperlink6);
//---- xHyperlink7 ----
xHyperlink7.setText("Delete");
xTaskPane4ContentPane.add(xHyperlink7);
}
xTaskPaneContainer1.add(xTaskPane4);
//======== xTaskPane5 ========
{
xTaskPane5.setTitle("Special Tasks");
xTaskPane5.setSpecial(true);
Container xTaskPane5ContentPane = xTaskPane5.getContentPane();
//---- xHyperlink8 ----
xHyperlink8.setText("Go to space");
xTaskPane5ContentPane.add(xHyperlink8);
}
xTaskPaneContainer1.add(xTaskPane5);
//======== xTaskPane6 ========
{
xTaskPane6.setTitle("Collapsed");
xTaskPane6.setCollapsed(true);
Container xTaskPane6ContentPane = xTaskPane6.getContentPane();
//---- xHyperlink9 ----
xHyperlink9.setText("text");
xTaskPane6ContentPane.add(xHyperlink9);
//---- xHyperlink10 ----
xHyperlink10.setText("text");
xTaskPane6ContentPane.add(xHyperlink10);
}
xTaskPaneContainer1.add(xTaskPane6);
}
scrollPane1.setViewportView(xTaskPaneContainer1);
}
add(scrollPane1, "cell 1 1,width 150,height 350");
// JFormDesigner - End of component initialization //GEN-END:initComponents
}

View File

@@ -9,7 +9,7 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$layoutConstraints": "hidemode 3,ltr"
"$columnConstraints": "[left][][]"
"$rowConstraints": "[]"
"$rowConstraints": "[][]"
} ) {
name: "this"
add( new FormComponent( "javax.swing.JLabel" ) {
@@ -31,6 +31,86 @@ new FormModel {
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 2 0"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
"$columnConstraints": "[left]"
"$rowConstraints": "[][]"
"$layoutConstraints": "ltr,insets 0,hidemode 3"
} ) {
name: "panel1"
add( new FormComponent( "javax.swing.JLabel" ) {
name: "taskPaneContainerLabel"
"text": "JXTaskPaneContainer:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 0"
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "taskPaneLabel"
"text": "JXTaskPane:"
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1"
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 0 1,aligny top,growy 0"
} )
add( new FormContainer( "javax.swing.JScrollPane", new FormLayoutManager( class javax.swing.JScrollPane ) ) {
name: "scrollPane1"
add( new FormContainer( "org.jdesktop.swingx.JXTaskPaneContainer", new FormLayoutManager( class com.jformdesigner.runtime.GenericIndexLayout ) ) {
name: "xTaskPaneContainer1"
add( new FormContainer( "org.jdesktop.swingx.JXTaskPane", new FormLayoutManager( class com.jformdesigner.runtime.GenericIndexLayout ) ) {
name: "xTaskPane3"
"title": "Basic Tasks"
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink3"
"text": "New"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink4"
"text": "Open"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink5"
"text": "Save"
} )
} )
add( new FormContainer( "org.jdesktop.swingx.JXTaskPane", new FormLayoutManager( class com.jformdesigner.runtime.GenericIndexLayout ) ) {
name: "xTaskPane4"
"title": "Other Tasks"
"icon": new com.jformdesigner.model.SwingIcon( 2, "Tree.closedIcon" )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink6"
"text": "Duplicate"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink7"
"text": "Delete"
} )
} )
add( new FormContainer( "org.jdesktop.swingx.JXTaskPane", new FormLayoutManager( class com.jformdesigner.runtime.GenericIndexLayout ) ) {
name: "xTaskPane5"
"title": "Special Tasks"
"special": true
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink8"
"text": "Go to space"
} )
} )
add( new FormContainer( "org.jdesktop.swingx.JXTaskPane", new FormLayoutManager( class com.jformdesigner.runtime.GenericIndexLayout ) ) {
name: "xTaskPane6"
"title": "Collapsed"
"collapsed": true
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink9"
"text": "text"
} )
add( new FormComponent( "org.jdesktop.swingx.JXHyperlink" ) {
name: "xHyperlink10"
"text": "text"
} )
} )
} )
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
"value": "cell 1 1,width 150,height 350"
} )
}, new FormLayoutConstraints( null ) {
"location": new java.awt.Point( 0, 0 )
"size": new java.awt.Dimension( 645, 600 )

View File

@@ -0,0 +1,41 @@
#
# Copyright 2019 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
#
# http://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.
#
#---- Hyperlink ----
Hyperlink.linkColor=ff0000
Hyperlink.visitedColor=0000ff
Hyperlink.disabledText=000088
#---- TaskPaneContainer ----
TaskPaneContainer.background=ff8888
TaskPaneContainer.border=10,10,10,10
#---- TaskPane ----
TaskPane.background=00ff00
TaskPane.borderColor=0000ff
TaskPane.contentInsets=10,10,10,10
TaskPane.titleBackgroundGradientStart=ffff00
TaskPane.titleForeground=ff00ff
TaskPane.titleOver=0000aa
TaskPane.specialTitleBackground=00ffff
TaskPane.specialTitleForeground=444444
TaskPane.specialTitleOver=dd0000