001/* 002 * $Source: /cvsroot2/open/projects/WebARTS/ca/bc/webarts/tools/X10Buttons.java,v $ 003 * $Name: $ 004 * $Revision: 563 $ 005 * $Date: 2012-11-03 19:28:37 -0700 (Sat, 03 Nov 2012) $ 006 * $Locker: $ 007 */ 008/* 009 * X10Buttons -- A simple Panel control pad that lists the available X10 010 * devices and house codes and calls the required X10 call. 011 * 012 * Copyright (C) 2003 WebARTS Design, North Vancouver Canada 013 * http://www.webarts.bc.ca 014 * 015 * This program is free software; you can redistribute it and/or modify 016 * it under the terms of Version 2 of the GNU General Public License as 017 * published by the Free Software Foundation. 018 * 019 * This program is distributed in the hope that it will be useful, 020 * but WITHOUT ANY WARRANTY; without even the implied warranty of 021 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 022 * GNU General Public License for more details. 023 * 024 * You should have received a copy of the GNU General Public License 025 * along with this program; if not, write to the Free Software 026 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 027 */ 028package ca.bc.webarts.tools; 029 030import ca.bc.webarts.widgets.ColouredLabel; 031import ca.bc.webarts.widgets.JToggleButton; 032import ca.bc.webarts.widgets.Util; 033 034//import com.jpeterson.x10.SendX10; 035import javax.comm.NoSuchPortException; 036 037import javax.comm.PortInUseException; 038 039import java.awt.BorderLayout; 040import java.awt.Color; 041import java.awt.Dimension; 042import java.awt.FlowLayout; 043import java.awt.Font; 044import java.awt.GridLayout; 045import java.awt.event.ActionEvent; 046import java.awt.event.ActionListener; 047import java.awt.event.MouseAdapter; 048import java.awt.event.MouseEvent; 049import java.awt.event.MouseListener; 050import java.awt.event.MouseMotionAdapter; 051import java.io.File; 052import javax.swing.BorderFactory; 053import javax.swing.ButtonGroup; 054import javax.swing.ImageIcon; 055import javax.swing.JButton; 056import javax.swing.JCheckBox; 057import javax.swing.JPopupMenu; 058import javax.swing.JRadioButton; 059import javax.swing.JSpinner; 060import javax.swing.JWindow; 061import javax.swing.SpinnerListModel; 062import javax.swing.border.BevelBorder; 063import javax.swing.border.EmptyBorder; 064 065import kiwi.ui.KButton; 066import kiwi.ui.KPanel; 067 068import x10.FireCracker; 069import x10.X10Command; 070 071 072/** 073 * A simple window widget that holds a bunch of buttons that directly turn an 074 * X10 device on or off. This app requires a few other libraries: webarts, and 075 * kiwi java libraries as well as some x10 devices and a X10 java 076 * implementation on your system. 077 * 078 * @author tgutwin 079 */ 080public class X10Buttons extends JWindow implements ActionListener 081{ 082 083 // Colours 084 /** Constant holding the users file seperator. ("/" or "\") */ 085 private final static String SYSTEM_FILE_SEPERATOR = File.separator; 086 087 /** Description of the Field */ 088 private final static String DEFAULT_TRANSMITTER = 089 "com.jpeterson.x10.module.CM11A"; 090 /** A Class holder for its name (used in Logging). */ 091 private static String className_ = "X10Buttons"; 092 093 /** The colour used for all panels except the display area. */ 094 static Color mainBackColour_ = new Color( 100, 180, 245 ); 095 /** The colour used to back the display area. */ 096 static Color displayBackColour_ = Color.black; 097 /** The display area text colour. */ 098 static Color displayTextColour_ = mainBackColour_.brighter(); 099 100 /** The Main Popup menu */ 101 static JPopupMenu mainMenu = new JPopupMenu( className_ + " Main Menu" ); 102 103 /** Popup menu Mouse Listener. */ 104 static MouseListener popupListener_ = 105 new MouseAdapter() 106 { 107 108 public void mousePressed( MouseEvent e ) 109 { 110 maybeShowPopup( e ); 111 } 112 113 114 public void mouseReleased( MouseEvent e ) 115 { 116 maybeShowPopup( e ); 117 } 118 119 120 private void maybeShowPopup( MouseEvent e ) 121 { 122 if ( e.isPopupTrigger() ) 123 { 124 mainMenu.show( e.getComponent(), e.getX(), e.getY() ); 125 } 126 } 127 }; 128 /** The wrapper panel holding all in this JWindow. */ 129 KPanel dragableMiniViewPanel = new KPanel(); 130 /** The Button area wrapper inside the dragableMiniViewPanel. */ 131 KPanel miniViewPanel = new KPanel(); 132 /** The Control area at the top of the window. */ 133 KPanel miniViewWindowControlPanel = new KPanel(); 134 /** The window header / draggable button. */ 135 KButton miniDragButton = new KButton( "" ); 136 /** The button to Min/Max this mini app window */ 137 KButton miniButtonView_ = new KButton( "" ); 138 /** The button to close this mini app window. */ 139 KButton miniButtonClose_ = new KButton( "" ); 140 /** The panel holding the X10 buttons */ 141 KPanel miniButtonPanel_ = new KPanel(); 142 /** The panel holding the on/off toggle button */ 143 KPanel onOffPanel_ = new KPanel(); 144 /** The object holding the min/max icon. */ 145 ImageIcon iconMiniView_ = new ImageIcon(); 146 /** The object holding the close icon. */ 147 ImageIcon iconMiniClose_ = new ImageIcon(); 148 /** The object holding the dim icon. */ 149 ImageIcon iconDim_ = new ImageIcon(); 150 /** The object holding the bright icon. */ 151 ImageIcon iconBright_ = new ImageIcon(); 152 /** The X amount the current window was just dragged. */ 153 private int XDifference_; 154 /** The Y amount the current window was just dragged. * */ 155 private int YDifference_; 156 /** the x position of the mini window. * */ 157 private int xPosition_ = 100; 158 /** the y position of the mini window. * */ 159 private int yPosition_ = 100; 160 /** the x position of the app window. * */ 161 private int appXpos = -1; 162 /** the y position of the app window. * */ 163 private int appYpos = -1; 164 /** the number of rows of buttons to display in the app window. * */ 165 private int displayRows_ = 9; 166 /** the number of columns of buttons to display in the app window. * */ 167 private int displayCols_ = 2; 168 /** Class var holding the number of x10 buttons * */ 169 private int numButtons_ = 16; 170 /** Description of the Field */ 171 private String portDescriptor_ = "/dev/ttyS0"; 172 173 /** Holds the Hose code values for the House Code Spinner * */ 174 //private String [] houseCodes_ = {" F "," E "," D "," C "," B "," A "}; 175 private String[] houseCodes_ = {" A ", " B ", " C ", " D ", " E ", " F ", " G ", 176 " H ", " I ", " J ", " K ", " L ", " M ", " N ", 177 " O ", " P "}; 178 179 /** The Spinner model used in the Hose Code Spinner * */ 180 private SpinnerListModel spinnerModel_ = new SpinnerListModel( houseCodes_ ); 181 /** Description of the Field */ 182 private JSpinner houseSpinner_ = new JSpinner( spinnerModel_ ); 183 184 185 /** The dir where the images are located. */ 186 String IMAGE_DIR = "." + SYSTEM_FILE_SEPERATOR + 187 "images" + SYSTEM_FILE_SEPERATOR; 188 189 /** The Extension for the button images * */ 190 String buttonImageExtension_ = ".gif"; 191 192 /** The Extension for the button images * */ 193 String buttonImagepath_ = "/images/org/javalobby/icons/20x20/Circle_"; 194 195 /** This is this apps draggable - Title bar. */ 196 ColouredLabel miniDragLabel = new ColouredLabel( 197 displayBackColour_, 198 displayTextColour_, 199 new Font( "Arial", Font.PLAIN, 9 ), 200 "X10 Buttons" ); 201 202 /** An array of the x10 buttons. */ 203 KButton[] x10controlButton_ = new KButton[numButtons_]; 204 205 /** A dim button. */ 206 KButton x10DimButton_ = new KButton( "" ); 207 208 /** A dim button. */ 209 KButton x10BrightButton_ = new KButton( "" ); 210 211 /** The toggle controlling if the next X10 command will be on or Off. */ 212 JToggleButton onOffToggle_ = new JToggleButton(); 213 214 /** 215 * Listener for when the mouse is pressed on the fake window frame title bar 216 * button. 217 */ 218 MouseAdapter miniViewMouseListener = 219 new MouseAdapter() 220 { 221 /** 222 * the impl for a mouse press. 223 * 224 * @param e Description of Parameter 225 * @since 226 */ 227 public void mousePressed( MouseEvent e ) 228 { 229 XDifference_ = e.getX(); 230 YDifference_ = e.getY(); 231 } 232 }; 233 234 /** Listener for changing the location of this window. * */ 235 MouseMotionAdapter dragMiniViewMotionListener = 236 new MouseMotionAdapter() 237 { 238 /** 239 * Implementation of the mouse dragged event handler. 240 * 241 * @param e Description of Parameter 242 * @since 243 */ 244 public void mouseDragged( MouseEvent e ) 245 { 246 setLocation( xPosition_ + ( e.getX() - XDifference_ ), 247 yPosition_ + ( e.getY() - YDifference_ ) ); 248 xPosition_ = xPosition_ + ( e.getX() - XDifference_ ); 249 yPosition_ = yPosition_ + ( e.getY() - YDifference_ ); 250 } 251 }; 252 253 254 /** Constructor * */ 255 X10Buttons() 256 { 257 initWindowPanels(); 258 pack(); 259 setLocation( xPosition_, yPosition_ ); 260 setVisible( true ); 261 toFront(); 262 } 263 264 265 /** Constructor * */ 266 X10Buttons(boolean invisible) 267 { 268 if (!invisible) 269 { 270 initWindowPanels(); 271 pack(); 272 setLocation( xPosition_, yPosition_ ); 273 setVisible( true ); 274 toFront(); 275 } 276 } 277 278 279 /** 280 * The main program for the X10Buttons class. 281 * 282 * @param arg The command line arguments 283 */ 284 public static void main( String[] arg ) 285 { 286 System.out.println( "Starting X10Buttons " ); 287 X10Buttons instance = new X10Buttons(); 288 } 289 290 291 /** 292 * Handles all the Actions originating from the Control Buttons. 293 * 294 * @param e The action event to handle 295 */ 296 public void actionPerformed( ActionEvent e ) 297 { 298 final String methodName = className_ + ": actionPerformed()"; 299 300 JButton pressedButton = (JButton)( e.getSource() ); 301 ImageIcon buttonIcon = (ImageIcon)pressedButton.getIcon(); 302 String command = ""; 303 int commandButtonNumber = 0; 304 boolean dim = false; 305 boolean bright = false; 306 if ( buttonIcon != null ) 307 { 308 command = buttonIcon.getDescription(); 309 //System.out.println("Action From: "+command); 310 if ( command.trim().equals( "Close " + className_ ) ) 311 { 312 //System.out.println("Close App"); 313 //stop(); 314 //log_.close(); 315 System.exit( 0 ); 316 } 317 else if ( command.trim().equals( "dim" ) ) 318 { 319 System.out.println( "dim" ); 320 dim = true; 321 } 322 else if ( command.trim().equals( "bright" ) ) 323 { 324 System.out.println( "bright" ); 325 bright = true; 326 } 327 else 328 { 329 commandButtonNumber = 330 Integer.parseInt( ( command.substring( command.length() - 2 ) ).trim() ); 331 //System.out.println("Button ICON Pressed: "+commandButtonNumber); 332 } 333 } 334 else 335 { 336 command = pressedButton.getToolTipText(); 337 commandButtonNumber = 338 Integer.parseInt( ( command.substring( command.length() - 2 ) ).trim() ); 339 //System.out.println("Button Pressed: "+commandButtonNumber); 340 } 341 String x10HouseCode = ( (String)houseSpinner_.getValue() ).trim().toUpperCase(); 342 String x10DeviceNumber = String.valueOf( commandButtonNumber ); 343 String x10Command = ( onOffToggle_.getState() ? "on" : "off" ); 344 if ( dim || bright ) 345 { 346 x10Command = ( dim ? "dim" : "bright" ); 347 x10DeviceNumber = ""; 348 } 349 sendX10Command( x10Command, x10HouseCode, x10DeviceNumber ); 350 } 351 352 353 /** 354 * Abstracts the actual sending of the X10 Command. 355 * 356 * @param x10Command This is either 'on' or 'off' 357 * @param x10HouseCode send an uppercase house code 358 * @param x10DeviceNumber send the device nuymber as a string... ie. 'String.valueOf( 1 );' 359 */ 360 public void sendX10Command( String x10Command, 361 String x10HouseCode, 362 String x10DeviceNumber ) 363 { 364 // Now disable all buttons and send the X10 command 365 enableDeviceButtons( false ); 366 367 FireCracker fc = new FireCracker(); 368 try 369 { 370 System.out.println( "Connecting to FireCracker on port " + portDescriptor_ ); 371 372 fc.openPort( portDescriptor_ ); 373 } 374 catch ( PortInUseException piux ) 375 { 376 System.out.println( "Specified port in use by application: " + 377 piux.currentOwner ); 378 return; 379 } 380 catch ( NoSuchPortException nspx ) 381 { 382 System.out.println( "Specified port not recognized: " + portDescriptor_ + "\n" ); 383 //usage(); 384 } 385 386 // Give the device time to power up? 387 // It's not very reliable without this delay. 388 Util.sleep( 400 ); 389 390 X10Command xcmd = null; 391 //System.out.println("Preparing:"+ x10HouseCode.charAt(0)+Integer.parseInt(x10DeviceNumber)+" "+x10Command); 392 if ( x10Command.equals( "on" ) ) 393 { 394 xcmd = X10Command.makeOnCommand( x10HouseCode.charAt( 0 ), 395 Integer.parseInt( x10DeviceNumber ) ); 396 } 397 else if ( x10Command.equals( "off" ) ) 398 { 399 xcmd = X10Command.makeOffCommand( x10HouseCode.charAt( 0 ), 400 Integer.parseInt( x10DeviceNumber ) ); 401 } 402 else if ( x10Command.equals( "dim" ) ) 403 { 404 xcmd = X10Command.makeDimCommand( x10HouseCode.charAt( 0 ) ); 405 } 406 else if ( x10Command.equals( "bright" ) ) 407 { 408 xcmd = X10Command.makeBrightCommand( x10HouseCode.charAt( 0 ) ); 409 } 410 System.out.println( "Sending:" + x10HouseCode.charAt( 0 ) + x10DeviceNumber + " " + x10Command ); 411 fc.sendCommand( xcmd ); 412 413 System.out.println( "\nDisconnecting from FireCracker" ); 414 fc.closePort(); 415 416 //String [] x10Args = {x10Command, x10HouseCode, x10DeviceNumber}; 417 //SendX10 sx = new SendX10("/dev/ttyS1", DEFAULT_TRANSMITTER ); 418 //sx.transmit(0, x10Args); 419 420 //Util.sleep(2500); 421 enableDeviceButtons( true ); 422 } 423 424 425 /** 426 * Creates a button using a Icon with a preset imagename 427 * 428 * @param controlNumber Description of the Parameter 429 * @return Description of the Return Value 430 */ 431 private KButton createIconButton( int controlNumber ) 432 { 433 KButton retVal = new KButton( String.valueOf( controlNumber ) ); 434 ImageIcon tempIcon; 435 tempIcon = 436 new ImageIcon( 437 Util.loadImage( buttonImagepath_ + controlNumber + buttonImageExtension_ ), 438 "X10 Device " + controlNumber ); 439 440 retVal.setIcon( tempIcon ); 441 retVal.setPreferredSize( 442 new Dimension( tempIcon.getIconWidth() + 3, tempIcon.getIconHeight() + 3 ) ); 443 retVal.setToolTipText( "X10 Device #" + controlNumber ); 444 retVal.addActionListener( this ); 445 retVal.setBorder( BorderFactory.createBevelBorder( 446 BevelBorder.RAISED ) ); 447 return retVal; 448 } 449 450 451 /** 452 * Creates a button using only text inside 453 * 454 * @param controlNumber Description of the Parameter 455 * @return Description of the Return Value 456 */ 457 private KButton createButton( int controlNumber ) 458 { 459 KButton retVal = new KButton( String.valueOf( controlNumber ) ); 460 // TO_DO: Add a custom tooltip naming the device on the end of this num 461 retVal.setToolTipText( "X10 Device # " + controlNumber ); 462 retVal.addActionListener( this ); 463 retVal.setBorder( BorderFactory.createBevelBorder( 464 BevelBorder.RAISED ) ); 465 return retVal; 466 } 467 468 469 /** Inits the gui widgets * */ 470 private void initWindowPanels() 471 { 472 /* 473 * Init Window dressing 474 */ 475 String miniViewFilename = "/images/miniViewButtonImage.jpg"; 476 String miniCloseFilename = "/images/miniCloseButtonImage.jpg"; 477 String x10DimFilename = "/images/Down24.gif"; 478 String x10BrightFilename = "/images/Up24.gif"; 479 480 // the dragabler title bar button 481 miniDragButton.setMaximumSize( new Dimension( 100, 16 ) ); 482 miniDragButton.setBorder( BorderFactory.createRaisedBevelBorder() ); 483 miniDragButton.setBorderPainted( true ); 484 miniDragButton.setDoubleBuffered( true ); 485 miniDragButton.add( miniDragLabel ); 486 miniDragButton.addMouseListener( miniViewMouseListener ); 487 miniDragButton.addMouseMotionListener( dragMiniViewMotionListener ); 488 miniDragButton.addMouseListener( popupListener_ ); 489 490 // the mini close button 491 iconMiniClose_ = 492 new ImageIcon( Util.loadImage( miniCloseFilename ), "Close " + className_ ); 493 miniButtonClose_.addActionListener( this ); 494 miniButtonClose_.setIcon( iconMiniClose_ ); 495 miniButtonClose_.setToolTipText( "Close " + className_ ); 496 miniButtonClose_.setPreferredSize( new Dimension( 16, 16 ) ); 497 miniButtonClose_.setBorder( new EmptyBorder( 0, 0, 0, 0 ) ); 498 miniButtonClose_.setBorderPainted( false ); 499 miniButtonClose_.setDoubleBuffered( true ); 500 501 // the mini Dim button 502 iconDim_ = 503 new ImageIcon( Util.loadImage( x10DimFilename ), "dim" ); 504 x10DimButton_.addActionListener( this ); 505 x10DimButton_.setIcon( iconDim_ ); 506 x10DimButton_.setToolTipText( "dim" ); 507 x10DimButton_.setPreferredSize( new Dimension( 16, 16 ) ); 508 x10DimButton_.setBorder( new EmptyBorder( 0, 0, 0, 0 ) ); 509 x10DimButton_.setBorderPainted( false ); 510 x10DimButton_.setDoubleBuffered( true ); 511 512 // the mini Dim button 513 iconBright_ = 514 new ImageIcon( Util.loadImage( x10BrightFilename ), "bright" ); 515 x10BrightButton_.addActionListener( this ); 516 x10BrightButton_.setIcon( iconBright_ ); 517 x10BrightButton_.setToolTipText( "bright" ); 518 x10BrightButton_.setPreferredSize( new Dimension( 16, 16 ) ); 519 x10BrightButton_.setBorder( new EmptyBorder( 0, 0, 0, 0 ) ); 520 x10BrightButton_.setBorderPainted( false ); 521 x10BrightButton_.setDoubleBuffered( true ); 522 523 // the Title Area Panel 524 miniViewWindowControlPanel.add( miniDragButton, BorderLayout.CENTER ); 525 miniViewWindowControlPanel.add( miniButtonClose_, BorderLayout.EAST ); 526 miniViewWindowControlPanel.setDoubleBuffered( true ); 527 miniViewWindowControlPanel.addMouseListener( popupListener_ ); 528 529 // the Button Panel 530 miniButtonPanel_.setLayout( new GridLayout( displayRows_, displayCols_, 1, 1 ) ); 531 miniButtonPanel_.setBorder( new EmptyBorder( 0, 0, 0, 0 ) ); 532 miniButtonPanel_.addMouseListener( popupListener_ ); 533 for ( int i = 0; i < numButtons_; i++ ) 534 { 535 x10controlButton_[i] = createButton( i + 1 ); 536 miniButtonPanel_.add( x10controlButton_[i] ); 537 } 538 miniButtonPanel_.add( x10BrightButton_ ); 539 miniButtonPanel_.add( x10DimButton_ ); 540 541 onOffPanel_.setBorder( new EmptyBorder( 0, 0, 0, 0 ) ); 542 houseSpinner_.setValue( houseCodes_[0] ); 543 onOffPanel_.add( houseSpinner_ ); 544 onOffPanel_.add( onOffToggle_ ); 545 546 // now stitch it all together 547 dragableMiniViewPanel.setDoubleBuffered( true ); 548 dragableMiniViewPanel.setLayout( new BorderLayout( 0, 0 ) ); 549 dragableMiniViewPanel.add( miniViewWindowControlPanel, BorderLayout.NORTH ); 550 dragableMiniViewPanel.add( miniButtonPanel_, BorderLayout.CENTER ); 551 dragableMiniViewPanel.add( onOffPanel_, BorderLayout.SOUTH ); 552 getContentPane().add( dragableMiniViewPanel ); 553 } 554 555 556 /** 557 * Description of the Method 558 * 559 * @param state Description of the Parameter 560 */ 561 private void enableDeviceButtons( boolean state ) 562 { 563 for ( int i = 0; i < numButtons_; i++ ) 564 { 565 x10controlButton_[i].setEnabled( state ); 566 } 567 } 568} 569