Source for javax.swing.plaf.metal.MetalTabbedPaneUI

   1: /* MetalTabbedPaneUI.java
   2:    Copyright (C) 2005 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.Graphics;
  42: import java.awt.LayoutManager;
  43: import java.util.HashMap;
  44: 
  45: import javax.swing.JComponent;
  46: import javax.swing.JTabbedPane;
  47: import javax.swing.plaf.ComponentUI;
  48: import javax.swing.plaf.basic.BasicTabbedPaneUI;
  49: 
  50: /**
  51:  * A UI delegate used for the {@link JTabbedPane} component in the 
  52:  * {@link MetalLookAndFeel}.
  53:  */
  54: public class MetalTabbedPaneUI
  55:   extends BasicTabbedPaneUI
  56: {
  57: 
  58:   /**
  59:    * A {@link LayoutManager} responsible for placing all the tabs and the 
  60:    * visible component inside the {@link JTabbedPane}. This class is only used 
  61:    * for {@link JTabbedPane#WRAP_TAB_LAYOUT}.
  62:    *
  63:    * @specnote Apparently this class was intended to be protected,
  64:    *           but was made public by a compiler bug and is now
  65:    *           public for compatibility.
  66:    */
  67:   public class TabbedPaneLayout 
  68:       extends BasicTabbedPaneUI.TabbedPaneLayout
  69:   {
  70:     /**
  71:      * Creates a new instance of the layout manager.
  72:      */
  73:     public TabbedPaneLayout()
  74:     {
  75:     }
  76:     
  77:     /**
  78:      * Overridden to do nothing, because tab runs are not rotated in the 
  79:      * {@link MetalLookAndFeel}.
  80:      * 
  81:      * @param tabPlacement  the tab placement (one of {@link #TOP}, 
  82:      *        {@link #BOTTOM}, {@link #LEFT} or {@link #RIGHT}).
  83:      * @param selectedRun  the index of the selected run.
  84:      */
  85:     protected void rotateTabRuns(int tabPlacement, int selectedRun)
  86:     {
  87:       // do nothing, because tab runs are not rotated in the MetalLookAndFeel
  88:     }
  89:     
  90:     /**
  91:      * Overridden to do nothing, because the selected tab does not have extra
  92:      * padding in the {@link MetalLookAndFeel}.
  93:      * 
  94:      * @param tabPlacement  the tab placement (one of {@link #TOP}, 
  95:      *        {@link #BOTTOM}, {@link #LEFT} or {@link #RIGHT}).
  96:      * @param selectedIndex  the index of the selected tab.
  97:      */
  98:     protected void padSelectedTab(int tabPlacement, int selectedIndex)
  99:     {
 100:       // do nothing, because the selected tab does not have extra padding in 
 101:       // the MetalLookAndFeel
 102:     }
 103:   }
 104: 
 105:   /** The shared UI instance for JTabbedPanes. */
 106:   private static HashMap instances = null;
 107: 
 108:   /**
 109:    * Constructs a new instance of MetalTabbedPaneUI.
 110:    */
 111:   public MetalTabbedPaneUI()
 112:   {
 113:     super();
 114:   }
 115: 
 116:   /**
 117:    * Returns an instance of MetalTabbedPaneUI.
 118:    *
 119:    * @param component the component for which we return an UI instance
 120:    *
 121:    * @return an instance of MetalTabbedPaneUI
 122:    */
 123:   public static ComponentUI createUI(JComponent component)
 124:   {
 125:     if (instances == null)
 126:       instances = new HashMap();
 127: 
 128:     Object o = instances.get(component);
 129:     MetalTabbedPaneUI instance;
 130:     if (o == null)
 131:       {
 132:     instance = new MetalTabbedPaneUI();
 133:     instances.put(component, instance);
 134:       }
 135:     else
 136:       instance = (MetalTabbedPaneUI) o;
 137: 
 138:     return instance;
 139:   }
 140:   
 141:   /**
 142:    * Creates and returns an instance of {@link TabbedPaneLayout}.
 143:    * 
 144:    * @return A layout manager used by this UI delegate.
 145:    */
 146:   protected LayoutManager createLayoutManager()
 147:   {
 148:     return new TabbedPaneLayout();
 149:   }
 150:   
 151:   /**
 152:    * Paints the border for a single tab.
 153:    * 
 154:    * @param g  the graphics device.
 155:    * @param tabPlacement  the tab placement ({@link #TOP}, {@link #LEFT}, 
 156:    *        {@link #BOTTOM} or {@link #RIGHT}).
 157:    * @param tabIndex  the index of the tab to draw the border for.
 158:    * @param x  the x-coordinate for the tab's bounding rectangle.
 159:    * @param y  the y-coordinate for the tab's bounding rectangle.
 160:    * @param w  the width for the tab's bounding rectangle.
 161:    * @param h  the height for the tab's bounding rectangle.
 162:    * @param isSelected  indicates whether or not the tab is selected.
 163:    */
 164:   protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, 
 165:           int x, int y, int w, int h, boolean isSelected) 
 166:   {
 167:     if (tabPlacement == TOP)
 168:       paintTopTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected);
 169:     else if (tabPlacement == LEFT) 
 170:       paintLeftTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected);
 171:     else if (tabPlacement == BOTTOM)
 172:       paintBottomTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected);
 173:     else if (tabPlacement == RIGHT)
 174:       paintRightTabBorder(tabIndex, g, x, y, w, h, 0, 0, isSelected);
 175:     else 
 176:       throw new AssertionError("Unrecognised 'tabPlacement' argument.");
 177:   }
 178: 
 179:   /**
 180:    * Paints the border for a tab assuming that the tab position is at the top
 181:    * ({@link #TOP}).
 182:    * 
 183:    * @param tabIndex  the tab index.
 184:    * @param g  the graphics device.
 185:    * @param x  the x-coordinate for the tab's bounding rectangle.
 186:    * @param y  the y-coordinate for the tab's bounding rectangle.
 187:    * @param w  the width for the tab's bounding rectangle.
 188:    * @param h  the height for the tab's bounding rectangle.
 189:    * @param btm  ???
 190:    * @param rght  ???
 191:    * @param isSelected  indicates whether the tab is selected.
 192:    */
 193:   protected void paintTopTabBorder(int tabIndex, Graphics g, int x, int y,
 194:       int w, int h, int btm, int rght, boolean isSelected)
 195:   {
 196:     if (isSelected)
 197:     {
 198:       g.setColor(MetalLookAndFeel.getControlHighlight());
 199:       g.drawLine(x + 1, y + h, x + 1, y + 6);      
 200:       g.drawLine(x + 1, y + 6, x + 6, y + 1);
 201:       g.drawLine(x + 6, y + 1, x + w - 1, y + 1);
 202:     }
 203:     g.setColor(MetalLookAndFeel.getControlDarkShadow());
 204:     g.drawLine(x, y + h - 1, x, y + 6);
 205:     g.drawLine(x, y + 6, x + 6, y);
 206:     g.drawLine(x + 6, y, x + w, y);
 207:     g.drawLine(x + w, y, x + w, y + h - 1);
 208:   }
 209:   
 210:   /**
 211:    * Paints the border for a tab assuming that the tab position is at the left
 212:    * ({@link #LEFT}).
 213:    * 
 214:    * @param tabIndex  the tab index.
 215:    * @param g  the graphics device.
 216:    * @param x  the x-coordinate for the tab's bounding rectangle.
 217:    * @param y  the y-coordinate for the tab's bounding rectangle.
 218:    * @param w  the width for the tab's bounding rectangle.
 219:    * @param h  the height for the tab's bounding rectangle.
 220:    * @param btm  ???
 221:    * @param rght  ???
 222:    * @param isSelected  indicates whether the tab is selected.
 223:    */
 224:   protected void paintLeftTabBorder(int tabIndex, Graphics g, int x, int y,
 225:       int w, int h, int btm, int rght, boolean isSelected)
 226:   {
 227:     if (isSelected)
 228:     {
 229:       g.setColor(MetalLookAndFeel.getControlHighlight());
 230:       g.drawLine(x + 1, y + h, x + 1, y + 6);      
 231:       g.drawLine(x + 1, y + 6, x + 6, y + 1);
 232:       g.drawLine(x + 6, y + 1, x + w - 1, y + 1);
 233:     }
 234:     g.setColor(MetalLookAndFeel.getControlDarkShadow());
 235:     g.drawLine(x, y + h, x, y + 6);
 236:     g.drawLine(x, y + 6, x + 6, y);
 237:     g.drawLine(x + 6, y, x + w - 1, y);
 238:     g.drawLine(x, y + h, x + w - 1, y + h);
 239:   }
 240:   
 241:   /**
 242:    * Paints the border for a tab assuming that the tab position is at the right
 243:    * ({@link #RIGHT}).
 244:    * 
 245:    * @param tabIndex  the tab index.
 246:    * @param g  the graphics device.
 247:    * @param x  the x-coordinate for the tab's bounding rectangle.
 248:    * @param y  the y-coordinate for the tab's bounding rectangle.
 249:    * @param w  the width for the tab's bounding rectangle.
 250:    * @param h  the height for the tab's bounding rectangle.
 251:    * @param btm  ???
 252:    * @param rght  ???
 253:    * @param isSelected  indicates whether the tab is selected.
 254:    */
 255:   protected void paintRightTabBorder(int tabIndex, Graphics g, int x, int y,
 256:       int w, int h, int btm, int rght, boolean isSelected)
 257:   {
 258:     if (isSelected)
 259:     {
 260:       g.setColor(MetalLookAndFeel.getControlHighlight());
 261:       g.drawLine(x, y + 1, x + w - 7, y + 1);      
 262:       g.drawLine(x + w - 7, y + 1, x + w - 1, y + 7);
 263:     }
 264:     g.setColor(MetalLookAndFeel.getControlDarkShadow());
 265:     g.drawLine(x, y, x + w - 7, y);
 266:     g.drawLine(x + w - 7, y, x + w - 1, y + 6);
 267:     g.drawLine(x + w - 1, y + 6, x + w - 1, y + h - 1);
 268:     g.drawLine(x + w - 1, y + h, x, y + h);
 269:   }
 270:   
 271:   /**
 272:    * Paints the border for a tab assuming that the tab position is at the bottom
 273:    * ({@link #BOTTOM}).
 274:    * 
 275:    * @param tabIndex  the tab index.
 276:    * @param g  the graphics device.
 277:    * @param x  the x-coordinate for the tab's bounding rectangle.
 278:    * @param y  the y-coordinate for the tab's bounding rectangle.
 279:    * @param w  the width for the tab's bounding rectangle.
 280:    * @param h  the height for the tab's bounding rectangle.
 281:    * @param btm  ???
 282:    * @param rght  ???
 283:    * @param isSelected  indicates whether the tab is selected.
 284:    */
 285:   protected void paintBottomTabBorder(int tabIndex, Graphics g, int x, int y,
 286:       int w, int h, int btm, int rght, boolean isSelected)
 287:   {
 288:     if (isSelected)
 289:     {
 290:       g.setColor(MetalLookAndFeel.getControlHighlight());
 291:       g.drawLine(x + 1, y, x + 1, y + h - 7);      
 292:       g.drawLine(x + 1, y + h - 7, x + 7, y + h - 1);
 293:     }
 294:     g.setColor(MetalLookAndFeel.getControlDarkShadow());
 295:     g.drawLine(x, y, x, y + h - 7);
 296:     g.drawLine(x, y + h - 7, x + 6, y + h - 1);
 297:     g.drawLine(x + 6, y + h - 1, x + w, y + h - 1);
 298:     g.drawLine(x + w, y + h - 1, x + w, y);
 299:   }
 300: 
 301:   /**
 302:    * Paints the background for a tab.
 303:    * 
 304:    * @param g  the graphics device.
 305:    * @param tabPlacement  the tab placement ({@link #TOP}, {@link #LEFT}, 
 306:    *        {@link #BOTTOM} or {@link #RIGHT}).
 307:    * @param tabIndex  the index of the tab to draw the border for.
 308:    * @param x  the x-coordinate for the tab's bounding rectangle.
 309:    * @param y  the y-coordinate for the tab's bounding rectangle.
 310:    * @param w  the width for the tab's bounding rectangle.
 311:    * @param h  the height for the tab's bounding rectangle.
 312:    * @param isSelected  indicates whether or not the tab is selected.
 313:    */
 314:   protected void paintTabBackground(Graphics g, int tabPlacement,
 315:       int tabIndex, int x, int y, int w, int h, boolean isSelected)
 316:   {
 317:     if (isSelected)
 318:       g.setColor(MetalLookAndFeel.getControl());
 319:     else
 320:       g.setColor(MetalLookAndFeel.getControlShadow());
 321:     int[] px, py;
 322:     if (tabPlacement == TOP) 
 323:       {
 324:         px = new int[] {x + 6, x + w - 1, x + w -1, x + 2, x + 2};
 325:         py = new int[] {y + 2, y + 2, y + h - 1, y + h -1, y + 6};
 326:       }
 327:     else if (tabPlacement == LEFT)
 328:       {
 329:         px = new int[] {x + 6, x + w - 1, x + w -1, x + 2, x + 2};
 330:         py = new int[] {y + 2, y + 2, y + h - 1, y + h -1, y + 6};
 331:       }
 332:     else if (tabPlacement == BOTTOM)
 333:       {
 334:         px = new int[] {x + 2, x + w - 1, x + w -1, x + 8, x + 2};
 335:         py = new int[] {y, y, y + h - 1, y + h -1, y + h - 7};
 336:       }
 337:     else if (tabPlacement == RIGHT)
 338:       {
 339:         px = new int[] {x + 2, x + w - 7, x + w - 1, x + w - 1, x + 2};
 340:         py = new int[] {y + 2, y + 2, y + 7, y + h -1, y + h - 1};
 341:       }
 342:     else 
 343:       throw new AssertionError("Unrecognised 'tabPlacement' argument.");
 344:     g.fillPolygon(px, py, 5);
 345:   }
 346:   
 347:   /**
 348:    * Returns <code>true</code> if the tabs in the specified run should be 
 349:    * padded to make the run fill the width/height of the {@link JTabbedPane}.
 350:    * 
 351:    * @param tabPlacement  the tab placement for the {@link JTabbedPane} (one of
 352:    *        {@link #TOP}, {@link #BOTTOM}, {@link #LEFT} and {@link #RIGHT}).
 353:    * @param run  the run index.
 354:    * 
 355:    * @return A boolean.
 356:    */
 357:   protected boolean shouldPadTabRun(int tabPlacement, int run)
 358:   {
 359:     // as far as I can tell, all runs should be padded except the last run
 360:     // (which is drawn at the very top for tabPlacement == TOP)
 361:     return run < this.runCount - 1;
 362:   }
 363:   
 364: }