1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.java.swing.plaf.motif;
  27 
  28 import java.awt.*;
  29 import java.awt.event.*;
  30 import javax.swing.*;
  31 import javax.swing.border.*;
  32 import javax.swing.event.InternalFrameEvent;
  33 import javax.swing.plaf.basic.*;
  34 import java.util.EventListener;
  35 import java.beans.PropertyChangeListener;
  36 import java.beans.PropertyChangeEvent;
  37 import java.beans.VetoableChangeListener;
  38 import java.beans.PropertyVetoException;
  39 
  40 /**
  41  * Class that manages a Motif title bar
  42  *
  43  * @since 1.3
  44  */
  45 @SuppressWarnings("serial") // Superclass is not serializable across versions
  46 public class MotifInternalFrameTitlePane
  47     extends BasicInternalFrameTitlePane implements LayoutManager, ActionListener, PropertyChangeListener
  48 {
  49     SystemButton systemButton;
  50     MinimizeButton minimizeButton;
  51     MaximizeButton maximizeButton;
  52     JPopupMenu systemMenu;
  53     Title title;
  54     Color color;
  55     Color highlight;
  56     Color shadow;
  57 
  58     // The width and height of a title pane button
  59     public static final int BUTTON_SIZE = 19;  // 17 + 1 pixel border
  60 
  61 
  62     public MotifInternalFrameTitlePane(JInternalFrame frame) {
  63         super(frame);
  64     }
  65 
  66     protected void installDefaults() {
  67         setFont(UIManager.getFont("InternalFrame.titleFont"));
  68         setPreferredSize(new Dimension(100, BUTTON_SIZE));
  69     }
  70 
  71     protected void uninstallListeners() {
  72         // Get around protected method in superclass
  73         super.uninstallListeners();
  74     }
  75 
  76     protected PropertyChangeListener createPropertyChangeListener() {
  77         return this;
  78     }
  79 
  80     protected LayoutManager createLayout() {
  81         return this;
  82     }
  83 
  84     JPopupMenu getSystemMenu() {
  85         return systemMenu;
  86     }
  87 
  88     protected void assembleSystemMenu() {
  89         systemMenu = new JPopupMenu();
  90         JMenuItem mi = systemMenu.add(restoreAction);
  91         mi.setMnemonic(getButtonMnemonic("restore"));
  92         mi = systemMenu.add(moveAction);
  93         mi.setMnemonic(getButtonMnemonic("move"));
  94         mi = systemMenu.add(sizeAction);
  95         mi.setMnemonic(getButtonMnemonic("size"));
  96         mi = systemMenu.add(iconifyAction);
  97         mi.setMnemonic(getButtonMnemonic("minimize"));
  98         mi = systemMenu.add(maximizeAction);
  99         mi.setMnemonic(getButtonMnemonic("maximize"));
 100         systemMenu.add(new JSeparator());
 101         mi = systemMenu.add(closeAction);
 102         mi.setMnemonic(getButtonMnemonic("close"));
 103 
 104         systemButton = new SystemButton();
 105         systemButton.addActionListener(new ActionListener() {
 106             public void actionPerformed(ActionEvent e) {
 107                 systemMenu.show(systemButton, 0, BUTTON_SIZE);
 108             }
 109         });
 110 
 111         systemButton.addMouseListener(new MouseAdapter() {
 112             public void mousePressed(MouseEvent evt) {
 113                 try {
 114                     frame.setSelected(true);
 115                 } catch (PropertyVetoException pve) {
 116                 }
 117                 if ((evt.getClickCount() == 2)) {
 118                     closeAction.actionPerformed(new
 119                         ActionEvent(evt.getSource(),
 120                             ActionEvent.ACTION_PERFORMED,
 121                             null, evt.getWhen(), 0));
 122                     systemMenu.setVisible(false);
 123                 }
 124             }
 125         });
 126     }
 127 
 128     private static int getButtonMnemonic(String button) {
 129         try {
 130             return Integer.parseInt(UIManager.getString(
 131                     "InternalFrameTitlePane." + button + "Button.mnemonic"));
 132         } catch (NumberFormatException e) {
 133             return -1;
 134         }
 135     }
 136 
 137     protected void createButtons() {
 138         minimizeButton = new MinimizeButton();
 139         minimizeButton.addActionListener(iconifyAction);
 140 
 141         maximizeButton = new MaximizeButton();
 142         maximizeButton.addActionListener(maximizeAction);
 143     }
 144 
 145 
 146     protected void addSubComponents() {
 147         title = new Title(frame.getTitle());
 148         title.setFont(getFont());
 149 
 150         add(systemButton);
 151         add(title);
 152         add(minimizeButton);
 153         add(maximizeButton);
 154     }
 155 
 156     public void paintComponent(Graphics g) {
 157     }
 158 
 159     void setColors(Color c, Color h, Color s) {
 160         color = c;
 161         highlight = h;
 162         shadow = s;
 163     }
 164 
 165     public void actionPerformed(ActionEvent e) {
 166     }
 167 
 168     public void propertyChange(PropertyChangeEvent evt) {
 169         String prop = evt.getPropertyName();
 170         JInternalFrame f = (JInternalFrame)evt.getSource();
 171         boolean value = false;
 172         if (JInternalFrame.IS_SELECTED_PROPERTY.equals(prop)) {
 173             repaint();
 174         } else if (prop.equals("maximizable")) {
 175             if ((Boolean)evt.getNewValue() == Boolean.TRUE)
 176                 add(maximizeButton);
 177             else
 178                 remove(maximizeButton);
 179             revalidate();
 180             repaint();
 181         } else if (prop.equals("iconable")) {
 182             if ((Boolean)evt.getNewValue() == Boolean.TRUE)
 183                 add(minimizeButton);
 184             else
 185                 remove(minimizeButton);
 186             revalidate();
 187             repaint();
 188         } else if (prop.equals(JInternalFrame.TITLE_PROPERTY)) {
 189             repaint();
 190         }
 191         enableActions();
 192     }
 193 
 194     public void addLayoutComponent(String name, Component c) {}
 195     public void removeLayoutComponent(Component c) {}
 196     public Dimension preferredLayoutSize(Container c)  {
 197         return minimumLayoutSize(c);
 198     }
 199 
 200     public Dimension minimumLayoutSize(Container c) {
 201         return new Dimension(100, BUTTON_SIZE);
 202     }
 203 
 204     public void layoutContainer(Container c) {
 205         int w = getWidth();
 206         systemButton.setBounds(0, 0, BUTTON_SIZE, BUTTON_SIZE);
 207         int x = w - BUTTON_SIZE;
 208 
 209         if(frame.isMaximizable()) {
 210             maximizeButton.setBounds(x, 0, BUTTON_SIZE, BUTTON_SIZE);
 211             x -= BUTTON_SIZE;
 212         } else if(maximizeButton.getParent() != null) {
 213             maximizeButton.getParent().remove(maximizeButton);
 214         }
 215 
 216         if(frame.isIconifiable()) {
 217             minimizeButton.setBounds(x, 0, BUTTON_SIZE, BUTTON_SIZE);
 218             x -= BUTTON_SIZE;
 219         } else if(minimizeButton.getParent() != null) {
 220             minimizeButton.getParent().remove(minimizeButton);
 221         }
 222 
 223         title.setBounds(BUTTON_SIZE, 0, x, BUTTON_SIZE);
 224     }
 225 
 226     protected void showSystemMenu(){
 227       systemMenu.show(systemButton, 0, BUTTON_SIZE);
 228     }
 229 
 230     protected void hideSystemMenu(){
 231       systemMenu.setVisible(false);
 232     }
 233 
 234     static Dimension buttonDimension = new Dimension(BUTTON_SIZE, BUTTON_SIZE);
 235 
 236     @SuppressWarnings("serial") // Superclass is not serializable across versions
 237     private abstract class FrameButton extends JButton {
 238 
 239         FrameButton() {
 240             super();
 241             setFocusPainted(false);
 242             setBorderPainted(false);
 243         }
 244 
 245         @SuppressWarnings("deprecation")
 246         public boolean isFocusTraversable() {
 247             return false;
 248         }
 249 
 250         public void requestFocus() {
 251             // ignore request.
 252         }
 253 
 254         public Dimension getMinimumSize() {
 255             return buttonDimension;
 256         }
 257 
 258         public Dimension getPreferredSize() {
 259             return buttonDimension;
 260         }
 261 
 262         public void paintComponent(Graphics g) {
 263             Dimension d = getSize();
 264             int maxX = d.width - 1;
 265             int maxY = d.height - 1;
 266 
 267             // draw background
 268             g.setColor(color);
 269             g.fillRect(1, 1, d.width, d.height);
 270 
 271             // draw border
 272             boolean pressed = getModel().isPressed();
 273             g.setColor(pressed ? shadow : highlight);
 274             g.drawLine(0, 0, maxX, 0);
 275             g.drawLine(0, 0, 0, maxY);
 276             g.setColor(pressed ? highlight : shadow);
 277             g.drawLine(1, maxY, maxX, maxY);
 278             g.drawLine(maxX, 1, maxX, maxY);
 279         }
 280     }
 281 
 282     @SuppressWarnings("serial") // Superclass is not serializable across versions
 283     private class MinimizeButton extends FrameButton {
 284         public void paintComponent(Graphics g) {
 285             super.paintComponent(g);
 286             g.setColor(highlight);
 287             g.drawLine(7, 8, 7, 11);
 288             g.drawLine(7, 8, 10, 8);
 289             g.setColor(shadow);
 290             g.drawLine(8, 11, 10, 11);
 291             g.drawLine(11, 9, 11, 11);
 292         }
 293     }
 294 
 295    @SuppressWarnings("serial") // Superclass is not serializable across versions
 296    private class MaximizeButton extends FrameButton {
 297         public void paintComponent(Graphics g) {
 298             super.paintComponent(g);
 299             int max = BUTTON_SIZE - 5;
 300             boolean isMaxed = frame.isMaximum();
 301             g.setColor(isMaxed ? shadow : highlight);
 302             g.drawLine(4, 4, 4, max);
 303             g.drawLine(4, 4, max, 4);
 304             g.setColor(isMaxed ? highlight : shadow);
 305             g.drawLine(5, max, max, max);
 306             g.drawLine(max, 5, max, max);
 307         }
 308     }
 309 
 310     @SuppressWarnings("serial") // Superclass is not serializable across versions
 311     private class SystemButton extends FrameButton {
 312         public boolean isFocusTraversable() { return false; }
 313         public void requestFocus() {}
 314 
 315         public void paintComponent(Graphics g) {
 316             super.paintComponent(g);
 317             g.setColor(highlight);
 318             g.drawLine(4, 8, 4, 11);
 319             g.drawLine(4, 8, BUTTON_SIZE - 5, 8);
 320             g.setColor(shadow);
 321             g.drawLine(5, 11, BUTTON_SIZE - 5, 11);
 322             g.drawLine(BUTTON_SIZE - 5, 9, BUTTON_SIZE - 5, 11);
 323         }
 324     }
 325 
 326     @SuppressWarnings("serial") // Superclass is not serializable across versions
 327     private class Title extends FrameButton {
 328         Title(String title) {
 329             super();
 330             setText(title);
 331             setHorizontalAlignment(SwingConstants.CENTER);
 332             setBorder(BorderFactory.createBevelBorder(
 333                 BevelBorder.RAISED,
 334                 UIManager.getColor("activeCaptionBorder"),
 335                 UIManager.getColor("inactiveCaptionBorder")));
 336 
 337             // Forward mouse events to titlebar for moves.
 338             addMouseMotionListener(new MouseMotionListener() {
 339                 public void mouseDragged(MouseEvent e) {
 340                     forwardEventToParent(e);
 341                 }
 342                 public void mouseMoved(MouseEvent e) {
 343                     forwardEventToParent(e);
 344                 }
 345             });
 346             addMouseListener(new MouseListener() {
 347                 public void mouseClicked(MouseEvent e) {
 348                     forwardEventToParent(e);
 349                 }
 350                 public void mousePressed(MouseEvent e) {
 351                     forwardEventToParent(e);
 352                 }
 353                 public void mouseReleased(MouseEvent e) {
 354                     forwardEventToParent(e);
 355                 }
 356                 public void mouseEntered(MouseEvent e) {
 357                     forwardEventToParent(e);
 358                 }
 359                 public void mouseExited(MouseEvent e) {
 360                     forwardEventToParent(e);
 361                 }
 362             });
 363         }
 364 
 365         void forwardEventToParent(MouseEvent e) {
 366             getParent().dispatchEvent(new MouseEvent(
 367                 getParent(), e.getID(), e.getWhen(), e.getModifiers(),
 368                 e.getX(), e.getY(),  e.getXOnScreen(),
 369                 e.getYOnScreen(), e.getClickCount(),
 370                 e.isPopupTrigger(),  MouseEvent.NOBUTTON));
 371         }
 372 
 373         public void paintComponent(Graphics g) {
 374             super.paintComponent(g);
 375             if (frame.isSelected()) {
 376                 g.setColor(UIManager.getColor("activeCaptionText"));
 377             } else {
 378                 g.setColor(UIManager.getColor("inactiveCaptionText"));
 379             }
 380             Dimension d = getSize();
 381             String frameTitle = frame.getTitle();
 382             if (frameTitle != null) {
 383                 MotifGraphicsUtils.drawStringInRect(frame, g, frameTitle,
 384                                                     0, 0, d.width, d.height,
 385                                                     SwingConstants.CENTER);
 386             }
 387         }
 388     }
 389 }