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 @ 41511

History | View | Annotate | Download (65.1 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 boolean isInitialized() {
214
        return instance!=null ;
215
    }
216
    
217
    public static MDIFrame getInstance() {
218
        if ( instance == null ) {
219
            instance = new MDIFrame();
220
        }
221
        return instance;
222
    }
223

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

    
235
        // Se a?aden los listeners del JFrame
236
        this.addWindowListener(new WindowAdapter() {
237

    
238
            @Override
239
            public void windowClosing(WindowEvent e) {
240
                Launcher.closeApplication();
241
            }
242
        });
243
        this.addComponentListener(this);
244
        this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
245

    
246
        // Se configura la barra de menu
247
        setJMenuBar(menuBar);
248

    
249
        // Se configura el layout del JFrame principal
250
        this.getContentPane().setLayout(new BorderLayout());
251

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

    
262
        // Add the status bar of the application
263
        bEstado = new NewStatusBar();
264
        bEstado.message(Messages.getString("StatusBar.Aplicacion_iniciada"), JOptionPane.INFORMATION_MESSAGE);
265
        getContentPane().add(bEstado, BorderLayout.SOUTH);
266

    
267
        this.toolBars.addContainerListener(this);
268

    
269

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

    
283
        mdiManager.init(this);
284
    }
285

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

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

    
320
        JToolBarToggleButton btn;
321
        ImageIcon image
322
                = PluginServices.getIconTheme().get(selectableTool.getIcon());
323

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

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

    
346
        SelectableToolBar jtb = (SelectableToolBar) toolBarMap.get(name);
347

    
348
        if ( jtb == null ) {
349
            jtb = new SelectableToolBar(name);
350
            jtb.setRollover(true);
351
            jtb.setAndamiVisibility(toolBar.getIsVisible());
352
            toolBarMap.put(name, jtb);
353
            toolBars.add(jtb);
354
        }
355

    
356
        ButtonGroup group;
357
        if ( buttonGroupMap.containsKey(selectableTool.getGroup()) ) {
358
            group = (ButtonGroup) buttonGroupMap.get(selectableTool.getGroup());
359
        } else {
360
            group = new ButtonGroup();
361
            buttonGroupMap.put(selectableTool.getGroup(), group);
362

    
363
        }
364
        jtb.addButton(group, btn);
365
        buttonModel.setGroupName(selectableTool.getGroup());
366

    
367
        if ( selectableTool.getIsDefault() ) {
368
            btn.setSelected(true);
369
            initialSelectedTools.put(selectableTool.getGroup(),
370
                    btn.getActionCommand());
371
        }
372

    
373
        addControl(btn);
374

    
375
        if ( selectableTool.getName() != null ) {
376
            btn.setName(selectableTool.getName());
377
        }
378

    
379
        if ( selectableTool.getTooltip() != null ) {
380
            btn.setToolTip(i18nManager.getTranslation(selectableTool.getTooltip()));
381
            btn.setToolTipKey(selectableTool.getTooltip());
382
        }
383

    
384
        if ( selectableTool.getEnableText() != null ) {
385
            btn.setEnableText(i18nManager.getTranslation(selectableTool.getEnableText()));
386
        }
387

    
388
        if ( selectableTool.getLast() == true ) {
389
            jtb.addSeparator();
390
        }
391
    }
392

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

    
427
        I18nManager i18nManager = ToolsLocator.getI18nManager();
428

    
429
        JToolBarButton btn;
430
        ImageIcon image = IconThemeHelper.getImageIcon(actionTool.getIcon());
431

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

    
441
        btn.setMargin(new Insets(0, 0, 0, 0));
442
        btn.addMouseListener(tooltipListener);
443
        btn.addActionListener(this);
444
        btn.setFocusable(false);
445
        btn.setActionCommand(actionTool.getActionCommand());
446
        btn.setEnabled(false);
447
        btn.setVisible(false);
448

    
449
        String name = toolBar.getName();
450

    
451
        SelectableToolBar jtb = (SelectableToolBar) toolBarMap.get(name);
452

    
453
        if ( jtb == null ) {
454
            jtb = new SelectableToolBar(name);
455
            jtb.setRollover(true);
456
            jtb.setAndamiVisibility(toolBar.getIsVisible());
457
            toolBarMap.put(name, jtb);
458
            toolBars.add(jtb);
459
        }
