Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.framework / org.gvsig.andami / src / main / java / org / gvsig / andami / ui / mdiFrame / MDIFrame.java @ 41334

History | View | Annotate | Download (65 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA 02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.andami.ui.mdiFrame;
25

    
26
import java.awt.BorderLayout;
27
import java.awt.Component;
28
import java.awt.Dimension;
29
import java.awt.FlowLayout;
30
import java.awt.Insets;
31
import java.awt.event.ActionEvent;
32
import java.awt.event.ActionListener;
33
import java.awt.event.ComponentEvent;
34
import java.awt.event.ComponentListener;
35
import java.awt.event.ContainerEvent;
36
import java.awt.event.ContainerListener;
37
import java.awt.event.MouseAdapter;
38
import java.awt.event.MouseEvent;
39
import java.awt.event.WindowAdapter;
40
import java.awt.event.WindowEvent;
41
import java.io.File;
42
import java.util.ArrayList;
43
import java.util.Enumeration;
44
import java.util.HashMap;
45
import java.util.Iterator;
46
import java.util.List;
47
import java.util.Locale;
48
import java.util.Map;
49
import java.util.NoSuchElementException;
50
import java.util.StringTokenizer;
51
import java.util.Vector;
52

    
53
import javax.swing.AbstractButton;
54
import javax.swing.ButtonGroup;
55
import javax.swing.ImageIcon;
56
import javax.swing.JComponent;
57
import javax.swing.JFileChooser;
58
import javax.swing.JFrame;
59
import javax.swing.JMenu;
60
import javax.swing.JMenuBar;
61
import javax.swing.JOptionPane;
62
import javax.swing.JPanel;
63
import javax.swing.JPopupMenu;
64
import javax.swing.JSeparator;
65
import javax.swing.JToolBar;
66
import javax.swing.KeyStroke;
67
import javax.swing.MenuElement;
68
import javax.swing.SwingUtilities;
69
import javax.swing.Timer;
70
import javax.swing.WindowConstants;
71
import javax.swing.filechooser.FileFilter;
72

    
73
import org.gvsig.andami.IconThemeHelper;
74
import org.gvsig.andami.Launcher;
75
import org.gvsig.andami.PluginServices;
76
import org.gvsig.andami.PluginsLocator;
77
import org.gvsig.andami.PluginsManager;
78
import org.gvsig.andami.actioninfo.ActionInfo;
79
import org.gvsig.andami.actioninfo.ActionInfoManager;
80
import org.gvsig.andami.actioninfo.ActionInfoStatusCache;
81
import org.gvsig.andami.messages.Messages;
82
import org.gvsig.andami.plugins.ExtensionDecorator;
83
import org.gvsig.andami.plugins.IExtension;
84
import org.gvsig.andami.plugins.PluginClassLoader;
85
import org.gvsig.andami.plugins.config.generate.ActionTool;
86
import org.gvsig.andami.plugins.config.generate.Label;
87
import org.gvsig.andami.plugins.config.generate.Menu;
88
import org.gvsig.andami.plugins.config.generate.PopupMenu;
89
import org.gvsig.andami.plugins.config.generate.SelectableTool;
90
import org.gvsig.andami.plugins.config.generate.SkinExtensionType;
91
import org.gvsig.andami.plugins.config.generate.ToolBar;
92
import org.gvsig.andami.ui.mdiFrame.TranslatableButtonHelper.TranslatableButton;
93
import org.gvsig.andami.ui.mdiManager.MDIManager;
94
import org.gvsig.andami.ui.mdiManager.MDIManagerFactory;
95
import org.gvsig.gui.beans.controls.IControl;
96
import org.gvsig.tools.ToolsLocator;
97
import org.gvsig.tools.i18n.I18nManager;
98
import org.gvsig.tools.swing.api.ToolsSwingLocator;
99
import org.gvsig.tools.swing.icontheme.IconTheme;
100
import org.slf4j.Logger;
101
import org.slf4j.LoggerFactory;
102

    
103
/**
104
 * Main application window.
105
 *
106
 * Use Launcher.getMDIFrame to get the instance of this class.
107
 *
108
 * @version $Revision: 39484 $
109
 */
110
@SuppressWarnings("unchecked")
111
public class MDIFrame extends JFrame implements ComponentListener,
112
        ContainerListener, ActionListener, MainFrame {
113

    
114
    private static final long serialVersionUID = -2472484309160847654L;
115

    
116
    private static Logger logger = LoggerFactory.getLogger(MDIFrame.class);
117

    
118
    private static MDIFrame instance = null;
119

    
120
    private MDIManager mdiManager = MDIManagerFactory.createManager();
121

    
122
    /**
123
     * Elementos de la aplicaci?n
124
     */
125
    private JMenuBar menuBar = new JMenuBar();
126

    
127
    /**
128
     * Panel which contains the toolbars
129
     */
130
    private JPanel toolBars = new JPanel();
131

    
132
    /**
133
     * Status bar
134
     */
135
    private NewStatusBar bEstado = null;
136

    
137
    /**
138
     * Asocia los nombres con las barras de herramientas
139
     */
140
    private HashMap toolBarMap = new HashMap();
141

    
142
    /**
143
     * Almacena los grupos de selectableTools
144
     */
145
    private HashMap buttonGroupMap = new HashMap();
146
    /**
147
     * Stores the initially selected tools.
148
     * It contains pairs (String groupName, JToolBarToggleButton button)
149
     */
150
    private HashMap initialSelectedTools = new HashMap();
151

    
152
    /**
153
     * Stores the actionCommand of the selected tool, for each group.
154
     * It contains pairs (String groupName, JToolBarToggleButton button)
155
     */
156
    private Map selectedTool = null;
157
    // this should be the same value defined at plugin-config.xsd
158
    private String defaultGroup = "unico";
159

    
160
    /**
161
     * Asocia los nombres con los popupMenus
162
     */
163
    private HashMap popupMap = new HashMap();
164

    
165
    /**
166
     * Asocia controles con la clase de la extension asociada
167
     */
168
    private List<JComponent> controls = new ArrayList<JComponent>();
169

    
170
    /**
171
     * Asocia la informaci?n sobre las etiquetas que van en la status bar con
172
     * cada extension
173
     */
174
    private HashMap classLabels = new HashMap();
175

    
176
    // private HashMap classControls = new HashMap();
177
    /**
178
     * ProgressListeners (ver interfaz com.iver.mdiApp.ui.ProgressListener)
179
     */
180
    private ArrayList progressListeners = new ArrayList();
181

    
182
    /**
183
     * Timer para invocar los enventos de la interfaz anterior
184
     */
185
    private Timer progressTimer = null;
186

    
187
    /**
188
     * Tabla hash que asocia las clases con las extensiones
189
     */
190
    // private Map classesExtensions = new HashMap<Class<? extends IExtension>, ExtensionDecorator>();
191
    /**
192
     * ?ltima clase que activ? etiquetas
193
     */
194
    private Class lastLabelClass;
195

    
196
    /**
197
     * Instancia que pone los tooltip en la barra de estado
198
     */
199
    private TooltipListener tooltipListener = new TooltipListener();
200

    
201
    private HashMap infoCodedMenus = new HashMap();
202

    
203
    private String titlePrefix;
204

    
205
    private static final String noIcon = "no-icon";
206

    
207
    private Map<JComponent,IExtension> control2extensions = new HashMap<JComponent, IExtension>();
208
    
209
    private MDIFrame() {
210

    
211
    }
212

    
213
    public static MDIFrame getInstance() {
214
        if ( instance == null ) {
215
            instance = new MDIFrame();
216
        }
217
        return instance;
218
    }
219

    
220
    /**
221
     * Makes some initialization tasks.
222
     *
223
     * @throws RuntimeException
224
     */
225
    public void init() {
226
        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
227
        if ( !SwingUtilities.isEventDispatchThread() ) {
228
            throw new RuntimeException("Not Event Dispatch Thread");
229
        }
230

    
231
        // Se a?aden los listeners del JFrame
232
        this.addWindowListener(new WindowAdapter() {
233

    
234
            @Override
235
            public void windowClosing(WindowEvent e) {
236
                Launcher.closeApplication();
237
            }
238
        });
239
        this.addComponentListener(this);
240
        this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
241

    
242
        // Se configura la barra de menu
243
        setJMenuBar(menuBar);
244

    
245
        // Se configura el layout del JFrame principal
246
        this.getContentPane().setLayout(new BorderLayout());
247

    
248
        /*
249
         * Se configura y se a?ade el JPanel de las barras de
250
         * herramientas
251
         */
252
        FlowLayout layout = new FlowLayout(FlowLayout.LEFT);
253
        layout.setHgap(0);
254
        layout.setVgap(0);
255
        toolBars.setLayout(layout);
256
        getContentPane().add(toolBars, BorderLayout.PAGE_START);
257

    
258
        // Add the status bar of the application
259
        bEstado = new NewStatusBar();
260
        bEstado.message(Messages.getString("StatusBar.Aplicacion_iniciada"), JOptionPane.INFORMATION_MESSAGE);
261
        getContentPane().add(bEstado, BorderLayout.SOUTH);
262

    
263
        this.toolBars.addContainerListener(this);
264

    
265

    
266
        /*
267
         * Setting default values. Persistence is read
268
         * afterwards
269
         */
270
        setSize(
271
                MainFrame.MAIN_FRAME_SIZE_DEFAULT[0],
272
                MainFrame.MAIN_FRAME_SIZE_DEFAULT[1]);
273
        setLocation(
274
                MainFrame.MAIN_FRAME_POS_DEFAULT[0],
275
                MainFrame.MAIN_FRAME_POS_DEFAULT[1]);
276
        setExtendedState(
277
                MainFrame.MAIN_FRAME_EXT_STATE_DEFAULT);
278

    
279
        mdiManager.init(this);
280
    }
281

    
282
    @Override
283
    public void setTitle(final String title) {
284
        if ( !SwingUtilities.isEventDispatchThread() ) {
285
            SwingUtilities.invokeLater(new Runnable() {
286
                public void run() {
287
                    setTitle(title);
288
                }
289
            });
290
            return;
291
        }
292
        super.setTitle(titlePrefix + " : " + title);
293
    }
294

    
295
    public void addTool(final PluginClassLoader loader, final SkinExtensionType ext,
296
            final ToolBar toolBar, final SelectableTool selectableTool)
297
            throws ClassNotFoundException {
298
        if ( !SwingUtilities.isEventDispatchThread() ) {
299
            try {
300
                SwingUtilities.invokeAndWait(new Runnable() {
301
                    public void run() {
302
                        try {
303
                            addTool(loader, ext, toolBar, selectableTool);
304
                        } catch (ClassNotFoundException ex) {
305
                            logger.warn("??? Eehh????", ex);
306
                        }
307
                    }
308
                });
309
            } catch (Exception ex) {
310
                // Do nothing
311
            }
312
            return;
313
        }
314
        I18nManager i18nManager = ToolsLocator.getI18nManager();
315

    
316
        JToolBarToggleButton btn;
317
        ImageIcon image
318
                = PluginServices.getIconTheme().get(selectableTool.getIcon());
319

    
320
        if ( image != null ) {
321
            btn = new JToolBarToggleButton(selectableTool.getText(), image);
322
        } else {
323
            logger.warn("Unable to find icon '" + selectableTool.getIcon() + "'.");
324
            btn
325
                    = new JToolBarToggleButton(selectableTool.getText(),
326
                            PluginServices.getIconTheme().get(noIcon));
327
        }
328

    
329
        org.gvsig.andami.ui.mdiFrame.ToggleButtonModel buttonModel
330
                = new org.gvsig.andami.ui.mdiFrame.ToggleButtonModel();
331
        btn.setModel(buttonModel);
332
        btn.setMargin(new Insets(0, 0, 0, 0));
333
        btn.addMouseListener(tooltipListener);
334
        btn.addActionListener(this);
335
        btn.setFocusable(false);
336
        btn.setActionCommand(selectableTool.getActionCommand());
337
        btn.setToolTipText(selectableTool.getTooltip());
338
        btn.setEnabled(false);
339
        btn.setVisible(false);
340
        String name = toolBar.getName();
341

    
342
        SelectableToolBar jtb = (SelectableToolBar) toolBarMap.get(name);
343

    
344
        if ( jtb == null ) {
345
            jtb = new SelectableToolBar(name);
346
            jtb.setRollover(true);
347
            jtb.setAndamiVisibility(toolBar.getIsVisible());
348
            toolBarMap.put(name, jtb);
349
            toolBars.add(jtb);
350
        }
351

    
352
        ButtonGroup group;
353
        if ( buttonGroupMap.containsKey(selectableTool.getGroup()) ) {
354
            group = (ButtonGroup) buttonGroupMap.get(selectableTool.getGroup());
355
        } else {
356
            group = new ButtonGroup();
357
            buttonGroupMap.put(selectableTool.getGroup(), group);
358

    
359
        }
360
        jtb.addButton(group, btn);
361
        buttonModel.setGroupName(selectableTool.getGroup());
362

    
363
        if ( selectableTool.getIsDefault() ) {
364
            btn.setSelected(true);
365
            initialSelectedTools.put(selectableTool.getGroup(),
366
                    btn.getActionCommand());
367
        }
368

    
369
        addControl(btn);
370

    
371
        if ( selectableTool.getName() != null ) {
372
            btn.setName(selectableTool.getName());
373
        }
374

    
375
        if ( selectableTool.getTooltip() != null ) {
376
            btn.setToolTip(i18nManager.getTranslation(selectableTool.getTooltip()));
377
            btn.setToolTipKey(selectableTool.getTooltip());
378
        }
379

    
380
        if ( selectableTool.getEnableText() != null ) {
381
            btn.setEnableText(i18nManager.getTranslation(selectableTool.getEnableText()));
382
        }
383

    
384
        if ( selectableTool.getLast() == true ) {
385
            jtb.addSeparator();
386
        }
387
    }
388

    
389
    /**
390
     * Add a button to the toolbar.
391
     *
392
     * @param ext
393
     * Texto del boton, si es null no aparece texto
394
     * @param ext
395
     * Extension asociada al control
396
     * @param toolBar
397
     * Icono del boton, si es null no aparece texto
398
     * @param actionTool
399
     * Tooltip de la barra de herramientas
400
     *
401
     * @throws ClassNotFoundException
402
     * @throws RuntimeException
403
     */
404
    public void addTool(final PluginClassLoader loader, final SkinExtensionType ext,
405
            final ToolBar toolBar, final ActionTool actionTool) throws ClassNotFoundException {
406
        if ( !SwingUtilities.isEventDispatchThread() ) {
407
            try {
408
                SwingUtilities.invokeAndWait(new Runnable() {
409
                    public void run() {
410
                        try {
411
                            addTool(loader, ext, toolBar, actionTool);
412
                        } catch (ClassNotFoundException ex) {
413
                            logger.warn("??? Eehh????", ex);
414
                        }
415
                    }
416
                });
417
            } catch (Exception ex) {
418
                // Do nothing
419
            }
420
            return;
421
        }
422

    
423
        I18nManager i18nManager = ToolsLocator.getI18nManager();
424

    
425
        JToolBarButton btn;
426
        ImageIcon image = IconThemeHelper.getImageIcon(actionTool.getIcon());
427

    
428
        if ( image != null ) {
429
            btn = new JToolBarButton(actionTool.getText(), image);
430
        } else {
431
            logger.warn("Unable to find icon '" + actionTool.getIcon() + "'.");
432
            btn
433
                    = new JToolBarButton(actionTool.getText(), PluginServices
434
                            .getIconTheme().get(noIcon));
435
        }
436

    
437
        btn.setMargin(new Insets(0, 0, 0, 0));
438
        btn.addMouseListener(tooltipListener);
439
        btn.addActionListener(this);
440
        btn.setFocusable(false);
441
        btn.setActionCommand(actionTool.getActionCommand());
442
        btn.setEnabled(false);
443
        btn.setVisible(false);
444

    
445
        String name = toolBar.getName();
446

    
447
        SelectableToolBar jtb = (SelectableToolBar) toolBarMap.get(name);
448

    
449
        if ( jtb == null ) {
450
            jtb = new SelectableToolBar(name);
451
            jtb.setRollover(true);
452
            jtb.setAndamiVisibility(toolBar.getIsVisible());
453
            toolBarMap.put(name, jtb);
454
            toolBars.add(jtb);
455
        }
456

    
457
        jtb.add(btn);
458

    
459
        addControl(btn);
460

    
461
        if ( actionTool.getName() != null ) {
462
            btn.setName(actionTool.getName());
463
        }
464

    
465
        if ( actionTool.getTooltip() != null ) {
466
            btn.setToolTip(i18nManager.getTranslation(actionTool.getTooltip()));
467
            btn.setToolTipKey(actionTool.getTooltip());
468
        }
469

    
470
        if ( actionTool.getEnableText() != null ) {
471
            btn.setEnableText(i18nManager.getTranslation(actionTool.getEnableText()));
472
        }
473

    
474
        if ( actionTool.getLast() == true ) {
475
            jtb.addSeparator();
476
        }
477
    }
478

    
479
    public void addTool(final ActionInfo action, final String toolBarName) {
480
        I18nManager i18nManager = ToolsLocator.getI18nManager();
481

    
482
        if ( !SwingUtilities.isEventDispatchThread() ) {
483
            SwingUtilities.invokeLater(new Runnable() {
484
                public void run() {
485
                    addTool(action, toolBarName);
486
                }
487
            });
488
            return;
489
        }
490
        JToolBarButton btn = new JToolBarButton(action.getIcon());
491
        btn.setMargin(new Insets(0, 0, 0, 0));
492
        btn.addMouseListener(tooltipListener);
493
        btn.addActionListener(this);
494
        btn.setFocusable(false);
495
        btn.setActionCommand(action.getCommand());
496
        btn.setEnabled(false);
497
        btn.setVisible(false);
498
        btn.setName(action.getName());
499
        if ( action.getTooltip() != null ) {
500
            btn.setToolTip(i18nManager.getTranslation(action.getTooltip()));
501
            btn.setToolTipKey(action.getTooltip());
502
        }
503

    
504
        SelectableToolBar jtb = (SelectableToolBar) toolBarMap.get(toolBarName);
505
        if ( jtb == null ) {
506
            jtb = new SelectableToolBar(toolBarName);
507
            jtb.setRollover(true);
508
            jtb.setAndamiVisibility(true);
509
            toolBarMap.put(toolBarName, jtb);
510
            toolBars.add(jtb);
511
        }
512
        jtb.add(btn);
513

    
514
        addControl(btn);
515

    
516
    }
517

    
518
    /**
519
     * Creates the needed menu structure to add the menu to the bar.
520
     * Returns the father which must hold the menu which was
521
     * provided as parameter.
522
     *
523
     * Crea la estructura de menus necesaria para a?adir el menu a la barra.
524
     * Devuelve el padre del cual debe colgar el menu que se pasa como
525
     * parametro.
526
     *
527
     * @param menu
528
     * The Menu whose support is going to be added
529
     * @param loader
530
     * The plugin's class loader
531
     *
532
     * @return The proper father for the menu which was provided as parameter
533
     */
534
    private JMenu createMenuAncestors(Menu menu, PluginClassLoader loader) {
535
        return createMenuAncestors(menu.getText());
536
    }
537

    
538
    private JMenu createMenuAncestors(String text) {
539
        I18nManager i18nManager = ToolsLocator.getI18nManager();
540

    
541
        MenuElement menuPadre = null;
542

    
543
        String[] menues = text.split("/");
544
        List menuList = new ArrayList();
545
        menuList.add(menues[0]);
546
        menuPadre = getMenu(menuList, menuBar);
547

    
548
        JMenu padre = null;
549

    
550
        if ( menuPadre == null ) {
551
            padre = new JMenuTraslatable(i18nManager.getTranslation(menues[0]));
552
            ((JMenuTraslatable) padre).setTextKey(menues[0]);
553
            padre.setName(menues[0]);
554
            addControl(padre);
555
            menuBar.add(padre);
556
        } else if ( menuPadre instanceof JMenu ) {
557
            padre = (JMenu) menuPadre;
558
        } else {
559
            logger.warn("Error creating menu. Ancestor does not exist (" + text + ").");
560
            return null;
561
        }
562

    
563
        // Se crea el resto de menus
564
        ArrayList temp = new ArrayList();
565

    
566
        for ( int i = 1; i < (menues.length - 1); i++ ) {
567
            temp.add(menues[i]);
568
        }
569

    
570
        menuPadre = createMenus(temp, padre);
571

    
572
        return (JMenu) menuPadre;
573
    }
574

    
575
    /**
576
     * A?ade la informacion del menu al framework.
577
     * Debido a que los men?es se
578
     * pueden introducir en un orden determinado por el usuario, pero los
579
     * plugins se instalan en un orden arbitrario, primero se almacena la
580
     * informacion de todos los menus para luego ordenarlos y posteriormente
581
     * a?adirlos al interfaz
582
     *
583
     * @param loader
584
     * Posicion del menu. Se ordena por este campo
585
     * @param ext
586
     * Array con los nombres de los padres del menu
587
     * @param menu
588
     * Texto del menu
589
     *
590
     * @throws ClassNotFoundException
591
     * @throws RuntimeException
592
     */
593
    public void addMenu(final PluginClassLoader loader, final SkinExtensionType ext,
594
            final Menu menu) throws ClassNotFoundException {
595
        if ( !SwingUtilities.isEventDispatchThread() ) {
596
            try {
597
                SwingUtilities.invokeAndWait(new Runnable() {
598
                    public void run() {
599
                        try {
600
                            addMenu(loader, ext, menu);
601
                        } catch (ClassNotFoundException ex) {
602
                            logger.warn("??? Eehh????", ex);
603
                        }
604
                    }
605
                });
606
            } catch (Exception ex) {
607
                // Do nothing
608
            }
609
            return;
610
        }
611
        JMenu menuPadre = createMenuAncestors(menu, loader);
612

    
613
        if ( menu.getIs_separator() ) {
614
            menuPadre.addSeparator();
615
            return;
616
        }
617

    
618
        JMenuItem nuevoMenu = createJMenuItem(loader, menu);
619
        nuevoMenu.addMouseListener(tooltipListener);
620
        menuPadre.add(nuevoMenu);
621
        addControl(nuevoMenu);
622

    
623
    }
624

    
625
    public void addMenu(final ActionInfo action, final String text) {
626
        if ( !SwingUtilities.isEventDispatchThread() ) {
627
            SwingUtilities.invokeLater(new Runnable() {
628
                public void run() {
629
                    addMenu(action, text);
630
                }
631
            });
632
            return;
633
        }
634
        JMenu menuPadre = createMenuAncestors(text);
635
        JMenuItem nuevoMenu = createJMenuItem(action, text);
636
        nuevoMenu.addMouseListener(tooltipListener);
637
        menuPadre.add(nuevoMenu);
638
        Class<? extends IExtension> classExtension = action.getExtension().getClass();
639
        addControl(nuevoMenu);
640
    }
641

    
642
    /**
643
     * Dado lista de nombres de menu, encuentra el menu
644
     *
645
     * @param nombres
646
     * @param padre
647
     * @return
648
     */
649
    private javax.swing.JMenuItem getMenu(List nombres, MenuElement parent) {
650
        if ( parent instanceof javax.swing.JMenu ) {
651
            javax.swing.JMenu parentItem = (javax.swing.JMenu) parent;
652

    
653
            for ( int i = 0; i < parentItem.getMenuComponentCount(); i++ ) {
654

    
655
                String item_name = parentItem.getMenuComponent(i).getName();
656
                if ( ((item_name != null) && (item_name.compareTo((String) nombres.get(0)) == 0))
657
                        || /*
658
                         * We also accept "leaf menus" with no name
659
                         * (Project manager, View-1, View-2, etc)
660
                         */ lastMenuItemWithoutName(parentItem.getMenuComponent(i), nombres) ) {
661

    
662
                    nombres.remove(0);
663
                    if ( nombres.isEmpty() ) {
664
                        if ( parentItem.getMenuComponent(i) instanceof javax.swing.JMenuItem ) {
665
                            return (javax.swing.JMenuItem) parentItem
666
                                    .getMenuComponent(i);
667
                        } else {
668
                            logger.error(PluginServices.getText(this,
669
                                    "Menu_type_not_supported_")
670
                                    + " "
671
                                    + parentItem.getMenuComponent(i).getClass()
672
                                    .getName());
673
                            return null;
674
                        }
675
                    } else {
676
                        return getMenu(nombres,
677
                                (MenuElement) parentItem.getMenuComponent(i));
678
                    }
679
                }
680
            }
681
        } else if ( parent instanceof JMenuBar ) {
682
            javax.swing.JMenuBar parentItem = (javax.swing.JMenuBar) parent;
683

    
684
            for ( int i = 0; i < parentItem.getMenuCount(); i++ ) {
685
                if ( (parentItem.getMenu(i).getName() != null // not a
686
                        // JToolBar.Separator
687
                        )
688
                        && (parentItem.getMenu(i).getName()
689
                        .compareTo((String) nombres.get(0)) == 0) ) {
690
                    nombres.remove(0);
691
                    if ( nombres.isEmpty() ) {
692
                        if ( parentItem.getMenu(i) instanceof javax.swing.JMenuItem ) {
693
                            return parentItem.getMenu(i);
694
                        } else {
695
                            logger.error(PluginServices.getText(this,
696
                                    "Menu_type_not_supported_")
697
                                    + " "
698
                                    + parentItem.getMenu(i).getClass()
699
                                    .getName());
700
                            return null;
701
                        }
702
                    } else {
703
                        return getMenu(nombres, parentItem.getMenu(i));
704
                    }
705
                }
706
            }
707
        } else {
708
            logger.error(PluginServices.getText(this,
709
                    "Menu_type_not_supported_")
710
                    + " "
711
                    + parent.getClass().getName() + " " + parent.toString());
712
        }
713
        return null;
714
    }
715

    
716
    /**
717
     * @param menuComponent
718
     * @param nombres
719
     * @return
720
     */
721
    private boolean lastMenuItemWithoutName(Component mc, List names) {
722

    
723
        /*
724
         * names must have 1 string
725
         */
726
        if ( names == null || names.size() != 1 ) {
727
            return false;
728
        }
729
        if ( !(mc instanceof JMenuItem) ) {
730
            return false;
731
        }
732
        JMenuItem jmi = (JMenuItem) mc;
733
        if ( jmi.getName() != null ) {
734
            /*
735
             * Name must be null, so this is a menu leaf
736
             */
737
            return false;
738
        }
739
        if ( jmi.getText() == null ) {
740
            return false;
741
        }
742
        return jmi.getText().compareTo((String) names.get(0)) == 0;
743
    }
744

    
745
    private class JMenuTraslatable extends JMenu implements TranslatableButton {
746

    
747
        private TranslatableButtonHelper i18nHelper = new TranslatableButtonHelper();
748

    
749
        public JMenuTraslatable(String text) {
750
            super(text);
751
        }
752

    
753
        public void setTextKey(String key) {
754
            this.i18nHelper.setText(key);
755
        }
756

    
757
        public void setToolTipKey(String key) {
758
            this.i18nHelper.setTooltip(key);
759
        }
760

    
761
        public void translate() {
762
            if ( this.i18nHelper.needTranslation() ) {
763
                this.i18nHelper.translate();
764
                this.setText(this.i18nHelper.getText());
765
            }
766
        }
767

    
768
    }
769

    
770
    /**
771
     * Crea la estructura de menus recursivamente. Por ejemplo, si se le pasa
772
     * en el par?metro nombres el array {"Search", "References", "Workspace"}
773
     * crear? un men? Search, un submen? del anterior que se llamar?
774
     * References y debajo de ?ste ?ltimo otro menu llamado Workspace
775
     *
776
     * @param nombres
777
     * Array con los nombres de los men?s que se quieren crear
778
     * @param padre
779
     * Menu padre de los men?s creados. Es ?til porque es un
780
     * algoritmo recursivo
781
     *
782
     * @return Devuelve el men? creado. Al final de toda la recursividad,
783
     * devolver? el men? de m?s abajo en la jerarqu?a
784
     *
785
     * @throws RuntimeException
786
     */
787
    private JMenu createMenus(ArrayList nombres, JMenu padre) {
788
        if ( !SwingUtilities.isEventDispatchThread() ) {
789
            logger.warn("Este metodo requiere que se este ejecutando en el hilo de eventos de AWT.");
790
            throw new RuntimeException("No Event Dispatch Thread");
791
        }
792
        I18nManager i18nManager = ToolsLocator.getI18nManager();
793

    
794
        // si no quedan nombres de menu por crear se vuelve: caso base
795
        if ( nombres.isEmpty() ) {
796
            return padre;
797
        }
798

    
799
        // Se busca el menu por si ya existiera para no crearlo otra vez
800
        JMenu buscado = null;
801

    
802
        for ( int i = 0; i < padre.getMenuComponentCount(); i++ ) {
803
            try {
804
                JMenu hijo = (JMenu) padre.getMenuComponent(i);
805

    
806
                if ( hijo.getName().compareTo((String) nombres.get(0)) == 0 ) {
807
                    buscado = hijo;
808
                }
809
            } catch (ClassCastException e) {
810
                /*
811
                 * Se ha encontrado un elemento hoja del arbol de men?es
812
                 */
813
            }
814
        }
815

    
816
        if ( buscado != null ) {
817
            // Si lo hemos encontrado creamos el resto
818
            nombres.remove(0);
819

    
820
            return createMenus(nombres, buscado);
821
        } else {
822
            // Si no lo hemos encontrado se crea el menu, se a?ade al padre
823
            // y se crea el resto
824
            String nombre = (String) nombres.get(0);
825
            JMenuTraslatable menuPadre = new JMenuTraslatable(i18nManager.getTranslation(nombre));
826
            menuPadre.setTextKey(nombre);
827
            menuPadre.setName(nombre);
828
            addControl(menuPadre);
829
            padre.add(menuPadre);
830

    
831
            nombres.remove(0);
832

    
833
            return createMenus(nombres, menuPadre);
834
        }
835
    }
836

    
837
    /**
838
     * M?todo invocado en respuesta a ciertos eventos de la interfaz que
839
     * pueden
840
     * ocultar botones de las barras de herramientas y que redimensiona ?sta
841
     * de manera conveniente para que no se oculte ninguno
842
     */
843
    private void ajustarToolBar() {
844
        int margen = 8;
845
        int numFilas = 1;
846
        double acum = margen;
847

    
848
        int toolHeight = 0;
849

    
850
        for ( int i = 0; i < toolBars.getComponentCount(); i++ ) {
851
            Component c = toolBars.getComponent(i);
852

    
853
            if ( !c.isVisible() ) {
854
                continue;
855
            }
856

    
857
            double width = c.getPreferredSize().getWidth();
858
            acum = acum + width;
859

    
860
            if ( acum > this.getWidth() ) {
861
                numFilas++;
862
                acum = width + margen;
863
            }
864

    
865
            if ( c.getPreferredSize().getHeight() > toolHeight ) {
866
                toolHeight = c.getPreferredSize().height;
867
            }
868
        }
869

    
870
        toolBars.setPreferredSize(new Dimension(this.getWidth(),
871
                (numFilas * toolHeight)));
872

    
873
        toolBars.updateUI();
874
    }
875

    
876
    public void setClassesExtensions(Map<Class<? extends IExtension>, ExtensionDecorator> classesExtensions) {
877
        // Ya no es necesario que se mantenga el Map con las extensiones.
878

    
879
//            Map<Class<? extends IExtension>, ExtensionDecorator> extensions = new HashMap<Class<? extends IExtension>, ExtensionDecorator>();
880
//            for ( Entry<Class<? extends IExtension>, ExtensionDecorator>  entry: classesExtensions.entrySet()) {
881
//                        if( ! (entry.getValue().getExtension() instanceof LibraryExtension) ) {
882
//                                extensions.put(entry.getKey(), entry.getValue());
883
//                        }
884
//                }
885
//        this.classesExtensions = extensions;
886
    }
887

    
888
    /**
889
     * Metodo de callback invocado cuando se selecciona un menu o un boton
890
     * de
891
     * la barra de herramientas. Se busca la extensi?n asociada y se ejecuta
892
     *
893
     * @param e
894
     * Evento producido
895
     */
896
    public void actionPerformed(ActionEvent e) {
897

    
898
        String actionName = "(unknow)";
899
        try {
900
            JComponent control = (JComponent) e.getSource();
901
            actionName = control.getName();
902

    
903
            ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
904
            ActionInfo action = actionManager.getAction(control.getName());
905
            Object args = null;
906
            if ( control instanceof IControl ) {
907
                args = ((IControl) control).getValue();
908
            }
909
            if ( args == null ) {
910
                action.execute();
911
            } else {
912
                action.execute(args);
913
            }
914
            String actionCommand = e.getActionCommand();
915
            try {
916
                JToolBarToggleButton toggle = (JToolBarToggleButton) control;
917
                ToggleButtonModel model = (ToggleButtonModel) toggle.getModel();
918
                selectedTool.put(model.getGroupName(), actionCommand);
919
            } catch (ClassCastException ex) {
920
            } catch (NullPointerException ex) {
921
            }
922

    
923
        } catch (Throwable ex) {
924
            logger.error("Can't perform action '" + actionName + "'.", ex);
925
        }
926

    
927
        enableControls();
928
        showMemory();
929
    }
930

    
931
    private String getName(String name, PluginClassLoader loader) {
932
        if ( name.indexOf('.') == -1 ) {
933
            return loader.getPluginName() + "." + name;
934
        } else {
935
            return name;
936
        }
937
    }
938

    
939
    public void addPopupMenu(PluginClassLoader loader, PopupMenu menu) {
940
        if ( !SwingUtilities.isEventDispatchThread() ) {
941
            throw new RuntimeException("No Event Dispatch Thread");
942
        }
943

    
944
        String name = getName(menu.getName(), loader);
945

    
946
        // Se crea el control popupmenu
947
        JPopUpMenu popupMenu = (JPopUpMenu) popupMap.get(name);
948

    
949
        if ( popupMenu == null ) {
950
            popupMenu = new JPopUpMenu(menu.getName());
951
            popupMap.put(name, popupMenu);
952
        }
953

    
954
        Menu[] menues = menu.getMenu();
955
        for ( int i = 0; i < menues.length; i++ ) {
956
            JMenuItem nuevoMenu = createJMenuItem(loader, menues[i]);
957
            popupMenu.add(nuevoMenu);
958
        }
959
    }
960

    
961
    private JMenuItem createJMenuItem(PluginClassLoader loader, Menu menu) {
962
        JMenuItem nuevoMenu = null;
963

    
964
        I18nManager i18nManager = ToolsLocator.getI18nManager();
965

    
966
        String text = menu.getText();
967
        int n = text.lastIndexOf('/');
968
        if ( n >= 0 ) {
969
            text = text.substring(n + 1);
970
        }
971
        String translatedText = i18nManager.getTranslation(text);
972

    
973
        IconTheme iconTheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
974
        if ( menu.getIcon() != null ) {
975
            if ( iconTheme.exists(menu.getIcon()) ) {
976
                ImageIcon image = iconTheme.get(menu.getIcon());
977
                nuevoMenu = new JMenuItem(translatedText, image);
978
            } else {
979
                nuevoMenu = new JMenuItem(translatedText);
980
                logger.info("menu icon '" + menu.getIcon() + "' not exists.");
981
            }
982
        } else {
983
            nuevoMenu = new JMenuItem(translatedText);
984
        }
985
        nuevoMenu.setTextKey(text);
986
        nuevoMenu.setName(menu.getName());
987

    
988
        if ( menu.getKey() != null ) {
989
            nuevoMenu.setAccelerator(KeyMapping.getKeyStroke(menu.getKey()));
990
        }
991

    
992
        nuevoMenu.setActionCommand(menu.getActionCommand());
993

    
994
        if ( menu.getTooltip() != null ) {
995
            nuevoMenu.setToolTip(i18nManager.getTranslation(menu.getTooltip()));
996
            nuevoMenu.setToolTipKey(menu.getTooltip());
997
        }
998

    
999
        if ( menu.getEnableText() != null ) {
1000
            nuevoMenu.setEnableText(i18nManager.getTranslation(menu.getEnableText()));
1001
        }
1002

    
1003
        nuevoMenu.setEnabled(true);
1004
        nuevoMenu.setVisible(true);
1005

    
1006
        if ( menu.getName() != null ) {
1007
            ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1008
            final ActionInfo actionInfo = actionManager.getAction(menu.getName());
1009
            if ( actionInfo != null ) {
1010
                nuevoMenu.addActionListener(actionInfo);
1011
            }
1012
        }
1013
        return nuevoMenu;
1014
    }
1015

    
1016
    private JMenuItem createJMenuItem(ActionInfo action, String text) {
1017
        I18nManager i18nManager = ToolsLocator.getI18nManager();
1018
        JMenuItem nuevoMenu = null;
1019
        String label = null;
1020

    
1021
        if ( text == null ) {
1022
            label = action.getLabel();
1023
        } else if ( text.contains("/") ) {
1024
            String[] ss = text.split("/");
1025
            label = ss[ss.length - 1];
1026
        } else {
1027
            label = text;
1028
        }
1029
        String translatedText = i18nManager.getTranslation(label);
1030
        if ( action.getIconName() != null ) {
1031
            ImageIcon image = action.getIcon();
1032
            if ( image != null ) {
1033
                nuevoMenu = new JMenuItem(translatedText, image);
1034
            } else {
1035
                nuevoMenu = new JMenuItem(translatedText);
1036
            }
1037
        } else {
1038
            nuevoMenu = new JMenuItem(translatedText);
1039
        }
1040
        nuevoMenu.setName(action.getName());
1041
        KeyStroke key = action.getKeyStroke();
1042
        if ( key != null ) {
1043
            nuevoMenu.setAccelerator(key);
1044
        }
1045
        nuevoMenu.setActionCommand(action.getCommand());
1046
        if ( action.getTooltip() != null ) {
1047
            nuevoMenu.setToolTip(i18nManager.getTranslation(action.getTooltip()));
1048
        }
1049
        nuevoMenu.setEnabled(true);
1050
        nuevoMenu.setVisible(true);
1051
        nuevoMenu.addActionListener(action);
1052
        return nuevoMenu;
1053
    }
1054

    
1055
    /**
1056
     * Muestra u oculta el menu de nombre 'name'
1057
     *
1058
     * @param name
1059
     * Nombre del menu que se quiere mostrar
1060
     * @param x
1061
     * Evento de raton
1062
     * @param y
1063
     * @param c
1064
     */
1065
    private void showPopupMenu(String name, int x, int y, Component c) {
1066
        JPopupMenu menu = (JPopupMenu) popupMap.get(name);
1067

    
1068
        if ( menu != null ) {
1069
            menu.show(c, x, y);
1070
        }
1071
    }
1072

    
1073
    public void removePopupMenuListener(String name, ActionListener listener) {
1074
        JPopupMenu menu = (JPopupMenu) popupMap.get(name);
1075

    
1076
        if ( menu != null ) {
1077
            Component[] jmenuitems = menu.getComponents();
1078

    
1079
            for ( int i = 0; i < jmenuitems.length; i++ ) {
1080
                if ( jmenuitems[i] instanceof JMenuItem ) {
1081
                    ((JMenuItem) jmenuitems[i]).removeActionListener(listener);
1082
                }
1083
            }
1084
        }
1085
    }
1086

    
1087
    public void addPopupMenuListener(String popupName, Component c,
1088
            ActionListener listener, PluginClassLoader loader) {
1089
        final String name = getName(popupName, loader);
1090

    
1091
        JPopupMenu menu = (JPopupMenu) popupMap.get(name);
1092

    
1093
        if ( menu != null ) {
1094
            Component[] jmenuitems = menu.getComponents();
1095

    
1096
            for ( int i = 0; i < jmenuitems.length; i++ ) {
1097
                if ( jmenuitems[i] instanceof JMenuItem ) {
1098
                    ((JMenuItem) jmenuitems[i]).addActionListener(listener);
1099
                }
1100
            }
1101
        }
1102

    
1103
        c.addMouseListener(new MouseAdapter() {
1104

    
1105
            @Override
1106
            public void mousePressed(MouseEvent e) {
1107
                if ( e.isPopupTrigger() ) {
1108
                    showPopupMenu(name, e.getX(), e.getY(), e.getComponent());
1109
                }
1110
            }
1111

    
1112
            @Override
1113
            public void mouseReleased(MouseEvent e) {
1114
                if ( e.isPopupTrigger() ) {
1115
                    showPopupMenu(name, e.getX(), e.getY(), e.getComponent());
1116
                }
1117
            }
1118
        });
1119
    }
1120

    
1121
    /**
1122
     * Loop on the controls to enable/disable and show/hide them, according to
1123
     * its associated action (ActionInfo)
1124
     *
1125
     * @throws RuntimeException
1126
     */
1127
    public void enableControls() {
1128
        if ( !SwingUtilities.isEventDispatchThread() ) {
1129
            SwingUtilities.invokeLater(new Runnable() {
1130
                public void run() {
1131
                    enableControls();
1132
                }
1133
            });
1134
            return;
1135
        }
1136

    
1137
        ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1138
        ActionInfoStatusCache cache = actionManager.createActionStatusCache();
1139

    
1140
        // Enable or disable controls, according to its associated extensions
1141
        Iterator<JComponent> e = controlsIterator();
1142

    
1143
        while ( e.hasNext() ) {
1144
            JComponent control = (JComponent) e.next();
1145
            String actionName = control.getName();
1146
            ActionInfo action = actionManager.getAction(actionName);
1147
            try {
1148
                boolean enabled = false;
1149
                boolean visible = false;
1150

    
1151
                if ( action == null ) {
1152
                    if( control instanceof JMenuTraslatable ) {
1153
                        enabled = true;
1154
                        visible = true;
1155
                    } else {
1156
                        IExtension extension = this.control2extensions.get(control);
1157
                        if( extension!=null ) {
1158
                            enabled = extension.isEnabled();
1159
                            visible = extension.isVisible();
1160
                        } else {
1161
                            logger.warn("Can't enable/show control '"+control.getClass().getName()+"/"+control.getName()+".");
1162
                            enabled = true;
1163
                            visible = true;
1164
                        }
1165
                    }
1166
                } else {
1167
                    enabled = false;
1168
                    visible = cache.isVisible(action);
1169
                    if ( visible ) {
1170
                        enabled = cache.isEnabled(action);
1171
                    }
1172
                }
1173
                control.setEnabled(enabled);
1174
                control.setVisible(visible);
1175
            } catch (Exception ex) {
1176
                logger.info("Can't enable/show control '" + actionName + "'.", ex);
1177
                this.message("Can't enable/show control '" + actionName + "'.", JOptionPane.ERROR_MESSAGE);
1178
                try {
1179
                    control.setEnabled(false);
1180
                    control.setVisible(false);
1181
                } catch (Exception ex2) {
1182
                    // Ignore errors
1183
                }
1184
            }
1185
        }
1186

    
1187
        // Loop in the menus to hide the menus that don't have visible children
1188
        for ( int i = 0; i < menuBar.getMenuCount(); i++ ) {
1189
            MenuElement menu = menuBar.getMenu(i);
1190
            hideMenus(menu);
1191
            if ( menu instanceof JMenu ) {
1192
                // hide (ugly) redundant separators and assign keyboard
1193
                // mnemonics
1194
                Component[] comps = ((JMenu) menu).getMenuComponents();
1195
                // mnemonics have to be unique for each top-level menu
1196
                char mnemonics[] = new char[comps.length];
1197
                if ( comps.length > 0 ) {
1198
                    // Set keyboard mnemonic for this top-level entry
1199
                    String text = ((JMenu) menu).getText();
1200
                    char mnemonic = getMnemonic(text, mnemonics);
1201
                    if ( ' ' != mnemonic ) {
1202
                        ((JMenu) menu).setMnemonic(mnemonic);
1203
                        mnemonics[0] = mnemonic;
1204
                    }
1205
                }
1206
                // now go through all entries in this menu, hid
1207
                // separators if necessary and assing remaining mnemonics
1208
                hideSeparatorsAndMakeMnemonics(menu, mnemonics);
1209
            }
1210
        }
1211

    
1212
        // hide the toolbars that don't contain any visible tool
1213
        Iterator it = toolBarMap.values().iterator();
1214

    
1215
        while ( it.hasNext() ) {
1216
            JComponent t = (JComponent) it.next();
1217
            boolean todosOcultos = true;
1218

    
1219
            for ( int i = 0; i < t.getComponentCount(); i++ ) {
1220
                if ( !(t.getComponent(i) instanceof JSeparator) // separators
1221
                        // don't matter
1222
                        && t.getComponent(i).isVisible() ) {
1223
                    todosOcultos = false;
1224
                }
1225
            }
1226

    
1227
            if ( todosOcultos ) {
1228
                t.setVisible(false);
1229
            } else {
1230
                if ( t instanceof SelectableToolBar ) {
1231
                    t.setVisible(((SelectableToolBar) t).getAndamiVisibility());
1232
                } else {
1233
                    t.setVisible(true);
1234
                }
1235
            }
1236
        }
1237

    
1238
        if ( mdiManager != null ) {
1239
            JPanel f = (JPanel) mdiManager.getActiveWindow();
1240

    
1241
            if ( f != null ) {
1242
                if ( lastLabelClass != f.getClass() ) {
1243
                    lastLabelClass = f.getClass();
1244

    
1245
                    Label[] lbls = (Label[]) classLabels.get(lastLabelClass);
1246

    
1247
                    if ( lbls != null ) {
1248
                        bEstado.setLabelSet(lbls);
1249
                    }
1250
                }
1251
            }
1252
        }
1253

    
1254
        ajustarToolBar();
1255

    
1256
        showMemory();
1257
    }
1258

    
1259
    public void refreshControls() {
1260
        if ( !SwingUtilities.isEventDispatchThread() ) {
1261
            SwingUtilities.invokeLater(new Runnable() {
1262
                public void run() {
1263
                    refreshControls();
1264
                }
1265
            });
1266
            return;
1267
        }
1268

    
1269
        ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1270
        ActionInfoStatusCache cache = actionManager.createActionStatusCache();
1271
        IconTheme icontheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
1272

    
1273
        Iterator e = controlsIterator();
1274

    
1275
        while ( e.hasNext() ) {
1276
            JComponent control = (JComponent) e.next();
1277
            if ( control instanceof TranslatableButton ) {
1278
                ((TranslatableButton) control).translate();
1279
            }
1280
            String actionlName = control.getName();
1281
            ActionInfo action = actionManager.getAction(actionlName);
1282
            if ( action != null ) {
1283
                if ( control instanceof AbstractButton ) {
1284
                    AbstractButton button = (AbstractButton) control;
1285
                    if ( control instanceof javax.swing.JMenuItem ) {
1286
                        if ( action.getIconName() != null && action.getIconName().length() > 0 ) {
1287
                            if ( icontheme.exists(action.getIconName()) ) {
1288
                                button.setIcon(action.getIcon());
1289
                            }
1290
                        }
1291
                    } else {
1292
                        button.setIcon(action.getIcon());
1293
                    }
1294
                }
1295
            }
1296
        }
1297
        enableControls();
1298
    }
1299

    
1300
    public void message(String msg, int messageTyoe) {
1301
        this.getStatusBar().message(msg, messageTyoe);
1302
    }
1303

    
1304
    /**
1305
     * Establece la visibilidad de un menu y todos sus descendientes en la
1306
     * jerarquia teniendo en cuenta la visibilidad de todos los submenus.
1307
     *
1308
     * @param menu
1309
     * Menu que se quiere visualizar
1310
     *
1311
     * @return Devuelve true si el menu es visible y false en caso contrario
1312
     */
1313
    private boolean hideMenus(MenuElement menu) {
1314
        MenuElement[] submenus = menu.getSubElements();
1315

    
1316
        // Si no tiene hijos se devuelve su visibilidad
1317
        if ( submenus.length == 0 ) {
1318
            return menu.getComponent().isVisible();
1319
        }
1320

    
1321
        /*
1322
         * Si tiene hijos se devuelve true si alg?no de ellos es visible,
1323
         * pero se itera por todos ellos
1324
         */
1325
        boolean visible = false;
1326

    
1327
        for ( int i = 0; i < submenus.length; i++ ) {
1328
            if ( hideMenus(submenus[i]) ) {
1329
                if ( !(menu instanceof JPopupMenu) ) {
1330
                    menu.getComponent().setVisible(true);
1331
                }
1332

    
1333
                visible = true;
1334
            }
1335
        }
1336

    
1337
        if ( visible ) {
1338
            return true;
1339
        }
1340

    
1341
        menu.getComponent().setVisible(false);
1342

    
1343
        return false;
1344
    }
1345

    
1346
    /**
1347
     *
1348
     * Recurse through all menu elements and make sure there are no
1349
     * redundant separators.
1350
     * This method will make sure that a separator only becomes visible
1351
     * if at least one visible non-separator menu entry preceeded it.
1352
     *
1353
     *
1354
     */
1355
    private void hideSeparatorsAndMakeMnemonics(MenuElement menu,
1356
            char[] mnemonics) {
1357
        // flag that indicates whether a separator is to be displayed or not
1358
        boolean allowSeparator;
1359

    
1360
        allowSeparator = false; // separator not allowed as very first menu item
1361
        Component[] comps = ((JMenu) menu).getMenuComponents();
1362
        if ( comps.length < 1 ) {
1363
            // zero-length menu: skip
1364
            return;
1365
        }
1366

    
1367
        for ( int i = 0; i < comps.length; i++ ) {
1368
            if ( comps[i] instanceof JSeparator ) {
1369
                // got a separator: display only if allowed at this position
1370
                if ( allowSeparator == true ) {
1371
                    // look at all successive menu entries to make sure that at
1372
                    // least one
1373
                    // is visible and not a separator (otherwise, this separator
1374
                    // would
1375
                    // be the last visible item in this menu) -- we don't want
1376
                    // that
1377
                    comps[i].setVisible(false);
1378
                    for ( int j = i; j < comps.length; j++ ) {
1379
                        if ( !(comps[j] instanceof JSeparator) ) {
1380
                            if ( comps[j].isVisible() ) {
1381
                                comps[i].setVisible(true); // display separator!
1382
                                break;
1383
                            }
1384
                        }
1385
                    }
1386
                } else {
1387
                    comps[i].setVisible(false);
1388
                }
1389
                allowSeparator = false; // separator is not allowed right after
1390
                // another separator
1391
            } else {
1392
                if ( comps[i] instanceof JMenu ) { // got a submenu: recurse
1393
                    // through it
1394
                    // get number of submenu components
1395
                    Component[] scomps = ((JMenu) comps[i]).getMenuComponents();
1396
                    // make a new, fresh array to hold unique mnemonics for this
1397
                    // submenu
1398
                    char[] smnemonics = new char[scomps.length];
1399
                    hideSeparatorsAndMakeMnemonics(((MenuElement) comps[i]),
1400
                            smnemonics);
1401
                    if ( comps[i].isVisible() ) {
1402
                        allowSeparator = true; // separators are OK after
1403
                        // visible submenus
1404
                        // Set keyboard mnemonic for this submenu
1405
                        String text = ((JMenu) comps[i]).getText();
1406
                        char mnemonic = getMnemonic(text, mnemonics);
1407
                        if ( ' ' != mnemonic ) {
1408
                            ((JMenu) comps[i]).setMnemonic(mnemonic);
1409
                            mnemonics[i] = mnemonic;
1410
                        }
1411
                    }
1412
                } else {
1413
                    if ( comps[i].isVisible() ) {
1414
                        if ( comps[i] instanceof JMenuItem ) {
1415
                            // Set keyboard mnemonic for this menu item
1416
                            String text = ((JMenuItem) comps[i]).getText();
1417
                            char mnemonic = getMnemonic(text, mnemonics);
1418
                            if ( ' ' != mnemonic ) {
1419
                                ((JMenuItem) comps[i]).setMnemonic(mnemonic);
1420
                                mnemonics[i] = mnemonic;
1421
                            }
1422
                        }
1423
                        allowSeparator = true; // separators are OK after
1424
                        // regular, visible entries
1425
                    }
1426
                }
1427
            }
1428
        }
1429
    }
1430

    
1431
    /**
1432
     * Helper functios for assigning a unique mnemomic char from
1433
     * a pool of unassigned onces, stored in the array "mnemomnics"
1434
     */
1435
    private char getMnemonic(String text, char[] mnemonics) {
1436
        Vector words = new Vector();
1437
        StringTokenizer t = new StringTokenizer(text);
1438
        int maxsize = 0;
1439

    
1440
        while ( t.hasMoreTokens() ) {
1441
            String word = t.nextToken();
1442
            if ( word.length() > maxsize ) {
1443
                maxsize = word.length();
1444
            }
1445
            words.addElement(word);
1446
        }
1447
        words.trimToSize();
1448

    
1449
        for ( int i = 0; i < maxsize; ++i ) {
1450
            char mnemonic = getMnemonic(words, mnemonics, i);
1451
            if ( ' ' != mnemonic ) {
1452
                return mnemonic;
1453
            }
1454
        }
1455

    
1456
        return ' ';
1457
    }
1458

    
1459
    private char getMnemonic(Vector words, char[] mnemonics, int index) {
1460
        int numwords = words.size();
1461

    
1462
        for ( int i = 0; i < numwords; ++i ) {
1463
            String word = (String) words.elementAt(i);
1464
            if ( index >= word.length() ) {
1465
                continue;
1466
            }
1467

    
1468
            char c = word.charAt(index);
1469
            if ( !isMnemonicExists(c, mnemonics) ) {
1470
                /* pick only valid chars */
1471
                if ( (c != ':') && (c != '.') && (c != ',') && (c != ';')
1472
                        && (c != '-') && (c != '+') && (c != '/') && (c != '\\')
1473
                        && (c != '\'') && (c != '\"') && (c != ' ') && (c != '=')
1474
                        && (c != '(') && (c != ')') && (c != '[') && (c != ']')
1475
                        && (c != '{') && (c != '}') && (c != '$') && (c != '*')
1476
                        && (c != '&') && (c != '%') && (c != '!') && (c != '?')
1477
                        && (c != '#') && (c != '~') && (c != '_') ) {
1478
                    return c;
1479
                }
1480
            }
1481
        }
1482
        return ' ';
1483
    }
1484

    
1485
    private boolean isMnemonicExists(char c, char[] mnemonics) {
1486
        int num = mnemonics.length;
1487
        for ( int i = 0; i < num; ++i ) {
1488
            if ( mnemonics[i] == c ) {
1489
                return true;
1490
            }
1491
        }
1492
        return false;
1493
    }
1494

    
1495
    /**
1496
     * Muestra la memoria consumida por el programa
1497
     */
1498
    private void showMemory() {
1499
        Runtime r = Runtime.getRuntime();
1500
        long mem = r.totalMemory() - r.freeMemory();
1501
        logger.debug(PluginServices.getText(this, "memory_usage") + " " + mem
1502
                / 1024 + " KB");
1503
    }
1504

    
1505
    public MDIManager getMDIManager() {
1506
        return mdiManager;
1507
    }
1508

    
1509
    public NewStatusBar getStatusBar() {
1510
        return bEstado;
1511
    }
1512

    
1513
    /**
1514
     * You can use this function to select the appropiate
1515
     * tool inside the toolbars
1516
     */
1517
    public void setSelectedTool(String actionCommand) {
1518
        setSelectedTool(defaultGroup, actionCommand);
1519
    }
1520

    
1521
    /**
1522
     * You can use this function to select the appropiate
1523
     * tool inside the toolbars
1524
     */
1525
    public void setSelectedTool(String groupName, String actionCommand) {
1526
        ButtonGroup group = (ButtonGroup) buttonGroupMap.get(groupName);
1527
        if ( group == null ) {
1528
            return;
1529
        }
1530

    
1531
        Enumeration enumeration = group.getElements();
1532
        while ( enumeration.hasMoreElements() ) {
1533
            AbstractButton button = (AbstractButton) enumeration.nextElement();
1534
            if ( button.getActionCommand().equals(actionCommand) ) {
1535
                button.setSelected(true);
1536
            }
1537
        }
1538

    
1539
        selectedTool.put(groupName, actionCommand);
1540
    }
1541

    
1542
    /**
1543
     * You can use this function to select the appropiate
1544
     * tool inside the toolbars
1545
     */
1546
    public void setSelectedTools(Map selectedTools) {
1547
        selectedTool = selectedTools;
1548
        if ( selectedTools == null ) {
1549
            return;
1550
        }
1551
        Iterator groupNames = selectedTools.keySet().iterator();
1552
        while ( groupNames.hasNext() ) {
1553
            try {
1554
                String groupName = (String) groupNames.next();
1555
                ButtonGroup group = (ButtonGroup) buttonGroupMap.get(groupName);
1556
                Enumeration enumeration = group.getElements();
1557
                String actionCommand = (String) selectedTools.get(groupName);
1558
                if ( actionCommand == null ) {
1559
                    continue;
1560
                }
1561
                while ( enumeration.hasMoreElements() ) {
1562
                    AbstractButton button
1563
                            = (AbstractButton) enumeration.nextElement();
1564
                    if ( button.getActionCommand().equals(actionCommand) ) {
1565
                        button.setSelected(true);
1566
                    }
1567
                }
1568
            } catch (ClassCastException ex) {
1569
                logger
1570
                        .error("selectedTool should only contain pairs (String groupName, JToolBarToggleButton button)");
1571
            }
1572
        }
1573
    }
1574

    
1575
    /**
1576
     * DOCUMENT ME!
1577
     *
1578
     * @param clase
1579
     * @param label
1580
     */
1581
    public void setStatusBarLabels(Class<?> clase, Label[] label) {
1582
        classLabels.put(clase, label);
1583
    }
1584

    
1585
    public void removeStatusBarLabels(Class<?> clase) {
1586
        classLabels.remove(clase);
1587
    }
1588

    
1589
    public void addStatusBarControl(Class<?> extensionClass, IControl control) {
1590
        control.addActionListener(this);
1591
        bEstado.addControl(control.getName(), (Component) control);
1592
        if ( control instanceof JComponent ) {
1593
            addControl((JComponent) control);
1594
            PluginsManager pluginsManager = PluginsLocator.getManager();
1595
            IExtension extension = pluginsManager.getExtension((Class<? extends IExtension>) extensionClass);
1596
            this.control2extensions.put((JComponent)control, extension);
1597
        }
1598
    }
1599

    
1600
    public void addToolBarControl(Class<?> extensionClass, JToolBar control, String name) {
1601
        toolBars.add(control);
1602
        addControl(control);
1603
        
1604
        PluginsManager pluginsManager = PluginsLocator.getManager();
1605
        IExtension extension = pluginsManager.getExtension((Class<? extends IExtension>) extensionClass);
1606
        this.control2extensions.put(control, extension);
1607
    }
1608

    
1609
    public void removeStatusBarControl(String name) {
1610
        Component c = bEstado.removeControl(name);
1611
        if ( c instanceof JComponent ) {
1612
            removeControl((JComponent) c);
1613
        }
1614
    }
1615

    
1616
    public void removeMenu(Menu menu) {
1617
        JMenuItem delete = (JMenuItem) infoCodedMenus.get(menu);
1618

    
1619
        if ( delete == null ) {
1620
            throw new NoSuchElementException(menu.getText());
1621
        }
1622

    
1623
        delete.getParent().remove(delete);
1624
        infoCodedMenus.remove(menu);
1625
    }
1626

    
1627
    public void addMenu(Menu menu, ActionListener listener,
1628
            PluginClassLoader loader) {
1629
        JMenu menuPadre = createMenuAncestors(menu, loader);
1630

    
1631
        // Se registra y a?aade el menu
1632
        JMenuItem nuevoMenu = createJMenuItem(loader, menu);
1633
        nuevoMenu.addMouseListener(tooltipListener);
1634
        if ( listener != null && menu.getName() != null && menu.getName().trim().length() > 0 ) {
1635
            ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1636
            final ActionInfo actionInfo = actionManager.getAction(menu.getName());
1637
            if ( actionInfo != null ) {
1638
                nuevoMenu.removeActionListener(actionInfo);
1639
            }
1640
            nuevoMenu.addActionListener(listener);
1641
        } else {
1642
            /*
1643
             * We also add action listener for menu with
1644
             * no name but with text:
1645
             * 
1646
             * Window/Project manager
1647
             * Window/View - 1
1648
             * Window/View - 2
1649
             * etc
1650
             */
1651
            if ( listener != null && menu.getText() != null && menu.getText().trim().length() > 0 ) {
1652
                nuevoMenu.addActionListener(listener);
1653
            }
1654

    
1655
        }
1656
        menuPadre.add(nuevoMenu);
1657

    
1658
        infoCodedMenus.put(menu, nuevoMenu);
1659
    }
1660

    
1661
    public void changeMenuName(String[] menu, String newName,
1662
            PluginClassLoader loader) {
1663

    
1664
        ArrayList menuList = new ArrayList();
1665
        for ( int i = 0; i < menu.length; i++ ) {
1666
            menuList.add(menu[i]);
1667
        }
1668

    
1669
        javax.swing.JMenuItem newMenu = getMenu(menuList, menuBar);
1670
        if ( newMenu == null ) {
1671
            throw new NoSuchMenuException(menu[0]);
1672
        } else {
1673
            newMenu.setText(PluginServices.getText(this, newName));
1674
        }
1675
    }
1676

    
1677
    public void componentHidden(ComponentEvent arg0) {
1678
    }
1679

    
1680
    public void componentMoved(ComponentEvent arg0) {
1681
    }
1682

    
1683
    public void componentResized(ComponentEvent arg0) {
1684
        ajustarToolBar();
1685
    }
1686

    
1687
    public void componentShown(ComponentEvent arg0) {
1688
    }
1689

    
1690
    public void componentAdded(ContainerEvent arg0) {
1691
        ajustarToolBar();
1692
    }
1693

    
1694
    public void componentRemoved(ContainerEvent arg0) {
1695
        ajustarToolBar();
1696
    }
1697

    
1698
    public class TooltipListener extends MouseAdapter {
1699

    
1700
        @Override
1701
        public void mouseEntered(MouseEvent e) {
1702
            JComponent control = (JComponent) e.getSource();
1703
            EnableTextSupport ets = (EnableTextSupport) e.getSource();
1704

    
1705
            String texto = null;
1706
            texto = control.getToolTipText();
1707

    
1708
            if ( texto != null ) {
1709
                bEstado.setInfoTextTemporal(texto);
1710
            }
1711
        }
1712

    
1713
        @Override
1714
        public void mouseExited(MouseEvent arg0) {
1715
            bEstado.restaurarTexto();
1716
        }
1717

    
1718
        @Override
1719
        public void mousePressed(MouseEvent e) {
1720
            bEstado.restaurarTexto();
1721
        }
1722
    }
1723

    
1724
    public String getTitlePrefix() {
1725
        return titlePrefix;
1726
    }
1727

    
1728
    public void setTitlePrefix(String titlePrefix) {
1729
        this.titlePrefix = titlePrefix;
1730
    }
1731

    
1732
    public Map getSelectedTools() {
1733
        return selectedTool;
1734
    }
1735

    
1736
    public HashMap getInitialSelectedTools() {
1737
        return initialSelectedTools;
1738
    }
1739

    
1740
    /**
1741
     * Get a previously added JComponent by name.
1742
     * For example you can use it if you need to obtain a JToolBar to
1743
     * add some customized component.
1744
     *
1745
     * @param name
1746
     * @return the JComponent or null if none has been found
1747
     */
1748
    public JComponent getComponentByName(String name) {
1749
        Iterator e = controlsIterator();
1750

    
1751
        while ( e.hasNext() ) {
1752
            JComponent control = (JComponent) e.next();
1753
            String nameCtrl = control.getName();
1754
            if ( nameCtrl != null ) {
1755
                if ( nameCtrl.compareTo(name) == 0 ) {
1756
                    return control;
1757
                }
1758
            }
1759
        }
1760
        Iterator it = toolBarMap.values().iterator();
1761
        while ( it.hasNext() ) {
1762
            JComponent t = (JComponent) it.next();
1763
            String nameCtrl = t.getName();
1764
            if ( nameCtrl != null ) {
1765
                if ( nameCtrl.compareTo(name) == 0 ) {
1766
                    return t;
1767
                }
1768
            }
1769

    
1770
        }
1771

    
1772
        return null;
1773
    }
1774

    
1775
    public SelectableToolBar[] getToolbars() {
1776
        return (SelectableToolBar[]) toolBarMap.values().toArray(
1777
                new SelectableToolBar[0]);
1778
    }
1779

    
1780
    public boolean getToolbarVisibility(String name) {
1781
        JComponent component
1782
                = PluginServices.getMainFrame().getComponentByName(name);
1783
        if ( (component != null) && (component instanceof SelectableToolBar) ) {
1784
            SelectableToolBar toolBar = (SelectableToolBar) component;
1785
            return toolBar.getAndamiVisibility();
1786
        }
1787
        return false;
1788
    }
1789

    
1790
    public boolean setToolbarVisibility(String name, boolean visibility) {
1791
        JComponent component
1792
                = PluginServices.getMainFrame().getComponentByName(name);
1793
        if ( (component != null) && (component instanceof SelectableToolBar) ) {
1794
            SelectableToolBar toolBar = (SelectableToolBar) component;
1795
            boolean oldVisibility = toolBar.getAndamiVisibility();
1796
            toolBar.setAndamiVisibility(visibility);
1797
            enableControls();
1798
            return oldVisibility;
1799
        }
1800
        return false;
1801
    }
1802

    
1803
    public javax.swing.JMenuItem getMenuEntry(String[] menuPath) {
1804
        ArrayList menu = new ArrayList();
1805
        for ( int i = 0; i < menuPath.length; i++ ) {
1806
            menu.add(menuPath[i]);
1807
        }
1808
        return getMenu(menu, menuBar);
1809
    }
1810

    
1811
    public void messageDialog(String message, String title, int messageType) {
1812
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1813
        helper.messageDialog(message, title, messageType);
1814
    }
1815

    
1816
    public void messageDialog(String message, String[] messageArgs,
1817
            String title, int messageType) {
1818
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1819
        helper.messageDialog(message, messageArgs, title, messageType);
1820
    }
1821

    
1822
    public int confirmDialog(String message, String title, int optionType,
1823
            int messageType) {
1824
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1825
        return helper.confirmDialog(message, title, optionType, messageType);
1826
    }
1827

    
1828
    public String inputDialog(String message, String title, int messageType,
1829
            String initialValue) {
1830
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1831
        return helper.inputDialog(message, title, messageType, initialValue);
1832
    }
1833

    
1834
    public String inputDialog(String message, String title) {
1835
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1836
        return helper.inputDialog(message, title);
1837
    }
1838

    
1839
    public void showDialog(Component contents, String title) {
1840
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1841
        helper.showDialog(contents, title);
1842
    }
1843

    
1844
    public Component createComponent(Class<? extends Component> theClass,
1845
            Object... parameters) {
1846
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1847
        return helper.createComponentWithParams(theClass, parameters);
1848
    }
1849

    
1850
    public Component createComponentWithParams(
1851
            Class<? extends Component> theClass, Object[] parameters) {
1852
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1853
        return helper.createComponentWithParams(theClass, parameters);
1854
    }
1855

    
1856
    public File[] showChooserDialog(
1857
            final String title,
1858
            final int type, // SAVE_DIALOG / OPEN_DIALOG
1859
            final int selectionMode, //    JFileChooser.FILES_ONLY, JFileChooser.DIRECTORIES_ONLY, JFileChooser.FILES_AND_DIRECTORIES
1860
            final boolean multiselection,
1861
            final File initialPath,
1862
            final FileFilter filter,
1863
            final boolean fileHidingEnabled
1864
    ) {
1865
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1866
        return helper.showChooserDialog(title, type, selectionMode, multiselection, initialPath, filter, fileHidingEnabled);
1867
    }
1868

    
1869
    public File[] showOpenDirectoryDialog(String title, File initialPath) {
1870
        return showChooserDialog(title, JFileChooser.OPEN_DIALOG, JFileChooser.DIRECTORIES_ONLY, false, initialPath, null, false);
1871
    }
1872

    
1873
    public File[] showOpenFileDialog(String title, File initialPath) {
1874
        return showChooserDialog(title, JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY, false, initialPath, null, false);
1875
    }
1876

    
1877
    public File[] showSaveFileDialog(String title, File initialPath) {
1878
        return showChooserDialog(title, JFileChooser.SAVE_DIALOG, JFileChooser.FILES_ONLY, false, initialPath, null, false);
1879
    }
1880

    
1881
    private void addControl(JComponent control) {
1882
        controls.add(control);
1883
    }
1884

    
1885
    private void removeControl(JComponent control) {
1886
        controls.remove(control);
1887
    }
1888

    
1889
    private Iterator<JComponent> controlsIterator() {
1890
        return this.controls.iterator();
1891
    }
1892

    
1893
    @Override
1894
    public void setLocale(Locale locale) {
1895
        super.setLocale(locale); //To change body of generated methods, choose Tools | Templates.
1896
        MDIManager mdiManager = MDIManagerFactory.createManager();
1897
        mdiManager.setLocale(locale);
1898
        if ( this.controls != null && !this.controls.isEmpty() ) {
1899
            this.refreshControls();
1900
        }
1901
    }
1902

    
1903
}