Swing effects
Download
1 / 29

Swing Effects - PowerPoint PPT Presentation


  • 98 Views
  • Uploaded on

Swing Effects. Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007. What is this about?. Show two sample effects on buttons Show how this can be achieved with UI delegates Discuss alternative implementations. Demo. Possible ways to do this.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Swing Effects' - kalliyan-pach


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
Swing effects

Swing Effects

Kirill Grouchnikov, Amdocs

Desktop Matters Conference

San Jose, March 8-9 2007


What is this about
What is this about?

Show two sample effects on buttons

Show how this can be achieved with UI delegates

Discuss alternative implementations



Possible ways to do this
Possible ways to do this

Custom component – paintComponent

Custom repaint manager

Custom glass pane

Custom UI delegates


Possible ways to do this1
Possible ways to do this

Custom component – paintComponent

Custom repaint manager

Custom glass pane

Custom UI delegates (*)

* - next slides describe the UI delegates approach


How does swing paint
How does Swing paint?

UI delegates – classes responsible for painting Swing components.

The panels are painted by the PanelUI delegate (unless a panel overrides the paintComponent method).

The buttons are painted by the ButtonUI delegate (unless a button overrides the paintComponent method).


How is the button painted
How is the button painted?

JComponent

ButtonUI

paint()

paintComponent()

update()

paint()

layout text/icon

paintIcon()

paintText()

paintFocus()

paintBorder() [*]

* - this is why you should override paintComponent() and not paint() for custom painting logic.

paintChildren() [*]



Icon ghosting details
Icon ghosting - details

We add the custom painting code in the following places:

ButtonUI.paintIcon – before calling super(), paint the same icon scaled up and translucent (and offset).

PanelUI.update – paint the part of the icon that animates outside the child (button) bounds.

In addition, a ChangeListener is registered on the button model, tracking changes to the rollover state.


What to keep in mind
What to keep in mind?

The icon is not an Image. Call paintIcon after the Graphics has been scaled and a composite has been applied to it.

The ghost image must be centered around the original icon.

The ghost effect may “spill” from the immediate parent and overlay sibling components.


Buttonui code part i
ButtonUI code (part I)

protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) {

Graphics2D graphics = (Graphics2D) g.create();

FadeTrackerfadeTracker = FadeTracker.getInstance();

AbstractButton b = (AbstractButton) c;

if ((ButtonBackgroundDelegate.getKind(b) == ButtonTitleKind.NONE)

&& fadeTracker.isTracked(c, null,

FadeKind.GHOSTING_ICON_ROLLOVER, true)) {

float fade10 = fadeTracker.getFade10(c,

FadeKind.GHOSTING_ICON_ROLLOVER);

// 0.0 --> 0.5

// 10.0 --> 0.0

floatopFactor = -0.5f * fade10 / 10.0f + 0.5f;

graphics.setComposite(TransitionLayout.getAlphaComposite(c,

opFactor));

Icon icon = SubstanceCoreUtilities.getIcon(b);

if (icon != null) {

 see the next slide

}

}

graphics.setComposite(TransitionLayout.getAlphaComposite(c));

super.paintIcon(graphics, c, iconRect);

graphics.dispose();

}

Check if the button has ghost fade animation on the icon

Get the current animation position (number between 0.0 and 10.0)

Compute the ghost image translucency (fades from 50% to 0% opacity)

Set the composite for painting the ghost icon

Call super implementation to paint the icon itself


Buttonui code part ii
ButtonUI code (part II)

double iFactor = 1.0 + fade10 / 10.0;

double iWidth = icon.getIconWidth() * iFactor;

double iHeight = icon.getIconHeight() * iFactor;

BufferedImageiImage = SubstanceCoreUtilities.getBlankImage(

(int) iWidth, (int) iHeight);

Graphics2D iGraphics = (Graphics2D) iImage.createGraphics();

iGraphics.scale(iFactor, iFactor);

icon.paintIcon(b, iGraphics, 0, 0);

iGraphics.dispose();

intdx = (int) ((iWidth - icon.getIconWidth()) / 2);

intdy = (int) ((iHeight - icon.getIconHeight()) / 2);

graphics.drawImage(iImage, iconRect.x - dx, iconRect.y - dy,

null);

Compute the scale factor and scaled dimensions

Create a transparent image

Scale its graphics

Paint the icon on the scaled graphics (creates the scaled icon)

Paint the scaled icon centered around the original icon


Eye candy
Eye candy

Icon ghosting over multiple components

Press ghosting over multiple components

Multiple icon and press ghostings


Ui delegates pros cons
UI delegates – pros & cons

(+) Minimal changes in the application code.

(+) No need for custom painting code

(+/-) Available only under the specific LAF

Can use bytecode injection to change existing third-party LAFs (possible but slightly complicated – stay tuned for more in the future)

(-) Handling “spilling” is in container delegates

(-) Custom paintComponent implementations


Other approaches
Other approaches

How to handle painting order (background, ghost icon, icon+text)?

Custom components

(+/-) Work under all LAFs (???)

(-) Can handle only painting in the component bounds

Custom repaint manager

(+/-) Work under all LAFs (???)

(-) More complicated to write and test

(-) Interfere with existing repaint manager (e.g. from SwingX)

Custom glass pane

(+/-) Work under all LAFs (???)

(+/-) Interfere with existing app glass pane (JXLayer approach)



