OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [plaf/] [metal/] [MetalRootPaneUI.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* MetalRootPaneUI.java
2
   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.swing.plaf.metal;
40
 
41
import java.awt.Color;
42
import java.awt.Component;
43
import java.awt.Container;
44
import java.awt.Dimension;
45
import java.awt.Frame;
46
import java.awt.Graphics;
47
import java.awt.Insets;
48
import java.awt.LayoutManager;
49
import java.awt.LayoutManager2;
50
import java.awt.Point;
51
import java.awt.Rectangle;
52
import java.awt.Window;
53
import java.awt.event.ActionEvent;
54
import java.awt.event.MouseEvent;
55
import java.beans.PropertyChangeEvent;
56
 
57
import javax.swing.AbstractAction;
58
import javax.swing.Action;
59
import javax.swing.Icon;
60
import javax.swing.JButton;
61
import javax.swing.JComponent;
62
import javax.swing.JDialog;
63
import javax.swing.JFrame;
64
import javax.swing.JLabel;
65
import javax.swing.JLayeredPane;
66
import javax.swing.JMenu;
67
import javax.swing.JMenuBar;
68
import javax.swing.JRootPane;
69
import javax.swing.SwingConstants;
70
import javax.swing.SwingUtilities;
71
import javax.swing.UIManager;
72
import javax.swing.border.AbstractBorder;
73
import javax.swing.event.MouseInputAdapter;
74
import javax.swing.plaf.ComponentUI;
75
import javax.swing.plaf.basic.BasicRootPaneUI;
76
 
77
/**
78
 * A UI delegate for the {@link JRootPane} component. This implementation
79
 * supports the JRootPane <code>windowDecorationStyle</code> property.
80
 *
81
 * @author Roman Kennke (kennke@aicas.com)
82
 *
83
 * @since 1.4
84
 */
85
public class MetalRootPaneUI
86
  extends BasicRootPaneUI
87
{
88
 
89
  /**
90
   * The border that is used on JRootPane when the windowDecorationStyle
91
   * property of the JRootPane is set to a different value than NONE.
92
   *
93
   * @author Roman Kennke (kennke@aicas.com)
94
   */
95
  private static class MetalFrameBorder
96
    extends AbstractBorder
97
  {
98
    /**
99
     * Returns the border insets.
100
     *
101
     * @param c the component
102
     * @param newInsets the insets to be filled with the return value, may be
103
     *        <code>null</code> in which case a new object is created
104
     *
105
     * @return the border insets
106
     */
107
    public Insets getBorderInsets(Component c, Insets newInsets)
108
    {
109
      if (newInsets == null)
110
        newInsets = new Insets(5, 5, 5, 5);
111
      else
112
        {
113
          newInsets.top = 5;
114
          newInsets.left = 5;
115
          newInsets.bottom = 5;
116
          newInsets.right = 5;
117
        }
118
      return newInsets;
119
    }
120
 
121
    /**
122
     * Returns the border insets.
123
     *
124
     * @param c the component
125
     *
126
     * @return the border insets
127
     */
128
    public Insets getBorderInsets(Component c)
129
    {
130
      return getBorderInsets(c, null);
131
    }
132
 
133
    /**
134
     * Paints the border for the specified component.
135
     *
136
     * @param c  the component
137
     * @param g  the graphics device
138
     * @param x  the x-coordinate
139
     * @param y  the y-coordinate
140
     * @param w  the width
141
     * @param h  the height
142
     */
143
    public void paintBorder(Component c, Graphics g, int x, int y, int w,
144
                            int h)
145
    {
146
      JRootPane f = (JRootPane) c;
147
      Window frame = SwingUtilities.getWindowAncestor(f);
148
      if (frame.isActive())
149
        g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
150
      else
151
        g.setColor(MetalLookAndFeel.getControlDarkShadow());
152
 
153
      // Fill the border background.
154
      g.fillRect(x, y, w, 5);
155
      g.fillRect(x, y, 5, h);
156
      g.fillRect(x + w - 5, y, 5, h);
157
      g.fillRect(x, y + h - 5, w, 5);
158
 
159
      // Draw a dot in each corner.
160
      g.setColor(MetalLookAndFeel.getControl());
161
      g.fillRect(x, y, 1, 1);
162
      g.fillRect(x + w - 1, y, 1, 1);
163
      g.fillRect(x + w - 1, y + h - 1, 1, 1);
164
      g.fillRect(x, y + h - 1, 1, 1);
165
 
166
      // Draw the lines.
167
      g.setColor(MetalLookAndFeel.getBlack());
168
      g.drawLine(x + 14, y + 2, x + w - 15, y + 2);
169
      g.drawLine(x + 14, y + h - 3, x + w - 15, y + h - 3);
170
      g.drawLine(x + 2, y + 14, x + 2, y + h - 15);
171
      g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15);
172
 
173
      // Draw the line highlights.
174
      if (frame.isActive())
175
        g.setColor(MetalLookAndFeel.getPrimaryControlShadow());
176
      else
177
        g.setColor(MetalLookAndFeel.getControlShadow());
178
      g.drawLine(x + 15, y + 3, x + w - 14, y + 3);
179
      g.drawLine(x + 15, y + h - 2, x + w - 14, y + h - 2);
180
      g.drawLine(x + 3, y + 15, x + 3, y + h - 14);
181
      g.drawLine(x + w - 2, y + 15, x + w - 2, y + h - 14);
182
    }
183
  }
184
 
185
  /**
186
   * The component that renders the title bar for frames. This duplicates
187
   * most of {@link MetalInternalFrameTitlePane}. It is not reasonably possible
188
   * to reuse that class because that is bound to the JInternalFrame and we
189
   * need to handle JFrames/JRootPanes here.
190
   *
191
   * @author Roman Kennke (kennke@aicas.com)
192
   */
193
  private static class MetalTitlePane extends JComponent
194
  {
195
 
196
    /**
197
     * Handles dragging of the title pane and moves the window accordingly.
198
     */
199
    private class MouseHandler
200
      extends MouseInputAdapter
201
    {
202
      /**
203
       * The point where the dragging started.
204
       */
205
      Point lastDragLocation;
206
 
207
      /**
208
       * Receives notification when the mouse gets pressed on the title pane.
209
       * This updates the lastDragLocation.
210
       *
211
       * @param ev the mouse event
212
       */
213
      public void mousePressed(MouseEvent ev)
214
      {
215
        lastDragLocation = ev.getPoint();
216
      }
217
 
218
      /**
219
       * Receives notification when the mouse is dragged on the title pane.
220
       * This will move the nearest window accordingly.
221
       *
222
       * @param ev the mouse event
223
       */
224
      public void mouseDragged(MouseEvent ev)
225
      {
226
        Point dragLocation = ev.getPoint();
227
        int deltaX = dragLocation.x - lastDragLocation.x;
228
        int deltaY = dragLocation.y - lastDragLocation.y;
229
        Window window = SwingUtilities.getWindowAncestor(rootPane);
230
        Point loc = window.getLocation();
231
        window.setLocation(loc.x + deltaX, loc.y + deltaY);
232
        // Note that we do not update the lastDragLocation. This is because
233
        // we move the underlying window while dragging the component, which
234
        // results in having the same lastDragLocation under the mouse while
235
        // dragging.
236
      }
237
    }
238
 
239
    /**
240
     * The Action responsible for closing the JInternalFrame.
241
     */
242
    private class CloseAction extends AbstractAction
243
    {
244
      /**
245
       * Creates a new action.
246
       */
247
      public CloseAction()
248
      {
249
        super("Close");
250
      }
251
 
252
      /**
253
       * This method is called when something closes the frame.
254
       *
255
       * @param e the ActionEvent
256
       */
257
      public void actionPerformed(ActionEvent e)
258
      {
259
        Window frame = SwingUtilities.getWindowAncestor(rootPane);
260
        if (frame instanceof JFrame)
261
          {
262
            JFrame jframe = (JFrame) frame;
263
            switch (jframe.getDefaultCloseOperation())
264
            {
265
              case JFrame.EXIT_ON_CLOSE:
266
                jframe.setVisible(false);
267
                jframe.dispose();
268
                System.exit(0);
269
                break;
270
              case JFrame.DISPOSE_ON_CLOSE:
271
                jframe.setVisible(false);
272
                jframe.dispose();
273
                break;
274
              case JFrame.HIDE_ON_CLOSE:
275
                jframe.setVisible(false);
276
                break;
277
              case JFrame.DO_NOTHING_ON_CLOSE:
278
              default:
279
                  break;
280
            }
281
          }
282
        else if (frame instanceof JDialog)
283
          {
284
            JDialog jdialog = (JDialog) frame;
285
            switch (jdialog.getDefaultCloseOperation())
286
            {
287
              case JFrame.DISPOSE_ON_CLOSE:
288
                jdialog.setVisible(false);
289
                jdialog.dispose();
290
                break;
291
              case JFrame.HIDE_ON_CLOSE:
292
                jdialog.setVisible(false);
293
                break;
294
              case JFrame.DO_NOTHING_ON_CLOSE:
295
              default:
296
                  break;
297
            }
298
          }
299
      }
300
    }
301
 
302
    /**
303
     * This action is performed when the iconify button is pressed.
304
     */
305
    private class IconifyAction
306
      extends AbstractAction
307
    {
308
 
309
      public void actionPerformed(ActionEvent event)
310
      {
311
        Window w = SwingUtilities.getWindowAncestor(rootPane);
312
        if (w instanceof Frame)
313
          {
314
            Frame f = (Frame) w;
315
            int state = f.getExtendedState();
316
            f.setExtendedState(Frame.ICONIFIED);
317
          }
318
      }
319
 
320
    }
321
 
322
    /**
323
     * This action is performed when the maximize button is pressed.
324
     */
325
    private class MaximizeAction
326
      extends AbstractAction
327
    {
328
 
329
      public void actionPerformed(ActionEvent event)
330
      {
331
        Window w = SwingUtilities.getWindowAncestor(rootPane);
332
        if (w instanceof Frame)
333
          {
334
            Frame f = (Frame) w;
335
            int state = f.getExtendedState();
336
            f.setExtendedState(Frame.MAXIMIZED_BOTH);
337
          }
338
      }
339
    }
340
 
341
    /**
342
     * This helper class is used to create the minimize, maximize and close
343
     * buttons in the top right corner of the Title Pane. These buttons are
344
     * special since they cannot be given focus and have no border.
345
     */
346
    private class PaneButton extends JButton
347
    {
348
      /**
349
       * Creates a new PaneButton object with the given Action.
350
       *
351
       * @param a The Action that the button uses.
352
       */
353
      public PaneButton(Action a)
354
      {
355
        super(a);
356
        setMargin(new Insets(0, 0, 0, 0));
357
      }
358
 
359
      /**
360
       * This method returns true if the Component can be focused.
361
       *
362
       * @return false.
363
       */
364
      public boolean isFocusable()
365
      {
366
        // These buttons cannot be given focus.
367
        return false;
368
      }
369
 
370
    }
371
 
372
    /**
373
     * The layout for the JRootPane when the <code>windowDecorationStyle</code>
374
     * property is set. In addition to the usual JRootPane.RootLayout behaviour
375
     * this lays out the titlePane.
376
     *
377
     * @author Roman Kennke (kennke@aicas.com)
378
     */
379
    private class MetalTitlePaneLayout implements LayoutManager
380
    {
381
      /**
382
       * Creates a new <code>TitlePaneLayout</code> object.
383
       */
384
      public MetalTitlePaneLayout()
385
      {
386
        // Do nothing.
387
      }
388
 
389
      /**
390
       * Adds a Component to the Container.
391
       *
392
       * @param name The name to reference the added Component by.
393
       * @param c The Component to add.
394
       */
395
      public void addLayoutComponent(String name, Component c)
396
      {
397
        // Do nothing.
398
      }
399
 
400
      /**
401
       * This method is called to lay out the children of the Title Pane.
402
       *
403
       * @param c The Container to lay out.
404
       */
405
      public void layoutContainer(Container c)
406
      {
407
 
408
        Dimension size = c.getSize();
409
        Insets insets = c.getInsets();
410
        int width = size.width - insets.left - insets.right;
411
        int height = size.height - insets.top - insets.bottom;
412
 
413
        int loc = width - insets.right - 1;
414
        int top = insets.top + 2;
415
        int buttonHeight = height - 4;
416
        if (closeButton.isVisible())
417
          {
418
            int buttonWidth = closeIcon.getIconWidth();
419
            loc -= buttonWidth + 2;
420
            closeButton.setBounds(loc, top, buttonWidth, buttonHeight);
421
            loc -= 6;
422
          }
423
 
424
        if (maxButton.isVisible())
425
          {
426
            int buttonWidth = maxIcon.getIconWidth();
427
            loc -= buttonWidth + 4;
428
            maxButton.setBounds(loc, top, buttonWidth, buttonHeight);
429
          }
430
 
431
        if (iconButton.isVisible())
432
          {
433
            int buttonWidth = minIcon.getIconWidth();
434
            loc -= buttonWidth + 4;
435
            iconButton.setBounds(loc, top, buttonWidth, buttonHeight);
436
            loc -= 2;
437
          }
438
 
439
        Dimension titlePreferredSize = title.getPreferredSize();
440
        title.setBounds(insets.left + 5, insets.top,
441
                Math.min(titlePreferredSize.width, loc - insets.left - 10),
442
                height);
443
 
444
      }
445
 
446
      /**
447
       * This method returns the minimum size of the given Container given the
448
       * children that it has.
449
       *
450
       * @param c The Container to get a minimum size for.
451
       *
452
       * @return The minimum size of the Container.
453
       */
454
      public Dimension minimumLayoutSize(Container c)
455
      {
456
        return preferredLayoutSize(c);
457
      }
458
 
459
      /**
460
       * Returns the preferred size of the given Container taking
461
       * into account the children that it has.
462
       *
463
       * @param c The Container to lay out.
464
       *
465
       * @return The preferred size of the Container.
466
       */
467
      public Dimension preferredLayoutSize(Container c)
468
      {
469
        return new Dimension(22, 22);
470
      }
471
 
472
      /**
473
       * Removes a Component from the Container.
474
       *
475
       * @param c The Component to remove.
476
       */
477
      public void removeLayoutComponent(Component c)
478
      {
479
        // Nothing to do here.
480
      }
481
    }
482
 
483
    JRootPane rootPane;
484
 
485
    /** The button that closes the JInternalFrame. */
486
    JButton closeButton;
487
 
488
    /** The button that iconifies the JInternalFrame. */
489
    JButton iconButton;
490
 
491
    /** The button that maximizes the JInternalFrame. */
492
    JButton maxButton;
493
 
494
    Icon minIcon;
495
 
496
    /** The icon displayed in the maximize button. */
497
    Icon maxIcon;
498
 
499
    /** The icon displayed in the iconify button. */
500
    private Icon iconIcon;
501
 
502
    /** The icon displayed in the close button. */
503
    Icon closeIcon;
504
 
505
    /**
506
     * The background color of the TitlePane when the JInternalFrame is not
507
     * selected.
508
     */
509
    private Color notSelectedTitleColor;
510
 
511
    /**
512
     * The background color of the TitlePane when the JInternalFrame is
513
     * selected.
514
     */
515
    private Color selectedTitleColor;
516
 
517
    /**
518
     * The label used to display the title. This label is not added to the
519
     * TitlePane.
520
     */
521
    JLabel title;
522
 
523
    /** The action associated with closing the JInternalFrame. */
524
    private Action closeAction;
525
 
526
    /** The action associated with iconifying the JInternalFrame. */
527
    private Action iconifyAction;
528
 
529
    /** The action associated with maximizing the JInternalFrame. */
530
    private Action maximizeAction;
531
 
532
    /** The JMenuBar that is located at the top left of the Title Pane. */
533
    private JMenuBar menuBar;
534
 
535
    /** The JMenu inside the menuBar. */
536
    protected JMenu windowMenu;
537
 
538
    MetalTitlePane(JRootPane rp)
539
    {
540
      rootPane = rp;
541
      setLayout(createLayout());
542
      title = new JLabel();
543
      title.setHorizontalAlignment(SwingConstants.LEFT);
544
      title.setHorizontalTextPosition(SwingConstants.LEFT);
545
      title.setOpaque(false);
546
      installTitlePane();
547
    }
548
 
549
    protected LayoutManager createLayout()
550
    {
551
      return new MetalTitlePaneLayout();
552
    }
553
 
554
    /**
555
     * This method installs the TitlePane onto the JInternalFrameTitlePane. It
556
     * also creates any children components that need to be created and adds
557
     * listeners to the appropriate components.
558
     */
559
    protected void installTitlePane()
560
    {
561
      installDefaults();
562
      installListeners();
563
      createActions();
564
      assembleSystemMenu();
565
      createButtons();
566
      setButtonIcons();
567
      addSubComponents();
568
      enableActions();
569
    }
570
 
571
    private void enableActions()
572
    {
573
      // TODO: Implement this.
574
    }
575
 
576
    private void addSubComponents()
577
    {
578
      add(menuBar);
579
      add(closeButton);
580
      add(iconButton);
581
      add(maxButton);
582
    }
583
 
584
    private void installListeners()
585
    {
586
      MouseInputAdapter mouseHandler = new MouseHandler();
587
      addMouseListener(mouseHandler);
588
      addMouseMotionListener(mouseHandler);
589
    }
590
 
591
    private void createActions()
592
    {
593
      closeAction = new CloseAction();
594
      iconifyAction = new IconifyAction();
595
      maximizeAction = new MaximizeAction();
596
    }
597
 
598
    private void assembleSystemMenu()
599
    {
600
      menuBar = createSystemMenuBar();
601
      windowMenu = createSystemMenu();
602
      menuBar.add(windowMenu);
603
      addSystemMenuItems(windowMenu);
604
      enableActions();
605
    }
606
 
607
    protected JMenuBar createSystemMenuBar()
608
    {
609
      if (menuBar == null)
610
        menuBar = new JMenuBar();
611
      menuBar.removeAll();
612
      return menuBar;
613
    }
614
 
615
    protected JMenu createSystemMenu()
616
    {
617
      if (windowMenu == null)
618
        windowMenu = new JMenu();
619
      windowMenu.removeAll();
620
      return windowMenu;
621
    }
622
 
623
    private void addSystemMenuItems(JMenu menu)
624
    {
625
      // TODO: Implement this.
626
    }
627
 
628
    protected void createButtons()
629
    {
630
      closeButton = new PaneButton(closeAction);
631
      closeButton.setText(null);
632
      iconButton = new PaneButton(iconifyAction);
633
      iconButton.setText(null);
634
      maxButton = new PaneButton(maximizeAction);
635
      maxButton.setText(null);
636
      closeButton.setBorderPainted(false);
637
      closeButton.setContentAreaFilled(false);
638
      iconButton.setBorderPainted(false);
639
      iconButton.setContentAreaFilled(false);
640
      maxButton.setBorderPainted(false);
641
      maxButton.setContentAreaFilled(false);
642
    }
643
 
644
    protected void setButtonIcons()
645
    {
646
      if (closeIcon != null && closeButton != null)
647
        closeButton.setIcon(closeIcon);
648
      if (iconIcon != null && iconButton != null)
649
        iconButton.setIcon(iconIcon);
650
      if (maxIcon != null && maxButton != null)
651
        maxButton.setIcon(maxIcon);
652
    }
653
 
654
    /**
655
     * Paints a representation of the current state of the internal frame.
656
     *
657
     * @param g  the graphics device.
658
     */
659
    public void paintComponent(Graphics g)
660
    {
661
      Window frame = SwingUtilities.getWindowAncestor(rootPane);
662
      Color savedColor = g.getColor();
663
      paintTitleBackground(g);
664
      paintChildren(g);
665
      Dimension d = getSize();
666
      if (frame.isActive())
667
        g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow());
668
      else
669
        g.setColor(MetalLookAndFeel.getControlDarkShadow());
670
 
671
      // put a dot in each of the top corners
672
      g.drawLine(0, 0, 0, 0);
673
      g.drawLine(d.width - 1, 0, d.width - 1, 0);
674
 
675
      g.drawLine(0, d.height - 1, d.width - 1, d.height - 1);
676
 
677
      // draw the metal pattern
678
      if (UIManager.get("InternalFrame.activeTitleGradient") != null
679
          && frame.isActive())
680
        {
681
          MetalUtils.paintGradient(g, 0, 0, getWidth(), getHeight(),
682
                                   SwingConstants.VERTICAL,
683
          "InternalFrame.activeTitleGradient");
684
        }
685
 
686
      Rectangle b = title.getBounds();
687
      int startX = b.x + b.width + 5;
688
      int endX = startX;
689
      if (iconButton.isVisible())
690
        endX = Math.max(iconButton.getX(), endX);
691
      else if (maxButton.isVisible())
692
        endX = Math.max(maxButton.getX(), endX);
693
      else if (closeButton.isVisible())
694
        endX = Math.max(closeButton.getX(), endX);
695
      endX -= 7;
696
      if (endX > startX)
697
        MetalUtils.fillMetalPattern(this, g, startX, 3, endX - startX, getHeight() - 6, Color.white, Color.gray);
698
      g.setColor(savedColor);
699
    }
700
 
701
    /**
702
     * This method paints the TitlePane's background.
703
     *
704
     * @param g The Graphics object to paint with.
705
     */
706
    protected void paintTitleBackground(Graphics g)
707
    {
708
      Window frame = SwingUtilities.getWindowAncestor(rootPane);
709
 
710
      if (!isOpaque())
711
        return;
712
 
713
      Color saved = g.getColor();
714
      Dimension dims = getSize();
715
 
716
      Color bg = getBackground();
717
      if (frame.isActive())
718
        bg = selectedTitleColor;
719
      else
720
        bg = notSelectedTitleColor;
721
      g.setColor(bg);
722
      g.fillRect(0, 0, dims.width, dims.height);
723
      g.setColor(saved);
724
    }
725
 
726
    /**
727
     * This method installs the defaults determined by the look and feel.
728
     */
729
    private void installDefaults()
730
    {
731
      title.setFont(UIManager.getFont("InternalFrame.titleFont"));
732
      selectedTitleColor = UIManager.getColor("InternalFrame.activeTitleBackground");
733
      notSelectedTitleColor = UIManager.getColor("InternalFrame.inactiveTitleBackground");
734
      closeIcon = UIManager.getIcon("InternalFrame.closeIcon");
735
      iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon");
736
      maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon");
737
      minIcon = MetalIconFactory.getInternalFrameAltMaximizeIcon(16);
738
      Frame frame = (Frame) SwingUtilities.getWindowAncestor(rootPane);
739
      title = new JLabel(frame.getTitle(),
740
              MetalIconFactory.getInternalFrameDefaultMenuIcon(),
741
              SwingConstants.LEFT);
742
    }
743
  }
