This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 48811
Collapse All | Expand All

(-)core/swing/tabcontrol/demosrc/org/netbeans/swing/tabcontrol/demo/TestFrame.java (-10 / +92 lines)
Lines 63-72 Link Here
63
         */
63
         */
64
        
64
        
65
        try {
65
        try {
66
            //UIManager.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel());
66
//            UIManager.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel());
67
        } catch (Exception e) {
67
        } catch (Exception e) {
68
        }
68
        }
69
69
70
//        UIManager.put ("EditorTabDisplayerUI", "org.netbeans.swing.tabcontrol.plaf.WinClassicEditorTabDisplayerUI");
71
//        UIManager.put ("ViewTabDisplayerUI", "org.netbeans.swing.tabcontrol.plaf.WinClassicViewTabDisplayerUI");
72
//        UIManager.put ("EditorTabDisplayerUI", "org.netbeans.swing.tabcontrol.plaf.WinXPEditorTabDisplayerUI");
73
//        UIManager.put ("ViewTabDisplayerUI", "org.netbeans.swing.tabcontrol.plaf.WinXPViewTabDisplayerUI");
74
        
75
        
70
        JLabel jb1 = new JLabel("Label 1");
76
        JLabel jb1 = new JLabel("Label 1");
71
        final JButton jb2 = new JButton("Button 2 - Update UI");
77
        final JButton jb2 = new JButton("Button 2 - Update UI");
72
        JButton jb3 = new JButton("Click me to remove this tab");
78
        JButton jb3 = new JButton("Click me to remove this tab");
Lines 90-95 Link Here
90
        JTA.setColumns(80);
96
        JTA.setColumns(80);
91
        JTA.setLineWrap(true);
97
        JTA.setLineWrap(true);
92
        
98
        
99
        JButton jb7 = new JButton ("Remove non-contiguous tabs");
100
        JButton jb8 = new JButton ("Discontig add");
101
        
102
        JButton jb9 = new JButton ("Contig add");
103
        JButton jb10 = new JButton ("Contig remove");
104
        
105
        JButton jb11 = new JButton ("Discontig add and remove");
106
        
93
107
94
        TabData tab0 = new TabData(jtr, myIcon, "0 JTree", "0");
108
        TabData tab0 = new TabData(jtr, myIcon, "0 JTree", "0");
95
        TabData tab1 = new TabData(jb1, myIcon, "1 Tab 1", "1");
109
        TabData tab1 = new TabData(jb1, myIcon, "1 Tab 1", "1");
Lines 107-123 Link Here
107
                                   "7");
121
                                   "7");
108
        TabData tab8 = new TabData(new JLabel("gioo"), myIcon,
122
        TabData tab8 = new TabData(new JLabel("gioo"), myIcon,
109
                                   "8 something", "8");
123
                                   "8 something", "8");
110
        TabData tab9 = new TabData(new JButton("foo"), myIcon, "9 foob",
124
        TabData tab9 = new TabData(jb7, myIcon, "9 Discontig remove",
111
                                   "9");
125
                                   "9");
112
        TabData tab10 = new TabData(new JLabel("gioo"), myIcon, "10 wiggle",
126
        TabData tab10 = new TabData(new JLabel("gioo"), myIcon, "10 wiggle",
113
                                    "10");
127
                                    "10");
114
        TabData tab11 = new TabData(new JButton("foo"), myIcon, "11 bumble",
128
        TabData tab11 = new TabData(jb8, myIcon, "11 Discontig add",
115
                                    "11");
129
                                    "11");
116
        TabData tab12 = new TabData(new JLabel("mooble"), myIcon,
130
        TabData tab12 = new TabData(jb9, myIcon,
117
                                    "12 poodle", "12");
131
                                    "12 contig add", "12");
118
        TabData tab13 = new TabData(new JButton("fooble"), myIcon,
132
        TabData tab13 = new TabData(jb10, myIcon,
119
                                    "13 hoover", "13");
133
                                    "13 contig remove", "13");
120
        TabData tab14 = new TabData(new JLabel("gooble"), myIcon, "14 snip",
134
        TabData tab14 = new TabData(jb11, myIcon, "14 MUNGE",
121
                                    "14");
135
                                    "14");
122
136
123
        TabDataModel mdl = new DefaultTabDataModel(new TabData[]{
137
        TabDataModel mdl = new DefaultTabDataModel(new TabData[]{
Lines 130-137 Link Here
130
        );
144
        );
131
         */
145
         */
132
        
146
        
133
        final TabbedContainer tab = new TabbedContainer(mdl, TabbedContainer.TYPE_EDITOR);
147
        final TabbedContainer tab = new TabbedContainer(mdl, TabbedContainer.TYPE_VIEW);
134
        tab.setActive(true);    
148
        tab.setActive(true);
149
        tab.requestAttention(5);
150
        tab.requestAttention(3);
135
        
151
        
136
        jb6.addActionListener(new ActionListener() {
152
        jb6.addActionListener(new ActionListener() {
137
            public void actionPerformed(ActionEvent ae) {
153
            public void actionPerformed(ActionEvent ae) {
Lines 161-166 Link Here
161
                tab.updateUI();
177
                tab.updateUI();
162
            }
178
            }
163
        });
179
        });
180
        
181
        jb7.addActionListener(new ActionListener() {
182
            public void actionPerformed(ActionEvent ae) {
183
                tab.getModel().removeTabs(new int[] {1, 3, 7, 8});
184
            }
185
        });
186
        
187
        jb8.addActionListener(new ActionListener() {
188
            public void actionPerformed(ActionEvent ae) {
189
                int[] idxs = new int [] { 1, 3, 6, 8};
190
                TabData[] td = new TabData[] {
191
                    new TabData(new JButton("inserted 1"), myIcon, "I-1", "tip"),
192
                    new TabData(new JButton("inserted 3"), myIcon, "I-3", "tip"),
193
                    new TabData(new JButton("inserted 6"), myIcon, "I-6", "tip"),
194
                    new TabData(new JButton("inserted 8"), myIcon, "I-8", "tip"),
195
                    
196
                };
197
                tab.getModel().addTabs(idxs, td);
198
            }
199
        });  
200
        
201
        jb9.addActionListener(new ActionListener() {
202
            public void actionPerformed(ActionEvent ae) {
203
                int[] idxs = new int [] { 1, 3, 6, 8};
204
                TabData[] td = new TabData[] {
205
                    new TabData(new JButton("inserted c 1"), myIcon, "Ic-1", "tip"),
206
                    new TabData(new JButton("inserted c 2"), myIcon, "Ic-2", "tip"),
207
                    new TabData(new JButton("inserted c 3"), myIcon, "Ic-3", "tip"),
208
                    new TabData(new JButton("inserted c 4"), myIcon, "Ic-4", "tip"),
209
                    
210
                };
211
                tab.getModel().addTabs(1, td);
212
            }
213
        }); 
214
        
215
        jb10.addActionListener(new ActionListener() {
216
            public void actionPerformed(ActionEvent ae) {
217
                tab.getModel().removeTabs(1, 4);
218
            }
219
        });  
220
        
221
        jb11.addActionListener(new ActionListener() {
222
            public void actionPerformed(ActionEvent ae) {
223
                TabData[] data = (TabData[]) tab.getModel().getTabs().toArray(new TabData[0]);
224
                
225
                TabData[] newData = new TabData [ data.length - 3];
226
                int ct = 0;
227
                
228
                //strip out some tabs
229
                for (int i=0; i < data.length; i++) {
230
                    newData[ct] = data[i];
231
                    if (i != 2 && i != 3 && i != 7) {
232
                        ct++;
233
                    }
234
                }
235
                
236
                //replace one tab
237
                newData[1] = new TabData (new JLabel ("Hi there"), myIcon, "New tab", "foo");
238
                //swap some tabs
239
                TabData td = newData[8];
240
                newData[8] = newData[7];
241
                newData[7] = td;
242
                
243
                tab.getModel().setTabs(newData);
244
            }
245
        });  
164
246
165
        tab.setActive(true);
247
        tab.setActive(true);
166
        
248
        
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/DefaultTabDataModel.java (-2 / +9 lines)
Lines 327-335 Link Here
327
        fireIntervalRemoved(lde);
327
        fireIntervalRemoved(lde);
328
    }
328
    }
329
329
330
    /**
331
     * Remove a range of tabs from <code>start</code> up to <i>and including</i> 
332
     * <code>finish</code>.
333
     */
330
    public void removeTabs(int start, int end) {
334
    public void removeTabs(int start, int end) {
331
        java.util.List affected = list.subList(start, end);
335
        java.util.List affected = list.subList(start, end);
332
        list.removeRange(start, end);
336
        if (start == end) {
337
            list.remove(start);
338
        } else {
339
            list.removeRange(start, end + 1);
340
        }
333
        ComplexListDataEvent lde = new ComplexListDataEvent(this,
341
        ComplexListDataEvent lde = new ComplexListDataEvent(this,
334
                                                            ListDataEvent.INTERVAL_REMOVED,
342
                                                            ListDataEvent.INTERVAL_REMOVED,
335
                                                            start, end);
343
                                                            start, end);
Lines 343-349 Link Here
343
            m.put(new Integer(indices[i]), data[i]);
351
            m.put(new Integer(indices[i]), data[i]);
344
        }
352
        }
345
        Arrays.sort(indices);
353
        Arrays.sort(indices);
346
//        for (int i=indices.length-1; i >= 0; i--) {
347
        for (int i = 0; i < indices.length; i++) {
354
        for (int i = 0; i < indices.length; i++) {
348
            Integer key = new Integer(indices[i]);
355
            Integer key = new Integer(indices[i]);
349
            TabData currData = (TabData) m.get(key);
356
            TabData currData = (TabData) m.get(key);
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/TabDisplayer.java (+13 lines)
Lines 333-338 Link Here
333
    public final Dimension getMinimumSize() {
333
    public final Dimension getMinimumSize() {
334
        return getUI().getMinimumSize(this);
334
        return getUI().getMinimumSize(this);
335
    }
335
    }
336
    
337
    public final void requestAttention (int tab) {
338
        getUI().requestAttention(tab);
339
    }
340
    
341
    public final boolean requestAttention (TabData data) {
342
        int idx = getModel().indexOf(data);
343
        boolean result = idx >= 0;
344
        if (result) {
345
            requestAttention (idx);
346
        }
347
        return result;
348
    }
336
349
337
    /**
350
    /**
338
     * Accessor only for TabDisplayerUI when installing the UI
351
     * Accessor only for TabDisplayerUI when installing the UI
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/TabDisplayerUI.java (+2 lines)
Lines 184-188 Link Here
184
    public abstract void registerShortcuts (JComponent comp);
184
    public abstract void registerShortcuts (JComponent comp);
185
        
185
        
186
    public abstract void unregisterShortcuts (JComponent comp);
186
    public abstract void unregisterShortcuts (JComponent comp);
187
    
188
    public abstract void requestAttention (int tab);
187
189
188
}
190
}
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/TabbedContainer.java (+21 lines)
Lines 556-561 Link Here
556
            firePropertyChange(PROP_ACTIVE, !active, active);
556
            firePropertyChange(PROP_ACTIVE, !active, active);
557
        }
557
        }
558
    }
558
    }
559
    
560
    /**
561
     * Cause the tab at the specified index to blink or otherwise suggest that
562
     * the user should click it.
563
     */
564
    public void requestAttention (int tab) {
565
        getUI().requestAttention(tab);
566
    }
567
    
568
    /**
569
     * Cause the specified tab to blink or otherwisse suggest that the user should
570
     * click it.
571
     */
572
    public final boolean requestAttention (TabData data) {
573
        int idx = getModel().indexOf(data);
574
        boolean result = idx >= 0;
575
        if (result) {
576
            requestAttention (idx);
577
        }
578
        return result;
579
    }    
559
580
560
    /**
581
    /**
561
     * Determine if this component thinks it is &quot;active&quot;, which
582
     * Determine if this component thinks it is &quot;active&quot;, which
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/TabbedContainerUI.java (+2 lines)
Lines 199-202 Link Here
199
     */
199
     */
200
    public abstract int dropIndexOfPoint(Point p);
200
    public abstract int dropIndexOfPoint(Point p);
201
201
202
    public abstract void requestAttention (int tab);
203
    
202
}
204
}
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/AbstractTabCellRenderer.java (+4 lines)
Lines 190-195 Link Here
190
    protected final boolean isRightmost() {
190
    protected final boolean isRightmost() {
191
        return (state & TabState.RIGHTMOST) != 0;
191
        return (state & TabState.RIGHTMOST) != 0;
192
    }
192
    }
