Source Code Cross Referenced for BasicTabDisplayerUI.java in  » IDE-Netbeans » library » org » netbeans » swing » tabcontrol » plaf » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » library » org.netbeans.swing.tabcontrol.plaf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         *
026:         * The Original Software is NetBeans. The Initial Developer of the Original
027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028:         * Microsystems, Inc. All Rights Reserved.
029:         *
030:         * If you wish your version of this file to be governed by only the CDDL
031:         * or only the GPL Version 2, indicate your decision by adding
032:         * "[Contributor] elects to include this software in this distribution
033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
034:         * single choice of license, a recipient has the option to distribute
035:         * your version of this file under either the CDDL, the GPL Version 2 or
036:         * to extend the choice of license to its licensees as provided above.
037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
038:         * Version 2 license, then the option applies only if the new code is
039:         * made subject to such option by the copyright holder.
040:         */
041:
042:        package org.netbeans.swing.tabcontrol.plaf;
043:
044:        import java.awt.Graphics;
045:        import java.awt.Graphics2D;
046:        import java.awt.GraphicsConfiguration;
047:        import java.awt.GraphicsEnvironment;
048:        import java.awt.Image;
049:        import java.awt.Insets;
050:        import java.awt.Point;
051:        import java.awt.Polygon;
052:        import java.awt.Rectangle;
053:        import java.awt.Shape;
054:        import java.awt.event.MouseEvent;
055:        import java.awt.event.MouseListener;
056:        import java.awt.event.MouseMotionListener;
057:        import java.awt.event.MouseWheelEvent;
058:        import java.awt.event.MouseWheelListener;
059:        import java.awt.geom.Area;
060:        import java.awt.image.BufferedImage;
061:        import java.beans.PropertyChangeListener;
062:        import javax.swing.JComponent;
063:        import javax.swing.JLabel;
064:        import javax.swing.SwingUtilities;
065:        import javax.swing.event.ChangeEvent;
066:        import javax.swing.event.ChangeListener;
067:        import javax.swing.event.ListDataEvent;
068:        import org.netbeans.swing.tabcontrol.TabData;
069:        import org.netbeans.swing.tabcontrol.TabDisplayer;
070:        import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent;
071:
072:        /**
073:         * Base class for tab displayer UIs which use cell renderers to display tabs.
074:         * This class does not contain much logic itself, but rather acts to connect events
075:         * and data from various objects relating to the tab displayer, which it creates and
076:         * installs.  Basically, the things that are involved are:
077:         * <ul>
078:         * <li>A layout model ({@link TabLayoutModel}) - A data model providing the positions and sizes of tabs</li>
079:         * <li>A state model ({@link TabState}) - A data model which tracks state data (selected, pressed, etc.)
080:         *     for each tab, and can be queried when a tab is painted to determine how that should be done.</li>
081:         * <li>A selection model ({@link javax.swing.SingleSelectionModel}) - Which tracks which tab is selected</li>
082:         * <li>The {@link TabDisplayer} component itself</li>
083:         * <li>The {@link TabDisplayer}'s data model, which contains the list of tab names, their icons and
084:         *     tooltips and the user object (or {@link java.awt.Component}) they identify</li>
085:         * <li>Assorted listeners on the component and data models, specifically
086:         *       <ul><li>A mouse listener that tells the state model when a state-affecting event
087:         *               has happened, such as the mouse entering a tab</li>
088:         *           <li>A change listener that repaints appropriately when the selection changes</li>
089:         *           <li>A property change listener to trigger any repaints needed due to property
090:         *               changes on the displayer component</li>
091:         *           <li>A component listener to attach and detach listeners when the component is shown/
092:         *               hidden, and if neccessary, notify the layout model when the component is resized</li>
093:         *           <li>A default {@link TabCellRenderer}, which is what will actually paint the tabs, and which
094:         *               is also responsible for providing some miscellaneous data such as the number of
095:         *               pixels the layout model should add to tab widths to make room for decorations,
096:         *               etc.</li>
097:         *       </ul>
098:         * </ul>
099:         * The usage pattern of this class is similar to other {@link javax.swing.plaf.ComponentUI} subclasses -
100:         * {@link javax.swing.plaf.ComponentUI#installUI}
101:         * is called via {@link JComponent#updateUI}.  <code>installUI</code> initializes protected fields which
102:         * subclasses will need, in a well defined way; abstract methods are provided for subclasses to
103:         * create these objects (such as the things listed above), and convenience implementations of some
104:         * are provided. <strong>Under no circumstances</strong> should subclasses modify these protected fields -
105:         * due to the circuitousness of the way Swing installs UIs, they cannot be declared final, but should
106:         * be treated as read-only.
107:         * <p>
108:         * The goal of this class is to make it quite easy to implement new appearances
109:         * for tabs:  To create a new appearance, implement a {@link TabCellRenderer} that can 
110:         * paint individual tabs as desired.  This is made even easier via the 
111:         * {@link TabPainter} interface - simply create the painting logic needed there.  Then
112:         * subclass <code>BasicTabDisplayerUI</code> and include any painting logic for the background,
113:         * scroll buttons, etc. needed.  A good example is {@link AquaEditorTabDisplayerUI}.
114:         *
115:         */
116:        public abstract class BasicTabDisplayerUI extends
117:                AbstractTabDisplayerUI {
118:            protected TabState tabState = null;
119:            private static final boolean swingpainting = Boolean
120:                    .getBoolean("nb.tabs.swingpainting"); //NOI18N
121:
122:            protected TabCellRenderer defaultRenderer = null;
123:            protected int repaintPolicy = 0;
124:
125:            //A couple rectangles for calculation purposes
126:            private Rectangle scratch = new Rectangle();
127:            private Rectangle scratch2 = new Rectangle();
128:            private Rectangle scratch3 = new Rectangle();
129:
130:            private Point lastKnownMouseLocation = new Point();
131:
132:            int pixelsToAdd = 0;
133:
134:            public BasicTabDisplayerUI(TabDisplayer displayer) {
135:                super (displayer);
136:            }
137:
138:            /**
139:             * Overridden to initialize the <code>tabState</code> and <code>defaultRenderer</code>.
140:             */
141:            protected void install() {
142:                super .install();
143:                tabState = createTabState();
144:                defaultRenderer = createDefaultRenderer();
145:                layoutModel.setPadding(defaultRenderer.getPadding());
146:                pixelsToAdd = defaultRenderer.getPixelsToAddToSelection();
147:                repaintPolicy = createRepaintPolicy();
148:                if (displayer.getSelectionModel().getSelectedIndex() != -1) {
149:                    tabState.setSelected(displayer.getSelectionModel()
150:                            .getSelectedIndex());
151:                    tabState.setActive(displayer.isActive());
152:                }
153:            }
154:
155:            protected void uninstall() {
156:                tabState = null;
157:                defaultRenderer = null;
158:                super .uninstall();
159:            }
160:
161:            /** Used by unit tests */
162:            TabState getTabState() {
163:                return tabState;
164:            }
165:
166:            /**
167:             * Create a TabState instance.  TabState manages the state of tabs - that is, which one
168:             * contains the mouse, which one is pressed, and so forth, providing methods such as
169:             * <code>setMouseInTab(int tab)</code>.  Its getState() method returns a bitmask of
170:             * states a tab may have which affect the way it is painted.
171:             * <p>
172:             * <b>Usage:</b> It is expected that UIs will subclass TabState, to implement the
173:             * repaint methods, and possibly override <code>getState(int tab)</code> to mix
174:             * additional state bits into the bitmask.  For example, scrollable tabs have the
175:             * possible states CLIP_LEFT and CLIP_RIGHT; BasicScrollingTabDisplayerUI's
176:             * implementation of this determines these states by consulting its layout model, and
177:             * adds them in when appropriate.
178:             *
179:             * @return An implementation of TabState
180:             * @see BasicTabDisplayerUI.BasicTabState
181:             * @see BasicScrollingTabDisplayerUI.ScrollingTabState
182:             */
183:            protected TabState createTabState() {
184:                return new BasicTabState();
185:            }
186:
187:            /**
188:             * Create the default cell renderer for this control.  If it is desirable to
189:             * have more than one renderer, override getTabCellRenderer()
190:             */
191:            protected abstract TabCellRenderer createDefaultRenderer();
192:
193:            /**
194:             * Return a set of insets defining the margins into which tabs should not be
195:             * painted.  Subclasses that want to paint some controls to the right of the
196:             * tabs should include space for those controls in these insets.  If a
197:             * bottom margin under the tabs is to be painted, include that as well.
198:             */
199:            public abstract Insets getTabAreaInsets();
200:
201:            /**
202:             * Get the cell renderer for a given tab.  The default implementation simply
203:             * returns the renderer created by createDefaultRenderer().
204:             */
205:            protected TabCellRenderer getTabCellRenderer(int tab) {
206:                return defaultRenderer;
207:            }
208:
209:            /**
210:             * Set the passed rectangle's bounds to the recangle in which tabs will be
211:             * painted; if your look and feel reserves some part of the tab area for its
212:             * own painting.  The rectangle is determined by what is returned by
213:             * getTabAreaInsets() - this is simply a convenience method for finding the
214:             * rectange into which tabs will be painted.
215:             */
216:            protected final void getTabsVisibleArea(Rectangle rect) {
217:                Insets ins = getTabAreaInsets();
218:                rect.x = ins.left;
219:                rect.y = ins.top;
220:                rect.width = displayer.getWidth() - ins.right - ins.left;
221:                rect.height = displayer.getHeight() - ins.bottom - ins.top;
222:            }
223:
224:            protected MouseListener createMouseListener() {
225:                return new BasicDisplayerMouseListener();
226:            }
227:
228:            protected PropertyChangeListener createPropertyChangeListener() {
229:                return new BasicDisplayerPropertyChangeListener();
230:            }
231:
232:            public Polygon getExactTabIndication(int index) {
233:                Rectangle r = getTabRect(index, scratch);
234:                return getTabCellRenderer(index).getTabShape(
235:                        tabState.getState(index), r);
236:            }
237:
238:            public Polygon getInsertTabIndication(int index) {
239:                Polygon p;
240:                if (index == getLastVisibleTab() + 1) {
241:                    p = (Polygon) getExactTabIndication(index - 1);
242:                    Rectangle r = getTabRect(index - 1, scratch);
243:                    p.translate(r.width / 2, 0);
244:                } else {
245:                    p = (Polygon) getExactTabIndication(index);
246:                    Rectangle r = getTabRect(index, scratch);
247:                    p.translate(-(r.width / 2), 0);
248:                }
249:                return p;
250:            }
251:
252:            public int tabForCoordinate(Point p) {
253:                if (displayer.getModel().size() == 0) {
254:                    return -1;
255:                }
256:                getTabsVisibleArea(scratch);
257:                if (!scratch.contains(p)) {
258:                    return -1;
259:                }
260:                return layoutModel.indexOfPoint(p.x, p.y);
261:            }
262:
263:            public Rectangle getTabRect(int idx, Rectangle rect) {
264:                if (rect == null) {
265:                    rect = new Rectangle();
266:                }
267:                if (idx < 0 || idx >= displayer.getModel().size()) {
268:                    rect.x = rect.y = rect.width = rect.height = 0;
269:                    return rect;
270:                }
271:                rect.x = layoutModel.getX(idx);
272:                rect.y = layoutModel.getY(idx);
273:                rect.width = layoutModel.getW(idx);
274:                getTabsVisibleArea(scratch3);
275:                //XXX for R->L component orientation cannot assume x = 0
276:                int maxPos = scratch.x + scratch3.width;
277:                if (rect.x > maxPos) {
278:                    rect.width = 0;
279:                } else if (rect.x + rect.width > maxPos) {
280:                    rect.width = (maxPos - rect.x);
281:                }
282:                rect.height = layoutModel.getH(idx);
283:                getTabsVisibleArea(scratch2);
284:                if (rect.y + rect.height > scratch2.y + scratch2.height) {
285:                    rect.height = (scratch2.y + scratch2.height) - rect.y;
286:                }
287:                if (rect.x + rect.width > scratch2.x + scratch2.width) {
288:                    rect.width = (scratch2.x + scratch2.width) - rect.x;
289:                }
290:                return rect;
291:            }
292:
293:            public Image createImageOfTab(int index) {
294:                TabData td = displayer.getModel().getTab(index);
295:
296:                JLabel lbl = new JLabel(td.getText());
297:                int width = lbl.getFontMetrics(lbl.getFont()).stringWidth(
298:                        td.getText());
299:                int height = lbl.getFontMetrics(lbl.getFont()).getHeight();
300:                width = width + td.getIcon().getIconWidth() + 6;
301:                height = Math.max(height, td.getIcon().getIconHeight()) + 5;
302:
303:                GraphicsConfiguration config = GraphicsEnvironment
304:                        .getLocalGraphicsEnvironment().getDefaultScreenDevice()
305:                        .getDefaultConfiguration();
306:
307:                BufferedImage image = config.createCompatibleImage(width,
308:                        height);
309:                Graphics2D g = image.createGraphics();
310:                g.setColor(lbl.getForeground());
311:                g.setFont(lbl.getFont());
312:                td.getIcon().paintIcon(lbl, g, 0, 0);
313:                g.drawString(td.getText(), 18, height / 2);
314:
315:                return image;
316:            }
317:
318:            public int dropIndexOfPoint(Point p) {
319:                Point p2 = toDropPoint(p);
320:                int start = getFirstVisibleTab();
321:                int end = getLastVisibleTab();
322:                int target;
323:                for (target = start; target <= end; target++) {
324:                    getTabRect(target, scratch);
325:                    if (scratch.contains(p2)) {
326:                        if (target == end) {
327:                            Object orientation = displayer
328:                                    .getClientProperty(TabDisplayer.PROP_ORIENTATION);
329:                            boolean flip = displayer.getType() == TabDisplayer.TYPE_SLIDING
330:                                    && (orientation == TabDisplayer.ORIENTATION_EAST || orientation == TabDisplayer.ORIENTATION_WEST);
331:
332:                            if (flip) {
333:                                if (p2.y > scratch.y + (scratch.height / 2)) {
334:                                    return target + 1;
335:                                }
336:                            } else {
337:                                if (p2.x > scratch.x + (scratch.width / 2)) {
338:                                    return target + 1;
339:                                }
340:                            }
341:                        }
342:                        return target;
343:                    }
344:                }
345:                return -1;
346:            }
347:
348:            protected boolean isAntialiased() {
349:                return ColorUtil.shouldAntialias();
350:            }
351:
352:            /**
353:             * Paints the tab control.  Calls paintBackground(), then paints the tabs using
354:             * their cell renderers,
355:             * then calls paintAfterTabs
356:             */
357:            public final void paint(Graphics g, JComponent c) {
358:                assert c == displayer;
359:
360:                ColorUtil.setupAntialiasing(g);
361:
362:                boolean showClose = displayer.isShowCloseButton();
363:
364:                paintBackground(g);
365:                int start = getFirstVisibleTab();
366:                if (start == -1 || !displayer.isShowing()) {
367:                    return;
368:                }
369:                //Possible to have a repaint called by a mouse-clicked event if close on mouse press
370:                int stop = Math.min(getLastVisibleTab(), displayer.getModel()
371:                        .size() - 1);
372:                getTabsVisibleArea(scratch);
373:
374:                //System.err.println("paint, clip bounds: " + g.getClipBounds() + " first visible: " + start + " last: " + stop);
375:
376:                if (g.hitClip(scratch.x, scratch.y, scratch.width,
377:                        scratch.height)) {
378:                    Shape s = g.getClip();
379:                    try {
380:                        //Ensure that we will never paint an icon into the controls area
381:                        //by setting the clipping bounds
382:                        if (s != null) {
383:                            //Okay, some clip area is already set.  Get the intersection.
384:                            Area a = new Area(s);
385:                            a.intersect(new Area(scratch.getBounds2D()));
386:                            g.setClip(a);
387:                        } else {
388:                            //Clip was not set (it's a normal call to repaint() or something
389:                            //like that).  Just set the bounds.
390:                            g.setClip(scratch.x, scratch.y, scratch.width,
391:                                    scratch.height);
392:                        }
393:
394:                        for (int i = start; i <= stop; i++) {
395:                            getTabRect(i, scratch);
396:                            if (g.hitClip(scratch.x, scratch.y,
397:                                    scratch.width + 1, scratch.height + 1)) {
398:
399:                                int state = tabState.getState(i);
400:
401:                                if ((state & TabState.NOT_ONSCREEN) == 0) {
402:                                    TabCellRenderer ren = getTabCellRenderer(i);
403:                                    ren.setShowCloseButton(showClose);
404:
405:                                    TabData data = displayer.getModel().getTab(
406:                                            i);
407:
408:                                    JComponent renderer = ren
409:                                            .getRendererComponent(data,
410:                                                    scratch, state);
411:
412:                                    renderer.setFont(displayer.getFont());
413:                                    //prepareRenderer ( renderer, data, ren.getLastKnownState () );
414:                                    if (swingpainting) {
415:                                        //Conceivable that some L&F may need this, but it generates
416:                                        //lots of useless events - better to do direct painting where
417:                                        //possible
418:                                        SwingUtilities.paintComponent(g,
419:                                                renderer, displayer, scratch);
420:                                    } else {
421:                                        try {
422:                                            g.translate(scratch.x, scratch.y);
423:                                            renderer.setBounds(scratch);
424:                                            renderer.paint(g);
425:                                        } finally {
426:                                            g.translate(-scratch.x, -scratch.y);
427:                                        }
428:                                    }
429:                                }
430:                            }
431:                        }
432:                    } finally {
433:                        g.setClip(s);
434:                    }
435:                }
436:                paintAfterTabs(g);
437:            }
438:
439:            /**
440:             * Fill in the background of the component prior to painting the tabs.  The default
441:             * implementation does nothing.  If it's just a matter of filling in a background color,
442:             * setOpaque (true) on the displayer, and ComponentUI.update() will take care of the rest.
443:             */
444:            protected void paintBackground(Graphics g) {
445:
446:            }
447:
448:            /**
449:             * Override this method to provide painting of areas outside the tabs
450:             * rectangle, such as margins and controls
451:             */
452:            protected void paintAfterTabs(Graphics g) {
453:                //do nothing
454:            }
455:
456:            /**
457:             * Scrollable implementations will override this method to provide the first
458:             * visible (even if clipped) tab.  The default implementation returns 0 if
459:             * there is at least one tab in the data model, or -1 to indicate the model
460:             * is completely empty
461:             */
462:            protected int getFirstVisibleTab() {
463:                return displayer.getModel().size() > 0 ? 0 : -1;
464:            }
465:
466:            /**
467:             * Scrollable implementations will override this method to provide the last
468:             * visible (even if clipped) tab.  The default implementation returns 0 if
469:             * there is at least one tab in the data model, or -1 to indicate the model
470:             * is completely empty
471:             */
472:            protected int getLastVisibleTab() {
473:                return displayer.getModel().size() - 1;
474:            }
475:
476:            protected ChangeListener createSelectionListener() {
477:                return new BasicSelectionListener();
478:            }
479:
480:            protected final Point getLastKnownMouseLocation() {
481:                return lastKnownMouseLocation;
482:            }
483:
484:            /**
485:             * Convenience method to override for handling mouse wheel events. The
486:             * defualt implementation does nothing.
487:             */
488:            protected void processMouseWheelEvent(MouseWheelEvent e) {
489:                //do nothing
490:            }
491:
492:            protected final void requestAttention(int tab) {
493:                tabState.addAlarmTab(tab);
494:            }
495:
496:            protected final void cancelRequestAttention(int tab) {
497:                tabState.removeAlarmTab(tab);
498:            }
499:
500:            protected void modelChanged() {
501:                tabState.clearTransientStates();
502:                //DefaultTabSelectionModel automatically updates its selected index when things
503:                //are added/removed from the model, so just make sure our state machine stays in
504:                //sync
505:                int idx = selectionModel.getSelectedIndex();
506:                tabState.setSelected(idx);
507:                tabState.pruneAlarmTabs(displayer.getModel().size());
508:                super .modelChanged();
509:            }
510:
511:            /**
512:             * Create the policy that will determine what types of events trigger a repaint of one or more tabs.
513:             * This is a bitmask composed of constants defined in TabState. The default value is
514:             * <pre>
515:             *  TabState.REPAINT_SELECTION_ON_ACTIVATION_CHANGE
516:                        | TabState.REPAINT_ON_SELECTION_CHANGE
517:                        | TabState.REPAINT_ON_MOUSE_ENTER_TAB
518:                        | TabState.REPAINT_ON_MOUSE_ENTER_CLOSE_BUTTON
519:                        | TabState.REPAINT_ON_MOUSE_PRESSED;
520:             *</pre>
521:             *
522:             *
523:             * @return  The repaint policy that should be used in conjunction with mouse events to determine when a
524:             *          repaint is needed.
525:             */
526:            protected int createRepaintPolicy() {
527:                return TabState.REPAINT_SELECTION_ON_ACTIVATION_CHANGE
528:                        | TabState.REPAINT_ON_SELECTION_CHANGE
529:                        | TabState.REPAINT_ON_MOUSE_ENTER_TAB
530:                        | TabState.REPAINT_ON_MOUSE_ENTER_CLOSE_BUTTON
531:                        | TabState.REPAINT_ON_MOUSE_PRESSED;
532:            }
533:
534:            /**
535:             * @return Rectangle of the tab to be repainted
536:             */
537:            protected Rectangle getTabRectForRepaint(int tab, Rectangle rect) {
538:                return getTabRect(tab, rect);
539:            }
540:
541:            protected class BasicTabState extends TabState {
542:
543:                public int getState(int tab) {
544:                    if (displayer.getModel().size() == 0) {
545:                        return TabState.NOT_ONSCREEN;
546:                    }
547:                    int result = super .getState(tab);
548:                    if (tab == 0) {
549:                        result |= TabState.LEFTMOST;
550:                    }
551:                    if (tab == displayer.getModel().size() - 1) {
552:                        result |= TabState.RIGHTMOST;
553:                    }
554:                    return result;
555:                }
556:
557:                protected void repaintAllTabs() {
558:                    //XXX would be nicer to just repaint the tabs area,
559:                    //but we also need to repaint below all the tabs in the
560:                    //event of activated/deactivated.  No actual reason to
561:                    //repaint the buttons here.
562:                    displayer.repaint();
563:                }
564:
565:                public int getRepaintPolicy(int tab) {
566:                    //Defined in createRepaintPolicy()
567:                    return repaintPolicy;
568:                }
569:
570:                protected void repaintTab(int tab) {
571:                    if (tab == -1 || tab > displayer.getModel().size()) {
572:                        return;
573:                    }
574:                    getTabRectForRepaint(tab, scratch);
575:                    scratch.y = 0;
576:                    scratch.height = displayer.getHeight();
577:                    displayer.repaint(scratch.x, scratch.y, scratch.width,
578:                            scratch.height);
579:                }
580:            }
581:
582:            protected ModelListener createModelListener() {
583:                return new BasicModelListener();
584:            }
585:
586:            private class BasicDisplayerPropertyChangeListener extends
587:                    DisplayerPropertyChangeListener {
588:
589:                protected void activationChanged() {
590:                    tabState.setActive(displayer.isActive());
591:                }
592:            }
593:
594:            protected class BasicDisplayerMouseListener implements 
595:                    MouseListener, MouseMotionListener, MouseWheelListener {
596:                private int updateMouseLocation(MouseEvent e) {
597:                    lastKnownMouseLocation.x = e.getX();
598:                    lastKnownMouseLocation.y = e.getY();
599:                    return tabForCoordinate(lastKnownMouseLocation);
600:                }
601:
602:                public void mouseClicked(MouseEvent e) {
603:                    int idx = updateMouseLocation(e);
604:                    if (idx == -1) {
605:                        return;
606:                    }
607:
608:                    TabCellRenderer tcr = getTabCellRenderer(idx);
609:                    getTabRect(idx, scratch);
610:                    int state = tabState.getState(idx);
611:
612:                    potentialCommand(idx, e, state, tcr, scratch);
613:                }
614:
615:                public void mouseDragged(MouseEvent e) {
616:                    mouseMoved(e);
617:                }
618:
619:                public void mouseEntered(MouseEvent e) {
620:                    int idx = updateMouseLocation(e);
621:                    tabState.setMouseInTabsArea(true);
622:                    tabState.setContainsMouse(idx);
623:                }
624:
625:                public void mouseExited(MouseEvent e) {
626:                    updateMouseLocation(e);
627:                    tabState.setMouseInTabsArea(false);
628:                    tabState.setContainsMouse(-1);
629:                    tabState.setCloseButtonContainsMouse(-1);
630:                }
631:
632:                public void mouseMoved(MouseEvent e) {
633:                    int idx = updateMouseLocation(e);
634:                    tabState.setMouseInTabsArea(true);
635:                    tabState.setContainsMouse(idx);
636:                    if (idx != -1) {
637:                        TabCellRenderer tcr = getTabCellRenderer(idx);
638:                        getTabRect(idx, scratch);
639:                        int state = tabState.getState(idx);
640:
641:                        String s = tcr.getCommandAtPoint(e.getPoint(), state,
642:                                scratch);
643:                        if (TabDisplayer.COMMAND_CLOSE == s) {
644:                            tabState.setCloseButtonContainsMouse(idx);
645:                        } else {
646:                            tabState.setCloseButtonContainsMouse(-1);
647:                        }
648:                    } else {
649:                        tabState.setContainsMouse(-1);
650:                    }
651:                }
652:
653:                private int lastPressedTab = -1;
654:                private long pressTime = -1;
655:
656:                public void mousePressed(MouseEvent e) {
657:                    int idx = updateMouseLocation(e);
658:                    tabState.setPressed(idx);
659:
660:                    //One a double click, preserve the tab that was initially clicked, in case
661:                    //a re-layout happened.  We'll pass that to the action.
662:                    long time = e.getWhen();
663:                    if (time - pressTime > 200) {
664:                        lastPressedTab = idx;
665:                    }
666:                    pressTime = time;
667:                    lastPressedTab = idx;
668:                    if (idx != -1) {
669:                        TabCellRenderer tcr = getTabCellRenderer(idx);
670:                        getTabRect(idx, scratch);
671:                        int state = tabState.getState(idx);
672:
673:                        //First find the command for the location with the default button -
674:                        //TabState may trigger a repaint
675:                        String command = tcr.getCommandAtPoint(e.getPoint(),
676:                                state, scratch);
677:                        if (TabDisplayer.COMMAND_CLOSE == command) {
678:                            tabState.setCloseButtonContainsMouse(idx);
679:                            tabState.setMousePressedInCloseButton(idx);
680:
681:                            //We're closing, don't try to maximize this tab if it turns out to be
682:                            //a double click
683:                            pressTime = -1;
684:                            lastPressedTab = -1;
685:                        }
686:
687:                        potentialCommand(idx, e, state, tcr, scratch);
688:                    } else {
689:                        tabState.setMousePressedInCloseButton(-1); //just in case
690:                    }
691:                }
692:
693:                private void potentialCommand(int idx, MouseEvent e, int state,
694:                        TabCellRenderer tcr, Rectangle bounds) {
695:                    String command = tcr.getCommandAtPoint(e.getPoint(), state,
696:                            bounds, e.getButton(), e.getID(), e
697:                                    .getModifiersEx());
698:                    if (command == null
699:                            || TabDisplayer.COMMAND_SELECT == command) {
700:                        if (e.isPopupTrigger()) {
701:                            displayer.repaint();
702:                            performCommand(TabDisplayer.COMMAND_POPUP_REQUEST,
703:                                    idx, e);
704:                            return;
705:                        } else if (e.getID() == MouseEvent.MOUSE_CLICKED
706:                                && e.getClickCount() >= 2) {
707:                            performCommand(TabDisplayer.COMMAND_MAXIMIZE, idx,
708:                                    e);
709:                            return;
710:                        }
711:                    }
712:
713:                    if (command != null) {
714:                        performCommand(command,
715:                                lastPressedTab == -1
716:                                        || lastPressedTab > displayer
717:                                                .getModel().size() ? idx
718:                                        : lastPressedTab, e);
719:                    }
720:                }
721:
722:                private void performCommand(String command, int idx,
723:                        MouseEvent evt) {
724:                    evt.consume();
725:                    if (TabDisplayer.COMMAND_SELECT == command) {
726:                        if (idx != displayer.getSelectionModel()
727:                                .getSelectedIndex()) {
728:                            boolean go = shouldPerformAction(command, idx, evt);
729:                            if (go) {
730:                                selectionModel.setSelectedIndex(idx);
731:                            }
732:                        }
733:                    } else {
734:                        boolean should = shouldPerformAction(command, idx, evt)
735:                                && displayer.isShowCloseButton();
736:                        if (should) {
737:                            if (TabDisplayer.COMMAND_CLOSE == command) {
738:                                displayer.getModel().removeTab(idx);
739:                            } else if (TabDisplayer.COMMAND_CLOSE_ALL == command) {
740:                                displayer.getModel().removeTabs(0,
741:                                        displayer.getModel().size());
742:                            } else if (TabDisplayer.COMMAND_CLOSE_ALL_BUT_THIS == command) {
743:                                int start;
744:                                int end;
745:                                if (idx != displayer.getModel().size() - 1) {
746:                                    start = idx + 1;
747:                                    end = displayer.getModel().size();
748:                                    displayer.getModel().removeTabs(start, end);
749:                                }
750:                                if (idx != 0) {
751:                                    start = 0;
752:                                    end = idx;
753:                                    displayer.getModel().removeTabs(start, end);
754:                                }
755:                            }
756:                        }
757:                    }
758:                }
759:
760:                public void mouseReleased(MouseEvent e) {
761:                    int idx = updateMouseLocation(e);
762:                    if (idx != -1) {
763:                        TabCellRenderer tcr = getTabCellRenderer(idx);
764:                        getTabRect(idx, scratch);
765:                        int state = tabState.getState(idx);
766:                        if ((state & TabState.PRESSED) != 0
767:                                && ((state & TabState.CLIP_LEFT) != 0)
768:                                || (state & TabState.CLIP_RIGHT) != 0) {
769:                            makeTabVisible(idx);
770:                        }
771:                        potentialCommand(idx, e, state, tcr, scratch);
772:                    }
773:                    tabState.setMouseInTabsArea(idx != -1);
774:                    tabState.setPressed(-1);
775:                    tabState.setMousePressedInCloseButton(-1);
776:                }
777:
778:                public final void mouseWheelMoved(MouseWheelEvent e) {
779:                    updateMouseLocation(e);
780:                    processMouseWheelEvent(e);
781:                }
782:            }
783:
784:            /** A simple selection listener implementation which updates the TabState model
785:             * with the new selected index from the selection model when it changes.
786:             */
787:            protected class BasicSelectionListener implements  ChangeListener {
788:                public void stateChanged(ChangeEvent e) {
789:                    assert e.getSource() == selectionModel : "Unknown event source: "
790:                            + e.getSource();
791:                    int idx = selectionModel.getSelectedIndex();
792:                    tabState.setSelected(idx >= 0 ? idx : -1);
793:                    if (idx >= 0) {
794:                        makeTabVisible(selectionModel.getSelectedIndex());
795:                    }
796:                }
797:            }
798:
799:            /**
800:             * Listener on data model which will pass modified indices to the
801:             * TabState object, so it can update which tab indices are flashing in
802:             * "attention" mode, if any.
803:             */
804:            protected class BasicModelListener extends
805:                    AbstractTabDisplayerUI.ModelListener {
806:                public void contentsChanged(ListDataEvent e) {
807:                    super .contentsChanged(e);
808:                    tabState.contentsChanged(e);
809:                }
810:
811:                public void indicesAdded(ComplexListDataEvent e) {
812:                    super .indicesAdded(e);
813:                    tabState.indicesAdded(e);
814:                }
815:
816:                public void indicesChanged(ComplexListDataEvent e) {
817:                    tabState.indicesChanged(e);
818:                }
819:
820:                public void indicesRemoved(ComplexListDataEvent e) {
821:                    tabState.indicesRemoved(e);
822:                }
823:
824:                public void intervalAdded(ListDataEvent e) {
825:                    tabState.intervalAdded(e);
826:                }
827:
828:                public void intervalRemoved(ListDataEvent e) {
829:                    tabState.intervalRemoved(e);
830:                }
831:            }
832:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.