Package cz.cuni.mff.inetpaint.communications

Source Code of cz.cuni.mff.inetpaint.communications.CommunicationFrame

package cz.cuni.mff.inetpaint.communications;

import cz.cuni.mff.inetpaint.communications.swing.ClosableTabComponent;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;

import cz.cuni.mff.inetpaint.*;
import cz.cuni.mff.inetpaint.dialog.*;
import org.jivesoftware.smack.packet.*;

/**
* Třída reprezentující hlavní okno komunikací.
* @author Jindřich Helcl
*/
public class CommunicationFrame extends JFrame {
    private static final Dimension MIN_SIZE = new Dimension(400,360);
    private static CommunicationFrame instance;
   
    /** Static methods */  
    private static CommunicationFrame getInstance() {
        if(instance == null) {
            instance = new CommunicationFrame();
           
            // až se okno zavře, tak se musí zrušit objekt - proč?
            /*
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    instance.addWindowListener(new WindowAdapter() {
                        @Override
                        public void windowClosed(WindowEvent e) {
                            super.windowClosed(e);
                            instance = null;
                        }
                    });
                }
            }); 
             *
             */
        }       
        return instance;
    }
   
    /**
     * Přepne okno na danou komunikaci. Pokud není otevřené, zobrazí se.
     * @param communication Komunikace, která se má zobrazit
     */
    public static void showCommunication(AbstractCommunication communication) {
        showCommunication(communication, false);       
    }
   
    /**
     * Přepne okno na danou komunikaci. Pokud není otevřené, zobrazí se.
     * @param communication Komunikace, která se má zobrazit
     * @param automatic Pokud je tento flag nastaven na {@literal true}, okno se otevře na pozadí
     */
    public static void showCommunication(AbstractCommunication communication, boolean automatic) {
        CommunicationFrame validInstance = getInstance();
       
        // pokud je okno zavřené a pokud jde o automatické otevření, otevřu ho minimalizovaně..
        if(automatic && !validInstance.isVisible()) {
            validInstance.setExtendedState(ICONIFIED);
        }
               
        // pokud to je manuál, vždy nastavím extended state na ten uloženej v preferences a otevřu ho
        else if (!automatic){
            validInstance.setExtendedState(NORMAL);
        }
       
        validInstance.setVisible(true);
       
        // pokud komunikace není zobrazena, zobrazím jí.
        int index = validInstance.addCommunication(communication);
       
        // přepnu panel na danou komunikaci (jen když neni automatic)
        if(!automatic) {
            validInstance.selectTabAt(index);
        }
    }

    /**
     * Skryje danou komunikaci z okna.
     * @param communication Komunikace, která se má skrýt
     */
    public static void hideCommunication(AbstractCommunication communication) {
        CommunicationFrame validInstance = getInstance();
        validInstance.removeCommunication(communication);
    }
   
    /**
     * Přidá objekt třídy {@link CommunicationListener}, který zpracovává události oznamování
     * příchozích paketů.
     * @param listener Listener, který se má přidat
     */
    public static void addCommunicationListener(CommunicationListener listener) {
        getInstance().showListeners.add(listener);
    }

    /**
     * Odebere objekt třídy {@link CommunicationListener}, který zpracovával události oznamování
     * příchozích paketů.
     * @param listener Listener, který se má odebrat
     */
    public static void removeCommunicationListener(CommunicationListener listener) {
        getInstance().showListeners.remove(listener);
    }
   
   
    /**
     * Zobrazí vizitku daného uživatele.
     * @param JID Jabber ID uživatele
     */
    public static void showVCardDialog(String JID) {
        if(instance == null) return;

        VCardDialog vc = new VCardDialog(instance, JID);
        vc.setLocationRelativeTo(instance);
        vc.setVisible(true);
    }
   
    /**
     * Pošle oznámení všem komunikacím o příchozím paketu.
     * @param packet Příchozí paket
     * @see CommunicationListener#communicationNotified(java.util.Collection)
     */
    public static void notifyPacket(Packet packet) {
        getInstance().fireCommunicationNotifiedEvent(packet);
    }

    /**
     * Zavře a zničí aktuální validní instanci tohoto okna (používá se při odhlášení)
     */
    public static void destroy() {
        CommunicationFrame validInstance = getInstance();       
        validInstance.processWindowEvent(new WindowEvent(validInstance, WindowEvent.WINDOW_CLOSING));
        instance = null;
    }
   
    /** End of static methods */
    /** Private fields and methods */
   
    private Collection<CommunicationListener> showListeners;
    private ArrayList<AbstractCommunication> showedCommunications;
    private JTabbedPane commTabs;
   
