001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019: package org.netbeans.modules.bpel.design.decoration.components;
020:
021: import java.awt.BasicStroke;
022: import java.awt.BorderLayout;
023: import java.awt.Color;
024: import java.awt.Component;
025: import java.awt.Container;
026: import java.awt.Dimension;
027: import java.awt.Font;
028: import java.awt.Graphics;
029: import java.awt.Graphics2D;
030: import java.awt.Insets;
031: import java.awt.RenderingHints;
032: import java.awt.Shape;
033: import java.awt.event.ActionEvent;
034: import java.awt.event.ActionListener;
035: import java.awt.event.FocusEvent;
036: import java.awt.event.FocusListener;
037: import java.awt.event.KeyEvent;
038: import java.awt.event.MouseEvent;
039: import java.awt.event.MouseListener;
040: import java.awt.geom.Arc2D;
041: import java.awt.geom.GeneralPath;
042: import java.awt.geom.Line2D;
043: import java.net.URL;
044: import javax.swing.Icon;
045: import javax.swing.InputMap;
046: import javax.swing.JButton;
047: import javax.swing.JComponent;
048: import javax.swing.JEditorPane;
049: import javax.swing.JLabel;
050: import javax.swing.JPanel;
051: import javax.swing.JScrollBar;
052: import javax.swing.JScrollPane;
053: import javax.swing.KeyStroke;
054: import javax.swing.border.Border;
055: import javax.swing.border.EmptyBorder;
056: import javax.swing.text.html.HTMLEditorKit;
057: import javax.swing.text.JTextComponent;
058: import org.netbeans.modules.bpel.design.DesignView;
059: import org.netbeans.modules.bpel.design.decoration.Decoration;
060: import org.netbeans.modules.bpel.design.geometry.FStroke;
061: import org.openide.util.NbBundle;
062:
063: /**
064: * @author aa160298
065: */
066: public class GlassPane extends JPanel implements ActionListener,
067: FocusListener, MouseListener {
068:
069: private JPanel labelPane;
070: private JButton hideButton;
071: private JTextComponent editorPane;
072: private JScrollPane scrollPane;
073: private StringBuffer html = new StringBuffer();
074: private boolean myEditable;
075:
076: public GlassPane(String text, ActionListener actionListener,
077: boolean editable) {
078: setLayout(new BorderLayout(0, 1));
079: setBorder(new EmptyBorder(6, 36, 6, 6));
080: setPreferredSize(new Dimension(320, 180));
081: myEditable = editable;
082: setOpaque(false);
083:
084: if (editable) {
085: editorPane = new javax.swing.JTextArea();
086: } else {
087: editorPane = new JEditorPane() {
088: protected void paintComponent(Graphics g) {
089: Graphics2D g2 = (Graphics2D) g.create();
090: g2.setRenderingHint(
091: RenderingHints.KEY_ANTIALIASING,
092: RenderingHints.VALUE_ANTIALIAS_ON);
093: super .paintComponent(g2);
094: g2.dispose();
095: }
096: };
097: String type = "text/html"; // NOI18N
098: ((JEditorPane) editorPane).setContentType(type);
099: ((JEditorPane) editorPane).setEditorKitForContentType(type,
100: new HTMLEditorKit());
101: }
102: editorPane.setEditable(editable);
103: editorPane.setBackground(null);
104: editorPane.setBorder(null);
105: editorPane.setOpaque(false);
106: scrollPane = createScrollPane(editorPane);
107:
108: InputMap oldIM = editorPane.getInputMap();
109: InputMap newIM = new InputMap();
110:
111: for (KeyStroke ks : oldIM.allKeys()) {
112: if (ks
113: .equals(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE,
114: 0))
115: || ks.equals(KeyStroke.getKeyStroke(KeyEvent.VK_F2,
116: 0))
117: || ks.equals(KeyStroke.getKeyStroke(
118: KeyEvent.VK_ESCAPE, 0))
119: || ks.equals(KeyStroke.getKeyStroke(KeyEvent.VK_O,
120: KeyEvent.ALT_DOWN_MASK))
121: || ks.equals(KeyStroke.getKeyStroke(KeyEvent.VK_M,
122: KeyEvent.CTRL_DOWN_MASK))
123: || ks.equals(KeyStroke.getKeyStroke(
124: KeyEvent.VK_CONTEXT_MENU, 0))
125: || ks.equals(KeyStroke.getKeyStroke(
126: KeyEvent.VK_F10, KeyEvent.SHIFT_DOWN_MASK))) {
127: continue;
128: }
129: newIM.put(ks, oldIM.get(ks));
130: }
131: if (!editable) {
132: editorPane.setInputMap(WHEN_FOCUSED, newIM);
133: }
134: labelPane = new JPanel(new BorderLayout(10, 0));
135: labelPane.setBackground(null);
136: labelPane.setOpaque(false);
137: int margin;
138:
139: if (editable) {
140: margin = 0;
141: } else {
142: margin = 8;
143: }
144: labelPane.setBorder(new EmptyBorder(0, margin, 0, margin));
145: hideButton = new HideButton();
146: hideButton.setMargin(new Insets(2, 2, 2, 2));
147: hideButton.addActionListener(this );
148:
149: JPanel headerPane = new JPanel(new BorderLayout(5, 0));
150: headerPane.setBorder(new UnderlineBorder(0, 0, 6, 0, STROKE));
151: headerPane.add(labelPane, BorderLayout.CENTER);
152: headerPane.add(hideButton, BorderLayout.EAST);
153: headerPane.setBackground(null);
154: headerPane.setOpaque(false);
155:
156: add(scrollPane, BorderLayout.CENTER);
157: add(headerPane, BorderLayout.NORTH);
158:
159: this .addMouseListener(this );
160: scrollPane.addMouseListener(this );
161: editorPane.addMouseListener(this );
162:
163: this .addFocusListener(this );
164: scrollPane.addFocusListener(this );
165: editorPane.addFocusListener(this );
166:
167: if (text != null) {
168: editorPane.setText(text);
169: editorPane.setCaretPosition(editorPane.getDocument()
170: .getStartPosition().getOffset());
171: }
172: myActionListener = actionListener;
173: }
174:
175: public boolean contains(int x, int y) {
176: return createBorderShape().contains(0.5 + x, 0.5 + y);
177: }
178:
179: public void addHeader(Icon icon, String text) {
180: addHeader(icon, text, TEXT_COLOR);
181: }
182:
183: public void addHeader(Icon icon, String text, Color color) {
184: HeaderLabel label = new HeaderLabel(icon, text, color);
185:
186: int headersCount = labelPane.getComponentCount();
187:
188: if (headersCount == 0) {
189: labelPane.add(label, BorderLayout.WEST);
190: int size = label.getPreferredSize().height;
191: hideButton.setPreferredSize(new Dimension(size, size));
192: } else if (headersCount == 1) {
193: label.setHorizontalAlignment(JLabel.CENTER);
194: labelPane.add(label, BorderLayout.CENTER);
195: } else if (headersCount == 2) {
196: labelPane.add(label, BorderLayout.EAST);
197: } else {
198: throw new IndexOutOfBoundsException("Too many headers"); // NOI18N
199: }
200: }
201:
202: public void removeHeaders() {
203: labelPane.removeAll();
204: }
205:
206: public void removeHTML() {
207: html.delete(0, html.length());
208: }
209:
210: public void addListItem(String iconPath, String description) {
211: if (html.length() == 0) {
212: fillHTMLHeader();
213: } else {
214: fillHTMLDivider();
215: }
216:
217: int iconSize;
218: int iconSpace;
219:
220: if (iconPath.indexOf("explicit") >= 0) { // NOI18N
221: iconSize = 12;
222: iconSpace = 0;
223: } else {
224: iconSize = 10;
225: iconSpace = 1;
226: }
227:
228: fillHTMLSpacer();
229: fillHTMLItem(Decoration.class.getResource(iconPath), iconSize,
230: iconSpace, description);
231: fillHTMLSpacer();
232: }
233:
234: public void updateHTML() {
235: if (html.length() == 0) {
236: fillHTMLHeader();
237: }
238: fillHTMLFooter();
239: String newText = html.toString();
240: String oldText = editorPane.getText();
241:
242: if (!equals(newText, oldText)) {
243: editorPane.setText(newText);
244: editorPane.setCaretPosition(editorPane.getDocument()
245: .getStartPosition().getOffset());
246: }
247: html.delete(0, html.length());
248: }
249:
250: private boolean equals(String s1, String s2) {
251: if (s1 == s2)
252: return true;
253: if (s1 == null)
254: return false;
255: if (s2 == null)
256: return false;
257: return s1.equals(s2);
258: }
259:
260: private void fillHTMLHeader() {
261: Font font = new JLabel().getFont();
262: html.append("<html><head>"); // NOI18N
263: html.append("<style> TD { font-family: "); // NOI18N
264: html.append(font.getFamily());
265: html.append("; font-size: "); // NOI18N
266: html.append(font.getSize());
267: html.append("pt; } </style>"); // NOI18N
268: html.append("</head><body>"); // NOI18N
269: }
270:
271: private void fillHTMLFooter() {
272: html.append("</body></html>"); // NOI18N
273: }
274:
275: private void fillHTMLDivider() {
276: html
277: .append("<table cellpadding=0 cellspacing=0 border=0 width=100%>"); // NOI18N
278: html.append("<tr><td bgcolor=#999999><img src=\""); // NOI18N
279: html.append(E_IMAGE_URL);
280: html.append("\" width=1 height=1></td></tr></table>"); // NOI18N
281: }
282:
283: private void fillHTMLItem(URL iconURL, int iconSize, int iconSpace,
284: String text) {
285: if (text == null) {
286: text = "";
287: } else {
288: text = text.replace("&", "&"); // NOI18N
289: text = text.replace("<", "<"); // NOI18N
290: text = text.replace(">", ">"); // NOI18N
291: }
292: html
293: .append("<table cellpadding=0 cellspacing=0 border=0 width=100%>"); // NOI18N
294: html.append("<tr valign=top><td width=19 align=right>"); // NOI18N
295: html.append(" <img src=\""); // NOI18N
296: html.append(iconURL);
297: html.append("\" width="); // NOI18N
298: html.append(iconSize);
299: html.append(" height="); // NOI18N
300: html.append(iconSize);
301: html.append(" hspace="); // NOI18N
302: html.append(iconSpace);
303: html.append(" vspace="); // NOI18N
304: html.append(iconSpace);
305: html.append("></td><td width=4><img src=\"");
306: html.append(E_IMAGE_URL);
307: html.append("\" width=4 height=1></td><td>"); // NOI18N
308: html.append(text);
309: html.append("</td><td align=right> </td></tr></table>"); // NOI18N
310: }
311:
312: private void fillHTMLSpacer() {
313: html
314: .append("<table cellpadding=0 cellspacing=0 border=0 width=100%>"); // NOI18N
315: html.append("<tr><td><img src=\""); // NOI18N
316: html.append(E_IMAGE_URL);
317: html.append("\" width=1 height=5></td></tr></table>"); // NOI18N
318: }
319:
320: public void actionPerformed(ActionEvent e) {
321: hidePane();
322: }
323:
324: private void hidePane() {
325: DesignView designView = (DesignView) (getParent().getParent()
326: .getParent());
327: designView.getOverlayView().remove(this );
328:
329: hideButton.getModel().setArmed(false);
330: hideButton.getModel().setPressed(false);
331: hideButton.getModel().setRollover(false);
332: hideButton.getModel().setSelected(false);
333:
334: designView.revalidate();
335: designView.repaint();
336:
337: if (myActionListener != null) {
338: myActionListener.actionPerformed(new ActionEvent(getText(),
339: 0, null));
340: }
341: }
342:
343: public String getText() {
344: return editorPane.getText();
345: }
346:
347: public void paintThumbnail(Graphics g) {
348: Graphics2D g2 = (Graphics2D) g;
349:
350: g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
351: RenderingHints.VALUE_STROKE_NORMALIZE);
352: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
353: RenderingHints.VALUE_ANTIALIAS_ON);
354:
355: Shape borderShape = createBorderShape();
356: g2.setPaint(new Color(FILL.getRed(), FILL.getGreen(), FILL
357: .getBlue(), 128));
358: g2.fill(borderShape);
359:
360: g2.setStroke(new FStroke(1).createStroke(g2));
361: g2.setPaint(STROKE);
362: g2.draw(borderShape);
363: }
364:
365: protected void paintComponent(Graphics g) {
366: Graphics2D g2 = (Graphics2D) g.create();
367: g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
368: RenderingHints.VALUE_STROKE_PURE);
369: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
370: RenderingHints.VALUE_ANTIALIAS_ON);
371:
372: Shape borderShape = createBorderShape();
373:
374: g2.setPaint(FILL);
375: g2.fill(borderShape);
376:
377: g2.setPaint(STROKE);
378: g2.draw(borderShape);
379:
380: g2.dispose();
381: }
382:
383: private Shape createBorderShape() {
384: GeneralPath gp = new GeneralPath();
385:
386: Insets inests = getBorder().getBorderInsets(this );
387:
388: float x0 = 0.5f;
389: float x1 = inests.left - 6 + 0.5f;
390: float x2 = getWidth() - 0.5f;
391:
392: float y0 = 0.5f;
393: float y1 = getHeight() - 0.5f;
394:
395: float arcSize = Math.min(Math.min(x2 - x1, y1 - y0), 10);
396:
397: gp.moveTo(x0, y0);
398: gp.lineTo(x1, y0 + 14);
399: gp.append(new Arc2D.Float(x1, y0, arcSize, arcSize, 180, -90,
400: Arc2D.OPEN), true);
401: gp.append(new Arc2D.Float(x2 - arcSize, y0, arcSize, arcSize,
402: 90, -90, Arc2D.OPEN), true);
403: gp.append(new Arc2D.Float(x2 - arcSize, y1 - arcSize, arcSize,
404: arcSize, 0, -90, Arc2D.OPEN), true);
405: gp.append(new Arc2D.Float(x1, y1 - arcSize, arcSize, arcSize,
406: -90, -90, Arc2D.OPEN), true);
407: gp.lineTo(x1, Math.min(y0 + arcSize / 2 + 14 + 14, y1 - arcSize
408: / 2));
409: gp.closePath();
410:
411: return gp;
412: }
413:
414: private static JScrollPane createScrollPane(JComponent content) {
415: JScrollPane res = new JScrollPane(content);
416: res.getVerticalScrollBar().setUnitIncrement(16);
417: res.setBorder(null);
418: res.setOpaque(false);
419: res.setBackground(null);
420: res.getViewport().setBackground(null);
421: res.getViewport().setOpaque(false);
422:
423: prepareScrollBar(res.getVerticalScrollBar());
424: prepareScrollBar(res.getHorizontalScrollBar());
425:
426: return res;
427: }
428:
429: private static void prepareScrollBar(JScrollBar scrollBar) {
430: scrollBar.setOpaque(false);
431: for (int i = scrollBar.getComponentCount() - 1; i >= 0; i--) {
432: Component c = scrollBar.getComponent(i);
433:
434: if (c instanceof JComponent) {
435: ((JComponent) c).setOpaque(false);
436: }
437: }
438: }
439:
440: private void moveOnTop() {
441: JComponent parent = (JComponent) getParent();
442: if (parent == null)
443: return;
444:
445: int currentIndex = parent.getComponentZOrder(this );
446: int topIndex = currentIndex;
447:
448: for (int i = currentIndex; i >= 0; i--) {
449: if (parent.getComponent(i) instanceof GlassPane) {
450: topIndex = i;
451: }
452: }
453:
454: if (currentIndex != topIndex) {
455: parent.setComponentZOrder(this , topIndex);
456: parent.revalidate();
457: parent.repaint();
458: }
459: }
460:
461: public void focusGained(FocusEvent e) {
462: moveOnTop();
463: }
464:
465: public void mouseClicked(MouseEvent e) {
466: moveOnTop();
467: }
468:
469: public void focusLost(FocusEvent e) {
470: if (myEditable) {
471: hidePane();
472: }
473: }
474:
475: public void mousePressed(MouseEvent e) {
476: }
477:
478: public void mouseReleased(MouseEvent e) {
479: }
480:
481: public void mouseEntered(MouseEvent e) {
482: }
483:
484: public void mouseExited(MouseEvent e) {
485: }
486:
487: private static class HideButton extends JButton {
488: public HideButton() {
489: setFocusable(false);
490: setOpaque(false);
491: setToolTipText(NbBundle.getMessage(getClass(),
492: "LBL_GlassPane_Hide")); // NOI18N
493: }
494:
495: protected void paintComponent(Graphics g) {
496: super .paintComponent(g);
497:
498: int w = getWidth();
499: int h = getHeight();
500:
501: float size = Math.max(2, 0.5f * Math.min(w, h) - 4.6f);
502:
503: float cx = 0.5f * w;
504: float cy = 0.5f * h;
505:
506: Graphics2D g2 = (Graphics2D) g.create();
507: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
508: RenderingHints.VALUE_ANTIALIAS_ON);
509: g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
510: RenderingHints.VALUE_STROKE_PURE);
511: g2.setPaint(STROKE);
512: g2.setStroke(new BasicStroke(1.2f, BasicStroke.JOIN_ROUND,
513: BasicStroke.CAP_ROUND));
514: g2.draw(new Line2D.Float(cx - size, cy - size, cx + size,
515: cy + size));
516: g2.draw(new Line2D.Float(cx + size, cy - size, cx - size,
517: cy + size));
518: g2.dispose();
519: }
520: }
521:
522: private static class HeaderLabel extends JLabel {
523: public HeaderLabel(Icon icon, String text, Color color) {
524: this (text);
525: setIcon(icon);
526: setForeground(color);
527: }
528:
529: public HeaderLabel(String text) {
530: this ();
531: setText(text);
532: }
533:
534: public HeaderLabel() {
535: setBackground(null);
536: setOpaque(false);
537: }
538:
539: protected void paintComponent(Graphics g) {
540: Graphics2D g2 = (Graphics2D) g;
541:
542: Object oldAntialiasing = g2
543: .getRenderingHint(RenderingHints.KEY_ANTIALIASING);
544:
545: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
546: RenderingHints.VALUE_ANTIALIAS_ON);
547:
548: super .paintComponent(g);
549:
550: g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
551: oldAntialiasing);
552: }
553: }
554:
555: private static class UnderlineBorder implements Border {
556: private int top;
557: private int left;
558: private int bottom;
559: private int right;
560: private Color color;
561:
562: public UnderlineBorder(int top, int left, int bottom,
563: int right, Color color) {
564: this .top = top;
565: this .left = left;
566: this .bottom = bottom;
567: this .right = right;
568: this .color = color;
569: }
570:
571: public void paintBorder(Component c, Graphics g, int x, int y,
572: int w, int h) {
573: Color oldColor = g.getColor();
574:
575: g.setColor(color);
576: g.drawLine(x, y + h - 1, x + w - 1, y + h - 1);
577: g.setColor(oldColor);
578: }
579:
580: public Insets getBorderInsets(Component c) {
581: return new Insets(top, left, bottom, right);
582: }
583:
584: public boolean isBorderOpaque() {
585: return false;
586: }
587: }
588:
589: private ActionListener myActionListener;
590: private static final Color FILL = Color.WHITE;
591: private static final Color STROKE = new Color(0x444444);
592: private static final URL E_IMAGE_URL = Decoration.class
593: .getResource("resources/e.png"); // NOI18N
594: private static final Color TEXT_COLOR = new Color(0xBB2200);
595: }
|