~ubuntu-branches/ubuntu/quantal/netbeans/quantal

« back to all changes in this revision

Viewing changes to form/src/org/netbeans/modules/form/menu/MenuEditLayer.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
30
 * If you wish your version of this file to be governed by only the CDDL
 
31
 * or only the GPL Version 2, indicate your decision by adding
 
32
 * "[Contributor] elects to include this software in this distribution
 
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 
34
 * single choice of license, a recipient has the option to distribute
 
35
 * your version of this file under either the CDDL, the GPL Version 2 or
 
36
 * to extend the choice of license to its licensees as provided above.
 
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 
38
 * Version 2 license, then the option applies only if the new code is
 
39
 * made subject to such option by the copyright holder.
 
40
 */
 
41
package org.netbeans.modules.form.menu;
 
42
 
 
43
import java.awt.BorderLayout;
 
44
import java.awt.Color;
 
45
import java.awt.Component;
 
46
import java.awt.Font;
 
47
import java.awt.Graphics;
 
48
import java.awt.Graphics2D;
 
49
import java.awt.Insets;
 
50
import java.awt.Point;
 
51
import java.awt.RenderingHints;
 
52
import java.awt.dnd.DropTarget;
 
53
import java.awt.dnd.DropTargetDragEvent;
 
54
import java.awt.dnd.DropTargetDropEvent;
 
55
import java.awt.dnd.DropTargetEvent;
 
56
import java.awt.dnd.DropTargetListener;
 
57
import java.awt.event.ComponentEvent;
 
58
import java.awt.event.ComponentListener;
 
59
import java.awt.event.KeyEvent;
 
60
import java.awt.event.KeyListener;
 
61
import java.awt.event.MouseEvent;
 
62
import java.beans.PropertyChangeEvent;
 
63
import java.beans.PropertyChangeListener;
 
64
import java.util.ArrayList;
 
65
import java.util.Collections;
 
66
import java.util.HashMap;
 
67
import java.util.List;
 
68
import java.util.Map;
 
69
import java.util.TooManyListenersException;
 
70
import javax.swing.Action;
 
71
import javax.swing.BorderFactory;
 
72
import javax.swing.Icon;
 
73
import javax.swing.JCheckBoxMenuItem;
 
74
import javax.swing.JComponent;
 
75
import javax.swing.JLayeredPane;
 
76
import javax.swing.JMenu;
 
77
import javax.swing.JMenuBar;
 
78
import javax.swing.JMenuItem;
 
79
import javax.swing.JPanel;
 
80
import javax.swing.JPopupMenu;
 
81
import javax.swing.JRadioButtonMenuItem;
 
82
import javax.swing.JSeparator;
 
83
import javax.swing.SwingUtilities;
 
84
import javax.swing.UIManager;
 
85
import javax.swing.border.Border;
 
86
import javax.swing.border.CompoundBorder;
 
87
import javax.swing.event.MouseInputAdapter;
 
88
import javax.swing.plaf.PopupMenuUI;
 
89
import org.netbeans.modules.form.*;
 
90
import org.netbeans.modules.form.actions.PropertyAction;
 
91
import org.netbeans.modules.form.assistant.AssistantMessages;
 
92
import org.netbeans.modules.form.editors.IconEditor.NbImageIcon;
 
93
import org.netbeans.modules.form.palette.PaletteItem;
 
94
import org.netbeans.modules.form.palette.PaletteUtils;
 
95
import org.openide.filesystems.FileObject;
 
96
import org.openide.nodes.Node;
 
97
import org.openide.nodes.NodeOp;
 
98
import org.openide.util.NbBundle;
 
99
 
 
100
/**
 
101
 *
 
102
 * @author joshua.marinacci@sun.com
 
103
 */
 
104
public class MenuEditLayer extends JPanel {
 
105
    /* === constants for the look of the designer === */
 
106
    public static final Border DRAG_MENU_BORDER = BorderFactory.createLineBorder(Color.BLACK,1);
 
107
    public static final Border DRAG_SEPARATOR_BORDER = BorderFactory.createLineBorder(Color.RED,1);
 
108
    public static final Color SELECTED_MENU_BACKGROUND = new Color(0xA5A6A9);
 
109
    public static final Color EMPTY_ICON_COLOR = new Color(0xDDDDDD);
 
110
    public static final int EMPTY_ICON_BORDER_WIDTH = 2;
 
111
    
 
112
    /* === private constants === */
 
113
    private static final boolean DEBUG = false;
 
114
    private static final boolean USE_NEW_ITEM_COLOR_SWITCHING = false;
 
115
    
 
116
    /* === public and package level fields. these should probably become getters and setters  ===*/
 
117
    public VisualDesignerPopupFactory hackedPopupFactory = null;
 
118
    public FormDesigner formDesigner;
 
119
    JLayeredPane layers;
 
120
    JComponent glassLayer;
 
121
    DropTargetLayer dropTargetLayer;
 
122
    boolean showMenubarWarning = false;
 
123
    
 
124
    /* === private fields === */
 
125
    private Map<JMenu, PopupMenuUI> menuPopupUIMap;
 
126
    
 
127
    public enum SelectedPortion { Icon, Text, Accelerator, All, None };
 
128
    private SelectedPortion selectedPortion = SelectedPortion.None;
 
129
    
 
130
    private KeyboardMenuNavigator keyboardMenuNavigator;
 
131
    private Map<RADVisualContainer,FormModelListener> formModelListeners;
 
132
    private DragOperation dragop;
 
133
    private FormModelListener menuBarFormListener;
 
134
    private PropertyChangeListener selectionListener;
 
135
    private boolean isAlive = true;
 
136
    private static final boolean USE_JSEPARATOR_FIX = true;
 
137
    
 
138
    /** Creates a new instance of MenuEditLayer */
 
139
    public MenuEditLayer(final FormDesigner formDesigner) {
 
140
        this.formDesigner = formDesigner;
 
141
        menuPopupUIMap = new HashMap<JMenu, PopupMenuUI>();
 
142
        formModelListeners = new HashMap<RADVisualContainer,FormModelListener>();
 
143
        
 
144
        
 
145
        setLayout(null);
 
146
        layers = new JLayeredPane();
 
147
        this.setLayout(new BorderLayout());
 
148
        this.add(layers,"Center");
 
149
        
 
150
        dragop = new DragOperation(this);
 
151
        
 
152
        glassLayer = new JComponent() {
 
153
            public void paintComponent(Graphics g) {
 
154
                if(DEBUG) {
 
155
                    g.setColor(Color.GREEN);
 
156
                    g.drawString("Glass Layer", 30,30);
 
157
                    g.drawRect(0,0,getWidth()-1,getHeight()-1);
 
158
                }
 
159
            }
 
160
        };
 
161
        
 
162
        layers.add(glassLayer, new Integer(500)); // put the glass layer over the drag layer
 
163
        glassLayer.setSize(400,400); //josh: do i need this line? probably can delete it.
 
164
        
 
165
        dropTargetLayer = new DropTargetLayer(this);
 
166
        layers.add(dropTargetLayer, new Integer(JLayeredPane.DRAG_LAYER-5)); // put the drop target layer just above the drag layer
 
167
        
 
168
        // make the extra layers resize to the main component
 
169
        this.addComponentListener(new ComponentListener() {
 
170
            public void componentResized(ComponentEvent e) {
 
171
                glassLayer.setSize(MenuEditLayer.this.getSize());
 
172
                dropTargetLayer.setSize(MenuEditLayer.this.getSize());
 
173
            }
 
174
 
 
175
            public void componentMoved(ComponentEvent arg0) {
 
176
            }
 
177
 
 
178
            public void componentShown(ComponentEvent arg0) {
 
179
            }
 
180
 
 
181
            public void componentHidden(ComponentEvent arg0) {
 
182
            }
 
183
        });
 
184
        
 
185
        MouseInputAdapter mia = new GlassLayerMouseListener();
 
186
        glassLayer.addMouseListener(mia);
 
187
        glassLayer.addMouseMotionListener(mia);
 
188
        configureSelectionListener();
 
189
        
 
190
        if (!assistantInitialized) {
 
191
            initAssistant();
 
192
        }
 
193
    }
 
194
    
 
195
    DragOperation getDragOperation() {
 
196
        return dragop;
 
197
    }
 
198
    
 
199
    private boolean assistantInitialized = false;
 
200
    private void initAssistant() {
 
201
        String missingMenubarMsg = "You cannot add a menu component to a form without a menubar";
 
202
        AssistantMessages messages = AssistantMessages.getDefault();
 
203
        messages.setMessages("missingMenubar", missingMenubarMsg); // NOI18N
 
204
        assistantInitialized = true;
 
205
    }
 
206
    
 
207
    public static boolean isMenuRelatedRADComponent(RADComponent comp) {
 
208
        if(comp == null) return false;
 
209
        return isMenuRelatedComponentClass(comp.getBeanClass());
 
210
    }
 
211
    
 
212
    public static boolean isNonMenuJSeparator(RADComponent comp) {
 
213
        if(comp == null) return false;
 
214
        if(JSeparator.class.isAssignableFrom(comp.getBeanClass())) {
 
215
            RADComponent parent = comp.getParentComponent();
 
216
            if(parent != null && JMenu.class.isAssignableFrom(parent.getBeanClass())) {
 
217
                return false;
 
218
            }
 
219
            return true;
 
220
        }
 
221
        return false;
 
222
    }
 
223
    
 
224
        
 
225
    public static boolean isMenuBarContainer(RADComponent comp) {
 
226
        if(comp == null) return false;
 
227
        Class clas = comp.getBeanClass();
 
228
        if(clas == null) return false;
 
229
        if(JMenuBar.class.isAssignableFrom(clas)) return true;
 
230
        return false;
 
231
    }
 
232
    
 
233
    public static boolean isMenuRelatedContainer(RADComponent comp) {
 
234
        if(comp == null) return false;
 
235
        Class clas = comp.getBeanClass();
 
236
        if(clas == null) return false;
 
237
        if(JMenu.class.isAssignableFrom(clas)) return true;
 
238
        if(JPopupMenu.class.isAssignableFrom(clas)) return true;
 
239
        return false;
 
240
    }
 
241
    
 
242
    public static boolean isMenuRelatedComponentClass(Class clas) {
 
243
        if(clas == null) return false;
 
244
        if(JMenuItem.class.isAssignableFrom(clas)) return true;
 
245
        if(JMenu.class.isAssignableFrom(clas)) return true;
 
246
        if(JSeparator.class.isAssignableFrom(clas)) return true;
 
247
        if(JMenuBar.class.isAssignableFrom(clas)) return true;
 
248
        return false;
 
249
    }
 
250
    
 
251
    public boolean isPossibleNewMenuComponent(PaletteItem item) {
 
252
        if(item == null) return false;
 
253
        if(item.getComponentClass() == null) return false;
 
254
        if(JMenuItem.class.isAssignableFrom(item.getComponentClass())) {
 
255
            return true;
 
256
        }
 
257
        return false;
 
258
    }
 
259
    
 
260
    
 
261
    public void startNewMenuComponentPickAndPlop(PaletteItem item, Point pt) {
 
262
        this.setVisible(true);
 
263
        this.requestFocus();
 
264
        dragop = new DragOperation(this);
 
265
        dragop.start(item, pt);
 
266
    }
 
267
    
 
268
    public void startNewMenuComponentDragAndDrop(PaletteItem item) {
 
269
        this.setVisible(true);
 
270
        this.requestFocus();
 
271
        configureGlassLayer();
 
272
        configureFormListeners();
 
273
    }
 
274
    
 
275
    
 
276
    protected void paintComponent(Graphics g) {
 
277
        super.paintComponent(g);
 
278
        if(DEBUG) {
 
279
            g.setColor(Color.RED);
 
280
            g.drawString("the MenuEditLayer is visible",5,getHeight()-5);
 
281
        }
 
282
        Graphics2D g2 = (Graphics2D) g.create();
 
283
        g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
 
284
        g2.setColor(Color.BLACK);
 
285
        /* Using the assistant now instead of text ontop of the glasspane.
 
286
         * josh: I need to delete all of the previous code related to the showMenubarWarning boolean
 
287
        if(showMenubarWarning) {
 
288
            g2.drawString("You cannot add a menu component to a form without a menubar.", 5, getHeight()-30);
 
289
        }*/
 
290
        g2.dispose();
 
291
    }
 
292
    
 
293
    
 
294
    // the public method for non-menu parts of the form editor to
 
295
    // start menu editing
 
296
    public void openAndShowMenu(RADComponent metacomp, Component comp) {
 
297
        //p("making sure the menu is open: " + metacomp +  " " + metacomp.getName());
 
298
        if(hackedPopupFactory == null) {
 
299
            this.hackedPopupFactory = new VisualDesignerPopupFactory(this);
 
300
        }
 
301
        openMenu(metacomp, comp);
 
302
        glassLayer.requestFocusInWindow();
 
303
    }
 
304
    
 
305
    void openMenu(RADComponent metacomp, Component comp) {
 
306
        getPopupFactory();
 
307
        configureGlassLayer();
 
308
        registerKeyListeners();
 
309
        configureFormListeners();
 
310
        configureSelectionListener();
 
311
        //reset the layers
 
312
        JMenu menu = (JMenu) comp;
 
313
        configureMenu(null,menu);
 
314
        showMenuPopup(menu);
 
315
        if(metacomp instanceof RADVisualContainer) {
 
316
            keyboardMenuNavigator.setCurrentMenuRAD((RADVisualContainer)metacomp);
 
317
        }
 
318
    }
 
319
    
 
320
    
 
321
    public void hideMenuLayer() {
 
322
        // tear down each menu and menu item
 
323
        unconfigureFormListeners();
 
324
        unconfigureSelectionListener();
 
325
        for(JMenu m : menuPopupUIMap.keySet()) {
 
326
            unconfigureMenu(m);
 
327
        }
 
328
        menuPopupUIMap.clear();
 
329
        if(hackedPopupFactory != null) {
 
330
            hackedPopupFactory.containerMap.clear();
 
331
            hackedPopupFactory = null;
 
332
        }
 
333
        if(dragop.isStarted()) {
 
334
            dragop.fastEnd();
 
335
        }
 
336
        // close all popup frames
 
337
        this.setVisible(false);
 
338
        if(keyboardMenuNavigator != null) {
 
339
            glassLayer.removeKeyListener(keyboardMenuNavigator);
 
340
            keyboardMenuNavigator.unconfigure();
 
341
            keyboardMenuNavigator = null;
 
342
        }
 
343
        backgroundMap.clear();
 
344
        //hackedPopupFactory.containerMap.clear();
 
345
        if(formDesigner.getHandleLayer() != null) {
 
346
            formDesigner.getHandleLayer().requestFocusInWindow();
 
347
        }
 
348
    }
 
349
    
 
350
    //josh: all this key listener stuff should go into a separate class
 
351
    private synchronized void registerKeyListeners() {
 
352
        if(keyboardMenuNavigator == null) {
 
353
            keyboardMenuNavigator = new KeyboardMenuNavigator(this);
 
354
            glassLayer.addKeyListener(keyboardMenuNavigator);
 
355
            glassLayer.addKeyListener(new KeyListener() {
 
356
 
 
357
                public void keyTyped(KeyEvent e) {
 
358
                }
 
359
 
 
360
                public void keyPressed(KeyEvent e) {
 
361
                    if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
 
362
                        dragop.fastEnd();
 
363
                    }
 
364
                }
 
365
 
 
366
                public void keyReleased(KeyEvent e) {
 
367
                }
 
368
                
 
369
            });
 
370
        }
 
371
    }
 
