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

History | View | Annotate | Download (63.7 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.actioninfo.ActionInfo;
78
import org.gvsig.andami.actioninfo.ActionInfoManager;
79
import org.gvsig.andami.actioninfo.ActionInfoStatusCache;
80
import org.gvsig.andami.messages.Messages;
81
import org.gvsig.andami.plugins.ExtensionDecorator;
82
import org.gvsig.andami.plugins.IExtension;
83
import org.gvsig.andami.plugins.PluginClassLoader;
84
import org.gvsig.andami.plugins.config.generate.ActionTool;
85
import org.gvsig.andami.plugins.config.generate.Label;
86
import org.gvsig.andami.plugins.config.generate.Menu;
87
import org.gvsig.andami.plugins.config.generate.PopupMenu;
88
import org.gvsig.andami.plugins.config.generate.SelectableTool;
89
import org.gvsig.andami.plugins.config.generate.SkinExtensionType;
90
import org.gvsig.andami.plugins.config.generate.ToolBar;
91
import org.gvsig.andami.ui.mdiFrame.TranslatableButtonHelper.TranslatableButton;
92
import org.gvsig.andami.ui.mdiManager.MDIManager;
93
import org.gvsig.andami.ui.mdiManager.MDIManagerFactory;
94
import org.gvsig.gui.beans.controls.IControl;
95
import org.gvsig.tools.ToolsLocator;
96
import org.gvsig.tools.i18n.I18nManager;
97
import org.gvsig.tools.swing.api.ToolsSwingLocator;
98
import org.gvsig.tools.swing.icontheme.IconTheme;
99
import org.slf4j.Logger;
100
import org.slf4j.LoggerFactory;
101

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

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

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

    
117
    private static MDIFrame instance = null;
118

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
200
    private HashMap infoCodedMenus = new HashMap();
201

    
202
    private String titlePrefix;
203

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

    
206
    private MDIFrame() {
207

    
208
    }
209

    
210
    public static MDIFrame getInstance() {
211
        if ( instance == null ) {
212
            instance = new MDIFrame();
213
        }
214
        return instance;
215
    }
216

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

    
228
        // Se a?aden los listeners del JFrame
229
        this.addWindowListener(new WindowAdapter() {
230

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

    
239
        // Se configura la barra de menu
240
        setJMenuBar(menuBar);
241

    
242
        // Se configura el layout del JFrame principal
243
        this.getContentPane().setLayout(new BorderLayout());
244

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

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

    
260
        this.toolBars.addContainerListener(this);
261

    
262

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

    
276
        mdiManager.init(this);
277
    }
278

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

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

    
313
        JToolBarToggleButton btn;
314
        ImageIcon image
315
                = PluginServices.getIconTheme().get(selectableTool.getIcon());
316

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

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

    
339
        SelectableToolBar jtb = (SelectableToolBar) toolBarMap.get(name);
340

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

    
349
        ButtonGroup group;
350
        if ( buttonGroupMap.containsKey(selectableTool.getGroup()) ) {
351
            group = (ButtonGroup) buttonGroupMap.get(selectableTool.getGroup());
352
        } else {
353
            group = new ButtonGroup();
354
            buttonGroupMap.put(selectableTool.getGroup(), group);
355

    
356
        }
357
        jtb.addButton(group, btn);
358
        buttonModel.setGroupName(selectableTool.getGroup());
359

    
360
        if ( selectableTool.getIsDefault() ) {
361
            btn.setSelected(true);
362
            initialSelectedTools.put(selectableTool.getGroup(),
363
                    btn.getActionCommand());
364
        }
365

    
366
        addControl(btn);
367

    
368
        if ( selectableTool.getName() != null ) {
369
            btn.setName(selectableTool.getName());
370
        }
371

    
372
        if ( selectableTool.getTooltip() != null ) {
373
            btn.setToolTip(i18nManager.getTranslation(selectableTool.getTooltip()));
374
            btn.setToolTipKey(selectableTool.getTooltip());
375
        }
376

    
377
        if ( selectableTool.getEnableText() != null ) {
378
            btn.setEnableText(i18nManager.getTranslation(selectableTool.getEnableText()));
379
        }
380

    
381
        if ( selectableTool.getLast() == true ) {
382
            jtb.addSeparator();
383
        }
384
    }
385

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

    
420
        I18nManager i18nManager = ToolsLocator.getI18nManager();
421

    
422
        JToolBarButton btn;
423
        ImageIcon image = IconThemeHelper.getImageIcon(actionTool.getIcon());
424

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

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

    
442
        String name = toolBar.getName();
443

    
444
        SelectableToolBar jtb = (SelectableToolBar) toolBarMap.get(name);
445

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

    
454
        jtb.add(btn);
455

    
456
        addControl(btn);
457

    
458
        if ( actionTool.getName() != null ) {
459
            btn.setName(actionTool.getName());
460
        }
461

    
462
        if ( actionTool.getTooltip() != null ) {
463
            btn.setToolTip(i18nManager.getTranslation(actionTool.getTooltip()));
464
            btn.setToolTipKey(actionTool.getTooltip());
465
        }
466

    
467
        if ( actionTool.getEnableText() != null ) {
468
            btn.setEnableText(i18nManager.getTranslation(actionTool.getEnableText()));
469
        }
470

    
471
        if ( actionTool.getLast() == true ) {
472
            jtb.addSeparator();
473
        }
474
    }
