001: // THIS SOFTWARE IS PROVIDED BY SOFTARIS PTY.LTD. AND OTHER METABOSS
002: // CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
003: // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
004: // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTARIS PTY.LTD.
005: // OR OTHER METABOSS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
006: // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
007: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
008: // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
009: // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
010: // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
011: // EVEN IF SOFTARIS PTY.LTD. OR OTHER METABOSS CONTRIBUTORS ARE ADVISED OF THE
012: // POSSIBILITY OF SUCH DAMAGE.
013: //
014: // Copyright 2000-2005 © Softaris Pty.Ltd. All Rights Reserved.
015: package com.metaboss.applications.designstudio.components;
016:
017: import java.awt.AWTEvent;
018: import java.awt.BorderLayout;
019: import java.awt.Color;
020: import java.awt.Component;
021: import java.awt.Container;
022: import java.awt.Dimension;
023: import java.awt.EventQueue;
024: import java.awt.Font;
025: import java.awt.Graphics;
026: import java.awt.Graphics2D;
027: import java.awt.LayoutManager;
028: import java.awt.Rectangle;
029: import java.awt.Shape;
030: import java.awt.SystemColor;
031: import java.awt.Toolkit;
032: import java.awt.event.ActionEvent;
033: import java.awt.event.ActionListener;
034: import java.awt.event.MouseAdapter;
035: import java.awt.event.MouseEvent;
036: import java.awt.event.MouseMotionAdapter;
037: import java.util.ArrayList;
038: import java.util.EventListener;
039:
040: import javax.swing.AbstractAction;
041: import javax.swing.GrayFilter;
042: import javax.swing.Icon;
043: import javax.swing.ImageIcon;
044: import javax.swing.JButton;
045: import javax.swing.JPanel;
046: import javax.swing.JPopupMenu;
047: import javax.swing.SwingUtilities;
048: import javax.swing.UIManager;
049: import javax.swing.plaf.IconUIResource;
050:
051: import com.metaboss.applications.designstudio.Application;
052: import com.metaboss.applications.designstudio.BaseChildPanel;
053: import com.metaboss.applications.designstudio.Application.OnModelChangedEvent;
054: import com.metaboss.sdlctools.models.metabossmodel.MetaBossModelPackage;
055:
056: /* Tab control panel class */
057:
058: public class TabPanel extends JPanel {
059: public static final int MAX_ITEM_WIDTH = 300;
060: public static final int MIN_HEIGHT = 24;
061: public static final int BUT_SIZE = 16;
062: // close button regimes
063: public static final int CB_INVISIBLE = 0;
064: public static final int CB_VISIBLE = 1;
065: public static final int CB_FLOATING = 2;
066: public static final int CB_ONEFORALL = 3;
067:
068: // convert close button regime to sting
069: public static String regimeToString(int pRegime) {
070: switch (pRegime) {
071: case CB_INVISIBLE:
072: return "Invisible";
073: case CB_VISIBLE:
074: return "Visible";
075: case CB_FLOATING:
076: return "Floating";
077: case CB_ONEFORALL:
078: return "One For All";
079: }
080: return "";
081: }
082:
083: protected LeftButton mLeftButton = new LeftButton();
084: protected RightButton mRightButton = new RightButton();
085: protected TabCloseButton mCloseButton = new TabCloseButton();
086:
087: protected ArrayList mItems = new ArrayList();
088: protected int mTabIndex = -1;
089: protected int mMouseTabIndex = -1;
090: protected int mVisibleItemsCount = 0;
091: protected int mFirstVisibleIndex = 0;
092: protected Container mContent = null;
093: protected int mCloseRegime = CB_INVISIBLE;
094: protected boolean mShowIcons = true;
095: private Color mBackColor = new Color(255, 253, 243);
096:
097: private CloseTabAction mCloseTabAction = new CloseTabAction();
098: private MoveLeftAction mMoveLeftAction = new MoveLeftAction();
099: private MoveRightAction mMoveRightAction = new MoveRightAction();
100:
101: /* constructors */
102:
103: public TabPanel(LayoutManager layout, boolean isDoubleBuffered) {
104: super (layout, isDoubleBuffered);
105: defineProperties();
106: }
107:
108: public TabPanel(LayoutManager layout) {
109: super (layout);
110: defineProperties();
111: }
112:
113: public TabPanel(boolean isDoubleBuffered) {
114: super (isDoubleBuffered);
115: defineProperties();
116: }
117:
118: public TabPanel(Container pContent) {
119: super ();
120: mContent = pContent;
121: defineProperties();
122: }
123:
124: // add tab
125: public int addTab(String lCaption, String pName,
126: BaseChildPanel pPanel, Icon mIcon) {
127: mItems.add(new TabPanelItem(lCaption, pName, this , pPanel,
128: mIcon));
129: int lIndex = mItems.size() - 1;
130: if (!isIndexVisible(lIndex))
131: makeTabVisible(lIndex);
132: else
133: updateTabs();
134: setTabIndex(lIndex);
135: return lIndex;
136: }
137:
138: // delete tab
139: public void deleteTab(int pIndex) {
140: TabPanelItem lItem = getItem(pIndex);
141: if (lItem != null) {
142: if (lItem.mButton != null) {
143: lItem.mButton.setVisible(false);
144: remove(lItem.mButton);
145: lItem.mButton = null;
146: }
147: if (lItem.mPanel != null) {
148: lItem.mPanel.setVisible(false);
149: lItem.mPanel.removeEventsListeners();
150: mContent.remove(lItem.mPanel);
151: lItem.mPanel = null;
152: }
153: }
154: mItems.remove(pIndex);
155: if (mFirstVisibleIndex + mVisibleItemsCount > getTabCount()) {
156: mFirstVisibleIndex = getTabCount() - mVisibleItemsCount;
157: if (mFirstVisibleIndex < 0)
158: mFirstVisibleIndex = 0;
159: }
160: updateTabs();
161:
162: pIndex--;
163: if (pIndex < 0 && mItems.size() > 0)
164: pIndex = 0;
165: if (pIndex < mItems.size())
166: setTabIndex(pIndex);
167: }
168:
169: // clear tabs
170: public void clearAll() {
171: while (getTabCount() > 0)
172: deleteTab(getTabCount() - 1);
173: changed();
174: }
175:
176: // move tab left
177: public void moveTabLeft(int pIndex) {
178: if (pIndex < 1)
179: return;
180:
181: TabPanelItem lOldItem = getItem(pIndex - 1);
182: TabPanelItem lItem = getItem(pIndex);
183:
184: mItems.set(pIndex, lOldItem);
185: mItems.set(pIndex - 1, lItem);
186:
187: if (mTabIndex == pIndex)
188: mTabIndex--;
189: else if (mTabIndex == pIndex - 1)
190: mTabIndex++;
191:
192: updateTabs();
193: }
194:
195: // move tab right
196: public void moveTabRight(int pIndex) {
197: if (pIndex >= getTabCount() - 1)
198: return;
199:
200: TabPanelItem lOldItem = getItem(pIndex + 1);
201: TabPanelItem lItem = getItem(pIndex);
202:
203: mItems.set(pIndex, lOldItem);
204: mItems.set(pIndex + 1, lItem);
205:
206: if (mTabIndex == pIndex)
207: mTabIndex++;
208: else if (mTabIndex == pIndex + 1)
209: mTabIndex--;
210:
211: updateTabs();
212: }
213:
214: // update tabs
215: public void updateTabs() {
216: checkPanels();
217: calcRectangles();
218: checkButtons();
219: repaint();
220: }
221:
222: // find tab index by caption
223: public int findTabIndexByName(String pName) {
224: for (int i = 0; i < mItems.size(); i++)
225: if (getItem(i).mName.equals(pName))
226: return i;
227: return -1;
228: }
229:
230: // reset tab caption
231: public void setTabCaption(String pCaption, int pIndex) {
232: TabPanelItem lItem = getItem(pIndex);
233: if (lItem != null) {
234: lItem.mCaption = pCaption;
235: repaint();
236: }
237: }
238:
239: // close active window
240: public void closeActiveWindow() {
241: int lCurrentIndex = getTabIndex();
242: if (lCurrentIndex > -1)
243: deleteTab(lCurrentIndex);
244: }
245:
246: public void addTabPanelEventListener(TabPanelListener listener) {
247: listenerList.add(TabPanelListener.class, listener);
248: }
249:
250: public void removeTabPanelEventListener(TabPanelListener listener) {
251: listenerList.remove(TabPanelListener.class, listener);
252: }
253:
254: protected void processEvent(AWTEvent e) {
255: if (e instanceof TabPanelEvent) {
256: EventListener[] listeners = listenerList
257: .getListeners(TabPanelListener.class);
258: for (int i = 0; i < listeners.length; i++)
259: ((TabPanelListener) listeners[i])
260: .tabChanged((TabPanelEvent) e);
261: } else
262: super .processEvent(e);
263: }
264:
265: /* properties accessors */
266:
267: public int getTabIndex() {
268: return mTabIndex;
269: }
270:
271: public void setTabIndex(int pValue) {
272: if (mTabIndex != pValue) {
273: mTabIndex = pValue;
274: if (!isIndexVisible(mTabIndex))
275: makeTabVisible(mTabIndex);
276: else
277: updateTabs();
278: changed();
279: }
280: }
281:
282: public int getTabCount() {
283: return mItems.size();
284: }
285:
286: public int getCloseRegime() {
287: return mCloseRegime;
288: }
289:
290: public void setCloseRegime(int pValue) {
291: if (mCloseRegime != pValue) {
292: mCloseRegime = pValue;
293: //checkButtons();
294: updateTabs();
295: }
296: }
297:
298: // return current container
299: public Container getCurrentPanel() {
300: if (mTabIndex > -1) {
301: TabPanelItem lItem = getItem(mTabIndex);
302: if (lItem != null)
303: return lItem.mPanel;
304: }
305: return null;
306: }
307:
308: public Container getPanel(int pIndex) {
309: TabPanelItem lItem = getItem(pIndex);
310: if (lItem != null)
311: return lItem.mPanel;
312: else
313: return null;
314: }
315:
316: // paint tab control
317: public void paintComponent(Graphics g) {
318: super .paintComponent(g);
319:
320: Rectangle lRect = getBounds();
321: //g.setColor(getParent().getBackground());
322: //g.fillRect(lRect.x, lRect.y, lRect.width, lRect.height);
323:
324: g.setColor(Color.white);
325: g.drawLine(lRect.x, lRect.y + lRect.height - 2, lRect.x
326: + lRect.width, lRect.y + lRect.height - 2);
327:
328: for (int i = mFirstVisibleIndex; i <= mFirstVisibleIndex
329: + mVisibleItemsCount; i++)
330: paintItem(g, getItem(i), i == mTabIndex);
331:
332: Dimension lDim = getSize();
333: g.setColor(SystemColor.controlShadow);
334: g.drawLine(0, lDim.height - 1, lDim.width, lDim.height - 1);
335: }
336:
337: public Icon getDisabledIcon(TabPanelItem pItem) {
338: if (pItem.mDisabledIcon == null && pItem.mIcon != null) {
339: pItem.mDisabledIcon = new IconUIResource(
340: new ImageIcon(
341: GrayFilter
342: .createDisabledImage(((ImageIcon) pItem.mIcon)
343: .getImage())));
344: }
345: return pItem.mDisabledIcon;
346: }
347:
348: public void setSize(int width, int height) {
349: int lOldWidth = getWidth();
350: super .setSize(width, height);
351: if (lOldWidth != width)
352: updateTabs();
353: }
354:
355: // paint item
356: protected void paintItem(Graphics g, TabPanelItem pItem,
357: boolean pSelected) {
358: if (pItem == null)
359: return;
360:
361: Graphics2D g2 = (Graphics2D) g;
362: Color lColor = getParent().getBackground();
363: Rectangle lRect = pItem.getCorrectedRect();
364: int lLeftButlocation = mLeftButton.getLocation().x - 2;
365: boolean lNeedRightBorder = true;
366:
367: if (lRect.x + lRect.width > lLeftButlocation) {
368: lRect.width = lLeftButlocation - lRect.x;
369: lNeedRightBorder = false;
370: }
371:
372: Shape lOldClip = g2.getClip();
373: g2.setClip(lRect);
374:
375: if (lRect.x + lRect.width > lLeftButlocation) {
376: lRect.width = mLeftButton.getLocation().x - 2 - lRect.x;
377: if (lRect.width < 0)
378: lRect.width = 0;
379: }
380:
381: // fill background
382: if (pSelected) {
383: /*g2.setPaint(new GradientPaint(
384: pItem.mRect.x, pItem.mRect.y, UIManager.getColor("control"),
385: pItem.mRect.x + pItem.mRect.width, pItem.mRect.y, lColor));*/
386: g2.setColor(UIManager.getColor("control"));
387: g2.fillRect(lRect.x, lRect.y, lRect.width, lRect.height);
388: } else {
389: //g2.setColor(lColor);
390: //g2.fillRect(pItem.mRect.x, pItem.mRect.y, pItem.mRect.x+pItem.mRect.width, pItem.mRect.y+pItem.mRect.height);
391: }
392:
393: // paint icon
394: int lxStep = 0;
395: if (mShowIcons && pItem.mIcon != null) {
396: int lh = (getHeight() - pItem.mIcon.getIconHeight()) / 2;
397: int lx = lRect.x + 2;
398: if (!pSelected)
399: getDisabledIcon(pItem).paintIcon(this , g, lx, lh);
400: else
401: pItem.mIcon.paintIcon(this , g, lx, lh);
402: lxStep += pItem.mIcon.getIconWidth();
403: }
404:
405: // paint caption
406: int lStep = getFontMetrics(g.getFont()).getHeight() / 2;
407: lStep = (pItem.mRect.height + lStep) / 2;
408: if (pSelected) {
409: g2.setFont(getFont().deriveFont(Font.BOLD));
410: g2.setColor(SystemColor.windowText);
411: } else {
412: g2.setFont(getFont());
413: g2.setColor(SystemColor.inactiveCaption);
414: }
415: //Shape lOldClip = g2.getClip();
416: //g2.setClip(lRect);
417: g2.drawString(pItem.mCaption, lRect.x + 5 + lxStep, lRect.y
418: + lStep);
419: //g2.setClip(lOldClip);
420:
421: // paint borders
422: if (pSelected) {
423: g2.setColor(Color.white);
424: g2.drawLine(lRect.x, lRect.y, lRect.x, lRect.y
425: + lRect.height);
426: g2.drawLine(lRect.x, lRect.y, lRect.x + lRect.width,
427: lRect.y);
428: if (lNeedRightBorder) {
429: int lx = lRect.x + lRect.width - 1;
430:
431: g2.setColor(Color.black);
432: g2.drawLine(lx, lRect.y + 1, lx, lRect.y + lRect.height
433: - 2);
434: }
435: } else {
436: if (lNeedRightBorder) {
437: int ly = lRect.height / 2;
438: int lx = lRect.x + lRect.width - 1;
439: g2.setColor(SystemColor.controlShadow);
440: g2.drawLine(lx, lRect.y, lx, lRect.y + ly);
441: }
442: }
443:
444: g2.setClip(lOldClip);
445: }
446:
447: // claculate items coordinates
448: protected void calcRectangles() {
449: Graphics g = getGraphics();
450:
451: clearRectangles();
452:
453: Dimension lDim = getSize();
454: int lStartX = 5;
455:
456: lDim.width -= BUT_SIZE * 2;
457: lDim.height -= 1;
458: if (mCloseRegime == CB_ONEFORALL)
459: lDim.width -= BUT_SIZE;
460:
461: int lStep = (lDim.height - BUT_SIZE) / 2;
462: //int lCalcWidth = (mItems.size()>0) ? lDim.width / mItems.size() : 0;
463:
464: for (int i = 0; i < mItems.size(); i++) {
465: TabPanelItem lItem = getItem(i);
466: if (lItem != null) {
467: if (i == mTabIndex)
468: g.setFont(getFont().deriveFont(Font.BOLD));
469: else
470: g.setFont(getFont());
471:
472: double ld = getFontMetrics(g.getFont())
473: .getStringBounds(lItem.mCaption, g).getWidth();
474: int lWidht = new Double(ld).intValue() + 6;
475: if (mShowIcons && lItem.mIcon != null)
476: lWidht += lItem.mIcon.getIconWidth() + 4;
477: //???if (lWidht>lCalcWidth) lWidht = lCalcWidth;
478:
479: if (mCloseRegime == CB_VISIBLE)
480: lWidht += BUT_SIZE;
481: //???if (lWidht>MAX_ITEM_WIDTH) lWidht = MAX_ITEM_WIDTH;
482:
483: lItem.mRect.setBounds(lStartX, 1, lWidht, lDim.height);
484: lItem.mButtonRect.setBounds(lStartX + lWidht - BUT_SIZE
485: - 2, lStep, BUT_SIZE, BUT_SIZE);
486: lItem.mButton.setBounds(lItem.mButtonRect);
487: lStartX += lWidht;
488:
489: if (lItem.mRect.x + lItem.mRect.width < lDim.width)
490: mVisibleItemsCount++;
491: }
492: }
493:
494: mLeftButton.setBounds(lDim.width, lStep, BUT_SIZE, BUT_SIZE);
495: mRightButton.setBounds(lDim.width + BUT_SIZE, lStep, BUT_SIZE,
496: BUT_SIZE);
497: if (mCloseRegime == CB_ONEFORALL)
498: mCloseButton.setBounds(lDim.width + BUT_SIZE * 2, lStep,
499: BUT_SIZE, BUT_SIZE);
500: }
501:
502: // clear tabs rectangles
503: protected void clearRectangles() {
504: mVisibleItemsCount = 0;
505: for (int i = 0; i < mItems.size(); i++)
506: getItem(i).clearRect();
507: }
508:
509: // get tab item
510: protected TabPanelItem getItem(int pIndex) {
511: try {
512: return (TabPanelItem) mItems.get(pIndex);
513: } catch (Throwable e) {
514: return null;
515: }
516: }
517:
518: // fire tab control changed event
519: protected void changed() {
520: TabPanelEvent lEvent = new TabPanelEvent(this );
521: EventQueue queue = Toolkit.getDefaultToolkit()
522: .getSystemEventQueue();
523: queue.postEvent(lEvent);
524: }
525:
526: // define initial properties
527: private void defineProperties() {
528: setBackground(mBackColor);
529:
530: add(mLeftButton, BorderLayout.EAST);
531: mLeftButton.setVisible(false);
532: mLeftButton.setBackground(mBackColor);
533: mLeftButton.addActionListener(new ActionListener() {
534: public void actionPerformed(ActionEvent e) {
535: scrollLeft();
536: }
537: });
538: add(mRightButton, BorderLayout.EAST);
539: mRightButton.setVisible(false);
540: mRightButton.setBackground(mBackColor);
541: mRightButton.addActionListener(new ActionListener() {
542: public void actionPerformed(ActionEvent e) {
543: scrollRight();
544: }
545: });
546: add(mCloseButton, BorderLayout.EAST);
547: mCloseButton.setVisible(false);
548: mCloseButton.setBackground(mBackColor);
549: mCloseButton.addActionListener(new ActionListener() {
550: public void actionPerformed(ActionEvent e) {
551: closeActiveWindow();
552: }
553: });
554:
555: setLayout(new BorderLayout() {
556: public Dimension minimumLayoutSize(Container target) {
557: Dimension lDim = super .minimumLayoutSize(target);
558: if (lDim.height < getMinHeight())
559: lDim.height = getMinHeight();
560: return lDim;
561: }
562:
563: public Dimension preferredLayoutSize(Container target) {
564: Dimension lDim = super .preferredLayoutSize(target);
565: if (lDim.height < getMinHeight())
566: lDim.height = getMinHeight();
567: return lDim;
568: }
569:
570: public void layoutContainer(Container target) {
571: //???
572: }
573: });
574:
575: addMouseListener(new MouseAdapter() {
576: public void mousePressed(MouseEvent e) {
577: if (SwingUtilities.isLeftMouseButton(e)) {
578: int lIndex = getItemIndexByXY(e.getX(), e.getY());
579: if (lIndex != -1)
580: setTabIndex(lIndex);
581: } else if (e.isPopupTrigger()) {
582: showPopUp(e.getX(), e.getY());
583: }
584: super .mousePressed(e);
585: }
586:
587: public void mouseReleased(MouseEvent e) {
588: if (e.isPopupTrigger()) {
589: showPopUp(e.getX(), e.getY());
590: }
591: super .mouseReleased(e);
592: }
593: });
594:
595: addMouseMotionListener(new MouseMotionAdapter() {
596: public void mouseMoved(MouseEvent e) {
597: int lMouseTabIndex = getItemIndexByXY(e.getX(), e
598: .getY());
599: if (lMouseTabIndex != mMouseTabIndex) {
600: mMouseTabIndex = lMouseTabIndex;
601: checkButtons();
602: }
603: }
604: });
605:
606: Application
607: .addOnModelChangedListener(new Application.OnModelChangedListener() {
608: public void modelChanged(OnModelChangedEvent event) {
609: if (event.getEventSource() == OnModelChangedEvent.MODEL_CLOSED) {
610: closeAllTabsForPackage(event.getModel()
611: .getPackage());
612: }
613: }
614: });
615: }
616:
617: private void closeAllTabsForPackage(MetaBossModelPackage pPackage) {
618: int i = 0;
619: while (i < mItems.size()) {
620: TabPanelItem lItem = getItem(i);
621: if (lItem.mPanel.getPackage().equals(pPackage))
622: deleteTab(i);
623: else
624: i++;
625: }
626: }
627:
628: // return item by X, Y coordinates
629: private int getItemIndexByXY(int X, int Y) {
630: for (int i = 0; i < mItems.size(); i++) {
631: Rectangle lRect = getItem(i).getCorrectedRect();
632: ;
633: if (lRect.contains(X, Y))
634: return i;
635: }
636: return -1;
637: }
638:
639: // get minimal control height
640: private int getMinHeight() {
641: return MIN_HEIGHT;
642: }
643:
644: // create button for tab
645: private void checkButtons() {
646: mLeftButton.setVisible(true);
647: mRightButton.setVisible(true);
648:
649: if (mCloseRegime == CB_ONEFORALL) {
650: mCloseButton.setVisible(true);
651: mCloseButton.setEnabled(mTabIndex > -1);
652: }
653:
654: for (int i = 0; i < mItems.size(); i++) {
655: TabPanelItem lItem = getItem(i);
656: if (lItem != null) {
657: switch (mCloseRegime) {
658: case CB_FLOATING:
659: lItem.setButtonVisible(mMouseTabIndex == i);
660: break;
661: case CB_VISIBLE:
662: lItem.setButtonVisible(true);
663: break;
664: case CB_INVISIBLE:
665: lItem.setButtonVisible(false);
666: break;
667: }
668: }
669: }
670:
671: boolean lLeftEnabled = mFirstVisibleIndex + mVisibleItemsCount < getTabCount();
672: boolean lRightEnabled = mFirstVisibleIndex > 0;
673:
674: mLeftButton.setEnabled(lLeftEnabled);
675: mRightButton.setEnabled(lRightEnabled);
676: }
677:
678: // set all buttons invisible
679: private void setAllButtonsInvsible() {
680: for (int i = 0; i < mItems.size(); i++) {
681: TabPanelItem lItem = getItem(i);
682: lItem.setButtonVisible(false);
683: }
684: }
685:
686: // check panels visiblility
687: private void checkPanels() {
688: for (int i = 0; i < mItems.size(); i++) {
689: TabPanelItem lItem = getItem(i);
690: if (lItem != null && lItem.mPanel != null) {
691: if (mTabIndex == i) {
692: mContent.add(lItem.mPanel, BorderLayout.CENTER);
693: lItem.mPanel.setVisible(true);
694: } else {
695: mContent.remove(lItem.mPanel);
696: lItem.mPanel.setVisible(false);
697: }
698: }
699: }
700: }
701:
702: // check is the child control focused
703: private boolean getIsChildFocused() {
704: for (int i = 0; i < mItems.size(); i++) {
705: TabPanelItem lItem = getItem(i);
706: if (lItem != null && lItem.mPanel != null
707: && checkContainerFocused(lItem.mPanel))
708: return true;
709: }
710: return false;
711: }
712:
713: private boolean checkContainerFocused(Container pContainer) {
714: for (int i = 0; i < pContainer.getComponentCount(); i++) {
715: Component lComponent = pContainer.getComponent(i);
716: if (lComponent.hasFocus())
717: return true;
718: if (lComponent instanceof Container) {
719: Container lContainer = (Container) lComponent;
720: if (checkContainerFocused(lContainer))
721: return true;
722: }
723: }
724: return false;
725: }
726:
727: private void showPopUp(int X, int Y) {
728: int lIndex = getItemIndexByXY(X, Y);
729: if (lIndex > -1) {
730: mMoveLeftAction.setEnabled(lIndex > 0);
731: mMoveRightAction.setEnabled(lIndex < mItems.size() - 1);
732:
733: mMoveLeftAction.setIndex(lIndex);
734: mMoveRightAction.setIndex(lIndex);
735: mCloseTabAction.setIndex(lIndex);
736:
737: JPopupMenu lMenu = new JPopupMenu();
738: lMenu.add(mMoveLeftAction);
739: lMenu.add(mMoveRightAction);
740: lMenu.addSeparator();
741: lMenu.add(mCloseTabAction);
742: lMenu.show(this , X, Y);
743: }
744: }
745:
746: // scroll panels left
747: private void scrollLeft() {
748: mFirstVisibleIndex++;
749: updateTabs();
750: }
751:
752: // scroll panels right
753: private void scrollRight() {
754: if (mFirstVisibleIndex > 0) {
755: mFirstVisibleIndex--;
756: updateTabs();
757: }
758: }
759:
760: // get X coordinate correction
761: private int getXCorrection() {
762: if (mFirstVisibleIndex > -1) {
763: TabPanelItem lItem = getItem(mFirstVisibleIndex);
764: if (lItem != null && lItem.mRect != null)
765: return lItem.mRect.x;
766: }
767: return 0;
768: }
769:
770: // check index
771: private boolean isIndexVisible(int pIndex) {
772: if (pIndex > -1) {
773: if (pIndex < mFirstVisibleIndex)
774: return false;
775: if (pIndex > mFirstVisibleIndex + mVisibleItemsCount)
776: return false;
777: }
778: return true;
779: }
780:
781: // make tab visible
782: private void makeTabVisible(int pIndex) {
783: if (pIndex < mFirstVisibleIndex) {
784: mFirstVisibleIndex = pIndex;
785: updateTabs();
786: } else if (pIndex > mFirstVisibleIndex + mVisibleItemsCount) {
787: mFirstVisibleIndex = pIndex - mVisibleItemsCount;
788: updateTabs();
789: }
790: }
791:
792: /* Auxilary classes */
793:
794: /* TabPanel Event */
795:
796: public class TabPanelEvent extends AWTEvent {
797: public static final int TABPANEL_EVENT = AWTEvent.RESERVED_ID_MAX + 999;
798:
799: public TabPanelEvent(TabPanel pPanel) {
800: super (pPanel, TABPANEL_EVENT);
801: }
802: }
803:
804: /* Tab Panle Event Listener */
805:
806: public interface TabPanelListener extends EventListener {
807: public void tabChanged(TabPanelEvent event);
808: }
809:
810: /* base tab panel button class */
811:
812: protected class BaseButton extends JButton {
813: public BaseButton(String pIconName) {
814: super ();
815: setIcon(new ImageIcon(getClass().getResource(pIconName)));
816: setBorder(null);
817: }
818:
819: public boolean hasFocus() {
820: return false;
821: }
822: }
823:
824: /* close button */
825:
826: protected class TabCloseButton extends BaseButton {
827: public TabCloseButton() {
828: super ("Close.gif");
829: setToolTipText("Close");
830: }
831: }
832:
833: /* left button */
834:
835: protected class LeftButton extends BaseButton {
836: public LeftButton() {
837: super ("Left.gif");
838: setToolTipText("Scroll Left");
839: }
840: }
841:
842: /* right button */
843:
844: protected class RightButton extends BaseButton {
845: public RightButton() {
846: super ("Right.gif");
847: setToolTipText("Scroll Right");
848: }
849: }
850:
851: private class MainFrame_Button_actionAdapter implements
852: ActionListener {
853: protected Object mObject = null;
854:
855: public MainFrame_Button_actionAdapter(Object lObject) {
856: mObject = lObject;
857: }
858:
859: public void actionPerformed(ActionEvent e) {
860: int lIndex = mItems.indexOf(mObject);
861: if (lIndex > -1)
862: deleteTab(lIndex);
863: }
864: }
865:
866: /* tab descriptor */
867:
868: protected class TabPanelItem {
869: protected String mCaption;
870: protected String mName;
871: protected Rectangle mRect = new Rectangle(0, 0, 0, 0);
872: protected Rectangle mButtonRect = new Rectangle(0, 0, 0, 0);
873: protected TabCloseButton mButton = new TabCloseButton();
874: protected BaseChildPanel mPanel = null;
875: protected Icon mIcon = null;
876: protected Icon mDisabledIcon = null;
877:
878: public TabPanelItem(String pCaption, String pName,
879: TabPanel pMaster, BaseChildPanel pPanel, Icon pIcon) {
880: mCaption = pCaption;
881: mName = pName;
882: mPanel = pPanel;
883: mIcon = pIcon;
884:
885: mPanel.setName(pCaption);
886:
887: mButton.setVisible(false);
888: TabPanelItem lItem = this ;
889: mButton
890: .addActionListener(new MainFrame_Button_actionAdapter(
891: this ));
892: pMaster.add(mButton);
893: }
894:
895: public void clearRect() {
896: mRect.setBounds(0, 0, 0, 0);
897: mButtonRect.setBounds(0, 0, 0, 0);
898: }
899:
900: public void setButtonVisible(boolean lValue) {
901: mButton.setVisible(lValue);
902: }
903:
904: public Rectangle getCorrectedRect() {
905: Rectangle lRect = new Rectangle(mRect);
906: lRect.x -= getXCorrection();
907: return lRect;
908: }
909: }
910:
911: /* Actions */
912:
913: public abstract class BaseTabAction extends AbstractAction {
914: private int mIndex = -1;
915:
916: public BaseTabAction(String pCaption) {
917: super (pCaption);
918: }
919:
920: public int getIndex() {
921: return mIndex;
922: }
923:
924: public void setIndex(int pIndex) {
925: mIndex = pIndex;
926: }
927: }
928:
929: public class CloseTabAction extends BaseTabAction {
930: public CloseTabAction() {
931: super ("Close");
932: }
933:
934: public void actionPerformed(ActionEvent e) {
935: deleteTab(getIndex());
936: }
937: }
938:
939: public class MoveLeftAction extends BaseTabAction {
940: public MoveLeftAction() {
941: super ("Move Left");
942: }
943:
944: public void actionPerformed(ActionEvent e) {
945: moveTabLeft(getIndex());
946: }
947: }
948:
949: public class MoveRightAction extends BaseTabAction {
950: public MoveRightAction() {
951: super ("Move Right");
952: }
953:
954: public void actionPerformed(ActionEvent e) {
955: moveTabRight(getIndex());
956: }
957: }
958: }
|