744
 
745
  private static class MetalRootLayout
746
    implements LayoutManager2
747
  {
748
 
749
    /**
750
     * The cached layout info for the glass pane.
751
     */
752
    private Rectangle glassPaneBounds;
753
 
754
    /**
755
     * The cached layout info for the layered pane.
756
     */
757
    private Rectangle layeredPaneBounds;
758
 
759
    /**
760
     * The cached layout info for the content pane.
761
     */
762
    private Rectangle contentPaneBounds;
763
 
764
    /**
765
     * The cached layout info for the menu bar.
766
     */
767
    private Rectangle menuBarBounds;
768
 
769
    /**
770
     * The cached layout info for the title pane.
771
     */
772
    private Rectangle titlePaneBounds;
773
 
774
    /**
775
     * The cached preferred size.
776
     */
777
    private Dimension prefSize;
778
 
779
    /**
780
     * The title pane for l&f decorated frames.
781
     */
782
    private MetalTitlePane titlePane;
783
 
784
    /**
785
     * Creates a new MetalRootLayout.
786
     *
787
     * @param tp the title pane
788
     */
789
    MetalRootLayout(MetalTitlePane tp)
790
    {
791
      titlePane = tp;
792
    }
793
 
794
    public void addLayoutComponent(Component component, Object constraints)
795
    {
796
      // Nothing to do here.
797
    }
798
 
799
    public Dimension maximumLayoutSize(Container target)
800
    {
801
      return preferredLayoutSize(target);
802
    }
803
 
804
    public float getLayoutAlignmentX(Container target)
805
    {
806
      return 0.0F;
807
    }
808
 
809
    public float getLayoutAlignmentY(Container target)
810
    {
811
      return 0.0F;
812
    }
813
 
814
    public void invalidateLayout(Container target)
815
    {
816
      synchronized (this)
817
      {
818
        glassPaneBounds = null;
819
        layeredPaneBounds = null;
820
        contentPaneBounds = null;
821
        menuBarBounds = null;
822
        titlePaneBounds = null;
823
        prefSize = null;
824
      }
825
    }
826
 
827
    public void addLayoutComponent(String name, Component component)
828
    {
829
      // Nothing to do here.
830
    }
831
 
832
    public void removeLayoutComponent(Component component)
833
    {
834
      // TODO Auto-generated method stub
835
 
836
    }
837
 
838
    public Dimension preferredLayoutSize(Container parent)
839
    {
840
      JRootPane rp = (JRootPane) parent;
841
      JLayeredPane layeredPane = rp.getLayeredPane();
842
      Component contentPane = rp.getContentPane();
843
      Component menuBar = rp.getJMenuBar();
844
 
845
      // We must synchronize here, otherwise we cannot guarantee that the
846
      // prefSize is still non-null when returning.
847
      synchronized (this)
848
        {
849
          if (prefSize == null)
850
            {
851
              Insets i = parent.getInsets();
852
              prefSize = new Dimension(i.left + i.right, i.top + i.bottom);
853
              Dimension contentPrefSize = contentPane.getPreferredSize();
854
              prefSize.width += contentPrefSize.width;
855
              prefSize.height += contentPrefSize.height
856
                                 + titlePane.getPreferredSize().height;
857
              if (menuBar != null)
858
                {
859
                  Dimension menuBarSize = menuBar.getPreferredSize();
860
                  if (menuBarSize.width > contentPrefSize.width)
861
                    prefSize.width += menuBarSize.width - contentPrefSize.width;
862
                  prefSize.height += menuBarSize.height;
863
                }
864
            }
865
          // Return a copy here so the cached value won't get trashed by some
866
          // other component.
867
          return new Dimension(prefSize);
868
      }
869
    }
870
 
871
    public Dimension minimumLayoutSize(Container parent)
872
    {
873
      return preferredLayoutSize(parent);
874
    }
875
 
876
    public void layoutContainer(Container parent)
877
    {
878
      JRootPane rp = (JRootPane) parent;
879
      JLayeredPane layeredPane = rp.getLayeredPane();
880
      Component contentPane = rp.getContentPane();
881
      Component menuBar = rp.getJMenuBar();
882
      Component glassPane = rp.getGlassPane();
883
 
884
      if (glassPaneBounds == null || layeredPaneBounds == null
885
          || contentPaneBounds == null || menuBarBounds == null)
886
        {
887
          Insets i = rp.getInsets();
888
          int containerWidth = parent.getBounds().width - i.left - i.right;
889
          int containerHeight = parent.getBounds().height - i.top - i.bottom;
890
 
891
          // 1. The glassPane fills entire viewable region (bounds - insets).
892
          // 2. The layeredPane filles entire viewable region.
893
          // 3. The titlePane is placed at the upper edge of the layeredPane.
894
          // 4. The menuBar is positioned at the upper edge of layeredPane.
895
          // 5. The contentPane fills viewable region minus menuBar minus
896
          //    titlePane, if present.
897
 
898
          // +-------------------------------+
899
          // |  JLayeredPane                 |
900
          // |  +--------------------------+ |
901
          // |  | titlePane                + |
902
          // |  +--------------------------+ |
903
          // |  +--------------------------+ |
904
          // |  | menuBar                  | |
905
          // |  +--------------------------+ |
906
          // |  +--------------------------+ |
907
          // |  |contentPane               | |
908
          // |  |                          | |
909
          // |  |                          | |
910
          // |  |                          | |
911
          // |  +--------------------------+ |
912
          // +-------------------------------+
913
 
914
          // Setup titlePaneBounds.
915
          if (titlePaneBounds == null)
916
            titlePaneBounds = new Rectangle();
917
          titlePaneBounds.width = containerWidth;
918
          titlePaneBounds.height = titlePane.getPreferredSize().height;
919
 
920
          // Setup menuBarBounds.
921
          if (menuBarBounds == null)
922
            menuBarBounds = new Rectangle();
923
          menuBarBounds.setBounds(0,
924
                                  titlePaneBounds.y + titlePaneBounds.height,
925
                                  containerWidth, 0);
926
          if (menuBar != null)
927
            {
928
              Dimension menuBarSize = menuBar.getPreferredSize();
929
              if (menuBarSize.height > containerHeight)
930
                menuBarBounds.height = containerHeight;
931
              else
932
                menuBarBounds.height = menuBarSize.height;
933
            }
934
 
935
          // Setup contentPaneBounds.
936
          if (contentPaneBounds == null)
937
            contentPaneBounds = new Rectangle();
938
          contentPaneBounds.setBounds(0,
939
                                      menuBarBounds.y + menuBarBounds.height,
940
                                      containerWidth,
941
                                      containerHeight - menuBarBounds.y
942
                                      - menuBarBounds.height);
943
          glassPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight);
944
          layeredPaneBounds = new Rectangle(i.left, i.top, containerWidth, containerHeight);
945
        }
946
 
947
      // Layout components.
948
      glassPane.setBounds(glassPaneBounds);
949
      layeredPane.setBounds(layeredPaneBounds);
950
      if (menuBar != null)
951
        menuBar.setBounds(menuBarBounds);
952
      contentPane.setBounds(contentPaneBounds);
953
      titlePane.setBounds(titlePaneBounds);
954
    }
