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.awt.event.*; 018 019 import java.io.*; 020 import java.text.SimpleDateFormat; 021 import java.util.*; 022 import java.text.*; 023 024 import javax.swing.*; 025 import javax.swing.event.*; 026 import java.awt.*; 027 028 import com.valhalla.gui.*; 029 import com.valhalla.jbother.*; 030 import com.valhalla.jbother.jabber.BuddyStatus; 031 import com.valhalla.jbother.plugins.events.*; 032 import com.valhalla.settings.Settings; 033 034 /** 035 * Provides common tools for conversation windows (such as logging). 036 * Must be extended. 037 * 038 * @author Adam Olsen 039 * @author Yury Soldak (tail) 040 * @created October 26, 2004 041 * @version 1.0 042 * @see com.valhalla.jbother.jabber.BuddyStatus 043 */ 044 public abstract class ConversationPanel extends JPanel implements LogViewerCaller, TabFramePanel 045 { 046 private ResourceBundle resources = ResourceBundle.getBundle( "JBotherBundle", Locale.getDefault() ); 047 protected BuddyStatus buddy; 048 /** 049 * the conversation area 050 */ 051 protected ConversationArea conversationArea = new ConversationArea(); 052 053 private int oldMaximum = 0; 054 // for logging 055 private File logFile; 056 /** 057 * the log writer 058 */ 059 protected PrintWriter logOut; 060 private FileWriter fw; 061 /** 062 * the close timer 063 */ 064 protected javax.swing.Timer timer = new javax.swing.Timer( 600000, new CloseListener() ); 065 private ConversationPanel thisPointer = this; 066 /** 067 * the containing frame 068 */ 069 protected JFrame frame = null; 070 /** 071 * if the listeners have been added 072 */ 073 protected boolean listenersAdded = false; 074 075 /** 076 * Sets up the defaults in the ConversationPanel 077 * 078 * @param buddy the buddy that this window corresponds to 079 */ 080 public ConversationPanel( BuddyStatus buddy ) 081 { 082 this.buddy = buddy; 083 startLog(); 084 } 085 086 /** 087 * Listens for a right click - and displays a menu if it's caught 088 * 089 * @author Adam Olsen 090 * @created October 26, 2004 091 * @version 1.0 092 */ 093 class RightClickListener extends MouseAdapter 094 { 095 private JPopupMenu menu; 096 private JMenuItem item = new JMenuItem( resources.getString( "closeConversation" ) ); 097 private boolean containsCloseItem = false; 098 099 /** 100 *Constructor for the RightClickListener object 101 * 102 * @param menu the menu 103 */ 104 public RightClickListener( JPopupMenu menu ) 105 { 106 this.menu = menu; 107 } 108 109 /** 110 * Description of the Method 111 * 112 * @param e the event 113 */ 114 public void mousePressed( MouseEvent e ) 115 { 116 checkPop( e ); 117 } 118 119 /** 120 * @param e the mouse event 121 */ 122 public void mouseReleased( MouseEvent e ) 123 { 124 checkPop( e ); 125 } 126 127 /** 128 * @param e the mouse event 129 */ 130 public void mouseClicked( MouseEvent e ) 131 { 132 checkPop( e ); 133 } 134 135 /** 136 * @param e the mouse event 137 */ 138 public void checkPop( MouseEvent e ) 139 { 140 if( e.isPopupTrigger() ) 141 { 142 if( Settings.getInstance().getBoolean( "useTabbedWindow" ) && !containsCloseItem ) 143 { 144 containsCloseItem = true; 145 menu.add( item ); 146 item.addActionListener( 147 new ActionListener() 148 { 149 public void actionPerformed( ActionEvent e ) 150 { 151 checkCloseHandler(); 152 } 153 } ); 154 } 155 else if( !Settings.getInstance().getBoolean( "useTabbedWindow" ) && containsCloseItem ) 156 { 157 containsCloseItem = false; 158 menu.remove( item ); 159 } 160 161 // if a right click is detected, show the popup menu 162 menu.show( e.getComponent(), e.getX(), e.getY() ); 163 } 164 } 165 } 166 167 /** 168 * @return true if the TabFrame panel listeners have already been added to this panel 169 */ 170 public boolean listenersAdded() 171 { 172 return listenersAdded; 173 } 174 175 /** 176 * Sets whether or not the TabFrame panel listeners have been added 177 * 178 * @param added true if they have been added 179 */ 180 public void setListenersAdded( boolean added ) 181 { 182 this.listenersAdded = added; 183 } 184 185 /** 186 * @return the input area of this panel 187 */ 188 public Component getInputComponent() 189 { 190 return conversationArea; 191 } 192 193 /** 194 * @return the name of the tab in the TabFrame 195 */ 196 public String getPanelName() 197 { 198 if( buddy != null ) 199 { 200 return buddy.getName(); 201 } 202 else 203 { 204 return "Blank Message"; 205 } 206 } 207 208 /** 209 * @return the title of the window in the TabFrame 210 */ 211 public String getWindowTitle() 212 { 213 if( buddy != null ) 214 { 215 return buddy.getName() + " (" + buddy.getUser() + ")"; 216 } 217 else 218 { 219 return "Blank Message"; 220 } 221 } 222 223 /** 224 * @return the tooltip for this tab in the TabFrame 225 */ 226 public String getTooltip() 227 { 228 if( buddy != null ) 229 { 230 return buddy.getUser(); 231 } 232 else 233 { 234 return "Blank Message"; 235 } 236 } 237 238 /** 239 * @return the containing frame for this panel 240 */ 241 public JFrame getContainingFrame() 242 { 243 return frame; 244 } 245 246 /** 247 * @param frame the new containing frame 248 */ 249 public void setContainingFrame( JFrame frame ) 250 { 251 this.frame = frame; 252 } 253 254 /** 255 * Focuses when a Tab in the TabFrame is clicked 256 */ 257 public abstract void focusYourself(); 258 259 /** 260 * Returns the buddy status for this dialog 261 * 262 * @return the buddy passed in to the constructor 263 */ 264 public BuddyStatus getBuddy() 265 { 266 return buddy; 267 } 268 269 /** 270 * Updates the conversation font 271 * 272 * @param font the font to update to 273 */ 274 public void updateStyle( Font font ) 275 { 276 conversationArea.loadStyleSheet( font ); 277 } 278 279 /** 280 * Listens for a close event, and either makes the dialog hidden or removes it from 281 * the dialog tracker 282 * 283 * @author Adam Olsen 284 * @created October 26, 2004 285 * @version 1.0 286 */ 287 class CloseListener implements ActionListener 288 { 289 /** 290 * @param e the event 291 */ 292 public void actionPerformed( ActionEvent e ) 293 { 294 timer.stop(); 295 closeHandler(); 296 } 297 } 298 299 /** 300 * Checks to see if we are preserving messages. If so, it starts the timer, otherwise 301 * it just closes the panel 302 */ 303 public void checkCloseHandler() 304 { 305 if( Settings.getInstance().getProperty( "preserveMessages" ) == null ) 306 { 307 closeHandler(); 308 } 309 else 310 { 311 startTimer(); 312 if( !Settings.getInstance().getBoolean( "useTabbedWindow" ) ) 313 { 314 frame.setVisible( false ); 315 } 316 else 317 { 318 BuddyList.getInstance().removeTabPanel( this ); 319 } 320 } 321 } 322 323 /** 324 * Destroys the dialog, disposes the containing frame if there is one 325 * and removes the panel from the TabFrame if required. 326 */ 327 public void closeHandler() 328 { 329 closeLog(); 330 if( frame != null ) 331 { 332 frame.setVisible( false ); 333 frame.dispose(); 334 } 335 336 if( buddy != null ) 337 { 338 com.valhalla.Logger.debug( "Closing ConversationPanel for " + buddy.getUser() ); 339 buddy.setConversation( null ); 340 } 341 342 if( Settings.getInstance().getBoolean( "useTabbedWindow" ) ) 343 { 344 BuddyList.getInstance().removeTabPanel( this ); 345 } 346 347 MessageDelegator.getInstance().removePanel( this ); 348 } 349 350 /** 351 * Opens a <code>com.valhalla.jbother.LogViewerDialog</code> 352 */ 353 public void openLogWindow() 354 { 355 new LogViewerDialog( this, buddy.getUser() ); 356 } 357 358 /** 359 * Opens a log and starts it. 360 */ 361 public void startLog() 362 { 363 if( buddy == null ) return; 364 // for loggingg 365 if( Settings.getInstance().getBoolean( "keepLogs" ) ) 366 { 367 try 368 { 369 String logFileName = LogViewerDialog.getDateName() + ".log.html"; 370 String logFileDir = JBother.profileDir + File.separatorChar + "logs" + 371 File.separatorChar + this.buddy.getUser().replaceAll( "@", "_at_" ).replaceAll( "\\/", "-" ); 372 File logDir = new File( logFileDir ); 373 374 if( !logDir.isDirectory() && !logDir.mkdirs() ) 375 { 376 Standard.warningMessage( this, resources.getString( "log" ), 377 resources.getString( "couldNotCreateLogDir" ) ); 378 } 379 logFile = new File( logDir, logFileName ); 380 fw = new FileWriter( logFile, true ); 381 logOut = new PrintWriter( fw, true ); 382 } 383 catch( IOException e ) 384 { 385 com.valhalla.Logger.debug( "Could not open logfile." ); 386 } 387 } 388 } 389 390 /** 391 * Sets a message to offline (displays "this message is offline") 392 */ 393 public void setOfflineMessage() 394 { 395 } 396 397 /** 398 * Gets the time in the format [hour:minute:second] 399 * 400 * @return the time in the format [hour:minute:second] 401 */ 402 public String getDate() 403 { 404 SimpleDateFormat formatter = new SimpleDateFormat( "[HH:mm:ss]" ); 405 String date = formatter.format( new Date() ); 406 return date; 407 } 408 409 /** 410 * Recieves a message 411 * 412 * @param sbj the subject of the message 413 * @param body the message body 414 * @param resource the message resource 415 */ 416 public void recieveMessage( String sbj, String body, String resource ) 417 { 418 recieveMessage(); 419 } 420 421 /** 422 * Calls the recieved message events 423 */ 424 public void recieveMessage() 425 { 426 com.valhalla.jbother.sound.SoundPlayer.play( "recievedSound" ); 427 428 MessageDelegator.getInstance().showPanel( this ); 429 430 stopTimer(); 431 432 JFrame f = frame; 433 if( !(this instanceof MessagePanel) && Settings.getInstance().getBoolean( "useTabbedWindow" ) ) 434 { 435 f = BuddyList.getInstance().getTabFrame(); 436 BuddyList.getInstance().getTabFrame().markTab( this ); 437 } 438 else 439 { 440 if( !frame.isVisible() ) 441 { 442 frame.setVisible( true ); 443 } 444 if( Settings.getInstance().getBoolean( "focusWindow" ) ) 445 { 446 frame.toFront(); 447 } 448 } 449 450 MessageRecievedEvent event = new MessageRecievedEvent( this ); 451 com.valhalla.pluginmanager.PluginChain.fireEvent( event ); 452 } 453 454 /** 455 * Abstract createFrame - creates the containing frame of this panel 456 */ 457 public abstract void createFrame(); 458 459 /** 460 * Stops the close timer 461 */ 462 public void stopTimer() 463 { 464 timer.stop(); 465 } 466 467 /** 468 * Starts the closet imer 469 */ 470 public void startTimer() 471 { 472 timer.start(); 473 } 474 475 /** 476 * Closes the log file 477 */ 478 public void closeLog() 479 { 480 try 481 { 482 if( fw != null ) 483 { 484 fw.close(); 485 } 486 } 487 catch( IOException e ) 488 { 489 } 490 } 491 } 492