372
    
 
373
    private VisualDesignerPopupFactory getPopupFactory() {
 
374
        if(hackedPopupFactory == null) {
 
375
            hackedPopupFactory = new VisualDesignerPopupFactory(this);
 
376
            }
 
377
        return hackedPopupFactory;
 
378
    }
 
379
    
 
380
    private void configureGlassLayer() {
 
381
        try {
 
382
            glassLayer.setDropTarget(new DropTarget());
 
383
            glassLayer.getDropTarget().addDropTargetListener(new GlassLayerDropTargetListener());
 
384
        } catch (TooManyListenersException ex) {
 
385
            ex.printStackTrace();
 
386
        }
 
387
    }
 
388
    
 
389
    PropertyChangeListener paletteListener = null;
 
390
    private void configureFormListeners() {
 
391
        
 
392
        if(menuBarFormListener == null) {
 
393
            menuBarFormListener = new FormModelListener() {
 
394
                public void formChanged(FormModelEvent[] events) {
 
395
                    if(events != null) {
 
396
                        for(FormModelEvent evt : events) {
 
397
                            // if this is a menubar delete event
 
398
                            if(evt.getChangeType() == evt.COMPONENT_REMOVED) {
 
399
                                if(evt.getComponent() != null && 
 
400
                                        JMenuBar.class.isAssignableFrom(evt.getComponent().getBeanClass())) {
 
401
                                    hideMenuLayer();
 
402
                                }
 
403
                            }
 
404
                            if(evt.getChangeType() == evt.FORM_TO_BE_CLOSED) {
 
405
                                hideMenuLayer();
 
406
                                isAlive = false;
 
407
                            }
 
408
                            if(evt.getChangeType() == evt.COMPONENT_ADDED) {
 
409
                                if(evt.getCreatedDeleted()) {
 
410
                                    if(USE_NEW_ITEM_COLOR_SWITCHING) {
 
411
                                        configureNewComponent(evt.getComponent());
 
412
                                    }
 
413
                                }
 
414
                            }
 
415
                            
 
416
                        }
 
417
                    }
 
418
                }                
 
419
            };
 
420
            formDesigner.getFormModel().addFormModelListener(menuBarFormListener);
 
421
        }
 
422
        if(paletteListener == null) {
 
423
            paletteListener = new PropertyChangeListener() {
 
424
                public void propertyChange(PropertyChangeEvent evt) {
 
425
                    if(PaletteUtils.getSelectedItem() == null || 
 
426
                            !isMenuRelatedComponentClass(PaletteUtils.getSelectedItem().getComponentClass())) {
 
427
                        if(dragop != null && dragop.isStarted()) {
 
428
                            dragop.fastEnd();
 
429
                        }
 
430
                    }     
 
431
                }
 
432
            };
 
433
            paletteContext = formDesigner.getFormEditor().getFormDataObject().getFormFile();
 
434
            PaletteUtils.addPaletteListener(paletteListener, paletteContext);
 
435
        }
 
436
    }    
 
437
    
 
438
    FileObject paletteContext = null;
 
439
    private void unconfigureFormListeners() {
 
440
        if(menuBarFormListener != null) {
 
441
            if(formDesigner != null && formDesigner.getFormModel() != null) {
 
442
                formDesigner.getFormModel().removeFormModelListener(menuBarFormListener);
 
443
            }
 
444
        }
 
445
        if(paletteListener != null) {
 
446
            PaletteUtils.removePaletteListener(paletteListener, paletteContext);
 
447
            paletteContext = null;
 
448
            paletteListener = null;
 
449
        }
 
450
        menuBarFormListener = null;
 
451
    }    
 
452
 
 
453
    private void configureSelectionListener() {
 
454
        if(selectionListener == null) {
 
455
            selectionListener = new PropertyChangeListener() {
 
456
                public void propertyChange(PropertyChangeEvent evt) {
 
457
                    if(!isAlive) return;
 
458
                    Node[] newNodes = (Node[])evt.getNewValue();
 
459
                    List<RADComponent> selectedNodes = new ArrayList<RADComponent>();
 
460
 
 
461
                    for(Node n : newNodes) {
 
462
                        if(n instanceof RADComponentNode) {
 
463
                            RADComponentNode radn = (RADComponentNode) n;
 
464
                            selectedNodes.add(radn.getRADComponent());
 
465
                        }
 
466
                    }
 
467
                    
 
468
                    setSelectedRADComponents(selectedNodes);
 
469
                    
 
470
                }
 
471
                
 
472
            };
 
473
            formDesigner.addPropertyChangeListener("activatedNodes",selectionListener);
 
474
        }
 
475
    }
 
476
    
 
477
    private void unconfigureSelectionListener() {
 
478
        if(selectionListener != null) {
 
479
            formDesigner.removePropertyChangeListener(selectionListener);
 
480
            selectionListener = null;
 
481
        }
 
482
    }
 
483
 
 
484
    void showMenuPopup(final JMenu menu) {
 
485
        getPopupFactory();
 
486
        // if already created then just make it visible
 
487
        if(hackedPopupFactory.containerMap.containsKey(menu)) {
 
488
            JPanel view = hackedPopupFactory.containerMap.get(menu);
 
489
            view.setVisible(true);
 
490
        } else {
 
491
            if(!isConfigured(menu)) {
 
492
                configureMenu(null, menu);
 
493
            }
 
494
            final JPopupMenu popup = menu.getPopupMenu();
 
495
            
 
496
            if(!(popup.getUI() instanceof VisualDesignerPopupMenuUI)) {
 
497
                popup.setUI(new VisualDesignerPopupMenuUI(this, popup.getUI()));
 
498
            }
 
499
            if(menu.isVisible()) {
 
500
                //force popup view creation
 
501
                hackedPopupFactory.getPopup(menu, null, 0, 0);
 
502
                
 
503
                // do later so that the component will definitely be on screen by then
 
504
                SwingUtilities.invokeLater(new Runnable() {
 
505
                    public void run() {
 
506
                        try {
 
507
                            popup.show(menu,0,menu.getHeight());
 
508
                        } catch (Exception ex) {
 
509
                            ex.printStackTrace();
 
510
                            //ignore anyexceptions caused by showing the popups
 
511
                        }
 
512
                        
 
513
                    }
 
514
                });
 
515
            }
 
516
        }
 
517
        this.validate();
 
518
    }
 