955
 
956
  }
957
 
958
  /**
959
   * The shared UI instance for MetalRootPaneUIs.
960
   */
961
  private static MetalRootPaneUI instance;
962
 
963
  /**
964
   * Constructs a shared instance of <code>MetalRootPaneUI</code>.
965
   */
966
  public MetalRootPaneUI()
967
  {
968
    super();
969
  }
970
 
971
  /**
972
   * Returns a shared instance of <code>MetalRootPaneUI</code>.
973
   *
974
   * @param component the component for which we return an UI instance
975
   *
976
   * @return A shared instance of <code>MetalRootPaneUI</code>.
977
   */
978
  public static ComponentUI createUI(JComponent component)
979
  {
980
    if (instance == null)
981
      instance = new MetalRootPaneUI();
982
    return instance;
983
  }
984
 
985
  /**
986
   * Installs this UI to the root pane. If the
987
   * <code>windowDecorationsStyle</code> property is set on the root pane,
988
   * the Metal window decorations are installed on the root pane.
989
   *
990
   * @param c
991
   */
992
  public void installUI(JComponent c)
993
  {
994
    super.installUI(c);
995
    JRootPane rp = (JRootPane) c;
996
    if (rp.getWindowDecorationStyle() != JRootPane.NONE)
997
      installWindowDecorations(rp);
998
  }
