001: /*
002: * AbstractToolbarFactory.java
003: *
004: * Created on January 25, 2004, 11:59 AM
005: */
006:
007: package org.netbeans.actions.engine.spi;
008:
009: import java.awt.Component;
010: import java.awt.event.ActionEvent;
011: import java.awt.event.ActionListener;
012: import java.awt.event.ComponentAdapter;
013: import java.awt.event.ComponentEvent;
014: import java.awt.event.ComponentListener;
015: import java.awt.event.ContainerEvent;
016: import java.awt.event.ContainerListener;
017: import java.beans.BeanInfo;
018: import java.util.Arrays;
019: import java.util.HashMap;
020: import java.util.Map;
021: import javax.swing.AbstractButton;
022: import javax.swing.Action;
023: import javax.swing.JButton;
024: import javax.swing.JComponent;
025: import javax.swing.JMenu;
026: import javax.swing.JToggleButton;
027: import javax.swing.JToolBar;
028: import org.netbeans.actions.engine.spi.ToolbarFactory;
029: import org.netbeans.actions.spi.ActionProvider;
030:
031: /**
032: *
033: * @author Tim Boudreau
034: */
035: public class AbstractToolbarFactory extends ToolbarFactory {
036: private AbstractEngine engine;
037: protected static final String KEY_CONTAINERCTX = "containerContext";
038: protected static final String KEY_ACTION = "action"; //NOI18N
039: protected static final String KEY_CREATOR = "creator"; //NOI18N
040:
041: /** Creates a new instance of AbstractToolbarFactory */
042: public AbstractToolbarFactory(AbstractEngine engine) {
043: if (engine == null) {
044: throw new NullPointerException("Engine may not be null"); //NOI18N
045: }
046: this .engine = engine;
047: }
048:
049: protected final AbstractEngine getEngine() {
050: return engine;
051: }
052:
053: private String munge(String containerCtx) {
054: return "toolbar" + "." + containerCtx; //NOI18N
055: }
056:
057: private Map mappings = new HashMap();
058:
059: private void addMapping(String containerCtx, JComponent jc) {
060: mappings.put(munge(containerCtx), jc);
061: }
062:
063: private void removeMapping(String containerCtx) {
064: mappings.remove(munge(containerCtx));
065: }
066:
067: private JToolBar getToolbarForContext(String containerCtx) {
068: return (JToolBar) mappings.get(munge(containerCtx));
069: }
070:
071: public JToolBar createToolbar(String containerCtx) {
072: JToolBar result = new JToolBar();
073: result.setName(containerCtx);
074: result.putClientProperty(KEY_CONTAINERCTX, containerCtx);
075: result.putClientProperty(KEY_CREATOR, this );
076: attachToToolbar(containerCtx, result);
077: populateToolbar(containerCtx, result); //XXX listener should do this
078: return result;
079: }
080:
081: private void attachToToolbar(String containerCtx, JToolBar toolbar) {
082: toolbar.addComponentListener(getToolbarListener());
083: toolbar.addContainerListener(getToolbarListener());
084: }
085:
086: private void detachFromToolbar(String containerCtx, JToolBar toolbar) {
087: toolbar.removeComponentListener(getToolbarListener());
088: toolbar.removeContainerListener(getToolbarListener());
089: mappings.remove(containerCtx);
090: }
091:
092: private Listener toolbarListener = null;
093:
094: private Listener getToolbarListener() {
095: if (toolbarListener == null) {
096: toolbarListener = new Listener();
097: }
098: return toolbarListener;
099: }
100:
101: protected AbstractButton getOrCreateToolbarButton(int type) {
102: AbstractButton result;
103: if (type == ActionProvider.ACTION_TYPE_TOGGLE) {
104: result = new JToggleButton();
105: } else if (type == ActionProvider.ACTION_TYPE_ITEM) {
106: result = new JButton();
107: } else if (type == ActionProvider.ACTION_TYPE_SUBCONTEXT) {
108: result = new JMenu();
109: } else {
110: result = null;
111: }
112: if (result != null) {
113: result.addActionListener(getToolbarButtonListener());
114: }
115: //Otherwise presumably a wrapper or subclass will produce the result
116: return result;
117: }
118:
119: public void update(String containerCtx) {
120: // System.err.println("ToolbarFactory update " + containerCtx);
121: JToolBar tb = (JToolBar) mappings.get(munge(containerCtx));
122: synchronized (tb.getTreeLock()) {
123: // System.err.println("Toolbar to update: " + tb);
124: ActionProvider provider = getEngine().getActionProvider();
125: if (tb != null) {
126: Component[] c = tb.getComponents();
127: for (int i = 0; i < c.length; i++) {
128: if (c[i] instanceof AbstractButton) {
129: AbstractButton b = (AbstractButton) c[i];
130: String action = (String) b
131: .getClientProperty(KEY_ACTION);
132: configureToolbarButton(b, containerCtx, action,
133: provider, getEngine()
134: .getContextProvider()
135: .getContext());
136: }
137: }
138:
139: } else {
140: System.err
141: .println("Asked to update non existent toolbar "
142: + containerCtx);
143: }
144: }
145: }
146:
147: protected void populateToolbar(String containerCtx, JToolBar toolbar) {
148: // System.err.println("AbstractToolbarFactory.populateToolbar");
149: ActionProvider provider = getEngine().getActionProvider();
150: String[] names = provider.getActionNames(containerCtx);
151: /// System.err.println("Names are " + Arrays.asList(names));
152: for (int i = 0; i < names.length; i++) {
153: int type = provider.getActionType(names[i], containerCtx);
154: AbstractButton item = getOrCreateToolbarButton(type);
155: configureToolbarButton(item, containerCtx, names[i],
156: provider, null);
157: toolbar.add(item);
158: }
159: addMapping(containerCtx, toolbar);
160: getEngine().notifyToolbarShown(containerCtx, toolbar); //XXX listener should do this
161: }
162:
163: private void configureToolbarButton(AbstractButton item,
164: String containerCtx, String action,
165: ActionProvider provider, Map ctx) {
166: item.setFocusable(false);
167: item.setName(action);
168: item.putClientProperty(KEY_ACTION, action);
169: item.setToolTipText(provider.getDisplayName(action,
170: containerCtx));
171: // item.setToolTipText(provider.getDescription(action, containerCtx));
172: int state = ctx == null ? ActionProvider.STATE_VISIBLE
173: : provider.getState(action, containerCtx, ctx);
174: boolean enabled = (state & ActionProvider.STATE_ENABLED) != 0;
175: item.setEnabled(enabled);
176: boolean visible = (state & ActionProvider.STATE_VISIBLE) != 0;
177: item.setVisible(visible);
178: boolean toggled = (state & ActionProvider.STATE_SELECTED) != 0;
179: item.setSelected(toggled);
180: // item.setMnemonic(provider.getMnemonic(action, containerCtx));
181: // item.setDisplayedMnemonicIndex(provider.getMnemonicIndex(action, containerCtx));
182: item.setIcon(provider.getIcon(action, containerCtx,
183: BeanInfo.ICON_COLOR_16x16));
184: }
185:
186: protected void depopulateToolbar(String containerCtx,
187: JToolBar toolbar) {
188: toolbar.removeAll();
189: detachFromToolbar(containerCtx, toolbar);
190: }
191:
192: private ButtonListener blistener = null;
193:
194: private ButtonListener getToolbarButtonListener() {
195: if (blistener == null) {
196: blistener = new ButtonListener();
197: }
198: return blistener;
199: }
200:
201: private class ButtonListener implements ActionListener {
202: public void actionPerformed(ActionEvent ae) {
203: JComponent item = (JComponent) ae.getSource();
204: String actionCommand = (String) item
205: .getClientProperty(KEY_ACTION);
206: String context = (String) item
207: .getClientProperty(KEY_CONTAINERCTX);
208:
209: getEngine().notifyWillPerform(actionCommand, context);
210:
211: Action action = getEngine().getAction(context,
212: actionCommand);
213:
214: if (action.isEnabled()) {
215: ActionEvent event = new ActionEvent(item,
216: ActionEvent.ACTION_PERFORMED, actionCommand);
217: action.actionPerformed(event);
218: }
219:
220: getEngine().notifyPerformed(actionCommand, context);
221: }
222: }
223:
224: private class Listener extends ComponentAdapter implements
225: ContainerListener {
226:
227: public void componentAdded(ContainerEvent e) {
228: JComponent jc = (JComponent) e.getChild();
229: JToolBar tb = (JToolBar) e.getContainer();
230: String ctx = (String) tb
231: .getClientProperty(KEY_CONTAINERCTX);
232: jc.putClientProperty(KEY_CONTAINERCTX, ctx);
233: }
234:
235: public void componentHidden(ComponentEvent e) {
236: JToolBar jtb = (JToolBar) e.getComponent();
237: String ctx = (String) jtb
238: .getClientProperty(KEY_CONTAINERCTX);
239: depopulateToolbar(ctx, jtb);
240: }
241:
242: public void componentRemoved(ContainerEvent e) {
243: JComponent jc = (JComponent) e.getChild();
244: jc.putClientProperty(KEY_CONTAINERCTX, null);
245: }
246:
247: public void componentShown(ComponentEvent e) {
248: JToolBar jtb = (JToolBar) e.getComponent();
249: String ctx = (String) jtb
250: .getClientProperty(KEY_CONTAINERCTX);
251: populateToolbar(ctx, jtb);
252: getEngine().notifyToolbarShown(ctx, jtb);
253: }
254:
255: }
256:
257: }
|