Home | Trees | Indices | Help |
|
---|
|
1 # Copyright (C) 2012 Vaadin Ltd. 2 # Copyright (C) 2012 Richard Lincoln 3 # 4 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # you may not use this file except in compliance with the License. 6 # You may obtain a copy of the License at 7 # 8 # http://www.apache.org/licenses/LICENSE-2.0 9 # 10 # Unless required by applicable law or agreed to in writing, software 11 # distributed under the License is distributed on an "AS IS" BASIS, 12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 # See the License for the specific language governing permissions and 14 # limitations under the License. 15 16 """Defines a generic button component.""" 17 18 from warnings import warn 19 20 from muntjac.ui.abstract_field import AbstractField 21 from muntjac.ui.component import Event as ComponentEvent 22 from muntjac.event.shortcut_listener import ShortcutListener 23 from muntjac.data.property import IProperty 24 25 from muntjac.terminal.gwt.client.mouse_event_details import MouseEventDetails 26 27 from muntjac.terminal.gwt.client.ui.v_button import VButton 28 29 from muntjac.event.field_events import \ 30 (BlurEvent, IBlurListener, IBlurNotifier, FocusEvent, 31 IFocusListener, IFocusNotifier) 32 3335 """Interface for listening for a L{ClickEvent} fired by a L{Component}. 36 37 @author: Vaadin Ltd. 38 @author: Richard Lincoln 39 @version: 1.1.2 40 """ 4150 51 52 _BUTTON_CLICK_METHOD = getattr(IClickListener, "buttonClick") 53 5456 """A generic button component. 57 58 @author: Vaadin Ltd. 59 @author: Richard Lincoln 60 @version: 1.1.2 61 """ 62 63 CLIENT_WIDGET = None #ClientWidget(VButton, LoadStyle.EAGER) 64410 41166 """Creates a new push button. 67 68 @param args: tuple of the form 69 - () 70 - (caption) 71 1. the Button caption 72 - (caption, listener) 73 1. the Button caption 74 2. the Button click listener 75 - (caption, target, methodName) 76 1. the Button caption 77 2. the object having the method for listening button clicks 78 3. the name of the method in target object, that receives 79 button click events 80 - (state) 81 1. the initial state of the switch-button 82 - (state, dataSource) 83 1. the initial state of the switch-button 84 2. boolean property 85 """ 86 super(Button, self).__init__() 87 88 self._switchMode = False 89 90 self._disableOnClick = False 91 92 self.clickShortcut = None 93 94 nargs = len(args) 95 if nargs == 0: 96 self.setValue(False) 97 elif nargs == 1: 98 caption, = args 99 Button.__init__(self) 100 self.setCaption(caption) 101 elif nargs == 2: 102 if isinstance(args[1], bool): 103 caption, initialState = args 104 self.setCaption(caption) 105 self.setValue(bool(initialState)) 106 self.setSwitchMode(True) 107 elif isinstance(args[1], IProperty): 108 caption, dataSource = args 109 self.setCaption(caption) 110 self.setSwitchMode(True) 111 self.setPropertyDataSource(dataSource) 112 else: 113 caption, listener = args 114 Button.__init__(self, caption) 115 if isinstance(listener, IClickListener): 116 self.addListener(listener, IClickListener) 117 else: 118 self.addCallback(listener, ClickEvent) 119 elif nargs == 3: 120 caption, target, methodName = args 121 Button.__init__(self, caption) 122 self.registerListener(ClickEvent, target, methodName) 123 else: 124 raise ValueError, 'too many arguments'125 126128 """Paints the content of this component. 129 130 @param target: 131 the PaintEvent. 132 @raise IOException: 133 if the writing failed due to input/output error. 134 @raise PaintException: 135 if the paint operation failed. 136 """ 137 super(Button, self).paintContent(target) 138 139 if self.isSwitchMode(): 140 target.addAttribute('type', 'switch') 141 142 target.addVariable(self, 'state', self.booleanValue()) 143 144 if self.isDisableOnClick(): 145 target.addAttribute(VButton.ATTR_DISABLE_ON_CLICK, True) 146 147 if self.clickShortcut is not None: 148 target.addAttribute('keycode', self.clickShortcut.getKeyCode())149 150152 """Invoked when the value of a variable has changed. Button 153 listeners are notified if the button is clicked. 154 """ 155 super(Button, self).changeVariables(source, variables) 156 157 if "disabledOnClick" in variables: 158 # Could be optimized so the button is not repainted because 159 # of this (client side has already disabled the button) 160 self.setEnabled(False) 161 162 if not self.isReadOnly() and ('state' in variables): 163 # Gets the new and old button states 164 newValue = bool( variables.get('state') ) 165 oldValue = bool( self.getValue() ) 166 167 if self.isSwitchMode(): 168 # For switch button, the event is only sent if the 169 # switch state is changed 170 if ((newValue is not None) and (newValue != oldValue) 171 and not self.isReadOnly()): 172 self.setValue(newValue) 173 if 'mousedetails' in variables: 174 self.fireClick(MouseEventDetails.deSerialize( 175 variables.get('mousedetails'))) 176 else: 177 # for compatibility with custom implementations 178 # which don't send mouse details 179 self.fireClick() 180 else: 181 # Only send click event if the button is pushed 182 if newValue: 183 if 'mousedetails' in variables: 184 self.fireClick(MouseEventDetails.deSerialize( 185 variables.get('mousedetails'))) 186 else: 187 # for compatibility with custom implementations 188 # which don't send mouse details 189 self.fireClick() 190 191 # If the button is true for some reason, release it 192 if (oldValue is None) or oldValue: 193 self.setValue(False) 194 195 if FocusEvent.EVENT_ID in variables: 196 self.fireEvent( FocusEvent(self) ) 197 198 if BlurEvent.EVENT_ID in variables: 199 self.fireEvent( BlurEvent(self) )200 201203 """Checks if it is switchMode. 204 205 @return: C{True} if it is in Switch Mode, otherwise C{False}. 206 @deprecated: the L{CheckBox} component should be used instead 207 of Button in switch mode 208 """ 209 warn('use CheckBox instead', DeprecationWarning) 210 return self._switchMode211 212214 """Sets the switchMode. 215 216 @param switchMode: 217 The switchMode to set. 218 @deprecated: the L{CheckBox} component should be used instead 219 of Button in switch mode 220 """ 221 self._switchMode = switchMode 222 if not switchMode: 223 self.setImmediate(True) 224 if self.booleanValue(): 225 self.setValue(False)226 227229 """Get the boolean value of the button state. 230 231 @return: True iff the button is pressed down or checked. 232 """ 233 value = self.getValue() 234 return False if value is None else bool(value)235 236238 """Sets immediate mode. Push buttons can not be set in 239 non-immediate mode. 240 241 @see: L{AbstractComponent.setImmediate} 242 """ 243 # Push buttons are always immediate 244 super(Button, self).setImmediate( 245 (not self.isSwitchMode()) or immediate)246 247249 """The type of the button as a property. 250 251 @see: L{IProperty.getType} 252 """ 253 return bool254 255 # Button style with no decorations. Looks like a link, acts like a button 256 # @deprecated: use L{BaseTheme.BUTTON_LINK} instead. 257 STYLE_LINK = 'link' 258 259261 """Adds the button click listener. 262 263 @param listener: 264 the Listener to be added. 265 """ 266 if (isinstance(listener, IBlurListener) and 267 (iface is None or issubclass(iface, IBlurListener))): 268 self.registerListener(BlurEvent.EVENT_ID, BlurEvent, 269 listener, IBlurListener.blurMethod) 270 271 if (isinstance(listener, IClickListener) and 272 (iface is None or issubclass(iface, IClickListener))): 273 self.registerListener(ClickEvent, listener, _BUTTON_CLICK_METHOD) 274 275 if (isinstance(listener, IFocusListener) and 276 (iface is None or issubclass(iface, IFocusListener))): 277 self.registerListener(FocusEvent.EVENT_ID, FocusEvent, 278 listener, IFocusListener.focusMethod) 279 280 super(Button, self).addListener(listener, iface)281 282284 if eventType is None: 285 eventType = callback._eventType # set by decorator 286 287 if issubclass(eventType, BlurEvent): 288 self.registerCallback(BlurEvent, callback, 289 BlurEvent.EVENT_ID, *args) 290 291 elif issubclass(eventType, ClickEvent): 292 self.registerCallback(ClickEvent, callback, None, *args) 293 294 elif issubclass(eventType, FocusEvent): 295 self.registerCallback(FocusEvent, callback, 296 FocusEvent.EVENT_ID, *args) 297 else: 298 super(Button, self).addCallback(callback, eventType, *args)299 300302 """Removes the button click listener. 303 304 @param listener: 305 the Listener to be removed. 306 """ 307 if (isinstance(listener, IBlurListener) and 308 (iface is None or issubclass(iface, IBlurListener))): 309 self.withdrawListener(BlurEvent.EVENT_ID, BlurEvent, listener) 310 311 if (isinstance(listener, IClickListener) and 312 (iface is None or issubclass(iface, IClickListener))): 313 self.withdrawListener(ClickEvent, listener, _BUTTON_CLICK_METHOD) 314 315 if (isinstance(listener, IFocusListener) and 316 (iface is None or issubclass(iface, IFocusListener))): 317 self.withdrawListener(FocusEvent.EVENT_ID, FocusEvent, listener) 318 319 super(Button, self).removeListener(listener, iface)320 321323 if eventType is None: 324 eventType = callback._eventType 325 326 if issubclass(eventType, BlurEvent): 327 self.withdrawCallback(BlurEvent, callback, BlurEvent.EVENT_ID) 328 329 elif issubclass(eventType, ClickEvent): 330 self.withdrawCallback(ClickEvent, callback) 331 332 elif issubclass(eventType, FocusEvent): 333 self.withdrawCallback(FocusEvent, callback, FocusEvent.EVENT_ID) 334 335 else: 336 super(Button, self).removeCallback(callback, eventType)337 338340 """Fires a click event to all listeners. 341 342 @param details: 343 MouseEventDetails from which keyboard modifiers and other 344 information about the mouse click can be obtained. If the 345 button was clicked by a keyboard event, some of the fields 346 may be empty/undefined. 347 """ 348 if details is None: 349 self.fireEvent( ClickEvent(self) ) 350 else: 351 self.fireEvent( ClickEvent(self, details) )352 353355 # Make sure only booleans get through 356 if newValue is not None and not isinstance(newValue, bool): 357 raise ValueError, (self.__class__.__name__ + 358 ' only accepts boolean values') 359 360 super(Button, self).setInternalValue(newValue)361 362364 """Makes it possible to invoke a click on this button by pressing 365 the given L{KeyCode} and (optional) L{ModifierKey}s. 366 367 The shortcut is global (bound to the containing Window). 368 369 @param keyCode: 370 the keycode for invoking the shortcut 371 @param modifiers: 372 the (optional) modifiers for invoking the shortcut, null 373 for none 374 """ 375 if self.clickShortcut is not None: 376 self.removeShortcutListener(self.clickShortcut) 377 378 self.clickShortcut = ClickShortcut(self, keyCode, *modifiers) 379 self.addShortcutListener(self.clickShortcut)380 381383 """Removes the keyboard shortcut previously set with 384 L{setClickShortcut}. 385 """ 386 if self.clickShortcut is not None: 387 self.removeShortcutListener(self.clickShortcut) 388 self.clickShortcut = None389 390392 """Determines if a button is automatically disabled when clicked. See 393 L{setDisableOnClick} for details. 394 395 @return: true if the button is disabled when clicked, false otherwise 396 """ 397 return self._disableOnClick398 399401 """Determines if a button is automatically disabled when clicked. If 402 this is set to true the button will be automatically disabled when 403 clicked, typically to prevent (accidental) extra clicks on a button. 404 405 @param disableOnClick: 406 true to disable button when it is clicked, false otherwise 407 """ 408 self.disableOnClick = disableOnClick 409 self.requestRepaint()413 """A L{ShortcutListener} specifically made to define a keyboard 414 shortcut that invokes a click on the given button. 415 """ 416457 458418 """Creates a keyboard shortcut for clicking the given button using 419 the shorthand notation defined in L{ShortcutAction} or using the 420 given L{KeyCode} and L{ModifierKey}s. 421 422 @param args: tuple of the form 423 - (button, shorthandCaption) 424 1. to be clicked when the shortcut is invoked 425 2. the caption with shortcut keycode and modifiers indicated 426 - (button, keyCode, modifiers) 427 1. to be clicked when the shortcut is invoked 428 2. KeyCode to react to 429 3. optional modifiers for shortcut 430 - (button, keyCode) 431 1. to be clicked when the shortcut is invoked 432 2. KeyCode to react to 433 """ 434 args = args 435 nargs = len(args) 436 if nargs == 2: 437 if isinstance(args[1], int): 438 button, keyCode = args 439 super(ClickShortcut, self).__init__(None, keyCode, tuple()) 440 self.button = button 441 else: 442 button, shorthandCaption = args 443 super(ClickShortcut, self).__init__(shorthandCaption) 444 self.button = button 445 elif nargs >= 3: 446 button, keyCode = args[:2] 447 modifiers = args[2:] 448 super(ClickShortcut, self).__init__(None, keyCode, modifiers) 449 self.button = button 450 else: 451 raise ValueError, 'too few arguments'452 453460 """Click event. This event is thrown, when the button is clicked. 461 462 @author: Vaadin Ltd. 463 @author: Richard Lincoln 464 @version: 1.1.2 465 """ 466583 584 588468 """New instance with mouse details 469 470 @param source: 471 The source where the click took place 472 @param details: 473 Details about the mouse click 474 """ 475 super(ClickEvent, self).__init__(source) 476 self._details = details477 478480 """Gets the Button where the event occurred. 481 482 @return: the Source of the event. 483 """ 484 return self.getSource()485 486488 """Returns the mouse position (x coordinate) when the click took 489 place. The position is relative to the browser client area. 490 491 @return: The mouse cursor x position or -1 if unknown 492 """ 493 if self._details is not None: 494 return self._details.getClientX() 495 else: 496 return -1497 498500 """Returns the mouse position (y coordinate) when the click took 501 place. The position is relative to the browser client area. 502 503 @return: The mouse cursor y position or -1 if unknown 504 """ 505 if self._details is not None: 506 return self._details.getClientY() 507 else: 508 return -1509 510512 """Returns the relative mouse position (x coordinate) when the click 513 took place. The position is relative to the clicked component. 514 515 @return: The mouse cursor x position relative to the clicked layout 516 component or -1 if no x coordinate available 517 """ 518 if self._details is not None: 519 return self._details.getRelativeX() 520 else: 521 return -1522 523525 """Returns the relative mouse position (y coordinate) when the click 526 took place. The position is relative to the clicked component. 527 528 @return: The mouse cursor y position relative to the clicked layout 529 component or -1 if no y coordinate available 530 """ 531 if self._details is not None: 532 return self._details.getRelativeY() 533 else: 534 return -1535 536538 """Checks if the Alt key was down when the mouse event took place. 539 540 @return: true if Alt was down when the event occured, false 541 otherwise or if unknown 542 """ 543 if self._details is not None: 544 return self._details.isAltKey() 545 else: 546 return False547 548550 """Checks if the Ctrl key was down when the mouse event took place. 551 552 @return: true if Ctrl was pressed when the event occured, false 553 otherwise or if unknown 554 """ 555 if self._details is not None: 556 return self._details.isCtrlKey() 557 else: 558 return False559 560562 """Checks if the Meta key was down when the mouse event took place. 563 564 @return: true if Meta was pressed when the event occurred, false 565 otherwise or if unknown 566 """ 567 if self._details is not None: 568 return self._details.isMetaKey() 569 else: 570 return False571 572574 """Checks if the Shift key was down when the mouse event took place. 575 576 @return: true if Shift was pressed when the event occurred, false 577 otherwise or if unknown 578 """ 579 if self._details is not None: 580 return self._details.isShiftKey() 581 else: 582 return False
Home | Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Sat Apr 20 16:01:35 2013 | http://epydoc.sourceforge.net |