193
    
194
    protected final boolean isAttention() {
195
        return (state & TabState.ATTENTION) != 0;
196
    }
193
197
194
    /**
198
    /**
195
     * Convenience getter to determine if the current state indicates
199
     * Convenience getter to determine if the current state indicates
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/AbstractTabDisplayerUI.java (-1 / +1 lines)
Lines 401-407 Link Here
401
         * No-op implementation
401
         * No-op implementation
402
         */
402
         */
403
        public void contentsChanged(ListDataEvent e) {
403
        public void contentsChanged(ListDataEvent e) {
404
            //do nothing
404
            
405
        }
405
        }
406
406
407
        /**
407
        /**
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/AbstractViewTabDisplayerUI.java (-3 / +89 lines)
Lines 13-18 Link Here
13
13
14
package org.netbeans.swing.tabcontrol.plaf;
14
package org.netbeans.swing.tabcontrol.plaf;
15
15
16
import javax.swing.event.ListDataEvent;
16
import org.netbeans.swing.tabcontrol.TabData;
17
import org.netbeans.swing.tabcontrol.TabData;
17
import org.netbeans.swing.tabcontrol.TabDataModel;
18
import org.netbeans.swing.tabcontrol.TabDataModel;
18
import org.netbeans.swing.tabcontrol.TabDisplayer;
19
import org.netbeans.swing.tabcontrol.TabDisplayer;
Lines 38-43 Link Here
38
import java.util.Map;
39
import java.util.Map;
39
import org.netbeans.swing.tabcontrol.LocationInformer;
40
import org.netbeans.swing.tabcontrol.LocationInformer;
40
import org.netbeans.swing.tabcontrol.TabbedContainer;
41
import org.netbeans.swing.tabcontrol.TabbedContainer;
42
import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent;
43
import org.netbeans.swing.tabcontrol.event.ComplexListDataListener;
41
44
42
/**
45
/**
43
 * Basic UI class for view tabs - non scrollable tabbed displayer, which shows all
46
 * Basic UI class for view tabs - non scrollable tabbed displayer, which shows all
Lines 83-88 Link Here
83
        dataModel = displayer.getModel();
86
        dataModel = displayer.getModel();
84
        layoutModel = new ViewTabLayoutModel(dataModel, displayer);
87
        layoutModel = new ViewTabLayoutModel(dataModel, displayer);
85
        dataModel.addChangeListener (controller);
88
        dataModel.addChangeListener (controller);
89
        dataModel.addComplexListDataListener(controller);
86
        displayer.addPropertyChangeListener (controller);
90
        displayer.addPropertyChangeListener (controller);
87
        selectionModel.addChangeListener (controller);
91
        selectionModel.addChangeListener (controller);
88
        displayer.addMouseListener(controller);
92
        displayer.addMouseListener(controller);
Lines 106-111 Link Here
106
        ToolTipManager.sharedInstance().unregisterComponent(displayer);
110
        ToolTipManager.sharedInstance().unregisterComponent(displayer);
107
        displayer.removePropertyChangeListener (controller);
111
        displayer.removePropertyChangeListener (controller);
108
        dataModel.removeChangeListener(controller);
112
        dataModel.removeChangeListener(controller);
113
        dataModel.removeComplexListDataListener(controller);
109
        selectionModel.removeChangeListener(controller);
114
        selectionModel.removeChangeListener(controller);
110
        displayer.removeMouseListener(controller);
115
        displayer.removeMouseListener(controller);
111
        displayer.removeMouseMotionListener(controller);
116
        displayer.removeMouseMotionListener(controller);
Lines 503-511 Link Here
503
    }
508
    }
504
509
505
    public Rectangle getTabRect(int index, Rectangle destination) {
510
    public Rectangle getTabRect(int index, Rectangle destination) {
511
        if (destination == null) {
512
            destination = new Rectangle();
513
        }
506
        if (index < 0 || index > displayer.getModel().size()) {
514
        if (index < 0 || index > displayer.getModel().size()) {
507
            throw new ArrayIndexOutOfBoundsException("Tab index out of " +
515
            destination.setBounds (0,0,0,0);
508
                "bounds: " + index);
516
            return destination;
509
        }
517
        }
510
        destination.x = layoutModel.getX(index);
518
        destination.x = layoutModel.getX(index);
511
        destination.width = layoutModel.getW(index);
519
        destination.width = layoutModel.getW(index);
Lines 532-544 Link Here
532
        
540
        
533
        return -1;
541
        return -1;
534
    }
542
    }
543
    
544
    protected int createRepaintPolicy () {
545
        return TabState.REPAINT_SELECTION_ON_ACTIVATION_CHANGE
546
                | TabState.REPAINT_ON_SELECTION_CHANGE
547
                | TabState.REPAINT_ON_MOUSE_ENTER_TAB
548
                | TabState.REPAINT_ON_MOUSE_ENTER_CLOSE_BUTTON
549
                | TabState.REPAINT_ON_MOUSE_PRESSED;
550
    }
551
    
552
    protected final TabState tabState = new ViewTabState();
553
    
554
    private class ViewTabState extends TabState {
555
        public int getRepaintPolicy(int tab) {
556
            return createRepaintPolicy();
557
        }
558
        
559
        public void repaintAllTabs() {
560
            displayer.repaint();
561
        }
562
        
563
        public void repaintTab (int tab) {
564
            Rectangle r = getTabRect(tab, null);
565
            displayer.repaint(r);
566
        }
567
    }
568
    
569
    /**
570
     * Determine if the tab should be flashing
571
     */
572
    protected boolean isAttention (int tab) {
573
        return (tabState.getState(tab) & TabState.ATTENTION) != 0;
574
    }
575
    
576
577
    public void requestAttention (int tab) {
578
        tabState.addAlarmTab(tab);
579
    }    
535
580
536
    /**
581
    /**
537
     * Listen to mouse events and handles selection behaviour and close icon
582
     * Listen to mouse events and handles selection behaviour and close icon
538
     * button behaviour.
583
     * button behaviour.
539
     */
584
     */
540
    abstract class Controller extends MouseAdapter
585
    abstract class Controller extends MouseAdapter
541
            implements MouseMotionListener, ChangeListener, PropertyChangeListener, ActionListener {
586
            implements MouseMotionListener, ChangeListener, PropertyChangeListener, ActionListener, ComplexListDataListener {
542
587
543
        /**
588
        /**
544
         * index of tab whose close icon currently pressed, -1 otherwise
589
         * index of tab whose close icon currently pressed, -1 otherwise
Lines 596-606 Link Here
596
        public void mousePressed(MouseEvent e) {
641
        public void mousePressed(MouseEvent e) {
597
            Point p = e.getPoint();
642
            Point p = e.getPoint();
598
            int i = getLayoutModel().indexOfPoint(p.x, p.y);
643
            int i = getLayoutModel().indexOfPoint(p.x, p.y);
644
            tabState.setPressed(i);
599
            SingleSelectionModel sel = getSelectionModel();
645
            SingleSelectionModel sel = getSelectionModel();
600
            selectionChanged = i != sel.getSelectedIndex();
646
            selectionChanged = i != sel.getSelectedIndex();
601
            // invoke possible selection change
647
            // invoke possible selection change
602
            if ((i != -1) || !selectionChanged) {
648
            if ((i != -1) || !selectionChanged) {
603
                getSelectionModel().setSelectedIndex(i);
649
                getSelectionModel().setSelectedIndex(i);
650
                tabState.setSelected(i);
604
            } 
651
            } 
605
            // update pressed state
652
            // update pressed state
606
            if (shouldReact(e) && !selectionChanged) {
653
            if (shouldReact(e) && !selectionChanged) {
Lines 632-637 Link Here
632
        public void mouseReleased(MouseEvent e) {
679
        public void mouseReleased(MouseEvent e) {
633
            // close button must not be active when selection change was
680
            // close button must not be active when selection change was
634
            // triggered by mouse press
681
            // triggered by mouse press
682
            tabState.setPressed(-1);
635
            if (shouldReact(e) && !selectionChanged) {
683
            if (shouldReact(e) && !selectionChanged) {
636
                setClosePressed(-1);
684
                setClosePressed(-1);
637
                Point point = e.getPoint();
685
                Point point = e.getPoint();
Lines 721-726 Link Here
721
            // sync of indexes
769
            // sync of indexes
722
            int oldValue = mouseInCloseButton;
770
            int oldValue = mouseInCloseButton;
723
            mouseInCloseButton = isNow;
771
            mouseInCloseButton = isNow;
772
            tabState.setCloseButtonContainsMouse(isNow);
724
            if (isNow == -1) {
773
            if (isNow == -1) {
725
                // exit from close area
774
                // exit from close area
726
                TabLayoutModel tlm = getLayoutModel();
775
                TabLayoutModel tlm = getLayoutModel();
Lines 745-751 Link Here
745
        public void actionPerformed(ActionEvent e) {
794
        public void actionPerformed(ActionEvent e) {
746
            performPinAction();
795
            performPinAction();
747
        }
796
        }
797
798
        public void indicesAdded(ComplexListDataEvent e) {
799
            tabState.indicesAdded(e);
800
        }
801
802
        /**
803
         * Elements have been removed at the indices specified by the event's
804
         * getIndices() value
805
         *
806
         * @param e The event
807
         */
808
        public void indicesRemoved(ComplexListDataEvent e) {
809
            tabState.indicesRemoved(e);
810
        }
811
812
        /**
813
         * Elements have been changed at the indices specified by the event's
814
         * getIndices() value.  If the changed data can affect display width (such
815
         * as a text change or a change in icon size), the event's
816
         * <code>isTextChanged()</code> method will return true.
817
         *
818
         * @param e The event
819
         */
820
        public void indicesChanged(ComplexListDataEvent e) {
821
            tabState.indicesChanged(e);
822
        }
823
        
824
        public void intervalAdded (ListDataEvent evt) {
825
            tabState.intervalAdded(evt);
826
        }
827
        
828
        public void intervalRemoved (ListDataEvent evt) {
829
            tabState.intervalRemoved(evt);
830
        }
748
        
831
        
832
        public void contentsChanged(ListDataEvent evt) {
833
            tabState.contentsChanged(evt);
834
        }
749
    } // end of Controller
835
    } // end of Controller
750
    
836
    