519
    
 
520
    public boolean isMenuLayerComponent(RADComponent metacomp) {
 
521
        if(metacomp == null) {
 
522
            return false;
 
523
        }
 
524
        if(metacomp.getBeanClass().equals(JMenuItem.class)) {
 
525
            return true;
 
526
        }
 
527
        if(metacomp.getBeanClass().equals(JMenu.class)) {
 
528
            return true;
 
529
        }
 
530
        return false;
 
531
    }
 
532
    
 
533
    
 
534
    
 
535
    void configureMenu(final JComponent parent, final JMenu menu) {
 
536
        //p("configuring the menu: " + menu.getText());
 
537
        // make sure it will draw it's border so we can have rollovers and selection
 
538
        menu.setBorderPainted(true);
 
539
        //install the wrapper icon if not a toplevel JMenu
 
540
        if(!isTopLevelMenu(menu)) {
 
541
            if(!(menu.getIcon() instanceof WrapperIcon)) {
 
542
                menu.setIcon(new WrapperIcon(menu.getIcon()));
 
543
            }
 
544
        }
 
545
        
 
546
        // configure the maps and popups
 
547
        JPopupMenu popup = menu.getPopupMenu();
 
548
        //p("got a popup: " + popup);
 
549
        menuPopupUIMap.put(menu, popup.getUI());
 
550
        popup.setUI(new VisualDesignerPopupMenuUI(this, popup.getUI()));
 
551
        
 
552
        // get all of the components in this menu
 
553
        Component[] subComps = menu.getMenuComponents();
 
554
        //p("the current subcomps of the menu are:");
 
555
        for(Component c : subComps) {
 
556
            //p("   comp: " + c);
 
557
        }
 
558
        // if this isn't the first time this menu has been opened then the sub components
 
559
        // will have been moved to the popupPanel already, so we will find them there instead.
 
560
        JPanel popupPanel = getPopupFactory().containerMap.get(menu);
 
561
        if(popupPanel != null) {
 
562
            subComps = popupPanel.getComponents();
 
563
        }
 
564
        
 
565
        
 
566
        RADVisualContainer menuRAD = (RADVisualContainer) formDesigner.getMetaComponent(menu);
 
567
        registerForm(menuRAD,menu);
 
568
        
 
569
        // recurse for sub-menus
 
570
        for(Component c : subComps) {
 
571
            if(c instanceof JMenu) {
 
572
                configureMenu(menu, (JMenu)c);
 
573
                RADComponent rad = formDesigner.getMetaComponent(c);
 
574
                registerForm((RADVisualContainer)rad,(JMenu)c);
 
575
            } else {
 
576
                configureMenuItem(menu, (JComponent) c);
 
577
            }
 
578
        }
 
579
    }
 
580
    
 
581
    private void unconfigureMenu(final JMenu menu) {
 
582
        // restore the UI
 
583
        menu.getPopupMenu().setUI(menuPopupUIMap.get(menu));
 
584
        
 
585
        // restore all children
 
586
        JPanel popup = hackedPopupFactory.containerMap.get(menu);
 
587
        if(popup != null) {
 
588
            for(Component c : popup.getComponents()) {
 
589
                if(c instanceof JMenu) {
 
590
                    unconfigureMenu((JMenu)c);
 
591
                } else {
 
592
                    unconfigureMenuItem((JComponent) c);
 
593
                }
 
594
            }
 
595
            
 
596
            //hide the popup(s) if it's still visible
 
597
            if(menu.getPopupMenu() != null) {
 
598
                menu.getPopupMenu().setVisible(false);
 
599
            }
 
600
            popup.setVisible(false);
 
601
            //layers.remove(popup);
 
602
        }
 
603
        VisualDesignerJPanelPopup pop = hackedPopupFactory.getPopup(menu);
 
604
        if(pop != null) {
 
605
            pop.hide();
 
606
        }
 
607
        if(popup != null) {
 
608
            popup.setVisible(false);
 
609
        }
 
610
        menu.setPopupMenuVisible(false);
 
611
        hackedPopupFactory.containerMap.remove(menu);
 
612
    }
 
613
    
 
614
    private boolean isConfigured(JComponent c) {
 
615
        return menuPopupUIMap.containsKey(c);
 
616
    }
 
617
    
 
618
    
 
619
    void configureMenuItem(final JMenu parent, final JComponent c) {
 
620
        if(c instanceof JMenuItem) {
 
621
            JMenuItem item = (JMenuItem) c;
 
622
            if(!(item.getIcon() instanceof WrapperIcon)) {
 
623
                item.setIcon(new WrapperIcon(item.getIcon()));
 
624
            }
 
625
            installAcceleratorPreview(item);
 
626
            item.setBorderPainted(true);
 
627
        }
 
628
    }
 
629
    
 
630
    static final int ACCEL_PREVIEW_WIDTH = 80;
 
631
    private static final Border accel_border = new Border() {
 
632
 
 
633
        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
 
634
            g.setColor(Color.WHITE);
 
635
            int offset = 5;
 
636
            if(DropTargetLayer.isAqua()) {
 
637
                offset = 2;
 
638
            }
 
639
            int ioffset = 0;
 
640
            if(DropTargetLayer.isVista()) {
 
641
                ioffset = -2;
 
642
            }
 
643
            g.fillRect(width-ACCEL_PREVIEW_WIDTH+offset,   1,ACCEL_PREVIEW_WIDTH-0+ioffset, height+ioffset);
 
644
            g.setColor(EMPTY_ICON_COLOR);
 
645
            g.drawRect(width-ACCEL_PREVIEW_WIDTH+offset,   1,ACCEL_PREVIEW_WIDTH-1+ioffset, height+ioffset);
 
646
            g.drawRect(width-ACCEL_PREVIEW_WIDTH+offset+1, 2,ACCEL_PREVIEW_WIDTH-3+ioffset, height-2+ioffset);
 
647
            g.setColor(Color.LIGHT_GRAY);
 
648
            g.setFont(new Font("SansSerif",Font.PLAIN,10));
 
649
            String shortcut = NbBundle.getMessage(MenuEditLayer.class, "MENU_Shortcut"); // NOI18N
 
650
            g.drawString(shortcut, width-ACCEL_PREVIEW_WIDTH+15,height-3+ioffset);
 
651
        }
 
652
 
 
653
        public Insets getBorderInsets(Component c) {
 
654
            return new Insets(0,0,0,ACCEL_PREVIEW_WIDTH);
 
655
        }
 
656
 
 
657
        public boolean isBorderOpaque() {
 
658
            return true;
 
659
        }
 
660
        
 
661
    };
 
662
    
 
663
    
 
664
    //installs a special border to represent the accelerator preview
 
665
    //if the menu item already has an accelerator, then it will
 
666
    //remove the preview if necessary.
 
667
    private static void installAcceleratorPreview(JMenuItem item) {
 
668
        if(item instanceof JMenu) return;
 
669
        //detect accelerator key
 
670
        boolean already_has_accel = false;
 
671
        if(item.getAccelerator() != null) already_has_accel = true;
 
672
        if(item.getAction() != null && item.getAction().getValue(Action.ACCELERATOR_KEY) != null) already_has_accel = true;
 
673
 
 
674
        
 
675
        
 
676
        boolean already_has_accel_border = false;
 
677
        if(item.getBorder() == accel_border) {
 
678
            already_has_accel_border = true;
 
679
            //uninstall if needed
 
680
            if(already_has_accel) {
 
681
                item.setBorder(null);
 
682
                return;
 
683
            }
 
684
        }
 
685
        
 
686
        if(item.getBorder() instanceof CompoundBorder) {
 
687
            CompoundBorder comp = (CompoundBorder)item.getBorder();
 
688
            if(comp.getInsideBorder() == accel_border) {
 
689
                already_has_accel_border = true;
 
690
                //uninstall if needed
 
691
                if(already_has_accel) {
 
692
                    item.setBorder(comp.getOutsideBorder());
 
693
                    return;
 
694
                }
 
695
            }
 
696
        }
 
697
        
 
698
        if(already_has_accel_border) return;
 
699
        if(already_has_accel) return;
 
700
        
 
701
        
 
702
        if(item.getBorder() == null) {
 
703
            item.setBorder(accel_border);
 
704
            return;
 
705
        }
 
706
        
 
707
        item.setBorder(BorderFactory.createCompoundBorder(
 
708
                    item.getBorder(),accel_border));
 
709
    }
 
710
    
 
711
    
 
712
    void unconfigureMenuItem(JComponent c) {
 
713
    }
 
714
    
 
715
    
 
716
    
 
717
    //override JComponent.isOpaque to always return false
 
718
    public boolean isOpaque() {
 
719
        return false;
 
720
    }
 
721
    
 
722
    
 
723
    // returns true if parent really is an ancestor of target
 
724
    boolean isAncestor(JComponent target, JComponent parent) {
 
725
        if(!(parent instanceof JMenu)) {
 
726
            return false;
 
727
        }
 
728
        RADComponent targetRad = formDesigner.getMetaComponent(target);
 
729
        RADComponent parentRad = targetRad.getParentComponent();
 
730
        if(parentRad == null) return false;
 
731
        Object possibleParent = formDesigner.getComponent(parentRad);
 
732
        RADComponent realParentRad = formDesigner.getMetaComponent(parent);
 
733
        if(parentRad == realParentRad) {
 
734
            return true;
 
735
        }
 
736
        if(parent == possibleParent) {
 
737
            return true;
 
738
        } else {
 
739
            // recursively check up the chain to see if this is a further ancestor
 
740
            if(possibleParent instanceof JMenu) {
 
741
                return isAncestor((JMenu)possibleParent, parent);
 
742
            }
 
743
        }
 
744
        return false;
 
745
    }
 
746
    
 
747
    boolean hasSelectedDescendants(JMenu menu) {
 
748
        RADComponent comp =formDesigner.getMetaComponent(menu);
 
749
        if(comp instanceof RADVisualContainer) {
 
750
            return hasSelectedDescendants((RADVisualContainer)comp);
 
751
        }
 
752
        return false;
 
753
    }
 
