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.crm.report.properties;
015:
016: import org.jetbrains.annotations.NonNls;
017: import org.jetbrains.annotations.NotNull;
018: import org.jetbrains.annotations.Nullable;
019: import org.jfree.report.function.Expression;
020: import org.pentaho.reportdesigner.crm.report.IconLoader;
021: import org.pentaho.reportdesigner.crm.report.PropertyKeys;
022: import org.pentaho.reportdesigner.crm.report.ReportDialog;
023: import org.pentaho.reportdesigner.crm.report.ReportElementSelectionModel;
024: import org.pentaho.reportdesigner.crm.report.UndoConstants;
025: import org.pentaho.reportdesigner.crm.report.model.ChartReportElement;
026: import org.pentaho.reportdesigner.crm.report.model.GroupingPropertyDescriptor;
027: import org.pentaho.reportdesigner.crm.report.model.ReportElement;
028: import org.pentaho.reportdesigner.crm.report.model.ReportFunctionsElement;
029: import org.pentaho.reportdesigner.crm.report.model.SubReportDataElement;
030: import org.pentaho.reportdesigner.crm.report.model.dataset.DataSetReportElement;
031: import org.pentaho.reportdesigner.crm.report.properties.editors.ChartEditor;
032: import org.pentaho.reportdesigner.lib.client.i18n.TranslationManager;
033: import org.pentaho.reportdesigner.lib.client.util.UncaughtExcpetionsModel;
034:
035: import javax.swing.*;
036: import javax.swing.event.ChangeEvent;
037: import java.awt.*;
038: import java.awt.event.ActionEvent;
039: import java.awt.event.ActionListener;
040: import java.beans.BeanInfo;
041: import java.beans.IntrospectionException;
042: import java.beans.Introspector;
043: import java.beans.PropertyChangeEvent;
044: import java.beans.PropertyChangeListener;
045: import java.beans.PropertyDescriptor;
046: import java.lang.reflect.InvocationTargetException;
047: import java.util.ArrayList;
048: import java.util.Collection;
049: import java.util.HashMap;
050: import java.util.HashSet;
051: import java.util.LinkedHashSet;
052: import java.util.logging.Level;
053: import java.util.logging.Logger;
054:
055: /**
056: * User: Martin
057: * Date: 21.10.2005
058: * Time: 07:40:47
059: */
060: public class PropertyEditorPanel extends JPanel implements
061: PropertyChangeListener {
062: @NonNls
063: @NotNull
064: private static final Logger LOG = Logger
065: .getLogger(PropertyEditorPanel.class.getName());
066:
067: @NotNull
068: private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
069:
070: @NotNull
071: private static final String TABLE = "table";
072: @NotNull
073: private static final String FUNCTIONS = "functions";
074:
075: @NotNull
076: private static final String EMPTY = "empty";
077: @NotNull
078: private static final String CUSTOM = "custom";
079: @NotNull
080: private static final String CHART = "chart";
081:
082: @NotNull
083: private PropertyTable propertyTable;
084: @NotNull
085: private PropertyTableModel propertyTableModel;
086:
087: @NotNull
088: private Object[] objects;
089: @NotNull
090: private ReportDialog reportDialog;
091:
092: @NotNull
093: private ReportElementSelectionModel reportElementSelectionModel;
094:
095: @NotNull
096: private CardLayout cardLayout;
097: @NotNull
098: private HashSet<String> exludedExpressionProperties;
099: @NotNull
100: private JPanel customPanel;
101: @NotNull
102: private JPanel chartPanel;
103:
104: public PropertyEditorPanel(@NotNull
105: final ReportDialog reportDialog, @NotNull
106: ReportElementSelectionModel reportElementSelectionModel) {
107: this .reportDialog = reportDialog;
108: this .reportElementSelectionModel = reportElementSelectionModel;
109: propertyTableModel = new PropertyTableModel(Style.GROUPED, this );
110: propertyTable = new PropertyTable(this , propertyTableModel);
111:
112: cardLayout = new CardLayout(0, 0);
113: setLayout(cardLayout);
114:
115: JPanel tableHelperPanel = new JPanel(new BorderLayout());
116: tableHelperPanel.add(propertyTable);
117: JScrollPane scrollPane = new JScrollPane(tableHelperPanel);
118: scrollPane.getHorizontalScrollBar().setUnitIncrement(20);
119: scrollPane.getHorizontalScrollBar().setBlockIncrement(50);
120: scrollPane.getVerticalScrollBar().setUnitIncrement(20);
121: scrollPane.getVerticalScrollBar().setBlockIncrement(50);
122: scrollPane.setPreferredSize(new Dimension(200, 300));
123:
124: JPanel groupSortPanel = new JPanel(new FlowLayout(
125: FlowLayout.LEADING));
126: JToggleButton groupButton = new JToggleButton(IconLoader
127: .getInstance().getGroupIcon());
128: JToggleButton sortAscendingButton = new JToggleButton(
129: IconLoader.getInstance().getSortAscendingIcon());
130: JToggleButton sortDescendingButton = new JToggleButton(
131: IconLoader.getInstance().getSortDescendingIcon());
132:
133: ButtonGroup buttonGroup = new ButtonGroup();
134: buttonGroup.add(groupButton);
135: buttonGroup.add(sortAscendingButton);
136: buttonGroup.add(sortDescendingButton);
137:
138: groupButton.setSelected(true);
139:
140: groupButton.addActionListener(new ActionListener() {
141: public void actionPerformed(@NotNull
142: ActionEvent e) {
143: propertyTableModel.setStyle(Style.GROUPED);
144: }
145: });
146:
147: sortAscendingButton.addActionListener(new ActionListener() {
148: public void actionPerformed(@NotNull
149: ActionEvent e) {
150: propertyTableModel.setStyle(Style.ASCENDING);
151: }
152: });
153:
154: sortDescendingButton.addActionListener(new ActionListener() {
155: public void actionPerformed(@NotNull
156: ActionEvent e) {
157: propertyTableModel.setStyle(Style.DESCENDING);
158: }
159: });
160:
161: groupSortPanel.add(groupButton);
162: groupSortPanel.add(sortAscendingButton);
163: groupSortPanel.add(sortDescendingButton);
164:
165: scrollPane.setColumnHeaderView(groupSortPanel);
166: scrollPane.setBorder(BorderFactory.createEmptyBorder());
167: add(scrollPane, TABLE);
168: add(new ExpressionChooser(reportDialog,
169: reportElementSelectionModel.getReport(),
170: reportElementSelectionModel), FUNCTIONS);
171:
172: customPanel = new JPanel(new BorderLayout());
173: add(customPanel, CUSTOM);
174:
175: chartPanel = new JPanel(new GridBagLayout());
176: JButton editButton = new JButton(TranslationManager
177: .getInstance().getTranslation("R",
178: "PropertyEditorPanel.EditChart"));
179: chartPanel.add(editButton);
180: add(chartPanel, CHART);
181: editButton.addActionListener(new ActionListener() {
182: public void actionPerformed(@NotNull
183: ActionEvent e) {
184: ChartEditor.showChartEditor(reportDialog
185: .getRootJComponent(), TranslationManager
186: .getInstance().getTranslation("R",
187: "ChartEditor.Title"),
188: (ChartReportElement) objects[0], reportDialog);
189: }
190: });
191:
192: add(new JPanel(), EMPTY);
193:
194: cardLayout.show(this , TABLE);
195:
196: objects = EMPTY_OBJECT_ARRAY;
197:
198: exludedExpressionProperties = new HashSet<String>();
199: exludedExpressionProperties.add(PropertyKeys.VALUE);
200: exludedExpressionProperties.add(PropertyKeys.ACTIVE);
201: exludedExpressionProperties.add(PropertyKeys.DATA_ROW);
202: exludedExpressionProperties.add(PropertyKeys.INSTANCE);
203: }
204:
205: @NotNull
206: public ReportDialog getReportDialog() {
207: return reportDialog;
208: }
209:
210: private boolean isExludedProperty(@NotNull
211: BeanInfo beanInfo, @NotNull
212: PropertyDescriptor propertyDescriptor) {
213: boolean assignableFrom = Expression.class
214: .isAssignableFrom(beanInfo.getBeanDescriptor()
215: .getBeanClass());
216: boolean b = exludedExpressionProperties
217: .contains(propertyDescriptor.getName());
218: return assignableFrom && b;
219: }
220:
221: public void selectProperty(@NotNull
222: String propertyName, boolean requestFocus) {
223: ArrayList<Object> propertyDescriptors = propertyTableModel
224: .getPropertyDescriptors();
225: for (int i = 0; i < propertyDescriptors.size(); i++) {
226: Object o = propertyDescriptors.get(i);
227: if (o instanceof PropertyDescriptor) {
228: PropertyDescriptor propertyDescriptor = (PropertyDescriptor) o;
229: if (propertyDescriptor.getName().equals(propertyName)) {
230: propertyTable.getSelectionModel()
231: .setSelectionInterval(i, i);
232: if (requestFocus) {
233: propertyTable.requestFocusInWindow();
234: }
235: }
236: }
237: }
238: }
239:
240: public void setBeans(@NotNull
241: final Object[] objects) {
242: //noinspection ConstantConditions
243: if (objects == null) {
244: throw new IllegalArgumentException(
245: "objects must not be null");
246: }
247:
248: if (objects.length == 1
249: && objects[0] instanceof ReportFunctionsElement) {
250: cardLayout.show(this , FUNCTIONS);
251: } else if (objects.length == 1
252: && objects[0] instanceof ChartReportElement) {
253: cardLayout.show(this , CHART);
254: } else if (objects.length == 1
255: && objects[0] instanceof DataSetReportElement) {
256: final DataSetReportElement dataSetReportElement = (DataSetReportElement) objects[0];
257: customPanel.removeAll();
258: customPanel.add(dataSetReportElement.getInfoComponent(),
259: BorderLayout.CENTER);
260: if (dataSetReportElement.canConfigure()) {
261: JButton configureButton = new JButton(
262: TranslationManager
263: .getInstance()
264: .getTranslation("R",
265: "PropertyEditorPanel.Configure"));
266: configureButton.addActionListener(new ActionListener() {
267: public void actionPerformed(@NotNull
268: ActionEvent e) {
269: dataSetReportElement
270: .showConfigurationComponent(
271: reportDialog, false);
272: setBeans(objects);//cheap way to refresh
273: }
274: });
275: customPanel.add(configureButton, BorderLayout.SOUTH);
276: }
277:
278: customPanel.revalidate();
279: cardLayout.show(this , CUSTOM);
280: } else if (objects.length == 1
281: && objects[0] instanceof SubReportDataElement) {
282: final SubReportDataElement subReportDataElement = (SubReportDataElement) objects[0];
283: customPanel.removeAll();
284: customPanel.add(subReportDataElement.getInfoComponent(),
285: BorderLayout.CENTER);
286: if (subReportDataElement.canConfigure()) {
287: JButton configureButton = new JButton(
288: TranslationManager
289: .getInstance()
290: .getTranslation("R",
291: "PropertyEditorPanel.Configure"));
292: configureButton.addActionListener(new ActionListener() {
293: public void actionPerformed(@NotNull
294: ActionEvent e) {
295: subReportDataElement
296: .showConfigurationComponent(reportDialog);
297: setBeans(objects);//cheap way to refresh
298: }
299: });
300: customPanel.add(configureButton, BorderLayout.SOUTH);
301: }
302:
303: customPanel.revalidate();
304: cardLayout.show(this , CUSTOM);
305: } else {
306: if (objects.length > 1) {
307: boolean showEmptyPanel = false;
308: for (Object object : objects) {
309: if (object instanceof SubReportDataElement
310: || object instanceof DataSetReportElement
311: || object instanceof ChartReportElement
312: || object instanceof ReportFunctionsElement) {
313: showEmptyPanel = true;
314: }
315: }
316:
317: if (showEmptyPanel) {
318: cardLayout.show(this , EMPTY);
319: } else {
320: cardLayout.show(this , TABLE);
321: }
322: } else {
323: cardLayout.show(this , TABLE);
324: }
325: }
326:
327: propertyTable.editingStopped(new ChangeEvent(this ));
328:
329: for (Object o : this .objects) {
330: if (o instanceof ReportElement) {
331: ReportElement reportElement = (ReportElement) o;
332: reportElement.removePropertyChangeListener(this );
333: }
334: }
335:
336: this .objects = objects;
337: //search properties available in all beans
338: HashMap<String, HashSet<PropertyDescriptor>> groupedProperties = new HashMap<String, HashSet<PropertyDescriptor>>();
339: try {
340: if (objects.length > 0) {
341: BeanInfo beanInfo = Introspector.getBeanInfo(objects[0]
342: .getClass(), Introspector.USE_ALL_BEANINFO);
343:
344: PropertyDescriptor[] propertyDescriptors = beanInfo
345: .getPropertyDescriptors();
346: for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
347: Class<?> clazz1 = propertyDescriptor
348: .getPropertyType();
349: if (clazz1 != null
350: && !isExludedProperty(beanInfo,
351: propertyDescriptor)) {
352: if (propertyDescriptor.getReadMethod() != null
353: && propertyDescriptor.getWriteMethod() != null) {
354: addToGroupedProperties(groupedProperties,
355: propertyDescriptor);
356: }
357: }
358: }
359: }
360:
361: if (objects.length > 1) {
362: for (int i = 1; i < objects.length; i++) {
363: BeanInfo beanInfo = Introspector
364: .getBeanInfo(objects[i].getClass());
365:
366: PropertyDescriptor[] propertyDescriptors = beanInfo
367: .getPropertyDescriptors();
368: HashSet<PropertyDescriptor> beanProperties = new HashSet<PropertyDescriptor>();
369:
370: for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
371: if (!isExludedProperty(beanInfo,
372: propertyDescriptor)) {
373: beanProperties.add(propertyDescriptor);
374: }
375: }
376:
377: retainProperties(groupedProperties, beanProperties);
378: }
379: }
380: } catch (IntrospectionException e) {
381: UncaughtExcpetionsModel.getInstance().addException(e);
382: }
383:
384: for (Object o : this .objects) {
385: if (o instanceof ReportElement) {
386: ReportElement reportElement = (ReportElement) o;
387: reportElement.addPropertyChangeListener(this );
388: }
389: }
390:
391: propertyTableModel.setPropertyDescriptors(groupedProperties);
392: }
393:
394: @NotNull
395: public Object[] getObjects() {
396: return objects;
397: }
398:
399: private void addToGroupedProperties(@NotNull
400: HashMap<String, HashSet<PropertyDescriptor>> groupedProperties,
401: @NotNull
402: PropertyDescriptor propertyDescriptor) {
403: if (propertyDescriptor instanceof GroupingPropertyDescriptor) {
404: GroupingPropertyDescriptor groupingPropertyDescriptor = (GroupingPropertyDescriptor) propertyDescriptor;
405: @Nullable
406: HashSet<PropertyDescriptor> propertyDescriptors = groupedProperties
407: .get(groupingPropertyDescriptor
408: .getPropertyGroupName());
409: if (propertyDescriptors == null) {
410: propertyDescriptors = new HashSet<PropertyDescriptor>();
411: groupedProperties.put(groupingPropertyDescriptor
412: .getPropertyGroupName(), propertyDescriptors);
413: }
414:
415: //search all maps for the same property, remove this property if it is contained in another group
416: Collection<HashSet<PropertyDescriptor>> hashSets = groupedProperties
417: .values();
418: for (HashSet<PropertyDescriptor> descriptors : hashSets) {
419: descriptors.remove(groupingPropertyDescriptor);
420: }
421:
422: //add it to the correct set
423: propertyDescriptors.add(groupingPropertyDescriptor);
424: } else {
425: @Nullable
426: HashSet<PropertyDescriptor> propertyDescriptors = groupedProperties
427: .get(PropertyKeys.GROUP_UNKNOWN);
428: if (propertyDescriptors == null) {
429: propertyDescriptors = new HashSet<PropertyDescriptor>();
430: groupedProperties.put(PropertyKeys.GROUP_UNKNOWN,
431: propertyDescriptors);
432: }
433:
434: //search all maps for the same property, remove this property if it is contained in another group
435: boolean alreadyAdded = false;
436: Collection<HashSet<PropertyDescriptor>> hashSets = groupedProperties
437: .values();
438: for (HashSet<PropertyDescriptor> descriptors : hashSets) {
439: if (descriptors.contains(propertyDescriptor)) {
440: alreadyAdded = true;
441: }
442: }
443:
444: if (!alreadyAdded) {
445: propertyDescriptors.add(propertyDescriptor);
446: }
447: }
448: }
449:
450: private void retainProperties(@NotNull
451: HashMap<String, HashSet<PropertyDescriptor>> groupedProperties,
452: @NotNull
453: HashSet<PropertyDescriptor> beanProperties) {
454: for (HashSet<PropertyDescriptor> propertyDescriptors : groupedProperties
455: .values()) {
456: propertyDescriptors.retainAll(beanProperties);
457: }
458: }
459:
460: @NotNull
461: public LinkedHashSet<?> getValues(@NotNull
462: PropertyDescriptor propertyDescriptor) {
463: LinkedHashSet<Object> values = new LinkedHashSet<Object>();
464:
465: for (Object beanObject : objects) {
466: try {
467: Object value = propertyDescriptor.getReadMethod()
468: .invoke(beanObject, EMPTY_OBJECT_ARRAY);
469: values.add(value);
470: } catch (IllegalAccessException e) {
471: UncaughtExcpetionsModel.getInstance().addException(e);
472: } catch (InvocationTargetException e) {
473: UncaughtExcpetionsModel.getInstance().addException(e);
474: } catch (IllegalArgumentException e) {
475: UncaughtExcpetionsModel.getInstance().addException(e);
476: }
477: }
478:
479: return values;
480: }
481:
482: public void setValues(@NotNull
483: PropertyDescriptor propertyDescriptor, @Nullable
484: Object newValue) {
485: if (LOG.isLoggable(Level.FINE))
486: LOG.log(Level.FINE,
487: "PropertyEditorPanel.setValues newValue = "
488: + newValue);
489:
490: reportDialog.getUndo().startTransaction(
491: UndoConstants.PROPERTY_SETVALUES);
492: for (Object o : objects) {
493: try {
494: propertyDescriptor.getWriteMethod().invoke(o, newValue);
495: } catch (IllegalAccessException e) {
496: UncaughtExcpetionsModel.getInstance().addException(e);
497: } catch (InvocationTargetException e) {
498: UncaughtExcpetionsModel.getInstance().addException(e);
499: } catch (IllegalArgumentException e) {
500: if (LOG.isLoggable(Level.FINE))
501: LOG.log(Level.FINE,
502: "PropertyEditorPanel.setValues ", e);
503: //UncaughtExcpetionsModel.getInstance().addException(e);
504: }
505: }
506: reportDialog.getUndo().endTransaction();
507: }
508:
509: public void propertyChange(@NotNull
510: PropertyChangeEvent evt) {
511: propertyTableModel.fireTableDataChanged();
512:
513: if (!reportDialog.getUndo().isInProgress()) {
514: if (PropertyKeys.POSITION.equals(evt.getPropertyName())) {
515: reportElementSelectionModel.refresh();
516: } else if (PropertyKeys.MINIMUM_SIZE.equals(evt
517: .getPropertyName())) {
518: reportElementSelectionModel.refresh();
519: } else if (PropertyKeys.REPORT_LAYOUT_MANAGER_TYPE
520: .equals(evt.getPropertyName())) {
521: reportElementSelectionModel.refresh();
522: }
523: }
524: }
525: }
|