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