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 import sun.awt.AWTAccessor;
  41 import sun.awt.AWTAccessor.MouseEventAccessor;
  42 
  43 /**
  44  * Class that manages a Motif title bar
  45  *
  46  * @since 1.3
  47  */
  48 @SuppressWarnings("serial") // Superclass is not serializable across versions
  49 public class MotifInternalFrameTitlePane
  50     extends BasicInternalFrameTitlePane implements LayoutManager, ActionListener, PropertyChangeListener
  51 {
  52     SystemButton systemButton;
  53     MinimizeButton minimizeButton;
  54     MaximizeButton maximizeButton;
  55     JPopupMenu systemMenu;
  56     Title title;
  57     Color color;
  58     Color highlight;
  59     Color shadow;
  60 
  61     // The width and height of a title pane button
  62     public static final int BUTTON_SIZE = 19;  // 17 + 1 pixel border
  63 
  64 
  65     public MotifInternalFrameTitlePane(JInternalFrame frame) {
  66         super(frame);
  67     }
  68 
  69     protected void installDefaults() {
  70         setFont(UIManager.getFont("InternalFrame.titleFont"));
  71         setPreferredSize(new Dimension(100, BUTTON_SIZE));
  72     }
  73 
  74     protected void uninstallListeners() {
  75         // Get around protected method in superclass
  76         super.uninstallListeners();
  77     }
  78 
  79     protected PropertyChangeListener createPropertyChangeListener() {
  80         return this;
  81     }
  82 
  83     protected LayoutManager createLayout() {
  84         return this;
  85     }
  86 
  87     JPopupMenu getSystemMenu() {
  88         return systemMenu;
  89     }
  90 
  91     protected void assembleSystemMenu() {
  92         systemMenu = new JPopupMenu();
  93         JMenuItem mi = systemMenu.add(restoreAction);
  94         mi.setMnemonic(getButtonMnemonic("restore"));
  95         mi = systemMenu.add(moveAction);
  96         mi.setMnemonic(getButtonMnemonic("move"));
  97         mi = systemMenu.add(sizeAction);
  98         mi.setMnemonic(getButtonMnemonic("size"));
  99         mi = systemMenu.add(iconifyAction);
 100         mi.setMnemonic(getButtonMnemonic("minimize"));
 101         mi = systemMenu.add(maximizeAction);
 102         mi.setMnemonic(getButtonMnemonic("maximize"));
 103         systemMenu.add(new JSeparator());
 104         mi = systemMenu.add(closeAction);
 105         mi.setMnemonic(getButtonMnemonic("close"));
 106 
 107         systemButton = new SystemButton();
 108         systemButton.addActionListener(new ActionListener() {
 109             public void actionPerformed(ActionEvent e) {
 110                 systemMenu.show(systemButton, 0, BUTTON_SIZE);
 111             }
 112         });
 113 
 114         systemButton.addMouseListener(new MouseAdapter() {
 115             public void mousePressed(MouseEvent evt) {
 116                 try {
 117                     frame.setSelected(true);
 118                 } catch (PropertyVetoException pve) {
 119                 }
 120                 if ((evt.getClickCount() == 2)) {
 121                     closeAction.actionPerformed(new
 122                         ActionEvent(evt.getSource(),
 123                             ActionEvent.ACTION_PERFORMED,
 124                             null, evt.getWhen(), 0));
 125                     systemMenu.setVisible(false);
 126                 }
 127             }
 128         });
 129     }
 130 
 131     private static int getButtonMnemonic(String button) {
 132         try {
 133             return Integer.parseInt(UIManager.getString(
 134                     "InternalFrameTitlePane." + button + "Button.mnemonic"));
 135         } catch (NumberFormatException e) {
 136             return -1;
 137         }
 138     }
 139 
 140     protected void createButtons() {
 141         minimizeButton = new MinimizeButton();
 142         minimizeButton.addActionListener(iconifyAction);
 143 
 144         maximizeButton = new MaximizeButton();
 145         maximizeButton.addActionListener(maximizeAction);
 146     }
 147 
 148 
 149     protected void addSubComponents() {
 150         title = new Title(frame.getTitle());
 151         title.setFont(getFont());
 152 
 153         add(systemButton);
 154         add(title);
 155         add(minimizeButton);
 156         add(maximizeButton);
 157     }
 158 
 159     public void paintComponent(Graphics g) {
 160     }
 161 
 162     void setColors(Color c, Color h, Color s) {
 163         color = c;
 164         highlight = h;
 165         shadow = s;
 166     }
 167 
 168     public void actionPerformed(ActionEvent e) {
 169     }
 170 
 171     public void propertyChange(PropertyChangeEvent evt) {
 172         String prop = evt.getPropertyName();
 173         JInternalFrame f = (JInternalFrame)evt.getSource();
 174         boolean value = false;
 175         if (JInternalFrame.IS_SELECTED_PROPERTY.equals(prop)) {
 176             repaint();
 177         } else if (prop.equals("maximizable")) {
 178             if ((Boolean)evt.getNewValue() == Boolean.TRUE)
 179                 add(maximizeButton);
 180             else
 181                 remove(maximizeButton);
 182             revalidate();
 183             repaint();
 184         } else if (prop.equals("iconable")) {
 185             if ((Boolean)evt.getNewValue() == Boolean.TRUE)
 186                 add(minimizeButton);
 187             else
 188                 remove(minimizeButton);
 189             revalidate();
 190             repaint();
 191         } else if (prop.equals(JInternalFrame.TITLE_PROPERTY)) {
 192             repaint();
 193         }
 194         enableActions();
 195     }
 196 
 197     public void addLayoutComponent(String name, Component c) {}
 198     public void removeLayoutComponent(Component c) {}
 199     public Dimension preferredLayoutSize(Container c)  {
 200         return minimumLayoutSize(c);
 201     }
 202 
 203     public Dimension minimumLayoutSize(Container c) {
 204         return new Dimension(100, BUTTON_SIZE);
 205     }
 206 
 207     public void layoutContainer(Container c) {
 208         int w = getWidth();
 209         systemButton.setBounds(0, 0, BUTTON_SIZE, BUTTON_SIZE);
 210         int x = w - BUTTON_SIZE;
 211 
 212         if(frame.isMaximizable()) {
 213             maximizeButton.setBounds(x, 0, BUTTON_SIZE, BUTTON_SIZE);
 214             x -= BUTTON_SIZE;
 215         } else if(maximizeButton.getParent() != null) {
 216             maximizeButton.getParent().remove(maximizeButton);
 217         }
 218 
 219         if(frame.isIconifiable()) {
 220             minimizeButton.setBounds(x, 0, BUTTON_SIZE, BUTTON_SIZE);
 221             x -= BUTTON_SIZE;
 222         } else if(minimizeButton.getParent() != null) {
 223             minimizeButton.getParent().remove(minimizeButton);
 224         }
 225 
 226         title.setBounds(BUTTON_SIZE, 0, x, BUTTON_SIZE);
 227     }
 228 
 229     protected void showSystemMenu(){
 230       systemMenu.show(systemButton, 0, BUTTON_SIZE);
 231     }
 232 
 233     protected void hideSystemMenu(){
 234       systemMenu.setVisible(false);
 235     }
 236 
 237     static Dimension buttonDimension = new Dimension(BUTTON_SIZE, BUTTON_SIZE);
 238 
 239     @SuppressWarnings("serial") // Superclass is not serializable across versions
 240     private abstract class FrameButton extends JButton {
 241 
 242         FrameButton() {
 243             super();
 244             setFocusPainted(false);
 245             setBorderPainted(false);
 246         }
 247 
 248         @SuppressWarnings("deprecation")
 249         public boolean isFocusTraversable() {
 250             return false;
 251         }
 252 
 253         public void requestFocus() {
 254             // ignore request.
 255         }
 256 
 257         public Dimension getMinimumSize() {
 258             return buttonDimension;
 259         }
 260 
 261         public Dimension getPreferredSize() {
 262             return buttonDimension;
 263         }
 264 
 265         public void paintComponent(Graphics g) {
 266             Dimension d = getSize();
 267             int maxX = d.width - 1;
 268             int maxY = d.height - 1;
 269 
 270             // draw background
 271             g.setColor(color);
 272             g.fillRect(1, 1, d.width, d.height);
 273 
 274             // draw border
 275             boolean pressed = getModel().isPressed();
 276             g.setColor(pressed ? shadow : highlight);
 277             g.drawLine(0, 0, maxX, 0);
 278             g.drawLine(0, 0, 0, maxY);
 279             g.setColor(pressed ? highlight : shadow);
 280             g.drawLine(1, maxY, maxX, maxY);
 281             g.drawLine(maxX, 1, maxX, maxY);
 282         }
 283     }
 284 
 285     @SuppressWarnings("serial") // Superclass is not serializable across versions
 286     private class MinimizeButton extends FrameButton {
 287         public void paintComponent(Graphics g) {
 288             super.paintComponent(g);
 289             g.setColor(highlight);
 290             g.drawLine(7, 8, 7, 11);
 291             g.drawLine(7, 8, 10, 8);
 292             g.setColor(shadow);
 293             g.drawLine(8, 11, 10, 11);
 294             g.drawLine(11, 9, 11, 11);
 295         }
 296     }
 297 
 298    @SuppressWarnings("serial") // Superclass is not serializable across versions
 299    private class MaximizeButton extends FrameButton {
 300         public void paintComponent(Graphics g) {
 301             super.paintComponent(g);
 302             int max = BUTTON_SIZE - 5;
 303             boolean isMaxed = frame.isMaximum();
 304             g.setColor(isMaxed ? shadow : highlight);
 305             g.drawLine(4, 4, 4, max);
 306             g.drawLine(4, 4, max, 4);
 307             g.setColor(isMaxed ? highlight : shadow);
 308             g.drawLine(5, max, max, max);
 309             g.drawLine(max, 5, max, max);
 310         }
 311     }
 312 
 313     @SuppressWarnings("serial") // Superclass is not serializable across versions
 314     private class SystemButton extends FrameButton {
 315         public boolean isFocusTraversable() { return false; }
 316         public void requestFocus() {}
 317 
 318         public void paintComponent(Graphics g) {
 319             super.paintComponent(g);
 320             g.setColor(highlight);
 321             g.drawLine(4, 8, 4, 11);
 322             g.drawLine(4, 8, BUTTON_SIZE - 5, 8);
 323             g.setColor(shadow);
 324             g.drawLine(5, 11, BUTTON_SIZE - 5, 11);
 325             g.drawLine(BUTTON_SIZE - 5, 9, BUTTON_SIZE - 5, 11);
 326         }
 327     }
 328 
 329     @SuppressWarnings("serial") // Superclass is not serializable across versions
 330     private class Title extends FrameButton {
 331         Title(String title) {
 332             super();
 333             setText(title);
 334             setHorizontalAlignment(SwingConstants.CENTER);
 335             setBorder(BorderFactory.createBevelBorder(
 336                 BevelBorder.RAISED,
 337                 UIManager.getColor("activeCaptionBorder"),
 338                 UIManager.getColor("inactiveCaptionBorder")));
 339 
 340             // Forward mouse events to titlebar for moves.
 341             addMouseMotionListener(new MouseMotionListener() {
 342                 public void mouseDragged(MouseEvent e) {
 343                     forwardEventToParent(e);
 344                 }
 345                 public void mouseMoved(MouseEvent e) {
 346                     forwardEventToParent(e);
 347                 }
 348             });
 349             addMouseListener(new MouseListener() {
 350                 public void mouseClicked(MouseEvent e) {
 351                     forwardEventToParent(e);
 352                 }
 353                 public void mousePressed(MouseEvent e) {
 354                     forwardEventToParent(e);
 355                 }
 356                 public void mouseReleased(MouseEvent e) {
 357                     forwardEventToParent(e);
 358                 }
 359                 public void mouseEntered(MouseEvent e) {
 360                     forwardEventToParent(e);
 361                 }
 362                 public void mouseExited(MouseEvent e) {
 363                     forwardEventToParent(e);
 364                 }
 365             });
 366         }
 367         @SuppressWarnings("deprecation")
 368         void forwardEventToParent(MouseEvent e) {
 369             MouseEvent newEvent = new MouseEvent(
 370                 getParent(), e.getID(), e.getWhen(), e.getModifiers(),
 371                 e.getX(), e.getY(),  e.getXOnScreen(),
 372                 e.getYOnScreen(), e.getClickCount(),
 373                 e.isPopupTrigger(),  MouseEvent.NOBUTTON);
 374             MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
 375             meAccessor.setCausedByTouchEvent(newEvent,
 376                 meAccessor.isCausedByTouchEvent(e));
 377             getParent().dispatchEvent(newEvent);
 378         }
 379 
 380         public void paintComponent(Graphics g) {
 381             super.paintComponent(g);
 382             if (frame.isSelected()) {
 383                 g.setColor(UIManager.getColor("activeCaptionText"));
 384             } else {
 385                 g.setColor(UIManager.getColor("inactiveCaptionText"));
 386             }
 387             Dimension d = getSize();
 388             String frameTitle = frame.getTitle();
 389             if (frameTitle != null) {
 390                 MotifGraphicsUtils.drawStringInRect(frame, g, frameTitle,
 391                                                     0, 0, d.width, d.height,
 392                                                     SwingConstants.CENTER);
 393             }
 394         }
 395     }
 396 }