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/SlidingButton.java (-1 / +53 lines)
Lines 12-21 Link Here
12
 */
12
 */
13
package org.netbeans.swing.tabcontrol;
13
package org.netbeans.swing.tabcontrol;
14
14
15
import java.awt.Color;
15
import java.awt.Component;
16
import java.awt.Component;
16
import java.awt.Insets;
17
import java.awt.Insets;
17
import java.awt.event.ActionEvent;
18
import java.awt.event.ActionEvent;
18
import java.awt.event.ActionListener;
19
import java.awt.event.ActionListener;
20
import javax.swing.Timer;
19
import javax.swing.JToggleButton;
21
import javax.swing.JToggleButton;
20
import javax.swing.SwingConstants;
22
import javax.swing.SwingConstants;
21
import javax.swing.UIManager;
23
import javax.swing.UIManager;
Lines 42-47 Link Here
42
    private int orientation;
44
    private int orientation;
43
    /** Asociated component which actually slides from this button */
45
    /** Asociated component which actually slides from this button */
44
    private Component component;
46
    private Component component;
47
    
48
    private TabData data;
45
        
49
        
46
    /** Create a new button representing TabData from the model.
50
    /** Create a new button representing TabData from the model.
47
     *
51
     *
Lines 66-72 Link Here
66
        setBorderPainted(false);
70
        setBorderPainted(false);
67
//        setHorizontalTextPosition(SwingConstants.);
71
//        setHorizontalTextPosition(SwingConstants.);
68
//        setVerticalTextPosition(SwingConstants.CENTER);
72
//        setVerticalTextPosition(SwingConstants.CENTER);
69
        
73
        this.data = buttonData;
70
        // note, updateUI() is called from superclass constructor
74
        // note, updateUI() is called from superclass constructor
71
    }
75
    }
72
76
Lines 77-82 Link Here
77
81
78
    public void removeNotify() {
82
    public void removeNotify() {
79
        super.removeNotify();
83
        super.removeNotify();
84
        setBlinking(false);
80
        //XXX register with tooltip manager
85
        //XXX register with tooltip manager
81
    }
86
    }
82
    
87
    
Lines 100-105 Link Here
100
    /** Returns orinetation of this button */
105
    /** Returns orinetation of this button */
101
    public int getOrientation() {
106
    public int getOrientation() {
102
        return orientation;
107
        return orientation;
108
    }
109
    
110
    public boolean isBlinking() {
111
        return blinkState;
112
    }
113
    
114
    private Timer blinkTimer = null;
115
    private boolean blinkState = false;
116
    public void setBlinking (boolean val) {
117
        if (!val && blinkTimer != null) {
118
            blinkTimer.stop();
119
            blinkTimer = null;
120
            boolean wasBlinkState = blinkState;
121
            blinkState = false;
122
            if (wasBlinkState) {
123
                repaint();
124
            }
125
        } else if (val && blinkTimer == null) {
126
            blinkTimer = new Timer(700, new BlinkListener());
127
            blinkState = true;
128
            blinkTimer.start();
129
            repaint();
130
        }
131
    }
132
    
133
    private class BlinkListener implements ActionListener {
134
        public void actionPerformed (ActionEvent ae) {
135
            blinkState = !blinkState;
136
            repaint();
137
        }
138
    }
139
    
140
    /**
141
     * Used by the UI to determine whether to use the blink
142
     * color or the regular color
143
     */
144
    public final boolean isBlinkState() {
145
        return blinkState;
146
    }
147
    
148
    public final Color getBackground() {
149
        return isBlinkState() ? 
150
            new Color(252, 250, 244) : super.getBackground();
151
    }
152
    
153
    public TabData getData() {
154
        return data;
103
    }
155
    }
104
    
156
    
105
}
157
}
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/SlidingButtonUI.java (-1 / +1 lines)
Lines 210-216 Link Here
210
        Insets margin = b.getMargin();
210
        Insets margin = b.getMargin();
211
        
211
        
212
        g.fillRect(insets.left - margin.left,
212
        g.fillRect(insets.left - margin.left,
213
        insets.top - margin.top,
213
            insets.top - margin.top,
214
        size.width - (insets.left-margin.left) - (insets.right - margin.right),
214
        size.width - (insets.left-margin.left) - (insets.right - margin.right),
215
        size.height - (insets.top-margin.top) - (insets.bottom - margin.bottom));
215
        size.height - (insets.top-margin.top) - (insets.bottom - margin.bottom));
216
    }
