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;
015:
016: import org.jetbrains.annotations.NotNull;
017: import org.jetbrains.annotations.Nullable;
018: import org.pentaho.reportdesigner.crm.report.model.LineReportElement;
019: import org.pentaho.reportdesigner.crm.report.model.Report;
020: import org.pentaho.reportdesigner.crm.report.model.ReportElement;
021: import org.pentaho.reportdesigner.crm.report.util.ReportElementUtilities;
022: import org.pentaho.reportdesigner.lib.client.undo.Undo;
023: import org.pentaho.reportdesigner.lib.client.undo.UndoEntry;
024:
025: import java.awt.geom.Point2D;
026: import java.awt.geom.Rectangle2D;
027: import java.util.ArrayList;
028: import java.util.Collection;
029: import java.util.Iterator;
030: import java.util.LinkedHashSet;
031:
032: /**
033: * User: Martin
034: * Date: 10.10.2005
035: * Time: 15:38:26
036: */
037: public class ReportElementSelectionModel {
038: @NotNull
039: private LinkedHashSet<BandElementModelListener> bandElementModelListeners;
040:
041: @NotNull
042: private ArrayList<ReportElement> selectedElementInfos;
043: @NotNull
044: private ArrayList<ReportElement> nonDescendentsSelectedElementInfos;
045:
046: @NotNull
047: private Report report;
048: @NotNull
049: private ReportDialog reportDialog;
050:
051: public ReportElementSelectionModel(@NotNull
052: ReportDialog reportDialog, @NotNull
053: Report report) {
054: //noinspection ConstantConditions
055: if (reportDialog == null) {
056: throw new IllegalArgumentException(
057: "reportDialog must not be null");
058: }
059: //noinspection ConstantConditions
060: if (report == null) {
061: throw new IllegalArgumentException(
062: "report must not be null");
063: }
064:
065: this .reportDialog = reportDialog;
066: this .report = report;
067:
068: bandElementModelListeners = new LinkedHashSet<BandElementModelListener>();
069:
070: selectedElementInfos = new ArrayList<ReportElement>();
071: nonDescendentsSelectedElementInfos = new ArrayList<ReportElement>();
072: }
073:
074: @Nullable
075: public ReportPanel getReportPanel(@NotNull
076: ReportElement reportElement) {
077: ArrayList<ReportBorderPanel> bands = reportDialog.getBands();
078: if (bands != null) {
079: for (ReportBorderPanel reportBorderPanel : bands) {
080: if (reportElement.isDescendant(reportBorderPanel
081: .getReportPanel()
082: .getBandToplevelReportElement())) {
083: return reportBorderPanel.getReportPanel();
084: }
085: }
086: }
087:
088: return null;
089: }
090:
091: @NotNull
092: public Report getReport() {
093: return report;
094: }
095:
096: public void addBandElementModelListener(@NotNull
097: BandElementModelListener bandElementModelListener) {
098: bandElementModelListeners.add(bandElementModelListener);
099: }
100:
101: public void removeBandElementModelListener(@NotNull
102: BandElementModelListener bandElementModelListener) {
103: bandElementModelListeners.remove(bandElementModelListener);
104: }
105:
106: private void fireLayoutChanged() {
107: LinkedHashSet<BandElementModelListener> beml = new LinkedHashSet<BandElementModelListener>(
108: bandElementModelListeners);
109: for (BandElementModelListener bandElementModelListener : beml) {
110: bandElementModelListener.layoutChanged();
111: }
112: }
113:
114: private void fireSelectionChanged() {
115: LinkedHashSet<BandElementModelListener> beml = new LinkedHashSet<BandElementModelListener>(
116: bandElementModelListeners);
117: for (BandElementModelListener bandElementModelListener : beml) {
118: bandElementModelListener.selectionChanged();
119: }
120: }
121:
122: public void refresh() {
123: report.validate();
124: fireLayoutChanged();
125: }
126:
127: private void addChildren(@NotNull
128: ReportElement reportElement, @NotNull
129: ArrayList<ReportElement> reportElements) {
130: ArrayList<ReportElement> children = reportElement.getChildren();
131: for (ReportElement element : children) {
132: addChildren(element, reportElements);
133: reportElements.add(element);
134: }
135: }
136:
137: @Nullable
138: public ReportElement getNextElementInfo(@NotNull
139: ReportElement root, @Nullable
140: ReportElement elementBefore, @NotNull
141: Point2D p) {
142: ArrayList<ReportElement> reportElements = new ArrayList<ReportElement>();
143: addChildren(root, reportElements);
144:
145: if (elementBefore != null && containsPoint(elementBefore, p)) {
146: boolean before = false;
147: for (int i = reportElements.size() - 1; i >= 0; i--) {
148: ReportElement elementInfo = reportElements.get(i);
149: if (before && containsPoint(elementInfo, p)) {
150: return elementInfo;
151: }
152:
153: //noinspection ObjectEquality
154: if (!before && elementBefore == elementInfo) {
155: before = true;
156: }
157: }
158: }
159:
160: for (int i = reportElements.size() - 1; i >= 0; i--) {
161: ReportElement elementInfo = reportElements.get(i);
162: if (containsPoint(elementInfo, p)) {
163: return elementInfo;
164: }
165: }
166:
167: return null;
168: }
169:
170: private boolean containsPoint(@NotNull
171: ReportElement elementInfo, @NotNull
172: Point2D p) {
173: if (!ReportElementUtilities.isShowInLayoutGUI(elementInfo)) {
174: return false;
175: }
176:
177: if (elementInfo instanceof LineReportElement) {
178: LineReportElement lineReportElement = (LineReportElement) elementInfo;
179: Rectangle2D.Double r = elementInfo.getRectangle();
180: double lw = Math.max(3, lineReportElement
181: .getLineDefinition().getWidth() / 2);
182: Rectangle2D.Double rect = new Rectangle2D.Double(r.x - lw,
183: r.y - lw, r.width + 2 * lw, r.height + 2 * lw);
184:
185: ReportElementUtilities.convertRectangle(rect,
186: lineReportElement, null);
187: return rect.contains(p);
188: } else {
189: Rectangle2D.Double rect = new Rectangle2D.Double();
190: rect.setRect(elementInfo.getRectangle());
191: ReportElementUtilities.convertRectangle(rect, elementInfo,
192: null);
193: return rect.contains(p);
194: }
195: }
196:
197: public void clearSelection() {
198: Undo undo = reportDialog.getUndo();
199: if (!undo.isInProgress() && !selectedElementInfos.isEmpty()) {
200: undo.startTransaction(UndoConstants.CLEAR_SELECTION);
201: undo.add(new UndoEntry() {
202: @NotNull
203: private ArrayList<ReportElement> selection = new ArrayList<ReportElement>(
204: selectedElementInfos);
205: @NotNull
206: private ArrayList<ReportElement> nonDescendents = new ArrayList<ReportElement>(
207: nonDescendentsSelectedElementInfos);
208:
209: public void undo() {
210: selectedElementInfos.addAll(selection);
211: nonDescendentsSelectedElementInfos
212: .addAll(nonDescendents);
213: fireSelectionChanged();
214: }
215:
216: public void redo() {
217: clearSelection();
218: }
219: });
220: undo.endTransaction();
221: }
222:
223: selectedElementInfos.clear();
224: nonDescendentsSelectedElementInfos.clear();
225: fireSelectionChanged();
226: }
227:
228: public void setSelection(@NotNull
229: final Collection<? extends ReportElement> elementInfos) {
230: Undo undo = reportDialog.getUndo();
231: if (!undo.isInProgress()) {
232: undo.startTransaction(UndoConstants.SET_SELECTION);
233: undo.add(new UndoEntry() {
234: @NotNull
235: private ArrayList<ReportElement> selection = new ArrayList<ReportElement>(
236: selectedElementInfos);
237: @NotNull
238: private ArrayList<ReportElement> nonDescendents = new ArrayList<ReportElement>(
239: nonDescendentsSelectedElementInfos);
240:
241: public void undo() {
242: selectedElementInfos.clear();
243: selectedElementInfos.addAll(selection);
244: nonDescendentsSelectedElementInfos.clear();
245: nonDescendentsSelectedElementInfos
246: .addAll(nonDescendents);
247: fireSelectionChanged();
248: }
249:
250: public void redo() {
251: setSelection(elementInfos);
252: }
253: });
254: undo.endTransaction();
255: }
256:
257: selectedElementInfos.clear();
258: selectedElementInfos.addAll(elementInfos);
259:
260: nonDescendentsSelectedElementInfos.clear();
261: for (ReportElement reportElement : selectedElementInfos) {
262: addToNonDescendents(reportElement);
263: }
264:
265: fireSelectionChanged();
266: }
267:
268: public void addSelectedElement(@Nullable
269: final ReportElement elementInfo) {
270: if (elementInfo != null) {
271: Undo undo = reportDialog.getUndo();
272: if (!undo.isInProgress()) {
273: undo
274: .startTransaction(UndoConstants.ADD_SELECTED_ELEMENT);
275: undo.add(new UndoEntry() {
276: @NotNull
277: private ArrayList<ReportElement> selection = new ArrayList<ReportElement>(
278: selectedElementInfos);
279: @NotNull
280: private ArrayList<ReportElement> nonDescendents = new ArrayList<ReportElement>(
281: nonDescendentsSelectedElementInfos);
282:
283: public void undo() {
284: selectedElementInfos.clear();
285: selectedElementInfos.addAll(selection);
286: nonDescendentsSelectedElementInfos.clear();
287: nonDescendentsSelectedElementInfos
288: .addAll(nonDescendents);
289: fireSelectionChanged();
290: }
291:
292: public void redo() {
293: addSelectedElement(elementInfo);
294: }
295: });
296: undo.endTransaction();
297: }
298:
299: selectedElementInfos.add(elementInfo);
300:
301: addToNonDescendents(elementInfo);
302:
303: fireSelectionChanged();
304: }
305: }
306:
307: private void addToNonDescendents(@NotNull
308: ReportElement reportElement) {
309: for (Iterator<ReportElement> iterator = nonDescendentsSelectedElementInfos
310: .iterator(); iterator.hasNext();) {
311: ReportElement element = iterator.next();
312: if (reportElement.isDescendant(element)) {
313: return;
314: }
315: if (element.isDescendant(reportElement)) {
316: iterator.remove();
317: }
318: }
319:
320: nonDescendentsSelectedElementInfos.add(reportElement);
321: }
322:
323: @NotNull
324: public ArrayList<ReportElement> getSelectedElementInfos() {
325: return selectedElementInfos;
326: }
327:
328: @NotNull
329: public ArrayList<ReportElement> getNonDescendentsSelectedElementInfos() {
330: return nonDescendentsSelectedElementInfos;
331: }
332:
333: }
|