460

    
461
        jtb.add(btn);
462

    
463
        addControl(btn);
464

    
465
        if ( actionTool.getName() != null ) {
466
            btn.setName(actionTool.getName());
467
        }
468

    
469
        if ( actionTool.getTooltip() != null ) {
470
            btn.setToolTip(i18nManager.getTranslation(actionTool.getTooltip()));
471
            btn.setToolTipKey(actionTool.getTooltip());
472
        }
473

    
474
        if ( actionTool.getEnableText() != null ) {
475
            btn.setEnableText(i18nManager.getTranslation(actionTool.getEnableText()));
476
        }
477

    
478
        if ( actionTool.getLast() == true ) {
479
            jtb.addSeparator();
480
        }
481
    }
482

    
483
    public void addTool(final ActionInfo action, final String toolBarName) {
484
        I18nManager i18nManager = ToolsLocator.getI18nManager();
485

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

    
508
        SelectableToolBar jtb = (SelectableToolBar) toolBarMap.get(toolBarName);
509
        if ( jtb == null ) {
510
            jtb = new SelectableToolBar(toolBarName);
511
            jtb.setRollover(true);
512
            jtb.setAndamiVisibility(true);
513
            toolBarMap.put(toolBarName, jtb);
514
            toolBars.add(jtb);
515
        }
516
        jtb.add(btn);
517

    
518
        addControl(btn);
519

    
520
    }
521

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

    
542
    private JMenu createMenuAncestors(String text) {
543
        I18nManager i18nManager = ToolsLocator.getI18nManager();
544

    
545
        MenuElement menuPadre = null;
546

    
547
        String[] menues = text.split("/");
548
        List menuList = new ArrayList();
549
        menuList.add(menues[0]);
550
        menuPadre = getMenu(menuList, menuBar);
551

    
552
        JMenu padre = null;
553

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

    
567
        // Se crea el resto de menus
568
        ArrayList temp = new ArrayList();
569

    
570
        for ( int i = 1; i < (menues.length - 1); i++ ) {
571
            temp.add(menues[i]);
572
        }
573

    
574
        menuPadre = createMenus(temp, padre);
575

    
576
        return (JMenu) menuPadre;
577
    }
578

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

    
617
        if ( menu.getIs_separator() ) {
618
            menuPadre.addSeparator();
619
            return;
620
        }
621

    
622
        JMenuItem nuevoMenu = createJMenuItem(loader, menu);
623
        nuevoMenu.addMouseListener(tooltipListener);
624
        menuPadre.add(nuevoMenu);
625
        addControl(nuevoMenu);
626

    
627
    }
