001: /*
002: * @(#)Contour.java
003: *
004: * Copyright 2002 JIDE Software Inc. All rights reserved.
005: */
006: package com.jidesoft.swing;
007:
008: import com.jidesoft.plaf.UIDefaultsLookup;
009:
010: import javax.swing.*;
011: import java.awt.*;
012:
013: /**
014: * A <code>Contour</code> is a lightweight component which only paints the outline
015: * of component when dragged. It is also used as a placeholder for some information during dragging.
016: * <p/>
017: * Notes: this class has to be public so that JIDE can use it in different packages,
018: * not meant to release to end user as a public API. JIDE will not gurantee the class
019: * will remain as it is.
020: */
021: public class Contour extends JComponent implements IContour {
022: public final static int PARTIAL_OUTLINE_MODE = 0;
023:
024: public final static int MIX_OUTLINE_MODE = 1;
025:
026: public final static int FULL_OUTLINE_MODE = 2;
027:
028: // Five values below should be configurable
029:
030: /**
031: * width of the contour.
032: */
033: private int _thickness = 4;
034:
035: /**
036: * the width of tab if in tab-docked mode.
037: */
038: private static final int TAB_WIDTH = 42;
039:
040: /**
041: * the distance from the beginning to the tab if in tab-docked mode.
042: */
043: private static final int TAB_LEADING = 8;
044:
045: /**
046: * the color of contour.
047: */
048: private Color _lineColor = new Color(136, 136, 136); // to fake the old contour color
049: // private static final Color LINE_COLOR = Color.BLACK;
050:
051: /**
052: * the stroke to paint special effect of a contour.
053: */
054: // private static final BasicStroke DOTTED_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE,
055: // BasicStroke.JOIN_ROUND, 1.0f, new float[]{0, 2, 0, 2}, 0);;
056: /**
057: * height of tab. It was used to draw contour. Application can set the height.
058: */
059: private int _tabHeight = 22;
060:
061: /**
062: * <code>true</code> if docking is allowed; <code>false</code> otherwise.
063: * Usually when user pressed ctrl key, dock is not allowed.
064: */
065: private boolean _allowDocking = true;
066:
067: /**
068: * <code>true</code> if tab-docked; <code>false</code> otherwise.
069: */
070: private boolean _tabDocking;
071:
072: /**
073: * Which side is the tab
074: */
075: private int _tabSide;
076:
077: /**
078: * <code>true</code> if float; <code>false</code> otherwise.
079: */
080: private boolean _floating;
081:
082: /**
083: * which component the dragged component will dock to.
084: */
085: private Component _attachedComponent;
086:
087: /**
088: * which side the dragged component will dock to.
089: */
090: private int _attachedSide;
091:
092: /**
093: * When you dragged a component, several other components could be dragged.
094: * For example, if user drags on title bar of FrameContainer, all components in the
095: * FrameContainer are considered as dragged. If user drags on tab, only selected one
096: * is dragged.
097: * <p/>
098: * <code>true</code> if all dragged components are affected; <code>false</code> otherwise.
099: */
100: private boolean _single;
101:
102: /**
103: * When user press and release ctrl key, the contour will toggle between dock and float mode.
104: * These three fields are used to remember previous state.
105: */
106: private JComponent _saveDraggedComponent;
107: private int _saveX, _saveY;
108: private int _saveMouseModifier;
109:
110: private Container _relativeContainer;
111:
112: private int _outlineMode = 0;
113:
114: private Outline _topOutline;
115: private Outline _bottomOutline;
116: private Outline _leftOutline;
117: private Outline _rightOutline;
118:
119: /**
120: * If ghost is true, it will not paint itself at all but paint to underlying LayerPane.
121: */
122: private boolean _ghost = false;
123:
124: private Component _glassPane;
125:
126: private boolean _changeCursor = false;
127:
128: /**
129: * Default Constructor.
130: */
131: public Contour() {
132: this (22);
133: setOpaque(false);
134: setDoubleBuffered(true);
135: }
136:
137: /**
138: * Constructor with tab height.
139: *
140: * @param tabHeight the tab height
141: */
142: public Contour(int tabHeight) {
143: _thickness = UIDefaultsLookup.getInt("Contour.thickness") == 0 ? 4
144: : UIDefaultsLookup.getInt("Contour.thickness");
145: _lineColor = UIDefaultsLookup.getColor("Contour.color") == null ? new Color(
146: 136, 136, 136)
147: : UIDefaultsLookup.getColor("Contour.color");
148: setTabHeight(tabHeight);
149: if (getOutlineMode() != PARTIAL_OUTLINE_MODE) {
150: initOutline();
151: }
152: }
153:
154: private void initOutline() {
155: // System.out.println("1");
156: _topOutline = new Outline();
157: _bottomOutline = new Outline();
158: _leftOutline = new Outline();
159: _rightOutline = new Outline();
160: }
161:
162: /**
163: * Returns whether this component should use a buffer to paint.
164: *
165: * @return true if this component is double buffered, otherwise false
166: */
167: @Override
168: public boolean isDoubleBuffered() {
169: return true;
170: }
171:
172: /**
173: * Paint a rectangle or tab-shape using <code>DOTTED_STROKE<code> with width of <code>WIDTH<code>.
174: *
175: * @param g
176: */
177: @Override
178: public void paint(Graphics g) {
179: if (!_ghost) {
180: paintOutline(g, false);
181: }
182: }
183:
184: private void paintOutline(Graphics g, boolean xorMode) {
185: Rectangle bounds = getBounds();
186: g.translate(-bounds.x, -bounds.y);
187:
188: if (xorMode) {
189: bounds = SwingUtilities
190: .convertRectangle(
191: this ,
192: bounds,
193: (getRelativeContainer() != null ? getRelativeContainer()
194: : getParent()));
195: // System.out.println(bounds);
196: } else {
197: g.setColor(_lineColor);
198: }
199: // comment to make it draw faster
200: // ((Graphics2D)g).setStroke(DOTTED_STROKE);
201:
202: if (getOutlineMode() != FULL_OUTLINE_MODE && isTabDocking()) {
203: drawTab(g, bounds.x, bounds.y, bounds.width,
204: bounds.height - 1, _tabHeight - 1, TAB_WIDTH,
205: TAB_LEADING, _thickness, getTabSide());
206: } else {
207: drawRect(g, bounds.x, bounds.y, bounds.width - 1,
208: bounds.height - 1, _thickness);
209: }
210: }
211:
212: /**
213: * Draws vertial or hotizontal lines. Try to test if fillRect then drawLine four times.
214: * Other unit test show it's about fillRect is 75% faster than drawLine, so we decide
215: * to use fillRect to draw the contour.
216: *
217: * @param g
218: * @param x1
219: * @param y1
220: * @param x2
221: * @param y2
222: * @param thick
223: */
224: private static void drawLine(Graphics g, int x1, int y1, int x2,
225: int y2, int thick) {
226: if (x1 == x2) {
227: if (y2 > y1) {
228: g.fillRect(x1, y1, thick, y2 - y1);
229: } else {
230: g.fillRect(x1, y2, thick, y1 - y2);
231: }
232: } else if (y1 == y2) {
233: if (x2 > x1) {
234: g.fillRect(x1, y1, x2 - x1, thick);
235: } else {
236: g.fillRect(x2, y1, x1 - x2, thick);
237: }
238: }
239:
240: }
241:
242: private static void drawRect(Graphics g, int x, int y, int width,
243: int height, int thick) {
244: if (width <= thick) {
245: drawLine(g, x, y, x, y + height, thick);
246: } else if (height <= thick) {
247: drawLine(g, x, y, x + width, y, thick);
248: } else {
249: drawLine(g, x, y, x + width - thick, y, thick);
250: drawLine(g, x + width - thick, y, x + width - thick, y
251: + height - thick, thick);
252: drawLine(g, x + width, y + height - thick, x + thick, y
253: + height - thick, thick);
254: drawLine(g, x, y + height, x, y + thick, thick);
255: }
256: // commented because of using fillRect
257: // g.drawLine(x, y, x + width - 1, y);
258: // g.drawLine(x + width, y, x + width, y + height - 1);
259: // g.drawLine(x + width, y + height, x + 1, y + height);
260: // g.drawLine(x, y + height, x, y + 1);
261: }
262:
263: private static void drawTab(Graphics g, int x, int y, int width,
264: int height, int tabHeight, int tabWidth, int tabLeading,
265: int thick, int side) {
266: switch (side) {
267: case SwingConstants.TOP:
268: drawTopTab(g, x, y, width, height, tabHeight, tabWidth,
269: tabLeading, thick);
270: break;
271: case SwingConstants.BOTTOM:
272: drawBottomTab(g, x, y, width, height, tabHeight, tabWidth,
273: tabLeading, thick);
274: break;
275: }
276: }
277:
278: // TabDocking
279: // |------
280: // | |
281: // |--- |--------
282: // | |
283: // | |
284: // | |
285: // | |
286: // | |
287: // -----------------|
288:
289: private static void drawTopTab(Graphics g, int x, int y, int width,
290: int height, int tabHeight, int tabWidth, int tabLeading,
291: int thick) {
292: drawLine(g, x + width - thick, y + tabHeight,
293: x + width - thick, y + height - 1, thick); // right
294:
295: drawLine(g, x + tabLeading + thick, y + tabHeight, x, y
296: + tabHeight, thick); // top leading
297: drawLine(g, x + tabWidth + tabLeading, y + tabHeight, x
298: + tabWidth + tabLeading, y, thick); // tab right
299: drawLine(g, x + tabWidth + tabLeading, y, x + tabLeading + 1,
300: y, thick); // tab top
301: drawLine(g, x + tabLeading, y, x + tabLeading, y + tabHeight,
302: thick); // tab left
303: drawLine(g, x + width, y + tabHeight,
304: x + tabWidth + tabLeading, y + tabHeight, thick); // top rest
305:
306: drawLine(g, x, y + tabHeight, x, y + height, thick); // left
307:
308: drawLine(g, x, y + height - thick, x + width, y + height
309: - thick, thick); // bottom
310:
311: // commented because of using fillRect
312: // g.drawLine(x, y, x + width - 1, y); // top
313: // g.drawLine(x + width, y, x + width, y + height - tabHeight - 1); // right
314: //
315: // g.drawLine(x + width, y + height - tabHeight, x + tabWidth + tabLeading + 1, y + height - tabHeight); // bottom rest
316: // g.drawLine(x + tabWidth + tabLeading, y + height - tabHeight, x + tabWidth + tabLeading, y + height - 1); // tab right
317: // g.drawLine(x + tabWidth + tabLeading, y + height, x + tabLeading + 1, y + height); // tab bottom
318: // g.drawLine(x + tabLeading, y + height, x + tabLeading, y + height - tabHeight + 1); // tab left
319: // g.drawLine(x + tabLeading, y + height - tabHeight, x + 1, y + height - tabHeight); // bottom leading
320: //
321: // g.drawLine(x, y + height - tabHeight, x, y + 1); // left
322: }
323:
324: // TabDocking
325: // -----------------|
326: // | |
327: // | |
328: // | |
329: // | |
330: // | |
331: // |--- |--------
332: // | |
333: // |------
334:
335: private static void drawBottomTab(Graphics g, int x, int y,
336: int width, int height, int tabHeight, int tabWidth,
337: int tabLeading, int thick) {
338: drawLine(g, x, y, x + width - 1, y, thick); // top
339: drawLine(g, x + width - thick, y, x + width - thick, y + height
340: - tabHeight - 1, thick); // right
341:
342: drawLine(g, x + width, y + height - tabHeight - thick, x
343: + tabWidth + tabLeading,
344: y + height - tabHeight - thick, thick); // bottom rest
345: drawLine(g, x + tabWidth + tabLeading, y + height - tabHeight,
346: x + tabWidth + tabLeading, y + height, thick); // tab right
347: drawLine(g, x + tabWidth + tabLeading, y + height - thick, x
348: + tabLeading + 1, y + height - thick, thick); // tab bottom
349: drawLine(g, x + tabLeading, y + height, x + tabLeading, y
350: + height - tabHeight, thick); // tab left
351: drawLine(g, x + tabLeading + thick, y + height - tabHeight
352: - thick, x + 1, y + height - tabHeight - thick, thick); // bottom leading
353:
354: drawLine(g, x, y + height - tabHeight, x, y + 1, thick); // left
355:
356: // commented because of using fillRect
357: // g.drawLine(x, y, x + width - 1, y); // top
358: // g.drawLine(x + width, y, x + width, y + height - tabHeight - 1); // right
359: //
360: // g.drawLine(x + width, y + height - tabHeight, x + tabWidth + tabLeading + 1, y + height - tabHeight); // bottom rest
361: // g.drawLine(x + tabWidth + tabLeading, y + height - tabHeight, x + tabWidth + tabLeading, y + height - 1); // tab right
362: // g.drawLine(x + tabWidth + tabLeading, y + height, x + tabLeading + 1, y + height); // tab bottom
363: // g.drawLine(x + tabLeading, y + height, x + tabLeading, y + height - tabHeight + 1); // tab left
364: // g.drawLine(x + tabLeading, y + height - tabHeight, x + 1, y + height - tabHeight); // bottom leading
365: //
366: // g.drawLine(x, y + height - tabHeight, x, y + 1); // left
367: }
368:
369: /**
370: * Overwirte setBounds so that width and height are always even.
371: *
372: * @param r the new bounding rectangle for this component
373: */
374: @Override
375: public void setBounds(Rectangle r) {
376: setBounds(r.x, r.y, r.width, r.height);
377: }
378:
379: /**
380: * Overwirte setBounds so that width and height are always even.
381: * <p/>
382: * It looks ugly for either dimension is odd when painting
383: * with <code>DOTTED_STROKE</code>
384: *
385: * @param x the new <i>x</i>-coordinate of this component
386: * @param y the new <i>y</i>-coordinate of this component
387: * @param width the new <code>width</code> of this component
388: * @param height the new <code>height</code> of this
389: * component
390: */
391: @Override
392: public void setBounds(int x, int y, int width, int height) {
393: if (isLightweight()) {
394: if (getOutlineMode() == PARTIAL_OUTLINE_MODE) {
395: if (_ghost
396: && (getRelativeContainer() != null || getParent() != null)) {
397: Graphics g = (getRelativeContainer() != null ? getRelativeContainer()
398: : getParent()).getGraphics();
399: g.setXORMode(_lineColor);
400: paintOutline(g, true);
401: super .setBounds(x, y, width % 2 == 0 ? width + 1
402: : width, height % 2 == 0 ? height + 1
403: : height);
404: // paintOutline(g, true);
405: } else {
406: super .setBounds(x, y, width % 2 == 0 ? width + 1
407: : width, height % 2 == 0 ? height + 1
408: : height);
409: }
410: } else {
411: Rectangle rectangle = new Rectangle(x, y,
412: width % 2 == 0 ? width + 1 : width,
413: height % 2 == 0 ? height + 1 : height);
414: if (getParent() != null) {
415: Rectangle parentRectangle = getParent().getBounds();
416: super .setBounds(x, y, width % 2 == 0 ? width + 1
417: : width, height % 2 == 0 ? height + 1
418: : height);
419: if (getOutlineMode() == MIX_OUTLINE_MODE
420: && parentRectangle.contains(rectangle)) {
421: _leftOutline.setVisible(false);
422: _rightOutline.setVisible(false);
423: _topOutline.setVisible(false);
424: _bottomOutline.setVisible(false);
425: } else {
426: super .setVisible(false);
427: Point point = rectangle.getLocation();
428: SwingUtilities.convertPointToScreen(point,
429: getParent());
430: arrangeOutline(rectangle, point);
431: }
432: }
433: }
434: } else {
435: if (getRelativeContainer() != null) {
436: Point point = new Point(x, y);
437: SwingUtilities.convertPointToScreen(point,
438: getRelativeContainer());
439: super .setBounds(point.x, point.y,
440: width % 2 == 0 ? width + 1 : width,
441: height % 2 == 0 ? height + 1 : height);
442: }
443: }
444: }
445:
446: private void arrangeOutline(Rectangle rectangle, Point point) {
447: // boolean beyondLeft = rectangle.x < 0;
448: // boolean beyondTop = rectangle.y < 0;
449: // boolean beyondRight = rectangle.x + rectangle.width > parentRectangle.x + parentRectangle.width;
450: // boolean beyondBottom = rectangle.y + rectangle.height > parentRectangle.y + parentRectangle.height;
451: _leftOutline.setBounds(point.x, point.y, _thickness,
452: rectangle.height - _thickness);
453: _topOutline.setBounds(point.x + _thickness, point.y,
454: rectangle.width - _thickness - 1, _thickness);
455: _rightOutline.setBounds(point.x + rectangle.width - _thickness
456: - 1, point.y + _thickness, _thickness, rectangle.height
457: - _thickness);
458: _bottomOutline.setBounds(point.x, point.y + rectangle.height
459: - _thickness, rectangle.width - 1, _thickness);
460: if (!_topOutline.isVisible()) {
461: _topOutline.setVisible(true);
462: }
463: if (!_leftOutline.isVisible()) {
464: _leftOutline.setVisible(true);
465: }
466: if (!_rightOutline.isVisible()) {
467: _rightOutline.setVisible(true);
468: }
469: if (!_bottomOutline.isVisible()) {
470: _bottomOutline.setVisible(true);
471: }
472: }
473:
474: /**
475: * Gets tab height.
476: *
477: * @return tab height
478: */
479: public int getTabHeight() {
480: return _tabHeight;
481: }
482:
483: /**
484: * Sets the tab height.
485: *
486: * @param tabHeight
487: */
488: public void setTabHeight(int tabHeight) {
489: _tabHeight = tabHeight;
490: }
491:
492: /**
493: * Returns true if the contour is in tab-dock mode.
494: *
495: * @return true if tab-docking; false otherwise
496: */
497: public boolean isTabDocking() {
498: return _tabDocking;
499: }
500:
501: /**
502: * Sets the tab-docking mode.
503: *
504: * @param tabDocking new mode
505: */
506: public void setTabDocking(boolean tabDocking) {
507: _tabDocking = tabDocking;
508: updateCursor();
509: }
510:
511: /**
512: * Gets the side of the tab.
513: *
514: * @return the side of the tab
515: */
516: public int getTabSide() {
517: return _tabSide;
518: }
519:
520: /**
521: * Sets the side of the tab.
522: *
523: * @param tabSide
524: */
525: public void setTabSide(int tabSide) {
526: _tabSide = tabSide;
527: }
528:
529: /**
530: * Returns true if the contour is in floating mode.
531: *
532: * @return true if floating; false otherwise
533: */
534: public boolean isFloating() {
535: return _floating;
536: }
537:
538: /**
539: * Sets the floating mode.
540: *
541: * @param floating new mode
542: */
543: public void setFloating(boolean floating) {
544: _floating = floating;
545: updateCursor();
546: }
547:
548: /**
549: * Gets the attached component of this contour.
550: *
551: * @return the attached component
552: */
553: public Component getAttachedComponent() {
554: return _attachedComponent;
555: }
556:
557: /**
558: * Sets the attached components.
559: *
560: * @param attachedComponent attached component to be set
561: */
562: public void setAttachedComponent(Component attachedComponent) {
563: _attachedComponent = attachedComponent;
564: }
565:
566: /**
567: * Gets the side of the attached component which the contour is attached to.
568: *
569: * @return side the attached side
570: */
571: public int getAttachedSide() {
572: return _attachedSide;
573: }
574:
575: /**
576: * Sets the side of the attached component which the contour is attached to.
577: *
578: * @param attachedSide the new attached side to be set
579: */
580: public void setAttachedSide(int attachedSide) {
581: _attachedSide = attachedSide;
582: updateCursor();
583: }
584:
585: private void updateCursor() {
586: if (getGlassPane() == null) { // if glass pane is not set, no way to change cursor shape.
587: return;
588: }
589:
590: // show a stop cursor if the floating is not allowed
591: if (!isVisible() && _floating) {
592: getGlassPane()
593: .setCursor(
594: JideCursors
595: .getPredefinedCursor(JideCursors.DRAG_STOP_CURSOR));
596: return;
597: } else {
598: getGlassPane().setCursor(Cursor.getDefaultCursor());
599: }
600:
601: if (!_changeCursor) {
602: return;
603: }
604:
605: if (!isVisible()) {
606: getGlassPane().setCursor(Cursor.getDefaultCursor());
607: return;
608: }
609:
610: if (isVisible() && (!_allowDocking || _floating)) {
611: getGlassPane()
612: .setCursor(
613: JideCursors
614: .getPredefinedCursor(JideCursors.FLOAT_CURSOR));
615: } else if (isVisible() && _tabDocking) {
616: getGlassPane()
617: .setCursor(
618: JideCursors
619: .getPredefinedCursor(JideCursors.TAB_CURSOR));
620: } else if (getAttachedComponent() instanceof JideSplitPaneDivider) {
621: if (((JideSplitPaneDivider) getAttachedComponent())
622: .getJideSplitPane().getOrientation() == JideSplitPane.HORIZONTAL_SPLIT) {
623: getGlassPane()
624: .setCursor(
625: JideCursors
626: .getPredefinedCursor(JideCursors.HORIZONTAL_CURSOR));
627: } else {
628: getGlassPane()
629: .setCursor(
630: JideCursors
631: .getPredefinedCursor(JideCursors.VERTICAL_CURSOR));
632: }
633: } else {
634: switch (_attachedSide) {
635: case 1:
636: getGlassPane()
637: .setCursor(
638: JideCursors
639: .getPredefinedCursor(JideCursors.NORTH_CURSOR));
640: break;
641: case 2:
642: getGlassPane()
643: .setCursor(
644: JideCursors
645: .getPredefinedCursor(JideCursors.SOUTH_CURSOR));
646: break;
647: case 4:
648: getGlassPane()
649: .setCursor(
650: JideCursors
651: .getPredefinedCursor(JideCursors.EAST_CURSOR));
652: break;
653: case 8:
654: getGlassPane()
655: .setCursor(
656: JideCursors
657: .getPredefinedCursor(JideCursors.WEST_CURSOR));
658: break;
659: default:
660: getGlassPane().setCursor(Cursor.getDefaultCursor());
661: break;
662: }
663: }
664: }
665:
666: /**
667: * When you dragged a component, several other components could be dragged.
668: * For example, if user drags on title bar of FrameContainer, all components in the
669: * FrameContainer are considered as dragged. If user drags on tab, only selected one
670: * is dragged.
671: *
672: * @return <code>true</code> if all dragged components are affected; <code>false</code> otherwise.
673: */
674: public boolean isSingle() {
675: return _single;
676: }
677:
678: /**
679: * Sets the value of single.
680: *
681: * @param single <code>true</code> if all dragged components are affected; <code>false</code> otherwise.
682: */
683: public void setSingle(boolean single) {
684: _single = single;
685: }
686:
687: /**
688: * Checks if docking is alloed.
689: *
690: * @return <code>true</code> if docking is allowed; <code>false</code> otherwise.
691: */
692: public boolean isAllowDocking() {
693: return _allowDocking;
694: }
695:
696: /**
697: * Sets the value of docking.
698: *
699: * @param allowDocking <code>true</code> if docking is allowed; <code>false</code> otherwise.
700: */
701: public void setAllowDocking(boolean allowDocking) {
702: _allowDocking = allowDocking;
703: updateCursor();
704: }
705:
706: public Container getRelativeContainer() {
707: return _relativeContainer;
708: }
709:
710: public void setRelativeContainer(Container relativeContainer) {
711: _relativeContainer = relativeContainer;
712: }
713:
714: /**
715: * Gets saved X position of contour before it's hidden.
716: *
717: * @return saved X position
718: */
719: public int getSaveX() {
720: return _saveX;
721: }
722:
723: /**
724: * Gets saved Y position of contour before it's hidden.
725: *
726: * @return saved Y position
727: */
728: public int getSaveY() {
729: return _saveY;
730: }
731:
732: /**
733: * Gets saved mouse modifier before the contour is hidden.
734: *
735: * @return saved mouse modifier
736: */
737: public int getSaveMouseModifier() {
738: return _saveMouseModifier;
739: }
740:
741: /**
742: * Gets saved dragged component before the contour is hidden.
743: *
744: * @return saved dragged component
745: */
746: public JComponent getSaveDraggedComponent() {
747: return _saveDraggedComponent;
748: }
749:
750: /**
751: * Stores information before the contour is hidden. Those information
752: * will be used to restore when the contour is set visible again.
753: *
754: * @param comp the dragged component
755: * @param saveX X position of the contour
756: * @param saveY Y position of the contour
757: * @param saveMouseModifier mouse modifier in the MouseEvent
758: */
759: public void setDraggingInformation(JComponent comp, int saveX,
760: int saveY, int saveMouseModifier) {
761: _saveDraggedComponent = comp;
762: _saveX = saveX;
763: _saveY = saveY;
764: _saveMouseModifier = saveMouseModifier;
765: }
766:
767: public void cleanup() {
768: if (getOutlineMode() != PARTIAL_OUTLINE_MODE) {
769: // System.out.println("0");
770: _leftOutline.dispose();
771: _rightOutline.dispose();
772: _topOutline.dispose();
773: _bottomOutline.dispose();
774: _leftOutline = null;
775: _rightOutline = null;
776: _topOutline = null;
777: _bottomOutline = null;
778: }
779: if (getGlassPane() != null) {
780: getGlassPane().setCursor(Cursor.getDefaultCursor());
781: }
782: }
783:
784: // private Screen _screen;
785: // private Container _savedContainer;
786:
787: /**
788: * Makes the component visible or invisible.
789: * Overrides <code>Component.setVisible</code>.
790: *
791: * @param aFlag true to make the component visible; false to
792: * make it invisible
793: */
794: @Override
795: public void setVisible(boolean aFlag) {
796: super .setVisible(aFlag);
797: updateCursor();
798: if (!aFlag && getOutlineMode() != PARTIAL_OUTLINE_MODE) {
799: _leftOutline.setVisible(false);
800: _rightOutline.setVisible(false);
801: _topOutline.setVisible(false);
802: _bottomOutline.setVisible(false);
803: }
804: }
805:
806: /**
807: * Determines whether this component should be visible when its
808: * parent is visible. Components are
809: * initially visible, with the exception of top level components such
810: * as <code>Frame</code> objects.
811: *
812: * @return <code>true</code> if the component is visible,
813: * <code>false</code> otherwise
814: * @see #setVisible
815: * @since JDK1.0
816: */
817: @Override
818: public boolean isVisible() {
819: if (super .isVisible()) {
820: return true;
821: } else if (getOutlineMode() != PARTIAL_OUTLINE_MODE
822: && (_topOutline.isVisible()
823: || _bottomOutline.isVisible()
824: || _leftOutline.isVisible() || _rightOutline
825: .isVisible())) {
826: return true;
827: } else
828: return false;
829: }
830:
831: class Outline extends JWindow {
832: public Outline() {
833: this .setVisible(false);
834: setBackground(_lineColor);
835: }
836:
837: @Override
838: public void paint(Graphics g) {
839: g.setColor(_lineColor);
840: g.fillRect(0, 0, getWidth(), getHeight());
841: }
842:
843: // Code for double buffer but doesn't work very well.
844: // Image offscreen;
845: //
846: // public void invalidate() {
847: // super.invalidate();
848: // offscreen = null;
849: // }
850: //
851: // public void update(Graphics g) {
852: // paint(g);
853: // }
854: //
855: // public void paint(Graphics g) {
856: // if (offscreen == null) {
857: // offscreen = createImage(getSize().width, getSize().height);
858: // }
859: // Graphics og = offscreen.getGraphics();
860: // // Here do something to draw your rectangle
861: // // og.setClip(0,0,getSize().width, getSize().height);
862: // super.paint(g);
863: //
864: // g.drawImage(offscreen, 0, 0, null);
865: // og.dispose();
866: // }
867: }
868:
869: public int getOutlineMode() {
870: return _outlineMode;
871: }
872:
873: public void setOutlineMode(int outlineMode) {
874: if (outlineMode != PARTIAL_OUTLINE_MODE
875: && _outlineMode == PARTIAL_OUTLINE_MODE) {
876: initOutline();
877: }
878: _outlineMode = outlineMode;
879: }
880:
881: public Component getGlassPane() {
882: return _glassPane;
883: }
884:
885: public void setGlassPane(Component glassPane) {
886: _glassPane = glassPane;
887: }
888:
889: public boolean isChangeCursor() {
890: return _changeCursor;
891: }
892:
893: public void setChangeCursor(boolean changeCursor) {
894: _changeCursor = changeCursor;
895: }
896: }
|