001: package com.jidesoft.utils;
002:
003: /**
004: * <p>Title: JideFocusTracker</p>
005: * <p>Description: This class is used to manage focus. It will register focus
006: * listeners for the highestComponent and any of its children.
007: * This allows for focusListeners to be tied to this adapter,
008: * and then all focus events can be routed through this.</p>
009: */
010:
011: import java.awt.*;
012: import java.awt.event.ContainerEvent;
013: import java.awt.event.ContainerListener;
014: import java.awt.event.FocusEvent;
015: import java.awt.event.FocusListener;
016:
017: /**
018: * For internal usage only.
019: */
020: public class JideFocusTracker {
021:
022: protected Component compHeighest;
023: protected FocusListener listenerFocus = null;
024: protected ContainerListener listenerContainer = null;
025: protected transient FocusListener listenerMultiCast;
026: protected boolean repeat;
027:
028: protected transient Component lastFocus;
029:
030: public JideFocusTracker() {
031: lastFocus = null;
032: setRepeating(true);
033: listenerFocus = new MainFocusListener();
034: listenerContainer = new MainContainerListener();
035: }
036:
037: public JideFocusTracker(Component compHeighest) {
038: this ();
039: //System.out.println("constructing focus tracker for comp " + compHeighest);
040: setHeighestComponent(compHeighest);
041: }
042:
043: ////////////////////////////////////////////////////////////////////////////////
044: // Public Methods
045: ////////////////////////////////////////////////////////////////////////////////
046:
047: public void setHeighestComponent(Component compHeighest) {
048: Component OldValue = this .compHeighest;
049:
050: if (OldValue != null) {
051: synchronized (OldValue.getTreeLock()) {
052: removeInternalListeners(OldValue);
053: }
054: }
055:
056: if (compHeighest != null) {
057: synchronized (compHeighest.getTreeLock()) {
058: addInternalListeners(compHeighest);
059: }
060: }
061:
062: this .compHeighest = compHeighest;
063: // note - I would fire an event here if I thought anyone would care.
064: }
065:
066: public Component getHeighestComponent() {
067: return compHeighest;
068: }
069:
070: /**
071: * This allows you to set whether focus lost or focus gained will be
072: * fired if the event is for the same component as a previous event.
073: * The default is true.
074: */
075: public boolean isRepeating() {
076: return this .repeat;
077: }
078:
079: /**
080: * @see #isRepeating
081: */
082: public void setRepeating(boolean repeat) {
083: this .repeat = repeat;
084: }
085:
086: public synchronized void addFocusListener(FocusListener l) {
087: listenerMultiCast = AWTEventMulticaster.add(listenerMultiCast,
088: l);
089: }
090:
091: public synchronized void removeFocusListener(FocusListener l) {
092: listenerMultiCast = AWTEventMulticaster.remove(
093: listenerMultiCast, l);
094: }
095:
096: ////////////////////////////////////////////////////////////////////////////////
097: // Protected Methods
098: ////////////////////////////////////////////////////////////////////////////////
099:
100: protected void addInternalListeners(Component component) {
101: component.addFocusListener(listenerFocus);
102: if (component instanceof Container) {
103: Container container = (Container) component;
104: container.addContainerListener(listenerContainer);
105: for (int i = 0; i < container.getComponentCount(); i++) {
106: addInternalListeners(container.getComponent(i));
107: }
108: }
109: }
110:
111: protected void removeInternalListeners(Component component) {
112: component.removeFocusListener(listenerFocus);
113: if (component instanceof Container) {
114: Container container = (Container) component;
115: container.removeContainerListener(listenerContainer);
116: for (int i = 0; i < container.getComponentCount(); i++) {
117: removeInternalListeners(container.getComponent(i));
118: }
119: }
120: }
121:
122: class MainContainerListener implements ContainerListener {
123: public void componentAdded(ContainerEvent e) {
124: //System.out.println(e.getChild().getClass().getName() + " add to container = " + e.getContainer().getClass().getName());
125: synchronized (e.getChild().getTreeLock()) {
126: addInternalListeners(e.getChild());
127: }
128: }
129:
130: public void componentRemoved(ContainerEvent e) {
131: //System.out.println(e.getChild().getClass().getName() + " removed from container = " + e.getContainer().getClass().getName());
132: synchronized (e.getChild().getTreeLock()) {
133: removeInternalListeners(e.getChild());
134: }
135: }
136: }
137:
138: class MainFocusListener implements FocusListener {
139: public void focusGained(FocusEvent e) {
140: // System.out.println("focusGained " + e.getSource());
141: if (listenerMultiCast != null)
142: if ((e.getSource() != lastFocus) || (isRepeating()))
143: listenerMultiCast.focusGained(e);
144: }
145:
146: public void focusLost(FocusEvent e) {
147: // System.out.println(this + " is firing");
148: if (listenerMultiCast != null)
149: if ((e.getSource() != lastFocus) || (isRepeating()))
150: listenerMultiCast.focusLost(e);
151: }
152: }
153: }
|