999
 
1000
  /**
1001
   * Uninstalls the UI from the root pane. This performs the superclass
1002
   * behaviour and uninstalls the window decorations that have possibly been
1003
   * installed by {@link #installUI}.
1004
   *
1005
   * @param c the root pane
1006
   */
1007
  public void uninstallUI(JComponent c)
1008
  {
1009
    JRootPane rp = (JRootPane) c;
1010
    if (rp.getWindowDecorationStyle() != JRootPane.NONE)
1011
      uninstallWindowDecorations(rp);
1012
    super.uninstallUI(c);
1013
  }
1014
 
1015
  /**
1016
   * Receives notification if any of the JRootPane's property changes. In
1017
   * particular this catches changes to the <code>windowDecorationStyle</code>
1018
   * property and installs the window decorations accordingly.
1019
   *
1020
   * @param ev the property change event
1021
   */
1022
  public void propertyChange(PropertyChangeEvent ev)
1023
  {
1024
    super.propertyChange(ev);
1025
    String propertyName = ev.getPropertyName();
1026
    if (propertyName.equals("windowDecorationStyle"))
1027
      {
1028
        JRootPane rp = (JRootPane) ev.getSource();
1029
        if (rp.getWindowDecorationStyle() != JRootPane.NONE)
1030
          installWindowDecorations(rp);
1031
        else
1032
          uninstallWindowDecorations(rp);
1033
      }
1034
  }
