001: /*
002: * @(#)BasicJidePopupUI.java 2/25/2005
003: *
004: * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
005: */
006:
007: package com.jidesoft.plaf.basic;
008:
009: import com.jidesoft.plaf.PopupUI;
010: import com.jidesoft.plaf.UIDefaultsLookup;
011: import com.jidesoft.popup.JidePopup;
012: import com.jidesoft.swing.Gripper;
013:
014: import javax.swing.*;
015: import javax.swing.plaf.ActionMapUIResource;
016: import javax.swing.plaf.ComponentUI;
017: import javax.swing.plaf.UIResource;
018: import java.awt.*;
019: import java.beans.PropertyChangeEvent;
020: import java.beans.PropertyChangeListener;
021:
022: /**
023: * A basic L&F implementation of Popup.
024: */
025: public class BasicJidePopupUI extends PopupUI {
026:
027: protected JidePopup _popup;
028:
029: // protected MouseInputAdapter _borderListener;
030: protected PropertyChangeListener _propertyChangeListener;
031: protected LayoutManager _dockablelFrameLayout;
032:
033: protected JComponent _northPane;
034: protected JComponent _southPane;
035: protected JComponent _westPane;
036: protected JComponent _eastPane;
037:
038: protected Gripper _titlePane; // access needs this
039:
040: private boolean keyBindingRegistered = false;
041: private boolean keyBindingActive = false;
042:
043: /////////////////////////////////////////////////////////////////////////////
044: // ComponentUI Interface Implementation methods
045: /////////////////////////////////////////////////////////////////////////////
046:
047: public static ComponentUI createUI(JComponent b) {
048: return new BasicJidePopupUI((JidePopup) b);
049: }
050:
051: public BasicJidePopupUI() {
052: }
053:
054: public BasicJidePopupUI(JidePopup f) {
055: _popup = f;
056: }
057:
058: @Override
059: public void installUI(JComponent c) {
060:
061: _popup = (JidePopup) c;
062:
063: installDefaults();
064: installListeners();
065: installComponents();
066: installKeyboardActions();
067: _popup.setOpaque(true);
068: }
069:
070: @Override
071: public void uninstallUI(JComponent c) {
072: if (c != _popup)
073: throw new IllegalComponentStateException(this
074: + " was asked to deinstall() " + c
075: + " when it only knows about " + _popup + ".");
076:
077: uninstallKeyboardActions();
078: uninstallComponents();
079: uninstallListeners();
080: uninstallDefaults();
081: _popup = null;
082: }
083:
084: protected void installDefaults() {
085: JComponent contentPane = (JComponent) _popup.getContentPane();
086: if (contentPane != null) {
087: Color bg = contentPane.getBackground();
088: if (bg instanceof UIResource)
089: contentPane.setBackground(null);
090: }
091: _popup.setLayout(_dockablelFrameLayout = createLayoutManager());
092: _popup.setBackground(UIDefaultsLookup
093: .getColor("JideButton.background"));
094:
095: LookAndFeel.installBorder(_popup, "Popup.border");
096:
097: }
098:
099: protected void installKeyboardActions() {
100: ActionMap actionMap = getActionMap();
101: SwingUtilities.replaceUIActionMap(_popup, actionMap);
102: }
103:
104: ActionMap getActionMap() {
105: ActionMap map = (ActionMap) UIDefaultsLookup
106: .get("Popup.actionMap");
107: if (map == null) {
108: map = createActionMap();
109: if (map != null) {
110: UIManager.getLookAndFeelDefaults().put(
111: "Popup.actionMap", map);
112: }
113: }
114: return map;
115: }
116:
117: ActionMap createActionMap() {
118: ActionMap map = new ActionMapUIResource();
119: // we don't use it right now. Leave it since we might use it later.
120: return map;
121: }
122:
123: protected void installComponents() {
124: setNorthPane(createNorthPane(_popup));
125: setSouthPane(createSouthPane(_popup));
126: setEastPane(createEastPane(_popup));
127: setWestPane(createWestPane(_popup));
128: }
129:
130: /*
131: * @since 1.3
132: */
133: protected void installListeners() {
134: _propertyChangeListener = createPropertyChangeListener();
135: _popup.addPropertyChangeListener(_propertyChangeListener);
136: }
137:
138: InputMap getInputMap(int condition) {
139: if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
140: return createInputMap(condition);
141: }
142: return null;
143: }
144:
145: InputMap createInputMap(int condition) {
146: if (condition == JComponent.WHEN_IN_FOCUSED_WINDOW) {
147: Object[] bindings = (Object[]) UIDefaultsLookup
148: .get("Popup.windowBindings");
149:
150: if (bindings != null) {
151: return LookAndFeel.makeComponentInputMap(_popup,
152: bindings);
153: }
154: }
155: return null;
156: }
157:
158: protected void uninstallDefaults() {
159: _dockablelFrameLayout = null;
160: _popup.setLayout(null);
161: LookAndFeel.uninstallBorder(_popup);
162: }
163:
164: protected void uninstallComponents() {
165: setNorthPane(null);
166: setSouthPane(null);
167: setEastPane(null);
168: setWestPane(null);
169: _titlePane = null;
170: }
171:
172: /*
173: * @since 1.3
174: */
175: protected void uninstallListeners() {
176: _popup.removePropertyChangeListener(_propertyChangeListener);
177: _propertyChangeListener = null;
178: }
179:
180: protected void uninstallKeyboardActions() {
181: SwingUtilities.replaceUIInputMap(_popup,
182: JComponent.WHEN_IN_FOCUSED_WINDOW, null);
183: SwingUtilities.replaceUIActionMap(_popup, null);
184:
185: }
186:
187: @Override
188: public Component getGripper() {
189: return _titlePane;
190: }
191:
192: protected LayoutManager createLayoutManager() {
193: return new PopupLayout();
194: }
195:
196: protected PropertyChangeListener createPropertyChangeListener() {
197: return new PopupPropertyChangeListener();
198: }
199:
200: @Override
201: public Dimension getPreferredSize(JComponent x) {
202: if (_popup == x && _popup.getLayout() != null)
203: return _popup.getLayout().preferredLayoutSize(x);
204: return new Dimension(100, 100);
205: }
206:
207: @Override
208: public Dimension getMinimumSize(JComponent x) {
209: if (_popup == x) {
210: return _popup.getLayout().minimumLayoutSize(x);
211: }
212: return new Dimension(0, 0);
213: }
214:
215: @Override
216: public Dimension getMaximumSize(JComponent x) {
217: return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
218: }
219:
220: /**
221: * Installs necessary mouse handlers on <code>newPane</code>
222: * and adds it to the frame.
223: * Reverse process for the <code>currentPane</code>.
224: */
225: protected void replacePane(JComponent currentPane,
226: JComponent newPane) {
227: if (currentPane != null) {
228: deinstallMouseHandlers(currentPane);
229: _popup.remove(currentPane);
230: }
231: if (newPane != null) {
232: _popup.add(newPane);
233: installMouseHandlers(newPane);
234: }
235: }
236:
237: protected void deinstallMouseHandlers(JComponent c) {
238: }
239:
240: protected void installMouseHandlers(JComponent c) {
241: }
242:
243: protected JComponent createNorthPane(JidePopup w) {
244: if (w.getGripperLocation() == SwingConstants.NORTH
245: && w.isMovable()) {
246: _titlePane = new Gripper();
247: _titlePane.setOrientation(SwingConstants.VERTICAL);
248: _titlePane.setRolloverEnabled(true);
249: _titlePane.setOpaque(true);
250: return _titlePane;
251: } else {
252: return null;
253: }
254: }
255:
256: protected JComponent createSouthPane(JidePopup w) {
257: if (w.getGripperLocation() == SwingConstants.SOUTH
258: && w.isMovable()) {
259: _titlePane = new Gripper();
260: _titlePane.setOrientation(SwingConstants.VERTICAL);
261: _titlePane.setRolloverEnabled(true);
262: _titlePane.setOpaque(true);
263: return _titlePane;
264: } else {
265: return null;
266: }
267: }
268:
269: protected JComponent createWestPane(JidePopup w) {
270: if (w.getGripperLocation() == SwingConstants.WEST
271: && w.isMovable()) {
272: _titlePane = new Gripper();
273: _titlePane.setOrientation(SwingConstants.HORIZONTAL);
274: _titlePane.setRolloverEnabled(true);
275: _titlePane.setOpaque(true);
276: return _titlePane;
277: } else {
278: return null;
279: }
280: }
281:
282: protected JComponent createEastPane(JidePopup w) {
283: if (w.getGripperLocation() == SwingConstants.EAST
284: && w.isMovable()) {
285: _titlePane = new Gripper();
286: _titlePane.setOrientation(SwingConstants.HORIZONTAL);
287: _titlePane.setRolloverEnabled(true);
288: _titlePane.setOpaque(true);
289: return _titlePane;
290: } else {
291: return null;
292: }
293: }
294:
295: protected final boolean isKeyBindingRegistered() {
296: return keyBindingRegistered;
297: }
298:
299: protected final void setKeyBindingRegistered(boolean b) {
300: keyBindingRegistered = b;
301: }
302:
303: public final boolean isKeyBindingActive() {
304: return keyBindingActive;
305: }
306:
307: protected final void setKeyBindingActive(boolean b) {
308: keyBindingActive = b;
309: }
310:
311: protected void setupMenuOpenKey() {
312: // PENDING(hania): Why are these WHEN_IN_FOCUSED_WINDOWs? Shouldn't
313: // they be WHEN_ANCESTOR_OF_FOCUSED_COMPONENT?
314: // Also, no longer registering on the desktopicon, the previous
315: // action did nothing.
316: InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
317: SwingUtilities.replaceUIInputMap(_popup,
318: JComponent.WHEN_IN_FOCUSED_WINDOW, map);
319: //ActionMap actionMap = getActionMap();
320: //SwingUtilities.replaceUIActionMap(frame, actionMap);
321: }
322:
323: protected void setupMenuCloseKey() {
324: }
325:
326: public JComponent getNorthPane() {
327: return _northPane;
328: }
329:
330: protected void setNorthPane(JComponent c) {
331: replacePane(_northPane, c);
332: _northPane = c;
333: }
334:
335: public JComponent getSouthPane() {
336: return _southPane;
337: }
338:
339: protected void setSouthPane(JComponent c) {
340: replacePane(_southPane, c);
341: _southPane = c;
342: }
343:
344: public JComponent getWestPane() {
345: return _westPane;
346: }
347:
348: protected void setWestPane(JComponent c) {
349: replacePane(_westPane, c);
350: _westPane = c;
351: }
352:
353: public JComponent getEastPane() {
354: return _eastPane;
355: }
356:
357: protected void setEastPane(JComponent c) {
358: replacePane(_eastPane, c);
359: _eastPane = c;
360: }
361:
362: public class PopupPropertyChangeListener implements
363: PropertyChangeListener {
364: /**
365: * Detects changes in state from the Popup and handles actions.
366: */
367: public void propertyChange(PropertyChangeEvent evt) {
368: String prop = evt.getPropertyName();
369: JidePopup f = (JidePopup) evt.getSource();
370: Object newValue = evt.getNewValue();
371: Object oldValue = evt.getOldValue();
372: if (JidePopup.MOVABLE_PROPERTY.equals(prop)) {
373: f.updateUI();
374: }
375: if (JidePopup.PROPERTY_GRIPPER_LOCATION.equals(prop)) {
376: f.updateUI();
377: }
378: }
379: }
380:
381: public class PopupLayout implements LayoutManager {
382: public void addLayoutComponent(String name, Component c) {
383: }
384:
385: public void removeLayoutComponent(Component c) {
386: }
387:
388: public Dimension preferredLayoutSize(Container c) {
389: Dimension result;
390: Insets i = _popup.getInsets();
391:
392: result = new Dimension(_popup.getRootPane()
393: .getPreferredSize());
394: result.width += i.left + i.right;
395: result.height += i.top + i.bottom;
396:
397: if (getNorthPane() != null) {
398: Dimension d = getNorthPane().getPreferredSize();
399: result.width = Math.max(d.width, result.width);
400: result.height += d.height;
401: }
402:
403: if (getSouthPane() != null) {
404: Dimension d = getSouthPane().getPreferredSize();
405: result.width = Math.max(d.width, result.width);
406: result.height += d.height;
407: }
408:
409: if (getEastPane() != null) {
410: Dimension d = getEastPane().getPreferredSize();
411: result.width += d.width;
412: result.height = Math.max(d.height, result.height);
413: }
414:
415: if (getWestPane() != null) {
416: Dimension d = getWestPane().getPreferredSize();
417: result.width += d.width;
418: result.height = Math.max(d.height, result.height);
419: }
420:
421: return result;
422: }
423:
424: public Dimension minimumLayoutSize(Container c) {
425:
426: // The minimum size of the dockable frame only takes into account the
427: // _title pane since you are allowed to resize the frames to the point
428: // where just the _title pane is visible.
429: Dimension result = new Dimension();
430: if (getNorthPane() != null) {
431: result = new Dimension(getNorthPane().getMinimumSize());
432: }
433: if (getSouthPane() != null) {
434: Dimension minimumSize = getSouthPane().getMinimumSize();
435: result.width = Math
436: .max(result.width, minimumSize.width);
437: result.height += minimumSize.height;
438: }
439: if (getEastPane() != null) {
440: Dimension minimumSize = getEastPane().getMinimumSize();
441: result.width += minimumSize.width;
442: result.height = Math.max(result.height,
443: minimumSize.height);
444: }
445: if (getWestPane() != null) {
446: Dimension minimumSize = getWestPane().getMinimumSize();
447: result.width = Math
448: .max(result.width, minimumSize.width);
449: result.height += minimumSize.height;
450: }
451: Dimension alter = _popup.getContentPane().getMinimumSize();
452:
453: if (alter.width > result.width) {
454: result.width = alter.width;
455: }
456: result.height += alter.height;
457:
458: Insets i = _popup.getInsets();
459: result.width += i.left + i.right;
460: result.height += i.top + i.bottom;
461:
462: return result;
463: }
464:
465: public void layoutContainer(Container c) {
466: Insets i = _popup.getInsets();
467: int cx, cy, cw, ch;
468:
469: cx = i.left;
470: cy = i.top;
471: cw = _popup.getWidth() - i.left - i.right;
472: ch = _popup.getHeight() - i.top - i.bottom;
473:
474: if (getNorthPane() != null) {
475: getNorthPane().setVisible(true);
476: Dimension size = getNorthPane().getPreferredSize();
477: getNorthPane().setBounds(cx, cy, cw, size.height);
478: cy += size.height;
479: ch -= size.height;
480: }
481: if (getSouthPane() != null) {
482: Dimension size = getSouthPane().getPreferredSize();
483: getSouthPane().setBounds(cx,
484: _popup.getHeight() - i.bottom - size.height,
485: cw, size.height);
486: ch -= size.height;
487: }
488: if (getWestPane() != null) {
489: Dimension size = getWestPane().getPreferredSize();
490: getWestPane().setBounds(cx, cy, size.width, ch);
491: cw -= size.width;
492: cx += size.width;
493: }
494: if (getEastPane() != null) {
495: Dimension size = getEastPane().getPreferredSize();
496: getEastPane().setBounds(cw - size.width, cy,
497: size.width, ch);
498: cw -= size.width;
499: }
500:
501: if (_popup.getRootPane() != null) {
502: _popup.getRootPane().setBounds(cx, cy, cw, ch);
503: }
504: }
505: }
506: }
|