628

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

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

    
657
            for ( int i = 0; i < parentItem.getMenuComponentCount(); i++ ) {
658

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

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

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

    
720
    /**
721
     * @param menuComponent
722
     * @param nombres
723
     * @return
724
     */
725
    private boolean lastMenuItemWithoutName(Component mc, List names) {
726

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

    
749
    private class JMenuTraslatable extends JMenu implements TranslatableButton {
750

    
751
        private TranslatableButtonHelper i18nHelper = new TranslatableButtonHelper();
752

    
753
        public JMenuTraslatable(String text) {
754
            super(text);
755
        }
756

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

    
761
        public void setToolTipKey(String key) {
762
            this.i18nHelper.setTooltip(key);
763
        }
764

    
765
        public void translate() {
766
            if ( this.i18nHelper.needTranslation() ) {
767
                this.i18nHelper.translate();
768
                this.setText(this.i18nHelper.getText());
769
            }
770
        }
771

    
772
    }
773

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

    
798
        // si no quedan nombres de menu por crear se vuelve: caso base
799
        if ( nombres.isEmpty() ) {
800
            return padre;
801
        }
802

    
803
        // Se busca el menu por si ya existiera para no crearlo otra vez
804
        JMenu buscado = null;
805

    
806
        for ( int i = 0; i < padre.getMenuComponentCount(); i++ ) {
807
            try {
808
                JMenu hijo = (JMenu) padre.getMenuComponent(i);
809

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

    
820
        if ( buscado != null ) {
821
            // Si lo hemos encontrado creamos el resto
822
            nombres.remove(0);
823

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

    
835
            nombres.remove(0);
836

    
837
            return createMenus(nombres, menuPadre);
838
        }
839
    }
840

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

    
852
        int toolHeight = 0;
853

    
854
        for ( int i = 0; i < toolBars.getComponentCount(); i++ ) {
855
            Component c = toolBars.getComponent(i);
856

    
857
            if ( !c.isVisible() ) {
858
                continue;
859
            }
860

    
861
            double width = c.getPreferredSize().getWidth();
862
            acum = acum + width;
863

    
864
            if ( acum > this.getWidth() ) {
865
                numFilas++;
866
                acum = width + margen;
867
            }
868

    
869
            if ( c.getPreferredSize().getHeight() > toolHeight ) {
870
                toolHeight = c.getPreferredSize().height;
871
            }
872
        }
873

    
874
        toolBars.setPreferredSize(new Dimension(this.getWidth(),
875
                (numFilas * toolHeight)));
876

    
877
        toolBars.updateUI();
878
    }
879

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

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

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

    
902
        String actionName = "(unknow)";
903
        try {
904
            JComponent control = (JComponent) e.getSource();
905
            actionName = control.getName();
906

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

    
927
        } catch (Throwable ex) {
928
            logger.error("Can't perform action '" + actionName + "'.", ex);
929
        }
930

    
931
        enableControls();
932
        showMemory();
933
    }
934

    
935
    private String getName(String name, PluginClassLoader loader) {
936
        if ( name.indexOf('.') == -1 ) {
937
            return loader.getPluginName() + "." + name;
938
        } else {
939
            return name;
940
        }
941
    }
942

    
943
    public void addPopupMenu(PluginClassLoader loader, PopupMenu menu) {
944
        if ( !SwingUtilities.isEventDispatchThread() ) {
945
            throw new RuntimeException("No Event Dispatch Thread");
946
        }
947

    
948
        String name = getName(menu.getName(), loader);
949

    
950
        // Se crea el control popupmenu
951
        JPopUpMenu popupMenu = (JPopUpMenu) popupMap.get(name);
952

    
953
        if ( popupMenu == null ) {
954
            popupMenu = new JPopUpMenu(menu.getName());
955
            popupMap.put(name, popupMenu);
956
        }
957

    
958
        Menu[] menues = menu.getMenu();
959
        for ( int i = 0; i < menues.length; i++ ) {
960
            JMenuItem nuevoMenu = createJMenuItem(loader, menues[i]);
961
            popupMenu.add(nuevoMenu);
962
        }
963
    }
964

    
965
    private JMenuItem createJMenuItem(PluginClassLoader loader, Menu menu) {
966
        JMenuItem nuevoMenu = null;
967

    
968
        I18nManager i18nManager = ToolsLocator.getI18nManager();
969

    
970
        String text = menu.getText();
971
        int n = text.lastIndexOf('/');
972
        if ( n >= 0 ) {
973
            text = text.substring(n + 1);
974
        }
975
        String translatedText = i18nManager.getTranslation(text);
976

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

    
992
        if ( menu.getKey() != null ) {
993
            nuevoMenu.setAccelerator(KeyMapping.getKeyStroke(menu.getKey()));
994
        }
995

    
996
        nuevoMenu.setActionCommand(menu.getActionCommand());
997

    
998
        if ( menu.getTooltip() != null ) {
999
            nuevoMenu.setToolTip(i18nManager.getTranslation(menu.getTooltip()));
1000
            nuevoMenu.setToolTipKey(menu.getTooltip());
1001
        }
1002

    
1003
        if ( menu.getEnableText() != null ) {
1004
            nuevoMenu.setEnableText(i18nManager.getTranslation(menu.getEnableText()));
1005
        }
1006

    
1007
        nuevoMenu.setEnabled(true);
1008
        nuevoMenu.setVisible(true);
1009

    
1010
        if ( menu.getName() != null ) {
1011
            ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1012
            final ActionInfo actionInfo = actionManager.getAction(menu.getName());
1013
            if ( actionInfo != null ) {
1014
                nuevoMenu.addActionListener(actionInfo);
1015
            }
1016
        }
1017
        return nuevoMenu;
1018
    }
1019

    
1020
    private JMenuItem createJMenuItem(ActionInfo action, String text) {
1021
        I18nManager i18nManager = ToolsLocator.getI18nManager();
1022
        JMenuItem nuevoMenu = null;
1023
        String label = null;
1024

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

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

    
1072
        if ( menu != null ) {
1073
            menu.show(c, x, y);
1074
        }
1075
    }
1076

    
1077
    public void removePopupMenuListener(String name, ActionListener listener) {
1078
        JPopupMenu menu = (JPopupMenu) popupMap.get(name);
1079

    
1080
        if ( menu != null ) {
1081
            Component[] jmenuitems = menu.getComponents();
1082

    
1083
            for ( int i = 0; i < jmenuitems.length; i++ ) {
1084
                if ( jmenuitems[i] instanceof JMenuItem ) {
1085
                    ((JMenuItem) jmenuitems[i]).removeActionListener(listener);
1086
                }
1087
            }
1088
        }
1089
    }
1090

    
1091
    public void addPopupMenuListener(String popupName, Component c,
1092
            ActionListener listener, PluginClassLoader loader) {
1093
        final String name = getName(popupName, loader);
1094

    
1095
        JPopupMenu menu = (JPopupMenu) popupMap.get(name);
1096

    
1097
        if ( menu != null ) {
1098
            Component[] jmenuitems = menu.getComponents();
1099

    
1100
            for ( int i = 0; i < jmenuitems.length; i++ ) {
1101
                if ( jmenuitems[i] instanceof JMenuItem ) {
1102
                    ((JMenuItem) jmenuitems[i]).addActionListener(listener);
1103
                }
1104
            }
1105
        }
1106

    
1107
        c.addMouseListener(new MouseAdapter() {
1108

    
1109
            @Override
1110
            public void mousePressed(MouseEvent e) {
1111
                if ( e.isPopupTrigger() ) {
1112
                    showPopupMenu(name, e.getX(), e.getY(), e.getComponent());
1113
                }
1114
            }
1115

    
1116
            @Override
1117
            public void mouseReleased(MouseEvent e) {
1118
                if ( e.isPopupTrigger() ) {
1119
                    showPopupMenu(name, e.getX(), e.getY(), e.getComponent());
1120
                }
1121
            }
1122
        });
1123
    }
1124

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

    
1141
        ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1142
        ActionInfoStatusCache cache = actionManager.createActionStatusCache();
1143

    
1144
        // Enable or disable controls, according to its associated extensions
1145
        Iterator<JComponent> e = controlsIterator();
1146

    
1147
        while ( e.hasNext() ) {
1148
            JComponent control = (JComponent) e.next();
1149
            String actionName = control.getName();
1150
            ActionInfo action = actionManager.getAction(actionName);
1151
            try {
1152
                boolean enabled = false;
1153
                boolean visible = false;
1154

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

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

    
1216
        // hide the toolbars that don't contain any visible tool
1217
        Iterator it = toolBarMap.values().iterator();
1218

    
1219
        while ( it.hasNext() ) {
1220
            JComponent t = (JComponent) it.next();
1221
            boolean todosOcultos = true;
1222

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

    
1231
            if ( todosOcultos ) {
1232
                t.setVisible(false);
1233
            } else {
1234
                if ( t instanceof SelectableToolBar ) {
1235
                    t.setVisible(((SelectableToolBar) t).getAndamiVisibility());
1236
                } else {
1237
                    t.setVisible(true);
1238
                }
1239
            }
1240
        }
1241

    
1242
        if ( mdiManager != null ) {
1243
            JPanel f = (JPanel) mdiManager.getActiveWindow();
1244

    
1245
            if ( f != null ) {
1246
                if ( lastLabelClass != f.getClass() ) {
1247
                    lastLabelClass = f.getClass();
1248

    
1249
                    Label[] lbls = (Label[]) classLabels.get(lastLabelClass);
1250

    
1251
                    if ( lbls != null ) {
1252
                        bEstado.setLabelSet(lbls);
1253
                    }
1254
                }
1255
            }
1256
        }
1257

    
1258
        ajustarToolBar();
1259

    
1260
        showMemory();
1261
    }
1262

    
1263
    public void refreshControls() {
1264
        if ( !SwingUtilities.isEventDispatchThread() ) {
1265
            SwingUtilities.invokeLater(new Runnable() {
1266
                public void run() {
1267
                    refreshControls();
1268
                }
1269
            });
1270
            return;
1271
        }
1272

    
1273
        ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1274
        ActionInfoStatusCache cache = actionManager.createActionStatusCache();
1275
        IconTheme icontheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
1276

    
1277
        Iterator e = controlsIterator();
1278

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

    
1304
    public void message(String msg, int messageTyoe) {
1305
        this.getStatusBar().message(msg, messageTyoe);
1306
    }
1307

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

    
1320
        // Si no tiene hijos se devuelve su visibilidad
1321
        if ( submenus.length == 0 ) {
1322
            return menu.getComponent().isVisible();
1323
        }
1324

    
1325
        /*
1326
         * Si tiene hijos se devuelve true si alg?no de ellos es visible,
1327
         * pero se itera por todos ellos
1328
         */
1329
        boolean visible = false;
1330

    
1331
        for ( int i = 0; i < submenus.length; i++ ) {
1332
            if ( hideMenus(submenus[i]) ) {
1333
                if ( !(menu instanceof JPopupMenu) ) {
1334
                    menu.getComponent().setVisible(true);
1335
                }
1336

    
1337
                visible = true;
1338
            }
1339
        }
1340

    
1341
        if ( visible ) {
1342
            return true;
1343
        }
1344

    
1345
        menu.getComponent().setVisible(false);
1346

    
1347
        return false;
1348
    }
1349

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

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

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

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

    
1444
        while ( t.hasMoreTokens() ) {
1445
            String word = t.nextToken();
1446
            if ( word.length() > maxsize ) {
1447
                maxsize = word.length();
1448
            }
1449
            words.addElement(word);
1450
        }
1451
        words.trimToSize();
1452

    
1453
        for ( int i = 0; i < maxsize; ++i ) {
1454
            char mnemonic = getMnemonic(words, mnemonics, i);
1455
            if ( ' ' != mnemonic ) {
1456
                return mnemonic;
1457
            }
1458
        }
1459

    
1460
        return ' ';
1461
    }
1462

    
1463
    private char getMnemonic(Vector words, char[] mnemonics, int index) {
1464
        int numwords = words.size();
1465

    
1466
        for ( int i = 0; i < numwords; ++i ) {
1467
            String word = (String) words.elementAt(i);
1468
            if ( index >= word.length() ) {
1469
                continue;
1470
            }
1471

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

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

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

    
1509
    public MDIManager getMDIManager() {
1510
        return mdiManager;
1511
    }
1512

    
1513
    public NewStatusBar getStatusBar() {
1514
        return bEstado;
1515
    }
1516

    
1517
    /**
1518
     * You can use this function to select the appropiate
1519
     * tool inside the toolbars
1520
     */
1521
    public void setSelectedTool(String actionCommand) {
1522
        setSelectedTool(defaultGroup, actionCommand);
1523
    }
1524

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

    
1535
        Enumeration enumeration = group.getElements();
1536
        while ( enumeration.hasMoreElements() ) {
1537
            AbstractButton button = (AbstractButton) enumeration.nextElement();
1538
            if ( button.getActionCommand().equals(actionCommand) ) {
1539
                button.setSelected(true);
1540
            }
1541
        }
1542

    
1543
        selectedTool.put(groupName, actionCommand);
1544
    }
1545

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

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

    
1589
    public void removeStatusBarLabels(Class<?> clase) {
1590
        classLabels.remove(clase);
1591
    }
1592

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

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

    
1613
    public void removeStatusBarControl(String name) {
1614
        Component c = bEstado.removeControl(name);
1615
        if ( c instanceof JComponent ) {
1616
            removeControl((JComponent) c);
1617
        }
1618
    }
1619

    
1620
    public void removeMenu(Menu menu) {
1621
        JMenuItem delete = (JMenuItem) infoCodedMenus.get(menu);
1622

    
1623
        if ( delete == null ) {
1624
            throw new NoSuchElementException(menu.getText());
1625
        }
1626

    
1627
        delete.getParent().remove(delete);
1628
        infoCodedMenus.remove(menu);
1629
    }
1630

    
1631
    public void addMenu(Menu menu, ActionListener listener,
1632
            PluginClassLoader loader) {
1633
        JMenu menuPadre = createMenuAncestors(menu, loader);
1634

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

    
1659
        }
1660
        menuPadre.add(nuevoMenu);
1661

    
1662
        infoCodedMenus.put(menu, nuevoMenu);
1663
    }
1664

    
1665
    public void changeMenuName(String[] menu, String newName,
1666
            PluginClassLoader loader) {
1667

    
1668
        ArrayList menuList = new ArrayList();
1669
        for ( int i = 0; i < menu.length; i++ ) {
1670
            menuList.add(menu[i]);
1671
        }
1672

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

    
1681
    public void componentHidden(ComponentEvent arg0) {
1682
    }
1683

    
1684
    public void componentMoved(ComponentEvent arg0) {
1685
    }
1686

    
1687
    public void componentResized(ComponentEvent arg0) {
1688
        ajustarToolBar();
1689
    }
1690

    
1691
    public void componentShown(ComponentEvent arg0) {
1692
    }
1693

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

    
1698
    public void componentRemoved(ContainerEvent arg0) {
1699
        ajustarToolBar();
1700
    }
1701

    
1702
    public class TooltipListener extends MouseAdapter {
1703

    
1704
        @Override
1705
        public void mouseEntered(MouseEvent e) {
1706
            JComponent control = (JComponent) e.getSource();
1707
            EnableTextSupport ets = (EnableTextSupport) e.getSource();
1708

    
1709
            String texto = null;
1710
            texto = control.getToolTipText();
1711

    
1712
            if ( texto != null ) {
1713
                bEstado.setInfoTextTemporal(texto);
1714
            }
1715
        }
1716

    
1717
        @Override
1718
        public void mouseExited(MouseEvent arg0) {
1719
            bEstado.restaurarTexto();
1720
        }
1721

    
1722
        @Override
1723
        public void mousePressed(MouseEvent e) {
1724
            bEstado.restaurarTexto();
1725
        }
1726
    }
1727

    
1728
    public String getTitlePrefix() {
1729
        return titlePrefix;
1730
    }
1731

    
1732
    public void setTitlePrefix(String titlePrefix) {
1733
        this.titlePrefix = titlePrefix;
1734
    }
1735

    
1736
    public Map getSelectedTools() {
1737
        return selectedTool;
1738
    }
1739

    
1740
    public HashMap getInitialSelectedTools() {
1741
        return initialSelectedTools;
1742
    }
1743

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

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

    
1774
        }
1775

    
1776
        return null;
1777
    }