216
    }
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/TabDisplayer.java (+25 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
    /**
338
     * Cause the specified tab to flash or otherwise call attention to itself
339
     * without changing selection or focus.  Supported by VIEW and EDITOR type
340
     * UIs.
341
     */
342
    public final void requestAttention (int tab) {
343
        getUI().requestAttention(tab);
344
    }
345
    
346
    /**
347
     * Cause a tab, if blinking, to stop.
348
     */
349
    public final void cancelRequestAttention (int tab) {
350
        getUI().cancelRequestAttention (tab);
351
    }
352
    
353
    public final boolean requestAttention (TabData data) {
354
        int idx = getModel().indexOf(data);
355
        boolean result = idx >= 0;
356
        if (result) {
357
            requestAttention (idx);
358
        }
359
        return result;
360
    }
336
361
337
    /**
362
    /**
338
     * Accessor only for TabDisplayerUI when installing the UI
363
     * Accessor only for TabDisplayerUI when installing the UI
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/TabDisplayerUI.java (+4 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
    protected abstract void requestAttention (int tab);
189
    
190
    protected abstract void cancelRequestAttention (int tab);
187
191
188
}
192
}
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/TabbedContainer.java (+32 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 final void requestAttention (int tab) {
565
        getUI().requestAttention(tab);
566
    }
567
    
568
    public final void cancelRequestAttention (int tab) {
569
        getUI().cancelRequestAttention(tab);
570
    }
571
    
572
    /**
573
     * Cause the specified tab to blink or otherwisse suggest that the user should
574
     * click it.
575
     */
576
    public final boolean requestAttention (TabData data) {
577
        int idx = getModel().indexOf(data);
578
        boolean result = idx >= 0;
579
        if (result) {
580
            requestAttention (idx);
581
        }
582
        return result;
583
    }    
584
    
585
    public final void cancelRequestAttention (TabData data) {
586
        int idx = getModel().indexOf(data);
587
        if (idx != -1) {
588
            cancelRequestAttention(idx);
589
        }
590
    }
559
591
560
    /**
592
    /**
561
     * Determine if this component thinks it is &quot;active&quot;, which
593
     * Determine if this component thinks it is &quot;active&quot;, which
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/TabbedContainerUI.java (+4 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
    protected abstract void requestAttention (int tab);
203
    
204
    protected abstract void cancelRequestAttention (int tab);
205
    
202
}
206
}
(-)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/AbstractViewTabDisplayerUI.java (-3 / +102 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-545 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
            if (tab < 0 || tab > displayer.getModel().size()) {
565
                //This can happen because we can be notified
566
                //of a change on a tab that has just been removed
567
                //from the model
568
                return;
569
            }
570
            Rectangle r = getTabRect(tab, null);
571
            displayer.repaint(r);
572
        }
573
    }
574
    
575
    /**
576
     * Determine if the tab should be flashing
577
     */
578
    protected boolean isAttention (int tab) {
579
        return (tabState.getState(tab) & TabState.ATTENTION) != 0;
580
    }
581
    
582
583
    protected void requestAttention (int tab) {
584
        tabState.addAlarmTab(tab);
585
    }    
586
    
587
    protected void cancelRequestAttention (int tab) {
588
        tabState.removeAlarmTab(tab);
589
    }
535
590
536
    /**
591
    /**
537
     * Listen to mouse events and handles selection behaviour and close icon
592
     * Listen to mouse events and handles selection behaviour and close icon
538
     * button behaviour.
593
     * button behaviour.
539
     */
594
     */
540
    abstract class Controller extends MouseAdapter
595
    abstract class Controller extends MouseAdapter
541
            implements MouseMotionListener, ChangeListener, PropertyChangeListener, ActionListener {
596
            implements MouseMotionListener, ChangeListener, PropertyChangeListener, ActionListener, ComplexListDataListener {
542
597
598
        //XXX should be able to replace most of this class with 
599
        //tabState - we're already using it to manage the blinking state
600
                
543
        /**
601
        /**
544
         * index of tab whose close icon currently pressed, -1 otherwise
602
         * index of tab whose close icon currently pressed, -1 otherwise
545
         */
603
         */
Lines 596-606 Link Here
596
        public void mousePressed(MouseEvent e) {
654
        public void mousePressed(MouseEvent e) {
597
            Point p = e.getPoint();
655
            Point p = e.getPoint();
598
            int i = getLayoutModel().indexOfPoint(p.x, p.y);
656
            int i = getLayoutModel().indexOfPoint(p.x, p.y);
657
            tabState.setPressed(i);
599
            SingleSelectionModel sel = getSelectionModel();
658
            SingleSelectionModel sel = getSelectionModel();
600
            selectionChanged = i != sel.getSelectedIndex();
659
            selectionChanged = i != sel.getSelectedIndex();
601
            // invoke possible selection change
660
            // invoke possible selection change
602
            if ((i != -1) || !selectionChanged) {
661
            if ((i != -1) || !selectionChanged) {
603
                getSelectionModel().setSelectedIndex(i);
662
                getSelectionModel().setSelectedIndex(i);
663
                tabState.setSelected(i);
604
            } 
664
            } 
605
            // update pressed state
665
            // update pressed state
606
            if (shouldReact(e) && !selectionChanged) {
666
            if (shouldReact(e) && !selectionChanged) {
Lines 632-637 Link Here
632
        public void mouseReleased(MouseEvent e) {
692
        public void mouseReleased(MouseEvent e) {
633
            // close button must not be active when selection change was
693
            // close button must not be active when selection change was
634
            // triggered by mouse press
694
            // triggered by mouse press
695
            tabState.setPressed(-1);
635
            if (shouldReact(e) && !selectionChanged) {
696
            if (shouldReact(e) && !selectionChanged) {
636
                setClosePressed(-1);
697
                setClosePressed(-1);
637
                Point point = e.getPoint();
698
                Point point = e.getPoint();
Lines 721-726 Link Here
721
            // sync of indexes
782
            // sync of indexes
722
            int oldValue = mouseInCloseButton;
783
            int oldValue = mouseInCloseButton;
723
            mouseInCloseButton = isNow;
784
            mouseInCloseButton = isNow;
785
            tabState.setCloseButtonContainsMouse(isNow);
724
            if (isNow == -1) {
786
            if (isNow == -1) {
725
                // exit from close area
787
                // exit from close area
726
                TabLayoutModel tlm = getLayoutModel();
788
                TabLayoutModel tlm = getLayoutModel();
Lines 745-751 Link Here
745
        public void actionPerformed(ActionEvent e) {
807
        public void actionPerformed(ActionEvent e) {
746
            performPinAction();
808
            performPinAction();
747
        }
809
        }
810
811
        public void indicesAdded(ComplexListDataEvent e) {
812
            tabState.indicesAdded(e);
813
        }
814
815
        /**
816
         * Elements have been removed at the indices specified by the event's
817
         * getIndices() value
818
         *
819
         * @param e The event
820
         */
821
        public void indicesRemoved(ComplexListDataEvent e) {
822
            tabState.indicesRemoved(e);
823
        }
824
825
        /**
826
         * Elements have been changed at the indices specified by the event's
827
         * getIndices() value.  If the changed data can affect display width (such
828
         * as a text change or a change in icon size), the event's
829
         * <code>isTextChanged()</code> method will return true.
830
         *
831
         * @param e The event
832
         */
833
        public void indicesChanged(ComplexListDataEvent e) {
834
            tabState.indicesChanged(e);
835
        }
748
        
836
        
837
        public void intervalAdded (ListDataEvent evt) {
838
            tabState.intervalAdded(evt);
839
        }
840
        
841
        public void intervalRemoved (ListDataEvent evt) {
842
            tabState.intervalRemoved(evt);
843
        }
844
        
845
        public void contentsChanged(ListDataEvent evt) {
846
            tabState.contentsChanged(evt);
847
        }
749
    } // end of Controller
848
    } // end of Controller
750
    
849
    
751
850
(-)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/AquaSlidingButtonUI.java (-1 / +3 lines)
Lines 27-32 Link Here
27
import javax.swing.plaf.ComponentUI;
27
import javax.swing.plaf.ComponentUI;
28
import javax.swing.plaf.basic.BasicHTML;
28
import javax.swing.plaf.basic.BasicHTML;
29
import javax.swing.text.View;
29
import javax.swing.text.View;
30
import org.netbeans.swing.tabcontrol.SlidingButton;
30
import org.netbeans.swing.tabcontrol.SlidingButtonUI;
31
import org.netbeans.swing.tabcontrol.SlidingButtonUI;
31
import org.netbeans.swing.tabcontrol.plaf.GenericGlowingChiclet;
32
import org.netbeans.swing.tabcontrol.plaf.GenericGlowingChiclet;
32
33
Lines 73-79 Link Here
73
   protected void paintBackground(Graphics2D graph, AbstractButton b) {
74
   protected void paintBackground(Graphics2D graph, AbstractButton b) {
74
        chic.setNotch(false, false);
75
        chic.setNotch(false, false);
75
76
76
        chic.setState(0);
77
        chic.setState(((SlidingButton) b).isBlinkState() ? GenericGlowingChiclet.STATE_ATTENTION : 0);
77
        chic.setArcs(0.5f, 0.5f, 0.5f, 0.5f);
78
        chic.setArcs(0.5f, 0.5f, 0.5f, 0.5f);
78
        chic.setBounds(0, 1, b.getWidth() - 2, b.getHeight() - 2);
79
        chic.setBounds(0, 1, b.getWidth() - 2, b.getHeight() - 2);
79
        chic.setAllowVertical(true);
80
        chic.setAllowVertical(true);
Lines 87-92 Link Here
87
        state |= b.getModel().isSelected() ? GenericGlowingChiclet.STATE_SELECTED : 0;
88
        state |= b.getModel().isSelected() ? GenericGlowingChiclet.STATE_SELECTED : 0;
88
        state |= b.getModel().isPressed() ? GenericGlowingChiclet.STATE_PRESSED : 0;
89
        state |= b.getModel().isPressed() ? GenericGlowingChiclet.STATE_PRESSED : 0;
89
        state |= b.getModel().isRollover() ? GenericGlowingChiclet.STATE_ACTIVE : 0;
90
        state |= b.getModel().isRollover() ? GenericGlowingChiclet.STATE_ACTIVE : 0;
91
        state |= ((SlidingButton) b).isBlinkState() ? GenericGlowingChiclet.STATE_ATTENTION : 0;
90
        chic.setState(state);
92
        chic.setState(state);
91
        chic.setArcs(0.5f, 0.5f, 0.5f, 0.5f);
93
        chic.setArcs(0.5f, 0.5f, 0.5f, 0.5f);
92
        chic.setBounds(0, 1, b.getWidth() - 2, b.getHeight() - 2);
94
        chic.setBounds(0, 1, b.getWidth() - 2, b.getHeight() - 2);
(-)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 (+8 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
    
134
    public void cancelRequestAttention (int tab) {
135
        //not implemented
136
    }
137
    
130
    protected ChangeListener createSelectionListener() {
138
    protected ChangeListener createSelectionListener() {
131
        return new ChangeListener() {
139
        return new ChangeListener() {
132
            private int lastKnownSelection = -1;
140
            private int lastKnownSelection = -1;
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/BasicTabDisplayerUI.java (-12 / +64 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
    protected final void requestAttention (int tab) {
465
        tabState.addAlarmTab(tab);
466
    }
467
    
468
    protected final void cancelRequestAttention (int tab) {
469
        tabState.removeAlarmTab(tab);
470
    }
471
    
452
472
453
    protected void modelChanged() {
473
    protected void modelChanged() {
454
        tabState.clearTransientStates();
474
        tabState.clearTransientStates();
Lines 457-462 Link Here
457
        //sync
477
        //sync
458
        int idx = selectionModel.getSelectedIndex();
478
        int idx = selectionModel.getSelectedIndex();
459
        tabState.setSelected(idx);
479
        tabState.setSelected(idx);
480
        tabState.pruneAlarmTabs(displayer.getModel().size());
460
        super.modelChanged();
481
        super.modelChanged();
461
    }
482
    }
462
483
Lines 501-516 Link Here
501
        }
522
        }
502
523
503
        protected void repaintAllTabs() {
524
        protected void repaintAllTabs() {
504
            getTabsVisibleArea(scratch);
525
            //XXX would be nicer to just repaint the tabs area,
505
            if (scratch.height < displayer.getHeight()) {
526
            //but we also need to repaint below all the tabs in the
506
                //Ensure any gap at the bottom is repainted
527
            //event of activated/deactivated.  No actual reason to
507
                scratch.y = 0;
528
            //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();
529
            displayer.repaint();
515
        }
530
        }
516
531
Lines 530-535 Link Here
530
                              scratch.height);
545
                              scratch.height);
531
        }
546
        }
532
    }
547
    }
548
    
549
    protected ModelListener createModelListener() {
550
        return new BasicModelListener();
551
    }    
533
552
534
    private class BasicDisplayerPropertyChangeListener
553
    private class BasicDisplayerPropertyChangeListener
535
            extends DisplayerPropertyChangeListener {
554
            extends DisplayerPropertyChangeListener {
Lines 722-731 Link Here
722
            assert e.getSource() == selectionModel : "Unknown event source: "
741
            assert e.getSource() == selectionModel : "Unknown event source: "
723
                    + e.getSource();
742
                    + e.getSource();
724
            int idx = selectionModel.getSelectedIndex();
743
            int idx = selectionModel.getSelectedIndex();
725
            tabState.setSelected(idx);
744
            tabState.setSelected(idx >= 0 ? idx : -1);
726
            if (idx != -1) {
745
            if (idx >= 0) {
727
                makeTabVisible (selectionModel.getSelectedIndex());
746
                makeTabVisible (selectionModel.getSelectedIndex());
728
            }
747
            }
729
        }
748
        }
730
    }
749
    }
750
    
751
    /**
752
     * Listener on data model which will pass modified indices to the
753
     * TabState object, so it can update which tab indices are flashing in
754
     * "attention" mode, if any.
755
     */
756
    protected class BasicModelListener extends ModelListener {
757
        public void contentsChanged(ListDataEvent e) {
758
            super.contentsChanged(e);
759
            tabState.contentsChanged(e);
760
        }
761
762
        public void indicesAdded(ComplexListDataEvent e) {
763
            super.indicesAdded(e);
764
            tabState.indicesAdded(e);
765
        }
766
767
        public void indicesChanged(ComplexListDataEvent e) {
768
            tabState.indicesChanged(e);
769
        }
770
771
        public void indicesRemoved(ComplexListDataEvent e) {
772
            tabState.indicesRemoved(e);
773
        }
774
775
        public void intervalAdded(ListDataEvent e) {
776
            tabState.intervalAdded(e);
777
        }
778
779
        public void intervalRemoved(ListDataEvent e) {
780
            tabState.intervalRemoved(e);
781
        }
782
    }    
731
}
783
}
(-)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 / +13 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
    protected void requestAttention (int tab) {
613
        tabDisplayer.requestAttention (tab);
614
    }
615
    
616
    protected void cancelRequestAttention (int tab) {
617
        tabDisplayer.cancelRequestAttention(tab);
607
    }
618
    }
608
619
609
    /**
620
    /**
(-)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/MetalSlidingButtonUI.java (+2 lines)
Lines 101-110 Link Here
101
    }
101
    }
102
    
102
    
103
    protected void paintBackground (Graphics2D g, AbstractButton button) {
103
    protected void paintBackground (Graphics2D g, AbstractButton button) {
104
        hiddenToggle.setBackground (button.getBackground());
104
        hiddenToggle.paint(g);
105
        hiddenToggle.paint(g);
105
    }
106
    }
106
    
107
    
107
    protected void paintButtonPressed(Graphics g, AbstractButton b) {    
108
    protected void paintButtonPressed(Graphics g, AbstractButton b) {    
109
        hiddenToggle.setBackground (b.getBackground());
108
        hiddenToggle.paint(g);
110
        hiddenToggle.paint(g);
109
    }
111
    }
110
    
112
    
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/MetalViewTabDisplayerUI.java (-1 / +5 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
        if (highlighted) {
199
        boolean attention = isAttention (index);
200
        if (highlighted && !attention) {
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 (+330 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 356-363 Link Here
356
        boolean prev = active;
387
        boolean prev = active;
357
        active = b;
388
        active = b;
358
        possibleChange(prev, b, ACTIVE);
389
        possibleChange(prev, b, ACTIVE);
390
        removeAlarmTab(selectedIndex);
359
        return prev;
391
        return prev;
360
    }
392
    }
393
    
394
    private boolean isAlarmTab (int tab) {
395
        return attentionToggle && alarmTabs.contains(new Integer(tab));
396
    }
397
    
398
    private final HashSet alarmTabs = new HashSet(6);
399
    
400
    /** Add a tab to the list of those which should "flash" or otherwise give
401
     * some notification to the user to get their attention */
402
    public final void addAlarmTab (int alarmTab) {
403
        Integer in = new Integer(alarmTab);
404
        boolean added = alarmTabs.contains(in);
405
        boolean wasEmpty = alarmTabs.isEmpty();
406
        if (!added) {
407
            alarmTabs.add (new Integer(alarmTab));
408
            repaintTab (alarmTab);
409
        }
410
        if (wasEmpty) {
411
            startAlarmTimer();
412
            attentionToggle = true;
413
            repaintTab (alarmTab);
414
        }
415
    }
416
    
417
    /** Remove a tab to the list of those which should "flash" or otherwise give
418
     * some notification to the user to get their attention */
419
    public final void removeAlarmTab (int alarmTab) {
420
        Integer in = new Integer(alarmTab);
421
        boolean contained = alarmTabs.contains(in);
422
        if (contained) {
423
            alarmTabs.remove(in);
424
            boolean empty = alarmTabs.isEmpty();
425
            boolean wasAttentionToggled = attentionToggle;
426
            if (alarmTabs.isEmpty()) {
427
                stopAlarmTimer();
428
            }
429
            if (wasAttentionToggled) {
430
                repaintTab(alarmTab);
431
            }
432
        }
433
    }
434
    
435
    private Timer alarmTimer = null;
436
    private boolean attentionToggle = false;
437
    private final void startAlarmTimer() {
438
        if (alarmTimer == null) {
439
            ActionListener al = new ActionListener() {
440
                public void actionPerformed (ActionEvent ae) {
441
                    attentionToggle = !attentionToggle;
442
                    Timer timer = (Timer) ae.getSource();
443
                    for (Iterator i=alarmTabs.iterator(); i.hasNext();) {
444
                        repaintTab (((Integer) i.next()).intValue());
445
                    }
446
                }
447
            };
448
            alarmTimer = new Timer (700, al);
449
            alarmTimer.setRepeats(true);
450
        }
451
        alarmTimer.start();
452
    }
453
    
454
    private final void stopAlarmTimer() {
455
        if (alarmTimer != null && alarmTimer.isRunning()) {
456
            alarmTimer.stop();
457
            attentionToggle = false;
458
            repaintAllTabs(); //XXX optimize
459
        }
460
    }
461
    
462
    boolean hasAlarmTabs() {
463
        return alarmTabs != null && !alarmTabs.isEmpty();
464
    }
465
    
466
    void pruneAlarmTabs(int max) {
467
        if (!hasAlarmTabs()) {
468
            return;
469
        }
470
        for (Iterator i=alarmTabs.iterator(); i.hasNext();) {
471
            if (((Integer) i.next()).intValue() >= max) {
472
                i.remove();
473
            }
474
        }
475
        if (alarmTabs.isEmpty()) {
476
            stopAlarmTimer();
477
        }
478
    }
479
    
480
    int[] getAlarmTabs() {
481
        int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
482
        Arrays.sort(alarms);
483
        return alarms;
484
    }
485
    
486
    //Handling of insertions/deletions where we'll need to update the 
487
    //list of blinking tabs here.
488
    void intervalAdded (ListDataEvent evt) {
489
        if (!hasAlarmTabs()) return;
490
        int start = evt.getIndex0();
491
        int end = evt.getIndex1();
492
        int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
493
        boolean changed = false;
494
        for (int i=0; i < alarms.length; i++) {
495
            if (alarms[i] >= start) {
496
                alarms[i] += (end - start) + 1;
497
                changed = true;
498
            }
499
        }
500
        if (changed) {
501
            alarmTabs.clear();
502
            for (int i=0; i < alarms.length; i++) {
503
                addAlarmTab(alarms[i]);
504
            }
505
        }
506
    }
507
    
508
    void intervalRemoved (ListDataEvent evt) {
509
        if (!hasAlarmTabs()) return;
510
        int start = evt.getIndex0();
511
        int end = evt.getIndex1();
512
        
513
        int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
514
        Arrays.sort(alarms);
515
        
516
        if (end == start) {
517
            //Faster to handle this case separately
518
            boolean changed = true;
519
            for (int i=0; i < alarms.length; i++) {
520
                if (alarms[i] > end) {
521
                    alarms[i]--;
522
                } else if (alarms[i] == end) {
523
                    alarms[i] = -1;
524
                }
525
            }
526
            if (changed) {
527
                alarmTabs.clear();
528
                boolean added = false;
529
                for (int i=0; i < alarms.length; i++) {
530
                    if (alarms[i] != -1) {
531
                        addAlarmTab(alarms[i]);
532
                        added = true;
533
                    }
534
                }
535
                if (!added) {
536
                    stopAlarmTimer();
537
                }
538
            }            
539
            return;
540
        }
541
        
542
        boolean changed = false;
543
        for (int i=0; i < alarms.length; i++) {
544
            if (alarms[i] >= start && alarms[i] <= end) {
545
                alarms[i] = -1;
546
                changed = true;
547
            }
548
        }
549
        for (int i=0; i < alarms.length; i++) {
550
            if (alarms[i] > end) {
551
                alarms[i] -= (end - start) + 1;
552
                changed = true;
553
            }
554
        }
555
        if (changed) {
556
            alarmTabs.clear();
557
            boolean added = false;
558
            for (int i=0; i < alarms.length; i++) {
559
                if (alarms[i] != -1) {
560
                    addAlarmTab(alarms[i]);
561
                    added = true;
562
                }
563
            }
564
            if (!added) {
565
                stopAlarmTimer();
566
            }
567
        }
568
    }
569
    
570
    void indicesAdded (ComplexListDataEvent e) {
571
        if (!hasAlarmTabs()) return;
572
        int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
573
        java.util.Arrays.sort(alarms);
574
575
        int[] indices = e.getIndices();
576
        java.util.Arrays.sort(indices);
577
        
578
        boolean changed = false;
579
        for (int i=0; i < indices.length; i++) {
580
            for (int j=0; j < alarms.length; j++) {
581
                if (alarms[j] >= indices[i]) {
582
                    alarms[j]++;
583
                    changed = true;
584
                }
585
            }
586
        }
587
        if (changed) {
588
            alarmTabs.clear();
589
            for (int i=0; i < alarms.length; i++) {
590
                if (alarms[i] != -1) {
591
                    addAlarmTab(alarms[i]);
592
                }
593
            }
594
        }
595
    }
596
    
597
    void indicesRemoved (ComplexListDataEvent e) {
598
        if (!hasAlarmTabs()) return;
599
        int[] indices = e.getIndices();
600
        java.util.Arrays.sort(indices);
601
        
602
        int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
603
        java.util.Arrays.sort(alarms);
604
        
605
        if (alarms[alarms.length -1] < indices[0]) {
606
            //Some tab removed after the last blinking tab, don't care
607
            return;
608
        }
609
610
        boolean changed = false;
611
        for (int i=0; i < alarms.length; i++) {
612
            //First weed out all deleted alarm tabs
613
            for (int j=0; j < indices.length; j++) {
614
                if (alarms[i] == indices[j]) {
615
                    alarms[i] = -1;
616
                    changed = true;
617
                }
618
            }
619
        }
620
        for (int i=0; i < alarms.length; i++) {
621
            //Now decrement those that remain that are affected
622
            int alarm = alarms[i];
623
            for (int j=0; j < indices.length; j++) {
624
                if (alarm > indices[j]) {
625
                    alarms[i]--;
626
                    changed = true;
627
                }
628
            }
629
        }
630
        
631
        if (changed) {
632
            alarmTabs.clear();
633
            boolean addedSome = false;
634
            for (int i=0; i < alarms.length; i++) {
635
                if (alarms[i] >= 0) {
636
                    addAlarmTab(alarms[i]);
637
                    addedSome = true;
638
                }
639
            }
640
            if (!addedSome) {
641
                stopAlarmTimer();
642
            }
643
        }        
644
        
645
        repaintAllTabs();
646
    }
647
    
648
    void indicesChanged (ComplexListDataEvent e) {
649
        if (!hasAlarmTabs()) return;
650
        if (e instanceof VeryComplexListDataEvent) { //it always will be
651
            VeryComplexListDataEvent ve = (VeryComplexListDataEvent) e;
652
            
653
            ArrayDiff dif = ((VeryComplexListDataEvent) e).getDiff();
654
            
655
            List old = Arrays.asList(dif.getOldData());
656
            List nue = Arrays.asList(dif.getNewData());
657
            
658
            int[] alarms = (int[]) Utilities.toPrimitiveArray((Integer[]) alarmTabs.toArray(new Integer[0]));
659
            
660
            boolean changed = false;
661
            for (int i=0; i < alarms.length; i++) {
662
                Object o = old.get(alarms[i]);
663
                int idx = nue.indexOf(o);
664
                changed |= idx != alarms[i];
665
                alarms[i] = nue.indexOf(o);
666
            }
667
            if (changed) {
668
                alarmTabs.clear();
669
                boolean addedSome = false;
670
                for (int i=0; i < alarms.length; i++) {
671
                    if (alarms[i] >= 0) {
672
                        addAlarmTab(alarms[i]);
673
                        addedSome = true;
674
                    }
675
                }
676
                if (!addedSome) {
677
                    stopAlarmTimer();
678
                }
679
            }             
680
        }
681
    }
682
683
    
684
    void contentsChanged(ListDataEvent evt) {
685
        if (!hasAlarmTabs()) return;
686
        //Do nothing, just means some text or icons changed
687
    }    
361
688
362
    //Change types
689
    //Change types
363
    /** Change type indicating no change happened (i.e. calling setSelected() with the same value it was previously
690
    /** 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;
835
                    type = ALL_TABS;
509
                    go = true;
836
                    go = true;
510
                }
837
                }
838
                break;
839
            case ATTENTION:
840
                go = true;
511
        }
841
        }
512
        if (go) {
842
        if (go) {
513
            if (type == ALL_TABS) {
843
            if (type == ALL_TABS) {
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/ToolbarTabDisplayerUI.java (-1 / +9 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
    }
110
    
111
    public void cancelRequestAttention (int tab) {
112
        //not implemented
113
    }
106
    
114
    
107
    protected ChangeListener createSelectionListener() {
115
    protected ChangeListener createSelectionListener() {
108
        return new ChangeListener() {
116
        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 (-2 / +6 lines)
Lines 228-243 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 && !attention) {
233
            result =
235
            result =
234
                    ColorUtil.getGradientPaint(x, y, getSelGradientColor(),
236
                    ColorUtil.getGradientPaint(x, y, getSelGradientColor(),
235
                                               //NOI18N
237
                                               //NOI18N
236
                                               x + width, y,
238
                                               x + width, y,
237
                                               UIManager.getColor(
239
                                               UIManager.getColor(
238
                                                       "TabbedPane.background"));
240
                                                       "TabbedPane.background"));
239
        } else if (selected) {
241
        } else if (selected && !attention) {
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/WinXPSlidingButtonUI.java (-3 / +9 lines)
Lines 39-44 Link Here
39
import javax.swing.border.CompoundBorder;
39
import javax.swing.border.CompoundBorder;
40
import javax.swing.plaf.ComponentUI;
40
import javax.swing.plaf.ComponentUI;
41
import javax.swing.plaf.basic.BasicGraphicsUtils;
41
import javax.swing.plaf.basic.BasicGraphicsUtils;
42
import org.netbeans.swing.tabcontrol.SlidingButton;
42
import org.netbeans.swing.tabcontrol.SlidingButtonUI;
43
import org.netbeans.swing.tabcontrol.SlidingButtonUI;
43
44
44
/** 
45
/** 
Lines 108-119 Link Here
108
        super.paint(g, c);
109
        super.paint(g, c);
109
    }
110
    }
110
    
111
    
111
    protected void paintBackground (Graphics2D g, AbstractButton button) {
112
    protected void paintBackground(Graphics2D g, AbstractButton b) {
112
        hiddenToggle.paint(g);
113
        if (((SlidingButton) b).isBlinkState()) {
114
            g.setColor(WinClassicEditorTabCellRenderer.ATTENTION_COLOR);
115
            g.fillRect (0, 0, b.getWidth(), b.getHeight());
116
            hiddenToggle.setFont(b.getFont());
117
        } else {
118
            hiddenToggle.paint(g);
119
        }
113
    }
120
    }
114
    
121
    
115
    protected void paintButtonPressed(Graphics g, AbstractButton b) {    
122
    protected void paintButtonPressed(Graphics g, AbstractButton b) {    
116
        hiddenToggle.paint(g);
123
        hiddenToggle.paint(g);
117
    }
124
    }
118
   
119
}
125
}
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/WinXPViewTabDisplayerUI.java (-5 / +13 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
        if (focused) {
193
        boolean attention = isAttention(index);
194
        if (focused && !attention) {
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() && !attention) {
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) {
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);
Lines 465-475 Link Here
465
        
471
        
466
        
472
        
467
        public Icon getIcon() {
473
        public Icon getIcon() {
468
            if (displayer.isActive()) {
474
            Icon result = null;
469
                return iconCache.obtainIcon((String)focusedNormal.get(getOrientation()));
475
            if (displayer != null && displayer.isActive()) {
476
                result = iconCache.obtainIcon((String)focusedNormal.get(getOrientation()));
470
            } else {
477
            } else {
471
                return super.getIcon();
478
                result = super.getIcon();
472
            }
479
            }
480
            return result;
473
        }
481
        }
474
482
475
        public Icon getRolloverIcon() {
483
        public Icon getRolloverIcon() {
(-)core/swing/tabcontrol/src/org/netbeans/swing/tabcontrol/plaf/WindowsSlidingButtonUI.java (-8 / +23 lines)
Lines 37-42 Link Here
37
import javax.swing.border.CompoundBorder;
37
import javax.swing.border.CompoundBorder;
38
import javax.swing.plaf.ComponentUI;
38
import javax.swing.plaf.ComponentUI;
39
import javax.swing.plaf.basic.BasicGraphicsUtils;
39
import javax.swing.plaf.basic.BasicGraphicsUtils;
40
import org.netbeans.swing.tabcontrol.SlidingButton;
40
import org.netbeans.swing.tabcontrol.SlidingButtonUI;
41
import org.netbeans.swing.tabcontrol.SlidingButtonUI;
41
42
42
/** 
43
/** 
Lines 77-86 Link Here
77
    public void installDefaults (AbstractButton b) {
78
    public void installDefaults (AbstractButton b) {
78
        super.installDefaults(b);
79
        super.installDefaults(b);
79
	if(!defaults_initialized) {
80
	if(!defaults_initialized) {
80
	    dashedRectGapX = ((Integer)UIManager.get("Button.dashedRectGapX")).intValue();
81
            //Null checks so this can be tested on other platforms
81
	    dashedRectGapY = ((Integer)UIManager.get("Button.dashedRectGapY")).intValue();
82
            Integer in = ((Integer)UIManager.get("Button.dashedRectGapX"));
82
	    dashedRectGapWidth = ((Integer)UIManager.get("Button.dashedRectGapWidth")).intValue();
83
	    dashedRectGapX = in == null ? 3 : in.intValue();
83
	    dashedRectGapHeight = ((Integer)UIManager.get("Button.dashedRectGapHeight")).intValue();
84
            in = ((Integer)UIManager.get("Button.dashedRectGapY"));
85
	    dashedRectGapY = in == null ? 3 : in.intValue();
86
            in = ((Integer)UIManager.get("Button.dashedRectGapWidth"));
87
	    dashedRectGapWidth = in == null ? 3 : in.intValue();
88
            in = ((Integer)UIManager.get("Button.dashedRectGapHeight"));
89
	    dashedRectGapHeight = in == null ? 3 : in.intValue();
84
            
90
            
85
	    focusColor = UIManager.getColor(getPropertyPrefix() + "focus");
91
	    focusColor = UIManager.getColor(getPropertyPrefix() + "focus");
86
	    defaults_initialized = true;
92
	    defaults_initialized = true;
Lines 92-106 Link Here
92
	defaults_initialized = false;
98
	defaults_initialized = false;
93
    }    
99
    }    
94
    
100
    
95
    protected void paintBackground (Graphics2D g, AbstractButton button) {
101
    protected void paintBackground(Graphics2D g, AbstractButton b) {
96
	super.paintBackground(g, button);
102
        if (((SlidingButton) b).isBlinkState()) {
97
    }
103
            g.setColor(WinClassicEditorTabCellRenderer.ATTENTION_COLOR);
98
    
104
            g.fillRect (0, 0, b.getWidth(), b.getHeight());
105
        } else {
106
            super.paintBackground(g, b);
107
        }
108
    }    
99
    
109
    
100
    protected void paintButtonPressed(Graphics g, AbstractButton b) {
110
    protected void paintButtonPressed(Graphics g, AbstractButton b) {
101
        // This is a special case in which the toggle button in the
111
        // This is a special case in which the toggle button in the
102
        // Rollover JToolBar will render the button in a pressed state
112
        // Rollover JToolBar will render the button in a pressed state
103
        Color oldColor = g.getColor();
113
        Color oldColor = g.getColor();
114
        
115
        if (((SlidingButton) b).isBlinkState()) {
116
            g.setColor(WinClassicEditorTabCellRenderer.ATTENTION_COLOR);
117
            g.fillRect (0, 0, b.getWidth(), b.getHeight());
118
        }
104
        
119
        
105
        int w = b.getWidth();
120
        int w = b.getWidth();
106
        int h = b.getHeight();
121
        int h = b.getHeight();
(-)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
}
(-)core/windows/src/org/netbeans/core/windows/Central.java (+12 lines)
Lines 48-53 Link Here
48
    }
48
    }
49
49
50
    
50
    
51
    public void topComponentRequestAttention (ModeImpl mode, TopComponent tc) {
52
        String modeName = getModeName(mode);
53
        viewRequestor.scheduleRequest (
54
            new ViewRequest(modeName, View.TOPCOMPONENT_REQUEST_ATTENTION, tc, tc));
55
    }
56
    
57
    public void topComponentCancelRequestAttention (ModeImpl mode, TopComponent tc) {
58
        String modeName = getModeName(mode);
59
        viewRequestor.scheduleRequest (
60
            new ViewRequest(modeName, View.TOPCOMPONENT_CANCEL_REQUEST_ATTENTION, tc, tc));
61
    }    
62
    
51
    /////////////////////
63
    /////////////////////
52
    // Mutators >>
64
    // Mutators >>
53
    /** Sets visible or invisible window system and requests view accordingly. */
65
    /** Sets visible or invisible window system and requests view accordingly. */
(-)core/windows/src/org/netbeans/core/windows/ViewRequest.java (+6 lines)
Lines 118-123 Link Here
118
            case  View.CHANGE_PROJECT_NAME :
118
            case  View.CHANGE_PROJECT_NAME :
119
                tp = "CHANGE_PROJECT_NAME"; //NOI18N
119
                tp = "CHANGE_PROJECT_NAME"; //NOI18N
120
                break;
120
                break;
121
            case  View.TOPCOMPONENT_REQUEST_ATTENTION :
122
                tp = "TOPCOMPONENT_REQUEST_ATTENTION"; //NOI18N
123
                break;
124
            case  View.TOPCOMPONENT_CANCEL_REQUEST_ATTENTION :
125
                tp = "TOPCOMPONENT_CANCEL_REQUEST_ATTENTION"; //NOI18N
126
                break;
121
            default :
127
            default :
122
                tp = "UNKNOWN";
128
                tp = "UNKNOWN";
123
                break;
129
                break;
(-)core/windows/src/org/netbeans/core/windows/ViewRequestor.java (-1 / +3 lines)
Lines 117-123 Link Here
117
            || type == View.CHANGE_TOPCOMPONENT_ACTIVATED
117
            || type == View.CHANGE_TOPCOMPONENT_ACTIVATED
118
            || type == View.CHANGE_DND_PERFORMED
118
            || type == View.CHANGE_DND_PERFORMED
119
            || type == View.CHANGE_UI_UPDATE
119
            || type == View.CHANGE_UI_UPDATE
120
            || type == View.CHANGE_PROJECT_NAME;
120
            || type == View.CHANGE_PROJECT_NAME
121
            || type == View.TOPCOMPONENT_CANCEL_REQUEST_ATTENTION
122
            || type == View.TOPCOMPONENT_REQUEST_ATTENTION;
121
            
123
            
122
        synchronized(requests) {
124
        synchronized(requests) {
123
            Object oldValue = null;
125
            Object oldValue = null;
(-)core/windows/src/org/netbeans/core/windows/WindowManagerImpl.java (+11 lines)
Lines 100-106 Link Here
100
        }
100
        }
101
        return (WindowManagerImpl)Lookup.getDefault().lookup(WindowManager.class);
101
        return (WindowManagerImpl)Lookup.getDefault().lookup(WindowManager.class);
102
    }
102
    }
103
    
104
    public void topComponentRequestAttention(TopComponent tc) {
105
        ModeImpl mode = (ModeImpl) findMode(tc);
106
        
107
        central.topComponentRequestAttention(mode, tc);
108
    }
103
109
110
    public void topComponentCancelRequestAttention(TopComponent tc) {
111
        ModeImpl mode = (ModeImpl) findMode(tc);
112
        
113
        central.topComponentCancelRequestAttention(mode, tc);
114
    }
104
115
105
    /////////////////////////
116
    /////////////////////////
106
    // API impelementation >>
117
    // API impelementation >>
(-)core/windows/src/org/netbeans/core/windows/view/DefaultView.java (-1 / +33 lines)
Lines 120-126 Link Here
120
                    type != CHANGE_TOPCOMPONENT_DISPLAY_NAME_ANNOTATION_CHANGED &&
120
                    type != CHANGE_TOPCOMPONENT_DISPLAY_NAME_ANNOTATION_CHANGED &&
121
                    type != CHANGE_TOPCOMPONENT_TOOLTIP_CHANGED && 
121
                    type != CHANGE_TOPCOMPONENT_TOOLTIP_CHANGED && 
122
                    type != CHANGE_TOPCOMPONENT_ICON_CHANGED && 
122
                    type != CHANGE_TOPCOMPONENT_ICON_CHANGED && 
123
                    type != CHANGE_PROJECT_NAME) {
123
                    type != CHANGE_PROJECT_NAME &&
124
                    type != TOPCOMPONENT_REQUEST_ATTENTION) {
124
                        isDangerous = true;
125
                        isDangerous = true;
125
                        break;
126
                        break;
126
                }
127
                }
Lines 449-454 Link Here
449
                hierarchy.setMaximizedModeView(hierarchy.getModeViewForAccessor(wsa.getMaximizedModeAccessor()));
450
                hierarchy.setMaximizedModeView(hierarchy.getModeViewForAccessor(wsa.getMaximizedModeAccessor()));
450
                hierarchy.updateDesktop(wsa);
451
                hierarchy.updateDesktop(wsa);
451
                hierarchy.activateMode(wsa.getActiveModeAccessor());
452
                hierarchy.activateMode(wsa.getActiveModeAccessor());
453
            } else if (changeType == View.TOPCOMPONENT_REQUEST_ATTENTION) {
454
                if (DEBUG) {
455
                    debugLog("Top component request attention");
456
                }
457
                ModeView modeView = hierarchy.getModeViewForAccessor(wsa.findModeAccessor((String)viewEvent.getSource())); // XXX
458
                if (modeView != null) {
459
                   TopComponent tc = (TopComponent) viewEvent.getNewValue();
460
                   if (tc == null) {
461
                       throw new NullPointerException ("Top component is null for attention request"); //NOI18N
462
                   }
463
                   modeView.requestAttention (tc); 
464
                } else {
465
                    ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, 
466
                        "Could not find mode " + viewEvent.getSource());
467
                }
468
            } else if (changeType == View.TOPCOMPONENT_CANCEL_REQUEST_ATTENTION) {
469
                if (DEBUG) {
470
                    debugLog("Top component cancel request attention"); //NOI18N
471
                }
472
                ModeView modeView = hierarchy.getModeViewForAccessor(wsa.findModeAccessor((String)viewEvent.getSource())); // XXX
473
                if (modeView != null) {
474
                   TopComponent tc = (TopComponent) viewEvent.getNewValue();
475
                   if (tc == null) {
476
                       throw new NullPointerException ("Top component is null for attention cancellation request"); //NOI18N
477
                   }
478
                   modeView.cancelRequestAttention (tc); 
479
                } else {
480
                    ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, 
481
                        "Could not find mode " + viewEvent.getSource());
482
                }
483
                
452
            }
