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