1778

    
1779
    public SelectableToolBar[] getToolbars() {
1780
        return (SelectableToolBar[]) toolBarMap.values().toArray(
1781
                new SelectableToolBar[0]);
1782
    }
1783

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

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

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

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

    
1820
    public void messageDialog(String message, String[] messageArgs,
1821
            String title, int messageType) {
1822
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1823
        helper.messageDialog(message, messageArgs, title, messageType);
1824
    }
1825

    
1826
    public int confirmDialog(String message, String title, int optionType,
1827
            int messageType) {
1828
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1829
        return helper.confirmDialog(message, title, optionType, messageType);
1830
    }
1831

    
1832
    public String inputDialog(String message, String title, int messageType,
1833
            String initialValue) {
1834
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1835
        return helper.inputDialog(message, title, messageType, initialValue);
1836
    }
1837

    
1838
    public String inputDialog(String message, String title) {
1839
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1840
        return helper.inputDialog(message, title);
1841
    }
1842

    
1843
    public void showDialog(Component contents, String title) {
1844
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1845
        helper.showDialog(contents, title);
1846
    }
1847

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

    
1854
    public Component createComponentWithParams(
1855
            Class<? extends Component> theClass, Object[] parameters) {
1856
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1857
        return helper.createComponentWithParams(theClass, parameters);
1858
    }
1859

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

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

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

    
1881
    public File[] showSaveFileDialog(String title, File initialPath) {
1882
        return showChooserDialog(title, JFileChooser.SAVE_DIALOG, JFileChooser.FILES_ONLY, false, initialPath, null, false);
1883
    }
1884

    
1885
    private void addControl(JComponent control) {
1886
        controls.add(control);
1887
    }
1888

    
1889
    private void removeControl(JComponent control) {
1890
        controls.remove(control);
1891
    }
1892

    
1893
    private Iterator<JComponent> controlsIterator() {
1894
        return this.controls.iterator();
1895
    }
1896

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

    
1907
}