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

Source Code for Module muntjac.ui.tab_sheet

   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 tab sheet component.""" 
  17   
  18  from warnings import warn 
  19   
  20  from muntjac.terminal.key_mapper import KeyMapper 
  21  from muntjac.terminal.paintable import IRepaintRequestListener,\ 
  22      RepaintRequestEvent 
  23   
  24  from muntjac.ui.component import IComponent, Event as ComponentEvent 
  25  from muntjac.ui.abstract_component_container import AbstractComponentContainer 
  26   
  27  from muntjac.terminal.gwt.server.communication_manager import \ 
  28      CommunicationManager 
  29   
  30   
31 -class ISelectedTabChangeListener(object):
32 """Selected tab change event listener. The listener is called whenever 33 another tab is selected, including when adding the first tab to a 34 tabsheet. 35 36 @author: Vaadin Ltd. 37 @author: Richard Lincoln 38 @version: 1.1.2 39 """ 40
41 - def selectedTabChange(self, event):
42 """Selected (shown) tab in tab sheet has has been changed. 43 44 @param event: the selected tab change event. 45 """ 46 raise NotImplementedError
47 48 49 _SELECTED_TAB_CHANGE_METHOD = getattr(ISelectedTabChangeListener, 50 'selectedTabChange') 51 52
53 -class TabSheet(AbstractComponentContainer):
54 """TabSheet component. 55 56 Tabs are typically identified by the component contained on the tab (see 57 L{ComponentContainer}), and tab metadata (including caption, icon, 58 visibility, enabledness, closability etc.) is kept in separate {@link 59 ITab} instances. 60 61 Tabs added with L{addComponent} get the caption and the 62 icon of the component at the time when the component is created, and these 63 are not automatically updated after tab creation. 64 65 A tab sheet can have multiple tab selection listeners and one tab close 66 handler (L{ICloseHandler}), which by default removes the tab from the 67 TabSheet. 68 69 The L{TabSheet} can be styled with the .v-tabsheet, .v-tabsheet-tabs 70 and .v-tabsheet-content styles. Themes may also have pre-defined 71 variations of the tab sheet presentation, such as 72 L{Reindeer.TABSHEET_BORDERLESS}, L{Runo.TABSHEET_SMALL} and 73 several other styles in L{Reindeer}. 74 75 The current implementation does not load the tabs to the UI before the 76 first time they are shown, but this may change in future releases. 77 78 @author: Vaadin Ltd. 79 @author: Richard Lincoln 80 @version: 1.1.2 81 """ 82 83 CLIENT_WIDGET = None #ClientWidget(VTabsheet, LoadStyle.EAGER) 84
85 - def __init__(self):
86 """Constructs a new Tabsheet. Tabsheet is immediate by default, and 87 the default close handler removes the tab being closed. 88 """ 89 super(TabSheet, self).__init__() 90 91 #: List of component tabs (tab contents). In addition to being on this 92 # list, there is a L{ITab} object in tabs for each tab with 93 # meta-data about the tab. 94 self._components = list() 95 96 #: Map containing information related to the tabs (caption, icon etc). 97 self._tabs = dict() 98 99 #: Selected tab content component. 100 self._selected = None 101 102 #: Mapper between server-side component instances (tab contents) and 103 # keys given to the client that identify tabs. 104 self._keyMapper = KeyMapper() 105 106 #: When true, the tab selection area is not displayed to the user. 107 self._tabsHidden = None 108 109 #: Tabs that have been shown to the user (have been painted as 110 # selected). 111 self._paintedTabs = set() 112 113 #: Handler to be called when a tab is closed. 114 self._closeHandler = None 115 116 #: expand horizontally by default 117 self.setWidth(100.0, self.UNITS_PERCENTAGE) 118 self.setImmediate(True) 119 120 self.setCloseHandler(InnerHandler())
121 122
123 - def getComponentIterator(self):
124 """Gets the component container iterator for going through all the 125 components (tab contents). 126 127 @return: the unmodifiable Iterator of the tab content components 128 """ 129 return iter(self._components)
130 131
132 - def getComponentCount(self):
133 """Gets the number of contained components (tabs). Consistent with 134 the iterator returned by L{getComponentIterator}. 135 136 @return: the number of contained components 137 """ 138 return len(self._components)
139 140
141 - def removeComponent(self, c):
142 """Removes a component and its corresponding tab. 143 144 If the tab was selected, the first eligible (visible and enabled) 145 remaining tab is selected. 146 147 @param c: the component to be removed. 148 """ 149 if c is not None and c in self._components: 150 super(TabSheet, self).removeComponent(c) 151 self._keyMapper.remove(c) 152 self._components.remove(c) 153 if c in self._tabs: 154 del self._tabs[c] 155 if c == self._selected: 156 if len(self._components) == 0: 157 self._selected = None 158 else: 159 # select the first enabled and visible tab, if any 160 self.updateSelection() 161 self.fireSelectedTabChange() 162 163 self.requestRepaint()
164 165
166 - def removeTab(self, tab):
167 """Removes a L{ITab} and the component associated with it, as 168 previously added with L{addTab}, or L{addComponent}. 169 170 If the tab was selected, the first eligible (visible and enabled) 171 remaining tab is selected. 172 173 @see: L{addTab} 174 @see: L{addComponent} 175 @see: L{removeComponent} 176 @param tab: the ITab to remove 177 """ 178 self.removeComponent(tab.getComponent())
179 180
181 - def addComponent(self, c):
182 """Adds a new tab into TabSheet. IComponent caption and icon are 183 copied to the tab metadata at creation time. 184 185 @see: L{addTab} 186 @param c: the component to be added. 187 """ 188 self.addTab(c)
189 190
191 - def addTab(self, *args):
192 """Adds a new tab into TabSheet. 193 194 The first tab added to a tab sheet is automatically selected and a 195 tab selection event is fired. 196 197 If the component is already present in the tab sheet, changes its 198 caption and icon and returns the corresponding (old) tab, preserving 199 other tab metadata. 200 201 @param args: tuple of the form 202 - (c, caption, icon) 203 1. the component to be added onto tab - should not be null. 204 2. the caption to be set for the component and used rendered 205 in tab bar 206 3. the icon to be set for the component and used rendered in 207 tab bar 208 - (c, caption, icon, position) 209 1. the component to be added onto tab - should not be null. 210 2. the caption to be set for the component and used rendered 211 in tab bar 212 3. the icon to be set for the component and used rendered in 213 tab bar 214 4. the position at where the the tab should be added 215 - (c) 216 1. the component to be added onto tab - should not be null. 217 - (c, position) 218 1. the component to be added onto tab - should not be null. 219 2. The position where the tab should be added 220 - (c, caption) 221 1. the component to be added onto tab - should not be null. 222 2. the caption to be set for the component and used rendered 223 in tab bar 224 225 @return: the created L{ITab} 226 """ 227 nargs = len(args) 228 if nargs == 1: 229 c, = args 230 return self.addTab(c, len(self._components)) 231 elif nargs == 2: 232 if isinstance(args[1], basestring): 233 c, caption = args 234 self.addTab(c, caption, None) 235 else: 236 c, position = args 237 if c is None: 238 return None 239 elif c in self._tabs: 240 return self._tabs.get(c) 241 else: 242 return self.addTab(c, c.getCaption(), c.getIcon(), position) 243 elif nargs == 3: 244 c, caption, icon = args 245 return self.addTab(c, caption, icon, len(self._components)) 246 elif nargs == 4: 247 c, caption, icon, position = args 248 if c is None: 249 return None 250 elif c in self._tabs: 251 tab = self._tabs.get(c) 252 tab.setCaption(caption) 253 tab.setIcon(icon) 254 return tab 255 else: 256 self._components.insert(position, c) 257 tab = TabSheetTabImpl(caption, icon, self) 258 self._tabs[c] = tab 259 if self._selected is None: 260 self._selected = c 261 self.fireSelectedTabChange() 262 super(TabSheet, self).addComponent(c) 263 self.requestRepaint() 264 return tab 265 else: 266 raise ValueError, 'invalid number of arguments'
267 268
269 - def moveComponentsFrom(self, source):
270 """Moves all components from another container to this container. The 271 components are removed from the other container. 272 273 If the source container is a L{TabSheet}, component captions and 274 icons are copied from it. 275 276 @param source: 277 the container components are removed from. 278 """ 279 i = source.getComponentIterator() 280 while True: 281 try: 282 c = i.next() 283 caption = None 284 icon = None 285 if issubclass(source.__class__, TabSheet): 286 caption = source.getTabCaption(c) 287 icon = source.getTabIcon(c) 288 source.removeComponent(c) 289 self.addTab(c, caption, icon) 290 except StopIteration: 291 break
292 293
294 - def paintContent(self, target):
295 """Paints the content of this component. 296 297 @param target: 298 the paint target 299 @raise PaintException: 300 if the paint operation failed. 301 """ 302 if self.areTabsHidden(): 303 target.addAttribute('hidetabs', True) 304 305 target.startTag('tabs') 306 307 orphaned = set(self._paintedTabs) 308 309 i = self.getComponentIterator() 310 while True: 311 try: 312 component = i.next() 313 if component in orphaned: 314 orphaned.remove(component) 315 tab = self._tabs.get(component) 316 target.startTag('tab') 317 if not tab.isEnabled() and tab.isVisible(): 318 target.addAttribute('disabled', True) 319 320 if not tab.isVisible(): 321 target.addAttribute('hidden', True) 322 323 if tab.isClosable(): 324 target.addAttribute('closable', True) 325 326 icon = tab.getIcon() 327 if icon is not None: 328 target.addAttribute('icon', icon) 329 330 caption = tab.getCaption() 331 if caption is not None and len(caption) > 0: 332 target.addAttribute('caption', caption) 333 334 description = tab.getDescription() 335 if description is not None: 336 target.addAttribute('description', description) 337 338 componentError = tab.getComponentError() 339 if componentError is not None: 340 componentError.paint(target) 341 342 target.addAttribute('key', self._keyMapper.key(component)) 343 if component == self._selected: 344 target.addAttribute('selected', True) 345 component.paint(target) 346 self._paintedTabs.add(component) 347 348 elif component in self._paintedTabs: 349 component.paint(target) 350 else: 351 component.requestRepaintRequests() 352 target.endTag('tab') 353 except StopIteration: 354 break 355 356 target.endTag('tabs') 357 358 if self._selected is not None: 359 target.addVariable(self, 'selected', 360 self._keyMapper.key(self._selected)) 361 362 # clean possibly orphaned entries in paintedTabs 363 for component2 in orphaned: 364 self._paintedTabs.remove(component2)
365 366
367 - def areTabsHidden(self):
368 """Are the tab selection parts ("tabs") hidden. 369 370 @return: true if the tabs are hidden in the UI 371 """ 372 return self._tabsHidden
373 374
375 - def hideTabs(self, tabsHidden):
376 """Hides or shows the tab selection parts ("tabs"). 377 378 @param tabsHidden: 379 true if the tabs should be hidden 380 """ 381 self._tabsHidden = tabsHidden 382 self.requestRepaint()
383 384
385 - def getTabCaption(self, c):
386 """Gets tab caption. The tab is identified by the tab content 387 component. 388 389 @param c: the component in the tab 390 @deprecated: Use L{getTab} and L{ITab.getCaption} instead. 391 """ 392 warn('use getTab() and ITab.getCaption() instead', DeprecationWarning) 393 394 info = self._tabs.get(c) 395 if info is None: 396 return '' 397 else: 398 return info.getCaption()
399 400
401 - def setTabCaption(self, c, caption):
402 """Sets tab caption. The tab is identified by the tab content 403 component. 404 405 @param c: the component in the tab 406 @param caption: the caption to set. 407 @deprecated: Use L{getTab} and L{ITab.setCaption} instead. 408 """ 409 warn('use getTab() and ITab.getCaption() instead', DeprecationWarning) 410 411 info = self._tabs.get(c) 412 if info is not None: 413 info.setCaption(caption) 414 self.requestRepaint()
415 416
417 - def getTabIcon(self, c):
418 """Gets the icon for a tab. The tab is identified by the tab content 419 component. 420 421 @param c: the component in the tab 422 @deprecated: Use L{getTab} and L{ITab.getIcon} instead. 423 """ 424 warn('use getTab() and ITab.getIcon() instead', DeprecationWarning) 425 426 info = self._tabs.get(c) 427 if info is None: 428 return None 429 else: 430 return info.getIcon()
431 432
433 - def setTabIcon(self, c, icon):
434 """Sets icon for the given component. The tab is identified by the 435 tab content component. 436 437 @param c: 438 the component in the tab 439 @param icon: 440 the icon to set 441 @deprecated: Use L{getTab} and L{ITab.setIcon} instead. 442 """ 443 warn('use getTab() and ITab.getIcon() instead', DeprecationWarning) 444 445 info = self._tabs.get(c) 446 if info is not None: 447 info.setIcon(icon) 448 self.requestRepaint()
449 450
451 - def getTab(self, arg):
452 """Returns the L{ITab} (metadata) for a component. The 453 L{ITab} object can be used for setting caption,icon, etc 454 for the tab. 455 456 @param arg: 457 the component or the position of the tab 458 """ 459 if isinstance(arg, IComponent): 460 c = arg 461 return self._tabs.get(c) 462 else: 463 position = arg 464 c = self._components[position] 465 if c is not None: 466 return self._tabs.get(c) 467 return None
468 469
470 - def setSelectedTab(self, c):
471 """Sets the selected tab. The tab is identified by the tab content 472 component. 473 """ 474 if (c is not None and c in self._components 475 and c != self._selected): 476 self._selected = c 477 self.updateSelection() 478 self.fireSelectedTabChange() 479 self.requestRepaint()
480 481
482 - def updateSelection(self):
483 """Checks if the current selection is valid, and updates the selection 484 if the previously selected component is not visible and enabled. The 485 first visible and enabled tab is selected if the current selection is 486 empty or invalid. 487 488 This method does not fire tab change events, but the caller should do 489 so if appropriate. 490 491 @return: true if selection was changed, false otherwise 492 """ 493 originalSelection = self._selected 494 495 i = self.getComponentIterator() 496 while True: 497 try: 498 component = i.next() 499 tab = self._tabs.get(component) 500 # If we have no selection, if the current selection is 501 # invisible or if the current selection is disabled (but 502 # the whole component is not) we select this tab instead 503 selectedTabInfo = None 504 if self._selected is not None: 505 selectedTabInfo = self._tabs.get(self._selected) 506 507 if (self._selected is None 508 or selectedTabInfo is None 509 or not selectedTabInfo.isVisible() 510 or not selectedTabInfo.isEnabled()): 511 # The current selection is not valid so we need to 512 # change it 513 if tab.isEnabled() and tab.isVisible(): 514 self._selected = component 515 break 516 else: 517 # The current selection is not valid but this 518 # tab cannot be selected either. 519 self._selected = None 520 except StopIteration: 521 break 522 523 return originalSelection != self._selected
524 525
526 - def getSelectedTab(self):
527 """Gets the selected tab content component. 528 529 @return: the selected tab contents 530 """ 531 return self._selected
532 533
534 - def changeVariables(self, source, variables):
535 if 'selected' in variables: 536 select = self._keyMapper.get(variables.get('selected')) 537 self.setSelectedTab(select) 538 539 if 'close' in variables: 540 tab = self._keyMapper.get(variables.get('close')) 541 542 if tab is not None: 543 self._closeHandler.onTabClose(self, tab)
544 545
546 - def replaceComponent(self, oldComponent, newComponent):
547 """Replaces a component (tab content) with another. This can be used 548 to change tab contents or to rearrange tabs. The tab position and some 549 metadata are preserved when moving components within the same 550 L{TabSheet}. 551 552 If the oldComponent is not present in the tab sheet, the new one is 553 added at the end. 554 555 If the oldComponent is already in the tab sheet but the newComponent 556 isn't, the old tab is replaced with a new one, and the caption and 557 icon of the old one are copied to the new tab. 558 559 If both old and new components are present, their positions are 560 swapped. 561 """ 562 if self._selected == oldComponent: 563 # keep selection w/o selectedTabChange event 564 self._selected = newComponent 565 566 newTab = self._tabs.get(newComponent) 567 oldTab = self._tabs.get(oldComponent) 568 569 # Gets the captions 570 oldCaption = None 571 oldIcon = None 572 newCaption = None 573 newIcon = None 574 575 if oldTab is not None: 576 oldCaption = oldTab.getCaption() 577 oldIcon = oldTab.getIcon() 578 579 if newTab is not None: 580 newCaption = newTab.getCaption() 581 newIcon = newTab.getIcon() 582 else: 583 newCaption = newComponent.getCaption() 584 newIcon = newComponent.getIcon() 585 586 # Gets the locations 587 oldLocation = -1 588 newLocation = -1 589 location = 0 590 for component in self._components: 591 if component == oldComponent: 592 oldLocation = location 593 if component == newComponent: 594 newLocation = location 595 location += 1 596 597 if oldLocation == -1: 598 self.addComponent(newComponent) 599 elif newLocation == -1: 600 self.removeComponent(oldComponent) 601 self._keyMapper.remove(oldComponent) 602 newTab = self.addTab(newComponent) 603 self._components.remove(newComponent) 604 self._components.append(oldLocation, newComponent) 605 newTab.setCaption(oldCaption) 606 newTab.setIcon(oldIcon) 607 else: 608 if oldLocation > newLocation: 609 self._components.remove(oldComponent) 610 self._components.append(newLocation, oldComponent) 611 self._components.remove(newComponent) 612 self._components.append(oldLocation, newComponent) 613 else: 614 self._components.remove(newComponent) 615 self._components.append(oldLocation, newComponent) 616 self._components.remove(oldComponent) 617 self._components.append(newLocation, oldComponent) 618 619 if newTab is not None: 620 # This should always be true 621 newTab.setCaption(oldCaption) 622 newTab.setIcon(oldIcon) 623 624 if oldTab is not None: 625 # This should always be true 626 oldTab.setCaption(newCaption) 627 oldTab.setIcon(newIcon) 628 629 self.requestRepaint()
630 631
632 - def addListener(self, listener, iface=None):
633 """Adds a tab selection listener 634 635 @param listener: 636 the Listener to be added. 637 """ 638 if (isinstance(listener, ISelectedTabChangeListener) and 639 (iface is None or 640 issubclass(iface, ISelectedTabChangeListener))): 641 self.registerListener(SelectedTabChangeEvent, 642 listener, _SELECTED_TAB_CHANGE_METHOD) 643 644 super(TabSheet, self).addListener(listener, iface)
645 646
647 - def addCallback(self, callback, eventType=None, *args):
648 if eventType is None: 649 eventType = callback._eventType 650 651 if issubclass(eventType, SelectedTabChangeEvent): 652 self.registerCallback(SelectedTabChangeEvent, callback, None, 653 *args) 654 else: 655 super(TabSheet, self).addCallback(callback, eventType, *args)
656 657
658 - def removeListener(self, listener, iface=None):
659 """Removes a tab selection listener 660 661 @param listener: 662 the Listener to be removed. 663 """ 664 if (isinstance(listener, IRepaintRequestListener) and 665 (iface is None or issubclass(iface, IRepaintRequestListener))): 666 super(TabSheet, self).removeListener(listener, iface) 667 if isinstance(listener, CommunicationManager): 668 # clean the paintedTabs here instead of detach to avoid subtree 669 # caching issues when detached-attached without render 670 self._paintedTabs.clear() 671 672 if (isinstance(listener, ISelectedTabChangeListener) and 673 (iface is None or 674 issubclass(iface, ISelectedTabChangeListener))): 675 self.withdrawListener(SelectedTabChangeEvent, 676 listener, _SELECTED_TAB_CHANGE_METHOD) 677 678 super(TabSheet, self).removeListener(listener, iface)
679 680
681 - def removeCallback(self, callback, eventType=None):
682 if eventType is None: 683 eventType = callback._eventType 684 685 if issubclass(eventType, SelectedTabChangeEvent): 686 self.withdrawCallback(SelectedTabChangeEvent, callback) 687 else: 688 super(TabSheet, self).removeCallback(callback, eventType)
689 690
691 - def fireSelectedTabChange(self):
692 """Sends an event that the currently selected tab has changed.""" 693 event = SelectedTabChangeEvent(self) 694 self.fireEvent(event)
695 696
697 - def setCloseHandler(self, handler):
698 """Provide a custom L{ICloseHandler} for this TabSheet if you 699 wish to perform some additional tasks when a user clicks on a tabs 700 close button, e.g. show a confirmation dialogue before removing the 701 tab. 702 703 To remove the tab, if you provide your own close handler, you must 704 call L{removeComponent} yourself. 705 706 The default ICloseHandler for TabSheet will only remove the tab. 707 """ 708 self._closeHandler = handler
709 710
711 - def setTabPosition(self, tab, position):
712 """Sets the position of the tab. 713 714 @param tab: 715 The tab 716 @param position: 717 The new position of the tab 718 """ 719 oldPosition = self.getTabPosition(tab) 720 self._components.remove(oldPosition) 721 self._components.append(position, tab.getComponent()) 722 self.requestRepaint()
723 724
725 - def getTabPosition(self, tab):
726 """Gets the position of the tab 727 728 @param tab: The tab 729 """ 730 try: 731 return self._components.index( tab.getComponent() ) 732 except ValueError: 733 return -1
734 735
736 -class SelectedTabChangeEvent(ComponentEvent):
737 """Selected tab change event. This event is sent when the selected 738 (shown) tab in the tab sheet is changed. 739 740 @author: Vaadin Ltd. 741 @author: Richard Lincoln 742 @version: 1.1.2 743 """ 744
745 - def __init__(self, source):
746 """New instance of selected tab change event 747 748 @param source: 749 the Source of the event. 750 """ 751 super(SelectedTabChangeEvent, self).__init__(source)
752 753
754 - def getTabSheet(self):
755 """TabSheet where the event occurred. 756 757 @return: the Source of the event. 758 """ 759 return self.getSource()
760 761
762 -class ITab(object):
763 """ITab meta-data for a component in a L{TabSheet}. 764 765 The meta-data includes the tab caption, icon, visibility and enabledness, 766 closability, description (tooltip) and an optional component error shown 767 in the tab. 768 769 Tabs are identified by the component contained on them in most cases, and 770 the meta-data can be obtained with L{TabSheet.getTab}. 771 """ 772
773 - def isVisible(self):
774 """Returns the visible status for the tab. An invisible tab is not 775 shown in the tab bar and cannot be selected. 776 777 @return: true for visible, false for hidden 778 """ 779 raise NotImplementedError
780 781
782 - def setVisible(self, visible):
783 """Sets the visible status for the tab. An invisible tab is not shown 784 in the tab bar and cannot be selected, selection is changed 785 automatically when there is an attempt to select an invisible tab. 786 787 @param visible: 788 true for visible, false for hidden 789 """ 790 raise NotImplementedError
791 792
793 - def isClosable(self):
794 """Returns the closability status for the tab. 795 796 @return: true if the tab is allowed to be closed by the end user, 797 false for not allowing closing 798 """ 799 raise NotImplementedError
800 801
802 - def setClosable(self, closable):
803 """Sets the closability status for the tab. A closable tab can be 804 closed by the user through the user interface. This also controls 805 if a close button is shown to the user or not. 806 807 Note! Currently only supported by TabSheet, not Accordion. 808 809 @param closable: 810 true if the end user is allowed to close the tab, false 811 for not allowing to close. Should default to false. 812 """ 813 raise NotImplementedError
814 815
816 - def isEnabled(self):
817 """Returns the enabled status for the tab. A disabled tab is shown as 818 such in the tab bar and cannot be selected. 819 820 @return: true for enabled, false for disabled 821 """ 822 raise NotImplementedError
823 824
825 - def setEnabled(self, enabled):
826 """Sets the enabled status for the tab. A disabled tab is shown as 827 such in the tab bar and cannot be selected. 828 829 @param enabled: 830 true for enabled, false for disabled 831 """ 832 raise NotImplementedError
833 834
835 - def setCaption(self, caption):
836 """Sets the caption for the tab. 837 838 @param caption: 839 the caption to set 840 """ 841 raise NotImplementedError
842 843
844 - def getCaption(self):
845 """Gets the caption for the tab.""" 846 raise NotImplementedError
847 848
849 - def getIcon(self):
850 """Gets the icon for the tab.""" 851 raise NotImplementedError
852 853
854 - def setIcon(self, icon):
855 """Sets the icon for the tab. 856 857 @param icon: 858 the icon to set 859 """ 860 raise NotImplementedError
861 862
863 - def getDescription(self):
864 """Gets the description for the tab. The description can be used to 865 briefly describe the state of the tab to the user, and is typically 866 shown as a tooltip when hovering over the tab. 867 868 @return: the description for the tab 869 """ 870 raise NotImplementedError
871 872
873 - def setDescription(self, description):
874 """Sets the description for the tab. The description can be used to 875 briefly describe the state of the tab to the user, and is typically 876 shown as a tooltip when hovering over the tab. 877 878 @param description: 879 the new description string for the tab. 880 """ 881 raise NotImplementedError
882 883
884 - def setComponentError(self, componentError):
885 """Sets an error indicator to be shown in the tab. This can be used 886 e.g. to communicate to the user that there is a problem in the 887 contents of the tab. 888 889 @see: L{AbstractComponent.setComponentError} 890 891 @param componentError: 892 error message or null for none 893 """ 894 raise NotImplementedError
895 896
897 - def getComponentError(self):
898 """Gets the curent error message shown for the tab. 899 900 @see: L{AbstractComponent.setComponentError} 901 902 @return: message or null if none 903 """ 904 raise NotImplementedError
905 906
907 - def getComponent(self):
908 """Get the component related to the ITab""" 909 raise NotImplementedError
910 911
912 -class TabSheetTabImpl(ITab):
913 """TabSheet's implementation of L{ITab} - tab metadata.""" 914
915 - def __init__(self, caption, icon, sheet):
916 self._sheet = sheet 917 918 self._enabled = True 919 self._visible = True 920 self._closable = False 921 self._description = None 922 self._componentError = None 923 924 if caption is None: 925 caption = '' 926 self._caption = caption 927 self._icon = icon
928 929
930 - def getCaption(self):
931 """Returns the tab caption. Can never be null.""" 932 return self._caption
933 934
935 - def setCaption(self, caption):
936 self._caption = caption 937 self._sheet.requestRepaint()
938 939
940 - def getIcon(self):
941 return self._icon
942 943
944 - def setIcon(self, icon):
945 self._icon = icon 946 self._sheet.requestRepaint()
947 948
949 - def isEnabled(self):
950 return self._enabled
951 952
953 - def setEnabled(self, enabled):
954 self._enabled = enabled 955 if self._sheet.updateSelection(): 956 self._sheet.fireSelectedTabChange() 957 self._sheet.requestRepaint()
958 959
960 - def isVisible(self):
961 return self._visible
962 963
964 - def setVisible(self, visible):
965 self._visible = visible 966 if self._sheet.updateSelection(): 967 self._sheet.fireSelectedTabChange() 968 self._sheet.requestRepaint()
969 970
971 - def isClosable(self):
972 return self._closable
973 974
975 - def setClosable(self, closable):
976 self._closable = closable 977 self._sheet.requestRepaint()
978 979
980 - def close(self):
981 pass
982 983
984 - def getDescription(self):
985 return self._description
986 987
988 - def setDescription(self, description):
989 self._description = description 990 self._sheet.requestRepaint()
991 992
993 - def getComponentError(self):
994 return self._componentError
995 996
997 - def setComponentError(self, componentError):
998 self._componentError = componentError 999 self._sheet.requestRepaint()
1000 1001
1002 - def getComponent(self):
1003 for k, v in self._sheet._tabs.iteritems(): 1004 if v == self: 1005 return k 1006 return None
1007 1008
1009 -class ICloseHandler(object):
1010 """ICloseHandler is used to process tab closing events. Default behavior 1011 is to remove the tab from the TabSheet. 1012 1013 @author: Jouni Koivuviita / Vaadin Ltd. 1014 @author: Richard Lincoln 1015 """ 1016
1017 - def onTabClose(self, tabsheet, tabContent):
1018 """Called when a user has pressed the close icon of a tab in the 1019 client side widget. 1020 1021 @param tabsheet: 1022 the TabSheet to which the tab belongs to 1023 @param tabContent: 1024 the component that corresponds to the tab whose close 1025 button was clicked 1026 """ 1027 raise NotImplementedError
1028 1029
1030 -class InnerHandler(ICloseHandler):
1031
1032 - def onTabClose(self, tabsheet, c):
1033 tabsheet.removeComponent(c)
1034