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 33949
Collapse All | Expand All

(-)NavigationView.java (-3 / +178 lines)
Lines 19-30 Link Here
19
19
20
import java.lang.ref.WeakReference;
20
import java.lang.ref.WeakReference;
21
import java.lang.ref.Reference;
21
import java.lang.ref.Reference;
22
import java.lang.reflect.InvocationHandler;
23
import java.lang.reflect.InvocationTargetException;
24
import java.lang.reflect.Proxy;
22
25
23
import java.util.LinkedList;
26
import java.util.LinkedList;
27
import java.awt.*;
24
28
25
import javax.swing.ComboBoxModel;
29
import javax.swing.*;
26
import javax.swing.JComboBox;
27
import javax.swing.JEditorPane;
28
import javax.swing.event.ListDataEvent;
30
import javax.swing.event.ListDataEvent;
29
31
30
import org.openide.cookies.SourceCookie;
32
import org.openide.cookies.SourceCookie;
Lines 147-152 Link Here
147
        return rootChangeListener = new RootL();
149
        return rootChangeListener = new RootL();
148
    }
150
    }
149
151
152
    private JCBRender cellRender = null;
150
    /**
153
    /**
151
     * Finds the context where the view is actually used.
154
     * Finds the context where the view is actually used.
152
     */
155
     */
Lines 171-176 Link Here
171
            topComponent.addPropertyChangeListener(rootChangeListener);
174
            topComponent.addPropertyChangeListener(rootChangeListener);
172
        }
175
        }
173
        getExplorerManager().addPropertyChangeListener(rootChangeListener);
176
        getExplorerManager().addPropertyChangeListener(rootChangeListener);
177
        
178
        if (cellRender == null && topComponent != null) {
179
            //System.out.println("##create renderer for: " + (topComponent==null?"warmup":topComponent.getDisplayName()));
180
            cellRender = new JCBRender();
181
            cellRender.addNotify();
182
        }
174
    }
183
    }
175
    
184
    
176
    public void removeNotify() {
185
    public void removeNotify() {
Lines 494-498 Link Here
494
            Node n = (Node)k;
503
            Node n = (Node)k;
495
            return new Node[] { new FNode(n, new FChildren(n)) };
504
            return new Node[] { new FNode(n, new FChildren(n)) };
496
        }
505
        }
506
    }
507
    
