001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019: package org.netbeans.modules.xslt.tmap.multiview.designer;
020:
021: import java.awt.Component;
022: import java.awt.Dimension;
023: import java.awt.GridBagConstraints;
024: import java.awt.GridBagLayout;
025: import java.io.IOException;
026: import java.io.ObjectInput;
027: import java.io.ObjectOutput;
028: import javax.swing.Box;
029: import javax.swing.JScrollPane;
030: import javax.swing.JToggleButton;
031: import org.netbeans.core.spi.multiview.CloseOperationState;
032: import org.netbeans.core.spi.multiview.MultiViewElement;
033: import org.netbeans.core.spi.multiview.MultiViewElementCallback;
034: import org.openide.windows.TopComponent;
035: import java.io.Serializable;
036: import java.util.Enumeration;
037: import java.util.Iterator;
038: import javax.swing.JButton;
039:
040: import javax.swing.JComponent;
041: import javax.swing.JSlider;
042: import javax.swing.JToolBar;
043: import javax.swing.text.JTextComponent;
044: import org.netbeans.core.api.multiview.MultiViewHandler;
045: import org.netbeans.core.api.multiview.MultiViewPerspective;
046: import org.netbeans.core.api.multiview.MultiViews;
047:
048: import org.netbeans.core.spi.multiview.MultiViewFactory;
049: import org.netbeans.modules.xml.xam.ui.undo.QuietUndoManager;
050: import org.netbeans.modules.xslt.tmap.TMapDataEditorSupport;
051: import org.netbeans.modules.xslt.tmap.TMapDataObject;
052: import org.openide.awt.UndoRedo;
053: import org.openide.util.Lookup;
054: import org.openide.util.lookup.ProxyLookup;
055: import org.openide.nodes.Node;
056: import org.openide.windows.CloneableTopComponent;
057: import org.openide.windows.Mode;
058: import org.openide.windows.TopComponentGroup;
059: import org.openide.windows.WindowManager;
060:
061: /**
062: *
063: * @author Vitaly Bychkov
064: * @version 1.0
065: *
066: */
067: public class DesignerMultiViewElement extends TopComponent implements
068: MultiViewElement, Serializable {
069: private static final long serialVersionUID = 1L;
070: private transient MultiViewElementCallback myMultiViewObserver;
071: private transient DesignView myDesignView;
072:
073: private TMapDataObject myDataObject;
074: private transient JComponent myToolBarPanel;
075: private static Boolean groupVisible = null;
076:
077: // for deserialization
078: private DesignerMultiViewElement() {
079: super ();
080: }
081:
082: /** Creates a new instance of DesignerMultiViewElement. This is the visual
083: * canvas 'Design' view in the multiview
084: */
085: public DesignerMultiViewElement(TMapDataObject dataObject) {
086: myDataObject = dataObject;
087: initializeLookup();
088: initializeUI();
089: }
090:
091: public void writeExternal(ObjectOutput out) throws IOException {
092: super .writeExternal(out);
093: out.writeObject(myDataObject);
094: }
095:
096: /**
097: * we are using Externalization semantics so that we can get a hook to call
098: * initialize() upon deserialization
099: */
100: public void readExternal(ObjectInput in) throws IOException,
101: ClassNotFoundException {
102: super .readExternal(in);
103: myDataObject = (TMapDataObject) in.readObject();
104: initializeLookup();
105: initializeUI();
106: }
107:
108: private GridBagConstraints createGBConstraints() {
109: GridBagConstraints gc = new GridBagConstraints();
110: gc.fill = java.awt.GridBagConstraints.BOTH;
111: gc.insets = new java.awt.Insets(0, 0, 0, 0);
112: gc.weightx = 1.0;
113: gc.weighty = 1.0;
114: gc.anchor = GridBagConstraints.NORTHWEST;
115: return gc;
116: }
117:
118: ////////////////////////////////////////////////////////////////////////////
119: // MultiViewElement
120: ////////////////////////////////////////////////////////////////////////////
121: public int getPersistenceType() {
122: return TopComponent.PERSISTENCE_NEVER;
123: }
124:
125: public CloseOperationState canCloseElement() {
126: //
127: // actually if there are any visual changed NOT committed to the model
128: // then we may need to flush something here or something
129: //
130: boolean lastView = isLastView();
131:
132: if (!lastView) {
133: return CloseOperationState.STATE_OK;
134: }
135:
136: TMapDataEditorSupport editorSupport = myDataObject
137: .getEditorSupport();
138: boolean modified = editorSupport.isModified();
139:
140: if (!modified) {
141: return CloseOperationState.STATE_OK;
142: } else {
143: return MultiViewFactory.createUnsafeCloseState(
144: "Data Object Modified", null, null); // NOI18N
145: }
146: }
147:
148: public void componentActivated() {
149: super .componentActivated();
150: // not sure that we need to add undo manager each time when
151: // component is activated, but calling method addUndoManager() more
152: // than once is not a problem.
153: addUndoManager();
154: }
155:
156: public void componentClosed() {
157: super .componentClosed();
158: myDesignView = null;
159: }
160:
161: public void componentDeactivated() {
162: super .componentDeactivated();
163: }
164:
165: public void componentHidden() {
166: super .componentHidden();
167: if (myDesignView != null) {
168: myDesignView.setVisible(false);
169: }
170: updateTMapTcGroupVisibility(false);
171: }
172:
173: public void componentOpened() {
174: super .componentOpened();
175: }
176:
177: public void componentShowing() {
178: super .componentShowing();
179: if (myDesignView != null) {
180: myDesignView.setVisible(true);
181: }
182:
183: addUndoManager();
184: //
185: updateTMapTcGroupVisibility(true);
186: }
187:
188: public JComponent getToolbarRepresentation() {
189: if (myToolBarPanel == null) {
190: JToolBar toolbar = new JToolBar();
191: toolbar.setFloatable(false);
192: //TODO a toolbar.addSeparator();
193:
194: // toolbar.add(Box.createHorizontalStrut(1));
195: // TODO r
196: // toolbar.add(new JButton("testButton"));
197: // TODO a toolbar.addSeparator();
198: int maxButtonHeight = 0;
199:
200: for (Component c : toolbar.getComponents()) {
201: if (c instanceof JButton || c instanceof JToggleButton) {
202: maxButtonHeight = Math.max(
203: c.getPreferredSize().height,
204: maxButtonHeight);
205: }
206: }
207:
208: for (Component c : toolbar.getComponents()) {
209: if (c instanceof JButton || c instanceof JToggleButton) {
210: Dimension size = c.getMaximumSize();
211: size.height = maxButtonHeight;
212: c.setMaximumSize(size);
213: c.setMinimumSize(c.getPreferredSize());
214: } else if (c instanceof JTextComponent) {
215: c.setMaximumSize(c.getPreferredSize());
216: c.setMinimumSize(c.getPreferredSize());
217: } else if (c instanceof JSlider) {
218: Dimension size;
219: size = c.getMaximumSize();
220: size.width = 160;
221: c.setMaximumSize(size);
222:
223: size = c.getPreferredSize();
224: size.width = 160;
225: c.setPreferredSize(size);
226: } else {
227: c.setMinimumSize(c.getPreferredSize());
228: }
229: }
230: myToolBarPanel = toolbar;
231: }
232: return myToolBarPanel;
233: }
234:
235: public UndoRedo getUndoRedo() {
236: return getDataObject().getEditorSupport().getUndoManager();
237: }
238:
239: public JComponent getVisualRepresentation() {
240: return this ;
241: }
242:
243: public void setMultiViewCallback(MultiViewElementCallback callback) {
244: myMultiViewObserver = callback;
245: }
246:
247: public void requestVisible() {
248: if (myMultiViewObserver != null) {
249: myMultiViewObserver.requestVisible();
250: } else {
251: super .requestVisible();
252: }
253: }
254:
255: public void requestActive() {
256: if (myMultiViewObserver != null) {
257: myMultiViewObserver.requestActive();
258: } else {
259: super .requestActive();
260: }
261: }
262:
263: protected boolean closeLast() {
264: return true;
265: }
266:
267: private DesignView createDesignView() {
268: DesignView view = new DesignView(getLookup()); // got TC's lookup or no Palette
269: return view;
270: }
271:
272: private void initializeUI() {
273: setLayout(new GridBagLayout());
274:
275: myDesignView = createDesignView();
276: JScrollPane scroll = new JScrollPane(myDesignView.getView());
277: scroll.setBorder(null);
278: GridBagConstraints gc = createGBConstraints();
279: gc.gridx = 0;
280: gc.gridy = 0;
281: scroll.getVerticalScrollBar().setUnitIncrement(16);
282: scroll.getHorizontalScrollBar().setUnitIncrement(16);
283: add(scroll, gc);
284:
285: setVisible(true);
286: }
287:
288: /**
289: * Open or close the tmap_designer TopComponentGroup.
290: */
291: private static void updateTMapTcGroupVisibility(final boolean show) {
292: // when active TopComponent changes, check if we should open or close
293: // the TMap editor group of windows
294: WindowManager wm = WindowManager.getDefault();
295: final TopComponentGroup group = wm
296: .findTopComponentGroup("tmap_designer"); // NOI18N
297: if (group == null) {
298: return; // group not found (should not happen)
299: }
300: //
301: boolean designerSelected = false;
302: Iterator it = wm.getModes().iterator();
303: while (it.hasNext()) {
304: Mode mode = (Mode) it.next();
305: TopComponent selected = mode.getSelectedTopComponent();
306: if (selected != null) {
307: MultiViewHandler mvh = MultiViews
308: .findMultiViewHandler(selected);
309: if (mvh != null) {
310: MultiViewPerspective mvp = mvh
311: .getSelectedPerspective();
312: if (mvp != null) {
313: String id = mvp.preferredID();
314: if (DesignerMultiViewElementDesc.PREFERRED_ID
315: .equals(id)) {
316: designerSelected = true;
317: break;
318: }
319: }
320: }
321: }
322: }
323: //
324: if (designerSelected && !Boolean.TRUE.equals(groupVisible)) {
325: group.open();
326: } else if (!designerSelected
327: && !Boolean.FALSE.equals(groupVisible)) {
328: group.close();
329: }
330: //
331: groupVisible = designerSelected ? Boolean.TRUE : Boolean.FALSE;
332: }
333:
334: public static String getMVEditorActivePanelPrefferedId() {
335: TopComponent activeTC = WindowManager.getDefault()
336: .getRegistry().getActivated();
337: MultiViewHandler mvh = MultiViews
338: .findMultiViewHandler(activeTC);
339: if (mvh == null) {
340: return null;
341: }
342:
343: MultiViewPerspective mvp = mvh.getSelectedPerspective();
344: if (mvp != null) {
345: return mvp.preferredID();
346: }
347:
348: return null;
349: }
350:
351: private boolean isLastView() {
352: boolean oneOrLess = true;
353: Enumeration en = ((CloneableTopComponent) myMultiViewObserver
354: .getTopComponent()).getReference().getComponents();
355: if (en.hasMoreElements()) {
356: en.nextElement();
357: if (en.hasMoreElements()) {
358: oneOrLess = false;
359: }
360: }
361:
362: return oneOrLess;
363: }
364:
365: private TMapDataObject getDataObject() {
366: return myDataObject;
367: }
368:
369: private void initializeLookup() {
370: associateLookup(createAssociateLookup());
371: setActivatedNodes(new Node[] { getDataObject()
372: .getNodeDelegate() });
373: }
374:
375: private Lookup createAssociateLookup() {
376:
377: //
378: // see http://www.netbeans.org/issues/show_bug.cgi?id=67257
379: //
380: return new ProxyLookup(new Lookup[] { myDataObject.getLookup(), // this lookup contain objects that are used in OM clients
381: });
382: }
383:
384: /**
385: * Adds the undo/redo manager to the bpel model as an undoable
386: * edit listener, so it receives the edits onto the queue.
387: */
388: private void addUndoManager() {
389: TMapDataEditorSupport support = myDataObject.getEditorSupport();
390: if (support != null) {
391: QuietUndoManager undo = support.getUndoManager();
392: support.addUndoManagerToModel(undo);
393: }
394: }
395:
396: }
|