001: /*
002: * Copyright (C) 2005 - 2008 JasperSoft Corporation. All rights reserved.
003: * http://www.jaspersoft.com.
004: *
005: * Unless you have purchased a commercial license agreement from JasperSoft,
006: * the following license terms apply:
007: *
008: * This program is free software; you can redistribute it and/or modify
009: * it under the terms of the GNU General Public License version 2 as published by
010: * the Free Software Foundation.
011: *
012: * This program is distributed WITHOUT ANY WARRANTY; and without the
013: * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
014: * See the GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, see http://www.gnu.org/licenses/gpl.txt
018: * or write to:
019: *
020: * Free Software Foundation, Inc.,
021: * 59 Temple Place - Suite 330,
022: * Boston, MA USA 02111-1307
023: *
024: *
025: *
026: *
027: * DockingContainer.java
028: *
029: * Created on January 25, 2006, 5:22 PM
030: *
031: */
032:
033: package it.businesslogic.ireport.gui.docking;
034:
035: import it.businesslogic.ireport.gui.event.TabPaneChangedEvent;
036: import it.businesslogic.ireport.gui.event.TabPaneChangedListener;
037: import java.awt.Component;
038: import java.awt.Dimension;
039: import java.awt.datatransfer.DataFlavor;
040: import java.awt.datatransfer.Transferable;
041: import java.awt.dnd.DnDConstants;
042: import java.awt.dnd.DropTarget;
043: import java.awt.dnd.DropTargetContext;
044: import java.awt.dnd.DropTargetDragEvent;
045: import java.awt.dnd.DropTargetDropEvent;
046: import java.awt.dnd.DropTargetEvent;
047: import java.awt.dnd.DropTargetListener;
048: import java.awt.event.ActionEvent;
049: import java.awt.event.ActionListener;
050: import java.beans.PropertyChangeListener;
051: import java.util.HashMap;
052: import java.util.Vector;
053: import javax.swing.Icon;
054: import javax.swing.JButton;
055: import javax.swing.JPanel;
056: import javax.swing.JSplitPane;
057: import it.businesslogic.ireport.util.I18n;
058:
059: /**
060: *
061: * @author gtoffoli
062: */
063: public class DockingContainer extends javax.swing.JPanel implements
064: TabPaneChangedListener, ActionListener {
065:
066: public static final int INSERT_MODE_SHAREDPOSTION = 0;
067: public static final int INSERT_MODE_NEWPOSITION = 1;
068:
069: private int oldWidth = 0;
070: private boolean compressed = false;
071:
072: private Vector panelViews = new Vector();
073: private Vector tabPanes = new Vector();
074: private int positions = 0;
075:
076: private DropTarget dropTarget;
077: private DropTargetListener dtListener;
078:
079: public static final int POSITION_RIGHT = 0;
080: public static final int POSITION_LEFT = 1;
081:
082: private int position = POSITION_LEFT;
083:
084: private int preferredDividerLocation = -1;
085: private int realCurrentSize = 0;
086:
087: /** Creates new form DockingContainer */
088: public DockingContainer() {
089: this (POSITION_LEFT);
090: }
091:
092: public DockingContainer(int position) {
093: initComponents();
094:
095: this .setSize(new Dimension(200, 100));
096: this .setPreferredSize(new Dimension(200, 100));
097:
098: this .dtListener = new DTListener();
099: // component, ops, listener, accepting
100:
101: this .setDropTarget(new DropTarget(this ,
102: DnDConstants.ACTION_MOVE, new DTListener()));
103: this .setBorder(null);
104: applyI18n();
105:
106: }
107:
108: private JButton createButton(PanelView pv) {
109:
110: JButton jButton = new JButton();
111:
112: Icon icon = new VTextIcon(
113: jButton1,
114: pv.getName(),
115: (getPosition() == POSITION_LEFT) ? VTextIcon.ROTATE_LEFT
116: : VTextIcon.ROTATE_RIGHT);
117: jButton.setIcon(icon);
118: jButton.setPreferredSize(new Dimension(20,
119: icon.getIconHeight() + 28));
120: jButton.setMinimumSize(new Dimension(20,
121: icon.getIconHeight() + 28));
122:
123: jButton.setActionCommand(pv.getId() + "");
124: jButton.addActionListener(this );
125:
126: return jButton;
127: }
128:
129: public void actionPerformed(ActionEvent e) {
130:
131: // Button pressed...
132: String s = e.getActionCommand();
133: try {
134: PanelView pv = getPanelViewById(Integer.parseInt(s));
135:
136: pv.setMinimized(false);
137: pv.setPosition(positions);
138:
139: recreateAll();
140: } catch (Exception ex) {
141:
142: ex.printStackTrace();
143: }
144:
145: }
146:
147: /**
148: * Add a component under the other
149: *
150: */
151: public void addPanel(String name, Component component,
152: boolean closable) {
153: insertPanel(positions, name, component, closable);
154:
155: }
156:
157: /*
158: public void addDropTarget(Component comp)
159: {
160: System.out.println( comp );
161: if (comp.getDropTarget() == null)
162: {
163: comp.setDropTarget( this.getDropTarget() );
164: }
165:
166: if (comp instanceof JComponent)
167: {
168: JComponent component = (JComponent)comp;
169: if (component.getDropTarget() == null)
170: {
171: component.setDropTarget( this.getDropTarget() );
172: }
173:
174: for (int i=0; i<component.getComponentCount(); ++i)
175: {
176: addDropTarget( component.getComponent(i) );
177: }
178: }
179: }
180: */
181:
182: public boolean contains(Component c) {
183: for (int i = 0; i < getPanelViews().size(); ++i) {
184: PanelView pv = (PanelView) getPanelViews().elementAt(i);
185: if (pv.getComponent() == c) {
186: return true;
187: }
188: }
189:
190: return false;
191: }
192:
193: /**
194: * Returns the panel view containing the Component c.
195: * Null if the component is not found.
196: *
197: */
198: public PanelView getPanelView(Component c) {
199: for (int i = 0; i < getPanelViews().size(); ++i) {
200: PanelView pv = (PanelView) getPanelViews().elementAt(i);
201: if (pv.getComponent() == c) {
202: return pv;
203: }
204: }
205:
206: return null;
207: }
208:
209: /**
210: * Returns the panel view containing the Component c.
211: * Null if the component is not found.
212: *
213: */
214: public PanelView getPanelViewById(int id) {
215: for (int i = 0; i < getPanelViews().size(); ++i) {
216: PanelView pv = (PanelView) getPanelViews().elementAt(i);
217: if (pv.getId() == id) {
218: return pv;
219: }
220: }
221:
222: return null;
223: }
224:
225: public void insertPanel(int position, String name,
226: Component component, int insertMode, boolean closable) {
227: if (component == null)
228: return;
229: if (name == null)
230: name = "Panel";
231:
232: // Check if the component is already present somewhere...
233: for (int i = 0; i < getPanelViews().size(); ++i) {
234: PanelView pv = (PanelView) getPanelViews().elementAt(i);
235: if (pv.getComponent() == component) {
236: return;
237: }
238: }
239:
240: //addDropTarget( component );
241:
242: //if (component.getDropTarget() == null)
243: //{
244: // component.setDropTarget(new DropTarget(component, new GenericDragTargetListener()));
245: //}
246:
247: //System.out.println("Added panel " + name + " at position " + position);
248: if (position >= positions) {
249: position = positions;
250: positions++;
251: } else if (insertMode == INSERT_MODE_NEWPOSITION) {
252: for (int i = 0; i < getPanelViews().size(); ++i) {
253: PanelView pv = (PanelView) getPanelViews().elementAt(i);
254:
255: if (pv.getPosition() >= position) {
256: pv.setPosition(pv.getPosition() + 1);
257: }
258: }
259: positions++;
260: }
261:
262: panelViews.add(new PanelView(name, component, position,
263: closable));
264: recreateAll();
265:
266: }
267:
268: /**
269: * Add a component at position
270: *
271: */
272: public void insertPanel(int position, String name,
273: Component component, boolean closable) {
274: insertPanel(position, name, component, INSERT_MODE_NEWPOSITION,
275: closable);
276: }
277:
278: /**
279: * Add a component at position
280: *
281: */
282: public void removePanel(Component component) {
283:
284: int position = -1;
285: for (int i = 0; i < getPanelViews().size(); ++i) {
286: PanelView pv = (PanelView) getPanelViews().elementAt(i);
287:
288: if (pv.getComponent() == component) {
289: position = pv.getPosition();
290: //System.out.println("removing panel " + pv.getName() + " at position " + pv.getPosition());
291: getPanelViews().remove(pv);
292: break;
293: }
294: }
295:
296: // If "position" is not used, normalize all...
297: if (position >= 0) {
298: boolean found = false;
299: for (int i = 0; i < getPanelViews().size(); ++i) {
300: PanelView pv = (PanelView) getPanelViews().elementAt(i);
301: if (pv.isMinimized())
302: continue;
303: if (pv.getPosition() == position) {
304: found = true;
305: break;
306: }
307: }
308:
309: if (!found) {
310: for (int i = 0; i < getPanelViews().size(); ++i) {
311: PanelView pv = (PanelView) getPanelViews()
312: .elementAt(i);
313: if (pv.isMinimized())
314: continue;
315: if (pv.getPosition() > position) {
316: pv.setPosition(pv.getPosition() - 1);
317: }
318: }
319: positions--;
320: }
321: recreateAll();
322: }
323: this .updateUI();
324: }
325:
326: private void normalizePositions() {
327: // 1. Find the number of different positions....
328: HashMap map = new HashMap();
329: int differentPositions = 0;
330:
331: for (int i = 0; i < getPanelViews().size(); ++i) {
332: PanelView pv = (PanelView) getPanelViews().elementAt(i);
333: if (pv.isMinimized())
334: continue;
335: map.put(new Integer(pv.getPosition()), "");
336: }
337:
338: differentPositions = map.size();
339:
340: for (int k = 0; k < differentPositions; ++k) {
341:
342: while (getPanelCount(k) == 0) {
343: // position = position -1 for all panels with position >= k
344: downPosition(k);
345: }
346: }
347:
348: this .positions = differentPositions;
349: }
350:
351: /* if position > minimumPosition -> position = position - 1;
352: *
353: */
354: private void downPosition(int minimumPosition) {
355: for (int i = 0; i < getPanelViews().size(); ++i) {
356: PanelView pv = (PanelView) getPanelViews().elementAt(i);
357: if (pv.isMinimized())
358: continue;
359: if (pv.getPosition() > minimumPosition) {
360: pv.setPosition(pv.getPosition() - 1);
361: }
362: }
363: }
364:
365: /**
366: * Use this panelView to describe the panel to move. Only component and name are used
367: * to move the component in the newPosition
368: * panelView.component is removed then inserted again in newPosition with label panelView.name
369: */
370: public void moveComponent(PanelView panelView, int newPosition) {
371: moveComponent(panelView, newPosition, INSERT_MODE_NEWPOSITION);
372: }
373:
374: /**
375: * Use this panelView to describe the panel to move. Only component and name are used
376: * to move the component in the newPosition
377: * panelView.component is removed then inserted again in newPosition with label panelView.name
378: */
379: public void moveComponent(PanelView panelView, int newPosition,
380: int mode) {
381: removePanel(panelView.getComponent());
382: insertPanel(newPosition, panelView.getName(), panelView
383: .getComponent(), mode, panelView.isClosable());
384: }
385:
386: /**
387: * Use this panelView to describe the panel to move. Only component and name are used
388: * to move the component in the newPosition
389: * panelView.component is removed then inserted again in newPosition with label panelView.name
390: */
391: public void mergePosition(int newPosition) {
392: if (positions == 1)
393: return;
394: if (newPosition >= positions)
395: return;
396: if (newPosition == 0 && positions > 1)
397: newPosition = 1;
398: for (int i = 0; i < getPanelViews().size(); ++i) {
399: PanelView pv = (PanelView) getPanelViews().elementAt(i);
400:
401: if (pv.isMinimized())
402: continue;
403:
404: if (pv.getPosition() >= newPosition) {
405: pv.setPosition(pv.getPosition() - 1);
406: }
407:
408: }
409:
410: positions--;
411: recreateAll();
412: }
413:
414: public void recreateAll() {
415: this .removeAll();
416:
417: jPanel1.removeAll();
418:
419: int numPositions = positions;
420:
421: normalizePositions();
422:
423: if (positions > 0) {
424: if (compressed) {
425: compressed = false;
426: this .setSize(getOldWidth(), 1);
427: }
428:
429: tabPanes.removeAllElements();
430: Vector tabbedPanes = new Vector();
431: if (positions == 0)
432: return;
433:
434: add(addComponents(0), java.awt.BorderLayout.CENTER);
435: this .updateUI();
436: } else {
437: compressed = true;
438: setOldWidth(getSize().width);
439: this .setSize(0, 1);
440: }
441:
442: int minimizedButton = 0;
443: for (int i = 0; i < getPanelViews().size(); ++i) {
444: PanelView pv = (PanelView) getPanelViews().elementAt(i);
445: if (pv.isMinimized()) {
446: JButton b = createButton(pv);
447: java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
448: gridBagConstraints.gridx = 0;
449: gridBagConstraints.weightx = 1.0;
450: gridBagConstraints.weighty = 0;
451: jPanel1.add(b, gridBagConstraints);
452: minimizedButton++;
453: }
454: }
455:
456: if (minimizedButton > 0) {
457: java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
458: gridBagConstraints.gridx = 0;
459: gridBagConstraints.weightx = 1.0;
460: gridBagConstraints.weighty = 1.0;
461: jPanel1.add(new JPanel(), gridBagConstraints);
462: add(
463: jPanel1,
464: (getPosition() == POSITION_LEFT) ? java.awt.BorderLayout.WEST
465: : java.awt.BorderLayout.EAST);
466: }
467:
468: if (this .getParent() != null
469: && this .getParent() instanceof JSplitPane) {
470: JSplitPane sp = (JSplitPane) this .getParent();
471: int currentWidth = realCurrentSize;
472: if (positions == 0) {
473:
474: //this.setPreferredSize(new Dimension(24,0));
475:
476: if (getPosition() == POSITION_LEFT) {
477: sp.setDividerLocation(jPanel1.getWidth());
478: } else {
479:
480: //sp.setDividerLocation(1.0);
481: this .setSize(new Dimension(24, 0));
482: sp.setDividerLocation((int) (sp.getBounds()
483: .getWidth())
484: - sp.getDividerSize() - 24);
485: }
486: } else {
487: int width = currentWidth;
488: if (width <= 150 + 24) {
489: width = 150 + 24;
490: }
491: //this.setPreferredSize(new Dimension(width,0));
492: //this.setSize(new Dimension(width,0));
493: //this.setMinimumSize(new Dimension(width,0));
494: if (getPosition() == POSITION_LEFT) {
495: sp.setDividerLocation(width);
496: } else {
497: sp.setDividerLocation(getPreferredDividerLocation()
498: - (width - currentWidth));
499:
500: //sp.setDividerLocation();
501: //sp.setDividerLocation( sp.getWidth() - width );
502: }
503: }
504:
505: sp.updateUI();
506:
507: }
508: this .updateUI();
509: }
510:
511: public void setSelectedComponent(Component component) {
512: for (int i = 0; i < tabPanes.size(); ++i) {
513: JDraggableTabbedPane tab = (JDraggableTabbedPane) tabPanes
514: .get(i);
515:
516: try {
517: tab.setSelectedComponent(component);
518: break;
519: } catch (Exception ex) {
520: }
521: }
522: }
523:
524: public Component addComponents(int pos) {
525:
526: JDraggableTabbedPane jTabbedPane = new JDraggableTabbedPane();
527: jTabbedPane.setPosition(pos);
528: jTabbedPane.setOrientation(getPosition());
529: jTabbedPane.setDockingContainer(this );
530: jTabbedPane.addTabPaneChangedListener(this );
531:
532: tabPanes.add(jTabbedPane);
533:
534: for (int i = 0; i < getPanelViews().size(); ++i) {
535: PanelView pv = (PanelView) getPanelViews().elementAt(i);
536: if (pv.isMinimized())
537: continue;
538: if (pv.getPosition() == pos) {
539: jTabbedPane.addTab(pv.getName(), pv.getComponent(), pv
540: .isClosable());
541: }
542:
543: //System.out.println("Adding " + pv.getName() + " on position " + pos + "/" + positions);
544: }
545:
546: if (pos < positions - 1) {
547: javax.swing.JSplitPane jSplitPane = new javax.swing.JSplitPane();
548: jSplitPane
549: .setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
550: jSplitPane.setBorder(null);
551: //jSplitPane.setDividerSize(6);
552:
553: jSplitPane.setResizeWeight(1.0 / (positions - pos));
554: jSplitPane.setLeftComponent(jTabbedPane);
555: jSplitPane.setRightComponent(addComponents(pos + 1));
556: jSplitPane.setDividerSize(5);
557: return jSplitPane;
558: } else {
559: return jTabbedPane;
560: }
561: }
562:
563: public Vector getPanelViews() {
564: return panelViews;
565: }
566:
567: public int getPanelCount(int position) {
568: int p_number = 0;
569: for (int i = 0; i < getPanelViews().size(); ++i) {
570: PanelView pv = (PanelView) getPanelViews().elementAt(i);
571: if (pv.isMinimized())
572: continue;
573: if (pv.getPosition() == position) {
574: p_number++;
575: }
576: }
577:
578: return p_number;
579: }
580:
581: public void setPanelViews(Vector panelViews) {
582: this .panelViews = panelViews;
583: }
584:
585: public int getOldWidth() {
586: return oldWidth;
587: }
588:
589: public void setOldWidth(int oldWidth) {
590: this .oldWidth = oldWidth;
591: }
592:
593: public boolean isCompressed() {
594: return compressed;
595: }
596:
597: public void setCompressed(boolean compressed) {
598: this .compressed = compressed;
599: }
600:
601: /** This method is called from within the constructor to
602: * initialize the form.
603: * WARNING: Do NOT modify this code. The content of this method is
604: * always regenerated by the Form Editor.
605: */
606: // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
607: private void initComponents() {
608: java.awt.GridBagConstraints gridBagConstraints;
609:
610: jPanel1 = new javax.swing.JPanel();
611: jButton1 = new javax.swing.JButton();
612:
613: setLayout(new java.awt.BorderLayout());
614:
615: addComponentListener(new java.awt.event.ComponentAdapter() {
616: public void componentResized(
617: java.awt.event.ComponentEvent evt) {
618: formComponentResized(evt);
619: }
620: });
621:
622: jPanel1.setLayout(new java.awt.GridBagLayout());
623:
624: jPanel1.setPreferredSize(new java.awt.Dimension(24, 10));
625: jButton1.setBorder(null);
626: jButton1.setBorderPainted(false);
627: jButton1.setFocusPainted(false);
628: jButton1.setFocusable(false);
629: jButton1.setMaximumSize(new java.awt.Dimension(33, 500));
630: jButton1.setMinimumSize(new java.awt.Dimension(33, 100));
631: jButton1.setPreferredSize(new java.awt.Dimension(33, 100));
632: jButton1.setRequestFocusEnabled(false);
633: gridBagConstraints = new java.awt.GridBagConstraints();
634: gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
635: gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
636: gridBagConstraints.weightx = 1.0;
637: gridBagConstraints.weighty = 1.0;
638: jPanel1.add(jButton1, gridBagConstraints);
639:
640: add(jPanel1, java.awt.BorderLayout.WEST);
641:
642: }// </editor-fold>//GEN-END:initComponents
643:
644: private void formComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentResized
645:
646: realCurrentSize = (int) evt.getComponent().getSize().getWidth();
647: //System.out.println("Current size: " + );
648: }//GEN-LAST:event_formComponentResized
649:
650: public void tabPaneChanged(TabPaneChangedEvent evt) {
651:
652: if (evt.getOperation() == evt.CLOSED) {
653: this .removePanel(evt.getTabComponent());
654:
655: } else if (evt.getOperation() == evt.MINIMIZED) {
656: // Look for the right panel view..
657: PanelView pv = getPanelView(evt.getTabComponent());
658: pv.setMinimized(true);
659: recreateAll();
660: }
661:
662: }
663:
664: // Variables declaration - do not modify//GEN-BEGIN:variables
665: private javax.swing.JButton jButton1;
666: private javax.swing.JPanel jPanel1;
667:
668: // End of variables declaration//GEN-END:variables
669:
670: class DTListener implements DropTargetListener {
671:
672: /**
673: * start "drag under" feedback on component
674: * invoke acceptDrag or rejectDrag based on isDragOk
675: */
676: public void dragEnter(DropTargetDragEvent e) {
677: e.acceptDrag(e.getDropAction());
678: }
679:
680: /**
681: * continue "drag under" feedback on component
682: * invoke acceptDrag or rejectDrag based on isDragOk
683: */
684: public void dragOver(DropTargetDragEvent e) {
685: e.acceptDrag(e.getDropAction());
686: }
687:
688: public void dropActionChanged(DropTargetDragEvent e) {
689: }
690:
691: public void dragExit(DropTargetEvent e) {
692: }
693:
694: /**
695: * perform action from getSourceActions on
696: * the transferrable
697: * invoke acceptDrop or rejectDrop
698: * invoke dropComplete
699: * if its a local (same JVM) transfer, use StringTransferable.localStringFlavor
700: * find a match for the flavor
701: * check the operation
702: * get the transferable according to the chosen flavor
703: * do the transfer
704: */
705: public void drop(DropTargetDropEvent dtde) {
706: try {
707:
708: DropTargetContext context = dtde.getDropTargetContext();
709:
710: Transferable tr = dtde.getTransferable();
711:
712: DataFlavor[] df = tr.getTransferDataFlavors();
713:
714: if (df[0]
715: .getHumanPresentableName()
716: .equals(
717: "it.businesslogic.ireport.gui.docking.PanelView")) {
718: java.awt.datatransfer.DataFlavor myFlavor = new java.awt.datatransfer.DataFlavor(
719: it.businesslogic.ireport.gui.docking.PanelView.class,
720: it.businesslogic.ireport.gui.docking.PanelView.class
721: .getName());
722: it.businesslogic.ireport.gui.docking.PanelView panelView = (it.businesslogic.ireport.gui.docking.PanelView) tr
723: .getTransferData(myFlavor);
724:
725: if (DockingContainer.this != null) {
726: if (panelView.getDockingContainer() != DockingContainer.this ) {
727: panelView.getDockingContainer()
728: .removePanel(
729: panelView.getComponent());
730: DockingContainer.this .insertPanel(0,
731: panelView.getName(), panelView
732: .getComponent(), panelView
733: .isClosable());
734: }
735: }
736: }
737:
738: context.dropComplete(true);
739: } catch (Exception ex) {
740: ex.printStackTrace();
741: }
742: }
743:
744: }
745:
746: public int getPosition() {
747: return position;
748: }
749:
750: public void setPosition(int position) {
751: this .position = position;
752: }
753:
754: public int getPreferredDividerLocation() {
755: return preferredDividerLocation;
756: }
757:
758: public void setPreferredDividerLocation(int preferredDividerLocation) {
759: this .preferredDividerLocation = preferredDividerLocation;
760: }
761:
762: public void applyI18n() {
763: // Start autogenerated code ----------------------
764: // End autogenerated code ----------------------
765:
766: }
767: }
|