001: /*
002: * Copyright 2006-2007 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt.
007: *
008: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
009: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
010: * the license for the specific language governing your rights and limitations.
011: *
012: * Additional Contributor(s): Martin Schmid gridvision engineering GmbH
013: */
014: package org.pentaho.reportdesigner.lib.client.commands;
015:
016: import org.jetbrains.annotations.NotNull;
017: import org.jetbrains.annotations.Nullable;
018:
019: import javax.swing.*;
020: import javax.swing.border.Border;
021: import java.awt.*;
022: import java.awt.event.ActionEvent;
023: import java.awt.event.ActionListener;
024: import java.awt.event.MouseAdapter;
025: import java.awt.event.MouseEvent;
026: import java.awt.event.MouseMotionAdapter;
027: import java.beans.PropertyChangeEvent;
028: import java.beans.PropertyChangeListener;
029: import java.util.ArrayList;
030: import java.util.Collection;
031:
032: /**
033: * User: Martin
034: * Date: 21.11.2004
035: * Time: 13:21:43
036: */
037: public class CommandDropDownToolBarButton extends CommandButton
038: implements PropertyChangeListener {
039: @NotNull
040: private String iconKey;
041:
042: @NotNull
043: private JLabel label1;
044: @NotNull
045: private JLabel label2;
046: private boolean actionDropdown;
047:
048: @Nullable
049: private Presentation lastExecutedPresentation;
050:
051: @NotNull
052: private ArrayList<Presentation> presentations;
053:
054: public CommandDropDownToolBarButton(@NotNull
055: final CommandGroup commandGroup, @NotNull
056: final Presentation presentation, @NotNull
057: String iconKey) {
058: super (presentation);
059:
060: presentations = new ArrayList<Presentation>();
061:
062: setHorizontalTextPosition(CommandButton.CENTER);
063: setVerticalTextPosition(CommandButton.BOTTOM);
064: setRolloverEnabled(true);
065: setMargin(new Insets(4, 4, 4, 4));
066:
067: label1 = new JLabel();
068: label2 = new JLabel(new ImageIcon(
069: CommandDropDownToolBarButton.class
070: .getResource("DropDownIcon.png")));//NON-NLS
071: label2.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
072:
073: setLayout(new ButtonLayout());
074: add(label1);
075: add(label2);
076:
077: this .iconKey = iconKey;
078:
079: addListener(commandGroup, presentation);
080:
081: setFocusable(false);
082:
083: addMouseListener(new MouseAdapter() {
084: public void mouseEntered(@NotNull
085: MouseEvent e) {
086: Presentation lastExecutedPresentation = CommandDropDownToolBarButton.this .lastExecutedPresentation;
087: if (lastExecutedPresentation != null) {
088: lastExecutedPresentation
089: .getCommandApplicationRoot().setStatusText(
090: lastExecutedPresentation
091: .getDescription());
092: } else {
093: presentation.getCommandApplicationRoot()
094: .setStatusText(
095: presentation.getDescription());
096: }
097: }
098:
099: public void mouseExited(@NotNull
100: MouseEvent e) {
101: presentation.getCommandApplicationRoot()
102: .clearStatusText();
103: }
104: });
105:
106: label1.addMouseMotionListener(new MouseMotionAdapter() {
107: public void mouseDragged(@NotNull
108: MouseEvent e) {
109: MouseEvent me = SwingUtilities.convertMouseEvent(
110: label1, e, CommandDropDownToolBarButton.this );
111: CommandDropDownToolBarButton.this .dispatchEvent(me);
112: }
113:
114: public void mouseMoved(@NotNull
115: MouseEvent e) {
116: MouseEvent me = SwingUtilities.convertMouseEvent(
117: label1, e, CommandDropDownToolBarButton.this );
118: CommandDropDownToolBarButton.this .dispatchEvent(me);
119: }
120: });
121: label1.addMouseListener(new MouseAdapter() {
122: public void mouseEntered(@NotNull
123: MouseEvent e) {
124: MouseEvent me = SwingUtilities.convertMouseEvent(
125: label1, e, CommandDropDownToolBarButton.this );
126: CommandDropDownToolBarButton.this .dispatchEvent(me);
127: }
128:
129: public void mouseExited(@NotNull
130: MouseEvent e) {
131: MouseEvent me = SwingUtilities.convertMouseEvent(
132: label1, e, CommandDropDownToolBarButton.this );
133: CommandDropDownToolBarButton.this .dispatchEvent(me);
134: }
135:
136: public void mouseClicked(@NotNull
137: MouseEvent e) {
138: MouseEvent me = SwingUtilities.convertMouseEvent(
139: label1, e, CommandDropDownToolBarButton.this );
140: CommandDropDownToolBarButton.this .dispatchEvent(me);
141: }
142:
143: public void mousePressed(@NotNull
144: MouseEvent e) {
145: MouseEvent me = SwingUtilities.convertMouseEvent(
146: label1, e, CommandDropDownToolBarButton.this );
147: CommandDropDownToolBarButton.this .dispatchEvent(me);
148: }
149:
150: public void mouseReleased(@NotNull
151: MouseEvent e) {
152: MouseEvent me = SwingUtilities.convertMouseEvent(
153: label1, e, CommandDropDownToolBarButton.this );
154: CommandDropDownToolBarButton.this .dispatchEvent(me);
155: }
156: });
157:
158: label2.addMouseMotionListener(new MouseMotionAdapter() {
159: public void mouseDragged(@NotNull
160: MouseEvent e) {
161: MouseEvent me = SwingUtilities.convertMouseEvent(
162: label2, e, CommandDropDownToolBarButton.this );
163: CommandDropDownToolBarButton.this .dispatchEvent(me);
164: }
165:
166: public void mouseMoved(@NotNull
167: MouseEvent e) {
168: MouseEvent me = SwingUtilities.convertMouseEvent(
169: label2, e, CommandDropDownToolBarButton.this );
170: CommandDropDownToolBarButton.this .dispatchEvent(me);
171: }
172: });
173: label2.addMouseListener(new MouseAdapter() {
174: public void mouseEntered(@NotNull
175: MouseEvent e) {
176: actionDropdown = true;
177: MouseEvent me = SwingUtilities.convertMouseEvent(
178: label2, e, CommandDropDownToolBarButton.this );
179: CommandDropDownToolBarButton.this .dispatchEvent(me);
180: label2.setBorder(new DividerBorder());
181: }
182:
183: public void mouseExited(@NotNull
184: MouseEvent e) {
185: actionDropdown = false;
186: MouseEvent me = SwingUtilities.convertMouseEvent(
187: label2, e, CommandDropDownToolBarButton.this );
188: CommandDropDownToolBarButton.this .dispatchEvent(me);
189: label2.setBorder(BorderFactory.createEmptyBorder(0, 2,
190: 0, 0));
191: }
192:
193: public void mouseClicked(@NotNull
194: MouseEvent e) {
195: MouseEvent me = SwingUtilities.convertMouseEvent(
196: label2, e, CommandDropDownToolBarButton.this );
197: CommandDropDownToolBarButton.this .dispatchEvent(me);
198: }
199:
200: public void mousePressed(@NotNull
201: MouseEvent e) {
202: MouseEvent me = SwingUtilities.convertMouseEvent(
203: label2, e, CommandDropDownToolBarButton.this );
204: CommandDropDownToolBarButton.this .dispatchEvent(me);
205: }
206:
207: public void mouseReleased(@NotNull
208: MouseEvent e) {
209: MouseEvent me = SwingUtilities.convertMouseEvent(
210: label2, e, CommandDropDownToolBarButton.this );
211: CommandDropDownToolBarButton.this .dispatchEvent(me);
212: }
213: });
214:
215: //noinspection ConstantConditions
216: if (commandGroup != null) {
217: addActionListener(new ActionListener() {
218: public void actionPerformed(@NotNull
219: ActionEvent e) {
220: Presentation lastExecutedPresentation = CommandDropDownToolBarButton.this .lastExecutedPresentation;
221: if (actionDropdown
222: || lastExecutedPresentation == null
223: || !lastExecutedPresentation.isEnabled()) {
224: CommandDropDownPopupMenu commandPopupMenu = new CommandDropDownPopupMenu(
225: presentation
226: .getCommandApplicationRoot(),
227: commandGroup, CommandSettings
228: .getInstance()
229: .getToolbarIconKey(),
230: CommandDropDownToolBarButton.this );
231: JPopupMenu popupMenu = commandPopupMenu
232: .getJPopupMenu();
233: CommandDropDownToolBarButton button = CommandDropDownToolBarButton.this ;
234: popupMenu.show(button, 0, button.getHeight());
235: } else {
236: //execute seleted command
237: if (lastExecutedPresentation.isEnabled()) {
238: DataProvider dataProvider = CommandManager
239: .getCurrentCommandProvider();
240: presentation.getCommandApplicationRoot()
241: .clearStatusText();
242: lastExecutedPresentation
243: .getCommand()
244: .execute(
245: new DefaultCommandEvent(
246: null,
247: dataProvider
248: .getDataContext(),
249: dataProvider
250: .getPlace(),
251: presentation));
252: CommandManager.dataProviderChanged();
253: }
254: }
255: }
256:
257: });
258: }
259:
260: update();
261: }
262:
263: private void addListener(@NotNull
264: final CommandGroup commandGroup, @NotNull
265: final Presentation presentation) {
266: Command[] children = commandGroup.getChildren();
267: for (Command command : children) {
268: Presentation pres = command.getTemplatePresentation()
269: .getCopy(presentation.getCommandApplicationRoot());
270: presentations.add(pres);
271:
272: if (pres.isEnabled() && lastExecutedPresentation == null) {
273: setLastExecutedPresentation(pres);
274: } else if (pres.isEnabled()
275: && lastExecutedPresentation != null
276: && !lastExecutedPresentation.isEnabled()) {
277: setLastExecutedPresentation(pres);
278: }
279: pres.addPropertyChangeListener(this );
280:
281: if (command instanceof CommandGroup) {
282: CommandGroup group = (CommandGroup) command;
283: addListener(group, presentation);
284: }
285: }
286: }
287:
288: public void propertyChange(@NotNull
289: PropertyChangeEvent evt) {
290:
291: Presentation lastExecutedPresentation1 = lastExecutedPresentation;
292: if (lastExecutedPresentation1 == null) {
293: //search an enable presentation
294: Presentation p = (Presentation) evt.getSource();
295: if (p.isEnabled()) {
296: lastExecutedPresentation = p;
297: update();
298: }
299: } else {
300: Presentation p = (Presentation) evt.getSource();
301: if (!lastExecutedPresentation1.isEnabled() && p.isEnabled()) {
302: lastExecutedPresentation = p;
303: update();
304: }
305: }
306: }
307:
308: public void setLastExecutedPresentation(@Nullable
309: Presentation lastExecutedPresentation) {
310: this .lastExecutedPresentation = lastExecutedPresentation;
311: if (lastExecutedPresentation != null) {
312: lastExecutedPresentation.addPropertyChangeListener(this );
313: update();
314: }
315: }
316:
317: protected void update() {
318:
319: Presentation presentation = getPresentation();
320:
321: setEnabled(presentation.isEnabled());
322: setVisible(presentation.isVisible());
323:
324: if (!presentation.isEnabled() || !presentation.isVisible()) {
325: label1.setVisible(presentation.isVisible());
326: label1.setEnabled(presentation.isEnabled());
327:
328: label2.setEnabled(presentation.isEnabled());
329: label2.setVisible(presentation.isVisible());
330: }
331:
332: Presentation lastExecutedPresentation = this .lastExecutedPresentation;
333: if (lastExecutedPresentation != null) {
334: label1.setIcon(lastExecutedPresentation.getIcon(iconKey));
335: label1.setEnabled(lastExecutedPresentation.isEnabled());
336: label1.setToolTipText(lastExecutedPresentation.getText());
337: } else {
338: label1.setIcon(presentation.getIcon(iconKey));
339: label1.setEnabled(presentation.isEnabled());
340: label1.setToolTipText(presentation.getText());
341: }
342:
343: }
344:
345: @NotNull
346: public Collection<? extends Presentation> getPresentations() {
347: return presentations;
348: }
349:
350: private static class DividerBorder implements Border {
351: @NotNull
352: private Insets insets;
353:
354: private DividerBorder() {
355: insets = new Insets(0, 2, 0, 0);
356: }
357:
358: public void paintBorder(@NotNull
359: Component c, @NotNull
360: Graphics g, int x, int y, int width, int height) {
361: Color c1 = c.getBackground().darker();
362: Color c2 = c.getBackground().brighter();
363:
364: g.translate(x, y);
365: g.setColor(c1);
366: g.drawLine(0, 2, 0, height - 4);
367:
368: g.setColor(c2);
369: g.drawLine(1, 2, 1, height - 4);
370:
371: g.translate(-x, -y);
372: }
373:
374: @NotNull
375: public Insets getBorderInsets(@NotNull
376: Component c) {
377: return insets;
378: }
379:
380: public boolean isBorderOpaque() {
381: return false;
382: }
383: }
384:
385: private class ButtonLayout implements LayoutManager2 {
386: public void addLayoutComponent(@NotNull
387: Component comp, @Nullable
388: Object constraints) {
389: }
390:
391: @NotNull
392: public Dimension maximumLayoutSize(@NotNull
393: Container target) {
394: JButton button = (JButton) target;
395: return getPreferredButtonSize(button, button
396: .getIconTextGap());
397: }
398:
399: public float getLayoutAlignmentX(@NotNull
400: Container target) {
401: return 0;
402: }
403:
404: public float getLayoutAlignmentY(@NotNull
405: Container target) {
406: return 0;
407: }
408:
409: public void invalidateLayout(@NotNull
410: Container target) {
411: }
412:
413: public void addLayoutComponent(@NotNull
414: String name, @NotNull
415: Component comp) {
416: }
417:
418: public void removeLayoutComponent(@NotNull
419: Component comp) {
420: }
421:
422: @NotNull
423: public Dimension preferredLayoutSize(@NotNull
424: Container parent) {
425: JButton button = (JButton) parent;
426: return getPreferredButtonSize(button, button
427: .getIconTextGap());
428: }
429:
430: @NotNull
431: public Dimension minimumLayoutSize(@NotNull
432: Container parent) {
433: JButton button = (JButton) parent;
434: return getPreferredButtonSize(button, button
435: .getIconTextGap());
436: }
437:
438: public void layoutContainer(@NotNull
439: Container parent) {
440: int count = parent.getComponentCount();
441: if (count == 2) {
442: JButton button = (JButton) parent;
443: Insets insets = button.getInsets();
444: label1.setBounds(insets.left, insets.top,
445: button.getWidth()
446: - (insets.left + label2
447: .getPreferredSize().width),
448: button.getHeight()
449: - (insets.top + insets.bottom));
450: label2.setBounds(button.getWidth()
451: - (label2.getPreferredSize().width), 0, label2
452: .getPreferredSize().width, button.getHeight());
453: }
454: }
455:
456: @NotNull
457: public Dimension getPreferredButtonSize(@NotNull
458: AbstractButton b, int textIconGap) {
459:
460: Rectangle iconRL1 = new Rectangle();
461: Rectangle textRL1 = new Rectangle();
462: Rectangle viewRL1 = new Rectangle(Short.MAX_VALUE,
463: Short.MAX_VALUE);
464:
465: SwingUtilities.layoutCompoundLabel(label1, label1
466: .getFontMetrics(label1.getFont()),
467: label1.getText(), label1.getIcon(), label1
468: .getVerticalAlignment(), label1
469: .getHorizontalAlignment(), label1
470: .getVerticalTextPosition(), label1
471: .getHorizontalTextPosition(), viewRL1,
472: iconRL1, textRL1, (label1.getText() == null ? 0
473: : textIconGap));
474:
475: Rectangle iconRL2 = new Rectangle();
476: Rectangle textRL2 = new Rectangle();
477: Rectangle viewRL2 = new Rectangle(Short.MAX_VALUE,
478: Short.MAX_VALUE);
479:
480: SwingUtilities.layoutCompoundLabel(label2, label2
481: .getFontMetrics(label2.getFont()),
482: label2.getText(), label2.getIcon(), label2
483: .getVerticalAlignment(), label2
484: .getHorizontalAlignment(), label2
485: .getVerticalTextPosition(), label2
486: .getHorizontalTextPosition(), viewRL2,
487: iconRL2, textRL2, (label2.getText() == null ? 0
488: : textIconGap));
489:
490: /* The preferred size of the button is the size of
491: * the text and icon rectangles plus the buttons insets.
492: */
493:
494: Rectangle r1 = iconRL1.union(textRL1);
495: Rectangle r2 = iconRL2.union(textRL2);
496:
497: Insets insets = b.getInsets();
498: r1.width += r2.width + insets.left + insets.right;
499: r1.height += insets.top + insets.bottom;
500:
501: return r1.getSize();
502: }
503:
504: }
505:
506: }
|