754
    boolean hasSelectedDescendants(RADVisualContainer comp) {
 
755
        if(this.selectedComponents.contains(comp)) {
 
756
            return true;
 
757
        }
 
758
        for(RADComponent c : comp.getSubBeans()) {
 
759
            if(this.selectedComponents.contains(c)) return true;
 
760
            if(c instanceof RADVisualContainer) {
 
761
                boolean sel = hasSelectedDescendants((RADVisualContainer)c);
 
762
                if(sel) return true;
 
763
            }
 
764
        }
 
765
        return false;
 
766
    }
 
767
    
 
768
    JComponent getMenuParent(JComponent menu) {
 
769
        RADComponent targetRad = formDesigner.getMetaComponent(menu);
 
770
        RADComponent parentRad = targetRad.getParentComponent();
 
771
        Object possibleParent = formDesigner.getComponent(parentRad);
 
772
        if(possibleParent instanceof JComponent) {
 
773
            return (JComponent) possibleParent;
 
774
        } else {
 
775
            return null;
 
776
        }
 
777
    }
 
778
    
 
779
   
 
780
    List<RADComponent> getSelectedRADComponents() {
 
781
        return Collections.unmodifiableList(selectedComponents);
 
782
    }
 
783
    
 
784
    RADComponent getSingleSelectedComponent() {
 
785
        if(selectedComponents.isEmpty()) {
 
786
            return null;
 
787
        }
 
788
        if(selectedComponents.size() > 1) {
 
789
            setSelectedRADComponent(selectedComponents.get(0));
 
790
        }
 
791
        return selectedComponents.get(0);
 
792
    }
 
793
    
 
794
    
 
795
    private List<RADComponent> selectedComponents = new ArrayList<RADComponent>();
 
796
    
 
797
    
 
798
    boolean isComponentSelected() {
 
799
        return !selectedComponents.isEmpty();
 
800
    }
 
801
    
 
802
    void setSelectedRADComponent(RADComponent comp) {
 
803
        List<RADComponent> comps = new ArrayList<RADComponent>();
 
804
        comps.add(comp);
 
805
        setSelectedRADComponents(comps);
 
806
        formDesigner.setSelectedComponent(comp);
 
807
    }
 
808
    
 
809
    void addSelectedRADComponent(RADComponent comp) {
 
810
        List<RADComponent> comps = new ArrayList<RADComponent>();
 
811
        comps.addAll(selectedComponents);
 
812
        comps.add(comp);
 
813
        setSelectedRADComponents(comps);
 
814
        formDesigner.addComponentToSelection(comp);
 
815
    }
 
816
    
 
817
    void setSelectedRADComponents(List<RADComponent> comps) {
 
818
        try {
 
819
            //clear old bgs first
 
820
            for(RADComponent rad : selectedComponents) {
 
821
                if(isMenuRelatedRADComponent(rad) && !isMenuBarContainer(rad) && !isNonMenuJSeparator(rad)) { // don't mess w/ the menubar's background
 
822
                    JComponent c = (JComponent) formDesigner.getComponent(rad);
 
823
                    if(c != null) { // could be null if comp was just deleted
 
824
                        c.setBackground(getNormalBackground(rad, c));
 
825
                    }
 
826
                }
 
827
            }
 
828
 
 
829
            selectedComponents.clear();
 
830
            selectedComponents.addAll(comps);
 
831
 
 
832
            //check for non-menu comps
 
833
            for(RADComponent c : selectedComponents) {
 
834
                if (!isMenuRelatedRADComponent(c) || isNonMenuJSeparator(c)) {
 
835
                    setVisible(false);
 
836
                    return;
 
837
                }
 
838
            }
 
839
 
 
840
            registerKeyListeners();
 
841
 
 
842
            for(RADComponent rad : selectedComponents) {
 
843
                JComponent c = (JComponent) formDesigner.getComponent(rad);
 
844
                if(c != null) {
 
845
                    if(!isMenuBarContainer(rad)) { // don't mess w/ the menubar's background
 
846
                        c.setBackground(getSelectedBackground(c));
 
847
                    }
 
848
                    makeSureShowingOnScreen(rad, c);
 
849
                    if (c instanceof JMenu) {
 
850
                        showMenuPopup((JMenu) c);
 
851
                    }
 
852
                    }
 
853
                }
 
854
 
 
855
            repaint();
 
856
        
 
857
        } catch (Exception ex) {
 
858
            ex.printStackTrace();
 
859
        }
 
860
    }
 
861
 
 
862
    private String getComponentDefaultsPrefix(JComponent c) {
 
863
        if(c instanceof JMenuBar) {
 
864
            return "MenuBar";
 
865
        }
 
866
        if(c instanceof JMenu) {
 
867
            return "Menu";
 
868
        }
 
869
        if(c instanceof JCheckBoxMenuItem) {
 
870
            return "CheckBoxMenuItem";
 
871
        }
 
872
        if(c instanceof JRadioButtonMenuItem) {
 
873
            return "RadioButtonMenuItem";
 
874
        }
 
875
        return "MenuItem";
 
876
    }
 
877
    
 
878
    private Color getNormalBackground(RADComponent metacomp, JComponent c) {
 
879
        RADProperty prop = metacomp.getBeanProperty("background"); // NOI18N
 
880
        Color color = null;
 
881
        if (prop != null) {
 
882
            try {
 
883
                Object value = prop.getTargetValue();
 
884
                if (value instanceof Color) {
 
885
                    color = (Color)value;
 
886
                }
 
887
            } catch (Exception ex) {}
 
888
        }
 
889
        if (color == null) {
 
890
            // fallback - for example subclass of menu component
 
891
            // that hides background property
 
892
            color = backgroundMap.get(c);
 
893
        }
 
894
        return color;
 
895
    }
 
896
 
 
897
    private Map<JComponent, Color> backgroundMap = new HashMap<JComponent,Color>();
 
898
    private Color getSelectedBackground(JComponent c) {
 
899
        //don't put into the map twice
 
900
        if(!backgroundMap.containsKey(c)) {
 
901
            backgroundMap.put(c,c.getBackground());
 
902
        }
 
903
        return SELECTED_MENU_BACKGROUND;
 
904
    }
 
905
    
 
906
    private Color getNormalForeground(JComponent c) {
 
907
        String prefix = getComponentDefaultsPrefix(c);
 
908
        Color color = UIManager.getDefaults().getColor(prefix+".foreground");
 
909
        if(color == null) {
 
910
            color = Color.BLACK;
 
911
        }
 
912
        return color;
 
913
    }
 
914
    
 
915
    
 
916
    
 
917
    private void makeSureShowingOnScreen(RADComponent rad, JComponent comp) {
 
918
        if(!this.isVisible()) {
 
919
            this.setVisible(true);
 
920
            registerKeyListeners();
 
921
            if(rad instanceof RADVisualContainer) {
 
922
                keyboardMenuNavigator.setCurrentMenuRAD((RADVisualContainer)rad);
 
923
            } else {
 
924
                keyboardMenuNavigator.setCurrentMenuRAD((RADVisualContainer)rad.getParentComponent());
 
925
            }
 
926
        }
 
927
        
 
928
        List<RADComponent> path = new ArrayList<RADComponent>();
 
929
        RADComponent temp = rad.getParentComponent();
 
930
        while(true) {
 
931
            if(temp == null) break;
 
932
            path.add(temp);
 
933
            temp = temp.getParentComponent();
 
934
            if(!isMenuRelatedRADComponent(temp)) {
 
935
                break;
 
936
            }
 
937
        }
 
938
        
 
939
        // go backwards, top to bottom
 
940
        for(int i = path.size()-1; i>=0; i--) {
 
941
            RADComponent r = path.get(i);
 
942
            JComponent c = (JComponent) formDesigner.getComponent(r);
 
943
            if(c instanceof JMenu) {
 
944
                showMenuPopup((JMenu)c);
 
945
            }
 
946
        }
 
947
        
 
948
    }
 
949
    
 
950
    
 
951
 
 
952
    
 
953
    private void showContextMenu(Point popupPos) {
 
954
        ComponentInspector inspector = ComponentInspector.getInstance();
 
955
        Node[] selectedNodes = inspector.getSelectedNodes();
 
956
        JPopupMenu popup = NodeOp.findContextMenu(selectedNodes);
 
957
        if(!this.isVisible()) {
 
958
            this.setVisible(true);
 
959
        }
 
960
        if (popup != null) {
 
961
            popup.show(this, popupPos.x, popupPos.y);
 
962
        }
 
963
    }
 
964
 
 
965
    
 
966
    // returns true if this is a menu container that should be highlighted if the component
 
967
    // tcomp is dragged over it.
 
968
    public boolean canHighlightContainer(RADVisualContainer targetContainer, RADVisualComponent tcomp) {
 
969
        Class beanclass = tcomp.getBeanClass();
 
970
        if(targetContainer != null && targetContainer.isMenuComponent() && targetContainer.canAddComponent(beanclass)) {
 
971
            return true;
 
972
        }
 
973
        return false;
 
974
    }
 
975
    
 
976
    // is this rollover code still being used?
 
977
    // this turns on and off the rollover highlight as well as auto-opening the menu
 
978
    // if it is a menu
 
979
    private JComponent prevRollover = null;
 
980
    public void rolloverContainer(RADVisualContainer targetContainer) {
 
981
        if(targetContainer == null && prevRollover != null) {
 
982
            clearRollover();
 
983
        }
 
984
        if(targetContainer != null) {
 
985
            JComponent rollover = (JComponent) formDesigner.getComponent(targetContainer);
 
986
            if(rollover != prevRollover){
 
987
                clearRollover();
 
988
            }
 
989
            prevRollover = rollover;
 
990
            prevRollover.setBorder(new Border() {
 
991
 
 
992
                public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
 
993
                    Graphics2D g2 = (Graphics2D) g;
 
994
                    g2.setStroke(DropTargetLayer.DROP_TARGET_LINE_STROKE);
 
995
                    g2.setColor(DropTargetLayer.DROP_TARGET_COLOR);
 
996
                    g2.drawRect(x,y,width,height);
 
997
                }
 
998
 
 
999
                public Insets getBorderInsets(Component c) {
 
1000
                    return new Insets(2,2,2,2);
 
1001
                }
 
1002
 
 
1003
                public boolean isBorderOpaque() {
 
1004
                    return false;
 
1005
                }
 
1006
                //BorderFactory.createLineBorder(Color.ORANGE,2)
 
1007
            });
 
1008
            prevRollover.repaint();
 
1009
            if(rollover instanceof JMenu) {
 
1010
                formDesigner.openMenu(targetContainer);
 
1011
                //openMenu(targetContainer,rollover);
 
1012
            }
 
1013
        }
 
1014
    }
 
1015
    
 
1016
    public void clearRollover() {
 
1017
        if(prevRollover==null) return;
 
1018
        prevRollover.setBorder(BorderFactory.createEmptyBorder());
 
1019
        prevRollover.repaint();
 
1020
        prevRollover = null;
 
1021
    }
 