751
837
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/AquaEditorTabCellRenderer.java (+5 lines)
Lines 140-145 Link Here
140
                boolean leftmost = ((AquaEditorTabCellRenderer) c).isLeftmost();
140
                boolean leftmost = ((AquaEditorTabCellRenderer) c).isLeftmost();
141
                boolean closing = pressed
141
                boolean closing = pressed
142
                        && ((AquaEditorTabCellRenderer) c).inCloseButton();
142
                        && ((AquaEditorTabCellRenderer) c).inCloseButton();
143
                boolean attention = !pressed && !closing 
144
                        && ((AquaEditorTabCellRenderer) c).isAttention();
143
145
144
                //add in a pixel for rightmost/leftmost so we don't clip off 
146
                //add in a pixel for rightmost/leftmost so we don't clip off 
145
                //antialiasing of the curve
147
                //antialiasing of the curve
Lines 161-166 Link Here
161
                }
163
                }
162
                if (closing) {
164
                if (closing) {
163
                    state |= GenericGlowingChiclet.STATE_CLOSING;
165
                    state |= GenericGlowingChiclet.STATE_CLOSING;
166
                }
167
                if (attention) {
168
                    state |= GenericGlowingChiclet.STATE_ATTENTION;
164
                }
169
                }
165
                chiclet.setArcs(leftarc, rightarc, leftarc, rightarc);
170
                chiclet.setArcs(leftarc, rightarc, leftarc, rightarc);
166
171
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/AquaViewTabDisplayerUI.java (+11 lines)
Lines 205-210 Link Here
205
        if (isSelected(index)) {
205
        if (isSelected(index)) {
206
            state |= GenericGlowingChiclet.STATE_SELECTED;
206
            state |= GenericGlowingChiclet.STATE_SELECTED;
207
        }
207
        }
208
        if (isAttention(index)) {
209
            state |= GenericGlowingChiclet.STATE_ATTENTION;
210
        }
208
211
209
        chiclet.setState(state);
212
        chiclet.setState(state);
210
        chiclet.setBounds(x, y, width, height);
213
        chiclet.setBounds(x, y, width, height);
Lines 299-307 Link Here
299
            Point p = e.getPoint();
302
            Point p = e.getPoint();
300
            int i = getLayoutModel().indexOfPoint(p.x, p.y);
303
            int i = getLayoutModel().indexOfPoint(p.x, p.y);
301
            int closeRectIdx = inCloseIconRect(p);
304
            int closeRectIdx = inCloseIconRect(p);
305
            tabState.setPressed(i);
306
            tabState.setCloseButtonContainsMouse(closeRectIdx);
307
            tabState.setMousePressedInCloseButton(closeRectIdx);
302
            // invoke possible selection change
308
            // invoke possible selection change
303
            if ((i != -1) && closeRectIdx == -1) {
309
            if ((i != -1) && closeRectIdx == -1) {
304
                getSelectionModel().setSelectedIndex(i);
310
                getSelectionModel().setSelectedIndex(i);
311
                tabState.setSelected(i);
305
            }
312
            }
306
            if (shouldReact(e) && closeRectIdx != -1) {
313
            if (shouldReact(e) && closeRectIdx != -1) {
307
                setClosePressed(closeRectIdx);
314
                setClosePressed(closeRectIdx);
Lines 317-322 Link Here
317
        }
324
        }
318
325
319
        public void mouseReleased(MouseEvent e) {
326
        public void mouseReleased(MouseEvent e) {
327
            tabState.setMousePressedInCloseButton(-1);
328
            tabState.setPressed(-1);
320
            // close button must not be active when selection change was
329
            // close button must not be active when selection change was
321
            // triggered by mouse press
330
            // triggered by mouse press
322
            if (shouldReact(e)) {
331
            if (shouldReact(e)) {
Lines 338-347 Link Here
338
347
339
        public void mouseEntered(MouseEvent me) {
348
        public void mouseEntered(MouseEvent me) {
340
            setContainsMouse(true);
349
            setContainsMouse(true);
350
            tabState.setMouseInTabsArea(true);
341
        }
351
        }
342
352
343
        public void mouseExited(MouseEvent me) {
353
        public void mouseExited(MouseEvent me) {
344
            setContainsMouse(false);
354
            setContainsMouse(false);
355
            tabState.setMouseInTabsArea(false);
345
        }
356
        }
346
    } // end of OwnController
357
    } // end of OwnController
347
358
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/BasicSlidingTabDisplayerUI.java (+4 lines)
Lines 127-132 Link Here
127
        return new MouseAdapter() {}; //XXX
127
        return new MouseAdapter() {}; //XXX
128
    }
128
    }
129
    
129
    
130
    public void requestAttention (int tab) {
131
        //not implemented
132
    }
133
    
130
    protected ChangeListener createSelectionListener() {
134
    protected ChangeListener createSelectionListener() {
131
        return new ChangeListener() {
135
        return new ChangeListener() {
132
            private int lastKnownSelection = -1;
136
            private int lastKnownSelection = -1;
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/BasicTabDisplayerUI.java (-12 / +60 lines)
Lines 12-17 Link Here
12
 */
12
 */
13
package org.netbeans.swing.tabcontrol.plaf;
13
package org.netbeans.swing.tabcontrol.plaf;
14
14
15
import javax.swing.event.ListDataEvent;
15
import org.netbeans.swing.tabcontrol.TabData;
16
import org.netbeans.swing.tabcontrol.TabData;
16
import org.netbeans.swing.tabcontrol.TabDisplayer;
17
import org.netbeans.swing.tabcontrol.TabDisplayer;
17
import org.netbeans.swing.tabcontrol.TabbedContainer;
18
import org.netbeans.swing.tabcontrol.TabbedContainer;
Lines 24-29 Link Here
24
import java.awt.geom.Area;
25
import java.awt.geom.Area;
25
import java.awt.image.BufferedImage;
26
import java.awt.image.BufferedImage;
26
import java.beans.PropertyChangeListener;
27
import java.beans.PropertyChangeListener;
28
import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent;
27
29
28
/**
30
/**
29
 * Base class for tab displayer UIs which use cell renderers to display tabs.
31
 * Base class for tab displayer UIs which use cell renderers to display tabs.
Lines 117-122 Link Here
117
        defaultRenderer = null;
119
        defaultRenderer = null;
118
        super.uninstall();
120
        super.uninstall();
119
    }
121
    }
122
    
123
    /** Used by unit tests */
124
    TabState getTabState() {
125
        return tabState;
126
    }
120
127
121
    /**
128
    /**
122
     * Create a TabState instance.  TabState manages the state of tabs - that is, which one
129
     * Create a TabState instance.  TabState manages the state of tabs - that is, which one
Lines 218-223 Link Here
218
        if (rect == null) {
225
        if (rect == null) {
219
            rect = new Rectangle();
226
            rect = new Rectangle();
220
        }
227
        }
228
        if (idx < 0 || idx >= displayer.getModel().size()) {
229
            rect.x = rect.y = rect.width = rect.height = 0;
230
            return rect;
231
        }
221
        rect.x = layoutModel.getX(idx);
232
        rect.x = layoutModel.getX(idx);
222
        rect.y = layoutModel.getY(idx);
233
        rect.y = layoutModel.getY(idx);
223
        rect.width = layoutModel.getW(idx);
234
        rect.width = layoutModel.getW(idx);
Lines 449-454 Link Here
449
    protected void processMouseWheelEvent(MouseWheelEvent e) {
460
    protected void processMouseWheelEvent(MouseWheelEvent e) {
450
        //do nothing
461
        //do nothing
451
    }
462
    }
463
    
464
    public void requestAttention (int tab) {
465
        tabState.addAlarmTab(tab);
466
    }
467
    
452
468
453
    protected void modelChanged() {
469
    protected void modelChanged() {
454
        tabState.clearTransientStates();
470
        tabState.clearTransientStates();
Lines 457-462 Link Here
457
        //sync
473
        //sync
458
        int idx = selectionModel.getSelectedIndex();
474
        int idx = selectionModel.getSelectedIndex();
459
        tabState.setSelected(idx);
475
        tabState.setSelected(idx);
476
        tabState.pruneAlarmTabs(displayer.getModel().size());
460
        super.modelChanged();
477
        super.modelChanged();
461
    }
478
    }
462
479
Lines 501-516 Link Here
501
        }
518
        }
502
519
503
        protected void repaintAllTabs() {
520
        protected void repaintAllTabs() {
504
            getTabsVisibleArea(scratch);
521
            //XXX would be nicer to just repaint the tabs area,
505
            if (scratch.height < displayer.getHeight()) {
522
            //but we also need to repaint below all the tabs in the
506
                //Ensure any gap at the bottom is repainted
523
            //event of activated/deactivated.  No actual reason to
507
                scratch.y = 0;
524
            //repaint the buttons here.
508
                scratch.height = displayer.getHeight();
509
            }
510
/*            displayer.repaint(scratch.x, scratch.y, scratch.width,
511
                              scratch.height);
512
                              */
513
            //XXX optimize this
514
            displayer.repaint();
525
            displayer.repaint();
515
        }
526
        }
516
527
Lines 530-535 Link Here
530
                              scratch.height);
541
                              scratch.height);
531
        }
542
        }
532
    }
543
    }
544
    
545
    protected ModelListener createModelListener() {
546
        return new BasicModelListener();
547
    }    
533
548
534
    private class BasicDisplayerPropertyChangeListener
549
    private class BasicDisplayerPropertyChangeListener
535
            extends DisplayerPropertyChangeListener {
550
            extends DisplayerPropertyChangeListener {
Lines 722-731 Link Here
722
            assert e.getSource() == selectionModel : "Unknown event source: "
737
            assert e.getSource() == selectionModel : "Unknown event source: "
723
                    + e.getSource();
738
                    + e.getSource();
724
            int idx = selectionModel.getSelectedIndex();
739
            int idx = selectionModel.getSelectedIndex();
725
            tabState.setSelected(idx);
740
            tabState.setSelected(idx >= 0 ? idx : -1);
726
            if (idx != -1) {
741
            if (idx >= 0) {
727
                makeTabVisible (selectionModel.getSelectedIndex());
742
                makeTabVisible (selectionModel.getSelectedIndex());
728
            }
743
            }
729
        }
744
        }
730
    }
745
    }
746
    
747
    /**
748
     * Listener on data model which will pass modified indices to the
749
     * TabState object, so it can update which tab indices are flashing in
750
     * "attention" mode, if any.
751
     */
752
    protected class BasicModelListener extends ModelListener {
753
        public void contentsChanged(ListDataEvent e) {
754
            super.contentsChanged(e);
755
            tabState.contentsChanged(e);
756
        }
757
758
        public void indicesAdded(ComplexListDataEvent e) {
759
            super.indicesAdded(e);
760
            tabState.indicesAdded(e);
761
        }
762
763
        public void indicesChanged(ComplexListDataEvent e) {
764
            tabState.indicesChanged(e);
765
        }
766
767
        public void indicesRemoved(ComplexListDataEvent e) {
768
            tabState.indicesRemoved(e);
769
        }
770
771
        public void intervalAdded(ListDataEvent e) {
772
            tabState.intervalAdded(e);
773
        }
774
775
        public void intervalRemoved(ListDataEvent e) {
776
            tabState.intervalRemoved(e);
777
        }
778
    }    
731
}
779
}
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/DefaultTabSelectionModel.java (-2 / +5 lines)
Lines 88-94 Link Here
88
    }
88
    }
