bogdanrechi.lansator.MainWindow.java Source code

Java tutorial

Introduction

Here is the source code for bogdanrechi.lansator.MainWindow.java

Source

/*
 * The MIT License (MIT)
 * 
 * Copyright (c) 2015 Bogdan Rechi
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

package bogdanrechi.lansator;

import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MenuDetectEvent;
import org.eclipse.swt.events.MenuDetectListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.TrayItem;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;

import bogdanrechi.commons.About;
import bogdanrechi.commons.Exec;
import bogdanrechi.commons.Localization;
import bogdanrechi.commons.Platform;
import bogdanrechi.commons.Property;
import bogdanrechi.commons.Run;
import bogdanrechi.commons.SingleInstance;
import bogdanrechi.commons.exceptions.StringException;
import bogdanrechi.commons.file.FileContent;
import bogdanrechi.commons.file.Files;
import bogdanrechi.commons.text.Text;
import bogdanrechi.lansator.properties.Configuration;
import bogdanrechi.lansator.properties.Item;
import bogdanrechi.lansator.properties.ProgramItem;
import bogdanrechi.lansator.properties.ProgramsGroupItem;
import bogdanrechi.lansator.resources.LansatorResources;
import bogdanrechi.swt.commons.SwtMessageBox;
import bogdanrechi.swt.commons.SwtPlatform;
import bogdanrechi.swt.commons.SwtPoints;
import bogdanrechi.swt.commons.SwtResourceManager;
import bogdanrechi.swt.commons.SwtShell;
import bogdanrechi.swt.commons.dialogs.AboutBox;

/**
 * Applications launcher
 *
 * @author Bogdan Rechi
 */
public final class MainWindow extends Shell {
    private static final String ERROR_CANNOT_CREATE_SINGLE_INSTANCE_OBJECT = "Cannot create single instance object";

    /**
     * Single instance port
     */
    private static final int SINGLE_INSTANCE_PORT = 50123;

    /**
     * Single instance handshake
     */
    private static final String SINGLE_INSTANCE_HANDSHAKE = "6ad8a44a-0f48-4d75-9734-96f6a62e1ec7";

    /**
     * Big ampersand, workaround for group names. The double & does not work
     */
    private static final String BIG_AMPERSAND = "";

    /**
     * Item images folder
     */
    private static final String IMAGES_PATH = Platform.CURRENT_DIRECTORY + "images" + Platform.FILE_SEPARATOR;

    /**
     * Last path used for loading
     */
    public String LastLoadingPath = IMAGES_PATH;

    public static int ImagesMaximumDimension = 32;

    // localizations
    private Localization _localizedControls;
    private Localization _localizedMessages;

    /**
     * Application language
     */
    private String _language = Platform.SYSTEM_LANGUAGE;

    /**
     * Resource manager
     */
    private SwtResourceManager _swtResourceManager;

    /**
     * Application log4j log
     */
    private Logger _log;

    /**
     * Application main image
     */
    private Image _mainImage;

    private Gson _gson;

    /**
     * Application configuration
     */
    private Configuration _config;

    /**
     * Tray menu images
     */
    private Image _showImage;
    private Image _aboutImage;
    private Image _terminalImage;
    private Image _centerOnScreenImage;
    private Image _saveConfigurationImage;
    private Image _exitImage;

    /**
     * Default image path
     */
    private String _defaultImagePath = LansatorResources.RESOURCES_ICONS_PATH + "running big.png";

    /**
     * Default image path
     */
    private Image _defaultImage;

    /**
     * Allow explicit exit
     */
    private boolean _doExit = false;

    /**
     * Signals an ongoing operation (against, for example, the hiding of the main window)
     */
    private boolean _ongoingOperation = false;

    private int _lastSelectedGroup = -1;

    // region

    private Display _display;

    private static MainWindow _mainWindow;

    // region

    private TabFolder _tabFolder;

    /**
     * Tray menu
     */
    private Menu menuTray;

    /**
     * @wbp.nonvisual location=73,509
     */
    private TrayItem _trayMain;

    /**
     * Launch the application
     *
     * @param args
     *          Program arguments
     */
    public static void main(String[] args) {
        Platform.validateCurrentJavaVersion("1.9");
        SwtPlatform.validateCurrentSwtVersion(4763);

        Run.DEBUG_ACTIVE = System.getenv("LANSATOR_DEBUG") != null;

        SingleInstance.ReceiveMessageDelegate receiveMessageDelegate = new SingleInstance.ReceiveMessageDelegate() {
            @Override
            public void receiveMessage(String message) {
                _mainWindow.showMainWindow();
            }
        };

        SingleInstance singleInstance = null;

        try {
            singleInstance = SingleInstance.request(SINGLE_INSTANCE_PORT, SINGLE_INSTANCE_HANDSHAKE,
                    receiveMessageDelegate);
        } catch (StringException e2) {
            _mainWindow._log.fatal(ERROR_CANNOT_CREATE_SINGLE_INSTANCE_OBJECT);
            SwtMessageBox.messageBoxError(_mainWindow._localizedMessages.get("CRITICAL_APPLICATION_ERROR"));

            return;
        }

        if (singleInstance == null) {
            return;
        }

        _mainWindow = new MainWindow(Display.getDefault());

        _mainWindow._trayMain = new TrayItem(_mainWindow._display.getSystemTray(), SWT.NONE);

        try {
            _mainWindow._log = LogManager.getLogger(MainWindow.class);

            if (args.length == 1) {
                _mainWindow._language = args[0];
            }

            _mainWindow
                    .setLocalizedMessages(new Localization(_mainWindow._language, LansatorResources.MESSAGES_JSON));
            _mainWindow
                    .setLocalizedControls(new Localization(_mainWindow._language, LansatorResources.CONTROLS_JSON));

            _mainWindow.loadConfiguration();

            _mainWindow.setDefaultImage(_mainWindow._swtResourceManager.loadResourceImage(MainWindow.class,
                    _mainWindow._defaultImagePath));

            _mainWindow.createContents();

            _mainWindow.setup();

            _mainWindow.setVisible(false);
            _mainWindow.setInitialSize();

            while (!_mainWindow.isDisposed()) {
                if (!_mainWindow._display.readAndDispatch()) {
                    _mainWindow._display.sleep();
                }
            }
        } catch (Throwable e) {
            _mainWindow._log.fatal(Run.getExceptionStackTrace(e));
            _mainWindow.displayFatalErrorAndExit("CRITICAL_APPLICATION_ERROR");
        } finally {
            _mainWindow._trayMain.dispose();

            try {
                singleInstance.closeInstance();
            } catch (StringException e) {
                _mainWindow._log.fatal(Run.getExceptionStackTrace(e));
            }
        }
    }