1022
    
 
1023
    
 
1024
    void addRadComponentToBefore(RADVisualComponent payloadRad, JComponent target) {
 
1025
        addRadComponentTo(payloadRad, target, +0);
 
1026
    }
 
1027
    
 
1028
    void addRadComponentToAfter(RADVisualComponent payloadRad, JComponent target) {
 
1029
        addRadComponentTo(payloadRad, target, +1);
 
1030
    }
 
1031
    private void addRadComponentTo(RADVisualComponent payloadRad, JComponent target, int offset) {
 
1032
        try {
 
1033
            JComponent targetParent = getMenuParent(target);
 
1034
            if(target.getParent() instanceof JMenuBar) {
 
1035
                targetParent = (JComponent) target.getParent();
 
1036
            }
 
1037
            //p("target parent = " + targetParent);
 
1038
            RADVisualComponent targetRad = (RADVisualComponent) formDesigner.getMetaComponent(target);
 
1039
            //p("target rad = " + targetRad);
 
1040
            RADVisualContainer targetParentRad = (RADVisualContainer) formDesigner.getMetaComponent(targetParent);
 
1041
            //p("target parent rad = " + targetParentRad);
 
1042
            
 
1043
            assert targetParentRad != null;
 
1044
            
 
1045
            //p("=== inserting before drop target component ===");
 
1046
            int index2 = targetParentRad.getIndexOf(targetRad) + offset;
 
1047
            //p("inserting at index: " + index2);
 
1048
            FormModelEvent fme2 = formDesigner.getFormModel().fireComponentAdded(payloadRad, false);
 
1049
            formDesigner.getFormModel().addVisualComponent(payloadRad, targetParentRad, new Integer(index2), true);
 
1050
        } catch (Exception ex) {
 
1051
            ex.printStackTrace();
 
1052
        }
 
1053
        
 
1054
    }
 
1055
    
 
1056
    boolean addRadComponentToEnd(JComponent targetComponent, MetaComponentCreator creator) {
 
1057
        RADVisualContainer targetContainer = (RADVisualContainer) formDesigner.getMetaComponent(targetComponent);
 
1058
        //p("target container = " + targetContainer);
 
1059
        Object constraints = null;
 
1060
        boolean added = creator.addPrecreatedComponent(targetContainer, constraints);
 
1061
        //p("added comp: " + creator.getPrecreatedMetaComponent());
 
1062
        return added;
 
1063
    }
 
1064
    
 
1065
    void moveRadComponentInto(JComponent payload, JComponent targetMenu) {
 
1066
        try {
 
1067
            
 
1068
            //check if dragging onto self
 
1069
            if(payload == targetMenu) {
 
1070
                return;
 
1071
            }
 
1072
            
 
1073
            //check if dragging to a descendant node
 
1074
            if(isAncestor(targetMenu, payload)) {
 
1075
                return;
 
1076
            }
 
1077
            
 
1078
            JComponent payloadParent = getMenuParent(payload);
 
1079
            if(payloadParent == null) {
 
1080
                payloadParent = (JComponent) payload.getParent();
 
1081
            }
 
1082
            //p("payload parent = " + payloadParent);
 
1083
            RADVisualComponent payloadRad = (RADVisualComponent) formDesigner.getMetaComponent(payload);
 
1084
            //p("payload rad = " + payloadRad);
 
1085
            RADVisualContainer payloadParentRad = (RADVisualContainer) formDesigner.getMetaComponent(payloadParent);
 
1086
            //p("payload parent rad = " + payloadParentRad);
 
1087
            
 
1088
            if(payloadRad != null && payloadParentRad == null) {
 
1089
                p("MenuDesigner: WARNING! their is a payload rad without a parent! how did we get here!");
 
1090
            }
 
1091
            
 
1092
            // remove the component from it's old location
 
1093
            // if no payload rad then that probably means this is a new component from the palette
 
1094
            if(payloadRad != null && payloadParentRad != null) {
 
1095
                int index = payloadParentRad.getIndexOf(payloadRad);
 
1096
                payloadParentRad.remove(payloadRad);
 
1097
                FormModelEvent fme = formDesigner.getFormModel().fireComponentRemoved(payloadRad, payloadParentRad, index, false);
 
1098
            }
 
1099
            
 
1100
            RADVisualContainer targetMenuRad = (RADVisualContainer) formDesigner.getMetaComponent(targetMenu);
 
1101
            //p("target menu rad = " + targetMenuRad);
 
1102
            //add inside the target menu
 
1103
            //p("=== inserting at end of a menu ===");
 
1104
            //add to end of the toplevel menu
 
1105
            targetMenuRad.add(payloadRad, -1);
 
1106
            targetMenuRad.getLayoutSupport().addComponents(new RADVisualComponent[] { payloadRad }, null, -1);
 
1107
            FormModelEvent fme2 = formDesigner.getFormModel().fireComponentAdded(payloadRad, false);
 
1108
            return;
 
1109
        } catch (Exception ex) {
 
1110
            ex.printStackTrace();
 
1111
        }        
 
1112
    }
 
1113
    
 
1114
    void moveRadComponentToBefore(JComponent payload, JComponent target) {
 
1115
        moveRadComponentTo(payload, target, 0);
 
1116
    }
 
1117
    void moveRadComponentToAfter(JComponent payload, JComponent target) {
 
1118
        moveRadComponentTo(payload, target, 1);
 
1119
    }
 
1120
    private void moveRadComponentTo(JComponent payload, JComponent target, int offset) {
 
1121
        try {
 
1122
            if(payload == target) {
 
1123
                return;
 
1124
            }
 
1125
            //check if dragging to a descendant node
 
1126
            if(isAncestor(target, payload)) {
 
1127
                return;
 
1128
            }
 
1129
            JComponent payloadParent = getMenuParent(payload);
 
1130
            /*
 
1131
            if(payloadParent == null) {
 
1132
                payloadParent = (JComponent) payload.getParent();
 
1133
            }*/
 
1134
            //p("payload parent = " + payloadParent);
 
1135
            
 
1136
            JComponent targetParent = getMenuParent(target);
 
1137
            
 
1138
            if(targetParent == null) {
 
1139
                targetParent = (JComponent) target.getParent();
 
1140
            }
 
1141
            //p("target parent = " + targetParent);
 
1142
            
 
1143
            RADVisualComponent payloadRad = (RADVisualComponent) formDesigner.getMetaComponent(payload);
 
1144
            //p("payload rad = " + payloadRad);
 
1145
            RADVisualComponent targetRad = (RADVisualComponent) formDesigner.getMetaComponent(target);
 
1146
            //p("target rad = " + targetRad);
 
1147
            RADVisualContainer payloadParentRad = (RADVisualContainer) formDesigner.getMetaComponent(payloadParent);
 
1148
            //p("payload parent rad = " + payloadParentRad);
 
1149
            RADVisualContainer targetParentRad = (RADVisualContainer) formDesigner.getMetaComponent(targetParent);
 
1150
            //p("target parent rad = " + targetParentRad);
 
1151
            
 
1152
 
 
1153
            //if a toplevel menu dragged next to another toplevel menu
 
1154
            if(payload instanceof JMenu && payload.getParent() instanceof JMenuBar 
 
1155
                    && target instanceof JMenu && target.getParent() instanceof JMenuBar) {
 
1156
                //remove from old spot
 
1157
                targetParent = (JComponent) target.getParent();
 
1158
                payloadParent = (JComponent) payload.getParent();
 
1159
                payloadParentRad = (RADVisualContainer) formDesigner.getMetaComponent(payloadParent);
 
1160
                targetParentRad = (RADVisualContainer) formDesigner.getMetaComponent(targetParent);
 
1161
                //p("new payload parent rad = " + payloadParentRad);
 
1162
            }
 
1163
            
 
1164
            //p("=== removing ===");
 
1165
            //skip if no payload rad, which probably means this is a new component from the palette
 
1166
            if(payloadRad != null && payloadParentRad != null) {
 
1167
                //p("=== did a remove ===");
 
1168
                int index = payloadParentRad.getIndexOf(payloadRad);
 
1169
                payloadParentRad.remove(payloadRad);
 
1170
                FormModelEvent fme = formDesigner.getFormModel().fireComponentRemoved(payloadRad, payloadParentRad, index, false);
 
1171
            }
 
1172
 
 
1173
                
 
1174
            //if dragged component into a toplevel menu
 
1175
            if(targetParent == null && target instanceof JMenu && target.getParent() instanceof JMenuBar) {
 
1176
                //p("=== inserting at end of a toplevel menu ===");
 
1177
                targetParentRad = (RADVisualContainer) targetRad;
 
1178
                //add to end of the toplevel menu
 
1179
                targetParentRad.add(payloadRad, -1);
 
1180
                targetParentRad.getLayoutSupport().addComponents(new RADVisualComponent[] { payloadRad }, null, -1);
 
1181
                FormModelEvent fme2 = formDesigner.getFormModel().fireComponentAdded(payloadRad, false);
 
1182
                return;
 
1183
            }
 
1184
            
 
1185
            // insert if target exists, else the item was removed by dragging out of the menu
 
1186
            if(targetParentRad != null) {
 
1187
                //p("=== inserting before drop target component ===");
 
1188
                int index2 = targetParentRad.getIndexOf(targetRad) + offset;
 
1189
                //p("index of target = " + index2);
 
1190
                targetParentRad.add(payloadRad, index2);
 
1191
                targetParentRad.getLayoutSupport().addComponents(new RADVisualComponent[] { payloadRad }, 
 
1192
                        null, index2);
 
1193
                FormModelEvent fme2 = formDesigner.getFormModel().fireComponentAdded(payloadRad, false);
 
1194
            }
 
1195
        } catch (Exception ex) {
 
1196
            ex.printStackTrace();
 
1197
        }
 
1198
    }
 
1199
    
 
1200
    public static boolean addComponentToEndOfMenu(RADComponent targetContainer, PaletteItem paletteItem) {
 
1201
        FormModel model = targetContainer.getFormModel();
 
1202
        MetaComponentCreator creator = model.getComponentCreator();
 
1203
        RADVisualComponent precreated = creator.precreateVisualComponent(
 
1204
                paletteItem.getComponentClassSource());
 
1205
        JComponent newComponent = (JComponent) precreated.getBeanInstance();
 
1206
        boolean added = creator.addPrecreatedComponent(targetContainer, null);
 
1207
        return added;
 
1208
    }
 
1209
    
 
1210
    
 
1211
    // change the look of the component to reflect the newly added state.
 
1212
    // this mainly means making the foreground color light gray.
 
1213
    void configureNewComponent(RADComponent item) {
 
1214
        if(item != null) {
 
1215
            JComponent c = (JComponent) formDesigner.getComponent(item);
 
1216
            if(c != null) {
 
1217
                c.setForeground(Color.LIGHT_GRAY);
 
1218
            }
 
1219
        }
 
1220
    }
 