Additional information
Additional information

Kirill’s blog

http://weblogs.java.net/blog/kirillcool

Alex’s blog

http://weblogs.java.net/blog/alexfromsun

Substance LAF project

https://substance.dev.java.net

Laf-Widget project

https://laf-widget.dev.java.net




Container ui code part i
Container UI code (part I)

@Override

public void update(Graphics g, JComponent c) {

// Paint regular container stuff. In most cases -

// background (fill, gradient, watermark)

// Paint ghost images of the animated overlapping

// components

GhostPaintingUtils.paintGhostImages(c, g);

}


Container ui code part ii
Container UI code (part II)

public static void paintGhostImages(Component mainComponent, Graphics g) {

Graphics2D graphics = (Graphics2D) g.create();

Rectangle panelRect = mainComponent.getBounds();

panelRect.setLocation(mainComponent.getLocationOnScreen());

if (FadeConfigurationManager.getInstance().fadeAllowed(

FadeKind.GHOSTING_ICON_ROLLOVER, mainComponent)) {

Set<Component> animComps = FadeTracker.getInstance()

.getAllComponentsByFadeKind(

FadeKind.GHOSTING_ICON_ROLLOVER);

for (Component comp : animComps) {

// see next slide

}

}

graphics.dispose();

}

Work on disposable graphics context

Compute screen bounds of the container

Check if the icon ghosting animations are allowed

Get all components under icon ghosting animations

For each such component, do code on next slide


Container ui code part iii
Container UI code (part III)

Rectangle compRect = comp.getBounds();

compRect.setLocation(comp.getLocationOnScreen());

intdx = compRect.x - panelRect.x;

intdy = compRect.y - panelRect.y;

compRect.x -= compRect.width / 2;

compRect.y -= compRect.height / 2;

compRect.width *= 2;

compRect.height *= 2;

if (panelRect.intersects(compRect)) {

// see next slide

}

Compute offsets between screen bounds

The icon ghosting can take an area twice as large as the component screen bounds

Check if container screen bounds and extended screen bounds of the animated component intersect

Compute screen bounds of animated component


Container ui code part iv
Container UI code (part IV)

float fade10 = FadeTracker.getInstance().getFade10(comp,

null, FadeKind.GHOSTING_ICON_ROLLOVER);

// 0.0 --> 0.5, 10.0 --> 0.0

float opFactor = 0.5f * (1.0f - fade10 / 10.0f);

graphics.setComposite(TransitionLayout.getAlphaComposite(mainComponent, opFactor));

Icon icon = null;

Rectangle iconRect = null;

if (comp instanceofAbstractButton) {

AbstractButton button = (AbstractButton) comp;

icon = SubstanceCoreUtilities.getIcon(button, false);

iconRect = (Rectangle)button.getClientProperty(SubstanceButtonUI.ICON_RECT);

}

if ((icon != null) && (iconRect != null)) {

// see next slide

}

Compute the ghost image translucency (fades from 50% to 0% opacity)

Get the current animation position

Set the composite for painting the ghost icon

Get the icon and the icon rectangle


Container ui code part v
Container UI code (part V)

double iFactor = 1.0 + fade10 / 10.0;

double iWidth = icon.getIconWidth() * iFactor;

double iHeight = icon.getIconHeight() * iFactor;

BufferedImageiImage = SubstanceCoreUtilities.getBlankImage((int) iWidth, (int) iHeight);

Graphics2D iGraphics = (Graphics2D) iImage.createGraphics();

iGraphics.scale(iFactor, iFactor);

icon.paintIcon(comp, iGraphics, 0, 0);

iGraphics.dispose();

dx -= (int) ((iWidth - icon.getIconWidth()) / 2);

dy -= (int) ((iHeight - icon.getIconHeight()) / 2);

graphics.drawImage(iImage, dx + iconRect.x, dy + iconRect.y, null);

Compute the scale factor and scaled dimensions

Create a transparent image

Scale its graphics

Paint the icon on the scaled graphics (creates the scaled icon)

Paint the scaled icon centered around the original icon (note the computation of icon offsets)




What to keep in mind1
What to keep in mind?

The ghost image must be centered around the button image.

The ghost effect may “spill” from the immediate parent and overlay sibling components.


Container ui code partial
Container UI code (partial)

doubleiFactor = 1.0 + fade10 / 10.0;

doubleiWidth = bounds.width * iFactor;

doubleiHeight = bounds.height * iFactor;

BufferedImageiImage = SubstanceCoreUtilities.getBlankImage(

(int) iWidth, (int) iHeight);

Graphics2D iGraphics = (Graphics2D)iImage.createGraphics();

iGraphics.scale(iFactor, iFactor);

comp.paint(iGraphics);

iGraphics.dispose();

dx -= (int) ((iWidth - bounds.width) / 2);

dy -= (int) ((iHeight - bounds.height) / 2);

graphics.drawImage(iImage, bounds.x - dx, bounds.y - dy, null);

Paint the scaled component centered around the original component (note the computation of component offsets)

Compute the scale factor and scaled dimensions

Create a transparent image

Scale its graphics

Paint the component on the scaled graphics (creates the scaled component)


Some corner cases
Some corner cases

Not paint too much (trigger repaint only of the affected area)

Handle change in showing / visibility during the animation

Account for large button / icons (start from lower alpha)

Cache animating child image for reuse during painting in the same animation cycle on different containers


ad