Advertisement
Guest User

Untitled

a guest
May 1st, 2018
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.71 KB | None | 0 0
  1. /*
  2. * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * This code is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 only, as
  7. * published by the Free Software Foundation. Oracle designates this
  8. * particular file as subject to the "Classpath" exception as provided
  9. * by Oracle in the LICENSE file that accompanied this code.
  10. *
  11. * This code is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14. * version 2 for more details (a copy is included in the LICENSE file that
  15. * accompanied this code).
  16. *
  17. * You should have received a copy of the GNU General Public License version
  18. * 2 along with this work; if not, write to the Free Software Foundation,
  19. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22. * or visit www.oracle.com if you need additional information or have any
  23. * questions.
  24. */
  25.  
  26. package com.sun.java.swing.plaf.windows;
  27.  
  28. import java.security.AccessController;
  29. import sun.security.action.GetBooleanAction;
  30.  
  31. import java.util.*;
  32. import java.beans.PropertyChangeListener;
  33. import java.beans.PropertyChangeEvent;
  34. import java.awt.*;
  35. import java.awt.event.*;
  36. import javax.swing.*;
  37.  
  38.  
  39.  
  40. import sun.swing.UIClientPropertyKey;
  41. import com.sun.java.swing.plaf.windows.TMSchema.State;
  42. import static com.sun.java.swing.plaf.windows.TMSchema.State.*;
  43. import com.sun.java.swing.plaf.windows.TMSchema.Part;
  44. import com.sun.java.swing.plaf.windows.TMSchema.Prop;
  45. import com.sun.java.swing.plaf.windows.XPStyle2.Skin;
  46.  
  47. import sun.awt.AppContext;
  48.  
  49. /**
  50. * A class to help mimic Vista theme animations. The only kind of
  51. * animation it handles for now is 'transition' animation (this seems
  52. * to be the only animation which Vista theme can do). This is when
  53. * one picture fadein over another one in some period of time.
  54. * According to
  55. * https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=86852&SiteID=4
  56. * The animations are all linear.
  57. *
  58. * This class has a number of responsibilities.
  59. * <ul>
  60. * <li> It trigger rapaint for the UI components involved in the animation
  61. * <li> It tracks the animation state for every UI component involved in the
  62. * animation and paints {@code Skin} in new {@code State} over the
  63. * {@code Skin} in last {@code State} using
  64. * {@code AlphaComposite.SrcOver.derive(alpha)} where {code alpha}
  65. * depends on the state of animation
  66. * </ul>
  67. *
  68. * @author Igor Kushnirskiy
  69. */
  70. class AnimationController2 implements ActionListener, PropertyChangeListener {
  71.  
  72. private final static boolean VISTA_ANIMATION_DISABLED =
  73. AccessController.doPrivileged(new GetBooleanAction("swing.disablevistaanimation"));
  74.  
  75.  
  76. private final static Object ANIMATION_CONTROLLER_KEY =
  77. new StringBuilder("ANIMATION_CONTROLLER_KEY");
  78.  
  79. private final Map<JComponent, Map<Part, AnimationState>> animationStateMap =
  80. new WeakHashMap<JComponent, Map<Part, AnimationState>>();
  81.  
  82. //this timer is used to cause repaint on animated components
  83. //30 repaints per second should give smooth animation affect
  84. private final javax.swing.Timer timer =
  85. new javax.swing.Timer(1000/30, this);
  86.  
  87. private static synchronized AnimationController2 getAnimationController() {
  88. AppContext appContext = AppContext.getAppContext();
  89. Object obj = appContext.get(ANIMATION_CONTROLLER_KEY);
  90. if (obj == null) {
  91. obj = new AnimationController2();
  92. appContext.put(ANIMATION_CONTROLLER_KEY, obj);
  93. }
  94. return (AnimationController2) obj;
  95. }
  96.  
  97. private AnimationController2() {
  98. timer.setRepeats(true);
  99. timer.setCoalesce(true);
  100. //we need to dispose the controller on l&f change
  101. UIManager.addPropertyChangeListener(this);
  102. }
  103.  
  104. private static void triggerAnimation(JComponent c,
  105. Part part, State newState) {
  106. if (c instanceof javax.swing.JTabbedPane
  107. || part == Part.TP_BUTTON) {
  108. //idk: we can not handle tabs animation because
  109. //the same (component,part) is used to handle all the tabs
  110. //and we can not track the states
  111. //Vista theme might have transition duration for toolbar buttons
  112. //but native application does not seem to animate them
  113. return;
  114. }
  115. AnimationController2 controller =
  116. AnimationController2.getAnimationController();
  117. State oldState = controller.getState(c, part);
  118. if (oldState != newState) {
  119. controller.putState(c, part, newState);
  120. if (newState == State.DEFAULTED) {
  121. // it seems for DEFAULTED button state Vista does animation from
  122. // HOT
  123. oldState = State.HOT;
  124. }
  125. if (oldState != null) {
  126. long duration;
  127. if (newState == State.DEFAULTED) {
  128. //Only button might have DEFAULTED state
  129. //idk: do not know how to get the value from Vista
  130. //one second seems plausible value
  131. duration = 1000;
  132. } else {
  133. XPStyle2 xp = XPStyle2.getXP();
  134. duration = (xp != null)
  135. ? xp.getThemeTransitionDuration(
  136. c, part,
  137. normalizeState(oldState),
  138. normalizeState(newState),
  139. Prop.TRANSITIONDURATIONS)
  140. : 1000;
  141. }
  142. controller.startAnimation(c, part, oldState, newState, duration);
  143. }
  144. }
  145. }
  146.  
  147. // for scrollbar up, down, left and right button pictures are
  148. // defined by states. It seems that theme has duration defined
  149. // only for up button states thus we doing this translation here.
  150. private static State normalizeState(State state) {
  151. State rv;
  152. switch (state) {
  153. case DOWNPRESSED:
  154. /* falls through */
  155. case LEFTPRESSED:
  156. /* falls through */
  157. case RIGHTPRESSED:
  158. rv = UPPRESSED;
  159. break;
  160.  
  161. case DOWNDISABLED:
  162. /* falls through */
  163. case LEFTDISABLED:
  164. /* falls through */
  165. case RIGHTDISABLED:
  166. rv = UPDISABLED;
  167. break;
  168.  
  169. case DOWNHOT:
  170. /* falls through */
  171. case LEFTHOT:
  172. /* falls through */
  173. case RIGHTHOT:
  174. rv = UPHOT;
  175. break;
  176.  
  177. case DOWNNORMAL:
  178. /* falls through */
  179. case LEFTNORMAL:
  180. /* falls through */
  181. case RIGHTNORMAL:
  182. rv = UPNORMAL;
  183. break;
  184.  
  185. default :
  186. rv = state;
  187. break;
  188. }
  189. return rv;
  190. }
  191.  
  192. private synchronized State getState(JComponent component, Part part) {
  193. State rv = null;
  194. Object tmpObject =
  195. component.getClientProperty(PartUIClientPropertyKey.getKey(part));
  196. if (tmpObject instanceof State) {
  197. rv = (State) tmpObject;
  198. }
  199. return rv;
  200. }
  201.  
  202. private synchronized void putState(JComponent component, Part part,
  203. State state) {
  204. component.putClientProperty(PartUIClientPropertyKey.getKey(part),
  205. state);
  206. }
  207.  
  208. private synchronized void startAnimation(JComponent component,
  209. Part part,
  210. State startState,
  211. State endState,
  212. long millis) {
  213. boolean isForwardAndReverse = false;
  214. if (endState == State.DEFAULTED) {
  215. isForwardAndReverse = true;
  216. }
  217. Map<Part, AnimationState> map = animationStateMap.get(component);
  218. if (millis <= 0) {
  219. if (map != null) {
  220. map.remove(part);
  221. if (map.size() == 0) {
  222. animationStateMap.remove(component);
  223. }
  224. }
  225. return;
  226. }
  227. if (map == null) {
  228. map = new EnumMap<Part, AnimationState>(Part.class);
  229. animationStateMap.put(component, map);
  230. }
  231. map.put(part,
  232. new AnimationState(startState, millis, isForwardAndReverse));
  233. if (! timer.isRunning()) {
  234. timer.start();
  235. }
  236. }
  237.  
  238. static void paintSkin(JComponent component, Skin skin,
  239. Graphics g, int dx, int dy, int dw, int dh, State state) {
  240. if (VISTA_ANIMATION_DISABLED) {
  241. skin.paintSkinRaw(g, dx, dy, dw, dh, state);
  242. return;
  243. }
  244. triggerAnimation(component, skin.part, state);
  245. AnimationController2 controller = getAnimationController();
  246. synchronized (controller) {
  247. AnimationState animationState = null;
  248. Map<Part, AnimationState> map =
  249. controller.animationStateMap.get(component);
  250. if (map != null) {
  251. animationState = map.get(skin.part);
  252. }
  253. if (animationState != null) {
  254. animationState.paintSkin(skin, g, dx, dy, dw, dh, state);
  255. } else {
  256. skin.paintSkinRaw(g, dx, dy, dw, dh, state);
  257. }
  258. }
  259. }
  260.  
  261. public synchronized void propertyChange(PropertyChangeEvent e) {
  262. if ("lookAndFeel" == e.getPropertyName()
  263. && ! (e.getNewValue() instanceof WindowsLookAndFeel) ) {
  264. dispose();
  265. }
  266. }
  267.  
  268. public synchronized void actionPerformed(ActionEvent e) {
  269. java.util.List<JComponent> componentsToRemove = null;
  270. java.util.List<Part> partsToRemove = null;
  271. for (JComponent component : animationStateMap.keySet()) {
  272. component.repaint();
  273. if (partsToRemove != null) {
  274. partsToRemove.clear();
  275. }
  276. Map<Part, AnimationState> map = animationStateMap.get(component);
  277. if (! component.isShowing()
  278. || map == null
  279. || map.size() == 0) {
  280. if (componentsToRemove == null) {
  281. componentsToRemove = new ArrayList<JComponent>();
  282. }
  283. componentsToRemove.add(component);
  284. continue;
  285. }
  286. for (Part part : map.keySet()) {
  287. if (map.get(part).isDone()) {
  288. if (partsToRemove == null) {
  289. partsToRemove = new ArrayList<Part>();
  290. }
  291. partsToRemove.add(part);
  292. }
  293. }
  294. if (partsToRemove != null) {
  295. if (partsToRemove.size() == map.size()) {
  296. //animation is done for the component
  297. if (componentsToRemove == null) {
  298. componentsToRemove = new ArrayList<JComponent>();
  299. }
  300. componentsToRemove.add(component);
  301. } else {
  302. for (Part part : partsToRemove) {
  303. map.remove(part);
  304. }
  305. }
  306. }
  307. }
  308. if (componentsToRemove != null) {
  309. for (JComponent component : componentsToRemove) {
  310. animationStateMap.remove(component);
  311. }
  312. }
  313. if (animationStateMap.size() == 0) {
  314. timer.stop();
  315. }
  316. }
  317.  
  318. private synchronized void dispose() {
  319. timer.stop();
  320. UIManager.removePropertyChangeListener(this);
  321. synchronized (AnimationController2.class) {
  322. AppContext.getAppContext()
  323. .put(ANIMATION_CONTROLLER_KEY, null);
  324. }
  325. }
  326.  
  327. private static class AnimationState {
  328. private final State startState;
  329.  
  330. //animation duration in nanoseconds
  331. private final long duration;
  332.  
  333. //animatin start time in nanoseconds
  334. private long startTime;
  335.  
  336. //direction the alpha value is changing
  337. //forward - from 0 to 1
  338. //!forward - from 1 to 0
  339. private boolean isForward = true;
  340.  
  341. //if isForwardAndReverse the animation continually goes
  342. //forward and reverse. alpha value is changing from 0 to 1 then
  343. //from 1 to 0 and so forth
  344. private boolean isForwardAndReverse;
  345.  
  346. private float progress;
  347.  
  348. AnimationState(final State startState,
  349. final long milliseconds,
  350. boolean isForwardAndReverse) {
  351. assert startState != null && milliseconds > 0;
  352. assert SwingUtilities.isEventDispatchThread();
  353.  
  354. this.startState = startState;
  355. this.duration = milliseconds * 1000000;
  356. this.startTime = System.nanoTime();
  357. this.isForwardAndReverse = isForwardAndReverse;
  358. progress = 0f;
  359. }
  360. private void updateProgress() {
  361. assert SwingUtilities.isEventDispatchThread();
  362.  
  363. if (isDone()) {
  364. return;
  365. }
  366. long currentTime = System.nanoTime();
  367.  
  368. progress = ((float) (currentTime - startTime))
  369. / duration;
  370. progress = Math.max(progress, 0); //in case time was reset
  371. if (progress >= 1) {
  372. progress = 1;
  373. if (isForwardAndReverse) {
  374. startTime = currentTime;
  375. progress = 0;
  376. isForward = ! isForward;
  377. }
  378. }
  379. }
  380. void paintSkin(Skin skin, Graphics _g,
  381. int dx, int dy, int dw, int dh, State state) {
  382. assert SwingUtilities.isEventDispatchThread();
  383.  
  384. updateProgress();
  385. if (! isDone()) {
  386. Graphics2D g = (Graphics2D) _g.create();
  387. skin.paintSkinRaw(g, dx, dy, dw, dh, startState);
  388. float alpha;
  389. if (isForward) {
  390. alpha = progress;
  391. } else {
  392. alpha = 1 - progress;
  393. }
  394. g.setComposite(AlphaComposite.SrcOver.derive(alpha));
  395. skin.paintSkinRaw(g, dx, dy, dw, dh, state);
  396. g.dispose();
  397. } else {
  398. skin.paintSkinRaw(_g, dx, dy, dw, dh, state);
  399. }
  400. }
  401. boolean isDone() {
  402. assert SwingUtilities.isEventDispatchThread();
  403.  
  404. return progress >= 1;
  405. }
  406. }
  407.  
  408. private static class PartUIClientPropertyKey
  409. implements UIClientPropertyKey {
  410.  
  411. private static final Map<Part, PartUIClientPropertyKey> map =
  412. new EnumMap<Part, PartUIClientPropertyKey>(Part.class);
  413.  
  414. static synchronized PartUIClientPropertyKey getKey(Part part) {
  415. PartUIClientPropertyKey rv = map.get(part);
  416. if (rv == null) {
  417. rv = new PartUIClientPropertyKey(part);
  418. map.put(part, rv);
  419. }
  420. return rv;
  421. }
  422.  
  423. private final Part part;
  424. private PartUIClientPropertyKey(Part part) {
  425. this.part = part;
  426. }
  427. public String toString() {
  428. return part.toString();
  429. }
  430. }
  431. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement