001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.vmd.game.model;
043:
044: import java.awt.Dialog;
045: import java.awt.event.ActionEvent;
046: import java.beans.PropertyChangeListener;
047: import java.beans.PropertyChangeSupport;
048: import java.text.DecimalFormat;
049: import java.util.ArrayList;
050: import java.util.Collections;
051: import java.util.Iterator;
052: import java.util.List;
053: import javax.swing.AbstractAction;
054: import javax.swing.Action;
055: import javax.swing.JComponent;
056: import javax.swing.event.EventListenerList;
057: import org.netbeans.modules.vmd.game.dialog.NewSequenceDialog;
058: import org.netbeans.modules.vmd.game.editor.sequece.SequenceContainerEditor;
059: import org.openide.DialogDescriptor;
060: import org.openide.DialogDisplayer;
061: import org.openide.util.NbBundle;
062:
063: /**
064: *
065: * @author kherink
066: */
067: public interface SequenceContainer extends Editable {
068:
069: public static final String PROPERTY_DEFAULT_SEQUENCE = "sequencecontainer.prop.defaultsequence"; // NOI18N
070:
071: public void addPropertyChangeListener(PropertyChangeListener l);
072:
073: public void removePropertyChangeListener(PropertyChangeListener l);
074:
075: public void addSequenceContainerListener(
076: SequenceContainerListener listener);
077:
078: public void removeSequenceContainerListener(
079: SequenceContainerListener listener);
080:
081: public boolean append(Sequence sequence);
082:
083: public boolean insert(Sequence sequence, int index);
084:
085: public boolean remove(Sequence sequence);
086:
087: public void move(Sequence sequence, int newIndex);
088:
089: /**
090: * Create a duplicate of sequence
091: * Implementation must register the sequence in the list of all sequences available for it's ImageResource
092: * by calling ImageResource.addSequence(Sequence)
093: */
094: public Sequence createSequence(String string, Sequence sequence);
095:
096: /**
097: * Implementation must register the sequence in the list of all sequences available for it's ImageResource
098: * by calling ImageResource.addSequence(Sequence)
099: *
100: */
101: public Sequence createSequence(String name, int numberFrames,
102: int frameWidth, int frameHeight);
103:
104: public Sequence getDefaultSequence();
105:
106: public Sequence getSequenceAt(int index);
107:
108: public Sequence getSequenceByName(String name);
109:
110: public int getSequenceCount();
111:
112: public List<Sequence> getSequences();
113:
114: public void setDefaultSequence(Sequence defaultSequence);
115:
116: public String getName();
117:
118: public int indexOf(Sequence sequence);
119:
120: public List<Action> getActionsForSequence(Sequence sequence);
121:
122: public String getNextSequenceName(String prefix);
123:
124: public GlobalRepository getGameDesign();
125:
126: public static class SequenceContainerImpl implements
127: SequenceContainer {
128:
129: public static final boolean DEBUG = false;
130:
131: EventListenerList listenerList;
132: PropertyChangeSupport propertyChangeSupport;
133:
134: private List<Sequence> sequences;
135: private Sequence defaultSequence;
136: private SequenceContainer aggregator;
137:
138: private ImageResource imageResource;
139: private SequenceContainerEditor editor;
140:
141: private int frameWidth;
142: private int frameHeight;
143: boolean zeroBasedIndex;
144:
145: public SequenceContainerImpl(SequenceContainer aggregator,
146: EventListenerList ll, PropertyChangeSupport pcs,
147: ImageResource imageResource, int frameWidth,
148: int frameHeight, boolean zeroBasedIndex) {
149: this .aggregator = aggregator;
150: this .listenerList = (ll == null ? new EventListenerList()
151: : ll);
152: this .propertyChangeSupport = (pcs == null ? new PropertyChangeSupport(
153: aggregator)
154: : pcs);
155: this .sequences = new ArrayList();
156: this .imageResource = imageResource;
157: this .frameWidth = frameWidth;
158: this .frameHeight = frameHeight;
159: this .zeroBasedIndex = zeroBasedIndex;
160: }
161:
162: public GlobalRepository getGameDesign() {
163: return this .imageResource.getGameDesign();
164: }
165:
166: public void addPropertyChangeListener(PropertyChangeListener l) {
167: propertyChangeSupport.addPropertyChangeListener(l);
168: }
169:
170: public void removePropertyChangeListener(
171: PropertyChangeListener l) {
172: propertyChangeSupport.removePropertyChangeListener(l);
173: }
174:
175: public void addSequenceContainerListener(
176: SequenceContainerListener listener) {
177: this .listenerList.add(SequenceContainerListener.class,
178: listener);
179: }
180:
181: public void removeSequenceContainerListener(
182: SequenceContainerListener listener) {
183: this .listenerList.remove(SequenceContainerListener.class,
184: listener);
185: }
186:
187: protected void fireSequenceAdded(Sequence sequence, int index) {
188: Object[] listeners = listenerList.getListenerList();
189: for (int i = listeners.length - 2; i >= 0; i -= 2) {
190: if (listeners[i] == SequenceContainerListener.class) {
191: ((SequenceContainerListener) listeners[i + 1])
192: .sequenceAdded(this .aggregator, sequence,
193: index);
194: }
195: }
196: }
197:
198: protected void fireSequenceMoved(Sequence sequence,
199: int oldIndex, int newIndex) {
200: Object[] listeners = listenerList.getListenerList();
201: for (int i = listeners.length - 2; i >= 0; i -= 2) {
202: if (listeners[i] == SequenceContainerListener.class) {
203: ((SequenceContainerListener) listeners[i + 1])
204: .sequenceMoved(this .aggregator, sequence,
205: oldIndex, newIndex);
206: }
207: }
208: }
209:
210: protected void fireSequenceRemoved(Sequence sequence, int index) {
211: Object[] listeners = listenerList.getListenerList();
212: for (int i = listeners.length - 2; i >= 0; i -= 2) {
213: if (listeners[i] == SequenceContainerListener.class) {
214: ((SequenceContainerListener) listeners[i + 1])
215: .sequenceRemoved(this .aggregator, sequence,
216: index);
217: }
218: }
219: }
220:
221: //------SequenceContainer-------
222: public Sequence createSequence(String name, int numberFrames,
223: int frameWidth, int frameHeight) {
224: Sequence sequence = this .imageResource.createSequence(name,
225: numberFrames, frameWidth, frameHeight,
226: zeroBasedIndex);
227: this .append(sequence);
228: return sequence;
229: }
230:
231: public Sequence createSequence(String name, Sequence sequence) {
232: Sequence newSequence = this .imageResource.createSequence(
233: name, sequence);
234: this .append(newSequence);
235: return newSequence;
236: }
237:
238: public String getNextSequenceName(String prefix) {
239: int biggestNum = 0;
240: for (Sequence at : this .getSequences()) {
241: String name = at.getName();
242: if (name.startsWith(prefix)) {
243: try {
244: int num = Integer.parseInt(name
245: .substring(prefix.length()));
246: if (num > biggestNum)
247: biggestNum = num;
248: } catch (NumberFormatException nfe) {
249: }
250: }
251: }
252: DecimalFormat df = new DecimalFormat("000"); // NOI18N
253: String nextName;
254: do {
255: nextName = prefix + df.format(++biggestNum);
256: } while (!this .getGameDesign().isComponentNameAvailable(
257: nextName));
258: return nextName;
259: }
260:
261: public boolean append(Sequence sequence) {
262: if (DEBUG)
263: System.out.println(this + " append " + sequence); // NOI18N
264: if (this .sequences.contains(sequence)) {
265: if (!this .remove(sequence))
266: return false;
267: }
268: this .sequences.add(sequence);
269: int index = this .sequences.indexOf(sequence);
270: this .fireSequenceAdded(sequence, index);
271: return true;
272: }
273:
274: public boolean insert(Sequence sequence, int index) {
275: if (DEBUG)
276: System.out.println(this + " insert " + sequence
277: + " at " + index); // NOI18N
278: if (this .sequences.contains(sequence)) {
279: if (!this .remove(sequence))
280: return false;
281: }
282: this .sequences.add(index, sequence);
283: this .fireSequenceAdded(sequence, index);
284: return true;
285: }
286:
287: public boolean remove(Sequence sequence) {
288: if (DEBUG)
289: System.out.println(this + " remove " + sequence); // NOI18N
290: //cannot remove Default sequence
291: if (this .getDefaultSequence() == sequence)
292: return false;
293:
294: int index = this .sequences.indexOf(sequence);
295: if (this .sequences.remove(sequence)) {
296: this .fireSequenceRemoved(sequence, index);
297: }
298: return true;
299: }
300:
301: public void move(Sequence sequence, int newIndex) {
302: int oldIndex = this .sequences.indexOf(sequence);
303: if (oldIndex == -1) {
304: if (DEBUG)
305: System.out.println(this + " cannot move "
306: + sequence + " - it is not present"); // NOI18N
307: return;
308: }
309: if (DEBUG)
310: System.out.println(this + " move " + sequence
311: + " from " + oldIndex + " to " + newIndex); // NOI18N
312: this .sequences.remove(sequence);
313: this .sequences.add(newIndex, sequence);
314: this .fireSequenceMoved(sequence, oldIndex, newIndex);
315: }
316:
317: public Sequence getSequenceByName(String name) {
318: Sequence seq = null;
319: for (Iterator iter = this .sequences.iterator(); iter
320: .hasNext();) {
321: Sequence tmp = (Sequence) iter.next();
322: if (tmp.getName().equals(name)) {
323: seq = tmp;
324: break;
325: }
326: }
327: return seq;
328: }
329:
330: public void setDefaultSequence(Sequence defaultSequence) {
331: if (DEBUG)
332: System.out.println("DefaultSequence set to: "
333: + defaultSequence); // NOI18N
334: Sequence oldDef = this .defaultSequence;
335: if (!this .sequences.contains(defaultSequence)) {
336: this .append(defaultSequence);
337: }
338: this .defaultSequence = defaultSequence;
339: this .propertyChangeSupport.firePropertyChange(
340: PROPERTY_DEFAULT_SEQUENCE, oldDef, defaultSequence);
341: }
342:
343: public Sequence getDefaultSequence() {
344: return (Sequence) this .defaultSequence;
345: }
346:
347: public int indexOf(Sequence sequence) {
348: return this .sequences.indexOf(sequence);
349: }
350:
351: public Sequence getSequenceAt(int index) {
352: return (Sequence) this .sequences.get(index);
353: }
354:
355: public String getName() {
356: throw new UnsupportedOperationException(
357: "Must be overriden by aggregating class."); // NOI18N
358: }
359:
360: public List<Sequence> getSequences() {
361: return Collections.unmodifiableList(this .sequences);
362: }
363:
364: public int getSequenceCount() {
365: return this .sequences.size();
366: }
367:
368: public JComponent getEditor() {
369: return this .editor == null ? this .editor = new SequenceContainerEditor(
370: this )
371: : this .editor;
372: }
373:
374: public ImageResourceInfo getImageResourceInfo() {
375: return new ImageResourceInfo(this .imageResource,
376: this .frameWidth, this .frameHeight,
377: this .zeroBasedIndex);
378: }
379:
380: public JComponent getNavigator() {
381: return null;
382: }
383:
384: public List<Action> getActions() {
385: return Collections.EMPTY_LIST;
386: }
387:
388: public List<Action> getActionsForSequence(Sequence sequence) {
389: List<Action> commonActions = new ArrayList();
390:
391: CreateSequenceAction csa = new CreateSequenceAction();
392: DuplicateSequenceAction dsa = new DuplicateSequenceAction(
393: sequence);
394: DefaultSequenceAction defsa = new DefaultSequenceAction(
395: sequence);
396: RemoveSequenceAction rsa = new RemoveSequenceAction(
397: sequence);
398: //cannot remove default sequence
399: if (this .getDefaultSequence() == sequence) {
400: rsa.setEnabled(false);
401: defsa.setEnabled(false);
402: }
403: commonActions.add(csa);
404: commonActions.add(dsa);
405: commonActions.add(defsa);
406: commonActions.add(rsa);
407: commonActions.addAll(sequence.getActions());
408: //remove the "edit" action since this menu shows up in the editor :)
409: for (Iterator it = commonActions.iterator(); it.hasNext();) {
410: Action action = (Action) it.next();
411: if (action instanceof Sequence.EditSequenceAction) {
412: it.remove();
413: }
414: }
415:
416: return Collections.unmodifiableList(commonActions);
417: }
418:
419: public class CreateSequenceAction extends AbstractAction {
420: {
421: this .putValue(NAME, NbBundle.getMessage(
422: SequenceContainer.class,
423: "SequenceContainer.CreateSequenceAction.text"));
424: }
425:
426: public void actionPerformed(ActionEvent e) {
427: NewSequenceDialog dialog = new NewSequenceDialog(
428: SequenceContainerImpl.this ,
429: SequenceContainerImpl.this .frameWidth,
430: SequenceContainerImpl.this .frameHeight);
431: DialogDescriptor dd = new DialogDescriptor(
432: dialog,
433: NbBundle
434: .getMessage(SequenceContainer.class,
435: "SequenceContainer.CreateSequenceAction.text"));
436: dd.setButtonListener(dialog);
437: dd.setValid(false);
438: dialog.setDialogDescriptor(dd);
439: Dialog d = DialogDisplayer.getDefault()
440: .createDialog(dd);
441: d.setVisible(true);
442: }
443: }
444:
445: public class DuplicateSequenceAction extends AbstractAction {
446: private Sequence sequence;
447:
448: public DuplicateSequenceAction(Sequence sequence) {
449: this .sequence = sequence;
450: this
451: .putValue(
452: NAME,
453: NbBundle
454: .getMessage(
455: SequenceContainer.class,
456: "SequenceContainer.DuplicateSequenceAction.text"));
457: }
458:
459: public void actionPerformed(ActionEvent e) {
460: NewSequenceDialog dialog = new NewSequenceDialog(
461: SequenceContainerImpl.this , this .sequence);
462: DialogDescriptor dd = new DialogDescriptor(
463: dialog,
464: NbBundle
465: .getMessage(SequenceContainer.class,
466: "SequenceContainer.DuplicateSequenceAction.text"));
467: dd.setButtonListener(dialog);
468: dd.setValid(false);
469: dialog.setDialogDescriptor(dd);
470: Dialog d = DialogDisplayer.getDefault()
471: .createDialog(dd);
472: d.setVisible(true);
473: }
474: }
475:
476: public class DefaultSequenceAction extends AbstractAction {
477: private Sequence sequence;
478:
479: public DefaultSequenceAction(Sequence sequence) {
480: this .sequence = sequence;
481: this
482: .putValue(
483: NAME,
484: NbBundle
485: .getMessage(
486: SequenceContainer.class,
487: "SequenceContainer.DefaultSequenceAction.text"));
488: }
489:
490: public void actionPerformed(ActionEvent e) {
491: SequenceContainerImpl.this
492: .setDefaultSequence(this .sequence);
493: }
494: }
495:
496: public class RemoveSequenceAction extends AbstractAction {
497: private Sequence sequence;
498:
499: public RemoveSequenceAction(Sequence sequence) {
500: this .sequence = sequence;
501: this .putValue(NAME, NbBundle.getMessage(
502: SequenceContainer.class,
503: "SequenceContainer.RemoveSequenceAction.text"));
504: }
505:
506: public void actionPerformed(ActionEvent e) {
507: SequenceContainerImpl.this.remove(this.sequence);
508: }
509: }
510: }
511:
512: }
|