001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Anton Avtamonov
019: * @version $Revision$
020: */package javax.swing.plaf.basic;
021:
022: import java.awt.Rectangle;
023: import java.awt.event.ActionEvent;
024:
025: import javax.swing.AbstractAction;
026: import javax.swing.JComponent;
027: import javax.swing.JTree;
028: import javax.swing.SwingConstants;
029: import javax.swing.TransferHandler;
030: import javax.swing.tree.TreePath;
031:
032: import org.apache.harmony.x.swing.Utilities;
033:
034: final class BasicTreeKeyboardActions {
035: private static abstract class TreeAction extends AbstractAction {
036: public void actionPerformed(final ActionEvent e) {
037: JTree tree = (JTree) e.getSource();
038: if (tree.getRowCount() == 0) {
039: return;
040: }
041:
042: actionPerformed(tree);
043: }
044:
045: public abstract void actionPerformed(JTree tree);
046:
047: protected TreePath getPreviousPath(final JTree tree,
048: final int currentRow) {
049: if (currentRow == -1) {
050: return tree.getPathForRow(tree.getRowCount() - 1);
051: }
052: return currentRow > 0 ? tree.getPathForRow(currentRow - 1)
053: : tree.getPathForRow(0);
054: }
055:
056: protected TreePath getNextPath(final JTree tree,
057: final int currentRow) {
058: if (currentRow == -1) {
059: return tree.getPathForRow(0);
060: }
061: return currentRow < tree.getRowCount() - 1 ? tree
062: .getPathForRow(currentRow + 1) : tree
063: .getPathForRow(tree.getRowCount() - 1);
064: }
065:
066: protected void extendSelection(final JTree tree,
067: final TreePath toPath) {
068: TreePath anchorPath = tree.getAnchorSelectionPath();
069: if (anchorPath == null) {
070: tree.setSelectionPath(toPath);
071: } else {
072: int anchorRow = tree.getRowForPath(anchorPath);
073: int leadRow = tree.getRowForPath(toPath);
074: tree.setSelectionInterval(anchorRow, leadRow);
075: tree.setAnchorSelectionPath(anchorPath);
076: tree.setLeadSelectionPath(toPath);
077: }
078: tree.scrollPathToVisible(toPath);
079: }
080:
081: protected boolean isLeaf(final JTree tree, final TreePath path) {
082: return tree.getModel().isLeaf(path.getLastPathComponent());
083: }
084:
085: protected TreePath getLastPath(final JTree tree) {
086: return tree.getPathForRow(tree.getRowCount() - 1);
087: }
088:
089: protected TreePath getUpPath(final JTree tree) {
090: Rectangle visibleRect = tree.getVisibleRect();
091: TreePath result = tree.getClosestPathForLocation(
092: visibleRect.x, visibleRect.y + 1);
093: TreePath leadPath = tree.getLeadSelectionPath();
094: if (result.equals(leadPath)) {
095: result = tree.getClosestPathForLocation(visibleRect.x,
096: visibleRect.y - visibleRect.height);
097: }
098:
099: return result;
100: }
101:
102: protected TreePath getDownPath(final JTree tree) {
103: Rectangle visibleRect = tree.getVisibleRect();
104: TreePath result = tree.getClosestPathForLocation(
105: visibleRect.x, visibleRect.y + visibleRect.height
106: - 1);
107: TreePath leadPath = tree.getLeadSelectionPath();
108: if (result.equals(leadPath)) {
109: result = tree.getClosestPathForLocation(visibleRect.x,
110: visibleRect.y + 2 * visibleRect.height);
111: }
112:
113: return result;
114: }
115: }
116:
117: private static abstract class ChangeLeadAction extends TreeAction {
118: public void actionPerformed(final JTree tree) {
119: changeLeadActionPerformed(tree, getNewLeadPath(tree));
120: }
121:
122: protected void changeLeadActionPerformed(final JTree tree,
123: final TreePath newLeadPath) {
124: TreePath oldLeadPath = tree.getLeadSelectionPath();
125: tree.setLeadSelectionPath(newLeadPath);
126: tree.scrollPathToVisible(newLeadPath);
127: tree.repaint(tree.getPathBounds(oldLeadPath));
128: tree.repaint(tree.getPathBounds(newLeadPath));
129: }
130:
131: protected abstract TreePath getNewLeadPath(JTree tree);
132: }
133:
134: private static abstract class PreserveLeadAnchorAction extends
135: TreeAction {
136: public void actionPerformed(final JTree tree) {
137: TreePath leadPath = tree.getLeadSelectionPath();
138: TreePath anchorPath = tree.getAnchorSelectionPath();
139: preserveActionPerformed(tree);
140: if (leadPath != null) {
141: tree.setLeadSelectionPath(leadPath);
142: }
143: if (anchorPath != null) {
144: tree.setAnchorSelectionPath(anchorPath);
145: }
146: }
147:
148: protected abstract void preserveActionPerformed(JTree tree);
149: }
150:
151: private static AbstractAction startEditingAction = new TreeAction() {
152: public void actionPerformed(final JTree tree) {
153: TreePath path = tree.getLeadSelectionPath();
154: if (path == null) {
155: return;
156: }
157:
158: tree.startEditingAtPath(path);
159: }
160: };
161: static AbstractAction cancelAction = new AbstractAction() {
162: public void actionPerformed(final ActionEvent e) {
163: JTree tree = (JTree) e.getSource();
164: tree.cancelEditing();
165: }
166: };
167: static AbstractAction selectPreviousAction = new TreeAction() {
168: public void actionPerformed(final JTree tree) {
169: int leadRow = tree.getLeadSelectionRow();
170: TreePath prevPath = getPreviousPath(tree, leadRow);
171: tree.setSelectionPath(prevPath);
172: tree.scrollPathToVisible(prevPath);
173: }
174: };
175: private static AbstractAction selectPreviousExtendSelectionAction = new TreeAction() {
176: public void actionPerformed(final JTree tree) {
177: TreePath prevPath = getPreviousPath(tree, tree
178: .getLeadSelectionRow());
179: extendSelection(tree, prevPath);
180: }
181: };
182: static AbstractAction selectNextAction = new TreeAction() {
183: public void actionPerformed(final JTree tree) {
184: int leadRow = tree.getLeadSelectionRow();
185: TreePath nextPath = getNextPath(tree, leadRow);
186: tree.setSelectionPath(nextPath);
187: tree.scrollPathToVisible(nextPath);
188: }
189: };
190: private static AbstractAction selectNextExtendSelectionAction = new TreeAction() {
191: public void actionPerformed(final JTree tree) {
192: TreePath nextPath = getNextPath(tree, tree
193: .getLeadSelectionRow());
194: extendSelection(tree, nextPath);
195: }
196: };
197: static AbstractAction selectChildAction = new TreeAction() {
198: public void actionPerformed(final JTree tree) {
199: TreePath leadPath = tree.getLeadSelectionPath();
200: if (leadPath == null) {
201: tree.setSelectionRow(0);
202: tree.scrollRowToVisible(0);
203: return;
204: }
205:
206: if (!isLeaf(tree, leadPath) && !tree.isExpanded(leadPath)) {
207: tree.expandPath(leadPath);
208: return;
209: }
210:
211: TreePath nextPath = getNextPath(tree, tree
212: .getLeadSelectionRow());
213: tree.setSelectionPath(nextPath);
214: tree.scrollPathToVisible(nextPath);
215: }
216: };
217: static AbstractAction selectParentAction = new TreeAction() {
218: public void actionPerformed(final JTree tree) {
219: TreePath leadPath = tree.getLeadSelectionPath();
220: if (leadPath == null) {
221: TreePath lastPath = getLastPath(tree);
222: tree.setSelectionPath(lastPath);
223: tree.scrollPathToVisible(lastPath);
224: return;
225: }
226:
227: if (!isLeaf(tree, leadPath) && tree.isExpanded(leadPath)) {
228: tree.collapsePath(leadPath);
229: return;
230: }
231:
232: TreePath prevPath = leadPath.getParentPath();
233: if (!tree.isVisible(prevPath)) {
234: return;
235: }
236: tree.setSelectionPath(prevPath);
237: tree.scrollPathToVisible(prevPath);
238: }
239: };
240: static AbstractAction selectFirstAction = new TreeAction() {
241: public void actionPerformed(final JTree tree) {
242: tree.setSelectionPath(tree.getPathForRow(0));
243: }
244: };
245: private static AbstractAction selectFirstExtendSelectionAction = new TreeAction() {
246: public void actionPerformed(final JTree tree) {
247: TreePath firstPath = tree.getPathForRow(0);
248: extendSelection(tree, firstPath);
249: }
250: };
251: static AbstractAction selectLastAction = new TreeAction() {
252: public void actionPerformed(final JTree tree) {
253: tree.setSelectionPath(getLastPath(tree));
254: }
255: };
256: private static AbstractAction selectLastExtendSelectionAction = new TreeAction() {
257: public void actionPerformed(final JTree tree) {
258: extendSelection(tree, getLastPath(tree));
259: }
260: };
261: private static AbstractAction selectAllAction = new PreserveLeadAnchorAction() {
262: public void preserveActionPerformed(final JTree tree) {
263: tree.setSelectionInterval(0, tree.getRowCount() - 1);
264: }
265: };
266: private static AbstractAction clearSelectionAction = new PreserveLeadAnchorAction() {
267: public void preserveActionPerformed(final JTree tree) {
268: tree.clearSelection();
269: }
270: };
271: private static AbstractAction toggleSelectionPreserveAnchorAction = new PreserveLeadAnchorAction() {
272: public void preserveActionPerformed(final JTree tree) {
273: TreePath leadPath = tree.getLeadSelectionPath();
274: if (leadPath == null) {
275: return;
276: }
277:
278: if (tree.isPathSelected(leadPath)) {
279: tree.removeSelectionPath(leadPath);
280: } else {
281: tree.addSelectionPath(leadPath);
282: }
283: }
284: };
285: private static AbstractAction moveSelectionToAction = new TreeAction() {
286: public void actionPerformed(final JTree tree) {
287: TreePath leadPath = tree.getLeadSelectionPath();
288: if (leadPath == null) {
289: return;
290: }
291: tree.setSelectionPath(leadPath);
292: }
293: };
294: private static AbstractAction extendSelectionAction = new TreeAction() {
295: public void actionPerformed(final JTree tree) {
296: TreePath leadPath = tree.getLeadSelectionPath();
297: if (leadPath == null) {
298: return;
299: }
300: extendSelection(tree, leadPath);
301: }
302: };
303: private static AbstractAction selectFirstChangeLeadAction = new ChangeLeadAction() {
304: protected TreePath getNewLeadPath(final JTree tree) {
305: return tree.getPathForRow(0);
306: }
307: };
308: private static AbstractAction selectLastChangeLeadAction = new ChangeLeadAction() {
309: protected TreePath getNewLeadPath(final JTree tree) {
310: return getLastPath(tree);
311: }
312: };
313: private static AbstractAction selectPreviousChangeLeadAction = new ChangeLeadAction() {
314: protected TreePath getNewLeadPath(final JTree tree) {
315: return getPreviousPath(tree, tree.getLeadSelectionRow());
316: }
317: };
318: private static AbstractAction selectNextChangeLeadAction = new ChangeLeadAction() {
319: protected TreePath getNewLeadPath(final JTree tree) {
320: return getNextPath(tree, tree.getLeadSelectionRow());
321: }
322: };
323:
324: static AbstractAction scrollUpChangeSelectionAction = new TreeAction() {
325: public void actionPerformed(final JTree tree) {
326: TreePath upPath = getUpPath(tree);
327: tree.setSelectionPath(upPath);
328: tree.scrollPathToVisible(upPath);
329: }
330: };
331: private static AbstractAction scrollUpExtendSelectionAction = new TreeAction() {
332: public void actionPerformed(final JTree tree) {
333: TreePath upPath = getUpPath(tree);
334: extendSelection(tree, upPath);
335: tree.scrollPathToVisible(upPath);
336: }
337: };
338: private static AbstractAction scrollUpChangeLeadAction = new ChangeLeadAction() {
339: protected TreePath getNewLeadPath(final JTree tree) {
340: return getUpPath(tree);
341: }
342: };
343: static AbstractAction scrollDownChangeSelectionAction = new TreeAction() {
344: public void actionPerformed(final JTree tree) {
345: TreePath downPath = getDownPath(tree);
346: tree.setSelectionPath(downPath);
347: tree.scrollPathToVisible(downPath);
348: }
349: };
350: private static AbstractAction scrollDownExtendSelectionAction = new TreeAction() {
351: public void actionPerformed(final JTree tree) {
352: TreePath downPath = getDownPath(tree);
353: extendSelection(tree, downPath);
354: tree.scrollPathToVisible(downPath);
355: }
356: };
357: private static AbstractAction scrollDownChangeLeadAction = new ChangeLeadAction() {
358: protected TreePath getNewLeadPath(final JTree tree) {
359: return getDownPath(tree);
360: }
361: };
362: private static AbstractAction scrollLeftAction = new TreeAction() {
363: public void actionPerformed(final JTree tree) {
364: Rectangle visibleRect = tree.getVisibleRect();
365: int increment = tree.getScrollableUnitIncrement(
366: visibleRect, SwingConstants.HORIZONTAL, -1);
367: visibleRect.translate(-increment, 0);
368: tree.scrollRectToVisible(visibleRect);
369: }
370: };
371: private static AbstractAction scrollRightAction = new TreeAction() {
372: public void actionPerformed(final JTree tree) {
373: Rectangle visibleRect = tree.getVisibleRect();
374: int increment = tree.getScrollableUnitIncrement(
375: visibleRect, SwingConstants.HORIZONTAL, 1);
376: visibleRect.translate(increment, 0);
377: tree.scrollRectToVisible(visibleRect);
378: }
379: };
380: private static AbstractAction expandAction = new TreeAction() {
381: public void actionPerformed(final JTree tree) {
382: int leadRow = tree.getLeadSelectionRow();
383: tree.expandRow(leadRow);
384: }
385: };
386: private static AbstractAction collapseAction = new TreeAction() {
387: public void actionPerformed(final JTree tree) {
388: int leadRow = tree.getLeadSelectionRow();
389: tree.collapseRow(leadRow);
390: }
391: };
392:
393: public static void installKeyboardActions(final JTree tree) {
394: Utilities.installKeyboardActions(tree, JComponent.WHEN_FOCUSED,
395: "Tree.focusInputMap", "Tree.focusInputMap.RightToLeft");
396: Utilities.installKeyboardActions(tree,
397: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
398: "Tree.ancestorInputMap", null);
399:
400: tree.getActionMap()
401: .put("copy", TransferHandler.getCopyAction());
402: tree.getActionMap().put("paste",
403: TransferHandler.getPasteAction());
404: tree.getActionMap().put("cut", TransferHandler.getCutAction());
405:
406: tree.getActionMap().put("selectPrevious", selectPreviousAction);
407: tree.getActionMap().put("selectPreviousExtendSelection",
408: selectPreviousExtendSelectionAction);
409: tree.getActionMap().put("selectNext", selectNextAction);
410: tree.getActionMap().put("selectNextExtendSelection",
411: selectNextExtendSelectionAction);
412: tree.getActionMap().put("selectChild", selectChildAction);
413: tree.getActionMap().put("selectParent", selectParentAction);
414:
415: tree.getActionMap().put("selectFirst", selectFirstAction);
416: tree.getActionMap().put("selectFirstExtendSelection",
417: selectFirstExtendSelectionAction);
418: tree.getActionMap().put("selectLast", selectLastAction);
419: tree.getActionMap().put("selectLastExtendSelection",
420: selectLastExtendSelectionAction);
421:
422: tree.getActionMap().put("selectAll", selectAllAction);
423: tree.getActionMap().put("clearSelection", clearSelectionAction);
424:
425: tree.getActionMap().put("toggleSelectionPreserveAnchor",
426: toggleSelectionPreserveAnchorAction);
427: tree.getActionMap().put("extendSelection",
428: extendSelectionAction);
429: tree.getActionMap().put("moveSelectionTo",
430: moveSelectionToAction);
431:
432: tree.getActionMap().put("selectFirstChangeLead",
433: selectFirstChangeLeadAction);
434: tree.getActionMap().put("selectLastChangeLead",
435: selectLastChangeLeadAction);
436: tree.getActionMap().put("selectPreviousChangeLead",
437: selectPreviousChangeLeadAction);
438: tree.getActionMap().put("selectNextChangeLead",
439: selectNextChangeLeadAction);
440:
441: tree.getActionMap().put("scrollUpChangeSelection",
442: scrollUpChangeSelectionAction);
443: tree.getActionMap().put("scrollUpExtendSelection",
444: scrollUpExtendSelectionAction);
445: tree.getActionMap().put("scrollUpChangeLead",
446: scrollUpChangeLeadAction);
447: tree.getActionMap().put("scrollDownChangeSelection",
448: scrollDownChangeSelectionAction);
449: tree.getActionMap().put("scrollDownExtendSelection",
450: scrollDownExtendSelectionAction);
451: tree.getActionMap().put("scrollDownChangeLead",
452: scrollDownChangeLeadAction);
453:
454: tree.getActionMap().put("scrollLeft", scrollLeftAction);
455: tree.getActionMap().put("scrollRight", scrollRightAction);
456:
457: tree.getActionMap().put("startEditing", startEditingAction);
458: tree.getActionMap().put("cancel", cancelAction);
459:
460: tree.getActionMap().put("expand", expandAction);
461: tree.getActionMap().put("collapse", collapseAction);
462: }
463:
464: public static void uninstallKeyboardActions(final JTree tree) {
465: Utilities.uninstallKeyboardActions(tree,
466: JComponent.WHEN_FOCUSED);
467: Utilities.uninstallKeyboardActions(tree,
468: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
469: }
470: }
|