Package muntjac :: Package ui :: Module component
[hide private]
[frames] | no frames]

Source Code for Module muntjac.ui.component

  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 the top-level interface that is and must be implemented by 
 17  all Muntjac components.""" 
 18   
 19  from muntjac.terminal.variable_owner import IVariableOwner 
 20  from muntjac.terminal.sizeable import ISizeable 
 21  from muntjac.terminal.paintable import IPaintable 
 22  from muntjac.util import EventObject, IEventListener 
 23   
 24   
25 -class IComponent(IPaintable, IVariableOwner, ISizeable):
26 """C{IComponent} is the top-level interface that is and must be 27 implemented by all Muntjac components. C{IComponent} is paired with 28 L{AbstractComponent}, which provides a default implementation for 29 all the methods defined in this interface. 30 31 Components are laid out in the user interface hierarchically. The layout 32 is managed by layout components, or more generally by components that 33 implement the L{ComponentContainer} interface. Such a container is 34 the I{parent} of the contained components. 35 36 The L{getParent} method allows retrieving the parent component 37 of a component. While there is a L{setParent}, you rarely need 38 it as you normally add components with the 39 L{addComponent()<ComponentContainer.addComponent>} method 40 of the layout or other C{ComponentContainer}, which automatically 41 sets the parent. 42 43 A component becomes I{attached} to an application (and the 44 L{attach} is called) when it or one of its parents is attached to 45 the main window of the application through its containment hierarchy. 46 47 @author: Vaadin Ltd. 48 @author: Richard Lincoln 49 @version: 1.1.2 50 """ 51
52 - def getStyleName(self):
53 """Gets all user-defined CSS style names of a component. If the 54 component has multiple style names defined, the return string is a 55 space-separated list of style names. Built-in style names defined in 56 Muntjac or GWT are not returned. 57 58 The style names are returned only in the basic form in which they 59 were added; each user-defined style name shows as two CSS style class 60 names in the rendered HTML: one as it was given and one prefixed with 61 the component-specific style name. Only the former is returned. 62 63 @return: the style name or a space-separated list of user-defined 64 style names of the component 65 @see: L{setStyleName} 66 @see: L{addStyleName} 67 @see: L{removeStyleName} 68 """ 69 raise NotImplementedError
70 71
72 - def setStyleName(self, style):
73 """Sets one or more user-defined style names of the component, 74 replacing any previous user-defined styles. Multiple styles can be 75 specified as a space-separated list of style names. The style names 76 must be valid CSS class names and should not conflict with any 77 built-in style names in Muntjac or GWT:: 78 79 label = new Label("This text has a lot of style") 80 label.setStyleName("myonestyle myotherstyle") 81 82 Each style name will occur in two versions: one as specified and one 83 that is prefixed with the style name of the component. For example, 84 if you have a C{Button} component and give it "C{mystyle}" 85 style, the component will have both "C{mystyle}" and 86 "C{v-button-mystyle}" styles. You could then style the component 87 either with:: 88 89 .myonestyle {background: blue;} 90 91 or:: 92 93 .v-button-myonestyle {background: blue;} 94 95 It is normally a good practice to use L{addStyleName} rather than this 96 setter, as different software abstraction layers can then add their own 97 styles without accidentally removing those defined in other layers. 98 99 This method will trigger a L{RepaintRequestEvent}. 100 101 @param style: 102 the new style or styles of the component as a 103 space-separated list 104 @see: L{getStyleName} 105 @see: L{addStyleName} 106 @see: L{removeStyleName} 107 """ 108 raise NotImplementedError
109 110
111 - def addStyleName(self, style):
112 """Adds a style name to component. The style name will be rendered as 113 a HTML class name, which can be used in a CSS definition:: 114 115 label = new Label("This text has style") 116 label.addStyleName("mystyle") 117 118 Each style name will occur in two versions: one as specified and one 119 that is prefixed wil the style name of the component. For example, if 120 you have a C{Button} component and give it "C{mystyle}" 121 style, the component will have both "C{mystyle}" and 122 "C{v-button-mystyle}" styles. You could then style the component 123 either with:: 124 125 .mystyle {font-style: italic;} 126 127 or:: 128 129 .v-button-mystyle {font-style: italic;} 130 131 This method will trigger a L{RepaintRequestEvent}. 132 133 @param style: 134 the new style to be added to the component 135 @see: L{getStyleName} 136 @see: L{setStyleName} 137 @see: L{removeStyleName} 138 """ 139 raise NotImplementedError
140 141
142 - def removeStyleName(self, style):
143 """Removes one or more style names from component. Multiple styles 144 can be specified as a space-separated list of style names. 145 146 The parameter must be a valid CSS style name. Only user-defined style 147 names added with L{addStyleName} or L{setStyleName} can be removed; 148 built-in style names defined in Muntjac or GWT can not be removed. 149 150 This method will trigger a L{RepaintRequestEvent}. 151 152 @param style: 153 the style name or style names to be removed 154 @see: L{getStyleName} 155 @see: L{setStyleName} 156 @see: L{addStyleName} 157 """ 158 raise NotImplementedError
159 160
161 - def isEnabled(self):
162 """Tests whether the component is enabled or not. A user can not 163 interact with disabled components. Disabled components are rendered 164 in a style that indicates the status, usually in gray color. Children 165 of a disabled component are also disabled. Components are enabled by 166 default. 167 168 As a security feature, all variable change events for disabled 169 components are blocked on the server-side. 170 171 @return: C{True} if the component and its parent are enabled, 172 C{False} otherwise. 173 @see: L{IVariableOwner.isEnabled} 174 """ 175 raise NotImplementedError
176 177
178 - def setEnabled(self, enabled):
179 """Enables or disables the component. The user can not interact 180 disabled components, which are shown with a style that indicates the 181 status, usually shaded in light gray color. Components are enabled 182 by default. Children of a disabled component are automatically 183 disabled; if a child component is explicitly set as disabled, changes 184 in the disabled status of its parents do not change its status:: 185 186 enabled = new Button("Enabled") 187 enabled.setEnabled(True) # the default 188 layout.addComponent(enabled) 189 190 disabled = Button("Disabled") 191 disabled.setEnabled(False) 192 layout.addComponent(disabled) 193 194 This method will trigger a L{RepaintRequestEvent} for the 195 component and, if it is a L{ComponentContainer}, for all its 196 children recursively. 197 198 @param enabled: 199 a boolean value specifying if the component should be 200 enabled or not 201 """ 202 raise NotImplementedError
203 204
205 - def isVisible(self):
206 """Tests the I{visibility} property of the component. 207 208 Visible components are drawn in the user interface, while invisible 209 ones are not. The effect is not merely a cosmetic CSS change, but the 210 entire HTML element will be empty. Making a component invisible 211 through this property can alter the positioning of other components. 212 213 A component is visible only if all its parents are also visible. 214 Notice that if a child component is explicitly set as invisible, 215 changes in the visibility status of its parents do not change its 216 status. 217 218 This method does not check whether the component is attached (see 219 L{attach}). The component and all its parents may be 220 considered "visible", but not necessarily attached to application. 221 To test if component will actually be drawn, check both its visibility 222 and that L{getApplication} does not return C{None}. 223 224 @return: C{True} if the component is visible in the user 225 interface, C{False} if not 226 @see: L{setVisible} 227 @see: L{attach} 228 """ 229 raise NotImplementedError
230 231
232 - def setVisible(self, visible):
233 """Sets the visibility of the component. 234 235 Visible components are drawn in the user interface, while invisible 236 ones are not. The effect is not merely a cosmetic CSS change, but the 237 entire HTML element will be empty:: 238 239 readonly = TextField("Read-Only") 240 readonly.setValue("You can't see this!") 241 readonly.setVisible(False) 242 layout.addComponent(readonly) 243 244 A component is visible only if all of its parents are also visible. 245 If a component is explicitly set to be invisible, changes in the 246 visibility of its parents will not change the visibility of the 247 component. 248 249 @param visible: 250 the boolean value specifying if the component should be 251 visible after the call or not. 252 @see: L{isVisible} 253 """ 254 raise NotImplementedError
255 256
257 - def getParent(self):
258 """Gets the parent component of the component. 259 260 Components can be nested but a component can have only one parent. A 261 component that contains other components, that is, can be a parent, 262 should usually inherit the L{ComponentContainer} interface. 263 264 @return: the parent component 265 @see: L{setParent} 266 """ 267 raise NotImplementedError
268 269
270 - def setParent(self, parent):
271 """Sets the parent component of the component. 272 273 This method automatically calls L{attach} if the parent 274 becomes attached to the application, regardless of whether it was 275 attached previously. Conversely, if the parent is C{None} and 276 the component is attached to the application, L{detach} is 277 called for the component. 278 279 This method is rarely called directly. The 280 L{ComponentContainer.addComponent} method is normally used for adding 281 components to a container and it will call this method implicitly. 282 283 It is not possible to change the parent without first setting the 284 parent to C{None}. 285 286 @param parent: 287 the parent component 288 @raise ValueError: 289 if a parent is given even though the component already has 290 a parent 291 """ 292 raise NotImplementedError
293 294
295 - def isReadOnly(self):
296 """Tests whether the component is in the read-only mode. The user can 297 not change the value of a read-only component. As only L{IField} 298 components normally have a value that can be input or changed by the 299 user, this is mostly relevant only to field components, though not 300 restricted to them. 301 302 Notice that the read-only mode only affects whether the user can 303 change the I{value} of the component; it is possible to, for 304 example, scroll a read-only table. 305 306 The read-only status affects only the user; the value can still be 307 changed programmatically, for example, with L{IProperty.setValue}. 308 309 The method will return C{True} if the component or any of its 310 parents is in the read-only mode. 311 312 @return: C{True} if the component or any of its parents is in 313 read-only mode, C{False} if not. 314 @see: L{setReadOnly} 315 """ 316 raise NotImplementedError
317 318
319 - def setReadOnly(self, readOnly):
320 """Sets the read-only mode of the component to the specified mode. 321 The user can not change the value of a read-only component. 322 323 As only L{IField} components normally have a value that can be 324 input or changed by the user, this is mostly relevant only to field 325 components, though not restricted to them. 326 327 Notice that the read-only mode only affects whether the user can 328 change the I{value} of the component; it is possible to, for 329 example, scroll a read-only table. 330 331 The read-only status affects only the user; the value can still be 332 changed programmatically, for example, with L{IProperty.setValue}. 333 334 This method will trigger a L{RepaintRequestEvent}. 335 336 @param readOnly: 337 a boolean value specifying whether the component is put 338 read-only mode or not 339 """ 340 raise NotImplementedError
341 342
343 - def getCaption(self):
344 """Gets the caption of the component. 345 346 See L{setCaption} for a detailed description of the caption. 347 348 @return: the caption of the component or C{null} if the caption 349 is not set. 350 @see: L{setCaption} 351 """ 352 raise NotImplementedError
353 354
355 - def setCaption(self, caption):
356 """Sets the caption of the component. 357 358 A I{caption} is an explanatory textual label accompanying a user 359 interface component, usually shown above, left of, or inside the 360 component. I{Icon} (see L{setIcon} is 361 closely related to caption and is usually displayed horizontally before 362 or after it, depending on the component and the containing layout. 363 364 The caption can usually also be given as the first parameter to a 365 constructor, though some components do not support it:: 366 367 area = new RichTextArea() 368 area.setCaption("You can edit stuff here") 369 area.setValue("<h1>Helpful Heading</h1>" 370 + "<p>All this is for you to edit.</p>") 371 372 The contents of a caption are automatically quoted, so no raw XHTML can 373 be rendered in a caption. The validity of the used character encoding, 374 usually UTF-8, is not checked. 375 376 The caption of a component is, by default, managed and displayed by the 377 layout component or component container in which the component is 378 placed. For example, the L{VerticalLayout} component shows the captions 379 left-aligned above the contained components, while the L{FormLayout} 380 component shows the captions on the left side of the vertically laid 381 components, with the captions and their associated components 382 left-aligned in their own columns. The L{CustomComponent} does not 383 manage the caption of its composition root, so if the root component 384 has a caption, it will not be rendered. Some components, such as 385 L{Button} and L{Panel}, manage the caption themselves and display it 386 inside the component. 387 388 This method will trigger a L{RepaintRequestEvent}. A reimplementation 389 should call the superclass implementation. 390 391 @param caption: 392 the new caption for the component. If the caption is 393 C{None}, no caption is shown and it does not normally 394 take any space 395 """ 396 raise NotImplementedError
397 398
399 - def getIcon(self):
400 """Gets the icon resource of the component. 401 402 See L{setIcon} for a detailed description of the icon. 403 404 @return: the icon resource of the component or C{None} if the 405 component has no icon 406 @see: L{setIcon} 407 """ 408 raise NotImplementedError
409 410
411 - def setIcon(self, icon):
412 """Sets the icon of the component. 413 414 An icon is an explanatory graphical label accompanying a user interface 415 component, usually shown above, left of, or inside the component. Icon 416 is closely related to caption (see L{setCaption}) 417 and is usually displayed horizontally before or after it, depending on 418 the component and the containing layout. 419 420 The image is loaded by the browser from a resource, typically a 421 L{ThemeResource}:: 422 423 # IComponent with an icon from a custom theme 424 name = TextField("Name") 425 name.setIcon(ThemeResource("icons/user.png")) 426 layout.addComponent(name) 427 428 # IComponent with an icon from another theme ('runo') 429 ok = Button("OK") 430 ok.setIcon(ThemeResource("../runo/icons/16/ok.png")) 431 layout.addComponent(ok) 432 433 The icon of a component is, by default, managed and displayed by the 434 layout component or component container in which the component is 435 placed. For example, the L{VerticalLayout} component shows the icons 436 left-aligned above the contained components, while the L{FormLayout} 437 component shows the icons on the left side of the vertically laid 438 components, with the icons and their associated components left-aligned 439 in their own columns. The L{CustomComponent} does not manage the 440 icon of its composition root, so if the root component has an icon, it 441 will not be rendered. 442 443 An icon will be rendered inside an HTML element that has the 444 C{v-icon} CSS style class. The containing layout may enclose an icon 445 and a caption inside elements related to the caption, such as 446 C{v-caption} . 447 448 This method will trigger a L{RepaintRequestEvent}. 449 450 @param icon: 451 the icon of the component. If null, no icon is shown and it 452 does not normally take any space. 453 @see: L{getIcon} 454 @see: L{setCaption} 455 """ 456 raise NotImplementedError
457 458
459 - def getWindow(self):
460 """Gets the parent window of the component. 461 462 If the component is not attached to a window through a component 463 containment hierarchy, C{None} is returned. 464 465 The window can be either an application-level window or a sub-window. 466 If the component is itself a window, it returns a reference to itself, 467 not to its containing window (of a sub-window). 468 469 @return: the parent window of the component or C{None} if it is 470 not attached to a window or is itself a window 471 """ 472 raise NotImplementedError
473 474
475 - def getApplication(self):
476 """Gets the application object to which the component is attached. 477 478 The method will return C{None} if the component is not currently 479 attached to an application. This is often a problem in constructors of 480 regular components and in the initializers of custom composite 481 components. A standard workaround is to move the problematic 482 initialization to L{attach}, as described in the documentation of 483 the method. 484 485 @return: the parent application of the component or C{None}. 486 @see: L{attach} 487 """ 488 raise NotImplementedError
489 490
491 - def attach(self):
492 """Notifies the component that it is connected to an application. 493 494 The caller of this method is L{setParent} if the parent 495 is itself already attached to the application. If not, the parent will 496 call the L{attach} for all its children when it is attached to 497 the application. This method is always called before the component is 498 painted for the first time. 499 500 Reimplementing the C{attach()} method is useful for tasks that need 501 to get a reference to the parent, window, or application object with 502 the L{getParent}, L{getWindow}, and L{getApplication} methods. A 503 component does not yet know these objects in the constructor, 504 so in such case, the methods will return C{None}. For example, the 505 following is invalid:: 506 507 class AttachExample(CustomComponent): 508 def __init__(self): 509 # ERROR: We can't access the application object yet. 510 r = ClassResource("smiley.jpg", getApplication()) 511 image = Embedded("Image:", r) 512 setCompositionRoot(image) 513 514 Adding a component to an application triggers calling the 515 L{attach} method for the component. Correspondingly, removing a 516 component from a container triggers calling the L{detach} method. 517 If the parent of an added component is already connected to the 518 application, the C{attach()} is called immediately from 519 L{setParent}:: 520 521 class AttachExample(CustomComponent): 522 def __init__(self): 523 pass 524 525 def attach(self): 526 super(AttachExample, self).attach() # must call 527 528 # Now we know who ultimately owns us. 529 r = ClassResource("smiley.jpg", self.getApplication()) 530 image = Embedded("Image", r) 531 self.setCompositionRoot(image) 532 533 The attachment logic is implemented in L{AbstractComponent}. 534 535 @see: L{getApplication} 536 """ 537 raise NotImplementedError
538 539
540 - def detach(self):
541 """Notifies the component that it is detached from the application. 542 543 The L{getApplication} and L{getWindow} methods might 544 return C{None} after this method is called. 545 546 The caller of this method is L{setParent} if the parent is in the 547 application. When the parent is detached from the application 548 it is its response to call L{detach} for all the children and to 549 detach itself from the terminal. 550 """ 551 raise NotImplementedError
552 553
554 - def getLocale(self):
555 """Gets the locale of the component. 556 557 If a component does not have a locale set, the locale of its parent is 558 returned, and so on. Eventually, if no parent has locale set, the 559 locale of the application is returned. If the application does not have 560 a locale set, it is determined by C{getDefaultLocale()}. 561 562 As the component must be attached before its locale can be acquired, 563 using this method in the internationalization of component captions, 564 etc. is generally not feasible. For such use case, we recommend using 565 an otherwise acquired reference to the application locale. 566 567 @return: Locale of this component or C{null} if the component and 568 none of its parents has a locale set and the component is not 569 yet attached to an application. 570 """ 571 raise NotImplementedError
572 573
574 - def childRequestedRepaint(self, alreadyNotified):
575 """The child components of the component must call this method when 576 they need repainting. The call must be made even in the case in which 577 the children sent the repaint request themselves. 578 579 A repaint request is ignored if the component is invisible. 580 581 This method is called automatically by L{AbstractComponent}, which 582 also provides a default implementation of it. As this is a somewhat 583 internal feature, it is rarely necessary to reimplement this or call it 584 explicitly. 585 586 @param alreadyNotified: 587 the collection of repaint request listeners that have been 588 already notified by the child. This component should not 589 re-notify the listed listeners again. The container given as 590 parameter must be modifiable as the component might modify 591 it and pass it forward. A C{None} parameter is interpreted 592 as an empty collection. 593 """ 594 raise NotImplementedError
595 596
597 - def addListener(self, listener, iface=None):
598 """Registers a new (generic) component event listener for the 599 component:: 600 601 class Listening(CustomComponent, IListener): 602 603 # Stored for determining the source of an event 604 ok = None 605 606 status = None # For displaying info about the event 607 608 def __init__(self): 609 layout = VerticalLayout() 610 611 # Some miscellaneous component 612 name = TextField("Say it all here") 613 name.addListener(self) 614 name.setImmediate(true) 615 layout.addComponent(name) 616 617 # Handle button clicks as generic events instead 618 # of Button.ClickEvent events 619 ok = new Button("OK") 620 ok.addListener(self) 621 layout.addComponent(ok) 622 623 # For displaying information about an event 624 status = new Label("") 625 layout.addComponent(status) 626 627 setCompositionRoot(layout) 628 629 630 def componentEvent(event): 631 # Act according to the source of the event 632 if (event.getSource() == ok): 633 getWindow().showNotification("Click!") 634 635 status.setValue("Event from " + 636 event.getSource().__class__.__name__ 637 + ": " + event.__class__.__name__) 638 639 640 listening = Listening() 641 layout.addComponent(listening) 642 643 @param listener: 644 the new IListener to be registered. 645 @see: L{component.Event} 646 @see: L{removeListener} 647 """ 648 raise NotImplementedError
649 650
651 - def addCallback(self, callback, eventType=None, *args):
652 raise NotImplementedError
653 654
655 - def removeListener(self, listener, iface=None):
656 """Removes a previously registered component event listener from this 657 component. 658 659 @param listener: 660 the listener to be removed. 661 @see: L{addListener} 662 """ 663 raise NotImplementedError
664 665
666 - def removeCallback(self, callback, eventType=None):
667 raise NotImplementedError
668 669
670 -class Event(EventObject):
671 """Superclass of all component originated events. 672 673 Events are the basis of all user interaction handling in Muntjac. To 674 handle events, you provide a listener object that receives the events of 675 the particular event type:: 676 677 Notice that while each of the event types have their corresponding 678 listener types; the listener interfaces are not required to inherit the 679 C{IComponent.IListener} interface. 680 681 @see: L{component.IListener} 682 """ 683
684 - def __init__(self, source):
685 """Constructs a new event with the specified source component. 686 687 @param source: 688 the source component of the event 689 """ 690 super(Event, self).__init__(source)
691 692
693 - def getComponent(self):
694 """Gets the component where the event occurred. 695 696 @return: the source component of the event 697 """ 698 return self.getSource()
699 700
701 -class IListener(IEventListener):
702 """IListener interface for receiving C{component.Event}s. 703 704 IListener interfaces are the basis of all user interaction handling in 705 Muntjac. You have or create a listener object that receives the events. 706 All event types have their corresponding listener types; they are not, 707 however, required to inherit the C{component.IListener} interface, 708 and they rarely do so. 709 710 This generic listener interface is useful typically when you wish to 711 handle events from different component types in a single listener method 712 (C{componentEvent()}. If you handle component events in an anonymous 713 listener class, you normally use the component specific listener class, 714 such as L{button.ClickEvent}:: 715 716 717 class Listening(CustomComponent, IListener): 718 ok = None # Stored for determining the source of an event 719 720 status = None # For displaying info about the event 721 722 def __init__(self): 723 layout = VerticalLayout() 724 725 # Some miscellaneous component 726 name = TextField("Say it all here") 727 name.addListener(self) 728 name.setImmediate(True) 729 layout.addComponent(name) 730 731 # Handle button clicks as generic events instead 732 # of Button.ClickEvent events 733 ok = new Button("OK") 734 ok.addListener(self) 735 layout.addComponent(ok) 736 737 # For displaying information about an event 738 status = Label("") 739 layout.addComponent(status) 740 741 setCompositionRoot(layout) 742 743 744 def componentEvent(event): 745 # Act according to the source of the event 746 if (event.getSource() == ok 747 and event__class__ == Button.ClickEvent): 748 getWindow().showNotification("Click!") 749 750 # Display source component and event class names 751 status.setValue("Event from " + 752 event.getSource().__class__.__name__ 753 + ": " + event.__class__.__name__) 754 755 listening = Listening() 756 layout.addComponent(listening) 757 758 @see: L{IComponent.addListener} 759 """ 760
761 - def componentEvent(self, event):
762 """Notifies the listener of a component event. 763 764 As the event can typically come from one of many source components, 765 you may need to differentiate between the event source by component 766 reference, class, etc:: 767 768 def componentEvent(event): 769 # Act according to the source of the event 770 if (event.getSource() == ok and 771 event.__class__ == button.ClickEvent): 772 getWindow().showNotification("Click!") 773 774 # Display source component and event class names 775 status.setValue("Event from " + 776 event.getSource().__class__.__name__ 777 + ": " + event.__class__.__name__) 778 779 @param event: 780 the event that has occured. 781 """ 782 raise NotImplementedError
783 784
785 -class ErrorEvent(Event):
786 """Class of all component originated error events. 787 788 The component error event is normally fired by 789 L{AbstractComponent.setComponentError}. The component errors are set 790 by the framework in some situations and can be set by user code. They 791 are indicated in a component with an error indicator. 792 """ 793
794 - def __init__(self, message, component):
795 """Constructs a new event with a specified source component. 796 797 @param message: 798 the error message. 799 @param component: 800 the source component. 801 """ 802 super(ErrorEvent, self).__init__(component) 803 self._message = message
804 805
806 - def getErrorMessage(self):
807 """Gets the error message. 808 809 @return: the error message. 810 """ 811 return self._message
812 813
814 -class IErrorListener(IEventListener):
815 """IListener interface for receiving C{IComponent.Errors}s.""" 816
817 - def componentError(self, event):
818 """Notifies the listener of a component error. 819 820 @param event: 821 the event that has occured. 822 """ 823 raise NotImplementedError
824 825
826 -class IFocusable(IComponent):
827 """A sub-interface implemented by components that can obtain input focus. 828 This includes all L{Field} components as well as some other 829 components, such as L{Upload}. 830 831 Focus can be set with L{focus}. This interface does not provide 832 an accessor that would allow finding out the currently focused component; 833 focus information can be acquired for some (but not all) L{Field} 834 components through the L{IFocusListener} and L{IBlurListener} interfaces. 835 836 @see: L{FieldEvents} 837 """ 838
839 - def focus(self):
840 """Sets the focus to this component:: 841 842 loginBox = Form() 843 loginBox.setCaption("Login") 844 layout.addComponent(loginBox) 845 846 # Create the first field which will be focused 847 username = TextField("User name") 848 loginBox.addField("username", username) 849 850 # Set focus to the user name 851 username.focus() 852 853 password = TextField("Password") 854 loginBox.addField("password", password) 855 856 login = Button("Login") 857 loginBox.getFooter().addComponent(login) 858 859 Notice that this interface does not provide an accessor that would 860 allow finding out the currently focused component. Focus information 861 can be acquired for some (but not all) L{IField} components 862 through the L{IFocusListener} and L{IBlurListener} interfaces. 863 864 @see: L{FieldEvents} 865 @see: L{FocusEvent} 866 @see: L{IFocusListener} 867 @see: L{BlurEvent} 868 @see: L{IBlurListener} 869 """ 870 raise NotImplementedError
871 872
873 - def getTabIndex(self):
874 """Gets the I{tabulator index} of the C{IFocusable} component. 875 876 @return: tab index set for the C{IFocusable} component 877 @see: L{setTabIndex} 878 """ 879 raise NotImplementedError
880 881
882 - def setTabIndex(self, tabIndex):
883 """Sets the I{tabulator index} of the C{IFocusable} component. 884 The tab index property is used to specify the order in which the 885 fields are focused when the user presses the Tab key. Components with 886 a defined tab index are focused sequentially first, and then the 887 components with no tab index:: 888 889 loginBox = Form() 890 loginBox.setCaption("Login") 891 layout.addComponent(loginBox) 892 893 # Create the first field which will be focused 894 username = TextField("User name") 895 loginBox.addField("username", username) 896 897 # Set focus to the user name 898 username.focus() 899 900 password = TextField("Password") 901 loginBox.addField("password", password) 902 903 login = Button("Login") 904 loginBox.getFooter().addComponent(login) 905 906 # An additional component which natural focus order would 907 # be after the button. 908 remember = CheckBox("Remember me") 909 loginBox.getFooter().addComponent(remember) 910 911 username.setTabIndex(1) 912 password.setTabIndex(2) 913 remember.setTabIndex(3) # Different than natural place 914 login.setTabIndex(4) 915 916 After all focusable user interface components are done, the browser 917 can begin again from the component with the smallest tab index, or it 918 can take the focus out of the page, for example, to the location bar. 919 920 If the tab index is not set (is set to zero), the default tab order 921 is used. The order is somewhat browser-dependent, but generally 922 follows the HTML structure of the page. 923 924 A negative value means that the component is completely removed from 925 the tabulation order and can not be reached by pressing the Tab key 926 at all. 927 928 @param tabIndex: 929 the tab order of this component. Indexes usually start 930 from 1. Zero means that default tab order should be used. 931 A negative value means that the field should not be 932 included in the tabbing sequence. 933 @see: L{getTabIndex} 934 """ 935 raise NotImplementedError
936