de.tor.tribes.ui.views.DSWorkbenchReportFrame.java Source code

Java tutorial

Introduction

Here is the source code for de.tor.tribes.ui.views.DSWorkbenchReportFrame.java

Source

/* 
 * Copyright 2015 Torridity.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.tor.tribes.ui.views;

import de.tor.tribes.control.GenericEventListener;
import de.tor.tribes.control.GenericManagerListener;
import de.tor.tribes.control.ManageableType;
import de.tor.tribes.types.*;
import de.tor.tribes.types.ext.Ally;
import de.tor.tribes.types.ext.Tribe;
import de.tor.tribes.types.ext.Village;
import de.tor.tribes.ui.components.TabPaneComponent;
import de.tor.tribes.ui.panels.GenericTestPanel;
import de.tor.tribes.ui.panels.ReportTableTab;
import de.tor.tribes.ui.windows.AbstractDSWorkbenchFrame;
import de.tor.tribes.ui.windows.ReportRulesDialog;
import de.tor.tribes.util.*;
import de.tor.tribes.util.bb.AllyReportStatsFormatter;
import de.tor.tribes.util.bb.OverallReportStatsFormatter;
import de.tor.tribes.util.bb.TribeReportStatsFormatter;
import de.tor.tribes.util.farm.FarmManager;
import de.tor.tribes.util.report.ReportManager;
import de.tor.tribes.util.report.ReportStatBuilder;
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.text.NumberFormat;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.configuration2.Configuration;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jdesktop.swingx.JXButton;
import org.jdesktop.swingx.JXTaskPane;
import org.jdesktop.swingx.painter.MattePainter;
import org.jdesktop.swingx.table.TableColumnExt;

/**
 * @author Torridity
 */