1221
    
 
1222
    
 
1223
    // change the look of the component to reflect the fully edited state
 
1224
    private void configureEditedComponent(JComponent c) {
 
1225
        //p("configuring an edited component");
 
1226
        if(c == null) return;
 
1227
        if(USE_NEW_ITEM_COLOR_SWITCHING) {
 
1228
            if(c.getForeground() == Color.LIGHT_GRAY) {
 
1229
                c.setForeground(getNormalForeground(c));
 
1230
            }
 
1231
        }
 
1232
    }
 
1233
    
 
1234
    void configureEditedComponent(RADComponent c) {
 
1235
        if(c != null) {
 
1236
            configureEditedComponent((JComponent)formDesigner.getComponent(c));
 
1237
        }
 
1238
    }
 
1239
 
 
1240
    //listens to see if this particular menu has been changed
 
1241
    private void registerForm(final RADVisualContainer metacomp, final JMenu menu) {
 
1242
        // don't double register
 
1243
        if(!formModelListeners.containsKey(metacomp)) {
 
1244
            FormModelListener fml = new FormModelListener() {
 
1245
                public void formChanged(FormModelEvent[] events) {
 
1246
                    p("form changed starting");
 
1247
                    if (events != null) {
 
1248
                        for(FormModelEvent evt : events) {
 
1249
                            
 
1250
                            p("form model update: " + evt.getChangeType() + " = ");
 
1251
                            switch(evt.getChangeType()) {
 
1252
                            case FormModelEvent.COMPONENT_PROPERTY_CHANGED: p("COMPONENT_PROPERTY_CHANGED");break;
 
1253
                            case FormModelEvent.COMPONENT_ADDED: p("COMPONENT_ADDED");break;
 
1254
                            case FormModelEvent.COMPONENT_REMOVED: p("COMPONENT_REMOVED");break;
 
1255
                            case FormModelEvent.COMPONENTS_REORDERED: p("COMPONENTS_REORDERED");break;
 
1256
                            case FormModelEvent.BINDING_PROPERTY_CHANGED: p("BINDING_PROPERTY_CHANGED");break;
 
1257
                            case FormModelEvent.FORM_LOADED: p("FORM_LOADED"); break;
 
1258
                            case FormModelEvent.FORM_TO_BE_CLOSED: p("FORM_TO_BE_CLOSED"); break;
 
1259
                            default: p("unknown type");
 
1260
                            }
 
1261
                            if(evt.getComponent() != null) {
 
1262
                                p(" " + evt.getComponent().getName());
 
1263
                            };
 
1264
                            
 
1265
                            if(evt.getChangeType() == evt.FORM_TO_BE_CLOSED) {
 
1266
                                formModelListeners.remove(metacomp);
 
1267
                                metacomp.getFormModel().addFormModelListener(this);
 
1268
                                continue;
 
1269
                            }
 
1270
                            
 
1271
                            if(evt.getChangeType() == evt.COMPONENT_PROPERTY_CHANGED) {
 
1272
                                if("action".equals(evt.getPropertyName())) {
 
1273
                                    configureEditedComponent(evt.getComponent());
 
1274
                                }
 
1275
                            }
 
1276
                            if(evt.getChangeType() == evt.COMPONENT_PROPERTY_CHANGED || evt.getChangeType() == evt.BINDING_PROPERTY_CHANGED) {
 
1277
                                if(evt.getContainer() == metacomp || evt.getComponent() == metacomp) {
 
1278
                                    rebuildOnScreenMenu(metacomp);
 
1279
                                }
 
1280
                                updateIcon(evt.getComponent());
 
1281
                            }
 
1282
                            
 
1283
                            if(evt.getChangeType() == evt.COMPONENT_ADDED) {
 
1284
                                updateIcon(evt.getComponent());
 
1285
                                //reinstall the accelerator preview when moving items around
 
1286
                                if(evt.getComponent() != null) {
 
1287
                                    Component co = (Component) formDesigner.getComponent(evt.getComponent());
 
1288
                                    if(co instanceof JMenuItem) {
 
1289
                                        installAcceleratorPreview((JMenuItem)co);
 
1290
                                    }
 
1291
                                }
 
1292
                            }
 
1293
                            
 
1294
                            // if this menu was deleted then make sure it's popup is hidden and removed
 
1295
                            if(evt.getChangeType() == evt.COMPONENT_REMOVED) {
 
1296
                                if(evt.getComponent() == metacomp) {
 
1297
                                    p("this component was removed");
 
1298
                                    unconfigureMenu(menu);
 
1299
                                    continue;
 
1300
                                }
 
1301
                            }
 
1302
                            // if something added to the menu we monitor
 
1303
                            if(evt.getChangeType() == evt.COMPONENT_ADDED ||
 
1304
                                    evt.getChangeType() == evt.COMPONENTS_REORDERED ||
 
1305
                                    evt.getChangeType() == evt.COMPONENT_REMOVED) {
 
1306
                                if(evt.getContainer() == metacomp) {
 
1307
                                    // then rebuild the menu
 
1308
                                    rebuildOnScreenMenu(metacomp);
 
1309
                                    return;
 
1310
                                }
 
1311
                                if(evt.getContainer() == getFormMenuBar()) {
 
1312
                                    p("it was a rad though: " + getFormMenuBar());
 
1313
                                    JComponent comp = (JComponent) formDesigner.getComponent(getFormMenuBar());
 
1314
                                    p("comp = " + comp);
 
1315
                                    //comp.revalidate();
 
1316
                                    RADVisualContainer rad = (RADVisualContainer) getFormMenuBar();
 
1317
                                    comp.removeAll();
 
1318
                                    for(RADVisualComponent c : rad.getSubComponents()) {
 
1319
                                        p("c = " + c);
 
1320
                                        if(c!=null) {
 
1321
                                            comp.add((JComponent)formDesigner.getComponent(c));
 
1322
                                        }
 
1323
                                    }
 
1324
                                }
 
1325
                            }
 
1326
                        }
 
1327
                    }
 
1328
                    p("form changed ending");
 
1329
                }
 
1330
            };
 
1331
            formModelListeners.put(metacomp,fml);
 
1332
            metacomp.getFormModel().addFormModelListener(fml);
 
1333
        }
 
1334
    }
 
1335
    
 
1336
    private void rebuildOnScreenMenu(RADVisualContainer menuRAD) {
 
1337
        if(menuRAD == null) return;
 
1338
        if(hackedPopupFactory == null) return;
 
1339
        p("** rebuildOnScreenMenu() called on: " + menuRAD.getName());
 
1340
        JMenu menu = (JMenu) formDesigner.getComponent(menuRAD);
 
1341
        if(hackedPopupFactory.containerMap.containsKey(menu)) {
 
1342
            JPanel popupContainer = hackedPopupFactory.containerMap.get(menu);
 
1343
            if(popupContainer == null) return;
 
1344
            //p("looking over components left");
 
1345
            for(Component c : popupContainer.getComponents()) {
 
1346
                //p("found comp: " + c);
 
1347
                if(c instanceof JMenu) {
 
1348
                    unconfigureMenu((JMenu)c);
 
1349
                } else {
 
1350
                    unconfigureMenuItem((JComponent)c);
 
1351
                }
 
1352
            }
 
1353
            //p("removing all from container");;
 
1354
            popupContainer.removeAll();
 
1355
            // rebuild it
 
1356
            for(RADVisualComponent child : menuRAD.getSubComponents()) {
 
1357
                if(child != null) {
 
1358
                    JComponent jchild = (JComponent) formDesigner.getComponent(child);
 
1359
                    //p("checking: " + jchild);
 
1360
                    if(!isConfigured(jchild)) {
 
1361
                        //p("not configured!");
 
1362
                        if(jchild instanceof JMenu) {
 
1363
                            configureMenu(menu, (JMenu)jchild);
 
1364
                        } else {
 
1365
                            configureMenuItem(menu,jchild);
 
1366
                        }
 
1367
                    }
 
1368
                    popupContainer.add(jchild);
 
1369
                }
 
1370
            }
 
1371
            
 
1372
            // repack it
 
1373
            popupContainer.setSize(popupContainer.getLayout().preferredLayoutSize(popupContainer));
 
1374
            validate();
 
1375
            popupContainer.repaint();
 
1376
        } else {
 
1377
            //p("menu popup not built yet: " + menu.getName());
 
1378
        }
 
1379
    }
 
1380
    
 
1381
    private void updateIcon(RADComponent rad) {
 
1382
        p("updating icon for rad: " + rad);
 
1383
        try {
 
1384
            Component comp = (Component) formDesigner.getComponent(rad);
 
1385
            if(comp instanceof JMenuItem) {
 
1386
                JMenuItem item = (JMenuItem) comp;
 
1387
                //p("item rad = " + rad);
 
1388
                RADProperty icon_prop = rad.getBeanProperty("icon");
 
1389
                //p("icon prop = " + icon_prop);
 
1390
                Object value = icon_prop.getValue();
 
1391
                //p("value = " + value);
 
1392
                // extract the new value
 
1393
                Icon icon = null;
 
1394
                if(value instanceof Icon) {
 
1395
                    icon = (Icon) value;
 
1396
                }
 
1397
                if(value instanceof NbImageIcon) {
 
1398
                    icon = ((NbImageIcon)value).getIcon();
 
1399
                }
 
1400
                if(value instanceof ResourceValue) {
 
1401
                    ResourceValue rv = (ResourceValue) value;
 
1402
                    //p("design value = " + rv.getDesignValue());
 
1403
                    Object designValue = rv.getDesignValue();
 
1404
                    if(designValue instanceof Icon) {
 
1405
                        //p("updating icon w/ design value");
 
1406
                        icon = (Icon) designValue;
 
1407
                    }
 
1408
                    if(designValue instanceof NbImageIcon) {
 
1409
                        icon = ((NbImageIcon)designValue).getIcon();
 
1410
                    }
 
1411
                }
 
1412
                // do the actual update
 
1413
                if(!(item.getIcon() instanceof WrapperIcon) && !isTopLevelMenu(item)) {
 
1414
                    item.setIcon(new WrapperIcon(item.getIcon()));
 
1415
                }
 
1416
                
 
1417
                if(item.getIcon() instanceof WrapperIcon) {
 
1418
                    ((WrapperIcon)item.getIcon()).setIcon(icon);
 
1419
                } else { // we should never get here
 
1420
                    item.setIcon(icon);
 
1421
                }
 
1422
            }
 
1423
        } catch (Throwable thr) {
 
1424
            thr.printStackTrace();
 
1425
        }
 
1426
        
 
1427
    }
 
