/*
* Copyright © 2007-2017 Rebecca G. Bettencourt / Kreative Software
* <p>
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* <a href="http://www.mozilla.org/MPL/">http://www.mozilla.org/MPL/</a>
* <p>
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
* <p>
* Alternatively, the contents of this file may be used under the terms
* of the GNU Lesser General Public License (the "LGPL License"), in which
* case the provisions of LGPL License are applicable instead of those
* above. If you wish to allow use of your version of this file only
* under the terms of the LGPL License and not to allow others to use
* your version of this file under the MPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the LGPL License. If you do not delete
* the provisions above, a recipient may use your version of this file
* under either the MPL or the LGPL License.
* @since KJL 1.0
* @author Rebecca G. Bettencourt, Kreative Software
*/
package com.kreative.paint.swing;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class JPalette extends JFrame {
private static final long serialVersionUID = 1L;
private static boolean isMacOS;
static {
try {
String osName = System.getProperty("os.name");
isMacOS = (osName.toUpperCase().contains("MAC OS"));
} catch (Exception e) {
isMacOS = false;
}
}
private JPanel main = null;
private JPanel titlebar = null;
private JLabel titlelabel = null;
private Container contentpane = null;
private JPanel resizefooter = null;
private boolean jplte_visible = super.isVisible();
private boolean jplte_obscured = false;
private boolean jplte_lock = false;
public JPalette() {
makeGUI();
makeVT();
}
public JPalette(String title) {
super.setTitle(title);
makeGUI();
makeVT();
}
private void makeGUI() {
if (isMacOS) {
setAlwaysOnTop(true);
setFocusable(false);
setFocusableWindowState(false);
getRootPane().putClientProperty("Window.style", "small");
setMinimumSize(new Dimension(16, 16));
main = new JPanel(new BorderLayout());
titlebar = null;
titlelabel = null;
contentpane = super.getContentPane();
resizefooter = new JPanel(new BorderLayout());
resizefooter.add(new PaletteResizeBox(this), BorderLayout.EAST);
resizefooter.setVisible(super.isResizable());
main.add(contentpane, BorderLayout.CENTER);
main.add(resizefooter, BorderLayout.SOUTH);
super.setContentPane(main);
} else {
setAlwaysOnTop(true);
setFocusable(false);
setFocusableWindowState(false);
setUndecorated(true);
setMinimumSize(new Dimension(16, 16));
main = new JPanel(new BorderLayout());
titlebar = new JPanel(new BorderLayout()) {
private static final long serialVersionUID = 1L;
protected void paintComponent(Graphics g) {
Insets i = getInsets();
int x = i.left;
int y = i.top;
int w = getWidth() - i.left - i.right;
int h = getHeight() - i.top - i.bottom;
((Graphics2D)g).setPaint(new GradientPaint(x, y, new Color(0xFF0A246A), x+w, y, new Color(0xFFA6CAF0)));
g.fillRect(x, y, w, h);
}
};
titlelabel = new PaletteTitleLabel(this, super.getTitle());
contentpane = super.getContentPane();
resizefooter = null;
titlebar.setOpaque(true);
titlebar.setBackground(Color.blue.darker());
titlebar.setBorder(BorderFactory.createEmptyBorder(0, 0, 2, 0));
titlelabel.setFont(titlelabel.getFont().deriveFont(Font.BOLD, 11.0f));
titlelabel.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 0));
titlelabel.setForeground(Color.white);
PaletteCloseBox c = new PaletteCloseBox(this);
c.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
titlebar.add(titlelabel, BorderLayout.CENTER);
titlebar.add(c, BorderLayout.EAST);
main.add(titlebar, BorderLayout.NORTH);
main.add(contentpane, BorderLayout.CENTER);
Border inner = BorderFactory.createEmptyBorder(2, 2, 2, 2);
Border outer = BorderFactory.createBevelBorder(BevelBorder.RAISED, Color.lightGray, Color.white, Color.darkGray, Color.gray);
main.setBorder(BorderFactory.createCompoundBorder(outer, inner));
super.setContentPane(main);
}
}
private void makeVT() {
this.jplte_visible = super.isVisible();
this.jplte_obscured = false;
this.jplte_lock = false;
getToolkit().addAWTEventListener(new BoundAWTListener(), AWTEvent.WINDOW_EVENT_MASK | AWTEvent.WINDOW_FOCUS_EVENT_MASK);
}
private synchronized void setObscured(boolean obscured) {
if (!jplte_lock) {
jplte_lock = true;
if (obscured) {
this.jplte_obscured = true;
super.setVisible(false);
} else {
super.setVisible(this.jplte_visible);
this.jplte_obscured = false;
}
jplte_lock = false;
}
}
// overwriting this stuff is not for the faint of heart;
// if not done properly, the results can be disastrous
public synchronized boolean isVisible() {
return this.jplte_visible;
}
public synchronized void setVisible(boolean visible) {
if (!jplte_lock) {
jplte_lock = true;
this.jplte_visible = visible;
if (!jplte_obscured) super.setVisible(visible);
jplte_lock = false;
} else {
super.setVisible(visible);
}
}
@Deprecated
public synchronized void show() {
if (!jplte_lock) {
jplte_lock = true;
this.jplte_visible = true;
if (!jplte_obscured) super.show();
jplte_lock = false;
} else {
super.show();
}
}
@Deprecated
public synchronized void hide() {
if (!jplte_lock) {
jplte_lock = true;
this.jplte_visible = false;
if (!jplte_obscured) super.hide();
jplte_lock = false;
} else {
super.hide();
}
}
@Override
public Container getContentPane() {
return (main != null) ? contentpane : super.getContentPane();
}
@Override
public void setContentPane(Container c) {
if (main != null) {
main.remove(contentpane);
contentpane = c;
main.add(contentpane, BorderLayout.CENTER);
} else {
super.setContentPane(c);
}
}
@Override
public void setTitle(String title) {
super.setTitle(title);
if (titlelabel != null) {
titlelabel.setText(title);
}
}
@Override
public Component add(Component c) {
return (main != null) ? contentpane.add(c) : super.add(c);
}
@Override
public Component add(Component c, int index) {
return (main != null) ? contentpane.add(c,index) : super.add(c,index);
}
@Override
public void add(Component c, Object constraints) {
if (main != null) contentpane.add(c,constraints); else super.add(c,constraints);
}
@Override
public void add(Component c, Object constraints, int index) {
if (main != null) contentpane.add(c,constraints,index); else super.add(c,constraints,index);
}
@Override
public Component add(String name, Component c) {
return (main != null) ? contentpane.add(name,c) : super.add(name,c);
}
@Override
public void remove(Component c) {
if (main != null) contentpane.remove(c); else super.remove(c);
}
@Override
public void remove(int index) {
if (main != null) contentpane.remove(index); else super.remove(index);
}
@Override
public void removeAll() {
if (main != null) contentpane.removeAll(); else super.removeAll();
}
@Override
public LayoutManager getLayout() {
return (main != null) ? contentpane.getLayout() : super.getLayout();
}
@Override
public void setLayout(LayoutManager lm) {
if (main != null) contentpane.setLayout(lm); else super.setLayout(lm);
}
@Override
public void setResizable(boolean b) {
super.setResizable(b);
if (resizefooter != null) {
resizefooter.setVisible(b);
}
}
private class BoundAWTListener implements AWTEventListener {
public void eventDispatched(AWTEvent e) {
if (e instanceof WindowEvent) {
switch (e.getID()) {
case WindowEvent.WINDOW_ACTIVATED:
case WindowEvent.WINDOW_GAINED_FOCUS:
setObscured(false);
break;
case WindowEvent.WINDOW_DEACTIVATED:
case WindowEvent.WINDOW_LOST_FOCUS:
if (((WindowEvent)e).getOppositeWindow() == null) setObscured(true);
break;
}
}
}
}
private static class PaletteTitleLabel extends JLabel {
private static final long serialVersionUID = 1L;
private Window whatToMove;
private int ox, oy;
public PaletteTitleLabel(Window what, String s) {
super(s);
whatToMove = what;
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
Point p = MouseInfo.getPointerInfo().getLocation();
ox = p.x-whatToMove.getX();
oy = p.y-whatToMove.getY();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
Point p = MouseInfo.getPointerInfo().getLocation();
int nx = p.x-ox;
int ny = p.y-oy;
whatToMove.setLocation(nx, ny);
}
});
}
}
private static class PaletteCloseBox extends JLabel {
private static final long serialVersionUID = 1L;
private Window whatToClose;
public PaletteCloseBox(Window what) {
super(new ImageIcon(CLOSE_WIDGET));
whatToClose = what;
this.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
EventQueue eq = whatToClose.getToolkit().getSystemEventQueue();
eq.postEvent(new WindowEvent(whatToClose, WindowEvent.WINDOW_CLOSING));
}
});
}
}
private static class PaletteResizeBox extends JLabel {
private static final long serialVersionUID = 1L;
private Window whatToResize;
private int ox, oy;
public PaletteResizeBox(Window what) {
super(new ImageIcon(RESIZE_WIDGET));
whatToResize = what;
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
Point p = MouseInfo.getPointerInfo().getLocation();
ox = p.x-whatToResize.getWidth();
oy = p.y-whatToResize.getHeight();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
public void mouseDragged(MouseEvent e) {
Point p = MouseInfo.getPointerInfo().getLocation();
int nx = Math.max(32, p.x-ox);
int ny = Math.max(32, p.y-oy);
whatToResize.setSize(nx, ny);
}
});
}
}
private static final Image CLOSE_WIDGET;
private static final Image RESIZE_WIDGET;
static {
Toolkit tk = Toolkit.getDefaultToolkit();
CLOSE_WIDGET = tk.createImage(new byte[] {
-119,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,
0,0,0,13,0,0,0,13,8,6,0,0,0,114,-21,-28,
124,0,0,0,66,73,68,65,84,120,-38,99,96,32,7,-4,
39,17,56,56,56,-4,7,107,-70,114,-31,4,81,-72,-95,-95,
-127,74,-102,64,-82,5,97,92,124,-100,54,-63,20,-94,107,32,
-24,60,108,26,-88,107,19,-39,126,-94,109,-112,-125,56,-60,98,
-80,38,16,65,42,6,0,1,-108,-69,-110,-56,40,120,-123,0,
0,0,0,73,69,78,68,-82,66,96,-126
});
RESIZE_WIDGET = tk.createImage(new byte[] {
-119,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,
0,0,0,11,0,0,0,11,8,6,0,0,0,-87,-84,119,
38,0,0,0,-92,73,68,65,84,120,-38,-115,-112,75,10,-124,
48,16,68,-67,-1,73,18,93,-27,54,-30,70,18,-125,-97,104,
76,80,-4,-20,106,-88,108,100,112,112,44,-24,38,-48,-113,-22,
74,103,85,85,-95,-82,-21,87,-107,-79,-67,-43,43,120,28,71,
-100,-25,-7,31,-10,-34,35,-49,115,-60,24,-97,97,58,74,41,
-47,-74,-19,115,12,58,18,-76,-42,-90,-38,-9,-3,55,60,77,
19,-118,-94,-128,-42,26,-61,48,-92,-9,-78,44,119,-104,67,33,
4,-116,49,105,61,-35,67,8,-9,24,-52,72,-112,107,-5,-66,
79,31,-101,-25,25,101,89,98,93,-41,11,118,-50,37,-105,-82,
-21,-48,52,-51,23,-88,-108,-62,113,28,23,-52,59,-14,60,-44,
-74,109,41,35,69,71,-126,-44,7,92,-121,-58,18,51,43,-121,
32,0,0,0,0,73,69,78,68,-82,66,96,-126
});
tk.prepareImage(CLOSE_WIDGET, -1, -1, null);
tk.prepareImage(RESIZE_WIDGET, -1, -1, null);
}
}