001: /*
002: * The contents of this file are subject to the Mozilla Public License
003: * Version 1.1 (the "License"); you may not use this file except in
004: * compliance with the License. You may obtain a copy of the License at
005: * http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
009: * License for the specific language governing rights and limitations
010: * under the License.
011: *
012: * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
013: *
014: * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
015: * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
016: *
017: * Contributor(s):
018: * Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
019: *
020: * If you didn't download this code from the following link, you should check
021: * if you aren't using an obsolete version: http://www.isqlviewer.com
022: */
023: package org.isqlviewer.ui;
024:
025: import java.awt.Color;
026: import java.awt.GridBagConstraints;
027: import java.awt.Insets;
028: import java.awt.event.ActionEvent;
029: import java.awt.event.KeyEvent;
030:
031: import javax.swing.AbstractAction;
032: import javax.swing.AbstractButton;
033: import javax.swing.Action;
034: import javax.swing.ActionMap;
035: import javax.swing.ButtonGroup;
036: import javax.swing.JButton;
037: import javax.swing.JMenu;
038: import javax.swing.JMenuItem;
039: import javax.swing.JRadioButtonMenuItem;
040: import javax.swing.JToolBar;
041: import javax.swing.KeyStroke;
042: import javax.swing.text.DefaultEditorKit;
043: import javax.swing.text.JTextComponent;
044: import javax.swing.text.Keymap;
045: import javax.swing.undo.UndoManager;
046:
047: import org.isqlviewer.swing.JTextPopup;
048: import org.isqlviewer.swing.SwingUtilities;
049: import org.isqlviewer.swing.action.CustomAction;
050: import org.isqlviewer.swing.action.SwingEventManager;
051: import org.isqlviewer.util.BasicUtilities;
052: import org.isqlviewer.util.LoggableObject;
053:
054: /**
055: * @author Mark A. Kobold <mkobold at isqlviewer dot com>
056: * @version 1.0
057: */
058: public abstract class AbstractApplicationView extends LoggableObject
059: implements ApplicationView {
060:
061: private static final Insets buttonInsets = SwingUtilities.isMacOS() ? new Insets(
062: 2, 3, 2, 3)
063: : new Insets(1, 1, 1, 1);
064: private static final JTextPopup textPopup = new JTextPopup();
065:
066: private static final GridBagConstraints UI_CONSTRAINT = new GridBagConstraints(
067: 0, 0, 0, 0, 0, 0, 0, 0, new Insets(1, 1, 1, 1), 0, 0);
068:
069: protected JMenu createMenu(String name) {
070:
071: StringBuilder title = new StringBuilder(name);
072: int mnemonicIdx = name.indexOf('&');
073: char mnemonic = 0;
074:
075: if (mnemonicIdx > 1) {
076: // check to see if it is escaped ?
077: char previous = name.charAt(mnemonicIdx - 1);
078: char next = mnemonicIdx == name.length() ? 0 : name
079: .charAt(mnemonicIdx + 1);
080: if (previous != '&') {
081: mnemonic = next;
082: title.delete(mnemonicIdx - 1, mnemonicIdx);
083: }
084: } else if (mnemonicIdx == 0) {
085: char next = mnemonicIdx == name.length() ? 0 : name
086: .charAt(mnemonicIdx + 1);
087: if (next != '&') {
088: title.delete(mnemonicIdx, mnemonicIdx + 1);
089: mnemonic = next;
090: }
091: }
092:
093: JMenu menu = new JMenu(title.toString());
094: if (mnemonic > 0) {
095: menu.setMnemonic(mnemonic);
096: }
097: return menu;
098: }
099:
100: protected void addMenuItem(JMenu menu, Action action) {
101:
102: if (action == null)
103: return;
104: JMenuItem menuItem = menu.add(action);
105: configureMenuItem(menuItem, action);
106: }
107:
108: protected void addRadioButtonMenuItem(JMenu menu,
109: ButtonGroup group, Action a) {
110:
111: addRadioButtonMenuItem(menu, group, a, false);
112: }
113:
114: protected void addRadioButtonMenuItem(JMenu menu,
115: ButtonGroup group, Action a, boolean selected) {
116:
117: JRadioButtonMenuItem mi = new JRadioButtonMenuItem(a);
118: mi.setSelected(selected);
119: menu.add(mi);
120: group.add(mi);
121: configureMenuItem(mi, a);
122: mi.setIcon(null);
123: }
124:
125: protected void addDynamicGroupAction(JMenu menu, String icon,
126: ButtonGroup group, int key, String text) {
127:
128: CustomAction action = new CustomAction(text, key, null);
129: action.putValue(Action.NAME, text);
130: action.putValue(Action.DEFAULT, text);
131: action.putValue(CustomAction.ICON_NAME, icon);
132: addRadioButtonMenuItem(menu, group, action);
133: }
134:
135: protected void addDynamicAction(JMenu menu,
136: SwingEventManager manager, String icon, int key, String text) {
137:
138: CustomAction action = new CustomAction(text, key, manager);
139: action.putValue(Action.NAME, text);
140: action.putValue(Action.DEFAULT, text);
141: action.putValue(Action.ACTION_COMMAND_KEY, text);
142: action.putValue(CustomAction.ICON_NAME, icon);
143: if ((menu.getMenuComponentCount() >= 0)
144: && (menu.getMenuComponentCount() <= 9)) {
145: char code = Character.forDigit(
146: menu.getMenuComponentCount(), 10);
147: KeyStroke ks = KeyStroke.getKeyStroke(code, BasicUtilities
148: .getCommandMask(), true);
149: action.putValue(Action.ACCELERATOR_KEY, ks);
150: }
151: addMenuItem(menu, action);
152: }
153:
154: protected void configureMenuItem(JMenuItem menuItem, Action action) {
155:
156: String value = null;
157: KeyStroke ks = (KeyStroke) action
158: .getValue(Action.ACCELERATOR_KEY);
159: if (ks != null) {
160: menuItem.setAccelerator(ks);
161: }
162:
163: value = (String) action.getValue(Action.DEFAULT);
164: if (value != null) {
165: menuItem.setText(value);
166: } else {
167: menuItem.setText("<!--NULL--!>");
168: menuItem.setForeground(Color.RED);
169: }
170: value = (String) action.getValue(CustomAction.ICON_NAME);
171: if (value != null) {
172: menuItem
173: .setIcon(SwingUtilities.loadIconResource(value, 16));
174: } else {
175: menuItem.setIcon((SwingUtilities.loadIconResource("spacer",
176: 16)));
177: }
178: }
179:
180: protected void addButton(JToolBar toolbar,
181: SwingEventManager manager, Action action) {
182:
183: if (action == null || toolbar == null) {
184: return;
185: }
186: JButton button = toolbar.add(action);
187: configureButton(manager, button, action);
188: }
189:
190: /**
191: * Helper method to configure the button
192: */
193: protected void configureButton(SwingEventManager manager,
194: AbstractButton button, Action action) {
195:
196: if (action != null) {
197: Object actionID = action.getValue(CustomAction.ACTION_ID);
198: button.setActionCommand(actionID == null ? "-1" : actionID
199: .toString());
200: button.setText("");
201: String s = (String) action.getValue(CustomAction.ICON_NAME);
202: button.setIcon(SwingUtilities.loadIconResource(s, 16));
203: }
204:
205: button.setAlignmentY(0.5f);
206: button.setBorderPainted(!SwingUtilities.isMacOS());
207: button.setFocusPainted(false);
208: button.setMargin(buttonInsets);
209: if (manager != null) {
210: button.addMouseListener(manager);
211: }
212: }
213:
214: protected static final void unlocalizeTextComponent(
215: JTextComponent txt, UndoManager mgr) {
216:
217: textPopup.removeJTextComponent(txt);
218: if (mgr != null) {
219: Keymap map = txt.getKeymap();
220: KeyStroke ks = null;
221:
222: ks = SwingUtilities.createKeyStroke(KeyEvent.VK_Z,
223: SwingUtilities.MENU_SHORTCUT_MASK);
224: map.removeKeyStrokeBinding(ks);
225: ks = SwingUtilities.createKeyStroke(KeyEvent.VK_Y,
226: SwingUtilities.MENU_SHORTCUT_MASK);
227: map.removeKeyStrokeBinding(ks);
228: }
229: }
230:
231: /**
232: * Ensures the editor kit for the given text component is using standard clipboard accelerators.
233: * <p>
234: * This will also install the {ctrl|command}-[Y-Z] if the given undo manager is null.
235: *
236: * @param txt to localize.
237: * @param mgr if undo support is enabled for this txt component.
238: */
239: protected static final void localizeTextComponent(
240: JTextComponent txt, UndoManager mgr) {
241:
242: ActionMap am = txt.getActionMap();
243: Keymap map = txt.getKeymap();
244: Action a = null;
245: KeyStroke ks = null;
246:
247: a = am.get(DefaultEditorKit.cutAction);
248: ks = SwingUtilities.createKeyStroke(KeyEvent.VK_X,
249: SwingUtilities.MENU_SHORTCUT_MASK);
250: map.addActionForKeyStroke(ks, a);
251: a = am.get(DefaultEditorKit.copyAction);
252: ks = SwingUtilities.createKeyStroke(KeyEvent.VK_C,
253: SwingUtilities.MENU_SHORTCUT_MASK);
254: map.addActionForKeyStroke(ks, a);
255: a = am.get(DefaultEditorKit.pasteAction);
256: ks = SwingUtilities.createKeyStroke(KeyEvent.VK_V,
257: SwingUtilities.MENU_SHORTCUT_MASK);
258: map.addActionForKeyStroke(ks, a);
259: a = am.get(DefaultEditorKit.selectAllAction);
260: ks = SwingUtilities.createKeyStroke(KeyEvent.VK_A,
261: SwingUtilities.MENU_SHORTCUT_MASK);
262: map.addActionForKeyStroke(ks, a);
263:
264: textPopup.addJTextComponent(txt);
265: if (mgr != null) {
266: a = new UndoTextAction(mgr);
267: ks = SwingUtilities.createKeyStroke(KeyEvent.VK_Z,
268: SwingUtilities.MENU_SHORTCUT_MASK);
269: map.addActionForKeyStroke(ks, a);
270: a = new RedoTextAction(mgr);
271: ks = SwingUtilities.createKeyStroke(KeyEvent.VK_Y,
272: SwingUtilities.MENU_SHORTCUT_MASK);
273: map.addActionForKeyStroke(ks, a);
274: }
275: }
276:
277: protected static GridBagConstraints constrain(int x, int y, int w,
278: int h, double wx, double wy, int a, int f) {
279:
280: UI_CONSTRAINT.gridx = x;
281: UI_CONSTRAINT.gridy = y;
282: UI_CONSTRAINT.gridwidth = w;
283: UI_CONSTRAINT.gridheight = h;
284: UI_CONSTRAINT.weightx = wx;
285: UI_CONSTRAINT.weighty = wy;
286: UI_CONSTRAINT.anchor = a;
287: UI_CONSTRAINT.fill = f;
288: return UI_CONSTRAINT;
289: }
290:
291: public static class UndoTextAction extends AbstractAction {
292:
293: private static final long serialVersionUID = 1L;
294: private UndoManager um = null;
295:
296: public UndoTextAction(UndoManager mgr) {
297:
298: um = mgr;
299: }
300:
301: public void actionPerformed(ActionEvent e) {
302:
303: try {
304: um.undo();
305: } catch (Throwable t) {
306: // beep();
307: }
308: }
309: }
310:
311: public static class RedoTextAction extends AbstractAction {
312:
313: private static final long serialVersionUID = 1L;
314: private UndoManager um = null;
315:
316: public RedoTextAction(UndoManager mgr) {
317:
318: um = mgr;
319: }
320:
321: public void actionPerformed(ActionEvent e) {
322:
323: try {
324: um.redo();
325: } catch (Throwable t) {
326: // beep();
327: }
328: }
329: }
330: }
|