89
89
90
    private void adjustSelectionForEvent(ListDataEvent e) {
90
    private void adjustSelectionForEvent(ListDataEvent e) {
91
        if (e.getType() == e.CONTENTS_CHANGED) {
91
        if (e.getType() == e.CONTENTS_CHANGED || sel == -1) {
92
            return;
92
            return;
93
        }
93
        }
94
        int start = e.getIndex0();
94
        int start = e.getIndex0();
Lines 140-145 Link Here
140
    }
140
    }
141
141
142
    public void indicesAdded(ComplexListDataEvent e) {
142
    public void indicesAdded(ComplexListDataEvent e) {
143
        if (sel < 0) return;
143
        int[] indices = e.getIndices();
144
        int[] indices = e.getIndices();
144
        java.util.Arrays.sort(indices);
145
        java.util.Arrays.sort(indices);
145
        int offset = 0;
146
        int offset = 0;
Lines 157-162 Link Here
157
    }
158
    }
158
159
159
    public void indicesRemoved(ComplexListDataEvent e) {
160
    public void indicesRemoved(ComplexListDataEvent e) {
161
        if (sel < 0) return;
160
        int[] indices = e.getIndices();
162
        int[] indices = e.getIndices();
161
        java.util.Arrays.sort(indices);
163
        java.util.Arrays.sort(indices);
162
        int offset = -1;
164
        int offset = -1;
Lines 176-187 Link Here
176
            sel = -1;
178
            sel = -1;
177
            fireStateChanged();
179
            fireStateChanged();
178
        } else if (offset != 0) {
180
        } else if (offset != 0) {
179
            sel += offset;
181
            sel = Math.max( -1, Math.min (sel + offset, -1));
180
            fireStateChanged();
182
            fireStateChanged();
181
        }
183
        }
182
    }
184
    }
