1. /*
  2. * @(#)BasicDesktopPaneUI.java 1.45 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.plaf.basic;
  8. import javax.swing.*;
  9. import javax.swing.plaf.*;
  10. import java.beans.*;
  11. import java.awt.event.*;
  12. import java.awt.Dimension;
  13. import java.awt.Insets;
  14. import java.awt.Graphics;
  15. import java.awt.KeyboardFocusManager;
  16. import java.awt.*;
  17. import java.util.Vector;
  18. /**
  19. * Basic L&F for a desktop.
  20. *
  21. * @version 1.45 01/23/03
  22. * @author Steve Wilson
  23. */
  24. public class BasicDesktopPaneUI extends DesktopPaneUI
  25. {
  26. private static Dimension minSize = new Dimension(0,0);
  27. private static Dimension maxSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
  28. protected JDesktopPane desktop;
  29. protected DesktopManager desktopManager;
  30. /**
  31. * As of Java 2 platform v1.3 this previously undocumented field is no
  32. * longer used.
  33. * Key bindings are now defined by the LookAndFeel, please refer to
  34. * the key bindings specification for further details.
  35. *
  36. * @deprecated As of 1.3.
  37. */
  38. protected KeyStroke minimizeKey;
  39. /**
  40. * As of Java 2 platform v1.3 this previously undocumented field is no
  41. * longer used.
  42. * Key bindings are now defined by the LookAndFeel, please refer to
  43. * the key bindings specification for further details.
  44. *
  45. * @deprecated As of 1.3.
  46. */
  47. protected KeyStroke maximizeKey;
  48. /**
  49. * As of Java 2 platform v1.3 this previously undocumented field is no
  50. * longer used.
  51. * Key bindings are now defined by the LookAndFeel, please refer to
  52. * the key bindings specification for further details.
  53. *
  54. * @deprecated As of 1.3.
  55. */
  56. protected KeyStroke closeKey;
  57. /**
  58. * As of Java 2 platform v1.3 this previously undocumented field is no
  59. * longer used.
  60. * Key bindings are now defined by the LookAndFeel, please refer to
  61. * the key bindings specification for further details.
  62. *
  63. * @deprecated As of 1.3.
  64. */
  65. protected KeyStroke navigateKey;
  66. /**
  67. * As of Java 2 platform v1.3 this previously undocumented field is no
  68. * longer used.
  69. * Key bindings are now defined by the LookAndFeel, please refer to
  70. * the key bindings specification for further details.
  71. *
  72. * @deprecated As of 1.3.
  73. */
  74. protected KeyStroke navigateKey2;
  75. public static ComponentUI createUI(JComponent c) {
  76. return new BasicDesktopPaneUI();
  77. }
  78. public BasicDesktopPaneUI() {
  79. }
  80. public void installUI(JComponent c) {
  81. desktop = (JDesktopPane)c;
  82. installDefaults();
  83. installDesktopManager();
  84. installKeyboardActions();
  85. }
  86. public void uninstallUI(JComponent c) {
  87. uninstallKeyboardActions();
  88. uninstallDesktopManager();
  89. uninstallDefaults();
  90. desktop = null;
  91. }
  92. protected void installDefaults() {
  93. if (desktop.getBackground() == null ||
  94. desktop.getBackground() instanceof UIResource) {
  95. desktop.setBackground(UIManager.getColor("Desktop.background"));
  96. }
  97. }
  98. protected void uninstallDefaults() { }
  99. protected void installDesktopManager() {
  100. if(desktop.getDesktopManager() == null) {
  101. desktopManager = new DefaultDesktopManager();
  102. desktop.setDesktopManager(desktopManager);
  103. }
  104. }
  105. protected void uninstallDesktopManager() {
  106. if(desktop.getDesktopManager() == desktopManager) {
  107. desktop.setDesktopManager(null);
  108. }
  109. desktopManager = null;
  110. }
  111. protected void installKeyboardActions(){
  112. InputMap inputMap = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
  113. if (inputMap != null) {
  114. SwingUtilities.replaceUIInputMap(desktop,
  115. JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);
  116. }
  117. inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
  118. if (inputMap != null) {
  119. SwingUtilities.replaceUIInputMap(desktop,
  120. JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
  121. inputMap);
  122. }
  123. ActionMap actionMap = getActionMap();
  124. SwingUtilities.replaceUIActionMap(desktop, actionMap);
  125. registerKeyboardActions();
  126. }
  127. protected void registerKeyboardActions(){
  128. }
  129. protected void unregisterKeyboardActions(){
  130. }
  131. InputMap getInputMap(int condition) {
  132. if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
  133. return createInputMap(condition);
  134. }
  135. else if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
  136. return (InputMap)UIManager.get("Desktop.ancestorInputMap");
  137. }
  138. return null;
  139. }
  140. InputMap createInputMap(int condition) {
  141. if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
  142. Object[] bindings = (Object[])UIManager.get
  143. ("Desktop.windowBindings");
  144. if (bindings != null) {
  145. return LookAndFeel.makeComponentInputMap(desktop, bindings);
  146. }
  147. }
  148. return null;
  149. }
  150. ActionMap getActionMap() {
  151. return createActionMap();
  152. }
  153. ActionMap createActionMap() {
  154. ActionMap map = new ActionMapUIResource();
  155. map.put("restore", new OpenAction());
  156. map.put("close", new CloseAction());
  157. map.put("move", new MoveResizeAction("move"));
  158. map.put("resize", new MoveResizeAction("resize"));
  159. map.put("left", new MoveResizeAction("left"));
  160. map.put("shrinkLeft", new MoveResizeAction("shrinkLeft"));
  161. map.put("right", new MoveResizeAction("right"));
  162. map.put("shrinkRight", new MoveResizeAction("shrinkRight"));
  163. map.put("up", new MoveResizeAction("up"));
  164. map.put("shrinkUp", new MoveResizeAction("shrinkUp"));
  165. map.put("down", new MoveResizeAction("down"));
  166. map.put("shrinkDown", new MoveResizeAction("shrinkDown"));
  167. map.put("escape", new MoveResizeAction("escape"));
  168. map.put("minimize", new MinimizeAction());
  169. map.put("maximize", new MaximizeAction());
  170. map.put("selectNextFrame", nextAction = new NavigateAction());
  171. map.put("selectPreviousFrame", new PreviousAction());
  172. map.put("navigateNext", new NavigateOutAction(true));
  173. map.put("navigatePrevious", new NavigateOutAction(false));
  174. return map;
  175. }
  176. protected void uninstallKeyboardActions(){
  177. unregisterKeyboardActions();
  178. SwingUtilities.replaceUIInputMap(desktop, JComponent.
  179. WHEN_IN_FOCUSED_WINDOW, null);
  180. SwingUtilities.replaceUIInputMap(desktop, JComponent.
  181. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
  182. SwingUtilities.replaceUIActionMap(desktop, null);
  183. }
  184. public void paint(Graphics g, JComponent c) {}
  185. public Dimension getPreferredSize(JComponent c) {return null;}
  186. public Dimension getMinimumSize(JComponent c) {
  187. return minSize;
  188. }
  189. public Dimension getMaximumSize(JComponent c){
  190. return maxSize;
  191. }
  192. /*
  193. * Key binding for accessibility -----------------
  194. */
  195. private static Vector framesCache;
  196. private NavigateAction nextAction;
  197. private boolean moving = false;
  198. private boolean resizing = false;
  199. private final int MOVE_RESIZE_INCREMENT = 10;
  200. /*
  201. * Handles restoring a minimized or maximized internal frame.
  202. */
  203. protected class OpenAction extends AbstractAction {
  204. public void actionPerformed(ActionEvent e) {
  205. // restore the selected minimized or maximized frame
  206. JInternalFrame f = desktop.getSelectedFrame();
  207. if (f == null) return;
  208. try {
  209. if (f.isIcon()) {
  210. f.setIcon(false);
  211. } else if (f.isMaximum()) {
  212. f.setMaximum(false);
  213. }
  214. f.setSelected(true);
  215. } catch (PropertyVetoException pve) {
  216. }
  217. }
  218. public boolean isEnabled() {
  219. return true;
  220. }
  221. }
  222. /*
  223. * Handles closing an internal frame
  224. */
  225. protected class CloseAction extends AbstractAction {
  226. public void actionPerformed(ActionEvent e) {
  227. JInternalFrame f = desktop.getSelectedFrame();
  228. if (f == null) return;
  229. if (f.isClosable()) {
  230. try {
  231. f.setClosed(true);
  232. } catch (PropertyVetoException pve) {
  233. }
  234. }
  235. }
  236. public boolean isEnabled() {
  237. return true;
  238. }
  239. }
  240. /*
  241. * Handles moving and resizing an internal frame
  242. */
  243. private class MoveResizeAction extends AbstractAction {
  244. private String command;
  245. public MoveResizeAction(String command) {
  246. this.command = command;
  247. }
  248. public void actionPerformed(ActionEvent e) {
  249. JInternalFrame c = desktop.getSelectedFrame();
  250. if (c == null) {
  251. return;
  252. }
  253. if ("move".equals(command)) {
  254. moving = true;
  255. resizing = false;
  256. return;
  257. } else if ("resize".equals(command)) {
  258. moving = false;
  259. resizing = true;
  260. return;
  261. } else if ("escape".equals(command)) {
  262. moving = resizing = false;
  263. return;
  264. }
  265. if (!moving && !resizing) {
  266. return;
  267. }
  268. Dimension size = c.getSize();
  269. Dimension minSize = c.getMinimumSize();
  270. Point loc = c.getLocation();
  271. if ("left".equals(command)) {
  272. if (moving) {
  273. c.setLocation(loc.x - MOVE_RESIZE_INCREMENT, loc.y);
  274. } else if (resizing) {
  275. c.setLocation(loc.x - MOVE_RESIZE_INCREMENT, loc.y);
  276. c.setSize(size.width + MOVE_RESIZE_INCREMENT, size.height);
  277. }
  278. } else if ("right".equals(command)) {
  279. if (moving) {
  280. c.setLocation(loc.x + MOVE_RESIZE_INCREMENT, loc.y);
  281. } else if (resizing) {
  282. c.setLocation(loc.x, loc.y);
  283. c.setSize(size.width + MOVE_RESIZE_INCREMENT, size.height);
  284. }
  285. } else if ("up".equals(command)) {
  286. if (moving) {
  287. c.setLocation(loc.x, loc.y - MOVE_RESIZE_INCREMENT);
  288. } else if (resizing) {
  289. c.setLocation(loc.x, loc.y - MOVE_RESIZE_INCREMENT);
  290. c.setSize(size.width, size.height + MOVE_RESIZE_INCREMENT);
  291. }
  292. } else if ("down".equals(command)) {
  293. if (moving) {
  294. c.setLocation(loc.x, loc.y + MOVE_RESIZE_INCREMENT);
  295. } else if (resizing) {
  296. c.setLocation(loc.x, loc.y);
  297. c.setSize(size.width, size.height + MOVE_RESIZE_INCREMENT);
  298. }
  299. } else if ("shrinkLeft".equals(command) && resizing) {
  300. if (minSize.width < (size.width - MOVE_RESIZE_INCREMENT)) {
  301. c.setLocation(loc.x, loc.y);
  302. c.setSize(size.width - MOVE_RESIZE_INCREMENT, size.height);
  303. } else {
  304. c.setSize(minSize.width, size.height);
  305. }
  306. } else if ("shrinkRight".equals(command) && resizing) {
  307. if (minSize.width < (size.width - MOVE_RESIZE_INCREMENT)) {
  308. c.setLocation(loc.x + MOVE_RESIZE_INCREMENT, loc.y);
  309. c.setSize(size.width - MOVE_RESIZE_INCREMENT, size.height);
  310. } else {
  311. c.setLocation(loc.x - minSize.width + size.width , loc.y);
  312. c.setSize(minSize.width, size.height);
  313. }
  314. } else if ("shrinkUp".equals(command) && resizing) {
  315. if (minSize.height < (size.height - MOVE_RESIZE_INCREMENT)) {
  316. c.setLocation(loc.x, loc.y);
  317. c.setSize(size.width, size.height - MOVE_RESIZE_INCREMENT);
  318. } else {
  319. c.setSize(size.width, minSize.height);
  320. }
  321. } else if ("shrinkDown".equals(command) && resizing) {
  322. if (minSize.height < (size.height - MOVE_RESIZE_INCREMENT)) {
  323. c.setLocation(loc.x, loc.y + MOVE_RESIZE_INCREMENT);
  324. c.setSize(size.width, size.height - MOVE_RESIZE_INCREMENT);
  325. } else {
  326. c.setLocation(loc.x, loc.y - minSize.height + size.height);
  327. c.setSize(size.width, minSize.height);
  328. }
  329. }
  330. }
  331. public boolean isEnabled() {
  332. return true;
  333. }
  334. }
  335. /*
  336. * Handles minimizing an internal frame
  337. */
  338. protected class MinimizeAction extends AbstractAction {
  339. public void actionPerformed(ActionEvent e) {
  340. // minimize the selected frame
  341. JInternalFrame f = desktop.getSelectedFrame();
  342. if (f == null) return;
  343. if (f.isIconifiable() && ! f.isIcon()) {
  344. try {
  345. f.setIcon(true);
  346. } catch (PropertyVetoException pve) {
  347. }
  348. }
  349. }
  350. public boolean isEnabled() {
  351. return true;
  352. }
  353. }
  354. /*
  355. * Handles maximizing an internal frame
  356. */
  357. protected class MaximizeAction extends AbstractAction {
  358. public void actionPerformed(ActionEvent e) {
  359. // maximize the selected frame
  360. JInternalFrame f = desktop.getSelectedFrame();
  361. if (f == null) return;
  362. if (f.isMaximizable() && !f.isMaximum()) {
  363. if (f.isIcon()) {
  364. try {
  365. f.setIcon(false);
  366. f.setMaximum(true);
  367. } catch (PropertyVetoException pve) {}
  368. } else
  369. try {
  370. f.setMaximum(true);
  371. } catch (PropertyVetoException pve) {
  372. }
  373. }
  374. }
  375. public boolean isEnabled() {
  376. return true;
  377. }
  378. }
  379. /*
  380. * Handles navigating to the next internal frame.
  381. */
  382. protected class NavigateAction extends AbstractAction {
  383. public void actionPerformed(ActionEvent e) {
  384. // navigate to the next frame
  385. int i = 0;
  386. verifyFramesCache();
  387. if (framesCache.size() == 0) return;
  388. JInternalFrame f = desktop.getSelectedFrame();
  389. if (f != null) i = framesCache.indexOf(f);
  390. if (i == -1) {
  391. /* if the frame is not there, its icon may be */
  392. i = framesCache.indexOf(f.getDesktopIcon());
  393. if (i == -1) {
  394. /* error */ return;
  395. }
  396. }
  397. if (++i == framesCache.size()) /* wrap */ i = 0;
  398. JComponent c = (JComponent) framesCache.elementAt(i);
  399. if (c instanceof JInternalFrame) {
  400. try {
  401. ((JInternalFrame) c).setSelected(true);
  402. desktopManager.activateFrame((JInternalFrame) c);
  403. }
  404. catch (PropertyVetoException pve) {}
  405. } else {
  406. /* it had better be an icon! */
  407. if (!(c instanceof JInternalFrame.JDesktopIcon)){
  408. /* error */
  409. return;
  410. }
  411. try {
  412. ((JInternalFrame)((JInternalFrame.JDesktopIcon) c).getInternalFrame()).setSelected(true);
  413. desktopManager.activateFrame(((JInternalFrame.JDesktopIcon) c).getInternalFrame());
  414. }
  415. catch (PropertyVetoException pve) {}
  416. }
  417. }
  418. public boolean isEnabled() {
  419. return true;
  420. }
  421. }
  422. /*
  423. * Handles navigating to the previous internal frame.
  424. */
  425. private class PreviousAction extends AbstractAction {
  426. public void actionPerformed(ActionEvent e) {
  427. // navigate to the previous internal frame
  428. int i = 0;
  429. verifyFramesCache();
  430. if (framesCache.size() == 0) return;
  431. JInternalFrame f = desktop.getSelectedFrame();
  432. if (f != null) i = framesCache.indexOf(f);
  433. if (i == -1) {
  434. /* if the frame is not there, its icon may be */
  435. i = framesCache.indexOf(f.getDesktopIcon());
  436. if (i == -1) {
  437. /* error */ return;
  438. }
  439. }
  440. if (--i == -1) /* wrap */ i = framesCache.size() - 1;
  441. JComponent c = (JComponent) framesCache.elementAt(i);
  442. if (c instanceof JInternalFrame) {
  443. try {
  444. ((JInternalFrame) c).setSelected(true);
  445. }
  446. catch (PropertyVetoException pve) {}
  447. } else {
  448. /* it had better be an icon! */
  449. if (!(c instanceof JInternalFrame.JDesktopIcon)){
  450. /* error */
  451. return;
  452. }
  453. try {
  454. ((JInternalFrame)((JInternalFrame.JDesktopIcon) c).getInternalFrame()).setSelected(true);
  455. }
  456. catch (PropertyVetoException pve) {}
  457. }
  458. }
  459. public boolean isEnabled() {
  460. return true;
  461. }
  462. }
  463. /**
  464. * Handles navigating to the component before or after the desktop.
  465. */
  466. private class NavigateOutAction extends AbstractAction {
  467. private boolean moveForward;
  468. public NavigateOutAction(boolean moveForward) {
  469. this.moveForward = moveForward;
  470. }
  471. public void actionPerformed(ActionEvent e) {
  472. Container cycleRoot = desktop.getFocusCycleRootAncestor();
  473. if (cycleRoot != null) {
  474. FocusTraversalPolicy policy =
  475. cycleRoot.getFocusTraversalPolicy();
  476. if (policy != null && policy instanceof
  477. SortingFocusTraversalPolicy) {
  478. SortingFocusTraversalPolicy sPolicy =
  479. (SortingFocusTraversalPolicy)policy;
  480. boolean idc = sPolicy.getImplicitDownCycleTraversal();
  481. try {
  482. sPolicy.setImplicitDownCycleTraversal(false);
  483. if (moveForward) {
  484. KeyboardFocusManager.
  485. getCurrentKeyboardFocusManager().
  486. focusNextComponent(desktop);
  487. } else {
  488. KeyboardFocusManager.
  489. getCurrentKeyboardFocusManager().
  490. focusPreviousComponent(desktop);
  491. }
  492. } finally {
  493. sPolicy.setImplicitDownCycleTraversal(idc);
  494. }
  495. }
  496. }
  497. }
  498. public boolean isEnabled() {
  499. return true;
  500. }
  501. }
  502. /*
  503. * Verifies the internal frames cache is up to date.
  504. */
  505. private void verifyFramesCache() {
  506. // Need to initialize?
  507. if (framesCache == null) {
  508. framesCache = new Vector();
  509. }
  510. // Check whether any internal frames have closed in
  511. // which case we have to refresh the frames cache.
  512. boolean framesHaveClosed = false;
  513. int len = framesCache.size();
  514. for (int i = 0; i < len; i++) {
  515. JComponent c =
  516. (JComponent)framesCache.elementAt(i);
  517. if (c instanceof JInternalFrame) {
  518. JInternalFrame f = (JInternalFrame)c;
  519. if (f.isClosed()) {
  520. framesHaveClosed = true;
  521. break;
  522. }
  523. }
  524. else if (c instanceof JInternalFrame.JDesktopIcon) {
  525. JInternalFrame.JDesktopIcon icon =
  526. (JInternalFrame.JDesktopIcon)c;
  527. JInternalFrame f = (JInternalFrame)icon.getInternalFrame();
  528. if (f.isClosed()) {
  529. framesHaveClosed = true;
  530. break;
  531. }
  532. }
  533. }
  534. JInternalFrame [] allFrames = desktop.getAllFrames();
  535. if (framesHaveClosed || allFrames.length != framesCache.size()) {
  536. // Cache frames starting at the lowest layer.
  537. framesCache.clear();
  538. int low = desktop.lowestLayer();
  539. int high = desktop.highestLayer();
  540. for (int i = high; i >= low; i--) {
  541. Component [] comp = desktop.getComponentsInLayer(i);
  542. if (comp.length > 0) {
  543. for (int j = 0; j < comp.length; j++) {
  544. framesCache.addElement(comp[j]);
  545. }
  546. }
  547. }
  548. }
  549. }
  550. // End of accessibility keybindings
  551. }