484
            }
453
        }
485
        }
454
        
486
        
(-)core/windows/src/org/netbeans/core/windows/view/ModeContainer.java (+4 lines)
Lines 52-56 Link Here
52
    public void updateToolTip(TopComponent tc);
52
    public void updateToolTip(TopComponent tc);
53
    
53
    
54
    public void updateIcon(TopComponent tc);
54
    public void updateIcon(TopComponent tc);
55
    
56
    public void requestAttention(TopComponent tc);
57
58
    public void cancelRequestAttention(TopComponent tc);
55
}
59
}
56
60
(-)core/windows/src/org/netbeans/core/windows/view/ModeView.java (+8 lines)
Lines 144-149 Link Here
144
    public void updateIcon(TopComponent tc) {
144
    public void updateIcon(TopComponent tc) {
145
        container.updateIcon(tc);
145
        container.updateIcon(tc);
146
    }
146
    }
147
    
148
    public void requestAttention (TopComponent tc) {
149
        container.requestAttention(tc);
150
    }
151
152
    public void cancelRequestAttention (TopComponent tc) {
153
        container.cancelRequestAttention(tc);
154
    }
147
155
148
    // XXX
156
    // XXX
149
    public void updateFrameState() {
157
    public void updateFrameState() {
(-)core/windows/src/org/netbeans/core/windows/view/View.java (+3 lines)
Lines 74-79 Link Here
74
    public int CHANGE_UI_UPDATE    = 61;
74
    public int CHANGE_UI_UPDATE    = 61;
75
    public int CHANGE_PROJECT_NAME = 62;
75
    public int CHANGE_PROJECT_NAME = 62;
76
    
76
    
77
    public int TOPCOMPONENT_REQUEST_ATTENTION = 63;
78
    public int TOPCOMPONENT_CANCEL_REQUEST_ATTENTION = 64;
79
    
77
    /** Provides GUI changes to manifest model changes to user. */
80
    /** Provides GUI changes to manifest model changes to user. */
78
    public void changeGUI(ViewEvent[] viewEvents, WindowSystemSnapshot snapshot);
81
    public void changeGUI(ViewEvent[] viewEvents, WindowSystemSnapshot snapshot);
79
    
82
    
(-)core/windows/src/org/netbeans/core/windows/view/ViewEvent.java (+2 lines)
Lines 97-102 Link Here
97
            case View.CHANGE_TOPCOMPONENT_TOOLTIP_CHANGED : typeStr = "CHANGE_TOPCOMPONENT_TOOLTIP_CHANGED"; break; //NOI18N
97
            case View.CHANGE_TOPCOMPONENT_TOOLTIP_CHANGED : typeStr = "CHANGE_TOPCOMPONENT_TOOLTIP_CHANGED"; break; //NOI18N
98
            case View.CHANGE_UI_UPDATE : typeStr = "CHANGE_UI_UPDATE"; break; //NOI18N
98
            case View.CHANGE_UI_UPDATE : typeStr = "CHANGE_UI_UPDATE"; break; //NOI18N
99
            case View.CHANGE_VISIBILITY_CHANGED : typeStr = "CHANGE_VISIBILITY_CHANGED"; break; //NOI18N
99
            case View.CHANGE_VISIBILITY_CHANGED : typeStr = "CHANGE_VISIBILITY_CHANGED"; break; //NOI18N
100
            case View.TOPCOMPONENT_REQUEST_ATTENTION : typeStr = "TOPCOMPONENT_REQUEST_ATTENTION"; break; //NOI18N
101
            case View.TOPCOMPONENT_CANCEL_REQUEST_ATTENTION : typeStr = "TOPCOMPONENT_CANCEL_REQUEST_ATTENTION"; break; //NOI18N
100
        }
102
        }