183
185
184
    public void indicesChanged(ComplexListDataEvent e) {
186
    public void indicesChanged(ComplexListDataEvent e) {
187
        if (sel < 0) return;
185
        if (e instanceof VeryComplexListDataEvent) { //it always will be
188
        if (e instanceof VeryComplexListDataEvent) { //it always will be
186
189
187
            ArrayDiff dif = ((VeryComplexListDataEvent) e).getDiff();
190
            ArrayDiff dif = ((VeryComplexListDataEvent) e).getDiff();
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/DefaultTabbedContainerUI.java (-2 / +9 lines)
Lines 182-189 Link Here
182
        //#41681, #44278, etc. FOCUS related. the UI needs to be the first listener to be notified
182
        //#41681, #44278, etc. FOCUS related. the UI needs to be the first listener to be notified
183
        // that the selection has changed. Otherwise strange focus effects kick in, eg. when the winsys snapshot gets undated beforehand..
183
        // that the selection has changed. Otherwise strange focus effects kick in, eg. when the winsys snapshot gets undated beforehand..
184
        tabDisplayer.getSelectionModel().addChangeListener(selectionListener);
184
        tabDisplayer.getSelectionModel().addChangeListener(selectionListener);
185
185
    }
186
186
    
187
    /** Used by unit tests */
188
    TabDisplayer getTabDisplayer() {
189
        return tabDisplayer;
187
    }
190
    }
188
191
189
    /** This method is final.  Subclasses which need to provide additional initialization should override
192
    /** This method is final.  Subclasses which need to provide additional initialization should override
Lines 604-609 Link Here
604
        r.x += p.x;
607
        r.x += p.x;
605
        r.y += p.y;
608
        r.y += p.y;
606
        return r;
609
        return r;
610
    }
611
    
612
    public void requestAttention (int tab) {
613
        tabDisplayer.requestAttention (tab);
607
    }
614
    }
608
615
609
    /**
616
    /**
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/GenericGlowingChiclet.java (+7 lines)
Lines 34-39 Link Here
34
    public static final int STATE_SELECTED = 2;
34
    public static final int STATE_SELECTED = 2;
35
    public static final int STATE_ACTIVE = 4;
35
    public static final int STATE_ACTIVE = 4;
36
    public static final int STATE_CLOSING = 8;
36
    public static final int STATE_CLOSING = 8;
37
    public static final int STATE_ATTENTION = 16;
37
38
38
    //Basic apple colors.  Package access so that GtkChiclet can install its own
39
    //Basic apple colors.  Package access so that GtkChiclet can install its own
39
    //defaults if the GTK classes it proxies for colors are not available or
40
    //defaults if the GTK classes it proxies for colors are not available or
Lines 62-67 Link Here
62
        new Color(255, 238, 220), new Color(238, 137, 109),
63
        new Color(255, 238, 220), new Color(238, 137, 109),
63
        new Color(255, 50, 50), new Color(255, 237, 40)};
64
        new Color(255, 50, 50), new Color(255, 237, 40)};
64
65
66
    static Color[] attention = new Color[]{
67
        new Color(255, 255, 220), new Color(238, 237, 109),
68
        new Color(255, 255, 50), new Color(255, 237, 40)};
69
        
65
    private Color upperTop = selectedActive[0];
70
    private Color upperTop = selectedActive[0];
66
    private Color upperBottom = selectedActive[1];
71
    private Color upperBottom = selectedActive[1];
67
    private Color lowerTop = selectedActive[2];
72
    private Color lowerTop = selectedActive[2];
Lines 124-129 Link Here
124
            Color[] nue;
129
            Color[] nue;
125
            if ((state & STATE_CLOSING) != 0) {
130
            if ((state & STATE_CLOSING) != 0) {
126
                nue = closing;
131
                nue = closing;
132
            } else if ((state & STATE_ATTENTION) != 0) {
133
                nue = attention;
127
            } else {
134
            } else {
128
                switch (state) {
135
                switch (state) {
129
                    case STATE_PRESSED | STATE_ACTIVE:
136
                    case STATE_PRESSED | STATE_ACTIVE:
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/MetalEditorTabCellRenderer.java (+14 lines)
Lines 31-36 Link Here
31
    private static final MetalRightClippedTabPainter rightBorder = new MetalRightClippedTabPainter();
31
    private static final MetalRightClippedTabPainter rightBorder = new MetalRightClippedTabPainter();
32
    private static final MetalLeftClippedTabPainter leftBorder = new MetalLeftClippedTabPainter();
32
    private static final MetalLeftClippedTabPainter leftBorder = new MetalLeftClippedTabPainter();
33
33
34
    static final Color ATTENTION_COLOR = new Color(255, 238, 120);
34
    /**
35
    /**
35
     * Creates a new instance of MetalEditorTabCellRenderer
36
     * Creates a new instance of MetalEditorTabCellRenderer
36
     */
37
     */
Lines 129-134 Link Here
129
        public void paintInterior(Graphics g, Component c) {
130
        public void paintInterior(Graphics g, Component c) {
130
            MetalEditorTabCellRenderer mtr = (MetalEditorTabCellRenderer) c;
131
            MetalEditorTabCellRenderer mtr = (MetalEditorTabCellRenderer) c;
131
132
133
            if (mtr.isAttention()) {
134
                g.setColor(ATTENTION_COLOR);
135
            }
136
            
132
            Polygon p = getInteriorPolygon(c);
137
            Polygon p = getInteriorPolygon(c);
133
            g.fillPolygon(p);
138
            g.fillPolygon(p);
134
            Rectangle r = new Rectangle();
139
            Rectangle r = new Rectangle();
Lines 246-251 Link Here
246
251
247
        public void paintInterior(Graphics g, Component c) {
252
        public void paintInterior(Graphics g, Component c) {
248
            Polygon p = getInteriorPolygon(c);
253
            Polygon p = getInteriorPolygon(c);
254
            MetalEditorTabCellRenderer mtr = (MetalEditorTabCellRenderer) c;
255
            if (mtr.isAttention()) {
256
                g.setColor(ATTENTION_COLOR);
257
            }
258
            
249
            g.fillPolygon(p);
259
            g.fillPolygon(p);
250
        }
260
        }
251
261
Lines 340-345 Link Here
340
350
341
        public void paintInterior(Graphics g, Component c) {
351
        public void paintInterior(Graphics g, Component c) {
342
            Polygon p = getInteriorPolygon(c);
352
            Polygon p = getInteriorPolygon(c);
353
            MetalEditorTabCellRenderer mtr = (MetalEditorTabCellRenderer) c;
354
            if (mtr.isAttention()) {
355
                g.setColor(ATTENTION_COLOR);
356
            }
343
            g.fillPolygon(p);
357
            g.fillPolygon(p);
344
        }
358
        }
345
359
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/MetalViewTabDisplayerUI.java (+4 lines)
Lines 196-203 Link Here
196
                                      int width, int height) {
196
                                      int width, int height) {
197
        boolean selected = isSelected(index);
197
        boolean selected = isSelected(index);
198
        boolean highlighted = selected && isActive();
198
        boolean highlighted = selected && isActive();
199
        boolean attention = isAttention (index);
199
        if (highlighted) {
200
        if (highlighted) {
200
            g.setColor(getActBgColor());
201
            g.setColor(getActBgColor());
202
            g.fillRect(x, y, width, height - 3);
203
        } else if (attention) {
204
            g.setColor(MetalEditorTabCellRenderer.ATTENTION_COLOR);
201
            g.fillRect(x, y, width, height - 3);
205
            g.fillRect(x, y, width, height - 3);
202
        } else {
206
        } else {
203
            g.setColor(getInactBgColor());
207
            g.setColor(getInactBgColor());
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/TabState.java (+329 lines)
Lines 12-17 Link Here
12
 */
12
 */
13
package org.netbeans.swing.tabcontrol.plaf;
13
package org.netbeans.swing.tabcontrol.plaf;
14
14
15
import java.awt.event.ActionEvent;
16
import java.awt.event.ActionListener;
17
import java.util.ArrayList;
18
import java.util.Arrays;
19
import java.util.HashSet;
20
import java.util.Iterator;
21
import java.util.List;
22
import java.util.Set;
23
import javax.swing.Timer;
24
import javax.swing.event.ListDataEvent;
25
import org.netbeans.swing.tabcontrol.TabData;
26
import org.netbeans.swing.tabcontrol.event.ArrayDiff;
27
import org.netbeans.swing.tabcontrol.event.ComplexListDataEvent;
28
import org.netbeans.swing.tabcontrol.event.VeryComplexListDataEvent;
29
import org.openide.util.Utilities;
30
15
/**
31
/**
16
 * Used by BasicTabDisplayerUI and its subclasses.
32
 * Used by BasicTabDisplayerUI and its subclasses.
17
 * Tracks and manages the state of tabs, mainly which one currently contains the
33
 * Tracks and manages the state of tabs, mainly which one currently contains the
Lines 142-148 Link Here
142
     */
158
     */
143
    public static final int MOUSE_IN_TABS_AREA = 4096;
159
    public static final int MOUSE_IN_TABS_AREA = 4096;
144
160
161
    /**
162
     * Bitmask indicating that the mouse is inside the close button and has 
163
     * been pressed.
164
     */
145
    public static final int MOUSE_PRESSED_IN_CLOSE_BUTTON = 8192;
165
    public static final int MOUSE_PRESSED_IN_CLOSE_BUTTON = 8192;
166
    
167
    /**
168
     * Bitmask indicating that the tab is in "attention" mode - blinking or
169
     * flashing to get the user's attention.
170
     */
171
    public static final int ATTENTION = 16384;
172
    
146
    /**
173
    /**
147
     * Indicates the last constant defined - renderers that wish to add their
174
     * Indicates the last constant defined - renderers that wish to add their
148
     * own bitmasks should use multiples of this number
175
     * own bitmasks should use multiples of this number
Lines 224-229 Link Here
224
        if (tab == selectedIndex - 1) {
251
        if (tab == selectedIndex - 1) {
225
            result |= BEFORE_SELECTED;
252
            result |= BEFORE_SELECTED;
226
        }
253
        }
254
        if (isAlarmTab(tab)) {
255
            result |= ATTENTION;
256
        }
227
        return result;
257
        return result;
228
    }
258
    }
229
    
259
    
Lines 328-333 Link Here
328
        prev = selectedIndex;
358
        prev = selectedIndex;
329
        selectedIndex = i;
359
        selectedIndex = i;
330
        curr = i;
360
        curr = i;
361
        removeAlarmTab(i);
331
        possibleChange(prev, curr, SELECTED);
362
        possibleChange(prev, curr, SELECTED);
332
        return prev;
363
        return prev;
333
    }
364
    }
Lines 358-363 Link Here
358
        possibleChange(prev, b, ACTIVE);
389
        possibleChange(prev, b, ACTIVE);
359
        return prev;
390
        return prev;
360
    }
391
    }
392
    
393
    private boolean isAlarmTab (int tab) {
394
        return attentionToggle && alarmTabs.contains(new Integer(tab));
395
    }
396
    
397
    private final HashSet alarmTabs = new HashSet(6);
398
    
399
    /** Add a tab to the list of those which should "flash" or otherwise give
400
     * some notification to the user to get their attention */
401
    public final void addAlarmTab (int alarmTab) {
402
        Integer in = new Integer(alarmTab);
403
        boolean added = alarmTabs.contains(in);
404
        boolean wasEmpty = alarmTabs.isEmpty();
405
        if (!added) {
406
            alarmTabs.add (new Integer(alarmTab));
407
            repaintTab (alarmTab);
408
        }
409
        if (wasEmpty) {
410
            startAlarmTimer();
411
            attentionToggle = true;
412
            repaintTab (alarmTab);
413
        }
414
    }
415
    
416
    /** Remove a tab to the list of those which should "flash" or otherwise give
417
     * some notification to the user to get their attention */
418
    public final void removeAlarmTab (int alarmTab) {
419
        Integer in = new Integer(alarmTab);
420
        boolean contained = alarmTabs.contains(in);
421
        if (contained) {
422
            alarmTabs.remove(in);
423
            boolean empty = alarmTabs.isEmpty();
424
            boolean wasAttentionToggled = attentionToggle;
425
            if (alarmTabs.isEmpty()) {
426
                stopAlarmTimer();
427
            }
428
            if (wasAttentionToggled) {
429
                repaintTab(alarmTab);
430
            }
431
        }
432
    }
433
    
434
    private Timer alarmTimer = null;
435
    private boolean attentionToggle = false;
436
    private final void startAlarmTimer() {
437
        if (alarmTimer == null) {
438
            ActionListener al = new ActionListener() {
439
                public void actionPerformed (ActionEvent ae) {
440
                    attentionToggle = !attentionToggle;
441
                    Timer timer = (Timer) ae.getSource();
442
                    for (Iterator i=alarmTabs.iterator(); i.hasNext();) {
443
                        repaintTab (((Integer) i.next()).intValue());
444
                    }
445
                }
446
            };
447
            alarmTimer = new Timer (700, al);
448
            alarmTimer.setRepeats(true);
449
        }
450
        alarmTimer.start();
451
    }
452
    
453
    private final void stopAlarmTimer() {
454
        if (alarmTimer != null && alarmTimer.isRunning()) {
455
            alarmTimer.stop();
456
            attentionToggle = false;
457
            repaintAllTabs(); //XXX optimize
458
        }
459
    }
460
    
461
    boolean hasAlarmTabs() {
462
        return alarmTabs != null && !alarmTabs.isEmpty();
463
    }
464
    
465
    void pruneAlarmTabs(int max) {
466
        if (!hasAlarmTabs()) {
467
            return;
468
        }
469
        for (Iterator i=alarmTabs.iterator(); i.hasNext();) {
470
            if (((Integer) i.next()).intValue() >= max) {
471
                i.remove();
472
            }
473
        }
474
        if (alarmTabs.isEmpty()) {
475
            stopAlarmTimer();
476
        }
477
    }
478
    
479
    int[] getAlarmTabs() {
480
        int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
481
        Arrays.sort(alarms);
482
        return alarms;
483
    }
484
    
485
    //Handling of insertions/deletions where we'll need to update the 
486
    //list of blinking tabs here.
487
    void intervalAdded (ListDataEvent evt) {
488
        if (!hasAlarmTabs()) return;
489
        int start = evt.getIndex0();
490
        int end = evt.getIndex1();
491
        int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
492
        boolean changed = false;
493
        for (int i=0; i < alarms.length; i++) {
494
            if (alarms[i] >= start) {
495
                alarms[i] += (end - start) + 1;
496
                changed = true;
497
            }
498
        }
499
        if (changed) {
500
            alarmTabs.clear();
501
            for (int i=0; i < alarms.length; i++) {
502
                addAlarmTab(alarms[i]);
503
            }
504
        }
505
    }
506
    
507
    void intervalRemoved (ListDataEvent evt) {
508
        if (!hasAlarmTabs()) return;
509
        int start = evt.getIndex0();
510
        int end = evt.getIndex1();
511
        
512
        int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
513
        Arrays.sort(alarms);
514
        
515
        if (end == start) {
516
            //Faster to handle this case separately
517
            boolean changed = true;
518
            for (int i=0; i < alarms.length; i++) {
519
                if (alarms[i] > end) {
520
                    alarms[i]--;
521
                } else if (alarms[i] == end) {
522
                    alarms[i] = -1;
523
                }
524
            }
525
            if (changed) {
526
                alarmTabs.clear();
527
                boolean added = false;
528
                for (int i=0; i < alarms.length; i++) {
529
                    if (alarms[i] != -1) {
530
                        addAlarmTab(alarms[i]);
531
                        added = true;
532
                    }
533
                }
534
                if (!added) {
535
                    stopAlarmTimer();
536
                }
537
            }            
538
            return;
539
        }
540
        
541
        boolean changed = false;
542
        for (int i=0; i < alarms.length; i++) {
543
            if (alarms[i] >= start && alarms[i] <= end) {
544
                alarms[i] = -1;
545
                changed = true;
546
            }
547
        }
548
        for (int i=0; i < alarms.length; i++) {
549
            if (alarms[i] > end) {
550
                alarms[i] -= (end - start) + 1;
551
                changed = true;
552
            }
553
        }
554
        if (changed) {
555
            alarmTabs.clear();
556
            boolean added = false;
557
            for (int i=0; i < alarms.length; i++) {
558
                if (alarms[i] != -1) {
559
                    addAlarmTab(alarms[i]);
560
                    added = true;
561
                }
562
            }
563
            if (!added) {
564
                stopAlarmTimer();
565
            }
566
        }
567
    }
568
    
569
    void indicesAdded (ComplexListDataEvent e) {
570
        if (!hasAlarmTabs()) return;
571
        int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
572
        java.util.Arrays.sort(alarms);
573
574
        int[] indices = e.getIndices();
575
        java.util.Arrays.sort(indices);
576
        
577
        boolean changed = false;
578
        for (int i=0; i < indices.length; i++) {
579
            for (int j=0; j < alarms.length; j++) {
580
                if (alarms[j] >= indices[i]) {
581
                    alarms[j]++;
582
                    changed = true;
583
                }
584
            }
585
        }
586
        if (changed) {
587
            alarmTabs.clear();
588
            for (int i=0; i < alarms.length; i++) {
589
                if (alarms[i] != -1) {
590
                    addAlarmTab(alarms[i]);
591
                }
592
            }
593
        }
594
    }
595
    
596
    void indicesRemoved (ComplexListDataEvent e) {
597
        if (!hasAlarmTabs()) return;
598
        int[] indices = e.getIndices();
599
        java.util.Arrays.sort(indices);
600
        
601
        int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
602
        java.util.Arrays.sort(alarms);
603
        
604
        if (alarms[alarms.length -1] < indices[0]) {
605
            //Some tab removed after the last blinking tab, don't care
606
            return;
607
        }
608
609
        boolean changed = false;
610
        for (int i=0; i < alarms.length; i++) {
611
            //First weed out all deleted alarm tabs
612
            for (int j=0; j < indices.length; j++) {
613
                if (alarms[i] == indices[j]) {
614
                    alarms[i] = -1;
615
                    changed = true;
616
                }
617
            }
618
        }
619
        for (int i=0; i < alarms.length; i++) {
620
            //Now decrement those that remain that are affected
621
            int alarm = alarms[i];
622
            for (int j=0; j < indices.length; j++) {
623
                if (alarm > indices[j]) {
624
                    alarms[i]--;
625
                    changed = true;
626
                }
627
            }
628
        }
629
        
630
        if (changed) {
631
            alarmTabs.clear();
632
            boolean addedSome = false;
633
            for (int i=0; i < alarms.length; i++) {
634
                if (alarms[i] >= 0) {
635
                    addAlarmTab(alarms[i]);
636
                    addedSome = true;
637
                }
638
            }
639
            if (!addedSome) {
640
                stopAlarmTimer();
641
            }
642
        }        
643
        
644
        repaintAllTabs();
645
    }
646
    
647
    void indicesChanged (ComplexListDataEvent e) {
648
        if (!hasAlarmTabs()) return;
649
        if (e instanceof VeryComplexListDataEvent) { //it always will be
650
            VeryComplexListDataEvent ve = (VeryComplexListDataEvent) e;
651
            
652
            ArrayDiff dif = ((VeryComplexListDataEvent) e).getDiff();
653
            
654
            List old = Arrays.asList(dif.getOldData());
655
            List nue = Arrays.asList(dif.getNewData());
656
            
657
            int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
658
            
659
            boolean changed = false;
660
            for (int i=0; i < alarms.length; i++) {
661
                Object o = old.get(alarms[i]);
662
                int idx = nue.indexOf(o);
663
                changed |= idx != alarms[i];
664
                alarms[i] = nue.indexOf(o);
665
            }
666
            if (changed) {
667
                alarmTabs.clear();
668
                boolean addedSome = false;
669
                for (int i=0; i < alarms.length; i++) {
670
                    if (alarms[i] >= 0) {
671
                        addAlarmTab(alarms[i]);
672
                        addedSome = true;
673
                    }
674
                }
675
                if (!addedSome) {
676
                    stopAlarmTimer();
677
                }
678
            }             
679
        }
680
    }
681
682
    
683
    void contentsChanged(ListDataEvent evt) {
684
        if (!hasAlarmTabs()) return;
685
        //Do nothing, just means some text or icons changed
686
    }    
361
687
362
    //Change types
688
    //Change types
363
    /** Change type indicating no change happened (i.e. calling setSelected() with the same value it was previously
689
    /** Change type indicating no change happened (i.e. calling setSelected() with the same value it was previously
Lines 508-513 Link Here
508
                    type = ALL_TABS;
834
                    type = ALL_TABS;
509
                    go = true;
835
                    go = true;
510
                }
836
                }
837
                break;
838
            case ATTENTION:
839
                go = true;
511
        }
840
        }
512
        if (go) {
841
        if (go) {
513
            if (type == ALL_TABS) {
842
            if (type == ALL_TABS) {
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/ToolbarTabDisplayerUI.java (-1 / +5 lines)
Lines 102-108 Link Here
102
            }
102
            }
103
        }
103
        }
104
        return null;
104
        return null;
105
    }    
105
    }  
106
    
107
    public void requestAttention (int tab) {
108
        //not implemented
109
    }
106
    
110
    
107
    protected ChangeListener createSelectionListener() {
111
    protected ChangeListener createSelectionListener() {
108
        return new ChangeListener() {
112
        return new ChangeListener() {
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/WinClassicEditorTabCellRenderer.java (-6 / +20 lines)
Lines 31-36 Link Here
31
    private static final TabPainter rightClip = new WinClassicRightClipPainter();
31
    private static final TabPainter rightClip = new WinClassicRightClipPainter();
32
    private static final TabPainter normal = new WinClassicPainter();
32
    private static final TabPainter normal = new WinClassicPainter();
33
    
33
    
34
    static final Color ATTENTION_COLOR = new Color(255, 238, 120);    
35
    
34
    private static boolean isGenericUI = !"Windows".equals(
36
    private static boolean isGenericUI = !"Windows".equals(
35
        UIManager.getLookAndFeel().getID());
37
        UIManager.getLookAndFeel().getID());
36
38
Lines 135-143 Link Here
135
                ((Graphics2D) g).setPaint(ColorUtil.getGradientPaint(0, 0, getSelGradientColor(), ren.getWidth(), 0, UIManager.getColor(
137
                ((Graphics2D) g).setPaint(ColorUtil.getGradientPaint(0, 0, getSelGradientColor(), ren.getWidth(), 0, UIManager.getColor(
136
                        "TabbedPane.background")));//NOI18N
138
                        "TabbedPane.background")));//NOI18N
137
            } else {
139
            } else {
138
                g.setColor(ren.isSelected() ?
140
                if (!ren.isAttention()) {
139
                           UIManager.getColor("TabbedPane.background") :
141
                    g.setColor(ren.isSelected() ?
140
                           UIManager.getColor("tab_unsel_fill")); //NOI18N
142
                               UIManager.getColor("TabbedPane.background") :
143
                               UIManager.getColor("tab_unsel_fill")); //NOI18N
144
                } else {
145
                    g.setColor(ATTENTION_COLOR);
146
                }
141
            }
147
            }
142
            Polygon p = getInteriorPolygon(c);
148
            Polygon p = getInteriorPolygon(c);
143
            g.fillPolygon(p);
149
            g.fillPolygon(p);
Lines 260-268 Link Here
260
                ((Graphics2D) g).setPaint(ColorUtil.getGradientPaint(0, 0, getSelGradientColor(), ren.getWidth(), 0, UIManager.getColor(
266
                ((Graphics2D) g).setPaint(ColorUtil.getGradientPaint(0, 0, getSelGradientColor(), ren.getWidth(), 0, UIManager.getColor(
261
                        "TabbedPane.background")));//NOI18N
267
                        "TabbedPane.background")));//NOI18N
262
            } else {
268
            } else {
263
                g.setColor(ren.isSelected() ?
269
                if (!ren.isAttention()) {
270
                    g.setColor(ren.isSelected() ?
264
                           UIManager.getColor("TabbedPane.background") :
271
                           UIManager.getColor("TabbedPane.background") :
265
                           UIManager.getColor("tab_unsel_fill")); //NOI18N
272
                           UIManager.getColor("tab_unsel_fill")); //NOI18N
273
                } else {
274
                    g.setColor(ATTENTION_COLOR);
275
                }
266
            }
276
            }
267
            Polygon p = getInteriorPolygon(c);
277
            Polygon p = getInteriorPolygon(c);
268
            g.fillPolygon(p);
278
            g.fillPolygon(p);
Lines 353-361 Link Here
353
                ((Graphics2D) g).setPaint(ColorUtil.getGradientPaint(0, 0, getSelGradientColor(), ren.getWidth(), 0, UIManager.getColor(
363
                ((Graphics2D) g).setPaint(ColorUtil.getGradientPaint(0, 0, getSelGradientColor(), ren.getWidth(), 0, UIManager.getColor(
354
                        "TabbedPane.background")));//NOI18N
364
                        "TabbedPane.background")));//NOI18N
355
            } else {
365
            } else {
356
                g.setColor(ren.isSelected() ?
366
                if (!ren.isAttention()) {
357
                           UIManager.getColor("TabbedPane.background") :
367
                    g.setColor(ren.isSelected() ?
368
                           UIManager.getColor("TabbedPane.background") : //NOI18N
358
                           UIManager.getColor("tab_unsel_fill")); //NOI18N
369
                           UIManager.getColor("tab_unsel_fill")); //NOI18N
370
                } else {
371
                    g.setColor(ATTENTION_COLOR);
372
                }
359
            }
373
            }
360
374
361
            Polygon p = getInteriorPolygon(c);
375
            Polygon p = getInteriorPolygon(c);
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/WinClassicViewTabDisplayerUI.java (+4 lines)
Lines 228-233 Link Here
228
        // background body, colored according to state
228
        // background body, colored according to state
229
        boolean selected = isSelected(index);
229
        boolean selected = isSelected(index);
230
        boolean focused = isFocused(index);
230
        boolean focused = isFocused(index);
231
        boolean attention = isAttention(index);
232
        
231
        Paint result = null;
233
        Paint result = null;
232
        if (focused) {
234
        if (focused) {
233
            result =
235
            result =
Lines 238-243 Link Here
238
                                                       "TabbedPane.background"));
240
                                                       "TabbedPane.background"));
239
        } else if (selected) {
241
        } else if (selected) {
240
            result = UIManager.getColor("TabbedPane.background"); //NOI18N
242
            result = UIManager.getColor("TabbedPane.background"); //NOI18N
243
        } else if (attention) {
244
            result = WinClassicEditorTabCellRenderer.ATTENTION_COLOR;
241
        } else {
245
        } else {
242
            result = UIManager.getColor("tab_unsel_fill");
246
            result = UIManager.getColor("tab_unsel_fill");
243
        }
247
        }
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/WinXPEditorTabCellRenderer.java (-1 / +7 lines)
Lines 252-258 Link Here
252
252
253
    private static final Paint getPaint(int xTop, int yTop, int xBot, int yBot,
253
    private static final Paint getPaint(int xTop, int yTop, int xBot, int yBot,
254
                                        WinXPEditorTabCellRenderer ren) {
254
                                        WinXPEditorTabCellRenderer ren) {
255
        if (ren.isSelected() || (ren.isPressed() && !ren.inCloseButton())) {
255
              
256
        if (!ren.isSelected() && !ren.isPressed() && ren.isAttention()) {
257
            Color a = new Color (255, 255, 128);
258
            Color b = new Color (230, 200, 64);
259
                return ColorUtil.getGradientPaint(xTop, yTop, a, xBot,
260
                                                  yBot, b);
261
        } else if (ren.isSelected() || (ren.isPressed() && !ren.inCloseButton())) {
256
            if (ren.isActive()) {
262
            if (ren.isActive()) {
257
                return ColorUtil.getGradientPaint(xTop, yTop,
263
                return ColorUtil.getGradientPaint(xTop, yTop,
258
                                                  getTopActiveSelectedColor(),
264
                                                  getTopActiveSelectedColor(),
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/WinXPViewTabDisplayerUI.java (+6 lines)
Lines 190-201 Link Here
190
        // background body, colored according to state
190
        // background body, colored according to state
191
        boolean selected = isSelected(index);
191
        boolean selected = isSelected(index);
192
        boolean focused = selected && isActive();
192
        boolean focused = selected && isActive();
193
        boolean attention = isAttention(index);
193
        if (focused) {
194
        if (focused) {
194
            ColorUtil.xpFillRectGradient((Graphics2D) g, x, y, width, height,
195
            ColorUtil.xpFillRectGradient((Graphics2D) g, x, y, width, height,
195
                                         focusFillBrightC, focusFillDarkC);
196
                                         focusFillBrightC, focusFillDarkC);
196
        } else if (selected && isMoreThanOne()) {
197
        } else if (selected && isMoreThanOne()) {
197
            g.setColor(selFillC);
198
            g.setColor(selFillC);
198
            g.fillRect(x, y, width, height);
199
            g.fillRect(x, y, width, height);
200
        } else if (attention && !selected) {
201
            Color a = new Color (255, 255, 128);
202
            Color b = new Color (230, 200, 64);
203
            ColorUtil.xpFillRectGradient((Graphics2D) g, x, y, width, height,
204
                                         a, b);         
199
        } else {
205
        } else {
200
            ColorUtil.xpFillRectGradient((Graphics2D) g, x, y, width, height,
206
            ColorUtil.xpFillRectGradient((Graphics2D) g, x, y, width, height,
201
                                         unselFillBrightC, unselFillDarkC);
207
                                         unselFillBrightC, unselFillDarkC);
(-)core/swing/tabcontrol/test/unit/src/org/netbeans/swing/tabcontrol/DataModelTest.java (-2 / +2 lines)
Lines 200-207 Link Here
200
    public void doTestRemoveContiguous() {
200
    public void doTestRemoveContiguous() {
201
        System.err.println("testRemoveContiguous");
201
        System.err.println("testRemoveContiguous");
202
        int formerSize = mdl.size();
202
        int formerSize = mdl.size();
203
        mdl.removeTabs (10, 20);
203
        mdl.removeTabs (10, 19);
204
        int expectedSize=formerSize-10;
204
        int expectedSize=formerSize - 10;
205
        assertPravda (mdl.size() == expectedSize, "Model size should be " + expectedSize + " after removing 10 items, but is " + mdl.size());
205
        assertPravda (mdl.size() == expectedSize, "Model size should be " + expectedSize + " after removing 10 items, but is " + mdl.size());
206
        try {
206
        try {
207
            _testContentsValid();
207
            _testContentsValid();
(-)core/swing/tabcontrol/test/unit/src/org/netbeans/swing/tabcontrol/plaf/AttentionAndModelChangesTest.java (+554 lines)
Added Link Here
1
/*
2
 *                 Sun Public License Notice
3
 *
4
 * The contents of this file are subject to the Sun Public License
5
 * Version 1.0 (the "License"). You may not use this file except in
6
 * compliance with the License. A copy of the License is available at
7
 * http://www.sun.com/
8
 *
9
 * The Original Code is NetBeans. The Initial Developer of the Original
10
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
11
 * Microsystems, Inc. All Rights Reserved.
12
 */
13
14
package org.netbeans.swing.tabcontrol.plaf;
15
16
import java.awt.BorderLayout;
17
import java.util.ArrayList;
18
import java.util.Arrays;
19
import java.util.HashSet;
20
import java.util.Set;
21
import javax.swing.JFrame;
22
import javax.swing.JLabel;
23
import javax.swing.SwingUtilities;
24
import junit.framework.*;
25
import org.netbeans.swing.tabcontrol.DefaultTabDataModel;
26
import org.netbeans.swing.tabcontrol.TabData;
27
import org.netbeans.swing.tabcontrol.TabDataModel;
28
import org.netbeans.swing.tabcontrol.TabDisplayer;
29
import org.netbeans.swing.tabcontrol.TabbedContainer;
30
31
/**
32
 * TabState stores a list of tabs which are blinking for attention.
33
 * They are stored by index.  This test ensures that when tabs are added
34
 * or removed from the model, that the indices are updated correctly. 
35
 * <p>
36
 * This test also exercises the data model heavily.
37
 *
38
 * @author Tim Boudreau
39
 */
40
public class AttentionAndModelChangesTest extends TestCase {
41
    
42
    public AttentionAndModelChangesTest(java.lang.String testName) {
43
        super(testName);
44
    }
45
    
46
    public static Test suite() {
47
        TestSuite suite = new TestSuite(AttentionAndModelChangesTest.class);
48
        return suite;
49
    }
50
    
51
    TabDataModel mdl = null;
52
    TabData[] origData = null;
53
    TabState state = null;
54
    TabDisplayer displayer = null;
55
    TabbedContainer tab = null;
56
    public void setUp() {
57
        origData = new TabData[13];
58
        for (int i=0; i < origData.length; i++) {
59
            origData[i] = new TabData(new JLabel("TD " + i), null, "TD " + i, "tip");
60
        }
61
        
62
        mdl = new DefaultTabDataModel(origData);
63
 
64
        tab = new TabbedContainer(mdl, TabbedContainer.TYPE_EDITOR);
65
        tab.setActive(true);
66
        JFrame jf = new JFrame();
67
        jf.getContentPane().setLayout (new BorderLayout());
68
        jf.getContentPane().add (tab, BorderLayout.CENTER);
69
        jf.setBounds (20, 20, 400, 200);
70
        jf.show();
71
        jf.toFront();
72
        while (!jf.isShowing()) {
73
            try {
74
                Thread.currentThread().sleep(50);
75
            } catch (InterruptedException e) {
76
                fail (e.toString());
77
            }
78
        }
79
        displayer = ((DefaultTabbedContainerUI) tab.getUI()).getTabDisplayer();
80
        BasicTabDisplayerUI ui = (BasicTabDisplayerUI) displayer.getUI();
81
        state = ui.getTabState();
82
    }
83
84
    private void requestAttention (final int i) throws Exception  {
85
        SwingUtilities.invokeAndWait (new Runnable() {
86
            public void run() {
87
                tab.requestAttention(i);
88
            }
89
        });
90
    }
91
    
92
    private void assertAtt (final int[] i) throws Exception  {
93
        Arrays.sort (i);
94
        int[] att = state.getAlarmTabs();
95
        assertTrue ("Expected attention tabs to be " 
96
            + a2s(i) + " but they are " + a2s(att), 
97
            Arrays.equals(i, att));
98
    }
99
100
    private void assertNotAtt (final int[] i) throws Exception {
101
        SwingUtilities.invokeAndWait (new Runnable() {
102
            public void run() {
103
                Arrays.sort (i);
104
                int[] att = state.getAlarmTabs();
105
                assertFalse ("Expected attention tabs NOT to be " 
106
                    + a2s(i) + " but they are " + a2s(att), 
107
                    Arrays.equals(i, att));
108
            }
109
        });
110
    }
111
    
112
    private static String a2s (int[] ints) {
113
        if (ints == null) {
114
            return "null";
115
        }
116
        if (ints.length == 0) {
117
            return "[]";
118
        }
119
        StringBuffer sb = new StringBuffer();
120
        for (int i=0; i < ints.length; i++) {
121
            sb.append (ints[i]);
122
            if (i != ints.length -1) {
123
                sb.append(',');
124
            }
125
        }
126
        return sb.toString();
127
    }
128
129
    public void testRequestAttention () throws Exception {
130
        System.out.println("testRequestAttention");
131
        requestAttention (3);
132
        requestAttention (5);
133
        assertAtt(new int[] {3, 5});
134
    }
135
    
136
    public void testRemoveSingleInBetween() throws Exception {
137
        System.out.println("testRemoveSingleInBetween");
138
        requestAttention(3);
139
        requestAttention(5);
140
        mdl.removeTab(4);
141
        assertAtt(new int[] {3, 4});
142
    }
143
    
144
    public void testRemoveSingleBefore() throws Exception {
145
        System.out.println("testRemoveSingleBefore");
146
        requestAttention(3);
147
        requestAttention(5);
148
        mdl.removeTab(2);
149
        assertAtt(new int[] {2, 4});
150
    }
151
    
152
153
    public void testRemoveSingleAfter() throws Exception {
154
        System.out.println("testRemoveSingleAfter");
155
        requestAttention(3);
156
        requestAttention(5);
157
        mdl.removeTab(6);
158
        assertAtt(new int[] {3, 5});
159
        mdl.removeTab(10);
160
        assertAtt(new int[] {3, 5});
161
    }
162
    
163
    public void testRemoveSingleFirst() throws Exception {
164
        System.out.println("testRemoveSingleFirst");
165
        requestAttention(3);
166
        requestAttention(5);
167
        mdl.removeTab(3);
168
        assertAtt(new int[] {4});
169
    }
170
    
171
172
    public void testRemoveSingleSecond() throws Exception {
173
        System.out.println("testRemoveSingleSecond");
174
        requestAttention(3);
175
        requestAttention(5);
176
        mdl.removeTab(5);
177
        assertAtt(new int[] {3});
178
    }
179
    
180
    public void testAddSingleBefore() throws Exception {
181
        System.out.println("testAddSingleBefore");
182
        requestAttention(3);
183
        requestAttention(5);
184
        TabData td = new TabData (new JLabel("Added"), null, "Added", "tip");
185
        mdl.addTab(1, td);
186
        assertAtt(new int[] {4, 6});
187
    }
188
    
189
    public void testAddSingleBetween() throws Exception {
190
        System.out.println("testAddSingleBetween");
191
        requestAttention(3);
192
        requestAttention(5);
193
        TabData td = new TabData (new JLabel("Added"), null, "Added", "tip");
194
        mdl.addTab(4, td);
195
        assertAtt(new int[] {3, 6});
196
    }
197
    
198
    public void testAddSingleAt() throws Exception {
199
        System.out.println("testAddSingleAt");
200
        requestAttention(3);
201
        requestAttention(5);
202
        TabData td = new TabData (new JLabel("Added"), null, "Added", "tip");
203
        mdl.addTab(3, td);
204
        assertAtt(new int[] {4, 6});
205
    }    
206
    
207
    public void testAddSingleAfter() throws Exception {
208
        System.out.println("testAddSingleAfter");
209
        requestAttention(3);
210
        requestAttention(5);
211
        TabData td = new TabData (new JLabel("Added"), null, "Added", "tip");
212
        mdl.addTab(7, td);
213
        assertAtt(new int[] {3, 5});
214
    }
215
    
216
    public void testAddSingleAtEnd() throws Exception {
217
        System.out.println("testAddSingleAtEnd");
218
        requestAttention(3);
219
        requestAttention(5);
220
        TabData td = new TabData (new JLabel("Added"), null, "Added", "tip");
221
        mdl.addTab(5, td);
222
        assertAtt(new int[] {3, 6});
223
    }
224
    
225
    public void testAddMultipleBefore() throws Exception {
226
        System.out.println("testAddMultipleBefore");
227
        requestAttention(3);
228
        requestAttention(5);
229
        TabData att1 = mdl.getTab(3);
230
        TabData att2 = mdl.getTab(5);
231
232
        TabData td1 = new TabData (new JLabel("Added 1"), null, "Added 1", "tip");
233
        TabData td2 = new TabData (new JLabel("Added 2"), null, "Added 2", "tip");
234
        mdl.addTabs(1, new TabData[] {td1, td2});
235
        assertAtt(new int[] {5, 7});
236
237
        int[] tabs = state.getAlarmTabs();
238
        assertSame ("First attention tab should be " + att1 + " not " + mdl.getTab(tabs[0]), att1, mdl.getTab(tabs[0]));
239
        assertSame ("Second attention tab should be " + att2 + " not " + mdl.getTab(tabs[1]), att2, mdl.getTab(tabs[1]));
240
    }
241
    
242
243
    public void testAddMultipleAfter() throws Exception {
244
        System.out.println("testAddMultipleAfter");
245
        requestAttention(3);
246
        requestAttention(5);
247
        TabData td1 = new TabData (new JLabel("Added 1"), null, "Added 1", "tip");
248
        TabData td2 = new TabData (new JLabel("Added 2"), null, "Added 2", "tip");
249
        mdl.addTabs(7, new TabData[] {td1, td2});
250
        assertAtt(new int[] {3, 5});
251
    }    
252
    
253
    public void testAddMultipleBetween() throws Exception {
254
        System.out.println("testAddMultipleBetween");
255
        requestAttention(3);
256
        requestAttention(5);
257
        TabData att1 = mdl.getTab(3);
258
        TabData att2 = mdl.getTab(5);
259
260
        TabData td1 = new TabData (new JLabel("Added 1"), null, "Added 1", "tip");
261
        TabData td2 = new TabData (new JLabel("Added 2"), null, "Added 2", "tip");
262
        mdl.addTabs(4, new TabData[] {td1, td2});
263
        assertAtt(new int[] {3, 7});
264
265
        int[] tabs = state.getAlarmTabs();
266
        assertSame ("First attention tab should be " + att1 + " not " + mdl.getTab(tabs[0]), att1, mdl.getTab(tabs[0]));
267
        assertSame ("Second attention tab should be " + att2 + " not " + mdl.getTab(tabs[1]), att2, mdl.getTab(tabs[1]));
268
    }
269
    
270
    
271
    public void testRemoveMultipleBetween() throws Exception {
272
        System.out.println("testRemoveMultipleBetween");
273
        requestAttention(3);
274
        requestAttention(6);
275
        TabData att1 = mdl.getTab(3);
276
        TabData att2 = mdl.getTab(6);
277
278
        int sz = mdl.size();
279
        mdl.removeTabs(4, 5);
280
        assertTrue ("After removing tabs 4 and 5, model size should be 2 smaller - was " + sz + " is " + mdl.size(), mdl.size() == sz-2);
281
282
        assertAtt (new int[] {3, 4});
283
284
        int[] tabs = state.getAlarmTabs();
285
        System.out.println("Alarm tabs are " + tabs[0] + "," + tabs[1]);
286
        System.err.println("First attention tab " + mdl.getTab(tabs[0]));
287
        System.err.println("Second attention tab " + mdl.getTab(tabs[1]));
288
        assertSame ("First attention tab should be " + att1 + " not " + mdl.getTab(tabs[0]), att1, mdl.getTab(tabs[0]));
289
        assertSame ("Second attention tab should be " + att2 + " not " + mdl.getTab(tabs[1]), att2, mdl.getTab(tabs[1]));
290
    }
291
    
292
    public void testRemoveMultipleBefore() throws Exception {
293
        System.out.println("testRemoveMultipleBefore");
294
        requestAttention(3);
295
        requestAttention(6);
296
        TabData att1 = mdl.getTab(3);
297
        TabData att2 = mdl.getTab(6);
298
        int sz = mdl.size();
299
        
300
        mdl.removeTabs(1, 2);
301
        
302
        assertTrue ("After removing tabs 1 and 2, model size should be 2 smaller - was " + sz + " is " + mdl.size(), mdl.size() == sz-2);
303
        assertAtt (new int[] {1, 4});
304
        
305
        int[] tabs = state.getAlarmTabs();
306
        assertSame ("First attention tab should be " + att1 + " not " + mdl.getTab(tabs[0]), att1, mdl.getTab(tabs[0]));
307
        assertSame ("Second attention tab should be " + att2 + " not " + mdl.getTab(tabs[1]), att2, mdl.getTab(tabs[1]));
308
    }
309
310
    public void testRemoveMultipleAfter() throws Exception {
311
        System.out.println("testRemoveMultipleAfter");
312
        requestAttention(3);
313
        requestAttention(6);
314
        mdl.removeTabs(7, 10);
315
        assertAtt (new int[] {3, 6});
316
    }
317
    
318
    public void testRemoveMultipleIncluding() throws Exception {
319
        System.out.println("testRemoveMultipleIncluding");
320
        requestAttention(3);
321
        requestAttention(6);
322
        mdl.removeTabs(6, 10);
323
        assertAtt (new int[] {3});
324
    }    
325
    
326
    public void testRemoveMultipleInclusive() throws Exception {
327
        System.out.println("testRemoveMultipleInclusive");
328
        requestAttention(3);
329
        requestAttention(6);
330
        mdl.removeTabs(2, 7);
331
        assertAtt (new int[0]);
332
    }        
333
334
    public void testAddDiscontiguousBefore() throws Exception {
335
        System.out.println("testAddDiscontiguousBefore");
336
        requestAttention(7);
337
        requestAttention(9);
338
        TabData td1 = new TabData (new JLabel("Added 1"), null, "Added 1", "tip");
339
        TabData td2 = new TabData (new JLabel("Added 2"), null, "Added 2", "tip");
340
        TabData td3 = new TabData (new JLabel("Added 3"), null, "Added 3", "tip");
341
        mdl.addTabs (new int[] { 1, 3, 5}, new TabData[] {td1, td2, td3});
342
        assertAtt (new int[] {10, 12});
343
    }
344
    
345
    public void testRemoveDiscontiguousBefore() throws Exception {
346
        System.out.println("testRemoveDiscontiguousBefore");
347
        requestAttention(7);
348
        requestAttention(9);
349
        mdl.removeTabs (new int[] {1,3,5});
350
        assertAtt (new int[] {4, 6});
351
    }
352
    
353
    public void testRemoveDiscontiguousAfter() throws Exception {
354
        System.out.println("testRemoveDiscontiguousAfter");
355
        requestAttention(5);
356
        requestAttention(7);
357
        mdl.removeTabs (new int[] {8,10,11});
358
        assertAtt (new int[] {5, 7});
359
    }
360
    
361
362
    public void testAddDiscontiguousBeforeAndBetween() throws Exception {
363
        System.out.println("testAddDiscontiguousBeforeAndBetween");
364
        requestAttention(7);
365
        requestAttention(9);
366
        TabData att1 = mdl.getTab(7);
367
        TabData att2 = mdl.getTab(9);
368
        
369
        TabData td1 = new TabData (new JLabel("Added 1"), null, "Added 1", "tip");
370
        TabData td2 = new TabData (new JLabel("Added 2"), null, "Added 2", "tip");
371
        TabData td3 = new TabData (new JLabel("Added 3"), null, "Added 3", "tip");
372
        mdl.addTabs (new int[] {1, 3, 8}, new TabData[] {td1, td2, td3});
373
        assertAtt (new int[] {10, 12});
374
        
375
        int[] tabs = state.getAlarmTabs();
376
        assertSame ("First attention tab should be " + att1 + " not " + mdl.getTab(tabs[0]), att1, mdl.getTab(tabs[0]));
377
        assertSame ("Second attention tab should be " + att2 + " not " + mdl.getTab(tabs[1]), att2, mdl.getTab(tabs[1]));
378
    }
379
380
    public void testRemoveDiscontiguousBeforeAndBetween() throws Exception {
381
        System.out.println("testRemoveDiscontiguousBeforeAndBetween");
382
        requestAttention(7);
383
        requestAttention(9);
384
        TabData att1 = mdl.getTab(7);
385
        TabData att2 = mdl.getTab(9);
386
        mdl.removeTabs (new int[] {1,3,8});
387
        assertAtt (new int[] {5, 6});
388
        int[] tabs = state.getAlarmTabs();
389
        assertSame ("First attention tab should be " + att1 + " not " + mdl.getTab(tabs[0]), att1, mdl.getTab(tabs[0]));
390
        assertSame ("Second attention tab should be " + att2 + " not " + mdl.getTab(tabs[1]), att2, mdl.getTab(tabs[1]));
391
    }
392
393
    public void testRemoveDiscontiguousBeforeAndBetweenIncludingOne() throws Exception {
394
        System.out.println("testRemoveDiscontiguousBeforeAndBetweenIncludingOne");
395
        requestAttention(7);
396
        requestAttention(9);
397
        TabData att1 = mdl.getTab(7);
398
        TabData att2 = mdl.getTab(9);
399
        mdl.removeTabs (new int[] {1,3,7});
400
        assertAtt (new int[] {6});
401
    }
402
    
403
    public void testReorderComplex() throws Exception {
404
        System.out.println("testReorderComplex");
405
        requestAttention(7);
406
        requestAttention(9);
407
        TabData att1 = mdl.getTab(7);
408
        TabData att2 = mdl.getTab(9);
409
410
        TabData[] data = (TabData[]) mdl.getTabs().toArray(new TabData[mdl.size()]);
411
        TabData[] nue = new TabData[data.length];
412
        for (int i=data.length-1; i >=0; i--) {
413
            nue [data.length-(i+1)] = data[i];
414
        }
415
        mdl.setTabs(nue);
416
        int[] tabs = state.getAlarmTabs();
417
        Arrays.sort(tabs);
418
        assertSame ("First attention tab should be " + att2 + " not " + mdl.getTab(tabs[0]), att2, mdl.getTab(tabs[0]));
419
        assertSame ("Second attention tab should be " + att1 + " not " + mdl.getTab(tabs[1]), att1, mdl.getTab(tabs[1]));
420
    }
421
    
422
    public void testReplaceComplex() throws Exception {
423
        System.out.println("testReplaceComplex");
424
        requestAttention(7);
425
        requestAttention(9);
426
427
        TabData[] data = (TabData[]) mdl.getTabs().toArray(new TabData[mdl.size()]);
428
        data[7] = new TabData (new JLabel("foo"), null, "foo", "foo");
429
        mdl.setTabs(data);
430
        
431
        assertAtt(new int[] {9});
432
        
433
        data[9] = new TabData (new JLabel("goo"), null, "goo", "goo");
434
        mdl.setTabs(data);
435
        assertAtt(new int[0]);
436
    }
437
    
438
    public void testRemoveComplex() throws Exception {
439
        System.out.println("testRemoveComplex");
440
        requestAttention(7);
441
        requestAttention(9);
442
        TabData att1 = mdl.getTab(7);
443
        TabData att2 = mdl.getTab(9);
444
445
        TabData[] data = (TabData[]) mdl.getTabs().toArray(new TabData[mdl.size()]);
446
        TabData[] nue = new TabData[data.length-1];
447
        int ct = 0;
448
        for (int i=0; i < data.length; i++) {
449
            nue [ct] = data[i];
450
            if (i != 7) {
451
                ct++;
452
            }
453
        }
454
        mdl.setTabs(nue);
455
        int[] tabs = state.getAlarmTabs();
456
        
457
        assertTrue (tabs.length ==1);
458
        assertTrue (tabs[0] == 8);
459
        assertSame (mdl.getTab(tabs[0]), att2);
460
    }
461
    
462
463
    public void testAddComplex() throws Exception {
464
        System.out.println("testAddComplex");
465
        requestAttention(7);
466
        requestAttention(9);
467
        TabData att1 = mdl.getTab(7);
468
        TabData att2 = mdl.getTab(9);
469
470
        TabData[] data = (TabData[]) mdl.getTabs().toArray(new TabData[mdl.size()]);
471
        
472
        ArrayList al = new ArrayList (Arrays.asList(data));
473
        al.add (8, new TabData(new JLabel("boo"), null, "boo", "boo"));
474
        al.add (2, new TabData(new JLabel("moo"), null, "moo", "moo"));
475
        
476
        TabData[] nue = (TabData[]) al.toArray(new TabData[0]);
477
        
478
        mdl.setTabs(nue);
479
        int[] tabs = state.getAlarmTabs();
480
        Arrays.sort(tabs);
481
        assertSame ("First attention tab should be " + att1 + " not " + mdl.getTab(tabs[0]), att1, mdl.getTab(tabs[0]));
482
        assertSame ("Second attention tab should be " + att2 + " not " + mdl.getTab(tabs[1]), att2, mdl.getTab(tabs[1]));
483
    }    
484
    
485
    //Make sure (non)exceptional case of only 1 tab works
486
    
487
    private void makeSingle() throws Exception {
488
        SwingUtilities.invokeAndWait(new Runnable() {
489
           public void run() {
490
               TabData[] td = new TabData[] {
491
                   new TabData (new JLabel("Single"), null, "single", "single")
492
               };
493
               mdl.setTabs(td);
494
               state.addAlarmTab(0);
495
               assertTrue (state.getAlarmTabs().length == 1);
496
           } 
497
        });
498
        Thread.currentThread().sleep(50);
499
    }
500
    
501
    public void testHandleSingle1() throws Exception {
502
        System.out.println("testHandleSingle1");
503
        makeSingle();
504
        
505
        mdl.removeTab(0);
506
        assertAtt (new int[0]);
507
    }
508
509
    public void testHandleSingle2() throws Exception {
510
        System.out.println("testHandleSingle2");
511
        makeSingle();
512
        mdl.removeTabs(0, 0);
513
        assertAtt (new int[0]);
514
    }
515
516
    public void testHandleSingle3() throws Exception {
517
        System.out.println("testHandleSingle3");
518
        makeSingle();
519
        mdl.removeTabs(new int[] {0});
520
        assertAtt (new int[0]);
521
    }
522
    
523
    public void testAddSingle1() throws Exception {
524
        System.out.println("testAddSingle1");
525
        makeSingle();
526
        mdl.addTab(0, new TabData(new JLabel("foo"), null, "foo", "foo"));
527
        assertTrue ("Size should be 2", mdl.size() == 2);
528
        assertAtt(new int[] {1});
529
    }    
530
    
531
    public void testAddSingle2() throws Exception {
532
        System.out.println("testAddSingle2");
533
        makeSingle();
534
        mdl.addTabs(0, new TabData[] {new TabData(new JLabel("foo"), null, "foo", "foo")});
535
        assertTrue ("Size should be 2", mdl.size() == 2);
536
        assertAtt(new int[] {1});
537
    }    
538
539
    public void testAddSingle3() throws Exception {
540
        System.out.println("testAddSingle3");
541
        makeSingle();
542
        mdl.addTabs(new int[] {0}, new TabData[] {new TabData(new JLabel("foo"), null, "foo", "foo")});
543
        assertTrue ("Size should be 2", mdl.size() == 2);
544
        assertAtt(new int[] {1});
545
    }        
546
    
547
    public void testAddSingle4() throws Exception {
548
        System.out.println("testAddSingle4");
549
        makeSingle();
550
        mdl.addTabs(new int[] {1}, new TabData[] {new TabData(new JLabel("foo"), null, "foo", "foo")});
551
        assertTrue ("Size should be 2", mdl.size() == 2);
552
        assertAtt(new int[] {0});
553
    }    
554
}
(-)core/swing/tabcontrol/test/unit/src/org/netbeans/swing/tabcontrol/plaf/TabStateTest.java (-7 lines)
Lines 323-333 Link Here
323
    }
323
    }
324
    
324
    
325
    private int policy = 0;
325
    private int policy = 0;
326
327
    
328
    // TODO add test methods here, they have to start with 'test' name.
329
    // for example:
330
    // public void testHello() {}
331
    
332
    
333
}
326
}

Return to bug 48811