001: /**
002: * ========================================
003: * JFreeReport : a free Java report library
004: * ========================================
005: *
006: * Project Info: http://reporting.pentaho.org/
007: *
008: * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors.
009: *
010: * This library is free software; you can redistribute it and/or modify it under the terms
011: * of the GNU Lesser General Public License as published by the Free Software Foundation;
012: * either version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
015: * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: * See the GNU Lesser General Public License for more details.
017: *
018: * You should have received a copy of the GNU Lesser General Public License along with this
019: * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
020: * Boston, MA 02111-1307, USA.
021: *
022: * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
023: * in the United States and other countries.]
024: *
025: * ------------
026: * $Id: PreviewPaneUtilities.java 3525 2007-10-16 11:43:48Z tmorgner $
027: * ------------
028: * (C) Copyright 2000-2005, by Object Refinery Limited.
029: * (C) Copyright 2005-2007, by Pentaho Corporation.
030: */package org.jfree.report.modules.gui.swing.preview;
031:
032: import java.awt.Component;
033: import java.awt.FlowLayout;
034: import java.awt.Insets;
035: import java.awt.event.ActionEvent;
036: import java.util.ArrayList;
037: import java.util.Arrays;
038: import java.util.HashMap;
039: import java.util.Iterator;
040: import javax.swing.AbstractAction;
041: import javax.swing.Action;
042: import javax.swing.Icon;
043: import javax.swing.JButton;
044: import javax.swing.JComboBox;
045: import javax.swing.JMenu;
046: import javax.swing.JPanel;
047: import javax.swing.JToolBar;
048:
049: import org.jfree.report.modules.gui.common.DefaultIconTheme;
050: import org.jfree.report.modules.gui.common.IconTheme;
051: import org.jfree.report.modules.gui.swing.common.ActionFactory;
052: import org.jfree.report.modules.gui.swing.common.ActionPlugin;
053: import org.jfree.report.modules.gui.swing.common.ActionPluginMenuComparator;
054: import org.jfree.report.modules.gui.swing.common.DefaultActionFactory;
055: import org.jfree.report.modules.gui.swing.common.ExportActionPlugin;
056: import org.jfree.report.modules.gui.swing.common.SwingCommonModule;
057: import org.jfree.report.modules.gui.swing.common.SwingGuiContext;
058: import org.jfree.report.modules.gui.swing.preview.actions.ControlAction;
059: import org.jfree.report.modules.gui.swing.preview.actions.ControlActionPlugin;
060: import org.jfree.report.modules.gui.swing.preview.actions.ExportAction;
061: import org.jfree.report.modules.gui.swing.preview.actions.ZoomAction;
062: import org.jfree.report.modules.gui.swing.preview.actions.ZoomListActionPlugin;
063: import org.jfree.report.util.TextUtilities;
064: import org.jfree.ui.FloatingButtonEnabler;
065: import org.jfree.ui.KeyedComboBoxModel;
066: import org.jfree.ui.action.ActionButton;
067: import org.jfree.ui.action.ActionMenuItem;
068: import org.jfree.util.Configuration;
069: import org.jfree.util.Log;
070: import org.jfree.util.ObjectUtilities;
071:
072: /**
073: * Creation-Date: 17.11.2006, 15:06:51
074: *
075: * @author Thomas Morgner
076: */
077: public class PreviewPaneUtilities {
078: /**
079: * A zoom select action.
080: */
081: private static class ZoomSelectAction extends AbstractAction {
082: private KeyedComboBoxModel source;
083: private PreviewPane pane;
084:
085: /**
086: * Creates a new action.
087: */
088: private ZoomSelectAction(final KeyedComboBoxModel source,
089: final PreviewPane pane) {
090: this .source = source;
091: this .pane = pane;
092: }
093:
094: /**
095: * Invoked when an action occurs.
096: *
097: * @param e the event.
098: */
099: public void actionPerformed(final ActionEvent e) {
100: final Double selected = (Double) source.getSelectedKey();
101: if (selected != null) {
102: pane.setZoom(selected.doubleValue());
103: } else {
104: Log.warn("No selected key! : " + pane.getZoom());
105: }
106: }
107: }
108:
109: private static final String ICON_THEME_CONFIG_KEY = "org.jfree.report.modules.gui.common.IconTheme";
110: private static final String ACTION_FACTORY_CONFIG_KEY = "org.jfree.report.modules.gui.swing.preview.ActionFactory";
111: private static final String CATEGORY_PREFIX = "org.jfree.report.modules.gui.swing.category.";
112:
113: private PreviewPaneUtilities() {
114: }
115:
116: public static JMenu createMenu(final ActionCategory cat) {
117: final JMenu menu = new JMenu();
118: menu.setText(cat.getDisplayName());
119: final Integer mnemonicKey = cat.getMnemonicKey();
120: if (mnemonicKey != null) {
121: menu.setMnemonic(mnemonicKey.intValue());
122: }
123: final String toolTip = cat.getShortDescription();
124: if (toolTip != null && toolTip.length() > 0) {
125: menu.setToolTipText(toolTip);
126: }
127: return menu;
128: }
129:
130: public static int buildMenu(final JMenu menu,
131: final ActionPlugin[] actions, final PreviewPane pane) {
132: if (actions.length == 0) {
133: return 0;
134: }
135:
136: Arrays.sort(actions, new ActionPluginMenuComparator());
137: boolean separatorPending = false;
138: int count = 0;
139: for (int i = 0; i < actions.length; i++) {
140: final ActionPlugin actionPlugin = actions[i];
141: if (actionPlugin.isAddToMenu() == false) {
142: continue;
143: }
144:
145: if (count > 0 && separatorPending) {
146: menu.addSeparator();
147: separatorPending = false;
148: }
149:
150: if (actionPlugin instanceof ExportActionPlugin) {
151: final ExportActionPlugin exportPlugin = (ExportActionPlugin) actionPlugin;
152: final ExportAction action = new ExportAction(
153: exportPlugin, pane);
154: menu.add(new ActionMenuItem(action));
155: count += 1;
156: } else if (actionPlugin instanceof ControlActionPlugin) {
157: final ControlActionPlugin controlPlugin = (ControlActionPlugin) actionPlugin;
158: final ControlAction action = new ControlAction(
159: controlPlugin, pane);
160: menu.add(new ActionMenuItem(action));
161: count += 1;
162: } else if (actionPlugin instanceof ZoomListActionPlugin) {
163: buildViewMenu(menu, pane);
164: }
165:
166: if (actionPlugin.isSeparated()) {
167: separatorPending = true;
168: }
169:
170: }
171: return count;
172: }
173:
174: private static void buildViewMenu(final JMenu zoom,
175: final PreviewPane pane) {
176: final double[] zoomFactors = pane.getZoomFactors();
177: for (int i = 0; i < zoomFactors.length; i++) {
178: final double factor = zoomFactors[i];
179: zoom.add(new ActionMenuItem(new ZoomAction(factor, pane)));
180: }
181: }
182:
183: public static void addActionsToToolBar(final JToolBar toolBar,
184: final ActionPlugin[] reportActions, final PreviewPane pane) {
185: if (reportActions == null) {
186: return;
187: }
188:
189: boolean separatorPending = false;
190: int count = 0;
191:
192: for (int i = 0; i < reportActions.length; i++) {
193: final ActionPlugin actionPlugin = reportActions[i];
194: if (actionPlugin.isAddToToolbar() == false) {
195: continue;
196: }
197:
198: if (count > 0 && separatorPending) {
199: toolBar.addSeparator();
200: separatorPending = false;
201: }
202:
203: if (actionPlugin instanceof ExportActionPlugin) {
204: final ExportActionPlugin exportPlugin = (ExportActionPlugin) actionPlugin;
205: final ExportAction action = new ExportAction(
206: exportPlugin, pane);
207: toolBar.add(createButton(action, pane
208: .getSwingGuiContext()));
209: count += 1;
210: } else if (actionPlugin instanceof ControlActionPlugin) {
211: final ControlActionPlugin controlPlugin = (ControlActionPlugin) actionPlugin;
212: final ControlAction action = new ControlAction(
213: controlPlugin, pane);
214: toolBar.add(createButton(action, pane
215: .getSwingGuiContext()));
216: count += 1;
217: } else if (actionPlugin instanceof ZoomListActionPlugin) {
218: final JPanel zoomPane = new JPanel();
219: zoomPane.setLayout(new FlowLayout(FlowLayout.LEFT));
220: zoomPane.add(createZoomSelector(pane));
221: toolBar.add(zoomPane);
222: count += 1;
223: }
224:
225: if (actionPlugin.isSeparated()) {
226: separatorPending = true;
227: }
228: }
229: }
230:
231: private static JComboBox createZoomSelector(final PreviewPane pane) {
232: final JComboBox zoomSelect = new JComboBox(pane.getZoomModel());
233: zoomSelect.addActionListener(new ZoomSelectAction(pane
234: .getZoomModel(), pane));
235: zoomSelect.setAlignmentX(Component.RIGHT_ALIGNMENT);
236: return zoomSelect;
237: }
238:
239: /**
240: * Creates a button using the given action properties for the button's
241: * initialisation.
242: *
243: * @param action the action used to set up the button.
244: * @return a button based on the supplied action.
245: */
246: private static JButton createButton(final Action action,
247: final SwingGuiContext swingGuiContext) {
248: final JButton button = new ActionButton(action);
249: boolean needText = true;
250: if (isLargeButtonsEnabled(swingGuiContext)) {
251: final Icon icon = (Icon) action
252: .getValue(SwingCommonModule.LARGE_ICON_PROPERTY);
253: if (icon != null
254: && (icon.getIconHeight() > 1 && icon
255: .getIconHeight() > 1)) {
256: button.setIcon(icon);
257: needText = false;
258: }
259: } else {
260: final Icon icon = (Icon) action.getValue(Action.SMALL_ICON);
261: if (icon != null
262: && (icon.getIconHeight() > 1 && icon
263: .getIconHeight() > 1)) {
264: button.setIcon(icon);
265: needText = false;
266: }
267: }
268:
269: if (needText) {
270: final Object value = action.getValue(Action.NAME);
271: if (value != null) {
272: button.setText(String.valueOf(value));
273: }
274: } else {
275: button.setText(null);
276: button.setMargin(new Insets(0, 0, 0, 0));
277: }
278:
279: FloatingButtonEnabler.getInstance().addButton(button);
280: return button;
281: }
282:
283: private static boolean isLargeButtonsEnabled(
284: final SwingGuiContext swingGuiContext) {
285: final Configuration configuration = swingGuiContext
286: .getConfiguration();
287: if ("true"
288: .equals(configuration
289: .getConfigProperty("org.jfree.report.modules.gui.swing.preview.LargeIcons"))) {
290: return true;
291: }
292: return false;
293: }
294:
295: public static double getNextZoomOut(final double zoom,
296: final double[] zoomFactors) {
297: if (zoom <= zoomFactors[0]) {
298: return (zoom * 2.0) / 3.0;
299: }
300:
301: final double largestZoom = zoomFactors[zoomFactors.length - 1];
302: if (zoom > largestZoom) {
303: final double linear = (zoom * 2.0) / 3.0;
304: if (linear < largestZoom) {
305: return largestZoom;
306: }
307: return linear;
308: }
309:
310: for (int i = zoomFactors.length - 1; i >= 0; i--) {
311: final double factor = zoomFactors[i];
312: if (factor < zoom) {
313: return factor;
314: }
315: }
316:
317: return (zoom * 2.0) / 3.0;
318: }
319:
320: public static double getNextZoomIn(final double zoom,
321: final double[] zoomFactors) {
322: final double largestZoom = zoomFactors[zoomFactors.length - 1];
323: if (zoom >= largestZoom) {
324: return (zoom * 1.5);
325: }
326:
327: final double smallestZoom = zoomFactors[0];
328: if (zoom < smallestZoom) {
329: final double linear = (zoom * 1.5);
330: if (linear > smallestZoom) {
331: return smallestZoom;
332: }
333: return linear;
334: }
335:
336: for (int i = 0; i < zoomFactors.length; i++) {
337: final double factor = zoomFactors[i];
338: if (factor > zoom) {
339: return factor;
340: }
341: }
342: return (zoom * 1.5);
343: }
344:
345: public static IconTheme createIconTheme(final Configuration config) {
346: final String themeClass = config
347: .getConfigProperty(ICON_THEME_CONFIG_KEY);
348: final Object maybeTheme = ObjectUtilities.loadAndInstantiate(
349: themeClass, PreviewPane.class, IconTheme.class);
350: final IconTheme iconTheme;
351: if (maybeTheme != null) {
352: iconTheme = (IconTheme) maybeTheme;
353: } else {
354: iconTheme = new DefaultIconTheme();
355: }
356: iconTheme.initialize(config);
357: return iconTheme;
358: }
359:
360: public static ActionFactory createActionFactory(
361: final Configuration config) {
362: final String factoryClass = config
363: .getConfigProperty(ACTION_FACTORY_CONFIG_KEY);
364: final Object maybeFactory = ObjectUtilities.loadAndInstantiate(
365: factoryClass, PreviewPane.class, ActionFactory.class);
366: final ActionFactory actionFactory;
367: if (maybeFactory != null) {
368: actionFactory = (ActionFactory) maybeFactory;
369: } else {
370: actionFactory = new DefaultActionFactory();
371: }
372: return actionFactory;
373: }
374:
375: public static CategoryTreeItem[] buildMenuTree(
376: final ActionCategory[] categories) {
377: final CategoryTreeItem[] tree = new CategoryTreeItem[categories.length];
378: for (int i = 0; i < categories.length; i++) {
379: final ActionCategory category = categories[i];
380: tree[i] = new CategoryTreeItem(category);
381: }
382:
383: for (int j = 0; j < tree.length; j++) {
384: final CategoryTreeItem item = tree[j];
385: final String itemName = item.getName();
386: int parentWeight = 0;
387: CategoryTreeItem parent = null;
388: // now for each item, find the best parent item.
389: for (int k = 0; k < tree.length; k++) {
390: if (k == j) {
391: // never add yourself ..
392: continue;
393: }
394: final CategoryTreeItem treeItem = tree[k];
395: final String parentName = treeItem.getName();
396: if (itemName.startsWith(parentName) == false) {
397: continue;
398: }
399: if (parentName.length() > parentWeight) {
400: parent = treeItem;
401: parentWeight = parentName.length();
402: }
403: }
404:
405: item.setParent(parent);
406: }
407:
408: for (int j = 0; j < tree.length; j++) {
409: final CategoryTreeItem item = tree[j];
410: final CategoryTreeItem parent = item.getParent();
411: if (parent != null) {
412: parent.add(item);
413: }
414: }
415: return tree;
416: }
417:
418: public static HashMap loadActions(
419: final SwingGuiContext swingGuiContext) {
420: final HashMap actions = new HashMap();
421:
422: final Configuration configuration = swingGuiContext
423: .getConfiguration();
424: final ActionCategory[] categories = loadCategories(swingGuiContext);
425: final ActionFactory factory = PreviewPaneUtilities
426: .createActionFactory(configuration);
427:
428: for (int i = 0; i < categories.length; i++) {
429: final ActionCategory category = categories[i];
430: actions.put(category, factory.getActions(swingGuiContext,
431: category.getName()));
432: }
433: return actions;
434: }
435:
436: public static ActionCategory[] loadCategories(
437: final SwingGuiContext swingGuiContext) {
438: final ArrayList categories = new ArrayList();
439: final Configuration configuration = swingGuiContext
440: .getConfiguration();
441: final Iterator keys = configuration
442: .findPropertyKeys(CATEGORY_PREFIX);
443: while (keys.hasNext()) {
444: final String enableKey = (String) keys.next();
445: if (enableKey.endsWith(".enabled") == false) {
446: continue;
447: }
448:
449: if ("true".equals(configuration
450: .getConfigProperty(enableKey)) == false) {
451: continue;
452: }
453:
454: final String base = enableKey.substring(0, enableKey
455: .length()
456: - ".enabled".length());
457: if (base.length() == 0) {
458: continue;
459: }
460:
461: final String categoryKey = base.substring(CATEGORY_PREFIX
462: .length());
463: final String className = configuration
464: .getConfigProperty(base + ".class");
465: ActionCategory actionCategory;
466: if (className == null) {
467: actionCategory = new ActionCategory();
468: } else {
469: actionCategory = (ActionCategory) ObjectUtilities
470: .loadAndInstantiate(className,
471: PreviewPane.class, ActionCategory.class);
472: if (actionCategory == null) {
473: actionCategory = new ActionCategory();
474: }
475: }
476:
477: final String positionText = configuration
478: .getConfigProperty(base + ".position");
479: actionCategory.setPosition(TextUtilities.parseInt(
480: positionText, 0));
481: actionCategory.setName(categoryKey);
482: actionCategory.setResourceBase(configuration
483: .getConfigProperty(base + ".resource-base"));
484: actionCategory.setResourcePrefix(configuration
485: .getConfigProperty(base + ".resource-prefix"));
486: actionCategory.initialize(swingGuiContext);
487: categories.add(actionCategory);
488: }
489:
490: return (ActionCategory[]) categories
491: .toArray(new ActionCategory[categories.size()]);
492: }
493: }
|