001: /*
002: * Copyright (C) 2004 NNL Technology AB
003: * Visit www.infonode.net for information about InfoNode(R)
004: * products and how to contact NNL Technology AB.
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * 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, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
019: * MA 02111-1307, USA.
020: */
021:
022: // $Id: ShadowPainter.java,v 1.9 2005/12/04 13:46:05 jesper Exp $
023: package net.infonode.tabbedpanel.internal;
024:
025: import net.infonode.gui.ComponentUtil;
026: import net.infonode.gui.GraphicsUtil;
027: import net.infonode.gui.UIManagerUtil;
028: import net.infonode.util.ColorUtil;
029: import net.infonode.util.Direction;
030:
031: import javax.swing.*;
032: import java.awt.*;
033:
034: /**
035: * @author $Author: jesper $
036: * @version $Revision: 1.9 $
037: * @since ITP 1.1.0
038: */
039: public class ShadowPainter {
040: private Color panelBackgroundColor;
041: private Color tabBackgroundColor;
042: private Component component;
043: private JComponent componentsPanel;
044: private JComponent highlightedTab;
045: private JComponent contentPanel;
046: private JComponent tabAreaComponentsPanel;
047: private JComponent tabAreaContainer;
048: private JComponent tabBox;
049: private Direction tabOrientation;
050: private boolean paintTabAreaShadow;
051: private int shadowSize;
052: private int shadowBlendSize;
053: private Color shadowColor;
054: private float shadowStrength;
055: private boolean highlightedTabIsLast;
056:
057: public ShadowPainter(Component component,
058: JComponent componentsPanel, JComponent highlightedTab,
059: JComponent contentPanel, JComponent tabAreaComponentsPanel,
060: JComponent tabAreaContainer, JComponent tabBox,
061: Direction tabOrientation, boolean paintTabAreaShadow,
062: int shadowSize, int shadowBlendSize, Color shadowColor,
063: float shadowStrength, boolean highlightedTabIsLast) {
064: this .component = component;
065: this .componentsPanel = componentsPanel;
066: this .highlightedTab = highlightedTab == null ? null
067: : !highlightedTab.isVisible()
068: || !tabAreaContainer.isVisible() ? null
069: : highlightedTab;
070: this .contentPanel = contentPanel;
071: this .tabAreaComponentsPanel = tabAreaComponentsPanel;
072: this .tabAreaContainer = tabAreaContainer;
073: this .tabBox = tabBox;
074: this .tabOrientation = tabOrientation;
075: this .paintTabAreaShadow = paintTabAreaShadow
076: && tabAreaContainer.isVisible();
077: this .shadowSize = shadowSize;
078: this .shadowBlendSize = shadowBlendSize;
079: this .shadowColor = shadowColor;
080: this .shadowStrength = shadowStrength;
081: this .highlightedTabIsLast = highlightedTabIsLast;
082: }
083:
084: public void paint(Graphics g) {
085: panelBackgroundColor = ComponentUtil
086: .getBackgroundColor(component);
087: panelBackgroundColor = panelBackgroundColor == null ? UIManagerUtil
088: .getColor("Panel.background", "control")
089: : panelBackgroundColor;
090:
091: if (paintTabAreaShadow) {
092: Rectangle bounds = SwingUtilities.calculateInnerArea(
093: componentsPanel, new Rectangle());
094:
095: // Right shadow
096: drawBottomRightEdgeShadow(g, bounds.y, bounds.x
097: + bounds.width, bounds.height, true,
098: panelBackgroundColor);
099:
100: // Bottom shadow
101: drawBottomRightEdgeShadow(g, bounds.x, bounds.y
102: + bounds.height, bounds.width, false,
103: panelBackgroundColor);
104:
105: // Bottom right corner
106: drawRightCornerShadow(g, bounds.x + bounds.width, bounds.y
107: + bounds.height, false, panelBackgroundColor);
108: } else {
109: tabBackgroundColor = highlightedTab == null ? panelBackgroundColor
110: : ComponentUtil.getBackgroundColor(highlightedTab
111: .getParent());
112:
113: tabBackgroundColor = tabBackgroundColor == null ? panelBackgroundColor
114: : tabBackgroundColor;
115:
116: Rectangle contentPanelBounds = contentPanel.getBounds();
117: int len = 0;
118:
119: if (highlightedTab != null)
120: len = paintHighlightedTabShadow(g, tabOrientation,
121: contentPanelBounds);
122:
123: if (tabAreaComponentsPanel.isVisible()) {
124: len = tabOrientation.isHorizontal() ? (tabAreaContainer
125: .getInsets().bottom == 0 ? tabAreaComponentsPanel
126: .getWidth()
127: : 0)
128: : (tabAreaContainer.getInsets().right == 0 ? tabAreaComponentsPanel
129: .getHeight()
130: : 0);
131: }
132:
133: if (!tabAreaContainer.isVisible())
134: len = 0;
135:
136: if (tabOrientation != Direction.RIGHT
137: || highlightedTab == null)
138: drawBottomRightEdgeShadow(
139: g,
140: contentPanelBounds.y
141: - (tabOrientation == Direction.UP ? len
142: : 0),
143: contentPanelBounds.x + contentPanelBounds.width,
144: contentPanelBounds.height
145: + (!tabOrientation.isHorizontal() ? len
146: : 0), true,
147: highlightedTab == null ? null
148: : panelBackgroundColor);
149:
150: if (tabOrientation != Direction.DOWN
151: || highlightedTab == null)
152: drawBottomRightEdgeShadow(g, contentPanelBounds.x
153: - (tabOrientation == Direction.LEFT ? len : 0),
154: contentPanelBounds.y
155: + contentPanelBounds.height,
156: contentPanelBounds.width
157: + (tabOrientation.isHorizontal() ? len
158: : 0), false,
159: highlightedTab == null ? null
160: : panelBackgroundColor);
161:
162: drawRightCornerShadow(g, contentPanelBounds.x
163: + contentPanelBounds.width
164: + (tabOrientation == Direction.RIGHT ? len : 0),
165: contentPanelBounds.y
166: + contentPanelBounds.height
167: + (tabOrientation == Direction.DOWN ? len
168: : 0), false, panelBackgroundColor);
169: }
170:
171: }
172:
173: private int paintHighlightedTabShadow(Graphics g,
174: Direction tabOrientation, Rectangle contentPanelBounds) {
175: Point p = SwingUtilities.convertPoint(highlightedTab
176: .getParent(), highlightedTab.getLocation(), component);
177:
178: // JComponent tabBox = draggableComponentBox;
179: Dimension tabsSize = tabBox.getSize();
180: Rectangle bounds = tabAreaComponentsPanel.isVisible() ? SwingUtilities
181: .convertRectangle(tabAreaComponentsPanel.getParent(),
182: tabAreaComponentsPanel.getBounds(), component)
183: : new Rectangle(contentPanelBounds.x
184: + contentPanelBounds.width,
185: contentPanelBounds.y
186: + contentPanelBounds.height, 0, 0);
187: Point tabsPos = SwingUtilities.convertPoint(tabBox, 0, 0,
188: component);
189:
190: // Set tab clip
191: int width = (tabOrientation.isHorizontal() ? 0 : tabsPos.x)
192: + tabsSize.width;
193: int height = (tabOrientation.isHorizontal() ? tabsPos.y : 0)
194: + tabsSize.height;
195:
196: if (tabOrientation == Direction.DOWN)
197: drawBottomRightTabShadow(g, contentPanelBounds.x,
198: contentPanelBounds.y + contentPanelBounds.height,
199: contentPanelBounds.width, p.x, highlightedTab
200: .getWidth(), highlightedTab.getHeight(),
201: bounds.x, bounds.width, bounds.height, false,
202: highlightedTabIsLast);
203: else if (tabOrientation == Direction.RIGHT)
204: drawBottomRightTabShadow(g, contentPanelBounds.y,
205: contentPanelBounds.x + contentPanelBounds.width,
206: contentPanelBounds.height, p.y, highlightedTab
207: .getHeight(), highlightedTab.getWidth(),
208: bounds.y, bounds.height, bounds.width, true,
209: highlightedTabIsLast);
210: else if (tabOrientation == Direction.UP) {
211: drawTopLeftTabShadow(g, p.x + highlightedTab.getWidth(),
212: p.y, highlightedTab.getHeight(), bounds,
213: contentPanelBounds.width, false,
214: highlightedTabIsLast);
215: } else
216: drawTopLeftTabShadow(g, p.y + highlightedTab.getHeight(),
217: p.x, highlightedTab.getWidth(),
218: flipRectangle(bounds), contentPanelBounds.height,
219: true, highlightedTabIsLast);
220:
221: if (highlightedTabIsLast) {
222: return tabOrientation.isHorizontal() ? (p.y
223: + highlightedTab.getHeight() >= contentPanelBounds.height
224: && contentPanelBounds.height == height ? highlightedTab
225: .getWidth()
226: : 0)
227: : (p.x + highlightedTab.getWidth() >= contentPanelBounds.width
228: && contentPanelBounds.width == width ? highlightedTab
229: .getHeight()
230: : 0);
231: } else
232: return 0;
233: }
234:
235: private static Rectangle flipRectangle(Rectangle bounds) {
236: return new Rectangle(bounds.y, bounds.x, bounds.height,
237: bounds.width);
238: }
239:
240: private static Rectangle createRectangle(int x, int y, int width,
241: int height, boolean flip) {
242: return flip ? new Rectangle(y, x, height, width)
243: : new Rectangle(x, y, width, height);
244: }
245:
246: private void drawTopLeftTabShadow(Graphics g, int x, int y,
247: int height, Rectangle componentsBounds, int totalWidth,
248: boolean flip, boolean isLast) {
249: boolean connected = x + shadowSize > componentsBounds.x;
250:
251: if (!connected
252: || y + shadowSize + shadowBlendSize <= componentsBounds.y) {
253: drawLeftCornerShadow(g, y, Math.min(x, componentsBounds.x),
254: !flip, isLast ? tabBackgroundColor : null);
255: drawEdgeShadow(g, y, connected ? componentsBounds.y : y
256: + height, Math.min(x, componentsBounds.x), false,
257: !flip, isLast ? tabBackgroundColor : null);
258: }
259:
260: int endX = componentsBounds.x + componentsBounds.width;
261:
262: if (endX < totalWidth) {
263: drawLeftCornerShadow(g, componentsBounds.y, endX, !flip,
264: tabBackgroundColor);
265: drawEdgeShadow(g, componentsBounds.y, componentsBounds.y
266: + componentsBounds.height, endX, false, !flip,
267: tabBackgroundColor);
268: }
269: }
270:
271: private void drawBottomRightTabShadow(Graphics g, int x, int y,
272: int width, int tabX, int tabWidth, int tabHeight,
273: int componentsX, int componentsWidth, int componentsHeight,
274: boolean flip, boolean isLast) {
275: Shape oldClipRect = g.getClip();
276:
277: {
278: Rectangle clipRect = createRectangle(x, y, Math.min(tabX,
279: componentsX)
280: - x, 1000000, flip);
281: g.clipRect(clipRect.x, clipRect.y, clipRect.width,
282: clipRect.height);
283: }
284:
285: drawLeftCornerShadow(g, x, y, flip, null);
286: drawEdgeShadow(g, x, tabX, y, false, flip, null);
287:
288: boolean connected = tabX < componentsX
289: && tabX + tabWidth >= componentsX;
290: g.setClip(oldClipRect);
291:
292: if (!connected) {
293: Rectangle clipRect = createRectangle(x, y, componentsX - x,
294: 1000000, flip);
295: g.clipRect(clipRect.x, clipRect.y, clipRect.width,
296: clipRect.height);
297: }
298:
299: if (tabX < componentsX) {
300: int endX = connected && tabHeight == componentsHeight ? componentsX
301: + componentsWidth
302: : Math.min(componentsX, tabX + tabWidth);
303:
304: if (tabX + shadowSize < endX)
305: drawLeftCornerShadow(g, tabX, y + tabHeight, flip,
306: panelBackgroundColor);
307:
308: drawEdgeShadow(g, tabX, endX, y + tabHeight, false, flip,
309: panelBackgroundColor);
310:
311: if (endX < x + width
312: && (!connected || componentsHeight < tabHeight)) {
313: drawRightCornerShadow(g, endX, y + tabHeight, flip,
314: panelBackgroundColor);
315: drawEdgeShadow(g, y
316: + (connected ? componentsHeight : 0), y
317: + tabHeight, endX, true, !flip,
318: isLast ? tabBackgroundColor : null);
319: }
320: }
321:
322: if (!connected) {
323: drawEdgeShadow(g, tabX + tabWidth, componentsX, y, true,
324: flip, isLast ? tabBackgroundColor : null);
325: g.setClip(oldClipRect);
326: }
327:
328: if (componentsHeight > 0
329: && (!connected || tabHeight != componentsHeight)) {
330: if (!connected || componentsHeight > tabHeight) {
331: drawLeftCornerShadow(g, componentsX, y
332: + componentsHeight, flip, panelBackgroundColor);
333: drawEdgeShadow(g, componentsX, componentsX
334: + componentsWidth, y + componentsHeight, false,
335: flip, panelBackgroundColor);
336: } else
337: drawEdgeShadow(g, componentsX, componentsX
338: + componentsWidth, y + componentsHeight, true,
339: flip, panelBackgroundColor);
340: }
341:
342: if (componentsX + componentsWidth < x + width) {
343: drawRightCornerShadow(g, componentsX + componentsWidth, y
344: + componentsHeight, flip, panelBackgroundColor);
345: drawEdgeShadow(g, y, y + componentsHeight, componentsX
346: + componentsWidth, true, !flip,
347: panelBackgroundColor);
348: drawEdgeShadow(g, componentsX + componentsWidth, x + width,
349: y, true, flip, panelBackgroundColor);
350: }
351: }
352:
353: private void drawBottomRightEdgeShadow(Graphics g, int x, int y,
354: int width, boolean flip, Color backgroundColor) {
355: drawLeftCornerShadow(g, x, y, flip, backgroundColor);
356: drawEdgeShadow(g, x, x + width, y, false, flip, backgroundColor);
357: }
358:
359: private void drawLeftCornerShadow(Graphics g, int x, int y,
360: boolean upper, Color backgroundColor) {
361: for (int i = 0; i < shadowBlendSize; i++) {
362: g.setColor(getShadowBlendColor(i, backgroundColor));
363: int x1 = x + shadowSize + shadowBlendSize - 1 - i;
364: int y1 = y + shadowSize - shadowBlendSize;
365:
366: if (y1 > y)
367: drawLine(g, x1, y, x1, y1 - 1, upper);
368:
369: drawLine(g, x1, y1, x + shadowSize + shadowBlendSize - 1, y
370: + shadowSize - shadowBlendSize + i, upper);
371: }
372: }
373:
374: private void drawRightCornerShadow(Graphics g, int x, int y,
375: boolean flip, Color backgroundColor) {
376: g.setColor(getShadowColor(backgroundColor));
377:
378: for (int i = 0; i < shadowSize - shadowBlendSize; i++) {
379: drawLine(g, x + i, y, x + i, y + shadowSize
380: - shadowBlendSize, flip);
381: }
382:
383: for (int i = 0; i < shadowBlendSize; i++) {
384: g.setColor(getShadowBlendColor(i, backgroundColor));
385: int d = shadowSize - shadowBlendSize + i;
386: drawLine(g, x + d, y, x + d, y + shadowSize
387: - shadowBlendSize, flip);
388: drawLine(g, x, y + d, x + shadowSize - shadowBlendSize, y
389: + d, flip);
390: drawLine(g, x + d, y + shadowSize - shadowBlendSize, x
391: + shadowSize - shadowBlendSize, y + d, flip);
392: }
393: }
394:
395: private void drawEdgeShadow(Graphics g, int startX, int endX,
396: int y, boolean cornerStart, boolean vertical,
397: Color backgroundColor) {
398: if (startX + (cornerStart ? 0 : shadowSize + shadowBlendSize) >= endX)
399: return;
400:
401: g.setColor(getShadowColor(backgroundColor));
402:
403: for (int i = 0; i < shadowSize - shadowBlendSize; i++) {
404: drawLine(g, startX
405: + (cornerStart ? i + (vertical ? 1 : 0)
406: : shadowSize + shadowBlendSize), y + i,
407: endX - 1, y + i, vertical);
408: }
409:
410: for (int i = 0; i < shadowBlendSize; i++) {
411: g.setColor(getShadowBlendColor(i, backgroundColor));
412: int d = shadowSize - shadowBlendSize + i;
413: drawLine(g, startX
414: + (cornerStart ? d + (vertical ? 1 : 0)
415: : shadowSize + shadowBlendSize), y + d,
416: endX - 1, y + d, vertical);
417: }
418: }
419:
420: /* private void drawShadowLine(Graphics g, int startX, int endX, int y, boolean vertical, Color backgroundColor) {
421: if (startX >= endX)
422: return;
423:
424: g.setColor(getShadowColor(backgroundColor));
425:
426: for (int i = 0; i < shadowSize - shadowBlendSize; i++) {
427: drawLine(g, startX, y + i, endX - 1, y + i, vertical);
428: }
429:
430: for (int i = 0; i < shadowBlendSize; i++) {
431: g.setColor(getShadowBlendColor(i, backgroundColor));
432: int d = shadowSize - shadowBlendSize + i;
433: drawLine(g, startX, y + d, endX - 1, y + d, vertical);
434: }
435: }
436: */
437: private static void drawLine(Graphics g, int x1, int y1, int x2,
438: int y2, boolean flip) {
439: if (flip)
440: GraphicsUtil.drawOptimizedLine(g, y1, x1, y2, x2);
441: else
442: GraphicsUtil.drawOptimizedLine(g, x1, y1, x2, y2);
443: }
444:
445: private Color getShadowBlendColor(int offset, Color backgroundColor) {
446: return backgroundColor == null ? new Color(
447: shadowColor.getRed(),
448: shadowColor.getGreen(),
449: shadowColor.getBlue(),
450: (int) (255F * shadowStrength
451: * (shadowBlendSize - offset) / (shadowBlendSize + 1)))
452: : ColorUtil.blend(backgroundColor, shadowColor,
453: shadowStrength * (shadowBlendSize - offset)
454: / (shadowBlendSize + 1));
455: }
456:
457: private Color getShadowColor(Color backgroundColor) {
458: return backgroundColor == null ? new Color(
459: shadowColor.getRed(), shadowColor.getGreen(),
460: shadowColor.getBlue(), (int) (255F * shadowStrength))
461: : ColorUtil.blend(backgroundColor, shadowColor,
462: shadowStrength);
463: }
464: }
|