475

    
476
    public void addTool(final ActionInfo action, final String toolBarName) {
477
        I18nManager i18nManager = ToolsLocator.getI18nManager();
478

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

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

    
511
        addControl(btn);
512

    
513
    }
514

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

    
535
    private JMenu createMenuAncestors(String text) {
536
        I18nManager i18nManager = ToolsLocator.getI18nManager();
537

    
538
        MenuElement menuPadre = null;
539

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

    
545
        JMenu padre = null;
546

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

    
560
        // Se crea el resto de menus
561
        ArrayList temp = new ArrayList();
562

    
563
        for ( int i = 1; i < (menues.length - 1); i++ ) {
564
            temp.add(menues[i]);
565
        }
566

    
567
        menuPadre = createMenus(temp, padre);
568

    
569
        return (JMenu) menuPadre;
570
    }
571

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

    
610
        if ( menu.getIs_separator() ) {
611
            menuPadre.addSeparator();
612
            return;
613
        }
614

    
615
        JMenuItem nuevoMenu = createJMenuItem(loader, menu);
616
        nuevoMenu.addMouseListener(tooltipListener);
617
        menuPadre.add(nuevoMenu);
618
        addControl(nuevoMenu);
619

    
620
    }
621

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

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

    
650
            for ( int i = 0; i < parentItem.getMenuComponentCount(); i++ ) {
651

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

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

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

    
713
    /**
714
     * @param menuComponent
715
     * @param nombres
716
     * @return
717
     */
718
    private boolean lastMenuItemWithoutName(Component mc, List names) {
719

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

    
742
    private class JMenuTraslatable extends JMenu implements TranslatableButton {
743

    
744
        private TranslatableButtonHelper i18nHelper = new TranslatableButtonHelper();
745

    
746
        public JMenuTraslatable(String text) {
747
            super(text);
748
        }
749

    
750
        public void setTextKey(String key) {
751
            this.i18nHelper.setText(key);
752
        }
753

    
754
        public void setToolTipKey(String key) {
755
            this.i18nHelper.setTooltip(key);
756
        }
757

    
758
        public void translate() {
759
            if ( this.i18nHelper.needTranslation() ) {
760
                this.i18nHelper.translate();
761
                this.setText(this.i18nHelper.getText());
762
            }
763
        }
764

    
765
    }
766

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

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

    
796
        // Se busca el menu por si ya existiera para no crearlo otra vez
797
        JMenu buscado = null;
798

    
799
        for ( int i = 0; i < padre.getMenuComponentCount(); i++ ) {
800
            try {
801
                JMenu hijo = (JMenu) padre.getMenuComponent(i);
802

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

    
813
        if ( buscado != null ) {
814
            // Si lo hemos encontrado creamos el resto
815
            nombres.remove(0);
816

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

    
828
            nombres.remove(0);
829

    
830
            return createMenus(nombres, menuPadre);
831
        }
832
    }
833

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

    
845
        int toolHeight = 0;
846

    
847
        for ( int i = 0; i < toolBars.getComponentCount(); i++ ) {
848
            Component c = toolBars.getComponent(i);
849

    
850
            if ( !c.isVisible() ) {
851
                continue;
852
            }
853

    
854
            double width = c.getPreferredSize().getWidth();
855
            acum = acum + width;
856

    
857
            if ( acum > this.getWidth() ) {
858
                numFilas++;
859
                acum = width + margen;
860
            }
861

    
862
            if ( c.getPreferredSize().getHeight() > toolHeight ) {
863
                toolHeight = c.getPreferredSize().height;
864
            }
865
        }
866

    
867
        toolBars.setPreferredSize(new Dimension(this.getWidth(),
868
                (numFilas * toolHeight)));
869

    
870
        toolBars.updateUI();
871
    }
872

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

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

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

    
895
        String actionName = "(unknow)";
896
        try {
897
            JComponent control = (JComponent) e.getSource();
898
            actionName = control.getName();
899

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

    
920
        } catch (Throwable ex) {
921
            logger.error("Can't perform action '" + actionName + "'.", ex);
922
        }
923

    
924
        enableControls();
925
        showMemory();
926
    }
927

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

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

    
941
        String name = getName(menu.getName(), loader);
942

    
943
        // Se crea el control popupmenu
944
        JPopUpMenu popupMenu = (JPopUpMenu) popupMap.get(name);
945

    
946
        if ( popupMenu == null ) {
947
            popupMenu = new JPopUpMenu(menu.getName());
948
            popupMap.put(name, popupMenu);
949
        }
950

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

    
958
    private JMenuItem createJMenuItem(PluginClassLoader loader, Menu menu) {
959
        JMenuItem nuevoMenu = null;
960

    
961
        I18nManager i18nManager = ToolsLocator.getI18nManager();
962

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

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

    
985
        if ( menu.getKey() != null ) {
986
            nuevoMenu.setAccelerator(KeyMapping.getKeyStroke(menu.getKey()));
987
        }
988

    
989
        nuevoMenu.setActionCommand(menu.getActionCommand());
990

    
991
        if ( menu.getTooltip() != null ) {
992
            nuevoMenu.setToolTip(i18nManager.getTranslation(menu.getTooltip()));
993
            nuevoMenu.setToolTipKey(menu.getTooltip());
994
        }
995

    
996
        if ( menu.getEnableText() != null ) {
997
            nuevoMenu.setEnableText(i18nManager.getTranslation(menu.getEnableText()));
998
        }
999

    
1000
        nuevoMenu.setEnabled(true);
1001
        nuevoMenu.setVisible(true);
1002

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

    
1013
    private JMenuItem createJMenuItem(ActionInfo action, String text) {
1014
        I18nManager i18nManager = ToolsLocator.getI18nManager();
1015
        JMenuItem nuevoMenu = null;
1016
        String label = null;
1017

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

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

    
1065
        if ( menu != null ) {
1066
            menu.show(c, x, y);
1067
        }
1068
    }
1069

    
1070
    public void removePopupMenuListener(String name, ActionListener listener) {
1071
        JPopupMenu menu = (JPopupMenu) popupMap.get(name);
1072

    
1073
        if ( menu != null ) {
1074
            Component[] jmenuitems = menu.getComponents();
1075

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

    
1084
    public void addPopupMenuListener(String popupName, Component c,
1085
            ActionListener listener, PluginClassLoader loader) {
1086
        final String name = getName(popupName, loader);
1087

    
1088
        JPopupMenu menu = (JPopupMenu) popupMap.get(name);
1089

    
1090
        if ( menu != null ) {
1091
            Component[] jmenuitems = menu.getComponents();
1092

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

    
1100
        c.addMouseListener(new MouseAdapter() {
1101

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

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

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

    
1134
        ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1135
        ActionInfoStatusCache cache = actionManager.createActionStatusCache();
1136

    
1137
        // Enable or disable controls, according to its associated extensions
1138
        Iterator<JComponent> e = controlsIterator();
1139

    
1140
        while ( e.hasNext() ) {
1141
            JComponent control = (JComponent) e.next();
1142
            String actionlName = control.getName();
1143
            ActionInfo action = actionManager.getAction(actionlName);
1144
            try {
1145
                boolean enabled = false;
1146
                boolean visible = false;
1147

    
1148
                if ( action == null ) {
1149
                    enabled = true;
1150
                    visible = true;
1151
                } else {
1152
                    enabled = false;
1153
                    visible = cache.isVisible(action);
1154
                    if ( visible ) {
1155
                        enabled = cache.isEnabled(action);
1156
                    }
1157
                }
1158
                control.setEnabled(enabled);
1159
                control.setVisible(visible);
1160
            } catch (Exception ex) {
1161
                logger.info("Can't enable/show control '" + actionlName + "'.", ex);
1162
                this.message("Can't enable/show control '" + actionlName + "'.", JOptionPane.ERROR_MESSAGE);
1163
                try {
1164
                    control.setEnabled(false);
1165
                    control.setVisible(false);
1166
                } catch (Exception ex2) {
1167
                    // Ignore errors
1168
                }
1169
            }
1170
        }
1171

    
1172
        // Loop in the menus to hide the menus that don't have visible children
1173
        for ( int i = 0; i < menuBar.getMenuCount(); i++ ) {
1174
            MenuElement menu = menuBar.getMenu(i);
1175
            hideMenus(menu);
1176
            if ( menu instanceof JMenu ) {
1177
                // hide (ugly) redundant separators and assign keyboard
1178
                // mnemonics
1179
                Component[] comps = ((JMenu) menu).getMenuComponents();
1180
                // mnemonics have to be unique for each top-level menu
1181
                char mnemonics[] = new char[comps.length];
1182
                if ( comps.length > 0 ) {
1183
                    // Set keyboard mnemonic for this top-level entry
1184
                    String text = ((JMenu) menu).getText();
1185
                    char mnemonic = getMnemonic(text, mnemonics);
1186
                    if ( ' ' != mnemonic ) {
1187
                        ((JMenu) menu).setMnemonic(mnemonic);
1188
                        mnemonics[0] = mnemonic;
1189
                    }
1190
                }
1191
                // now go through all entries in this menu, hid
1192
                // separators if necessary and assing remaining mnemonics
1193
                hideSeparatorsAndMakeMnemonics(menu, mnemonics);
1194
            }
1195
        }
1196

    
1197
        // hide the toolbars that don't contain any visible tool
1198
        Iterator it = toolBarMap.values().iterator();
1199

    
1200
        while ( it.hasNext() ) {
1201
            JComponent t = (JComponent) it.next();
1202
            boolean todosOcultos = true;
1203

    
1204
            for ( int i = 0; i < t.getComponentCount(); i++ ) {
1205
                if ( !(t.getComponent(i) instanceof JSeparator) // separators
1206
                        // don't matter
1207
                        && t.getComponent(i).isVisible() ) {
1208
                    todosOcultos = false;
1209
                }
1210
            }
1211

    
1212
            if ( todosOcultos ) {
1213
                t.setVisible(false);
1214
            } else {
1215
                if ( t instanceof SelectableToolBar ) {
1216
                    t.setVisible(((SelectableToolBar) t).getAndamiVisibility());
1217
                } else {
1218
                    t.setVisible(true);
1219
                }
1220
            }
1221
        }
1222

    
1223
        if ( mdiManager != null ) {
1224
            JPanel f = (JPanel) mdiManager.getActiveWindow();
1225

    
1226
            if ( f != null ) {
1227
                if ( lastLabelClass != f.getClass() ) {
1228
                    lastLabelClass = f.getClass();
1229

    
1230
                    Label[] lbls = (Label[]) classLabels.get(lastLabelClass);
1231

    
1232
                    if ( lbls != null ) {
1233
                        bEstado.setLabelSet(lbls);
1234
                    }
1235
                }
1236
            }
1237
        }
1238

    
1239
        ajustarToolBar();
1240

    
1241
        showMemory();
1242
    }
1243

    
1244
    public void refreshControls() {
1245
        if ( !SwingUtilities.isEventDispatchThread() ) {
1246
            SwingUtilities.invokeLater(new Runnable() {
1247
                public void run() {
1248
                    refreshControls();
1249
                }
1250
            });
1251
            return;
1252
        }
1253

    
1254
        ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1255
        ActionInfoStatusCache cache = actionManager.createActionStatusCache();
1256
        IconTheme icontheme = ToolsSwingLocator.getIconThemeManager().getCurrent();
1257

    
1258
        Iterator e = controlsIterator();
1259

    
1260
        while ( e.hasNext() ) {
1261
            JComponent control = (JComponent) e.next();
1262
            if ( control instanceof TranslatableButton ) {
1263
                ((TranslatableButton) control).translate();
1264
            }
1265
            String actionlName = control.getName();
1266
            ActionInfo action = actionManager.getAction(actionlName);
1267
            if ( action != null ) {
1268
                if ( control instanceof AbstractButton ) {
1269
                    AbstractButton button = (AbstractButton) control;
1270
                    if ( control instanceof javax.swing.JMenuItem ) {
1271
                        if ( action.getIconName() != null && action.getIconName().length() > 0 ) {
1272
                            if ( icontheme.exists(action.getIconName()) ) {
1273
                                button.setIcon(action.getIcon());
1274
                            }
1275
                        }
1276
                    } else {
1277
                        button.setIcon(action.getIcon());
1278
                    }
1279
                }
1280
            }
1281
        }
1282
        enableControls();
1283
    }
1284

    
1285
    public void message(String msg, int messageTyoe) {
1286
        this.getStatusBar().message(msg, messageTyoe);
1287
    }
1288

    
1289
    /**
1290
     * Establece la visibilidad de un menu y todos sus descendientes en la
1291
     * jerarquia teniendo en cuenta la visibilidad de todos los submenus.
1292
     *
1293
     * @param menu
1294
     * Menu que se quiere visualizar
1295
     *
1296
     * @return Devuelve true si el menu es visible y false en caso contrario
1297
     */
1298
    private boolean hideMenus(MenuElement menu) {
1299
        MenuElement[] submenus = menu.getSubElements();
1300

    
1301
        // Si no tiene hijos se devuelve su visibilidad
1302
        if ( submenus.length == 0 ) {
1303
            return menu.getComponent().isVisible();
1304
        }
1305

    
1306
        /*
1307
         * Si tiene hijos se devuelve true si alg?no de ellos es visible,
1308
         * pero se itera por todos ellos
1309
         */
1310
        boolean visible = false;
1311

    
1312
        for ( int i = 0; i < submenus.length; i++ ) {
1313
            if ( hideMenus(submenus[i]) ) {
1314
                if ( !(menu instanceof JPopupMenu) ) {
1315
                    menu.getComponent().setVisible(true);
1316
                }
1317

    
1318
                visible = true;
1319
            }
1320
        }
1321

    
1322
        if ( visible ) {
1323
            return true;
1324
        }
1325

    
1326
        menu.getComponent().setVisible(false);
1327

    
1328
        return false;
1329
    }
1330

    
1331
    /**
1332
     *
1333
     * Recurse through all menu elements and make sure there are no
1334
     * redundant separators.
1335
     * This method will make sure that a separator only becomes visible
1336
     * if at least one visible non-separator menu entry preceeded it.
1337
     *
1338
     *
1339
     */
1340
    private void hideSeparatorsAndMakeMnemonics(MenuElement menu,
1341
            char[] mnemonics) {
1342
        // flag that indicates whether a separator is to be displayed or not
1343
        boolean allowSeparator;
1344

    
1345
        allowSeparator = false; // separator not allowed as very first menu item
1346
        Component[] comps = ((JMenu) menu).getMenuComponents();
1347
        if ( comps.length < 1 ) {
1348
            // zero-length menu: skip
1349
            return;
1350
        }
1351

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

    
1416
    /**
1417
     * Helper functios for assigning a unique mnemomic char from
1418
     * a pool of unassigned onces, stored in the array "mnemomnics"
1419
     */
1420
    private char getMnemonic(String text, char[] mnemonics) {
1421
        Vector words = new Vector();
1422
        StringTokenizer t = new StringTokenizer(text);
1423
        int maxsize = 0;
1424

    
1425
        while ( t.hasMoreTokens() ) {
1426
            String word = t.nextToken();
1427
            if ( word.length() > maxsize ) {
1428
                maxsize = word.length();
1429
            }
1430
            words.addElement(word);
1431
        }
1432
        words.trimToSize();
1433

    
1434
        for ( int i = 0; i < maxsize; ++i ) {
1435
            char mnemonic = getMnemonic(words, mnemonics, i);
1436
            if ( ' ' != mnemonic ) {
1437
                return mnemonic;
1438
            }
1439
        }
1440

    
1441
        return ' ';
1442
    }
1443

    
1444
    private char getMnemonic(Vector words, char[] mnemonics, int index) {
1445
        int numwords = words.size();
1446

    
1447
        for ( int i = 0; i < numwords; ++i ) {
1448
            String word = (String) words.elementAt(i);
1449
            if ( index >= word.length() ) {
1450
                continue;
1451
            }
1452

    
1453
            char c = word.charAt(index);
1454
            if ( !isMnemonicExists(c, mnemonics) ) {
1455
                /* pick only valid chars */
1456
                if ( (c != ':') && (c != '.') && (c != ',') && (c != ';')
1457
                        && (c != '-') && (c != '+') && (c != '/') && (c != '\\')
1458
                        && (c != '\'') && (c != '\"') && (c != ' ') && (c != '=')
1459
                        && (c != '(') && (c != ')') && (c != '[') && (c != ']')
1460
                        && (c != '{') && (c != '}') && (c != '$') && (c != '*')
1461
                        && (c != '&') && (c != '%') && (c != '!') && (c != '?')
1462
                        && (c != '#') && (c != '~') && (c != '_') ) {
1463
                    return c;
1464
                }
1465
            }
1466
        }
1467
        return ' ';
1468
    }
1469

    
1470
    private boolean isMnemonicExists(char c, char[] mnemonics) {
1471
        int num = mnemonics.length;
1472
        for ( int i = 0; i < num; ++i ) {
1473
            if ( mnemonics[i] == c ) {
1474
                return true;
1475
            }
1476
        }
1477
        return false;
1478
    }
1479

    
1480
    /**
1481
     * Muestra la memoria consumida por el programa
1482
     */
1483
    private void showMemory() {
1484
        Runtime r = Runtime.getRuntime();
1485
        long mem = r.totalMemory() - r.freeMemory();
1486
        logger.debug(PluginServices.getText(this, "memory_usage") + " " + mem
1487
                / 1024 + " KB");
1488
    }
1489

    
1490
    public MDIManager getMDIManager() {
1491
        return mdiManager;
1492
    }
1493

    
1494
    public NewStatusBar getStatusBar() {
1495
        return bEstado;
1496
    }
1497

    
1498
    /**
1499
     * You can use this function to select the appropiate
1500
     * tool inside the toolbars
1501
     */
1502
    public void setSelectedTool(String actionCommand) {
1503
        setSelectedTool(defaultGroup, actionCommand);
1504
    }
1505

    
1506
    /**
1507
     * You can use this function to select the appropiate
1508
     * tool inside the toolbars
1509
     */
1510
    public void setSelectedTool(String groupName, String actionCommand) {
1511
        ButtonGroup group = (ButtonGroup) buttonGroupMap.get(groupName);
1512
        if ( group == null ) {
1513
            return;
1514
        }
1515

    
1516
        Enumeration enumeration = group.getElements();
1517
        while ( enumeration.hasMoreElements() ) {
1518
            AbstractButton button = (AbstractButton) enumeration.nextElement();
1519
            if ( button.getActionCommand().equals(actionCommand) ) {
1520
                button.setSelected(true);
1521
            }
1522
        }
1523

    
1524
        selectedTool.put(groupName, actionCommand);
1525
    }
1526

    
1527
    /**
1528
     * You can use this function to select the appropiate
1529
     * tool inside the toolbars
1530
     */
1531
    public void setSelectedTools(Map selectedTools) {
1532
        selectedTool = selectedTools;
1533
        if ( selectedTools == null ) {
1534
            return;
1535
        }
1536
        Iterator groupNames = selectedTools.keySet().iterator();
1537
        while ( groupNames.hasNext() ) {
1538
            try {
1539
                String groupName = (String) groupNames.next();
1540
                ButtonGroup group = (ButtonGroup) buttonGroupMap.get(groupName);
1541
                Enumeration enumeration = group.getElements();
1542
                String actionCommand = (String) selectedTools.get(groupName);
1543
                if ( actionCommand == null ) {
1544
                    continue;
1545
                }
1546
                while ( enumeration.hasMoreElements() ) {
1547
                    AbstractButton button
1548
                            = (AbstractButton) enumeration.nextElement();
1549
                    if ( button.getActionCommand().equals(actionCommand) ) {
1550
                        button.setSelected(true);
1551
                    }
1552
                }
1553
            } catch (ClassCastException ex) {
1554
                logger
1555
                        .error("selectedTool should only contain pairs (String groupName, JToolBarToggleButton button)");
1556
            }
1557
        }
1558
    }
1559

    
1560
    /**
1561
     * DOCUMENT ME!
1562
     *
1563
     * @param clase
1564
     * @param label
1565
     */
1566
    public void setStatusBarLabels(Class<?> clase, Label[] label) {
1567
        classLabels.put(clase, label);
1568
    }
1569

    
1570
    public void removeStatusBarLabels(Class<?> clase) {
1571
        classLabels.remove(clase);
1572
    }
1573

    
1574
    public void addStatusBarControl(Class<?> extensionClass, IControl control) {
1575
        control.addActionListener(this);
1576
        bEstado.addControl(control.getName(), (Component) control);
1577
        if ( control instanceof JComponent ) {
1578
            addControl((JComponent) control);
1579
        }
1580
    }
1581

    
1582
    public void addToolBarControl(Class<?> extensionClass, JToolBar control, String name) {
1583
        toolBars.add(control);
1584
        addControl(control);
1585
    }
1586

    
1587
    public void removeStatusBarControl(String name) {
1588
        Component c = bEstado.removeControl(name);
1589
        if ( c instanceof JComponent ) {
1590
            removeControl((JComponent) c);
1591
        }
1592
    }
1593

    
1594
    public void removeMenu(Menu menu) {
1595
        JMenuItem delete = (JMenuItem) infoCodedMenus.get(menu);
1596

    
1597
        if ( delete == null ) {
1598
            throw new NoSuchElementException(menu.getText());
1599
        }
1600

    
1601
        delete.getParent().remove(delete);
1602
        infoCodedMenus.remove(menu);
1603
    }
1604

    
1605
    public void addMenu(Menu menu, ActionListener listener,
1606
            PluginClassLoader loader) {
1607
        JMenu menuPadre = createMenuAncestors(menu, loader);
1608

    
1609
        // Se registra y a?aade el menu
1610
        JMenuItem nuevoMenu = createJMenuItem(loader, menu);
1611
        nuevoMenu.addMouseListener(tooltipListener);
1612
        if ( listener != null && menu.getName() != null && menu.getName().trim().length() > 0 ) {
1613
            ActionInfoManager actionManager = PluginsLocator.getActionInfoManager();
1614
            final ActionInfo actionInfo = actionManager.getAction(menu.getName());
1615
            if ( actionInfo != null ) {
1616
                nuevoMenu.removeActionListener(actionInfo);
1617
            }
1618
            nuevoMenu.addActionListener(listener);
1619
        } else {
1620
            /*
1621
             * We also add action listener for menu with
1622
             * no name but with text:
1623
             * 
1624
             * Window/Project manager
1625
             * Window/View - 1
1626
             * Window/View - 2
1627
             * etc
1628
             */
1629
            if ( listener != null && menu.getText() != null && menu.getText().trim().length() > 0 ) {
1630
                nuevoMenu.addActionListener(listener);
1631
            }
1632

    
1633
        }
1634
        menuPadre.add(nuevoMenu);
1635

    
1636
        infoCodedMenus.put(menu, nuevoMenu);
1637
    }
1638

    
1639
    public void changeMenuName(String[] menu, String newName,
1640
            PluginClassLoader loader) {
1641

    
1642
        ArrayList menuList = new ArrayList();
1643
        for ( int i = 0; i < menu.length; i++ ) {
1644
            menuList.add(menu[i]);
1645
        }
1646

    
1647
        javax.swing.JMenuItem newMenu = getMenu(menuList, menuBar);
1648
        if ( newMenu == null ) {
1649
            throw new NoSuchMenuException(menu[0]);
1650
        } else {
1651
            newMenu.setText(PluginServices.getText(this, newName));
1652
        }
1653
    }
1654

    
1655
    public void componentHidden(ComponentEvent arg0) {
1656
    }
1657

    
1658
    public void componentMoved(ComponentEvent arg0) {
1659
    }
1660

    
1661
    public void componentResized(ComponentEvent arg0) {
1662
        ajustarToolBar();
1663
    }
1664

    
1665
    public void componentShown(ComponentEvent arg0) {
1666
    }
1667

    
1668
    public void componentAdded(ContainerEvent arg0) {
1669
        ajustarToolBar();
1670
    }
1671

    
1672
    public void componentRemoved(ContainerEvent arg0) {
1673
        ajustarToolBar();
1674
    }
1675

    
1676
    public class TooltipListener extends MouseAdapter {
1677

    
1678
        @Override
1679
        public void mouseEntered(MouseEvent e) {
1680
            JComponent control = (JComponent) e.getSource();
1681
            EnableTextSupport ets = (EnableTextSupport) e.getSource();
1682

    
1683
            String texto = null;
1684
            texto = control.getToolTipText();
1685

    
1686
            if ( texto != null ) {
1687
                bEstado.setInfoTextTemporal(texto);
1688
            }
1689
        }
1690

    
1691
        @Override
1692
        public void mouseExited(MouseEvent arg0) {
1693
            bEstado.restaurarTexto();
1694
        }
1695

    
1696
        @Override
1697
        public void mousePressed(MouseEvent e) {
1698
            bEstado.restaurarTexto();
1699
        }
1700
    }
1701

    
1702
    public String getTitlePrefix() {
1703
        return titlePrefix;
1704
    }
1705

    
1706
    public void setTitlePrefix(String titlePrefix) {
1707
        this.titlePrefix = titlePrefix;
1708
    }
1709

    
1710
    public Map getSelectedTools() {
1711
        return selectedTool;
1712
    }
1713

    
1714
    public HashMap getInitialSelectedTools() {
1715
        return initialSelectedTools;
1716
    }
1717

    
1718
    /**
1719
     * Get a previously added JComponent by name.
1720
     * For example you can use it if you need to obtain a JToolBar to
1721
     * add some customized component.
1722
     *
1723
     * @param name
1724
     * @return the JComponent or null if none has been found
1725
     */
1726
    public JComponent getComponentByName(String name) {
1727
        Iterator e = controlsIterator();
1728

    
1729
        while ( e.hasNext() ) {
1730
            JComponent control = (JComponent) e.next();
1731
            String nameCtrl = control.getName();
1732
            if ( nameCtrl != null ) {
1733
                if ( nameCtrl.compareTo(name) == 0 ) {
1734
                    return control;
1735
                }
1736
            }
1737
        }
1738
        Iterator it = toolBarMap.values().iterator();
1739
        while ( it.hasNext() ) {
1740
            JComponent t = (JComponent) it.next();
1741
            String nameCtrl = t.getName();
1742
            if ( nameCtrl != null ) {
1743
                if ( nameCtrl.compareTo(name) == 0 ) {
1744
                    return t;
1745
                }
1746
            }
1747

    
1748
        }
1749

    
1750
        return null;
1751
    }
1752

    
1753
    public SelectableToolBar[] getToolbars() {
1754
        return (SelectableToolBar[]) toolBarMap.values().toArray(
1755
                new SelectableToolBar[0]);
1756
    }
1757

    
1758
    public boolean getToolbarVisibility(String name) {
1759
        JComponent component
1760
                = PluginServices.getMainFrame().getComponentByName(name);
1761
        if ( (component != null) && (component instanceof SelectableToolBar) ) {
1762
            SelectableToolBar toolBar = (SelectableToolBar) component;
1763
            return toolBar.getAndamiVisibility();
1764
        }
1765
        return false;
1766
    }
1767

    
1768
    public boolean setToolbarVisibility(String name, boolean visibility) {
1769
        JComponent component
1770
                = PluginServices.getMainFrame().getComponentByName(name);
1771
        if ( (component != null) && (component instanceof SelectableToolBar) ) {
1772
            SelectableToolBar toolBar = (SelectableToolBar) component;
1773
            boolean oldVisibility = toolBar.getAndamiVisibility();
1774
            toolBar.setAndamiVisibility(visibility);
1775
            enableControls();
1776
            return oldVisibility;
1777
        }
1778
        return false;
1779
    }
1780

    
1781
    public javax.swing.JMenuItem getMenuEntry(String[] menuPath) {
1782
        ArrayList menu = new ArrayList();
1783
        for ( int i = 0; i < menuPath.length; i++ ) {
1784
            menu.add(menuPath[i]);
1785
        }
1786
        return getMenu(menu, menuBar);
1787
    }
1788

    
1789
    public void messageDialog(String message, String title, int messageType) {
1790
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1791
        helper.messageDialog(message, title, messageType);
1792
    }
1793

    
1794
    public void messageDialog(String message, String[] messageArgs,
1795
            String title, int messageType) {
1796
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1797
        helper.messageDialog(message, messageArgs, title, messageType);
1798
    }
1799

    
1800
    public int confirmDialog(String message, String title, int optionType,
1801
            int messageType) {
1802
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1803
        return helper.confirmDialog(message, title, optionType, messageType);
1804
    }
1805

    
1806
    public String inputDialog(String message, String title, int messageType,
1807
            String initialValue) {
1808
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1809
        return helper.inputDialog(message, title, messageType, initialValue);
1810
    }
1811

    
1812
    public String inputDialog(String message, String title) {
1813
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1814
        return helper.inputDialog(message, title);
1815
    }
1816

    
1817
    public void showDialog(Component contents, String title) {
1818
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1819
        helper.showDialog(contents, title);
1820
    }
1821

    
1822
    public Component createComponent(Class<? extends Component> theClass,
1823
            Object... parameters) {
1824
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1825
        return helper.createComponentWithParams(theClass, parameters);
1826
    }
1827

    
1828
    public Component createComponentWithParams(
1829
            Class<? extends Component> theClass, Object[] parameters) {
1830
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1831
        return helper.createComponentWithParams(theClass, parameters);
1832
    }
1833

    
1834
    public File[] showChooserDialog(
1835
            final String title,
1836
            final int type, // SAVE_DIALOG / OPEN_DIALOG
1837
            final int selectionMode, //    JFileChooser.FILES_ONLY, JFileChooser.DIRECTORIES_ONLY, JFileChooser.FILES_AND_DIRECTORIES
1838
            final boolean multiselection,
1839
            final File initialPath,
1840
            final FileFilter filter,
1841
            final boolean fileHidingEnabled
1842
    ) {
1843
        DefaultThreadSafeDialogs helper = new DefaultThreadSafeDialogs(this, this.bEstado);
1844
        return helper.showChooserDialog(title, type, selectionMode, multiselection, initialPath, filter, fileHidingEnabled);
1845
    }
1846

    
1847
    public File[] showOpenDirectoryDialog(String title, File initialPath) {
1848
        return showChooserDialog(title, JFileChooser.OPEN_DIALOG, JFileChooser.DIRECTORIES_ONLY, false, initialPath, null, false);
1849
    }
1850

    
1851
    public File[] showOpenFileDialog(String title, File initialPath) {
1852
        return showChooserDialog(title, JFileChooser.OPEN_DIALOG, JFileChooser.FILES_ONLY, false, initialPath, null, false);
1853
    }
1854

    
1855
    public File[] showSaveFileDialog(String title, File initialPath) {
1856
        return showChooserDialog(title, JFileChooser.SAVE_DIALOG, JFileChooser.FILES_ONLY, false, initialPath, null, false);
1857
    }
1858

    
1859
    private void addControl(JComponent control) {
1860
        controls.add(control);
1861
    }
1862

    
1863
    private void removeControl(JComponent control) {
1864
        controls.remove(control);
1865
    }
1866

    
1867
    private Iterator<JComponent> controlsIterator() {
1868
        return this.controls.iterator();
1869
    }
1870

    
1871
    @Override
1872
    public void setLocale(Locale locale) {
1873
        super.setLocale(locale); //To change body of generated methods, choose Tools | Templates.
1874
        MDIManager mdiManager = MDIManagerFactory.createManager();
1875
        mdiManager.setLocale(locale);
1876
        if ( this.controls != null && !this.controls.isEmpty() ) {
1877
            this.refreshControls();
1878
        }
1879
    }
1880

    
1881
}