1428
    
 
1429
    private static void p(String string) {
 
1430
        //turn off for now
 
1431
        if(DEBUG) {
 
1432
            System.out.println(string);
 
1433
        }
 
1434
    }
 
1435
    
 
1436
    
 
1437
    
 
1438
    //returns true if this array contains a menu component
 
1439
    public static boolean containsMenuTypeComponent(RADVisualComponent[] comps) {
 
1440
        if(comps == null) return false;
 
1441
        if(comps.length < 1) return false;
 
1442
        for(RADVisualComponent c : comps) {
 
1443
            if(JMenuItem.class.isAssignableFrom(c.getBeanClass())) return true;
 
1444
            if(JMenuBar.class.isAssignableFrom(c.getBeanClass())) return true;
 
1445
            if(JMenu.class.isAssignableFrom(c.getBeanClass())) return true;
 
1446
        }
 
1447
        return false;
 
1448
    }
 
1449
    
 
1450
    public static boolean containsMenuBar(RADVisualComponent[] comps) {
 
1451
        if(comps == null) return false;
 
1452
        if(comps.length < 1) return false;
 
1453
        for(RADVisualComponent c : comps) {
 
1454
            if(JMenuBar.class.isAssignableFrom(c.getBeanClass())) return true;
 
1455
        }
 
1456
        return false;
 
1457
    }
 
1458
    
 
1459
    // returns true if this container is a menubar or menu, else false
 
1460
    public static boolean isValidMenuContainer(RADVisualContainer cont) {
 
1461
        if(cont == null) return false;
 
1462
        if(JMenuBar.class.isAssignableFrom(cont.getBeanClass())) return true;
 
1463
        if(JMenu.class.isAssignableFrom(cont.getBeanClass())) return true;
 
1464
        return false;
 
1465
    }
 
1466
    
 
1467
    public static boolean isTopLevelMenu(JComponent comp) {
 
1468
        if(comp == null) return false;
 
1469
        if(comp instanceof JMenu) {
 
1470
            if(comp.getParent() instanceof JMenuBar) return true;
 
1471
        }
 
1472
        return false;
 
1473
    }
 
1474
    
 
1475
    public boolean doesFormContainMenuBar() {
 
1476
        for(RADComponent comp : formDesigner.getFormModel().getAllComponents()) {
 
1477
            if(JMenuBar.class.isAssignableFrom(comp.getBeanClass())) {
 
1478
                return true;
 
1479
            }
 
1480
        }
 
1481
        return false;
 
1482
    }
 
1483
    
 
1484
    public RADComponent getFormMenuBar() {
 
1485
        for(RADComponent comp : formDesigner.getFormModel().getAllComponents()) {
 
1486
            if(JMenuBar.class.isAssignableFrom(comp.getBeanClass())) {
 
1487
                return comp;
 
1488
            }
 
1489
        }
 
1490
        return null;
 
1491
    }
 
1492
 
 
1493
 
 
1494
    private class GlassLayerMouseListener extends MouseInputAdapter {
 
1495
        Point pressPoint = null;
 
1496
        JComponent pressComp = null;
 
1497
        private boolean isEditing = false;
 
1498
        
 
1499
        public void mouseClicked(MouseEvent e) {
 
1500
        }
 
1501
        
 
1502
        public void mousePressed(MouseEvent e) {
 
1503
            p("mouse pressed: " + e);
 
1504
            p("started = " + dragop.isStarted() + " pnp = " + dragop.isPickAndPlop() + " target = " + dragop.getTargetComponent());
 
1505
            
 
1506
            //if this is a valid menu drop
 
1507
            if(dragop.isStarted() && dragop.getTargetComponent() != null &&
 
1508
                    isMenuRelatedComponentClass(dragop.getTargetComponent().getClass())) {
 
1509
                p("skipping the lower part");
 
1510
                if(e.isShiftDown()) {
 
1511
                    dragop.end(e.getPoint(), false);
 
1512
                    PaletteItem item = PaletteUtils.getSelectedItem();
 
1513
                    dragop.start(item, e.getPoint());
 
1514
                } else {
 
1515
                    dragop.end(e.getPoint(), true);                    
 
1516
                }
 
1517
                return;
 
1518
            }
 
1519
            if(shouldRedispatchToHandle()) {
 
1520
                dragop.fastEnd();
 
1521
                formDesigner.getHandleLayer().dispatchEvent(e);
 
1522
                return;
 
1523
            }
 
1524
            // drag drag ops
 
1525
            if(dragop.isStarted()) {
 
1526
                dragop.end(e.getPoint());
 
1527
                return;
 
1528
            }
 
1529
 
 
1530
            // open top level menus when clicking them
 
1531
            RADComponent rad = formDesigner.getHandleLayer().getMetaComponentAt(e.getPoint(), HandleLayer.COMP_DEEPEST);
 
1532
            if(rad != null) {
 
1533
                JComponent c = (JComponent) formDesigner.getComponent(rad);
 
1534
                if(c != null && isTopLevelMenu(c)) {
 
1535
                    if(e.getClickCount() > 1) {
 
1536
                        isEditing = true;
 
1537
                        configureEditedComponent(c);
 
1538
                        formDesigner.startInPlaceEditing(rad);
 
1539
                    } else {
 
1540
                        openMenu(rad, c);
 
1541
                        glassLayer.requestFocusInWindow();                        
 
1542
                        if(DropTargetLayer.isMultiselectPressed(e)) {
 
1543
                            addSelectedRADComponent(rad);
 
1544
                        } else {
 
1545
                            setSelectedRADComponent(rad);
 
1546
                        }
 
1547
                        if(e.isPopupTrigger()) {
 
1548
                            showContextMenu(e.getPoint());
 
1549
                            return;
 
1550
                        }
 
1551
                        if(!dragop.isStarted()) {
 
1552
                            pressPoint = e.getPoint();
 
1553
                            pressComp = c;
 
1554
                            return;
 
1555
                        }
 
1556
                    }
 
1557
                    return;
 
1558
                }
 
1559
                if(c instanceof JMenuBar) {
 
1560
                     setSelectedRADComponent(rad);
 
1561
                     if(e.isPopupTrigger()) {
 
1562
                         showContextMenu(e.getPoint());
 
1563
                         return;
 
1564
                     }
 
1565
                     return;
 
1566
                }
 
1567
            }
 
1568
 
 
1569
            JComponent c = dragop.getDeepestComponentInPopups(e.getPoint());
 
1570
 
 
1571
            
 
1572
            if(c == null && !isMenuRelatedRADComponent(rad)) {
 
1573
                p("not a menu component. going back to handle layer");
 
1574
                PaletteUtils.clearPaletteSelection();
 
1575
                hideMenuLayer();
 
1576
                formDesigner.getHandleLayer().mousePressed(e);
 
1577
                return;
 
1578
            }
 
1579
 
 
1580
            // start editing
 
1581
            if(e.getClickCount() > 1) {
 
1582
                if(c instanceof JMenuItem) {
 
1583
                    p("starting the inline editing");
 
1584
                    JMenuItem item = (JMenuItem) c;
 
1585
                    Point pt = SwingUtilities.convertPoint(glassLayer, e.getPoint(), item);
 
1586
                    SelectedPortion portion = DropTargetLayer.calculateSelectedPortion(item, pt);
 
1587
                    p("selected portion = " + portion);
 
1588
                    RADComponent radcomp = formDesigner.getMetaComponent(item);
 
1589
                    configureEditedComponent(c);
 
1590
                    if(portion == SelectedPortion.Icon) {
 
1591
                        p("editing icon");
 
1592
                        showIconEditor(radcomp);
 
1593
                    } else if (portion == SelectedPortion.Accelerator) {
 
1594
                        p("editing accel");
 
1595
                        showAcceleratorEditor(radcomp);
 
1596
                    } else {
 
1597
                        isEditing = true;
 
1598
                        formDesigner.startInPlaceEditing(radcomp);
 
1599
                    }
 
1600
                }
 
1601
            }
 
1602
            
 
1603
            // show context menu
 
1604
            if(e.isPopupTrigger()) {
 
1605
                p("showing a context menu");
 
1606
                showContextMenu(e.getPoint());
 
1607
                return;
 
1608
            }
 
1609
 
 
1610
            //prep for drag motion for menuitem to menuitem drags
 
1611
            if(!dragop.isStarted() && c instanceof JMenuItem) {
 
1612
                p("possibly starting a drag op");
 
1613
                pressPoint = e.getPoint();
 
1614
                pressComp = c;
 
1615
                return;
 
1616
            }
 
1617
        }
 
1618
        
 
1619
        public void mouseReleased(MouseEvent e) {
 
1620
            if(e.isPopupTrigger()) {
 
1621
                //p("showing a context menu");
 
1622
                showContextMenu(e.getPoint());
 
1623
                return;
 
1624
            }
 
1625
            
 
1626
            //p("mouse released: " + e);
 
1627
            if(dragop.isStarted() && !e.isShiftDown()) {
 
1628
                dragop.end(e.getPoint());
 
1629
            } else {
 
1630
                if(!isEditing) {
 
1631
                    JComponent c = (JComponent) dragop.getDeepestComponentInPopups(e.getPoint());
 
1632
                    if(c != null) { 
 
1633
                        if(c instanceof JMenuItem) {
 
1634
                            Point localPt = SwingUtilities.convertPoint(glassLayer, e.getPoint(), c);
 
1635
                            selectedPortion = DropTargetLayer.calculateSelectedPortion((JMenuItem)c, localPt);
 
1636
                            dropTargetLayer.repaint();
 
1637
                        } else {
 
1638
                            selectedPortion = SelectedPortion.None;
 
1639
                        }
 
1640
                        glassLayer.requestFocusInWindow();
 
1641
                        RADComponent rad = formDesigner.getMetaComponent(c);
 
1642
                        //add to selection if shift is down, instead of replacing
 
1643
                        if(DropTargetLayer.isMultiselectPressed(e)) {
 
1644
                            addSelectedRADComponent(rad);
 
1645
                        } else {
 
1646
                            setSelectedRADComponent(rad);
 
1647
                        }
 
1648
                    }
 
1649
                }
 
1650
                isEditing = false;
 
1651
            }
 
1652
        }
 
1653
        
 
1654
        private void showIconEditor(RADComponent comp) {
 
1655
            try {
 
1656
                RADProperty prop = comp.getBeanProperty("icon");
 
1657
                new PropertyAction(prop).actionPerformed(null);
 
1658
            } catch (Throwable th) {
 
1659
                th.printStackTrace();
 
1660
            }
 
1661
        }
 
1662
        private void showAcceleratorEditor(RADComponent comp) {
 
1663
            try {
 
1664
                RADProperty prop = comp.getBeanProperty("accelerator");
 
1665
                new PropertyAction(prop).actionPerformed(null);
 
1666
            } catch (Throwable th) {
 
1667
                th.printStackTrace();
 
1668
            }
 
1669
        }
 
1670
        
 
1671
        public void mouseEntered(MouseEvent e) {
 
1672
            if(showMenubarWarning) {
 
1673
                showMenubarWarning = false;
 
1674
                repaint();
 
1675
            }
 
1676
            if(dragop.isStarted()) {
 
1677
                if(PaletteUtils.getSelectedItem() == null && dragop.isPickAndPlop()) {
 
1678
                    dragop.fastEnd();
 
1679
                } else {
 
1680
                    dragop.setTargetVisible(true);
 
1681
                }
 
1682
            }
 
1683
            if(!dragop.isStarted() || PaletteUtils.getSelectedItem() != dragop.getCurrentItem()) {
 
1684
                PaletteItem item = PaletteUtils.getSelectedItem();
 
1685
                
 
1686
                // if not menu related at all, then jump back to handle layer
 
1687
                if(item != null && !isMenuRelatedComponentClass(item.getComponentClass())) {
 
1688
                    p("not a menu component. going back to the handle layer");
 
1689
                    hideMenuLayer();
 
1690
                    return;
 
1691
                }
 
1692
                
 
1693
                if(formDesigner.getDesignerMode() == FormDesigner.MODE_ADD && item != null) {
 
1694
                    if(JMenuBar.class.isAssignableFrom(item.getComponentClass())) {
 
1695
                        p("dragging in a menu bar. go back to handle layer");
 
1696
                        hideMenuLayer();
 
1697
                        return;
 
1698
                    }
 
1699
                    dragop.start(item,e.getPoint());
 
1700
                }
 
1701
                
 
1702
                /*
 
1703
                if(formDesigner.getDesignerMode() == FormDesigner.MODE_SELECT && showMenubarWarning) {
 
1704
                    p("still in bad mode");
 
1705
                    //glassLayer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
 
1706
                    showMenubarWarning = false;
 
1707
                    repaint();
 
1708
                }*/
 
1709
            }
 
1710
        }
 
1711
        
 
1712
        public void mouseExited(MouseEvent e) {
 
1713
            //p("mouse exited: " + e);
 
1714
            if(dragop.isStarted()) {
 
1715
                 dragop.setTargetVisible(false);
 
1716
            }
 
1717
        }
 
1718
        
 
1719
        public void mouseDragged(MouseEvent e) {
 
1720
            if(!dragop.isStarted() && pressPoint != null && pressComp instanceof JMenuItem
 
1721
                    && e.getPoint().distance(pressPoint) > 10) {
 
1722
                p("starting the dragop");
 
1723
                dragop.start((JMenuItem)pressComp, e.getPoint());
 
1724
                pressPoint = null;
 
1725
                pressComp = null;
 
1726
            }
 
1727
            if(dragop.isStarted()) {
 
1728
                dragop.move(e.getPoint());
 
1729
            }
 
1730
            return;
 
1731
        }
 
1732
        
 
1733
        public void mouseMoved(MouseEvent e) {
 
1734
            if(shouldRedispatchToHandle()) {
 
1735
                formDesigner.getHandleLayer().dispatchEvent(e);
 
1736
                //hideMenuLayer();
 
1737
                //return;
 
1738
            }
 
1739
            if(dragop.isStarted()) {
 
1740
                if(!doesFormContainMenuBar()) {
 
1741
                    FormEditor.getAssistantModel(formDesigner.getFormModel()).setContext("missingMenubar"); // NOI18N
 
1742
                }
 
1743
                dragop.move(e.getPoint());
 
1744
            }                
 
1745
            
 
1746
        }
 
1747
        
 
1748
        private boolean shouldRedispatchToHandle() {
 
1749
            if(!USE_JSEPARATOR_FIX) return false;
 
1750
            if(dragop.isStarted() && dragop.isPickAndPlop()) {
 
1751
                if(dragop.getDragComponent() instanceof JSeparator /*&&
 
1752
                        dropTargetLayer.getDropTargetComponent() == null*/) {
 
1753
                    return true;
 
1754
                }
 
1755
            }
 
1756
            return false;
 
1757
        }
 
1758
                
 
1759
    }
 