    /*
    public void communicationShowed(AbstractCommunication communication) {
        // všechny panely, které zobrazují nepřečtenou zprávu, která se teď zobrazila, změní ikonku.
        // TODO panely, které zorazují ještě jinou nepřečtenou zprávu, by změnit ikonku neměly.
       
        // TODO prozatimní řešení: vsechny panely daneho JID zmeni ikonku na normal
        // návrh: panely budou mít flag "nepřečtená komunikace", a budou se ovládat metodou
        // "komunikace přečtena" s argumentem toho, co bylo přečtený. sami pak změní svojí ikonku podle toho.
        // dobře se to hrotí pomocí ID paketů. komunikace bude mít přístup k seznamu nepřečtenejch ídéček.
       
        // tohle teda nakonec vůbec nebude implementovat communicationlistener
       
        // nepřečtený ID budou uložený kde?
       
       
        for(int i = 0; i < commTabs.getTabCount(); ++i) {
            AbstractCommunicationPanel panel = (AbstractCommunicationPanel)commTabs.getComponentAt(i);

            if((panel instanceof ChatPanel) || (panel instanceof PaintPanel)) {
                if(panel.getJID().equalsIgnoreCase(JID)) {
                    ChatTabComponent tab = (ChatTabComponent) panel.getTabComponent();
                    tab.setMessageNotifyIcon(false);
                }
            }
        }
    }
    */
   
    private boolean isWindowVisible() {
        boolean visible = getExtendedState() != ICONIFIED &&
                isFocused();
        return visible;
    }
           
    private boolean isMessageVisible(Message message) {
        // vrátí true, když je vidět komunikace, ve která chytí tuto zprávu.
       
        AbstractCommunication comm = getSelectedCommunication();
       
        boolean visible = isWindowVisible() &&
                comm != null &&
                comm.getAcceptedMessagesFilter().accept(message);
        return visible;
    }
       
    private AbstractCommunication getSelectedCommunication() {
        int index = commTabs.getSelectedIndex();
       
        if(index == -1) return null;
       
        return showedCommunications.get(index);
    }
           
    private void selectTabAt(int index) {
        commTabs.setSelectedIndex(index);       
    }
   
    private void removeCommunication(AbstractCommunication communication) {
        commTabs.remove(communication.getComponent());
        showedCommunications.remove(communication);
       
        if(commTabs.getTabCount() == 0) {
            dispose();
        }
    }
   
    private int addCommunication(final AbstractCommunication communication) {
        if(!showedCommunications.contains(communication)) {
            showedCommunications.add(communication);
           
            final Component component = communication.getComponent();
            final ClosableTabComponent tab = communication.getTabComponent();
           
            commTabs.addTab(communication.getJID(), component);
           
            int index = commTabs.indexOfComponent(component);

            if(index != showedCommunications.indexOf(communication)) {
                throw new AssertionError("Tab-Comm Index consistency corrupted.");
            }
           
            commTabs.setTabComponentAt(index, tab);  
           
            tab.addCloseActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    hideCommunication(communication);
                    tab.removeCloseActionListener(this);
                }
            });
        }

        return showedCommunications.indexOf(communication);
    }
   
    private void fireCommunicationShowedEvent() {
        if(!isWindowVisible()) return;
       
        AbstractCommunication communication = getSelectedCommunication();
        if(communication == null) return;
       
        final CommunicationManager manager = CommunicationManager.getInstance();
       
        manager.communicationShowed(communication);
       
        for(CommunicationListener list : showListeners) {
            list.communicationShowed(manager.getNotifiedCommunications());
        }
    }
   
    private void fireCommunicationNotifiedEvent(Packet packet) {
        if(!(packet instanceof Message)) return;
       
        // je ta zpráva vidět? tzn. okno má focus, neni ICONIFIED a selectedIndex ukazuje na komunikaci, který to přijde
        Message message = (Message) packet;
       
        // pokud zpráva neni vidět, vystřelim
        if(!isMessageVisible(message)) {
            final CommunicationManager manager = CommunicationManager.getInstance();
           
            manager.packetNotified(packet);
           
            for(CommunicationListener list : showListeners) {
                list.communicationNotified(manager.getNotifiedCommunications());
            }           
        }
    }
   
    private void initComponents() {       
        ResourceBundle rb = Program.getStringsBundle();
        setMinimumSize(MIN_SIZE);

        int extendedState = UserPreferences.getChatFrameState();
        if(extendedState == NORMAL)
            setBounds(UserPreferences.getChatFrameLocation());
        else
            setExtendedState(UserPreferences.getChatFrameState());
       
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                UserPreferences.setChatFrameLocation(CommunicationFrame.this.getBounds());
                UserPreferences.setChatFrameState(CommunicationFrame.this.getExtendedState());
               
                // zavřít všechny komunikace - ani to neni potřeba přece!
                //showedCommunications.clear();               
            }
        });

        setTitle(rb.getString("chatTitle"));
        ArrayList<Image> icons = new ArrayList<Image>(2);
        icons.add(Program.getImage("icons/icon16.png"));
        icons.add(Program.getImage("icons/icon32.png"));
        setIconImages(icons);

        commTabs = new JTabbedPane();
        commTabs.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                fireCommunicationShowedEvent();
            }
        });

        addWindowFocusListener(new WindowAdapter() {
            @Override
            public void windowGainedFocus(WindowEvent e) {
                fireCommunicationShowedEvent();
            }
        });
       
        add(commTabs);
    }
   
   
    private CommunicationFrame() {
        this.showedCommunications = new ArrayList<AbstractCommunication>(15);
        this.showListeners = new ArrayList<CommunicationListener>(15);
       
        initComponents();
    }
}
TOP

Related Classes of cz.cuni.mff.inetpaint.communications.CommunicationFrame

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.