Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.
-
Upload
edgar-young -
Category
Documents
-
view
215 -
download
1
Transcript of Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.
![Page 1: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/1.jpg)
Swing EffectsKirill Grouchnikov, Amdocs
Desktop Matters ConferenceSan Jose, March 8-9 2007
![Page 2: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/2.jpg)
What is this about?
• Show two sample effects on buttons• Show how this can be achieved
with UI delegates• Discuss alternative
implementations
![Page 3: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/3.jpg)
Demo
![Page 4: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/4.jpg)
Possible ways to do this
• Custom component – paintComponent• Custom repaint manager• Custom glass pane• Custom UI delegates
![Page 5: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/5.jpg)
Possible ways to do this
• Custom component – paintComponent• Custom repaint manager• Custom glass pane• Custom UI delegates (*)
* - next slides describe the UI delegates approach
![Page 6: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/6.jpg)
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).
![Page 7: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/7.jpg)
How is the button painted?
update()
paintBorder() [*]
paintComponent()
paint()
paintIcon()layout text/iconpaintText()paintFocus()
paintChildren() [*]
paint()
JComponent ButtonUI
* - this is why you should override paintComponent() and not paint() for custom painting logic.
![Page 8: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/8.jpg)
Icon ghosting - schematics
![Page 9: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/9.jpg)
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.
![Page 10: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/10.jpg)
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.
![Page 11: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/11.jpg)
ButtonUI code (part I)protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) {
Graphics2D graphics = (Graphics2D) g.create();FadeTracker fadeTracker = 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.0float opFactor = -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 iconGet 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 iconCall super implementation to paint the icon itself
![Page 12: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/12.jpg)
ButtonUI code (part II)double iFactor = 1.0 + fade10 / 10.0;double iWidth = icon.getIconWidth() * iFactor;double iHeight = icon.getIconHeight() * iFactor;BufferedImage iImage = SubstanceCoreUtilities.getBlankImage(
(int) iWidth, (int) iHeight);Graphics2D iGraphics = (Graphics2D) iImage.createGraphics();iGraphics.scale(iFactor, iFactor);icon.paintIcon(b, iGraphics, 0, 0);iGraphics.dispose();int dx = (int) ((iWidth - icon.getIconWidth()) / 2);int dy = (int) ((iHeight - icon.getIconHeight()) / 2);graphics.drawImage(iImage, iconRect.x - dx, iconRect.y - dy,
null); Compute the scale factor and scaled dimensionsCreate a transparent imageScale its graphicsPaint the icon on the scaled graphics (creates the scaled icon)
Paint the scaled icon centered around the original icon
![Page 13: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/13.jpg)
Eye candyIcon ghosting over multiple
componentsPress ghosting over multiple
components
Multiple icon and press ghostings
![Page 14: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/14.jpg)
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
![Page 15: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/15.jpg)
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)
![Page 16: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/16.jpg)
Demo
![Page 17: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/17.jpg)
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
![Page 19: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/19.jpg)
Icon ghosting animation
![Page 20: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/20.jpg)
Container UI code (part I)@Overridepublic void update(Graphics g, JComponent c) { // Paint regular container stuff. In most cases -// background (fill, gradient, watermark)…// Paint ghost images of the animated overlapping// componentsGhostPaintingUtils.paintGhostImages(c, g);
}
![Page 21: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/21.jpg)
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 contextCompute screen bounds of the containerCheck if the icon ghosting animations are allowedGet all components under icon ghosting animationsFor each such component, do code on next slide
![Page 22: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/22.jpg)
Container UI code (part III)Rectangle compRect = comp.getBounds();compRect.setLocation(comp.getLocationOnScreen());
int dx = compRect.x - panelRect.x;int dy = 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 screen bounds of animated component
Compute offsets between screen boundsThe icon ghosting can take an area twice as large as the component screen boundsCheck if container screen bounds and extended screen bounds of the animated component intersect
![Page 23: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/23.jpg)
Container UI code (part IV)float fade10 = FadeTracker.getInstance().getFade10(comp,
null, FadeKind.GHOSTING_ICON_ROLLOVER);// 0.0 --> 0.5, 10.0 --> 0.0float opFactor = 0.5f * (1.0f - fade10 / 10.0f);graphics.setComposite(TransitionLayout.getAlphaComposite(mainComponent,
opFactor));Icon icon = null;Rectangle iconRect = null;if (comp instanceof AbstractButton) {
AbstractButton button = (AbstractButton) comp;icon = SubstanceCoreUtilities.getIcon(button, false);iconRect = (Rectangle)button.getClientProperty(SubstanceButtonUI.ICON_RECT);
}
if ((icon != null) && (iconRect != null)) {// see next slide
}Get the current animation positionCompute the ghost image translucency (fades from 50% to 0% opacity)Set the composite for painting the ghost iconGet the icon and the icon rectangle
![Page 24: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/24.jpg)
Container UI code (part V)double iFactor = 1.0 + fade10 / 10.0;double iWidth = icon.getIconWidth() * iFactor;double iHeight = icon.getIconHeight() * iFactor;BufferedImage iImage =
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 dimensionsCreate a transparent imageScale its graphicsPaint 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)
![Page 25: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/25.jpg)
Press ghosting animation
![Page 26: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/26.jpg)
Button press ghosting
![Page 27: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/27.jpg)
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.
![Page 28: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/28.jpg)
Container UI code (partial)double iFactor = 1.0 + fade10 / 10.0;double iWidth = bounds.width * iFactor;double iHeight = bounds.height * iFactor;BufferedImage iImage = 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);
Compute the scale factor and scaled dimensionsCreate a transparent imageScale its graphicsPaint the component on the scaled graphics (creates the scaled component)Paint the scaled component centered around the original component (note the computation of component offsets)
![Page 29: Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007.](https://reader035.fdocuments.us/reader035/viewer/2022062516/56649e4e5503460f94b4446a/html5/thumbnails/29.jpg)
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