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 final static 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         public boolean isFocusTraversable() {
 246             return false;
 247         }
 248 
 249         public void requestFocus() {
 250             // ignore request.
 251         }
 252 
 253         public Dimension getMinimumSize() {
 254             return buttonDimension;
 255         }
 256 
 257         public Dimension getPreferredSize() {
 258             return buttonDimension;
 259         }
 260 
 261         public void paintComponent(Graphics g) {
 262             Dimension d = getSize();
 263             int maxX = d.width - 1;
 264             int maxY = d.height - 1;
 265 
 266             // draw background
 267             g.setColor(color);
 268             g.fillRect(1, 1, d.width, d.height);
 269 
 270             // draw border
 271             boolean pressed = getModel().isPressed();
 272             g.setColor(pressed ? shadow : highlight);
 273             g.drawLine(0, 0, maxX, 0);
 274             g.drawLine(0, 0, 0, maxY);
 275             g.setColor(pressed ? highlight : shadow);
 276             g.drawLine(1, maxY, maxX, maxY);
 277             g.drawLine(maxX, 1, maxX, maxY);
 278         }
 279     }
 280 
 281     @SuppressWarnings("serial") // Superclass is not serializable across versions
 282     private class MinimizeButton extends FrameButton {
 283         public void paintComponent(Graphics g) {
 284             super.paintComponent(g);
 285             g.setColor(highlight);
 286             g.drawLine(7, 8, 7, 11);
 287             g.drawLine(7, 8, 10, 8);
 288             g.setColor(shadow);
 289             g.drawLine(8, 11, 10, 11);
 290             g.drawLine(11, 9, 11, 11);
 291         }
 292     }
 293 
 294    @SuppressWarnings("serial") // Superclass is not serializable across versions
 295    private class MaximizeButton extends FrameButton {
 296         public void paintComponent(Graphics g) {
 297             super.paintComponent(g);
 298             int max = BUTTON_SIZE - 5;
 299             boolean isMaxed = frame.isMaximum();
 300             g.setColor(isMaxed ? shadow : highlight);
 301             g.drawLine(4, 4, 4, max);
 302             g.drawLine(4, 4, max, 4);
 303             g.setColor(isMaxed ? highlight : shadow);
 304             g.drawLine(5, max, max, max);
 305             g.drawLine(max, 5, max, max);
 306         }
 307     }
 308 
 309     @SuppressWarnings("serial") // Superclass is not serializable across versions
 310     private class SystemButton extends FrameButton {
 311         public boolean isFocusTraversable() { return false; }
 312         public void requestFocus() {}
 313 
 314         public void paintComponent(Graphics g) {
 315             super.paintComponent(g);
 316             g.setColor(highlight);
 317             g.drawLine(4, 8, 4, 11);
 318             g.drawLine(4, 8, BUTTON_SIZE - 5, 8);
 319             g.setColor(shadow);
 320             g.drawLine(5, 11, BUTTON_SIZE - 5, 11);
 321             g.drawLine(BUTTON_SIZE - 5, 9, BUTTON_SIZE - 5, 11);
 322         }
 323     }
 324 
 325     @SuppressWarnings("serial") // Superclass is not serializable across versions
 326     private class Title extends FrameButton {
 327         Title(String title) {
 328             super();
 329             setText(title);
 330             setHorizontalAlignment(SwingConstants.CENTER);
 331             setBorder(BorderFactory.createBevelBorder(
 332                 BevelBorder.RAISED,
 333                 UIManager.getColor("activeCaptionBorder"),
 334                 UIManager.getColor("inactiveCaptionBorder")));
 335 
 336             // Forward mouse events to titlebar for moves.
 337             addMouseMotionListener(new MouseMotionListener() {
 338                 public void mouseDragged(MouseEvent e) {
 339                     forwardEventToParent(e);
 340                 }
 341                 public void mouseMoved(MouseEvent e) {
 342                     forwardEventToParent(e);
 343                 }
 344             });
 345             addMouseListener(new MouseListener() {
 346                 public void mouseClicked(MouseEvent e) {
 347                     forwardEventToParent(e);
 348                 }
 349                 public void mousePressed(MouseEvent e) {
 350                     forwardEventToParent(e);
 351                 }
 352                 public void mouseReleased(MouseEvent e) {
 353                     forwardEventToParent(e);
 354                 }
 355                 public void mouseEntered(MouseEvent e) {
 356                     forwardEventToParent(e);
 357                 }
 358                 public void mouseExited(MouseEvent e) {
 359                     forwardEventToParent(e);
 360                 }
 361             });
 362         }
 363 
 364         void forwardEventToParent(MouseEvent e) {
 365             getParent().dispatchEvent(new MouseEvent(
 366                 getParent(), e.getID(), e.getWhen(), e.getModifiers(),
 367                 e.getX(), e.getY(),  e.getXOnScreen(),
 368                 e.getYOnScreen(), e.getClickCount(),
 369                 e.isPopupTrigger(),  MouseEvent.NOBUTTON));
 370         }
 371 
 372         public void paintComponent(Graphics g) {
 373             super.paintComponent(g);
 374             if (frame.isSelected()) {
 375                 g.setColor(UIManager.getColor("activeCaptionText"));
 376             } else {
 377                 g.setColor(UIManager.getColor("inactiveCaptionText"));
 378             }
 379             Dimension d = getSize();
 380             String frameTitle = frame.getTitle();
 381             if (frameTitle != null) {
 382                 MotifGraphicsUtils.drawStringInRect(frame, g, frameTitle,
 383                                                     0, 0, d.width, d.height,
 384                                                     SwingConstants.CENTER);
 385             }
 386         }
 387     }
 388 }