    /**
     * Create the shell
     */
    private MainWindow(Display display) {
        super(display, SWT.CLOSE | SWT.RESIZE | SWT.TITLE);

        _display = display;

        _swtResourceManager = SwtResourceManager.getDisplayManager();

        SwtShell.CurrentApplicationShell = this;
    }

    /**
     * Create contents of the shell
     */
    protected void createContents() {
        setMinimumSize(new Point(200, 100));

        addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent arg0) {
                if (arg0.keyCode == SWT.ESC) {
                    _mainWindow.setVisible(false);
                }
            }
        });

        addShellListener(new ShellAdapter() {
            @Override
            public void shellClosed(ShellEvent arg0) {
                if (!_doExit) {
                    arg0.doit = false;

                    _mainWindow.setVisible(false);
                } else {
                    _mainWindow.saveLastBounds();

                    SwtResourceManager.disposeAll();
                }
            }
        });
        addTraverseListener(new TraverseListener() {
            @Override
            public void keyTraversed(TraverseEvent arg0) {
                if (arg0.keyCode == SWT.ESC) {
                    _mainWindow.setVisible(false);
                }
            }
        });

        this.setImages(new Image[] {
                _mainImage = _swtResourceManager.loadResourceImage(MainWindow.class,
                        LansatorResources.RESOURCES_ICONS_PATH + "running.png"),
                _swtResourceManager.loadResourceImage(MainWindow.class,
                        LansatorResources.RESOURCES_ICONS_PATH + "running big.png") });

        setText(getLocalizedControls().get("AppTitle"));
        setSize(523, 373);

        _trayMain.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                showMainWindow();
            }
        });

        _trayMain.addMenuDetectListener(new MenuDetectListener() {
            @Override
            public void menuDetected(MenuDetectEvent arg0) {
                menuTray.setVisible(true);
            }
        });
        _trayMain.setText("Lansator");
        _trayMain.setToolTipText("Lansator / " + About.getVersionText(LansatorResources.METADATA_JSON));
        _trayMain.setImage(_mainImage);

        createTrayMenu();

        addControlListener(new ControlAdapter() {
            @Override
            public void controlResized(ControlEvent arg0) {
                onResize();
            }
        });
    }

    /**
     * Set initial window size
     */
    private void setInitialSize() {
        setSize(_config.width, _config.height);

        if (_config.left != -1 && _config.top != -1) {
            setLocation(_config.left, _config.top);
        } else {
            centerOnScreen();
        }
    }

    /**
     * Save last window bounds
     */
    private void saveLastBounds() {
        Point size = getSize();

        _config.width = size.x;
        _config.height = size.y;

        Point location = getLocation();

        _config.top = location.y;
        _config.left = location.x;

        saveConfiguration();
    }

    /**
     * Create tray menu
     */
    private void createTrayMenu() {
        _showImage = _swtResourceManager.loadResourceImage(MainWindow.class,
                LansatorResources.RESOURCES_ICONS_PATH + "show.png");
        _terminalImage = _swtResourceManager.loadResourceImage(MainWindow.class,
                LansatorResources.RESOURCES_ICONS_PATH + "terminal.png");
        _centerOnScreenImage = _swtResourceManager.loadResourceImage(MainWindow.class,
                LansatorResources.RESOURCES_ICONS_PATH + "center.png");
        _saveConfigurationImage = _swtResourceManager.loadResourceImage(MainWindow.class,
                LansatorResources.RESOURCES_ICONS_PATH + "save.png");
        _aboutImage = _swtResourceManager.loadResourceImage(MainWindow.class,
                LansatorResources.RESOURCES_ICONS_PATH + "about.png");
        _exitImage = _swtResourceManager.loadResourceImage(MainWindow.class,
                LansatorResources.RESOURCES_ICONS_PATH + "exit.png");

        menuTray = new Menu(this);
        setMenu(menuTray);

        MenuItem menuItem = new MenuItem(menuTray, SWT.NONE);
        menuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                showMainWindow();
            }
        });
        menuItem.setText(getLocalizedControls().get("Show"));
        menuItem.setImage(_showImage);

        menuItem = new MenuItem(menuTray, SWT.SEPARATOR);

        menuItem = new MenuItem(menuTray, SWT.NONE);
        menuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                _doExit = true;
                _mainWindow.close();
            }
        });
        menuItem.setText(getLocalizedControls().get("Exit"));
        menuItem.setImage(_exitImage);
    }

    /**
     * Get the current groups
     *
     * @return An array of the current group names
     */
    protected String[] getGroupNames() {
        int count = _tabFolder.getItemCount();
        String[] groups = new String[count];

        for (int i = 0; i < count; i++) {
            groups[i] = ((ProgramsGroupItem) _tabFolder.getItem(i).getData()).name;
        }

        return groups;
    }

    /**
     * Setup application
     */
    private void setup() {
        if (_tabFolder != null) {
            _tabFolder.dispose();
            _tabFolder = null;
        }

        _tabFolder = new TabFolder(this, SWT.FLAT | SWT.WRAP | SWT.RIGHT);
        _tabFolder.setBounds(0, 0, 0, 0);
        _tabFolder.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseDown(MouseEvent arg0) {
                switch (arg0.button) {
                case 3:
                    setupGroupMenu(arg0);
                    break;

                case 2:
                    _mainWindow.setVisible(false);
                    break;
                }
            }
        });

        _tabFolder.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent arg0) {
                if (Platform.SYSTEM_IS_WINDOWS) {
                    if (!_ongoingOperation) {
                        _mainWindow.setVisible(false);
                    }
                }
            }
        });

        for (ProgramsGroupItem groupItem : _config.programsGroups) {
            setupGroup(groupItem);
        }

        _tabFolder.forceFocus();

        setupLastSelectedGroup();
    }

    /**
     * Setup last selected group
     */
    private void setupLastSelectedGroup() {
        if (_mainWindow != null) {
            onResize();

            if (_lastSelectedGroup != -1) {
                if (_tabFolder.getItemCount() > 0) {
                    if (_tabFolder.getItemCount() > _lastSelectedGroup) {
                        _tabFolder.setSelection(_lastSelectedGroup);
                    } else {
                        _tabFolder.setSelection(_lastSelectedGroup = 0);
                    }
                } else {
                    _lastSelectedGroup = -1;
                }
            }
        }
    }

    /**
     * Setup group item
     * 
     * @param groupItem
     *          Group item to setup
     */
    private void setupGroup(ProgramsGroupItem groupItem) {
        TabItem group = new TabItem(_tabFolder, SWT.NONE);

        setupGroupImageAndText(groupItem, group);

        final ToolBar groupToolbar = new ToolBar(_tabFolder, SWT.FLAT | SWT.WRAP | SWT.RIGHT);

        group.setControl(groupToolbar);

        groupToolbar.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseDown(MouseEvent arg0) {
                switch (arg0.button) {
                case 3:
                    setupGroupProgramsMenus(groupItem, groupToolbar, arg0);
                    break;

                case 2:
                    _mainWindow.setVisible(false);
                    break;
                }
            }
        });

        setupGroupProgramsTextAndOnClick(groupItem, groupToolbar);
    }

    /**
     * Setup group programs text and OnClick events
     * 
     * @param groupItem
     *          Selected group
     * @param groupToolbar
     *          Selected group toolbar
     */
    private void setupGroupProgramsTextAndOnClick(ProgramsGroupItem groupItem, final ToolBar groupToolbar) {
        for (ProgramItem itemData : groupItem.programs) {
            ToolItem item = setupProgramText(groupToolbar, itemData);

            item.setData(itemData);

            item.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent arg0) {
                    _ongoingOperation = true;

                    boolean executedOk = execute(itemData, false);

                    _ongoingOperation = false;

                    if (executedOk && (arg0.stateMask & SWT.CONTROL) == 0) {
                        _mainWindow.setVisible(false);
                    }
                }
            });
        }
    }

    /**
     * Setup program text
     * 
     * @param groupToolbar
     *          Parent toolbar of program item
     * @param itemData
     *          Config program data
     * 
     * @return Toolbar item
     */
    private ToolItem setupProgramText(final ToolBar groupToolbar, ProgramItem itemData) {
        ToolItem item;
        if (itemData.isSeparator) {
            item = new ToolItem(groupToolbar, SWT.SEPARATOR_FILL);
            item.setText("  |  ");
        } else {
            boolean hasImage = itemData.imageFile.length() != 0;
            String itemName = itemData.name;
            if (itemData.asSuperuser) {
                itemName = "* " + itemName;
            }

            item = new ToolItem(groupToolbar, SWT.NONE);

            if (hasImage) {
                Image itemImage = _swtResourceManager.loadImageAtMaximumDimension(IMAGES_PATH + itemData.imageFile,
                        ImagesMaximumDimension);

                if (itemImage != null && !itemImage.isDisposed()) {
                    item.setImage(itemImage);
                } else {
                    item.setImage(getDefaultImage());
                }
            }

            if ((hasImage && itemData.isImageAndText) || !hasImage) {
                item.setText(itemName.replaceAll("&", "&&"));
            } else {
                item.setToolTipText(itemName);
            }
        }

        return item;
    }

    /**
     * Setup group programs menus
     * 
     * @param groupItem
     *          Selected group
     * @param groupToolbar
     *          Group toolbar
     * @param arg0
     *          Mouse event
     */
    private void setupGroupProgramsMenus(ProgramsGroupItem groupItem, final ToolBar groupToolbar, MouseEvent arg0) {
        boolean hasItemsAbove = false;

        Menu popMenu = new Menu(groupToolbar);
        ProgramItem currentItemData = null;

        for (int i = 0; i < groupToolbar.getItemCount(); i++) {
            ToolItem ti = groupToolbar.getItem(i);

            if (SwtPoints.pointInRectangle(arg0.x, arg0.y, ti.getBounds())) {
                final ProgramItem itemData = (ProgramItem) ti.getData();
                currentItemData = itemData;

                _lastSelectedGroup = _tabFolder.getSelectionIndex();

                addProgramUpdateMenuItem(popMenu, itemData);

                addProgramDuplicateMenuItem(groupItem, popMenu, itemData);

                addProgramRemoveMenuItem(groupItem, popMenu, itemData);

                addProgramExecAsSuperuserMenuItem(popMenu, itemData);

                hasItemsAbove = true;

                break;
            }
        }

        addCommonMenuItems(currentItemData, false, hasItemsAbove, popMenu);

        popMenu.setVisible(true);
    }

    /**
     * Add program "exec as superuser" menu item
     * 
     * @param popMenu
     *          Menu to add the item to
     * @param itemData
     *          Config data of the program
     */
    private void addProgramExecAsSuperuserMenuItem(Menu popMenu, final ProgramItem itemData) {
        if (Platform.SYSTEM_IS_LINUX) {
            if (!itemData.asSuperuser) {
                MenuItem popMenuItem = new MenuItem(popMenu, SWT.SEPARATOR);

                popMenuItem = new MenuItem(popMenu, SWT.NONE);
                popMenuItem.setText(getLocalizedControls().get("ExecuteAsSuperuser"));
                popMenuItem.setImage(_terminalImage);
                popMenuItem.addSelectionListener(new SelectionAdapter() {
                    @Override
                    public void widgetSelected(SelectionEvent arg0) {
                        _ongoingOperation = true;

                        boolean executedOk = execute(itemData, true);

                        _ongoingOperation = false;

                        if (executedOk && (arg0.stateMask & SWT.CONTROL) == 0) {
                            _mainWindow.setVisible(false);
                        }
                    }
                });
            }
        }
    }

    /**
     * Add program "remove" menu item
     * 
     * @param groupItem
     *          Group containing program
     * @param popMenu
     *          Menu to add the item to
     * @param itemData
     *          Config data of the program
     */
    private void addProgramRemoveMenuItem(ProgramsGroupItem groupItem, Menu popMenu, final ProgramItem itemData) {
        MenuItem popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("Remove"));
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                _ongoingOperation = true;

                int response;

                if (itemData.isSeparator) {
                    response = SwtMessageBox.messageBox(getLocalizedMessages().get("CONFIRM_REMOVE_SEPARATOR"),
                            SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL);
                } else {
                    response = SwtMessageBox.messageBox(
                            String.format(getLocalizedMessages().get("CONFIRM_REMOVE_ITEM"), itemData.name),
                            SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL);
                }

                if (response == SWT.OK) {
                    removeItem(groupItem, itemData);

                    _lastSelectedGroup = _tabFolder.getSelectionIndex();

                    setup();
                }

                _ongoingOperation = false;
            }
        });
    }

    /**
     * Add program "duplicate" menu item
     * 
     * @param groupItem
     *          Group containing program
     * @param popMenu
     *          Menu to add the item to
     * @param itemData
     *          Config data of the program
     */
    private void addProgramDuplicateMenuItem(ProgramsGroupItem groupItem, Menu popMenu,
            final ProgramItem itemData) {
        MenuItem popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("Duplicate"));
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                _ongoingOperation = true;

                try {
                    duplicateProgramItem(groupItem, itemData);
                } catch (StringException e) {
                    _mainWindow.reportCriticalErrorAndTerminate(e);
                }

                _lastSelectedGroup = _tabFolder.getSelectionIndex();

                setup();

                _ongoingOperation = false;
            }
        });
    }

    /**
     * Add program "update" menu item
     * 
     * @param popMenu
     *          Program menu
     * @param itemData
     *          Config program data
     */
    private void addProgramUpdateMenuItem(Menu popMenu, final ProgramItem itemData) {
        MenuItem popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("Update"));
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                _ongoingOperation = true;

                AddUpdateProgram itemDlg = new AddUpdateProgram(_mainWindow, true);

                itemDlg.setDetails(itemData);
                itemDlg.setGroupNames(getGroupNames());
                itemDlg.setGroupIndex(_tabFolder.getSelectionIndex());

                if (itemDlg.open() == SWT.OK) {
                    updateItem(itemData, itemDlg.getDetails(), itemDlg.getGroupIndex());

                    _lastSelectedGroup = itemDlg.getGroupIndex();

                    setup();
                }

                _ongoingOperation = false;
            }
        });
    }

    /**
     * Setup group image and text
     * 
     * @param configGroupItem
     *          Config group item
     * @param group
     *          Group tab
     */
    private void setupGroupImageAndText(ProgramsGroupItem configGroupItem, TabItem group) {
        boolean hasImage = configGroupItem.imageFile.length() != 0;

        if (hasImage) {
            Image groupImage = _swtResourceManager
                    .loadImageAtMaximumDimension(IMAGES_PATH + configGroupItem.imageFile, ImagesMaximumDimension);

            if (groupImage != null && !groupImage.isDisposed()) {
                group.setImage(groupImage);
            } else {
                group.setImage(getDefaultImage());
            }
        }

        if ((hasImage && configGroupItem.isImageAndText) || !hasImage) {
            group.setText(configGroupItem.name.replaceAll("&", BIG_AMPERSAND));
        } else {
            group.setToolTipText(configGroupItem.name);
        }

        group.setData(configGroupItem);
    }

    /**
     * Setup group menu
     * 
     * @param arg0
     *          Right-click mouse event
     */
    private void setupGroupMenu(MouseEvent arg0) {
        boolean hasItemsAbove = false;

        ProgramsGroupItem currentGroupData = null;

        Menu popMenu = new Menu(_tabFolder);

        for (int i = 0; i < _tabFolder.getItemCount(); i++) {
            final TabItem ti = _tabFolder.getItem(i);

            if (SwtPoints.pointInRectangle(arg0.x, arg0.y, ti.getBounds())) {
                final ProgramsGroupItem groupData = (ProgramsGroupItem) ti.getData();
                currentGroupData = groupData;

                _tabFolder.setSelection(_lastSelectedGroup = i);

                addGroupUpdateMenuItem(popMenu, groupData);

                addGroupRemoveMenuItem(popMenu, groupData);

                hasItemsAbove = true;

                break;
            }
        }

        addCommonMenuItems(currentGroupData, true, hasItemsAbove, popMenu);

        popMenu.setVisible(true);
    }

    /**
     * Add common items to a popup menu
     *
     * @param programOrGroup
     *          The current program or group
     * @param isGroup
     *          true if a new group is added, otherwise false
     * @param hasItemsAbove
     *          true if there are items above, otherwise false
     * @param popMenu
     *          Popup menu to add the items to
     */
    private void addCommonMenuItems(final Item programOrGroup, final boolean isGroup, boolean hasItemsAbove,
            Menu popMenu) {
        if (hasItemsAbove) {
            new MenuItem(popMenu, SWT.SEPARATOR);
        }

        if (programOrGroup != null) {
            boolean canMove = false;

            if (canMoveItemBefore(programOrGroup)) {
                canMove = true;

                addCommonMoveLeftMenuItems(programOrGroup, isGroup, popMenu);
            }

            if (canMove) {
                new MenuItem(popMenu, SWT.SEPARATOR);
                canMove = false;
            }

            if (canMoveItemAfter(programOrGroup)) {
                canMove = true;

                addCommonMoveRightMenuItems(programOrGroup, isGroup, popMenu);
            }

            if (canMove) {
                new MenuItem(popMenu, SWT.SEPARATOR);
            }
        }

        addCommonAddGroupOrProgramMenuItem(programOrGroup, isGroup, popMenu);

        MenuItem popMenuItem = new MenuItem(popMenu, SWT.SEPARATOR);

        popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("CenterOnScreen"));
        popMenuItem.setImage(_centerOnScreenImage);
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                centerOnScreen();
            }
        });

        popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("SaveConfiguration"));
        popMenuItem.setImage(_saveConfigurationImage);
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                saveConfiguration();

                _ongoingOperation = true;

                SwtMessageBox.messageBox(getLocalizedMessages().get("CONFIGURATION_SAVED"));

                _ongoingOperation = false;
            }
        });

        popMenuItem = new MenuItem(popMenu, SWT.SEPARATOR);

        popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("About"));
        popMenuItem.setImage(_aboutImage);
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                showAbout();
            }
        });

        popMenuItem = new MenuItem(popMenu, SWT.SEPARATOR);

        popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("Exit"));
        popMenuItem.setImage(_exitImage);
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                _doExit = true;
                _mainWindow.close();
            }
        });
    }

    /**
     * Add common "add group" or "add program" menu item
     * 
     * @param programOrGroup
     *          Item being added the menu item
     * @param isGroup
     *          true if the item is group, otherwise false
     * @param popMenu
     *          Menu to add the item to
     */
    private void addCommonAddGroupOrProgramMenuItem(final Item programOrGroup, final boolean isGroup,
            Menu popMenu) {
        MenuItem popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get(isGroup ? "AddGroup" : "AddItem"));
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                _ongoingOperation = true;

                if (isGroup) {
                    AddUpdateGroup groupDlg = new AddUpdateGroup(_mainWindow, false);

                    if (groupDlg.open() == SWT.OK) {
                        addGroup((ProgramsGroupItem) programOrGroup, groupDlg.getDetails());

                        if (programOrGroup == null) {
                            _lastSelectedGroup = _tabFolder.getItemCount();
                        } else {
                            _lastSelectedGroup = getItemIndex(programOrGroup) - 2;
                        }

                        setup();
                    }
                } else // program
                {
                    AddUpdateProgram itemDlg = new AddUpdateProgram(_mainWindow, false);

                    itemDlg.setGroupNames(getGroupNames());
                    itemDlg.setGroupIndex(_tabFolder.getSelectionIndex());

                    if (itemDlg.open() == SWT.OK) {
                        addItem((ProgramItem) programOrGroup, itemDlg.getDetails(), itemDlg.getGroupIndex());

                        _lastSelectedGroup = itemDlg.getGroupIndex();

                        setup();
                    }
                }

                _ongoingOperation = false;
            }
        });
    }

    /**
     * Add common "move right" menu items
     * 
     * @param programOrGroup
     *          Item being added the menu items
     * @param isGroup
     *          true if the item is group, otherwise false
     * @param popMenu
     *          Menu to add the items to
     */
    private void addCommonMoveRightMenuItems(final Item programOrGroup, final boolean isGroup, Menu popMenu) {
        MenuItem popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("MoveRight"));
        popMenuItem.setImage(_swtResourceManager.loadResourceImage(MainWindow.class,
                LansatorResources.RESOURCES_ICONS_PATH + "right.png"));
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                onMoveItemAfter(programOrGroup, isGroup, 1);
            }
        });

        popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("MoveRight2"));
        popMenuItem.setImage(_swtResourceManager.loadResourceImage(MainWindow.class,
                LansatorResources.RESOURCES_ICONS_PATH + "right2.png"));
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                onMoveItemAfter(programOrGroup, isGroup, 2);
            }
        });
    }

    /**
     * Add common "move left" menu items
     * 
     * @param programOrGroup
     *          Item being added the menu items
     * @param isGroup
     *          true if the item is group, otherwise false
     * @param popMenu
     *          Menu to add the items to
     */
    private void addCommonMoveLeftMenuItems(final Item programOrGroup, final boolean isGroup, Menu popMenu) {
        MenuItem popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("MoveLeft"));
        popMenuItem.setImage(_swtResourceManager.loadResourceImage(MainWindow.class,
                LansatorResources.RESOURCES_ICONS_PATH + "left.png"));
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                onMoveItemBefore(programOrGroup, isGroup, 1);
            }
        });

        popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("MoveLeft2"));
        popMenuItem.setImage(_swtResourceManager.loadResourceImage(MainWindow.class,
                LansatorResources.RESOURCES_ICONS_PATH + "left2.png"));
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                onMoveItemBefore(programOrGroup, isGroup, 2);
            }
        });
    }

    /**
     * Add group update menu item
     * 
     * @param popMenu
     *          Group menu
     * @param groupData
     *          Config group data
     */
    private void addGroupUpdateMenuItem(Menu popMenu, final ProgramsGroupItem groupData) {
        MenuItem popMenuItem = new MenuItem(popMenu, SWT.NONE);
        popMenuItem.setText(getLocalizedControls().get("Update"));
        popMenuItem.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent arg0) {
                _ongoingOperation = true;

                AddUpdateGroup groupDlg = new AddUpdateGroup(_mainWindow, true);

                groupDlg.setDetails(groupData);

                if (groupDlg.open() == SWT.OK) {
                    saveConfiguration();

                    _lastSelectedGroup = _tabFolder.getSelectionIndex();

                    setup();
                }

                _ongoingOperation = false;
            }
        });
    }

    /**
     * Add group remove menu item
     * 
     * @param popMenu
     *          Group menu
     * @param groupData
     *          Config group data
     */
    private void addGroupRemoveMenuItem(Menu popMenu, final ProgramsGroupItem groupData) {
        MenuItem popMenuItem;
        // always at least one group in Linux
        if (Platform.SYSTEM_IS_WINDOWS || _tabFolder.getItemCount() > 1) {
            popMenuItem = new MenuItem(popMenu, SWT.NONE);
            popMenuItem.setText(getLocalizedControls().get("Remove"));
            popMenuItem.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent arg0) {
                    _ongoingOperation = true;

                    if (SwtMessageBox.messageBox(
                            String.format(getLocalizedMessages().get("CONFIRM_REMOVE_GROUP"), groupData.name),
                            SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL) == SWT.OK) {
                        removeGroup(groupData);

                        setup();
                    }

                    _ongoingOperation = false;
                }
            });
        }
    }

    /**
     * Show the About window
     */
    private void showAbout() {
        _ongoingOperation = true;

        AboutBox about = new AboutBox(_mainWindow, _language, LansatorResources.METADATA_JSON);
        about.open(true);

        _ongoingOperation = false;
    }

    @Override
    protected void checkSubclass() {
        // Disable the check that prevents subclassing of SWT components
    }

    /**
     * On resize main window
     */
    private void onResize() {
        if (_tabFolder != null) {
            Rectangle area = _mainWindow.getClientArea();
            _tabFolder.setSize(area.width, area.height);
        }
    }

    /**
     * Add new group
     *
     * @param beforeItem
     *          Item to add the group before
     * @param details
     *          Details of the added group
     */
    private void addGroup(ProgramsGroupItem beforeItem, Item details) {
        ProgramsGroupItem newGroupItem = new ProgramsGroupItem();

        newGroupItem.guid = details.guid;
        newGroupItem.name = details.name;
        newGroupItem.imageFile = details.imageFile;
        newGroupItem.isImageAndText = details.isImageAndText;

        addGroupItem(beforeItem, newGroupItem);

        saveConfiguration();
    }

    /**
     * Remove group
     *
     * @param groupItem
     *          Group item
     */
    private void removeGroup(ProgramsGroupItem groupItem) {
        _config.programsGroups.removeIf(item -> item.guid.equals(groupItem.guid));

        saveConfiguration();
    }

    /**
     * Add new item
     *
     * @param beforeItem
     *          Node to add the item before
     * @param newItem
     *          New item
     * @param groupIndex
     *          Group index
     */
    private void addItem(ProgramItem beforeItem, ProgramItem newItem, int groupIndex) {
        addProgramItem(_config.programsGroups.get(groupIndex), beforeItem, newItem);

        saveConfiguration();
    }

    /**
     * Update item
     *
     * @param oldItem
     *          Old item
     * @param updatedItem
     *          Updated item
     * @param groupIndex
     *          Group index
     */
    private void updateItem(ProgramItem oldItem, ProgramItem updatedItem, int groupIndex) {
        if (!updatedItem.isSeparator && groupIndex != _tabFolder.getSelectionIndex()) {
            ((ProgramsGroupItem) _tabFolder.getSelection()[0].getData()).programs
                    .removeIf(itm -> itm.guid.equals(oldItem.guid));
            ((ProgramsGroupItem) _tabFolder.getItem(groupIndex).getData()).programs.add(updatedItem);
        }

        saveConfiguration();
    }

    /**
     * Duplicate program item
     *
     * @param groupItem
     *          Group item to duplicate into
     * @param programItem
     *          Program item to duplicate
     */
    private void duplicateProgramItem(ProgramsGroupItem groupItem, ProgramItem programItem) throws StringException {
        groupItem.programs.add(getItemIndex(programItem), new ProgramItem(programItem));
    }

    /**
     * Remove item
     *
     * @param itemNode
     *          Node of the last selected item
     */
    private void removeItem(ProgramsGroupItem groupItem, ProgramItem itemNode) {
        groupItem.programs.removeIf(item -> item.guid.equals(itemNode.guid));

        saveConfiguration();
    }

    /**
     * Show main window
     */
    public void showMainWindow() {
        _display.asyncExec(new Runnable() {
            @Override
            public void run() {
                _mainWindow.setVisible(true);
                _mainWindow.setMinimized(false);
                _mainWindow.forceActive();

                if (Platform.SYSTEM_IS_LINUX) {
                    _tabFolder.forceFocus();
                }
            }
        });
    }

    /**
     * Center main window on screen and save the configuration
     */
    private void centerOnScreen() {
        SwtShell.centerShellOnScreen(_mainWindow, true);
        saveConfiguration();
    }

    /**
     * Execute program associated to item
     *
     * @param itemData
     *          Data of the item who's program is to be executed
     * @param asSuperuser
     *          true to execute as superuser, otherwise false
     *
     * @return true if successfully executed, otherwise false
     */
    private boolean execute(final ProgramItem itemData, boolean asSuperuser) {
        String path = itemData.path;
        if (path.length() == 0) {
            return false;
        }

        String parameters = itemData.parameters;
        String workingFolder = itemData.runInFolder;
        if (!asSuperuser) {
            asSuperuser = itemData.asSuperuser;
        }

        Property<Integer> errorCode = new Property<Integer>();
        Process executedProcess;
        if (asSuperuser) {
            executedProcess = Exec.executeAsSuperuser(path, parameters, workingFolder, errorCode);
        } else {
            executedProcess = Exec.execute(path, parameters, workingFolder, errorCode);
        }

        if (executedProcess == null) {
            if (errorCode.get() == 1) {
                SwtMessageBox.messageBoxError(getLocalizedMessages().get("ERROR_LAUNCHING_PARAMETERS"));
            } else {
                SwtMessageBox.messageBoxError(getLocalizedMessages().get("ERROR_LAUNCHING"));
            }
        }

        return executedProcess != null;
    }

    /**
     * Check if an item can be moved before its current position
     * 
     * @param item
     *          Item to check
     * 
     * @return true if movable, otherwise false
     */
    private boolean canMoveItemBefore(Item item) {
        for (int i = 0; i < _config.programsGroups.size(); i++) {
            if (item.guid.equals(_config.programsGroups.get(i).guid)) {
                return i != 0;
            } else if (_config.programsGroups.get(i).programs.size() != 0) {
                if (_config.programsGroups.get(i).programs.get(0).guid.equals(item.guid)) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Move item before its current position by a number of positions
     * 
     * @param item
     *          Item to be moved
     * 
     * @param positionsToMove
     *          Number of positions to move
     */
    private void moveItemBefore(Item item, int positionsToMove) {
        for (int i = 0; i < _config.programsGroups.size(); i++) {
            if (item.guid.equals(_config.programsGroups.get(i).guid)) {
                ProgramsGroupItem programsGroupItem = _config.programsGroups.remove(i);
                _config.programsGroups.add(Math.max(0, i - positionsToMove), programsGroupItem);

                break;
            } else {
                for (int j = 1; j < _config.programsGroups.get(i).programs.size(); j++) {
                    {
                        if (item.guid.equals(_config.programsGroups.get(i).programs.get(j).guid)) {
                            ProgramItem programItem = _config.programsGroups.get(i).programs.remove(j);
                            _config.programsGroups.get(i).programs.add(Math.max(0, j - positionsToMove),
                                    programItem);

                            break;
                        }
                    }
                }
            }
        }
    }

    /**
     * Check if an item can be moved after its current position
     * 
     * @param item
     *          Item to check
     * 
     * @return true if movable, otherwise false
     */
    private boolean canMoveItemAfter(Item item) {
        for (int i = _config.programsGroups.size() - 1; i >= 0; i--) {
            if (item.guid.equals(_config.programsGroups.get(i).guid)) {
                return i != _config.programsGroups.size() - 1;
            } else if (_config.programsGroups.get(i).programs.size() != 0) {
                if (_config.programsGroups.get(i).programs
                        .get(_config.programsGroups.get(i).programs.size() - 1).guid.equals(item.guid)) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Move item by a number of positions after its current position
     * 
     * @param item
     *          Item to be moved
     * @param positionsToMove
     *          Number of positions to move
     */
    private void moveItemAfter(Item item, int positionsToMove) {
        for (int i = 0; i < _config.programsGroups.size(); i++) {
            if (item.guid.equals(_config.programsGroups.get(i).guid)) {
                ProgramsGroupItem programsGroupItem = _config.programsGroups.remove(i);
                _config.programsGroups.add(Math.min(i + positionsToMove, _config.programsGroups.size()),
                        programsGroupItem);

                break;
            } else {
                for (int j = 0; j < _config.programsGroups.get(i).programs.size() - 1; j++) {
                    {
                        if (item.guid.equals(_config.programsGroups.get(i).programs.get(j).guid)) {
                            ProgramItem programItem = _config.programsGroups.get(i).programs.remove(j);
                            _config.programsGroups.get(i).programs.add(
                                    Math.min(j + positionsToMove, _config.programsGroups.get(i).programs.size()),
                                    programItem);

                            break;
                        }
                    }
                }
            }
        }
    }

    /**
     * Add item before another item
     * 
     * @param beforeItem
     *          Add before this item
     * @param newItem
     *          Item to add
     */
    private void addGroupItem(ProgramsGroupItem beforeItem, ProgramsGroupItem newItem) {
        if (beforeItem == null) {
            _config.programsGroups.add(newItem);
        } else {
            for (int i = 0; i < _config.programsGroups.size(); i++) {
                if (_config.programsGroups.get(i).guid.equals(beforeItem.guid)) {
                    _config.programsGroups.add(i, newItem);
                    break;
                }
            }
        }
    }

    /**
     * Add item before another item
     * 
     * @param groupItem
     *          Group item
     * @param beforeItem
     *          Add before this item
     * @param newItem
     *          Item to add
     */
    private void addProgramItem(ProgramsGroupItem groupItem, ProgramItem beforeItem, ProgramItem newItem) {
        if (beforeItem == null) {
            groupItem.programs.add(newItem);
        } else {
            for (int i = 0; i < groupItem.programs.size(); i++) {
                if (groupItem.programs.get(i).guid.equals(beforeItem.guid)) {
                    groupItem.programs.add(i, newItem);
                    break;
                }
            }
        }
    }

    /**
     * Get item index (starting with 1) with respect to its siblings
     * 
     * @param item
     *          Item to get the index for
     * 
     * @return Item index
     */
    private int getItemIndex(Item item) {
        for (int i = 0; i < _config.programsGroups.size(); i++) {
            if (item.guid.equals(_config.programsGroups.get(i).guid)) {
                return i + 1;
            } else {
                for (int j = 0; j < _config.programsGroups.get(i).programs.size(); j++) {
                    if (item.guid.equals(_config.programsGroups.get(i).programs.get(j).guid)) {
                        return j + 1;
                    }
                }
            }
        }

        return -1;
    }

    /**
     * Set item image file
     * 
     * @param newImageFile
     *          Newly selected image file
     * @param item
     *          Item to set the image for
     */
    public static void setItemImageFile(String newImageFile, Item item) throws StringException {
        String imageFileNewName = Text.newGuid() + "." + FilenameUtils.getExtension(newImageFile);

        if (!Files.exists(IMAGES_PATH)) {
            Files.createFolder(IMAGES_PATH);
        }

        Files.copyFileToFolder(newImageFile, IMAGES_PATH, imageFileNewName);

        String formerImageFile = item.imageFile;

        item.imageFile = imageFileNewName;

        if (formerImageFile.length() > 0 && Files.exists(IMAGES_PATH + formerImageFile)) {
            Files.delete(IMAGES_PATH + formerImageFile);
        }
    }

    /**
     * Display fatal error message and exit application
     * 
     * @param message
     *          ID of localized error message
     */
    private void displayFatalErrorAndExit(String message) {
        SwtMessageBox.messageBoxError(getLocalizedMessages().get(message));

        _mainWindow.close();
        System.exit(1);
    }

    /**
     * On move item before its current position
     * 
     * @param programOrGroup
     *          Item to move
     * @param isGroup
     *          true if the item is a group, otherwise false
     * @param positionsToMove
     *          Number of positions to move
     */
    private void onMoveItemBefore(final Item programOrGroup, final boolean isGroup, final int positionsToMove) {
        _ongoingOperation = true;

        if (isGroup) {
            _lastSelectedGroup = Math.max(0, _tabFolder.getSelectionIndex() - positionsToMove);
        }

        moveItemBefore(programOrGroup, positionsToMove);

        setup();

        _ongoingOperation = false;
    }

    /**
     * On move item after its current position
     * 
     * @param programOrGroup
     *          Item to move
     * @param isGroup
     *          true if the item is a group, otherwise false
     * @param positionsToMove
     *          Number of positions to move
     */
    private void onMoveItemAfter(final Item programOrGroup, final boolean isGroup, final int positionsToMove) {
        _ongoingOperation = true;

        if (isGroup) {
            _lastSelectedGroup = Math.min(_tabFolder.getSelectionIndex() + positionsToMove,
                    _tabFolder.getItemCount() - 1);
        }

        moveItemAfter(programOrGroup, positionsToMove);

        setup();

        _ongoingOperation = false;
    }

    // region

    /**
     * Save application configuration
     */
    private void saveConfiguration() {
        try {
            FileContent.writeTextFile(_mainWindow._gson.toJson(_mainWindow._config) + "\r\n",
                    Platform.CURRENT_DIRECTORY + "lansator.json");
        } catch (StringException e) {
            _log.fatal(e.getMessage());
            displayFatalErrorAndExit("CANNOT_SAVE_CONFIGURATION_FILE");
        }
    }

    /**
     * Load application configuration
     */
    private void loadConfiguration() {
        GsonBuilder builder = new GsonBuilder();
        _mainWindow._gson = builder.serializeNulls().setPrettyPrinting().create();

        try {
            _mainWindow._config = _mainWindow._gson.fromJson(
                    FileContent.readTextFile(Platform.CURRENT_DIRECTORY + "lansator.json"), Configuration.class);
        } catch (JsonSyntaxException | StringException e) {
            _mainWindow._log.fatal(e.getMessage());
            _mainWindow.displayFatalErrorAndExit("CANNOT_LOAD_CONFIGURATION_FILE");
        }
    }

    /**
     * Report critical error in message box and log file
     *
     * @param exception
     *          Exception to report
     */
    public void reportCriticalErrorAndTerminate(Throwable exception) {
        _log.fatal(Run.getExceptionStackTrace(exception));

        SwtMessageBox.messageBoxError(_localizedMessages.get("CRITICAL_APPLICATION_ERROR"));

        if (!Run.DEBUG_ACTIVE) {
            _display.asyncExec(new Runnable() {
                @Override
                public void run() {
                    close();
                }
            });
        }
    }

    // region getters

    /**
     * @return The localized controls
     */
    public Localization getLocalizedControls() {
        return _localizedControls;
    }

    /**
     * @param localizedControls
     *          The localizedControls to set
     */
    private void setLocalizedControls(Localization localizedControls) {
        this._localizedControls = localizedControls;
    }

    /**
     * @return The localized messages
     */
    public Localization getLocalizedMessages() {
        return _localizedMessages;
    }

    /**
     * @param localizedMessages
     *          The localized messages to set
     */
    private void setLocalizedMessages(Localization localizedMessages) {
        this._localizedMessages = localizedMessages;
    }

    /**
     * @return The default image of the application
     */
    public Image getDefaultImage() {
        return _defaultImage;
    }

    /**
     * @param defaultImage
     *          The default image to set
     */
    private void setDefaultImage(Image defaultImage) {
        this._defaultImage = defaultImage;
    }

    /**
     * Get images path
     * 
     * @return Images path
     */
    public static String getImagesPath() {
        return IMAGES_PATH;
    }
}