public class DSWorkbenchReportFrame extends AbstractDSWorkbenchFrame
        implements GenericManagerListener, ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        ReportTableTab activeTab = getActiveTab();
        if (e.getActionCommand() != null && activeTab != null) {
            if (e.getActionCommand().equals("Copy")) {
                activeTab.transferSelection(ReportTableTab.TRANSFER_TYPE.COPY_TO_INTERNAL_CLIPBOARD);
            } else if (e.getActionCommand().equals("BBCopy")) {
                activeTab.transferSelection(ReportTableTab.TRANSFER_TYPE.CLIPBOARD_BB);
            } else if (e.getActionCommand().equals("Cut")) {
                activeTab.transferSelection(ReportTableTab.TRANSFER_TYPE.CUT_TO_INTERNAL_CLIPBOARD);
            } else if (e.getActionCommand().equals("Paste")) {
                activeTab.transferSelection(ReportTableTab.TRANSFER_TYPE.FROM_INTERNAL_CLIPBOARD);
            } else if (e.getActionCommand().equals("Delete")) {
                activeTab.deleteSelection(true);
            } else if (e.getActionCommand().equals("Find")) {
                BufferedImage back = ImageUtils.createCompatibleBufferedImage(3, 3, BufferedImage.TRANSLUCENT);
                Graphics g = back.getGraphics();
                g.setColor(new Color(120, 120, 120, 120));
                g.fillRect(0, 0, back.getWidth(), back.getHeight());
                g.setColor(new Color(120, 120, 120));
                g.drawLine(0, 0, 3, 3);
                g.dispose();
                TexturePaint paint = new TexturePaint(back,
                        new Rectangle2D.Double(0, 0, back.getWidth(), back.getHeight()));
                jxSearchPane.setBackgroundPainter(new MattePainter(paint));
                DefaultListModel model = new DefaultListModel();

                for (int i = 0; i < activeTab.getReportTable().getColumnCount(); i++) {
                    TableColumnExt col = activeTab.getReportTable().getColumnExt(i);
                    if (col.isVisible()) {
                        if (!col.getTitle().equals("Status") && !col.getTitle().equals("Typ")
                                && !col.getTitle().equals("Sonstiges")) {
                            model.addElement(col.getTitle());
                        }
                    }
                }
                jXColumnList.setModel(model);
                jXColumnList.setSelectedIndex(0);
                jxSearchPane.setVisible(true);
            }
        }
    }

    @Override
    public void dataChangedEvent() {
        generateReportTabs();
    }

    @Override
    public void dataChangedEvent(String pGroup) {
        ReportTableTab tab = getActiveTab();
        if (tab != null) {
            tab.updateSet();
        }
    }

    private static Logger logger = LogManager.getLogger("ReportView");
    private static DSWorkbenchReportFrame SINGLETON = null;
    private FightStats lastStats = null;
    private GenericTestPanel centerPanel = null;
    private String overallResultCodes = null;
    private String allyResultCodes = null;
    private String tribeResultCodes = null;
    private ReportRulesDialog rulesDialog = null;

    public static synchronized DSWorkbenchReportFrame getSingleton() {
        if (SINGLETON == null) {
            SINGLETON = new DSWorkbenchReportFrame();
        }
        return SINGLETON;
    }

    /**
     * Creates new form DSWorkbenchReportFrame
     */
    DSWorkbenchReportFrame() {
        initComponents();
        centerPanel = new GenericTestPanel();
        jReportsPanel.add(centerPanel, BorderLayout.CENTER);
        centerPanel.setChildComponent(jXReportsPanel);
        buildMenu();
        capabilityInfoPanel1.addActionListener(this);
        KeyStroke bbCopy = KeyStroke.getKeyStroke(KeyEvent.VK_B, ActionEvent.CTRL_MASK, false);

        ActionListener resultListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                copyResultBBToClipboardEvent();
            }
        };

        capabilityInfoPanel2.addActionListener(resultListener);
        jResultTabbedPane.registerKeyboardAction(resultListener, "BBCopy", bbCopy,
                JComponent.WHEN_IN_FOCUSED_WINDOW);
        jReportsTabbedPane.getModel().addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                ReportTableTab activeTab = getActiveTab();
                if (activeTab != null) {
                    activeTab.updateSet();
                }
            }
        });
        jXColumnList.addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                updateFilter();
            }
        });
        jList1.addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (!e.getValueIsAdjusting()) {
                    fireRebuildStatsEvent();
                }
            }
        });

        setGlassPane(jxSearchPane);
        rulesDialog = new ReportRulesDialog(this, true);

        // <editor-fold defaultstate="collapsed" desc=" Init HelpSystem ">
        if (!Constants.DEBUG) {
            GlobalOptions.getHelpBroker().enableHelpKey(getRootPane(), "pages.reports_view",
                    GlobalOptions.getHelpBroker().getHelpSet());
            GlobalOptions.getHelpBroker().enableHelpKey(jCreateStatsFrame.getRootPane(), "pages.reports_view_stats",
                    GlobalOptions.getHelpBroker().getHelpSet());
        }
        // </editor-fold>

        jCreateStatsFrame.pack();
        pack();
    }

    @Override
    public void toBack() {
        jAlwaysOnTopBox.setSelected(false);
        fireAlwaysOnTopEvent(null);
        super.toBack();
    }

    @Override
    public void storeCustomProperties(Configuration pConfig) {
        pConfig.setProperty(getPropertyPrefix() + ".menu.visible", centerPanel.isMenuVisible());
        pConfig.setProperty(getPropertyPrefix() + ".alwaysOnTop", jAlwaysOnTopBox.isSelected());

        int selectedIndex = jReportsTabbedPane.getModel().getSelectedIndex();
        if (selectedIndex >= 0) {
            pConfig.setProperty(getPropertyPrefix() + ".tab.selection", selectedIndex);
        }

        ReportTableTab tab = ((ReportTableTab) jReportsTabbedPane.getComponentAt(0));
        PropertyHelper.storeTableProperties(tab.getReportTable(), pConfig, getPropertyPrefix());
    }

    @Override
    public void restoreCustomProperties(Configuration pConfig) {
        centerPanel.setMenuVisible(pConfig.getBoolean(getPropertyPrefix() + ".menu.visible", true));
        try {
            jReportsTabbedPane.setSelectedIndex(pConfig.getInteger(getPropertyPrefix() + ".tab.selection", 0));
        } catch (Exception ignored) {
        }
        try {
            jAlwaysOnTopBox.setSelected(pConfig.getBoolean(getPropertyPrefix() + ".alwaysOnTop"));
        } catch (Exception ignored) {
        }

        setAlwaysOnTop(jAlwaysOnTopBox.isSelected());

        ReportTableTab tab = ((ReportTableTab) jReportsTabbedPane.getComponentAt(0));
        PropertyHelper.restoreTableProperties(tab.getReportTable(), pConfig, getPropertyPrefix());

    }

    @Override
    public String getPropertyPrefix() {
        return "report.view";
    }

    private void buildMenu() {
        // <editor-fold defaultstate="collapsed" desc="view task pane">
        JXTaskPane viewTaskPane = new JXTaskPane();
        viewTaskPane.setTitle("Anzeigen");

        viewTaskPane.getContentPane().add(
                factoryButton("/res/ui/view_report.png", "Die gew&auml;hlten Berichte ffnen", new MouseAdapter() {
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        ReportTableTab tab = getActiveTab();
                        if (tab != null) {
                            tab.viewReport();
                        }
                    }
                }));
        // </editor-fold>
        // <editor-fold defaultstate="collapsed" desc="transfer task pane">
        JXTaskPane transferTaskPane = new JXTaskPane();
        transferTaskPane.setTitle("bertragen");

        transferTaskPane.getContentPane().add(factoryButton("/res/ui/troop_info_add.png",
                "&Uuml;bertr&auml;gt die &uuml;berlebenden Truppen des Verteidigers", new MouseAdapter() {
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        ReportTableTab tab = getActiveTab();
                        if (tab != null) {
                            tab.transferTroopInfos();
                        }
                    }
                }));

        transferTaskPane.getContentPane().add(factoryButton("/res/ui/report_toAStar.png",
                "&Uuml;bertr&auml;gt den gew&auml;hlten Berichte nach A*Star", new MouseAdapter() {
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        ReportTableTab tab = getActiveTab();
                        if (tab != null) {
                            tab.transferSelection(ReportTableTab.TRANSFER_TYPE.ASTAR);
                        }
                    }
                }));
        // </editor-fold>
        // <editor-fold defaultstate="collapsed" desc="misc task pane">
        JXTaskPane miscPane = new JXTaskPane();
        miscPane.setTitle("Sonstiges");

        miscPane.getContentPane()
                .add(factoryButton("/res/ui/document_new_24x24.png", "Neuen Plan erstellen", new MouseAdapter() {
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        fireCreateAttackPlanEvent(e);
                    }
                }));

        miscPane.getContentPane().add(factoryButton("/res/ui/medal.png",
                "Statistiken zu den gew&auml;hlten Berichten erstellen", new MouseAdapter() {
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        ReportTableTab tab = getActiveTab();
                        if (tab != null) {
                            String[] groups = ReportManager.getSingleton().getGroups();
                            DefaultListModel model = new DefaultListModel();
                            for (String group : groups) {
                                model.addElement(group);
                            }

                            jReportSetsForStatsList.setModel(model);
                            jCreateStatsFrame.setLocationRelativeTo(DSWorkbenchReportFrame.this);
                            jCreateStatsFrame.setVisible(true);
                        }
                    }
                }));

        miscPane.getContentPane().add(factoryButton("/res/ui/report_cleanup.png",
                "Veraltete und doppelte Berichte im gewhlten Berichtset l&ouml;schen", new MouseAdapter() {
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        cleanupReports();
                    }
                }));

        miscPane.getContentPane().add(factoryButton("/res/ui/index_edit.png",
                "Definierte Regeln bearbeiten oder neu erstellen", new MouseAdapter() {
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        rulesDialog.rebuildRuleList();
                        rulesDialog.setLocationRelativeTo(DSWorkbenchReportFrame.this);
                        rulesDialog.setVisible(true);
                    }
                }));

        miscPane.getContentPane().add(factoryButton("/res/ui/index_refresh.png",
                "Definierte Regeln jetzt auf das gew&auml;hlte Berichtset anwenden", new MouseAdapter() {
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        ReportTableTab tab = getActiveTab();
                        if (tab != null) {
                            int changed = ReportManager.getSingleton().filterNow(tab.getReportSet());
                            tab = getActiveTab();
                            if (tab != null) {
                                tab.showInfo(changed + " Berichte neu eingeordnet");
                            }
                        }
                    }
                }));
        // </editor-fold>

        centerPanel.setupTaskPane(viewTaskPane, transferTaskPane, miscPane);
    }

    private void cleanupReports() {
        Village source;
        Village target;
        ReportTableTab tab = getActiveTab();
        if (tab == null) {
            return;
        }
        String set = tab.getReportSet();
        List<FightReport> old = new LinkedList<>();
        int currentIndex = 0;
        for (ManageableType elem : ReportManager.getSingleton().getAllElements(set)) {
            FightReport r = (FightReport) elem;
            if (!old.contains(r)) {
                source = r.getSourceVillage();
                target = r.getTargetVillage();
                FarmInformation info = FarmManager.getSingleton().getFarmInformation(target);
                boolean removeByFarmInfo = false;
                if (info != null) {
                    if (info.getLastReport() > r.getTimestamp()) {
                        old.add(r);
                        removeByFarmInfo = true;
                    }
                }

                if (!removeByFarmInfo) {
                    long time = r.getTimestamp();
                    int secondaryIndex = 0;
                    for (ManageableType elem2 : ReportManager.getSingleton().getAllElements(set)) {
                        FightReport r1 = (FightReport) elem2;
                        if (!old.contains(r1) && r1.getSourceVillage().equals(source)
                                && r1.getTargetVillage().equals(target)) {
                            if (currentIndex != secondaryIndex) {
                                if (r1.getTimestamp() > time || r.equals(r1)) {
                                    old.add(r);
                                    break;
                                } else {
                                    old.add(r1);
                                }
                            }
                        }
                        secondaryIndex++;
                    }
                }
            }
            currentIndex++;
        }

        if (!old.isEmpty()) {
            if (JOptionPaneHelper.showQuestionConfirmBox(this,
                    old.size() + " veraltete Berichte gefunden. Jetzt lschen?", "Lschen", "Nein",
                    "Ja") == JOptionPane.YES_OPTION) {
                ReportManager.getSingleton().removeElements(set, old);
            }
            tab.showInfo(old.size() + " Berichte gelscht");
        } else {
            tab.showInfo("Keine alten Berichte gefunden");
        }
    }

    @Override
    public void resetView() {
        overallResultCodes = null;
        allyResultCodes = null;
        tribeResultCodes = null;
        jOverallStatsArea.setText("");
        jAllyStatsArea.setText("");
        jTribeStatsArea.setText("");
        ReportManager.getSingleton().addManagerListener(DSWorkbenchReportFrame.this);
        generateReportTabs();
    }

    /**
     * Initialize and add one tab for each report set to jTabbedPane1
     */
    public void generateReportTabs() {
        jReportsTabbedPane.invalidate();
        while (jReportsTabbedPane.getTabCount() > 0) {
            ReportTableTab tab = (ReportTableTab) jReportsTabbedPane.getComponentAt(0);
            tab.deregister();
            jReportsTabbedPane.removeTabAt(0);
        }

        String[] plans = ReportManager.getSingleton().getGroups();

        //insert default tab to first place
        for (String plan : plans) {
            ReportTableTab tab = new ReportTableTab(plan, this);
            jReportsTabbedPane.addTab(plan, tab);
        }

        for (int i = 0; i < jReportsTabbedPane.getTabCount(); i++) {
            final TabPaneComponent component = new TabPaneComponent(jReportsTabbedPane);
            component.setStopEditingListener(new GenericEventListener() {
                @Override
                public void event() {
                    int i = jReportsTabbedPane.indexOfTabComponent(component);
                    ReportTableTab tab = (ReportTableTab) jReportsTabbedPane.getComponentAt(i);
                    String newName = component.getEditedText();
                    if (!newName.equals(tab.getReportSet())) {
                        newName = newName.trim();
                        if (newName.length() == 0) {
                            JOptionPaneHelper.showWarningBox(jReportsTabbedPane,
                                    "'" + newName + "' ist ein ungltiger Setname", "Fehler");
                            return;
                        }
                        if (ReportManager.getSingleton().groupExists(newName)) {
                            JOptionPaneHelper.showWarningBox(jReportsTabbedPane,
                                    "Es existiert bereits ein Berichtset mit dem Namen '" + newName + "'",
                                    "Fehler");
                            return;
                        }

                        ReportManager.getSingleton().renameGroup(tab.getReportSet(), newName);
                    }
                }
            });

            component.setCloseTabListener(new GenericEventListener() {
                @Override
                public void event() {
                    int i = jReportsTabbedPane.indexOfTabComponent(component);
                    ReportTableTab tab = (ReportTableTab) jReportsTabbedPane.getComponentAt(i);
                    if (JOptionPaneHelper.showQuestionConfirmBox(jReportsTabbedPane,
                            "Befehlsplan '" + tab.getReportSet()
                                    + "' und alle darin enthaltenen Berichte wirklich lschen? ",
                            "Lschen", "Nein", "Ja") == JOptionPane.YES_OPTION) {
                        ReportManager.getSingleton().removeGroup(tab.getReportSet());
                    }
                }
            });

            if (i == 0 || i == 1) {
                component.setCloseable(false);
                component.setEditable(false);
            }

            jReportsTabbedPane.setTabComponentAt(i, component);
        }

        jReportsTabbedPane.revalidate();
        ReportTableTab tab = getActiveTab();
        if (tab != null) {
            tab.updateSet();
        }
    }

    /**
     * Get the currently selected tab
     */
    private ReportTableTab getActiveTab() {
        try {
            if (jReportsTabbedPane.getModel().getSelectedIndex() < 0) {
                return null;
            }
            return ((ReportTableTab) jReportsTabbedPane
                    .getComponentAt(jReportsTabbedPane.getModel().getSelectedIndex()));
        } catch (ClassCastException cce) {
            return null;
        }
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this
     * method is always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jCreateStatsFrame = new javax.swing.JFrame();
        jPanel2 = new javax.swing.JPanel();
        jLabel6 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        jReportSetsForStatsList = new javax.swing.JList();
        jButton10 = new javax.swing.JButton();
        jPanel3 = new javax.swing.JPanel();
        jLabel7 = new javax.swing.JLabel();
        jScrollPane3 = new javax.swing.JScrollPane();
        jList1 = new javax.swing.JList();
        jResultTabbedPane = new javax.swing.JTabbedPane();
        jPanel4 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jOverallStatsArea = new javax.swing.JTextPane();
        jPanel5 = new javax.swing.JPanel();
        jScrollPane5 = new javax.swing.JScrollPane();
        jAllyStatsArea = new javax.swing.JTextPane();
        jPanel6 = new javax.swing.JPanel();
        jScrollPane6 = new javax.swing.JScrollPane();
        jTribeStatsArea = new javax.swing.JTextPane();
        capabilityInfoPanel2 = new de.tor.tribes.ui.components.CapabilityInfoPanel();
        jXReportsPanel = new org.jdesktop.swingx.JXPanel();
        jReportsTabbedPane = new javax.swing.JTabbedPane();
        jNewPlanPanel = new javax.swing.JPanel();
        jLabel10 = new javax.swing.JLabel();
        jxSearchPane = new org.jdesktop.swingx.JXPanel();
        jXPanel2 = new org.jdesktop.swingx.JXPanel();
        jButton15 = new javax.swing.JButton();
        jTextField1 = new javax.swing.JTextField();
        jLabel21 = new javax.swing.JLabel();
        jFilterRows = new javax.swing.JCheckBox();
        jFilterCaseSensitive = new javax.swing.JCheckBox();
        jScrollPane8 = new javax.swing.JScrollPane();
        jXColumnList = new org.jdesktop.swingx.JXList();
        jLabel22 = new javax.swing.JLabel();
        jPanel7 = new javax.swing.JPanel();
        jGuessUnknownLosses = new javax.swing.JCheckBox();
        jUseSilentKillsBox = new javax.swing.JCheckBox();
        jCheckBox3 = new javax.swing.JCheckBox();
        jShowPercentsBox = new javax.swing.JCheckBox();
        jAlwaysOnTopBox = new javax.swing.JCheckBox();
        jReportsPanel = new javax.swing.JPanel();
        capabilityInfoPanel1 = new de.tor.tribes.ui.components.CapabilityInfoPanel();

        jCreateStatsFrame.setTitle("Kampfstatistiken");

        jPanel2.setBackground(new java.awt.Color(239, 235, 223));

        jLabel6.setText("Verwendete Berichtsets");

        jScrollPane2.setPreferredSize(new java.awt.Dimension(258, 100));

        jScrollPane2.setViewportView(jReportSetsForStatsList);

        jButton10.setIcon(new javax.swing.ImageIcon(getClass().getResource("/res/ui/select.png"))); // NOI18N
        jButton10.setText("Auswerten");
        jButton10.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                fireDoCreateStatsEvent(evt);
            }
        });

        jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Ergebnisse"));
        jPanel3.setOpaque(false);

        jLabel7.setText("Angezeigte Stmme");

        jScrollPane3.setMaximumSize(new java.awt.Dimension(140, 130));
        jScrollPane3.setMinimumSize(new java.awt.Dimension(140, 130));
        jScrollPane3.setPreferredSize(new java.awt.Dimension(140, 130));

        jScrollPane3.setViewportView(jList1);

        jResultTabbedPane.setBackground(new java.awt.Color(239, 235, 223));

        jPanel4.setOpaque(false);
        jPanel4.setLayout(new java.awt.BorderLayout());

        jOverallStatsArea.setContentType("text/html"); // NOI18N
        jOverallStatsArea.setEditable(false);
        jScrollPane1.setViewportView(jOverallStatsArea);

        jPanel4.add(jScrollPane1, java.awt.BorderLayout.CENTER);

        jResultTabbedPane.addTab("Gesamtbersicht",
                new javax.swing.ImageIcon(getClass().getResource("/res/ui/chart.png")), jPanel4); // NOI18N

        jPanel5.setBackground(new java.awt.Color(239, 235, 223));
        jPanel5.setLayout(new java.awt.BorderLayout());

        jAllyStatsArea.setContentType("text/html"); // NOI18N
        jAllyStatsArea.setEditable(false);
        jScrollPane5.setViewportView(jAllyStatsArea);

        jPanel5.add(jScrollPane5, java.awt.BorderLayout.CENTER);

        jResultTabbedPane.addTab("Stmme", new javax.swing.ImageIcon(getClass().getResource("/res/ally.png")),
                jPanel5); // NOI18N

        jPanel6.setBackground(new java.awt.Color(239, 235, 223));
        jPanel6.setLayout(new java.awt.BorderLayout());

        jTribeStatsArea.setContentType("text/html"); // NOI18N
        jTribeStatsArea.setEditable(false);
        jScrollPane6.setViewportView(jTribeStatsArea);

        jPanel6.add(jScrollPane6, java.awt.BorderLayout.CENTER);

        jResultTabbedPane.addTab("Spieler", new javax.swing.ImageIcon(getClass().getResource("/res/face.png")),
                jPanel6); // NOI18N

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(jPanel3Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                .addComponent(jResultTabbedPane, javax.swing.GroupLayout.Alignment.LEADING,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, 570, Short.MAX_VALUE)
                                .addGroup(jPanel3Layout.createSequentialGroup().addComponent(jLabel7)
                                        .addGap(18, 18, 18).addComponent(jScrollPane3,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, 457, Short.MAX_VALUE)))
                        .addContainerGap()));
        jPanel3Layout.setVerticalGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel3Layout.createSequentialGroup().addContainerGap()
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jLabel7).addComponent(jScrollPane3,
                                        javax.swing.GroupLayout.PREFERRED_SIZE, 99,
                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jResultTabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 215, Short.MAX_VALUE)
                        .addContainerGap()));

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(jPanel2Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                .addComponent(jPanel3, javax.swing.GroupLayout.Alignment.LEADING,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        Short.MAX_VALUE)
                                .addGroup(javax.swing.GroupLayout.Alignment.LEADING,
                                        jPanel2Layout.createSequentialGroup().addComponent(jLabel6)
                                                .addGap(18, 18, 18).addComponent(jScrollPane2,
                                                        javax.swing.GroupLayout.DEFAULT_SIZE, 470, Short.MAX_VALUE))
                                .addComponent(jButton10))
                        .addContainerGap()));
        jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel2Layout.createSequentialGroup().addContainerGap()
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jLabel6).addComponent(jScrollPane2,
                                        javax.swing.GroupLayout.PREFERRED_SIZE, 90,
                                        javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jButton10)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addContainerGap()));

        capabilityInfoPanel2.setCopyable(false);
        capabilityInfoPanel2.setDeletable(false);
        capabilityInfoPanel2.setPastable(false);
        capabilityInfoPanel2.setSearchable(false);

        javax.swing.GroupLayout jCreateStatsFrameLayout = new javax.swing.GroupLayout(
                jCreateStatsFrame.getContentPane());
        jCreateStatsFrame.getContentPane().setLayout(jCreateStatsFrameLayout);
        jCreateStatsFrameLayout.setHorizontalGroup(
                jCreateStatsFrameLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(jCreateStatsFrameLayout.createSequentialGroup().addContainerGap()
                                .addGroup(jCreateStatsFrameLayout
                                        .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(capabilityInfoPanel2, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addContainerGap()));
        jCreateStatsFrameLayout.setVerticalGroup(jCreateStatsFrameLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jCreateStatsFrameLayout.createSequentialGroup().addContainerGap()
                        .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(capabilityInfoPanel2, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addContainerGap()));

        jXReportsPanel.setLayout(new java.awt.BorderLayout());
        jXReportsPanel.add(jReportsTabbedPane, java.awt.BorderLayout.CENTER);

        jNewPlanPanel.setOpaque(false);
        jNewPlanPanel.setLayout(new java.awt.BorderLayout());

        jLabel10.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        jLabel10.setIcon(new javax.swing.ImageIcon(getClass().getResource("/res/ui/document_new_24x24.png"))); // NOI18N
        jLabel10.setToolTipText("Leeres Berichtset erstellen");
        jLabel10.setEnabled(false);
        jLabel10.setMaximumSize(new java.awt.Dimension(40, 40));
        jLabel10.setMinimumSize(new java.awt.Dimension(40, 40));
        jLabel10.setPreferredSize(new java.awt.Dimension(40, 40));
        jLabel10.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                fireEnterEvent(evt);
            }

            public void mouseExited(java.awt.event.MouseEvent evt) {
                fireExitEvent(evt);
            }

            public void mouseReleased(java.awt.event.MouseEvent evt) {
                fireCreateAttackPlanEvent(evt);
            }
        });
        jNewPlanPanel.add(jLabel10, java.awt.BorderLayout.CENTER);

        jxSearchPane.setOpaque(false);
        jxSearchPane.setLayout(new java.awt.GridBagLayout());

        jXPanel2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        jXPanel2.setInheritAlpha(false);

        jButton15.setText("Anwenden");
        jButton15.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                jButton15fireHideGlassPaneEvent(evt);
            }
        });

        jTextField1.addCaretListener(new javax.swing.event.CaretListener() {
            public void caretUpdate(javax.swing.event.CaretEvent evt) {
                jTextField1fireHighlightEvent(evt);
            }
        });

        jLabel21.setText("Suchbegriff");

        jFilterRows.setText("Nur gefilterte Zeilen anzeigen");
        jFilterRows.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jFilterRowsfireUpdateFilterEvent(evt);
            }
        });

        jFilterCaseSensitive.setText("Gro-/Kleinschreibung beachten");
        jFilterCaseSensitive.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jFilterCaseSensitivefireUpdateFilterEvent(evt);
            }
        });

        jXColumnList.setModel(new javax.swing.AbstractListModel() {
            String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };

            public int getSize() {
                return strings.length;
            }

            public Object getElementAt(int i) {
                return strings[i];
            }
        });
        jXColumnList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jScrollPane8.setViewportView(jXColumnList);

        jLabel22.setText("Spalten");

        javax.swing.GroupLayout jXPanel2Layout = new javax.swing.GroupLayout(jXPanel2);
        jXPanel2.setLayout(jXPanel2Layout);
        jXPanel2Layout
                .setHorizontalGroup(jXPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING,
                                jXPanel2Layout.createSequentialGroup().addContainerGap().addGroup(jXPanel2Layout
                                        .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                        .addComponent(jLabel22, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(
                                                jLabel21, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                                        .addGap(18, 18, 18)
                                        .addGroup(jXPanel2Layout
                                                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                .addGroup(jXPanel2Layout.createSequentialGroup()
                                                        .addComponent(jScrollPane8,
                                                                javax.swing.GroupLayout.PREFERRED_SIZE, 158,
                                                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                                        .addGap(18, 18, 18)
                                                        .addGroup(jXPanel2Layout
                                                                .createParallelGroup(
                                                                        javax.swing.GroupLayout.Alignment.TRAILING)
                                                                .addGroup(jXPanel2Layout.createParallelGroup(
                                                                        javax.swing.GroupLayout.Alignment.TRAILING,
                                                                        false)
                                                                        .addComponent(jFilterRows,
                                                                                javax.swing.GroupLayout.Alignment.LEADING,
                                                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                Short.MAX_VALUE)
                                                                        .addComponent(jFilterCaseSensitive,
                                                                                javax.swing.GroupLayout.Alignment.LEADING,
                                                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                Short.MAX_VALUE))
                                                                .addComponent(jButton15)))
                                                .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                        355, javax.swing.GroupLayout.PREFERRED_SIZE))
                                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
        jXPanel2Layout.setVerticalGroup(jXPanel2Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jXPanel2Layout.createSequentialGroup().addContainerGap().addGroup(jXPanel2Layout
                        .createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(jLabel21)
                        .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jXPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(jXPanel2Layout
                                        .createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                        .addGroup(javax.swing.GroupLayout.Alignment.LEADING, jXPanel2Layout
                                                .createSequentialGroup().addComponent(jFilterCaseSensitive)
                                                .addPreferredGap(
                                                        javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                                .addComponent(jFilterRows)
                                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED,
                                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                                .addComponent(jButton15))
                                        .addComponent(jScrollPane8, javax.swing.GroupLayout.Alignment.LEADING,
                                                javax.swing.GroupLayout.PREFERRED_SIZE, 164,
                                                javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addComponent(jLabel22))
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));

        jxSearchPane.add(jXPanel2, new java.awt.GridBagConstraints());

        jPanel7.setBorder(javax.swing.BorderFactory.createTitledBorder("Optionen"));
        jPanel7.setOpaque(false);

        jGuessUnknownLosses.setSelected(true);
        jGuessUnknownLosses.setText("Gegnerische Verluste schtzen, falls unbekannt");
        jGuessUnknownLosses.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                fireStatOptionsChangedEvent(evt);
            }
        });

        jUseSilentKillsBox.setSelected(true);
        jUseSilentKillsBox.setText("Auswrtige Einheiten bei Adelung als Verlust werten");
        jUseSilentKillsBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                fireStatOptionsChangedEvent(evt);
            }
        });

        jCheckBox3.setSelected(true);
        jCheckBox3.setText("Verluste pro Angreifer/Verteidiger anzeigen");
        jCheckBox3.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                fireStatOptionsChangedEvent(evt);
            }
        });

        jShowPercentsBox.setText("Prozentuale Anteile anzeigen");
        jShowPercentsBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                fireStatOptionsChangedEvent(evt);
            }
        });

        javax.swing.GroupLayout jPanel7Layout = new javax.swing.GroupLayout(jPanel7);
        jPanel7.setLayout(jPanel7Layout);
        jPanel7Layout.setHorizontalGroup(jPanel7Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel7Layout.createSequentialGroup().addContainerGap()
                        .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jGuessUnknownLosses).addComponent(jUseSilentKillsBox)
                                .addComponent(jCheckBox3).addComponent(jShowPercentsBox))));
        jPanel7Layout.setVerticalGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel7Layout.createSequentialGroup().addContainerGap().addComponent(jGuessUnknownLosses)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jUseSilentKillsBox)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jCheckBox3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jShowPercentsBox).addContainerGap(23, Short.MAX_VALUE)));

        setTitle("Berichtsdatenbank");
        getContentPane().setLayout(new java.awt.GridBagLayout());

        jAlwaysOnTopBox.setText("Immer im Vordergrund");
        jAlwaysOnTopBox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                fireAlwaysOnTopEvent(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(jAlwaysOnTopBox, gridBagConstraints);

        jReportsPanel.setBackground(new java.awt.Color(239, 235, 223));
        jReportsPanel.setPreferredSize(new java.awt.Dimension(500, 400));
        jReportsPanel.setLayout(new java.awt.BorderLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 500;
        gridBagConstraints.ipady = 400;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        getContentPane().add(jReportsPanel, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(capabilityInfoPanel1, gridBagConstraints);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void fireAlwaysOnTopEvent(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_fireAlwaysOnTopEvent
        setAlwaysOnTop(!isAlwaysOnTop());
    }//GEN-LAST:event_fireAlwaysOnTopEvent

    private void fireDoCreateStatsEvent(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_fireDoCreateStatsEvent
        List selection = jReportSetsForStatsList.getSelectedValuesList();
        if (selection == null || selection.isEmpty()) {
            JOptionPaneHelper.showInformationBox(jCreateStatsFrame, "Kein Berichtset ausgewhlt", "Information");
            return;
        }

        List<String> reportSets = new LinkedList<>();
        for (Object o : selection) {
            reportSets.add((String) o);
        }

        DefaultListModel model = new DefaultListModel();
        lastStats = ReportStatBuilder.buildStats(reportSets);
        for (Ally a : lastStats.getAttackingAllies()) {
            model.addElement(a);
        }

        jList1.setModel(model);
        jList1.setSelectionInterval(0, model.size() - 1);
        fireRebuildStatsEvent();
    }//GEN-LAST:event_fireDoCreateStatsEvent

    private void fireStatOptionsChangedEvent(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_fireStatOptionsChangedEvent
        fireRebuildStatsEvent();
    }//GEN-LAST:event_fireStatOptionsChangedEvent

    private void jButton15fireHideGlassPaneEvent(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jButton15fireHideGlassPaneEvent
        jxSearchPane.setBackgroundPainter(null);
        jxSearchPane.setVisible(false);
    }//GEN-LAST:event_jButton15fireHideGlassPaneEvent

    private void jTextField1fireHighlightEvent(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_jTextField1fireHighlightEvent
        updateFilter();
    }//GEN-LAST:event_jTextField1fireHighlightEvent

    private void jFilterRowsfireUpdateFilterEvent(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jFilterRowsfireUpdateFilterEvent
        updateFilter();
    }//GEN-LAST:event_jFilterRowsfireUpdateFilterEvent

    private void jFilterCaseSensitivefireUpdateFilterEvent(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jFilterCaseSensitivefireUpdateFilterEvent
        updateFilter();
    }//GEN-LAST:event_jFilterCaseSensitivefireUpdateFilterEvent

    private void fireCreateAttackPlanEvent(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_fireCreateAttackPlanEvent
        int unusedId = 1;
        while (unusedId < 1000) {
            if (ReportManager.getSingleton().addGroup("Neues Set " + unusedId)) {
                break;
            }
            unusedId++;
        }
        if (unusedId == 1000) {
            JOptionPaneHelper.showErrorBox(DSWorkbenchReportFrame.this,
                    "Du hast mehr als 1000 Berichtsets. Bitte lsche zuerst ein paar bevor du Neue erstellst.",
                    "Fehler");
        }
    }//GEN-LAST:event_fireCreateAttackPlanEvent

    private void fireExitEvent(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_fireExitEvent
        jLabel10.setEnabled(false);
    }//GEN-LAST:event_fireExitEvent

    private void fireEnterEvent(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_fireEnterEvent
        jLabel10.setEnabled(true);
    }//GEN-LAST:event_fireEnterEvent

    private void fireRebuildStatsEvent() {
        List selection = jList1.getSelectedValuesList();
        if (selection == null || selection.isEmpty()) {
            jOverallStatsArea.setText("<html>Kein Stamm ausgewhlt</html>");
            jAllyStatsArea.setText("<html>Kein Stamm ausgewhlt</html>");
            jTribeStatsArea.setText("<html>Kein Stamm ausgewhlt</html>");
            return;
        }
        int overallDefAllies = lastStats.getDefendingAllies().length;
        int overallDefTribes = lastStats.getDefendingTribes().length;

        NumberFormat f = NumberFormat.getInstance();
        f.setMinimumFractionDigits(0);
        f.setMaximumFractionDigits(0);

        StringBuilder allyBuffer = new StringBuilder();
        StringBuilder tribeBuffer = new StringBuilder();
        HashMap<Ally, AllyStatResult> allyResults = new HashMap<>();
        OverallStatResult overallResult = new OverallStatResult();
        for (Object o : selection) {
            Ally a = (Ally) o;
            AllyStatResult result = new AllyStatResult();
            allyResults.put(a, result);
            for (Tribe t : lastStats.getAttackingTribes(a)) {
                TribeStatResult tribeResult = new TribeStatResult();
                SingleAttackerStat stats = lastStats.getStatsForTribe(t);
                tribeResult.setTribeStats(stats, jGuessUnknownLosses.isSelected());
                result.addTribeStatResult(tribeResult);
            }
            overallResult.addAllyStatsResult(result);
        }
        overallResult.setStartDate(lastStats.getStartDate());
        overallResult.setEndDate(lastStats.getEndDate());
        overallResult.setReportCount(lastStats.getReportCount());
        overallResult.setAttackerAllies(selection.size());
        overallResult.setDefenders(overallDefTribes);
        overallResult.setDefenderAllies(overallDefAllies);

        for (Ally a : allyResults.keySet()) {
            AllyStatResult res = allyResults.get(a);
            res.setAlly(a);
            res.setOverallKills(overallResult.getKills());
            res.setOverallLosses(overallResult.getLosses());

            for (TribeStatResult tRes : res.getTribeStats()) {
                tRes.setOverallKills(res.getOverallKills());
                tRes.setOverallLosses(res.getOverallLosses());
                tRes.setAllyKills(res.getKills());
                tRes.setAllyLosses(res.getLosses());
            }
        }

        try {
            List<OverallStatResult> list = Arrays.asList(overallResult);
            overallResultCodes = new OverallReportStatsFormatter().formatElements(list, true);
            jOverallStatsArea.setText("<html><head>" + BBCodeFormatter.getStyles() + "</head><body>"
                    + BBCodeFormatter.toHtml(overallResultCodes) + "</body></html>");
        } catch (Exception e) {
            overallResultCodes = null;
            jOverallStatsArea.setText("<html>Fehler bei der Darstellung der Auswertung</html>");
            logger.error("Failed to render overall BB representation", e);
        }
        try {
            List<AllyStatResult> list = new LinkedList<>();
            CollectionUtils.addAll(list, allyResults.values());
            allyResultCodes = new AllyReportStatsFormatter().formatElements(list, true);
            jAllyStatsArea.setText("<html><head>" + BBCodeFormatter.getStyles() + "</head><body>"
                    + BBCodeFormatter.toHtml(allyResultCodes) + "</body></html>");
        } catch (Exception e) {
            allyResultCodes = null;
            jAllyStatsArea.setText("<html>Fehler bei der Darstellung der Auswertung</html>");
            logger.error("Failed to render BB representation for allies", e);
        }

        try {
            List<TribeStatResult> list = new LinkedList<>();
            for (AllyStatResult allyStat : allyResults.values()) {
                Collections.addAll(list,
                        allyStat.getTribeStats().toArray(new TribeStatResult[allyStat.getTribeStats().size()]));
            }
            tribeResultCodes = new TribeReportStatsFormatter().formatElements(list, true);
            jTribeStatsArea.setText("<html><head>" + BBCodeFormatter.getStyles() + "</head><body>"
                    + BBCodeFormatter.toHtml(tribeResultCodes) + "</body></html>");
        } catch (Exception e) {
            tribeResultCodes = null;
            jTribeStatsArea.setText("<html>Fehler bei der Darstellung der Auswertung</html>");
            logger.error("Failed to render BB representation for tribes", e);
        }
        jResultTabbedPane.setSelectedIndex(0);
    }

    private void copyResultBBToClipboardEvent() {
        StringSelection toCopy = null;
        String dataName = null;
        switch (jResultTabbedPane.getSelectedIndex()) {
        case 0:
            toCopy = new StringSelection(overallResultCodes);
            dataName = "Gesamtbersicht";
            break;
        case 1:
            toCopy = new StringSelection(allyResultCodes);
            dataName = "Stmme";
            break;
        case 2:
            toCopy = new StringSelection(tribeResultCodes);
            dataName = "Spieler";
            break;
        }
        if (toCopy == null) {
            JOptionPaneHelper.showInformationBox(jCreateStatsFrame,
                    "Bitte zuerst einen Tab mit einer Auswertung whlen.", "Information");
            return;
        }
        try {
            Toolkit.getDefaultToolkit().getSystemClipboard().setContents(toCopy, null);
            JOptionPaneHelper.showInformationBox(jCreateStatsFrame,
                    "Auswertung '" + dataName + "' in Zwischenablage kopiert.", "Information");
        } catch (Exception e) {
            logger.error("Failed to copy data to clipboard", e);
            JOptionPaneHelper.showErrorBox(jCreateStatsFrame, "Fehler beim Kopieren in die Zwischenablage.",
                    "Fehler");
        }
    }

    /**
     * Update the attack plan filter
     */
    private void updateFilter() {
        ReportTableTab tab = getActiveTab();
        if (tab != null) {
            final List<String> selection = new LinkedList<>();
            for (Object o : jXColumnList.getSelectedValues()) {
                selection.add((String) o);
            }
            tab.updateFilter(jTextField1.getText(), selection, jFilterCaseSensitive.isSelected(),
                    jFilterRows.isSelected());
        }
    }

    @Override
    public void fireVillagesDraggedEvent(List<Village> pVillages, Point pDropLocation) {
    }

    /**
     * Factory a new button
     */
    private JXButton factoryButton(String pIconResource, String pTooltip, MouseListener pListener) {
        JXButton button = new JXButton(new ImageIcon(DSWorkbenchAttackFrame.class.getResource(pIconResource)));
        if (pTooltip != null) {
            button.setToolTipText("<html><div width='150px'>" + pTooltip + "</div></html>");
        }
        button.addMouseListener(pListener);
        return button;
    }

    // <editor-fold defaultstate="collapsed" desc="Gesture Handling">
    @Override
    public void fireExportAsBBGestureEvent() {
        ReportTableTab tab = getActiveTab();
        if (tab != null) {
            tab.transferSelection(ReportTableTab.TRANSFER_TYPE.CLIPBOARD_BB);
        }
    }

    @Override
    public void fireNextPageGestureEvent() {
        int current = jReportsTabbedPane.getSelectedIndex();
        int size = jReportsTabbedPane.getTabCount();
        if (current + 1 > size - 1) {
            current = 0;
        } else {
            current += 1;
        }
        jReportsTabbedPane.setSelectedIndex(current);
    }

    @Override
    public void firePreviousPageGestureEvent() {
        int current = jReportsTabbedPane.getSelectedIndex();
        int size = jReportsTabbedPane.getTabCount();
        if (current - 1 < 0) {
            current = size - 1;
        } else {
            current -= 1;
        }
        jReportsTabbedPane.setSelectedIndex(current);
    }

    @Override
    public void fireRenameGestureEvent() {
        int idx = jReportsTabbedPane.getSelectedIndex();
        if (idx != 0 && idx != 1) {
            jReportsTabbedPane.setSelectedIndex(idx);
        }
    }
    // </editor-fold>

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private de.tor.tribes.ui.components.CapabilityInfoPanel capabilityInfoPanel1;
    private de.tor.tribes.ui.components.CapabilityInfoPanel capabilityInfoPanel2;
    private javax.swing.JTextPane jAllyStatsArea;
    private javax.swing.JCheckBox jAlwaysOnTopBox;
    private javax.swing.JButton jButton10;
    private javax.swing.JButton jButton15;
    private javax.swing.JCheckBox jCheckBox3;
    private javax.swing.JFrame jCreateStatsFrame;
    private javax.swing.JCheckBox jFilterCaseSensitive;
    private javax.swing.JCheckBox jFilterRows;
    private javax.swing.JCheckBox jGuessUnknownLosses;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel21;
    private javax.swing.JLabel jLabel22;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JList jList1;
    private javax.swing.JPanel jNewPlanPanel;
    private javax.swing.JTextPane jOverallStatsArea;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JPanel jPanel5;
    private javax.swing.JPanel jPanel6;
    private javax.swing.JPanel jPanel7;
    private javax.swing.JList jReportSetsForStatsList;
    private javax.swing.JPanel jReportsPanel;
    private javax.swing.JTabbedPane jReportsTabbedPane;
    private javax.swing.JTabbedPane jResultTabbedPane;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JScrollPane jScrollPane6;
    private javax.swing.JScrollPane jScrollPane8;
    private javax.swing.JCheckBox jShowPercentsBox;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextPane jTribeStatsArea;
    private javax.swing.JCheckBox jUseSilentKillsBox;
    private org.jdesktop.swingx.JXList jXColumnList;
    private org.jdesktop.swingx.JXPanel jXPanel2;
    private org.jdesktop.swingx.JXPanel jXReportsPanel;
    private org.jdesktop.swingx.JXPanel jxSearchPane;
    // End of variables declaration//GEN-END:variables
}