101
        buf.append(typeStr);
103
        buf.append(typeStr);
102
        buf.append("\nnewValue="); //NOI18N
104
        buf.append("\nnewValue="); //NOI18N
(-)core/windows/src/org/netbeans/core/windows/view/ui/DefaultSeparateContainer.java (+8 lines)
Lines 104-109 Link Here
104
            }
104
            }
105
        });
105
        });
106
    }
106
    }
107
    
108
    public void requestAttention (TopComponent tc) {
109
        //not implemented
110
    }
111
    
112
    public void cancelRequestAttention (TopComponent tc) {
113
        //not implemented
114
    }
107
115
108
    /** */
116
    /** */
109
    protected Component getModeComponent() {
117
    protected Component getModeComponent() {
(-)core/windows/src/org/netbeans/core/windows/view/ui/DefaultSplitContainer.java (+8 lines)
Lines 50-55 Link Here
50
        // To be able to move split dividers.
50
        // To be able to move split dividers.
51
        panel.setMinimumSize(new Dimension(1, 1));
51
        panel.setMinimumSize(new Dimension(1, 1));
52
    }
52
    }
53
    
54
    public void requestAttention (TopComponent tc) {
55
        tabbedHandler.requestAttention(tc);
56
    }
57
    
58
    public void cancelRequestAttention (TopComponent tc) {
59
        tabbedHandler.cancelRequestAttention(tc);
60
    }