1760
    
 
1761
    private boolean shouldRedispatchDnDToHandle(DropTargetDragEvent dtde) {
 
1762
        //return false;
 
1763
        
 
1764
        RADComponent rad = formDesigner.getHandleLayer().getMetaComponentAt(dtde.getLocation(), HandleLayer.COMP_DEEPEST);
 
1765
        p("comp under = " + rad);
 
1766
        if(rad != null && isMenuRelatedComponentClass(rad.getBeanClass())) {
 
1767
            p("over menu stuff. cancel the proxying");
 
1768
            return false;
 
1769
        }
 
1770
        //if(true) return false;
 
1771
        if(!USE_JSEPARATOR_FIX) return false;
 
1772
        PaletteItem item = PaletteUtils.getSelectedItem();
 
1773
        if(item != null && JSeparator.class.isAssignableFrom(item.getComponentClass())) {
 
1774
            return true;
 
1775
        }
 
1776
        return false;
 
1777
    }
 
1778
    
 
1779
    private class GlassLayerDropTargetListener implements DropTargetListener {
 
1780
        public void dragEnter(DropTargetDragEvent dtde) {
 
1781
            if(shouldRedispatchDnDToHandle(dtde)) {
 
1782
                dragProxying = true;
 
1783
                formDesigner.getHandleLayer().getNewComponentDropListener().dragEnter(dtde);
 
1784
                return;
 
1785
            }
 
1786
            p("drag enter: " + dtde);
 
1787
            if(!dragop.isStarted()) {
 
1788
                start(dtde);
 
1789
            }
 
1790
        }
 
1791
        
 
1792
        private void start(DropTargetDragEvent dtde) {
 
1793
            p("really starting the Drag stuff");
 
1794
            PaletteItem item = PaletteUtils.getSelectedItem();
 
1795
 
 
1796
            if(item != null && !isMenuRelatedComponentClass(item.getComponentClass())) {
 
1797
                p("not a menu component. going back to the handle layer");
 
1798
                hideMenuLayer();
 
1799
                return;
 
1800
            }
 
1801
 
 
1802
            if(formDesigner.getDesignerMode() == FormDesigner.MODE_ADD && item != null) {
 
1803
                if(JMenuBar.class.isAssignableFrom(item.getComponentClass())) {
 
1804
                    p("dragging in a menu bar. go back to handle layer");
 
1805
                    hideMenuLayer();
 
1806
                    return;
 
1807
                }
 
1808
                dragop.start(item,dtde.getLocation());
 
1809
            }
 
1810
        }
 
1811
        
 
1812
        public void dragOver(DropTargetDragEvent dtde) {
 
1813
            p("full dragover: " + dtde.getLocation());
 
1814
            p("should redispatch = " + shouldRedispatchDnDToHandle(dtde));
 
1815
            // look at the rad component under the cursor first
 
1816
 
 
1817
            if(dragProxying && shouldRedispatchDnDToHandle(dtde)) {
 
1818
                formDesigner.getHandleLayer().getNewComponentDropListener().dragOver(dtde);
 
1819
                return;
 
1820
            }
 
1821
            p("switching to normal menulayer dnd");
 
1822
            dragProxying = false;
 
1823
            p("drag over: " + dtde);
 
1824
            if(dragop.isStarted()) {
 
1825
                p("moving dragop");
 
1826
                dragop.move(dtde.getLocation());
 
1827
            } else {
 
1828
                start(dtde);
 
1829
            }
 
1830
        }
 
1831
 
 
1832
        public void dropActionChanged(DropTargetDragEvent dtde) {
 
1833
        }
 
1834
 
 
1835
        public void dragExit(DropTargetEvent dte) {
 
1836
            //if(shouldRedispatchDnDToHandle()) {
 
1837
            if(dragProxying) {
 
1838
                formDesigner.getHandleLayer().getNewComponentDropListener().dragExit(dte);
 
1839
            }
 
1840
            dragProxying = false;
 
1841
        }
 
1842
 
 
1843
        public void drop(DropTargetDropEvent dtde) {
 
1844
            //if(shouldRedispatchDnDToHandle()) {
 
1845
            if(dragProxying) {
 
1846
                formDesigner.getHandleLayer().getNewComponentDropListener().drop(dtde);
 
1847
                dragProxying = false;
 
1848
                return;
 
1849
            }
 
1850
            if(dragop.isStarted()) {
 
1851
                dragop.end(dtde.getLocation());
 
1852
                dragProxying = false;
 
1853
                return;
 
1854
            }
 
1855
        }
 
1856
        
 
1857
    }
 
1858
    
 
1859
    
 
1860
    public SelectedPortion getCurrentSelectedPortion() {
 
1861
        return selectedPortion;
 
1862
    }
 
1863
     
 
1864
    
 
1865
    private boolean dragProxying = false;
 
1866
    public boolean isDragProxying() {
 
1867
        return dragProxying;
 
1868
    }
 
1869
    
 
1870
    
 
1871
    static class WrapperIcon implements Icon {
 
1872
        private Icon wrapee;
 
1873
        public WrapperIcon() {
 
1874
            this(null);
 
1875
        }
 
1876
        public WrapperIcon(Icon icon) {
 
1877
            wrapee = icon;
 
1878
        }
 
1879
        
 
1880
        public void setIcon(Icon icon) {
 
1881
            this.wrapee = icon;
 
1882
        }
 
1883
        
 
1884
        public void paintIcon(Component arg0, Graphics g, int x,  int y) {
 
1885
            if(wrapee != null) {
 
1886
                wrapee.paintIcon(arg0, g, x, y);
 
1887
            } else {
 
1888
                Graphics g2 = g.create();
 
1889
                g2.setColor(Color.WHITE);
 
1890
                g2.fillRect(x,y,getIconWidth()-1, getIconHeight()-1);
 
1891
                g2.setColor(MenuEditLayer.EMPTY_ICON_COLOR);
 
1892
                g2.drawRect(x,y,getIconWidth()-1, getIconHeight()-1);
 
1893
                g2.drawRect(x+1,y+1,getIconWidth()-3, getIconHeight()-3);
 
1894
                g2.dispose();
 
1895
            }
 
1896
        }
 
1897
        
 
1898
        public int getIconWidth() {
 
1899
            if(wrapee != null) {
 
1900
                return wrapee.getIconWidth();
 
1901
            }
 
1902
            return 16;
 
1903
        }
 
1904
        
 
1905
        public int getIconHeight() {
 
1906
            if(wrapee != null) {
 
1907
                return wrapee.getIconHeight();
 
1908
            }
 
1909
            return 16;
 
1910
        }
 
1911
        
 
1912
    }
 
1913
 
 
1914
}