Path: blob/master/src/demo/share/jfc/TransparentRuler/transparentruler/Ruler.java
41155 views
/*1* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/3839package transparentruler;404142import java.awt.*;43import java.awt.GraphicsDevice.WindowTranslucency;44import static java.awt.GraphicsDevice.WindowTranslucency.*;45import java.awt.event.ActionEvent;46import java.awt.event.ComponentAdapter;47import java.awt.event.ComponentEvent;48import java.awt.event.KeyAdapter;49import java.awt.event.KeyEvent;50import java.awt.event.MouseAdapter;51import java.awt.event.MouseEvent;52import java.awt.geom.Path2D.Float;53import java.lang.reflect.InvocationTargetException;54import javax.swing.AbstractAction;55import javax.swing.Action;56import javax.swing.JFrame;57import javax.swing.JMenuItem;58import javax.swing.JPanel;59import javax.swing.JPopupMenu;60import javax.swing.SwingUtilities;61import javax.swing.WindowConstants;626364/**65* This sample demonstrates shaped and translucent window feature.66* @author Alexander Kouznetsov67*/68@SuppressWarnings("serial")69public class Ruler extends JFrame {7071private static final Color BACKGROUND = Color.RED;72private static final Color FOREGROUND = Color.WHITE;73private static final int OPACITY = 180;74private static final int W = 70;75private static final int F_HEIGHT = 400;76private static final int F_WIDTH = (int) (F_HEIGHT * 1.618 + 0.5);7778private static boolean translucencySupported;79private static boolean transparencySupported;8081private static boolean checkTranslucencyMode(WindowTranslucency arg) {82GraphicsEnvironment ge =83GraphicsEnvironment.getLocalGraphicsEnvironment();84GraphicsDevice gd = ge.getDefaultScreenDevice();85return gd.isWindowTranslucencySupported(arg);86}8788public Shape buildShape() {89int h = getHeight();90int w = getWidth();91float a = (float) Math.hypot(h, w);92Float path = new java.awt.geom.Path2D.Float();93path.moveTo(0, 0);94path.lineTo(w, 0);95path.lineTo(0, h);96path.closePath();97path.moveTo(W, W);98path.lineTo(W, h - W * (a + h) / w);99path.lineTo(w - W * (a + w) / h, W);100path.closePath();101return path;102}103104private final ComponentAdapter componentListener = new ComponentAdapter() {105106/**107* Applies the shape to window. It is recommended to apply shape in108* componentResized() method109*/110@Override111public void componentResized(ComponentEvent e) {112113// We do apply shape only if PERPIXEL_TRANSPARENT is supported114if (transparencySupported) {115setShape(buildShape());116}117}118};119120private final Action exitAction = new AbstractAction("Exit") {121122{123putValue(Action.MNEMONIC_KEY, KeyEvent.VK_X);124}125126@Override127public void actionPerformed(ActionEvent e) {128System.exit(0);129}130};131132private final JPopupMenu jPopupMenu = new JPopupMenu();133134{135jPopupMenu.add(new JMenuItem(exitAction));136137// To avoid popup cutting by main window shape forbid light-weight popups138jPopupMenu.setLightWeightPopupEnabled(false);139}140141/**142* Implements mouse-related behavior: window dragging and popup menu143* invocation144*/145private final MouseAdapter mouseListener = new MouseAdapter() {146147int x, y;148149@Override150public void mousePressed(MouseEvent e) {151if (e.getButton() == MouseEvent.BUTTON1) {152x = e.getX();153y = e.getY();154}155}156157@Override158public void mouseDragged(MouseEvent e) {159if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) != 0) {160setLocation(e.getXOnScreen() - x, e.getYOnScreen() - y);161}162}163164@Override165public void mouseReleased(MouseEvent e) {166if (e.isPopupTrigger()) {167jPopupMenu.show(getContentPane(), e.getX(), e.getY());168}169}170};171172/**173* Implements keyboard navigation. Arrows move by 5 pixels, Ctrl + arrows174* move by 50 pixels, Alt + arrows move by 1 pixel.175* Esc exits the application.176*/177private final KeyAdapter keyboardListener = new KeyAdapter() {178179@Override180public void keyPressed(KeyEvent e) {181int step = e.isControlDown() ? 50 : e.isAltDown() ? 1 : 5;182switch (e.getKeyCode()) {183case KeyEvent.VK_LEFT:184setLocation(getX() - step, getY());185break;186case KeyEvent.VK_RIGHT:187setLocation(getX() + step, getY());188break;189case KeyEvent.VK_UP:190setLocation(getX(), getY() - step);191break;192case KeyEvent.VK_DOWN:193setLocation(getX(), getY() + step);194break;195case KeyEvent.VK_ESCAPE:196exitAction.actionPerformed(null);197}198}199};200201public Ruler() {202setUndecorated(true);203204// Enables perpixel translucency205setBackground(new Color(BACKGROUND.getRed(), BACKGROUND.getGreen(),206BACKGROUND.getBlue(), OPACITY));207208addMouseListener(mouseListener);209addMouseMotionListener(mouseListener);210addComponentListener(componentListener);211addKeyListener(keyboardListener);212setContentPane(new JPanel() {213214@Override215protected void paintComponent(Graphics g) {216Graphics2D gg = (Graphics2D) g.create();217int w = getWidth();218int h = getHeight();219int hh = gg.getFontMetrics().getAscent();220221// This is an approach to apply shape when PERPIXEL_TRANSPARENT222// isn't supported223if (!transparencySupported) {224gg.setBackground(new Color(0, 0, 0, 0));225gg.clearRect(0, 0, w, h);226gg.clip(buildShape());227228gg.setBackground(Ruler.this.getBackground());229gg.clearRect(0, 0, w, h);230}231232gg.setColor(FOREGROUND);233for (int x = 0; x < w * (h - 8) / h - 5; x += 5) {234boolean hi = x % 50 == 0;235gg.drawLine(x + 5, 0, x + 5,236hi ? 20 : (x % 25 == 0 ? 13 : 8));237if (hi) {238String number = Integer.toString(x);239int ww = gg.getFontMetrics().stringWidth(number);240gg.drawString(number, x + 5 - ww / 2, 20 + hh);241}242}243244gg.dispose();245}246});247setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);248setSize(F_WIDTH, F_HEIGHT);249setLocationByPlatform(true);250}251252/**253* @param args the command line arguments are ignored254*/255public static void main(String[] args) throws InterruptedException, InvocationTargetException {256257SwingUtilities.invokeAndWait(new Runnable() {258259@Override260public void run() {261translucencySupported = checkTranslucencyMode(PERPIXEL_TRANSLUCENT);262transparencySupported = checkTranslucencyMode(PERPIXEL_TRANSPARENT);263264if (!translucencySupported) {265System.err.println("This application requires "266+ "'PERPIXEL_TRANSLUCENT' translucency mode to "267+ "be supported.");268System.exit(-1);269}270271Ruler ruler = new Ruler();272ruler.setVisible(true);273}274});275}276}277278279