508
    private class JCBRender implements InvocationHandler {
509
        
510
        private final ListCellRenderer orig;
511
        private boolean isHackable = true;
512
        private boolean isThin = false;
513
        private JPopupMenu popup;
514
        private JList list;
515
        private int height = 0;
516
        private int width;
517
        private Component comp;
518
        private final JComboBox comboToHack;
519
        private boolean debug = false;
520
521
        public JCBRender() {
522
            this.comboToHack = NavigationView.this;
523
            this.orig = comboToHack.getRenderer();
524
            this.width = comboToHack.getWidth();
525
        }
526
        
527
        public void addNotify() {
528
            if (comboToHack.getRenderer() == orig) {
529
                comboToHack.setRenderer(getProxy());
530
                this.width = comboToHack.getWidth();
531
            }
532
        }
533
        
534
        public void removeNotify() {
535
            comboToHack.setRenderer(orig);
536
        }
537
        
538
        private int lastMaxWidth;
539
        private boolean isReshaped = false;
540
        private boolean isFirstRun = true;
541
        public void processListCellRendererComponent(JList list, Object value, int index, Component comp) {
542
            if (index < 0) return;
543
            if (index == 0) {
544
                popup = findPopupMenu(list);
545
                this.list = list;
546
                if (popup == null) {
547
                    //System.out.println("## is not hackable: " + this);
548
                    isHackable = false;
549
                    return;
550
                }
551
                height = 0;
552
                if (isReshaped) {
553
                    this.lastMaxWidth = this.width;
554
                    isReshaped = false;
555
                }
556
                this.width = comboToHack.getWidth();
557
                if (lastMaxWidth < width) lastMaxWidth = width;
558
            }
559
            Dimension size = comp.getPreferredSize();
560
            height += size.height;
561
            if (width < size.width) {
562
                width = size.width;
563
                this.comp = comp;
564
                isThin = true;
565
            }
566
            //System.out.println("##process: idx:"+index+",last:" + lastMaxWidth + ",curr:" + width + ",size:"+size.width + ",isThin:" + isThin + ",model:"+(list.getModel().getSize() - 1)+", @" + System.identityHashCode(this));
567
            if (isThin && index == list.getModel().getSize() - 1 && width != lastMaxWidth ||
568
                    isFirstRun && index == list.getModel().getSize() - 1) {
569
                isReshaped = true;
570
                isThin = false;
571
                isFirstRun = false;
572
                reshapePopup();
573
                height = 0;
574
            }
575
        }
576
        
577
        public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable {
578
            Object res = null;
579
            try {
580
                res = method.invoke(orig, args);
581
                if (isHackable && "getListCellRendererComponent".equals(method.getName())) {
582
                    Component c = (Component) res;
583
                    JList l = (JList) args[0];
584
                    Object value = args[1];
585
                    int index = ((Integer) args[2]).intValue();
586
                    processListCellRendererComponent(l, value, index, c);
587
                }
588
            } catch (IllegalArgumentException ex) {
589
                ex.printStackTrace();
590
            } catch (InvocationTargetException ex) {
591
                Throwable t = ex.getCause();
592
                if (t != null) throw t;
593
                else ex.printStackTrace();
594
            }
595
            return res;
596
        }
597
        
598
        
599
        
600
        void reshapePopup() {
601
            int preferredWidth = Math.min(width + 20, getMaxWidth());
602
            int prefferedHeight = Math.min(height, getMaxHeight());
603
            
604
            //System.out.println("revalidate: w: " + preferredWidth + ", h: " +prefferedHeight + ", @" + System.identityHashCode(this) + ", AWT: " +EventQueue.isDispatchThread());
605
            this.comp = null;
606
            popup.removeAll();
607
            scroller.remove(list);
608
            popup.setPopupSize(preferredWidth, prefferedHeight);
609
            popup.add(createScroller());
610
            popup.revalidate();
611
            popup.repaint();
612
        }
613
        
614
        private JScrollPane scroller;
615
        
616
        private JPopupMenu findPopupMenu(Component c) {
617
            Component parent = c;
618
            Component previous = c;
619
            while (parent != null && !(parent instanceof JPopupMenu)) {
620
                previous = parent;
621
                parent = parent.getParent();
622
            }
623
            
624
            if (previous instanceof JScrollPane) {
625
                scroller = (JScrollPane) previous;
626
            } else {
627
                parent = null; // unsupported component hierarchy
628
            }
629
            return (JPopupMenu) parent;
630
        }
631
        /**
632
         * Creates the scroll pane which houses the scrollable list.
633
         */
634
        private JScrollPane createScroller() {
635
            JScrollPane scroller = new JScrollPane(list, 
636
                            ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
637
                            ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
638
            scroller.setFocusable(false);
639
            scroller.getVerticalScrollBar().setFocusable(false);
640
            scroller.setBorder(null);
641
            return scroller;
642
        }
643
        
644
        private int maxWidth = -1;
645
        private int maxHeight = -1;
646
647
        private int getMaxWidth() {
648
            TopComponent tc = NavigationView.this.findParentTopComponent();
649
            if (tc != null) {
650
                maxWidth = tc.getX() + tc.getWidth() - comboToHack.getX();
651
            } else {
652
                maxWidth = Toolkit.getDefaultToolkit().getScreenSize().width >> 1;
653
            }
654
            return maxWidth;
655
        }
656
        
657
        private int getMaxHeight() {
658
            TopComponent tc = NavigationView.this.findParentTopComponent();
659
            if (tc != null) {
660
                maxHeight = tc.getY() + tc.getHeight() - comboToHack.getY() - comboToHack.getHeight();
661
            } else {
662
                maxHeight = Toolkit.getDefaultToolkit().getScreenSize().height >> 1;
663
            }
664
            return maxHeight;
665
        }
666
        
667
        public ListCellRenderer getProxy() {
668
            return (ListCellRenderer) Proxy.newProxyInstance(
669
                    this.getClass().getClassLoader(), new Class[] {ListCellRenderer.class}, this);
670
        }
671
        
497
    }
672
    }
498
}
673
}

Return to bug 33949