001    /*
002        Copyright (C) 2003 Adam Olsen
003        This program is free software; you can redistribute it and/or modify
004        it under the terms of the GNU General Public License as published by
005        the Free Software Foundation; either version 1, or (at your option)
006        any later version.
007        This program is distributed in the hope that it will be useful,
008        but WITHOUT ANY WARRANTY; without even the implied warranty of
009        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
010        GNU General Public License for more details.
011        You should have received a copy of the GNU General Public License
012        along with this program; if not, write to the Free Software
013        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
014      */
015    package com.valhalla.jbother;
016    
017    import java.io.*;
018    import java.net.URL;
019    import java.util.*;
020    import javax.swing.*;
021    import java.awt.*;
022    import java.awt.event.*;
023    import javax.swing.event.*;
024    
025    import com.valhalla.gui.*;
026    import com.valhalla.settings.*;
027    
028    /**
029     * Replaces different emote symbols with images
030     *
031     * @author     Adam Olsen
032     * @created    October 30, 2004
033     * @version    1.0
034     */
035    public class Emoticons
036    {
037            private String imageDir;
038            private static Emoticons instance;
039            private Properties map;
040    
041            private String themeDir;
042            private InputStream emoticonStream;
043            private boolean switched = false;
044    
045            /**
046             * Default constructor - opens the emoticon theme dir and reads in the
047             * data file containing the different emote definitions
048             */
049            private Emoticons() { }
050    
051            /**
052             * @return    the Emoticons singleton
053             */
054            public static Emoticons getInstance()
055            {
056                    if( instance == null )
057                    {
058                            instance = new Emoticons();
059                    }
060                    if( !instance.switched )
061                    {
062                            instance.switchTheme( Settings.getInstance().getProperty( "emoticonTheme" ) );
063                    }
064                    return instance;
065            }
066    
067            /**
068             * Switches the emoticon theme
069             *
070             * @param  theme  the theme to switch to
071             */
072            public void switchTheme( String theme )
073            {
074                    switched = true;
075    
076                    map = new Properties();
077    
078                    themeDir = theme;
079                    if( themeDir == null )
080                    {
081                            themeDir = "default";
082                    }
083    
084                    emoticonStream = getClass().getClassLoader().getResourceAsStream( "imagethemes/emoticons/" + themeDir + '/' + "index.dat" );
085    
086                    if( emoticonStream == null )
087                    {
088                            com.valhalla.Logger.debug( "Bad Emoticon File" );
089                            return;
090                    }
091    
092                    InputStreamReader in = new InputStreamReader( emoticonStream );
093                    BufferedReader reader = new BufferedReader( in );
094    
095                    String line;
096                    String nameValue[] = new String[2];
097    
098                    try
099                    {
100    
101                            while( ( line = reader.readLine() ) != null )
102                            {
103                                    nameValue = line.split( " " );
104                                    if( nameValue[0] == null || nameValue[1] == null )
105                                    {
106                                            break;
107                                    }
108    
109                                    map.setProperty( nameValue[0], nameValue[1] );
110                            }
111    
112                            in.close();
113                            // close the file
114                    }
115                    catch( IOException e )
116                    {
117                            com.valhalla.Logger.debug( "Couldn't read emoticon file." );
118                    }
119            }
120    
121            /**
122             * Replaces the different symbols with the images defined in the emote data file
123             *
124             * @param  text  the text to modify
125             * @return       the modified text
126             */
127            public String replaceIcons( String text )
128            {
129                    if( emoticonStream == null )
130                    {
131                            return text;
132                    }
133    
134                    Iterator iterator = map.keySet().iterator();
135    
136                    while( iterator.hasNext() )
137                    {
138                            String symbol = (String)iterator.next();
139    
140                            symbol = symbol.replaceAll( "<", "<" );
141                            symbol = symbol.replaceAll( ">", ">" );
142    
143                            String image = map.getProperty( symbol );
144                            String imageLocation = "imagethemes/emoticons/" + themeDir + "/" + image;
145    
146                            int loc = -5;
147    
148                            while( ( loc = text.indexOf( " " + symbol + " " ) ) != -1 )
149                            {
150                                    String icon = appendIcon( imageLocation );
151                                    text = text.substring( 0, loc ) + icon + text.substring( loc + symbol.length() + 1 );
152                            }
153                    }
154    
155                    return text;
156            }
157    
158            /**
159             * Appends an image tag onto a StringBuffer
160             *
161             * @param  imageLocation  the location of the image
162             * @return                the string with the appended icon
163             */
164            private String appendIcon( String imageLocation )
165            {
166                    URL imageUrl = getClass().getClassLoader().getResource( imageLocation );
167    
168                    if( imageUrl == null )
169                    {
170                            com.valhalla.Logger.debug( "No emoticon image found for " + imageLocation );
171                            return "";
172                    }
173    
174                    ImageIcon iconTest = new ImageIcon( imageUrl );
175                    int width = iconTest.getIconWidth();
176                    int height = iconTest.getIconHeight();
177    
178                    return " <img border='0' width='" + width + "' height='" +
179                            height + "' src='" + imageUrl + "'>  ";
180            }
181    
182            /**
183             * Shows a small window displaying all available emoticons.
184             *
185             * @param  window     the parent window
186             * @param  component  the Component to display this frame over
187             * @param  area       the text area that the emoticons will be placed on when the user clicks an image
188             */
189            public void displayEmoticonChooser( JFrame window, Component component, JTextArea area )
190            {
191                    JDialog dialog = new JDialog( window );
192                    JPanel panel = (JPanel)dialog.getContentPane();
193                    panel.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) );
194                    panel.setLayout( new BoxLayout( panel, BoxLayout.Y_AXIS ) );
195                    EmoteClickListener listener = new EmoteClickListener( dialog, area );
196    
197                    int columns = 6;
198                    int current = 0;
199                    JPanel cPanel = null;
200    
201                    Iterator i = map.keySet().iterator();
202    
203                    Properties displayed = new Properties();
204                    while( i.hasNext() )
205                    {
206                            String symbol = (String)i.next();
207    
208                            if( symbol.equals( "(-)(-)" ) )
209                            {
210                                    continue;
211                            }
212    
213                            String image = map.getProperty( symbol );
214    
215                            if( displayed.getProperty( image ) != null ) continue;
216                            displayed.setProperty( image, "True" );
217    
218                            String imageLocation = "imagethemes/emoticons/" + themeDir + "/" + image;
219                            ImageIcon icon = Standard.getIcon( imageLocation );
220                            if( icon == null )
221                            {
222                                    continue;
223                            }
224    
225                            if( current > columns )
226                            {
227                                    panel.add( cPanel );
228                                    current = 0;
229                            }
230    
231                            if( current == 0 )
232                            {
233                                    cPanel = new JPanel();
234                                    cPanel.setLayout( new BoxLayout( cPanel, BoxLayout.X_AXIS ) );
235                            }
236    
237                            JLabel label = new JLabel( icon );
238                            label.setName( symbol );
239                            label.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) );
240                            label.addMouseListener( listener );
241                            if( icon != null )
242                            {
243                                    cPanel.add( label );
244                            }
245                            current++;
246                    }
247    
248                    dialog.pack();
249                    dialog.setLocationRelativeTo( component );
250                    dialog.setVisible( true );
251                    dialog.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
252            }
253    
254            /**
255             *  Listens for an emoticon to get clicked
256             *
257             * @author     synic
258             * @created    October 30, 2004
259             */
260            class EmoteClickListener extends MouseAdapter
261            {
262                    JDialog dialog;
263                    JTextArea area;
264    
265                    /**
266                     *Constructor for the EmoteClickListener object
267                     *
268                     * @param  dialog  the emote dialog that called this listener
269                     * @param  area    the textarea to append the emote symbol to
270                     */
271                    public EmoteClickListener( JDialog dialog, JTextArea area )
272                    {
273                            this.dialog = dialog;
274                            this.area = area;
275                    }
276    
277                    /**
278                     * Called by the mouse listener
279                     *
280                     * @param  e  the mouse event
281                     */
282                    public void mouseReleased( MouseEvent e )
283                    {
284                            dialog.dispose();
285                            JLabel label = (JLabel)e.getSource();
286                            String symbol = label.getName();
287                            area.setText( area.getText() + symbol + " " );
288                            area.grabFocus();
289                    }
290            }
291    }
292