53
61
54
    /** */
62
    /** */
55
    protected Component getModeComponent() {
63
    protected Component getModeComponent() {
(-)core/windows/src/org/netbeans/core/windows/view/ui/Tabbed.java (+4 lines)
Lines 31-36 Link Here
31
 */
31
 */
32
public interface Tabbed {
32
public interface Tabbed {
33
    
33
    
34
    public void requestAttention(TopComponent tc);
35
36
    public void cancelRequestAttention(TopComponent tc);
37
    
34
    public void addTopComponent(String name, Icon icon, TopComponent tc, String toolTip);
38
    public void addTopComponent(String name, Icon icon, TopComponent tc, String toolTip);
35
39
36
    public void insertComponent(String name, Icon icon, Component comp, String toolTip, int position);
40
    public void insertComponent(String name, Icon icon, Component comp, String toolTip, int position);
(-)core/windows/src/org/netbeans/core/windows/view/ui/TabbedHandler.java (+7 lines)
Lines 102-108 Link Here
102
102
103
        return tabbed;
103
        return tabbed;
104
    }
104
    }
105
    
106
    public void requestAttention (TopComponent tc) {
107
        tabbed.requestAttention(tc);
108
    }
105
109
110
    public void cancelRequestAttention (TopComponent tc) {
111
        tabbed.cancelRequestAttention(tc);
112
    }
106
    
113
    
107
    public Component getComponent() {
114
    public Component getComponent() {
108
        return tabbed.getComponent();
115
        return tabbed.getComponent();
(-)core/windows/src/org/netbeans/core/windows/view/ui/slides/SlideBar.java (-3 / +47 lines)
Lines 23-30 Link Here
23
import java.awt.event.MouseEvent;
23
import java.awt.event.MouseEvent;
24
import java.util.ArrayList;
24
import java.util.ArrayList;
25
import java.util.Arrays;
25
import java.util.Arrays;
26
import java.util.HashSet;
26
import java.util.Iterator;
27
import java.util.Iterator;
27
import java.util.List;
28
import java.util.List;
29
import java.util.Set;
28
import javax.swing.Box;
30
import javax.swing.Box;
29
import javax.swing.BoxLayout;
31
import javax.swing.BoxLayout;
30
import javax.swing.DefaultSingleSelectionModel;
32
import javax.swing.DefaultSingleSelectionModel;
Lines 219-228 Link Here
219
        int index = getButtonIndex(clickedButton);
221
        int index = getButtonIndex(clickedButton);
220
        commandMgr.showPopup(mouseEvent, index);
222
        commandMgr.showPopup(mouseEvent, index);
221
    }
223
    }
224
    
225
    private SlidingButton buttonFor (TopComponent tc) {
226
        int idx = 0;
227
        for (Iterator i=dataModel.getTabs().iterator(); i.hasNext();) {
228
            TabData td = (TabData) i.next();
229
            if (td.getComponent() == tc) {
230
                break;
231
            }
232
            if (!i.hasNext()) {
233
                idx = -1;
234
            } else {
235
                idx++;
236
            }
237
        }
238
        if (idx >= 0 && idx < dataModel.size()) {
239
            return getButton(idx);
240
        } else {
241
            return null;
242
        }
243
    }
244
    
245
    public void setBlinking (TopComponent tc, boolean val) {
246
        SlidingButton button = buttonFor (tc);
247
        if (button != null) {
248
            button.setBlinking(val);
249
        }
250
    }
222
251
223
    /** Triggers slide operation by changing selected index */
252
    /** Triggers slide operation by changing selected index */
224
    public void userClickedSlidingButton(Component clickedButton) {
253
    public void userClickedSlidingButton(Component clickedButton) {
225
        int index = getButtonIndex(clickedButton);
254
        int index = getButtonIndex(clickedButton);
255
        SlidingButton button = (SlidingButton) buttons.get(index);
256
        button.setBlinking(false);
226
        
257
        
227
        if (index != selModel.getSelectedIndex() || !isActive()) {
258
        if (index != selModel.getSelectedIndex() || !isActive()) {
228
            TopComponent tc = (TopComponent)dataModel.getTab(index).getComponent();
259
            TopComponent tc = (TopComponent)dataModel.getTab(index).getComponent();
Lines 240-245 Link Here
240
        if (index < 0) {
271
        if (index < 0) {
241
            return false;
272
            return false;
242
        }
273
        }
274
        SlidingButton button = (SlidingButton) buttons.get(index);
275
        button.setBlinking(false);
243
        TopComponent tc = (TopComponent)dataModel.getTab(index).getComponent();
276
        TopComponent tc = (TopComponent)dataModel.getTab(index).getComponent();
244
        if (tc == null) {
277
        if (tc == null) {
245
            return false;
278
            return false;
Lines 340-348 Link Here
340
    
373
    
341
    private void syncWithModel () {
374
    private void syncWithModel () {
342
        assert SwingUtilities.isEventDispatchThread();
375
        assert SwingUtilities.isEventDispatchThread();
343
        
376
        Set blinks = null;
344
        for (Iterator iter = buttons.iterator(); iter.hasNext(); ) {
377
        for (Iterator iter = buttons.iterator(); iter.hasNext(); ) {
345
            gestureRecognizer.detachButton((SlidingButton)iter.next());
378
            SlidingButton curr = (SlidingButton) iter.next();
379
            if (curr.isBlinking()) {
380
                if (blinks == null) {
381
                    blinks = new HashSet();
382
                }
383
                blinks.add (curr.getData());
384
            }
385
            gestureRecognizer.detachButton(curr);
346
        }
386
        }
347
        removeAll();
387
        removeAll();
348
        buttons.clear();
388
        buttons.clear();
Lines 350-356 Link Here
350
        List dataList = dataModel.getTabs();
390
        List dataList = dataModel.getTabs();
351
        SlidingButton curButton;
391
        SlidingButton curButton;
352
        for (Iterator iter = dataList.iterator(); iter.hasNext(); ) {
392
        for (Iterator iter = dataList.iterator(); iter.hasNext(); ) {
353
            curButton = new SlidingButton((TabData)iter.next(), dataModel.getOrientation());
393
            TabData td = (TabData) iter.next();
394
            curButton = new SlidingButton(td, dataModel.getOrientation());
395
            if (blinks != null && blinks.contains(td)) {
396
                curButton.setBlinking(true);
397
            }
354
            gestureRecognizer.attachButton(curButton);
398
            gestureRecognizer.attachButton(curButton);
355
            buttons.add(curButton);
399
            buttons.add(curButton);
356
            add(curButton);
400
            add(curButton);
(-)core/windows/src/org/netbeans/core/windows/view/ui/slides/SlideBarContainer.java (+8 lines)
Lines 48-53 Link Here
48
        panel.add(this.tabbedHandler.getComponent(), BorderLayout.CENTER);
48
        panel.add(this.tabbedHandler.getComponent(), BorderLayout.CENTER);
49
    }
49
    }
50
    
50
    
51
    public void requestAttention (TopComponent tc) {
52
        tabbedHandler.requestAttention(tc);
53
    }
54
55
    public void cancelRequestAttention (TopComponent tc) {
56
        tabbedHandler.cancelRequestAttention (tc);
57
    }    
58
    
51
    public void setTopComponents(TopComponent[] tcs, TopComponent selected) {
59
    public void setTopComponents(TopComponent[] tcs, TopComponent selected) {
52
        super.setTopComponents(tcs, selected);
60
        super.setTopComponents(tcs, selected);
53
    }
61
    }
(-)core/windows/src/org/netbeans/core/windows/view/ui/slides/TabbedSlideAdapter.java (+14 lines)
Lines 69-74 Link Here
69
        selModel = new DefaultSingleSelectionModel();
69
        selModel = new DefaultSingleSelectionModel();
70
        slideBar = new SlideBar(this, (SlideBarDataModel)dataModel, selModel);
70
        slideBar = new SlideBar(this, (SlideBarDataModel)dataModel, selModel);
71
    }
71
    }
72
    
73
    public void requestAttention (TopComponent tc) {
74
        slideBar.setBlinking(tc, true);
75
    }
76
    
77
    public void cancelRequestAttention (TopComponent tc) {
78
        slideBar.setBlinking(tc, false);
79
    }
80
    
72
81
73
    private void setSide (String side) {
82
    private void setSide (String side) {
74
        int orientation = SlideBarDataModel.WEST;
83
        int orientation = SlideBarDataModel.WEST;
Lines 235-240 Link Here
235
        int newIndex = indexOf(comp);
244
        int newIndex = indexOf(comp);
236
        if (selModel.getSelectedIndex() != newIndex) {
245
        if (selModel.getSelectedIndex() != newIndex) {
237
            selModel.setSelectedIndex(newIndex);
246
            selModel.setSelectedIndex(newIndex);
247
        }
248
        if (comp instanceof TopComponent) {
249
            //Inelegant to do this here, but it guarantees blinking stops
250
            TopComponent tc = (TopComponent) comp;
251
            tc.cancelRequestAttention();
238
        }
252
        }
239
    }
253
    }
240
    
254
    
(-)core/windows/src/org/netbeans/core/windows/view/ui/tabcontrol/TabbedAdapter.java (+20 lines)
Lines 83-88 Link Here
83
        int i = getSelectionModel().getSelectedIndex();
83
        int i = getSelectionModel().getSelectedIndex();
84
        return i == -1 ? null : getTopComponentAt(i);
84
        return i == -1 ? null : getTopComponentAt(i);
85
    }
85
    }
86
    
87
    public void requestAttention (TopComponent tc) {
88
        int idx = indexOf(tc);
89
        if (idx >= 0) {
90
            requestAttention(idx);
91
        } else {
92
            ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL,
93
                "RequestAttention on component unknown to container: " + tc); //NOI18N
94
        }
95
    }
96
    
97
    public void cancelRequestAttention (TopComponent tc) {
98
        int idx = indexOf(tc);
99
        if (idx >= 0) {
100
            cancelRequestAttention(idx);
101
        } else {
102
            throw new IllegalArgumentException ("TopComponent " + tc 
103
                + " is not a child of this container"); //NOI18N
104
        }
105
    }    
86
106
87
    public void insertComponent(String name, javax.swing.Icon icon, Component comp, String toolTip, int position) {
107
    public void insertComponent(String name, javax.swing.Icon icon, Component comp, String toolTip, int position) {
88
        TabData td = new TabData (comp, icon, name, toolTip);
108
        TabData td = new TabData (comp, icon, name, toolTip);
(-)openide/src/org/openide/windows/TopComponent.java (+93 lines)
Lines 16-21 Link Here
16
import java.awt.Image;
16
import java.awt.Image;
17
import java.awt.Toolkit;
17
import java.awt.Toolkit;
18
import java.awt.event.ActionEvent;
18
import java.awt.event.ActionEvent;
19
import java.awt.event.ActionListener;
19
import java.awt.event.KeyEvent;
20
import java.awt.event.KeyEvent;
20
import java.util.*;
21
import java.util.*;
21
import java.beans.*;
22
import java.beans.*;
Lines 40-49 Link Here
40
import javax.swing.JComponent;
41
import javax.swing.JComponent;
41
import javax.swing.KeyStroke;
42
import javax.swing.KeyStroke;
42
import javax.swing.SwingUtilities;
43
import javax.swing.SwingUtilities;
44
import javax.swing.Timer;
43
import javax.swing.text.Keymap;
45
import javax.swing.text.Keymap;
44
46
45
import org.openide.ErrorManager;
47
import org.openide.ErrorManager;
46
import org.openide.awt.UndoRedo;
48
import org.openide.awt.UndoRedo;
49
import org.openide.util.Mutex;
47
import org.openide.util.actions.SystemAction;
50
import org.openide.util.actions.SystemAction;
48
import org.openide.nodes.*;
51
import org.openide.nodes.*;
49
import org.openide.util.ContextAwareAction;
52
import org.openide.util.ContextAwareAction;
Lines 550-555 Link Here
550
    public void requestVisible () {
553
    public void requestVisible () {
551
        WindowManager.getDefault().topComponentRequestVisible(this);
554
        WindowManager.getDefault().topComponentRequestVisible(this);
552
    }
555
    }
556
    
557
    /**
558
     * Cause this TopComponent's tab to flash or otherwise draw attention to
559
     * itself.  This method is thread-safe.
560
     * <p>
561
     * It will remain flashing until either <code>cancelRequestAttention</code>
562
     * is called, the component becomes selected or its activated state changes,
563
     * unless the <code>brief</code> argument is true, in which case it will stop
564
     * after a few second.
565
     * @param brief True if the tab should blink a few times and stop
566
     * @since 4.45
567
     */
568
    public final void requestAttention(final boolean brief) {
569
        //Reentrancy issues - always invoke later
570
        SwingUtilities.invokeLater (new Runnable() {
571
            public void run() {
572
                if (attentionGetter != null && !brief) {
573
                    attentionGetter.kill();
574
                } else if (!brief) {
575
                    WindowManager.getDefault().topComponentRequestAttention(
576
                        TopComponent.this);
577
                } else if (attentionGetter != null) {
578
                    attentionGetter.reset();
579
                } else {
580
                    attentionGetter = new AttentionGetter();
581
                }
582
            }
583
        });
584
    }
585
586
    /**
587
     * Cause this TopComponent's tab to stop flashing if it was flashing.
588
     * @since 4.45
589
     */
590
    public final void cancelRequestAttention() {
591
        //Reentrancy issues - always invoke later
592
        SwingUtilities.invokeLater (new Runnable() {
593
            public void run() {
594
                if (attentionGetter != null) {
595
                    attentionGetter.stop();
596
                } else {
597
                    WindowManager.getDefault().topComponentCancelRequestAttention(
598
                        TopComponent.this);
599
                }
600
            }
601
        });
602
    }
603
    
604
    private AttentionGetter attentionGetter = null;
605
    private class AttentionGetter implements ActionListener {
606
        Timer timer = null;
607
        public AttentionGetter () {
608
            reset();
609
        }
610
        
611
        public void reset() {
612
            assert SwingUtilities.isEventDispatchThread();
613
            if (timer != null) {
614
                timer.stop();
615
            }
616
            start();
617
            timer = new Timer (3500, this);
618
            timer.setRepeats(false);
619
            timer.start();
620
        }
621
        
622
        private void start() {
623
            WindowManager.getDefault().topComponentRequestAttention(
624
                TopComponent.this);
625
        }
626
        
627
        public void kill() {
628
            timer.stop();
629
            attentionGetter = null;
630
        }
631
        
632
        private void stop() {
633
            if (timer != null) {
634
                timer.stop();
635
            }
636
            attentionGetter = null;
637
            WindowManager.getDefault().topComponentCancelRequestAttention(
638
                TopComponent.this);
639
            attentionGetter = null;
640
        }
641
        
642
        public void actionPerformed (ActionEvent ae) {
643
            stop();
644
        }
645
    }    
553
646
554
    /** Set the name of this top component.
647
    /** Set the name of this top component.
555
    * The default implementation just notifies the window manager.
648
    * The default implementation just notifies the window manager.
(-)openide/src/org/openide/windows/WindowManager.java (+14 lines)
Lines 365-370 Link Here
365
     * @since 4.13 */
365
     * @since 4.13 */
366
    protected abstract String topComponentID(TopComponent tc, String preferredID);
366
    protected abstract String topComponentID(TopComponent tc, String preferredID);
367
    
367
    
368
    /**
369
     * Cause this TopComponent's tab to flash or otherwise draw the users' attention
370
     * to it. 
371
     * @param tc A TopComponent
372
     * @since 4.45 */
373
    protected abstract void topComponentRequestAttention(TopComponent tc);
374
375
    /**
376
     * Stop this TopComponent's tab from flashing if it is flashing. 
377
     * 
378
     * @param tc A TopComponent
379
     * @since 4.45 */
380
    protected abstract void topComponentCancelRequestAttention(TopComponent tc);
381
    
368
    /** Returns unique ID for specified <code>TopComponent</code>.
382
    /** Returns unique ID for specified <code>TopComponent</code>.
369
     * @param tc <code>TopComponent</code> the component for which is ID returned
383
     * @param tc <code>TopComponent</code> the component for which is ID returned
370
     * @return unique <code>TopComponent</code> ID
384
     * @return unique <code>TopComponent</code> ID

Return to bug 48811