1035
 
1036
  /**
1037
   * Installs the window decorations to the root pane. This sets up a border,
1038
   * a title pane and a layout manager that can layout the root pane with that
1039
   * title pane.
1040
   *
1041
   * @param rp the root pane.
1042
   */
1043
  private void installWindowDecorations(JRootPane rp)
1044
  {
1045
    rp.setBorder(new MetalFrameBorder());
1046
    MetalTitlePane titlePane = new MetalTitlePane(rp);
1047
    rp.setLayout(new MetalRootLayout(titlePane));
1048
    // We should have a contentPane already.
1049
    assert rp.getLayeredPane().getComponentCount() > 0
1050
           : "We should have a contentPane already";
1051
 
1052
    rp.getLayeredPane().add(titlePane,
1053
                            JLayeredPane.FRAME_CONTENT_LAYER, 1);
1054
  }
1055
 
1056
  /**
1057
   * Uninstalls the window decorations from the root pane. This should rarely
1058
   * be necessary, but we do it anyway.
1059
   *
1060
   * @param rp the root pane
1061
   */
1062
  private void uninstallWindowDecorations(JRootPane rp)
1063
  {
1064
    rp.setBorder(null);
1065
    JLayeredPane lp = rp.getLayeredPane();
1066
    for (int i = lp.getComponentCount() - 1; i >= 0; --i)
1067
      {
1068
        if (lp.getComponent(i) instanceof MetalTitlePane)
1069
          {
1070
            lp.remove(i);
1071
            break;
1072
          }
1073
      }
1074
  }
1075
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.