/library/ui.py
Python | 2048 lines | 1972 code | 40 blank | 36 comment | 32 complexity | 4b04681a7447a7c2a260bda6a04419da MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
Large files files are truncated, but you can click here to view the full file
- # Copyright 2006 James Tauber and contributors
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- from __pyjamas__ import JS, console
- import DOM
- import pygwt
- from DeferredCommand import DeferredCommand
- import pyjslib
- from History import History
- import Window
- from sets import Set
-
-
- class Event:
- """
- This class contains flags and integer values used by the event system.
-
- It is not meant to be subclassed or instantiated.
- """
- BUTTON_LEFT = 1
- BUTTON_MIDDLE = 4
- BUTTON_RIGHT = 2
-
- ONBLUR = 0x01000
- ONCHANGE = 0x00400
- ONCLICK = 0x00001
- ONDBLCLICK = 0x00002
- ONERROR = 0x10000
- ONFOCUS = 0x00800
- ONKEYDOWN = 0x00080
- ONKEYPRESS = 0x00100
- ONKEYUP = 0x00200
- ONLOAD = 0x08000
- ONLOSECAPTURE = 0x02000
- ONMOUSEDOWN = 0x00004
- ONMOUSEMOVE = 0x00040
- ONMOUSEOUT = 0x00020
- ONMOUSEOVER = 0x00010
- ONMOUSEUP = 0x00008
- ONSCROLL = 0x04000
-
- FOCUSEVENTS = 0x01800 # ONFOCUS | ONBLUR
- KEYEVENTS = 0x00380 # ONKEYDOWN | ONKEYPRESS | ONKEYUP
- MOUSEEVENTS = 0x0007C # ONMOUSEDOWN | ONMOUSEUP | ONMOUSEMOVE | ONMOUSEOVER | ONMOUSEOUT
-
-
- # FocusListenerCollection
- class FocusListener:
- def fireFocusEvent(self, listeners, sender, event):
- type = DOM.eventGetType(event)
- if type == "focus":
- for listener in listeners:
- listener.onFocus(sender)
- elif type == "blur":
- for listener in listeners:
- listener.onLostFocus(sender)
-
-
- # KeyboardListener + KeyboardListenerCollection
- class KeyboardListener:
- KEY_ALT = 18
- KEY_BACKSPACE = 8
- KEY_CTRL = 17
- KEY_DELETE = 46
- KEY_DOWN = 40
- KEY_END = 35
- KEY_ENTER = 13
- KEY_ESCAPE = 27
- KEY_HOME = 36
- KEY_LEFT = 37
- KEY_PAGEDOWN = 34
- KEY_PAGEUP = 33
- KEY_RIGHT = 39
- KEY_SHIFT = 16
- KEY_TAB = 9
- KEY_UP = 38
-
- MODIFIER_ALT = 4
- MODIFIER_CTRL = 2
- MODIFIER_SHIFT = 1
-
- def getKeyboardModifiers(self, event):
- shift = 0
- ctrl = 0
- alt = 0
-
- if DOM.eventGetShiftKey(event):
- shift = KeyboardListener.MODIFIER_SHIFT
-
- if DOM.eventGetCtrlKey(event):
- ctrl = KeyboardListener.MODIFIER_CTRL
-
- if DOM.eventGetAltKey(event):
- alt = KeyboardListener.MODIFIER_ALT
-
- return shift | ctrl | alt
-
-
- def fireKeyboardEvent(self, listeners, sender, event):
- modifiers = KeyboardListener.getKeyboardModifiers(self, event)
-
- type = DOM.eventGetType(event)
- if type == "keydown":
- for listener in listeners:
- listener.onKeyDown(sender, DOM.eventGetKeyCode(event), modifiers)
- elif type == "keyup":
- for listener in listeners:
- listener.onKeyUp(sender, DOM.eventGetKeyCode(event), modifiers)
- elif type == "keypress":
- for listener in listeners:
- listener.onKeyPress(sender, DOM.eventGetKeyCode(event), modifiers)
-
-
- # MouseListenerCollection
- class MouseListener:
- def fireMouseEvent(self, listeners, sender, event):
- x = DOM.eventGetClientX(event) - DOM.getAbsoluteLeft(sender.getElement())
- y = DOM.eventGetClientY(event) - DOM.getAbsoluteTop(sender.getElement())
-
- type = DOM.eventGetType(event)
- if type == "mousedown":
- for listener in listeners:
- listener.onMouseDown(sender, x, y)
- elif type == "mouseup":
- for listener in listeners:
- listener.onMouseUp(sender, x, y)
- elif type == "mousemove":
- for listener in listeners:
- listener.onMouseMove(sender, x, y)
- elif type == "mouseover":
- from_element = DOM.eventGetFromElement(event)
- if not DOM.isOrHasChild(sender.getElement(), from_element):
- for listener in listeners:
- listener.onMouseEnter(sender)
- elif type == "mouseout":
- to_element = DOM.eventGetToElement(event)
- if not DOM.isOrHasChild(sender.getElement(), to_element):
- for listener in listeners:
- listener.onMouseLeave(sender)
-
-
- class UIObject:
-
- def getAbsoluteLeft(self):
- return DOM.getAbsoluteLeft(self.getElement())
-
- def getAbsoluteTop(self):
- return DOM.getAbsoluteTop(self.getElement())
-
- def getElement(self):
- """Get the DOM element associated with the UIObject, if any"""
- return self.element
-
- def getOffsetHeight(self):
- return DOM.getIntAttribute(self.element, "offsetHeight")
-
- def getOffsetWidth(self):
- return DOM.getIntAttribute(self.element, "offsetWidth")
-
- def getStyleName(self):
- return DOM.getAttribute(self.element, "className")
-
- def getTitle(self):
- return DOM.getAttribute(self.element, "title")
-
- def setElement(self, element):
- """Set the DOM element associated with the UIObject."""
- self.element = element
-
- def setHeight(self, height):
- """Set the height of the element associated with this UIObject. The
- value should be given as a CSS value, such as 100px, 30%, or 50pi"""
- DOM.setStyleAttribute(self.element, "height", height)
-
- def setPixelSize(self, width, height):
- """Set the width and height of the element associated with this UIObject
- in pixels. Width and height should be numbers."""
- if width >= 0:
- self.setWidth(width + "px")
- if height >= 0:
- self.setHeight(height + "px")
-
- def setSize(self, width, height):
- """Set the width and height of the element associated with this UIObject. The
- values should be given as a CSS value, such as 100px, 30%, or 50pi"""
- self.setWidth(width)
- self.setHeight(height)
-
- def addStyleName(self, style):
- """Append a style to the element associated with this UIObject. This is
- a CSS class name. It will be added after any already-assigned CSS class for
- the element."""
- self.setStyleName(self.element, style, True)
-
- def removeStyleName(self, style):
- """Remove a style from the element associated with this UIObject. This is
- a CSS class name."""
- self.setStyleName(self.element, style, False)
-
- # also callable as: setStyleName(self, style)
- def setStyleName(self, element, style=None, add=True):
- """When called with a single argument, this replaces all the CSS classes
- associated with this UIObject's element with the given parameter. Otherwise,
- this is assumed to be a worker function for addStyleName and removeStyleName."""
- # emulate setStyleName(self, style)
- if style == None:
- style = element
- DOM.setAttribute(self.element, "className", style)
- return
-
- oldStyle = DOM.getAttribute(element, "className")
- if oldStyle == None:
- oldStyle = ""
- idx = oldStyle.find(style)
-
- # Calculate matching index
- lastPos = len(oldStyle)
- while idx != -1:
- if idx == 0 or (oldStyle[idx - 1] == " "):
- last = idx + len(style)
- if (last == lastPos) or ((last < lastPos) and (oldStyle[last] == " ")):
- break
- idx = oldStyle.find(style, idx + 1)
-
- if add:
- if idx == -1:
- DOM.setAttribute(element, "className", oldStyle + " " + style)
- else:
- if idx != -1:
- begin = oldStyle[:idx]
- end = oldStyle[idx + len(style):]
- DOM.setAttribute(element, "className", begin + end)
-
- def setTitle(self, title):
- DOM.setAttribute(self.element, "title", title)
-
- def setWidth(self, width):
- """Set the width of the element associated with this UIObject. The
- value should be given as a CSS value, such as 100px, 30%, or 50pi"""
- DOM.setStyleAttribute(self.element, "width", width)
-
- def sinkEvents(self, eventBitsToAdd):
- """Request that the given events be delivered to the event handler for this
- element. The event bits passed are added (using inclusive OR) to the events
- already "sunk" for the element associated with the UIObject. The event bits
- are a combination of values from class L{Event}."""
- if self.element:
- DOM.sinkEvents(self.getElement(), eventBitsToAdd | DOM.getEventsSunk(self.getElement()))
-
- def isVisible(self, element=None):
- """Determine whether this element is currently visible, by checking the CSS
- property 'display'"""
- if not element:
- element = self.element
- return element.style.display != "none"
-
- # also callable as: setVisible(visible)
- def setVisible(self, element, visible=None):
- """Set whether this element is visible or not. If a single parameter is
- given, the self.element is used. This modifies the CSS property 'display',
- which means that an invisible element not only is not drawn, but doesn't
- occupy any space on the page."""
- if visible==None:
- visible = element
- element = self.element
-
- if visible:
- element.style.display = ""
- else:
- element.style.display = "none"
-
- def unsinkEvents(self, eventBitsToRemove):
- """Reverse the operation of sinkEvents. See L{UIObject.sinkevents}."""
- DOM.sinkEvents(self.getElement(), ~eventBitsToRemove & DOM.getEventsSunk(self.getElement()))
-
-
- class Widget(UIObject):
- """
- Base class for most of the UI classes. This class provides basic services
- used by any Widget, including management of parents and adding/removing the
- event handler association with the DOM.
- """
- def __init__(self):
- self.attached = False
- self.parent = None
- self.layoutData = None
-
- def getLayoutData(self):
- return self.layoutData
-
- def getParent(self):
- """Widgets are kept in a hierarchy, and widgets that have been added to a panel
- will have a parent widget that contains them. This retrieves the containing
- widget for this widget."""
- return self.parent
-
- def isAttached(self):
- """Return whether or not this widget has been attached to the document."""
- return self.attached
-
- def onBrowserEvent(self, event):
- pass
-
- def onLoad(self):
- pass
-
- def onAttach(self):
- """Called when this widget has an element, and that element is on the document's
- DOM tree, and we have a parent widget."""
- if self.attached:
- return
- self.attached = True
- DOM.setEventListener(self.getElement(), self)
- self.onLoad()
-
- def onDetach(self):
- """Called when this widget is being removed from the DOM tree of the document."""
- if not self.attached:
- return
- self.attached = False
- DOM.setEventListener(self.getElement(), None)
-
- def setLayoutData(self, layoutData):
- self.layoutData = layoutData
-
- def setParent(self, parent):
- """Update the parent attribute. If the parent is currently attached to the DOM this
- assumes we are being attached also and calls onAttach()."""
- self.parent = parent
- if parent == None:
- self.onDetach()
- elif parent.attached:
- self.onAttach()
-
- def removeFromParent(self):
- """Remove ourself from our parent. The parent widget will call setParent(None) on
- us automatically"""
- if hasattr(self.parent, "remove"):
- self.parent.remove(self)
-
- def getID(self):
- """Get the id attribute of the associated DOM element."""
- return DOM.getAttribute(self.getElement(), "id")
-
- def setID(self, id):
- """Set the id attribute of the associated DOM element."""
- DOM.setAttribute(self.getElement(), "id", id)
-
-
- class FocusWidget(Widget):
-
- def __init__(self, element):
- Widget.__init__(self)
- self.clickListeners = []
- self.focusListeners = []
- self.keyboardListeners = []
-
- self.setElement(element)
- self.sinkEvents(Event.ONCLICK | Event.FOCUSEVENTS | Event.KEYEVENTS)
-
- def addClickListener(self, listener):
- self.clickListeners.append(listener)
-
- def addFocusListener(self, listener):
- self.focusListeners.append(listener)
-
- def addKeyboardListener(self, listener):
- self.keyboardListeners.append(listener)
-
- def getTabIndex(self):
- return Focus.getTabIndex(self, self.getElement())
-
- def isEnabled(self):
- return not DOM.getBooleanAttribute(self.getElement(), "disabled")
-
- def onBrowserEvent(self, event):
- type = DOM.eventGetType(event)
- if type == "click":
- for listener in self.clickListeners:
- if listener.onClick: listener.onClick(self, event)
- else: listener(self, event)
- elif type == "blur" or type == "focus":
- FocusListener.fireFocusEvent(self, self.focusListeners, self, event)
- elif type == "keydown" or type == "keypress" or type == "keyup":
- KeyboardListener.fireKeyboardEvent(self, self.keyboardListeners, self, event)
-
- def removeClickListener(self, listener):
- self.clickListeners.remove(listener)
-
- def removeFocusListener(self, listener):
- self.focusListeners.remove(listener)
-
- def removeKeyboardListener(self, listener):
- self.keyboardListeners.remove(listener)
-
- def setAccessKey(self, key):
- DOM.setAttribute(self.getElement(), "accessKey", "" + key)
-
- def setEnabled(self, enabled):
- DOM.setBooleanAttribute(self.getElement(), "disabled", not enabled)
-
- def setFocus(self, focused):
- if (focused):
- Focus.focus(self, self.getElement())
- else:
- Focus.blur(self, self.getElement())
-
- def setTabIndex(self, index):
- Focus.setTabIndex(self, self.getElement(), index)
-
-
- class ButtonBase(FocusWidget):
-
- def __init__(self, element):
- FocusWidget.__init__(self, element)
-
- def getHTML(self):
- return DOM.getInnerHTML(self.getElement())
-
- def getText(self):
- return DOM.getInnerText(self.getElement())
-
- def setHTML(self, html):
- DOM.setInnerHTML(self.getElement(), html)
-
- def setText(self, text):
- DOM.setInnerText(self.getElement(), text)
-
-
- class Button(ButtonBase):
-
- def __init__(self, html=None, listener=None):
- """
- Create a new button widget.
-
- @param html: Html content (e.g. the button label); see setHTML()
- @param listener: A new click listener; see addClickListener()
-
- """
- ButtonBase.__init__(self, DOM.createButton())
- self.adjustType(self.getElement())
- self.setStyleName("gwt-Button")
- if html:
- self.setHTML(html)
- if listener:
- self.addClickListener(listener)
-
- def adjustType(self, button):
- JS("""
- if (button.type == 'submit') {
- try { button.setAttribute("type", "button"); } catch (e) { }
- }
- """)
-
- def click(self):
- """
- Simulate a button click.
- """
- self.getElement().click()
-
-
- class CheckBox(ButtonBase):
-
- def __init__(self, label=None, asHTML=False):
- self.initElement(DOM.createInputCheck())
-
- self.setStyleName("gwt-CheckBox")
- if label:
- if asHTML:
- self.setHTML(label)
- else:
- self.setText(label)
-
- def initElement(self, element):
- ButtonBase.__init__(self, DOM.createSpan())
- self.inputElem = element
- self.labelElem = DOM.createLabel()
-
- self.unsinkEvents(Event.FOCUSEVENTS| Event.ONCLICK)
- DOM.sinkEvents(self.inputElem, Event.FOCUSEVENTS | Event.ONCLICK | DOM.getEventsSunk(self.inputElem))
-
- DOM.appendChild(self.getElement(), self.inputElem)
- DOM.appendChild(self.getElement(), self.labelElem)
-
- uid = "check" + self.getUniqueID()
- DOM.setAttribute(self.inputElem, "id", uid)
- DOM.setAttribute(self.labelElem, "htmlFor", uid)
-
- # emulate static
- def getUniqueID(self):
- JS("""
- _CheckBox_unique_id++;
- return _CheckBox_unique_id;
- };
- var _CheckBox_unique_id=0;
- {
- """)
-
- def getHTML(self):
- return DOM.getInnerHTML(self.labelElem)
-
- def getName(self):
- return DOM.getAttribute(self.inputElem, "name")
-
- def getText(self):
- return DOM.getInnerText(self.labelElem)
-
- def setChecked(self, checked):
- DOM.setBooleanAttribute(self.inputElem, "checked", checked)
- DOM.setBooleanAttribute(self.inputElem, "defaultChecked", checked)
-
- def isChecked(self):
- if self.attached:
- propName = "checked"
- else:
- propName = "defaultChecked"
-
- return DOM.getBooleanAttribute(self.inputElem, propName)
-
- def isEnabled(self):
- return not DOM.getBooleanAttribute(self.inputElem, "disabled")
-
- def setEnabled(self, enabled):
- DOM.setBooleanAttribute(self.inputElem, "disabled", not enabled)
-
- def setFocus(self, focused):
- if focused:
- Focus.focus(self, self.inputElem)
- else:
- Focus.blur(self, self.inputElem)
-
- def setHTML(self, html):
- DOM.setInnerHTML(self.labelElem, html)
-
- def setName(self, name):
- DOM.setAttribute(self.inputElem, "name", name)
-
- def setTabIndex(self, index):
- Focus.setTabIndex(self, self.inputElem, index)
-
- def setText(self, text):
- DOM.setInnerText(self.labelElem, text)
-
- def onDetach(self):
- self.setChecked(self.isChecked())
- ButtonBase.onDetach(self)
-
-
- class RadioButton(CheckBox):
- def __init__(self, group, label=None, asHTML=False):
- self.initElement(DOM.createInputRadio(group))
-
- self.setStyleName("gwt-RadioButton")
- if label:
- if asHTML:
- self.setHTML(label)
- else:
- self.setText(label)
-
-
- class Composite(Widget):
- def __init__(self):
- Widget.__init__(self)
- self.widget = None
-
- def initWidget(self, widget):
- if self.widget != None:
- return
-
- widget.removeFromParent()
- self.setElement(widget.getElement())
-
- self.widget = widget
- widget.setParent(self)
-
- def onAttach(self):
- Widget.onAttach(self)
- self.widget.onAttach()
-
- def onDetach(self):
- Widget.onDetach(self)
- self.widget.onDetach()
-
- def setWidget(self, widget):
- self.initWidget(widget)
-
-
- class Panel(Widget):
- def __init__(self):
- Widget.__init__(self)
- self.children = []
-
- def add(self):
- console.error("This panel does not support no-arg add()")
-
- # TODO: fix iterator remove()
- def clear(self):
- for child in list(self):
- # should be iterator.remove() ==> self.remove(self.children[0]) or self.remove(child) ???
- self.remote(child)
-
- def disown(self, widget):
- if widget.getParent() != self:
- console.error("widget %o is not a child of this panel %o", widget, self)
- else:
- element = widget.getElement()
- widget.setParent(None)
- parentElement = DOM.getParent(element)
- if parentElement:
- DOM.removeChild(parentElement, element)
-
- def adopt(self, widget, container):
- widget.removeFromParent()
- if container:
- DOM.appendChild(container, widget.getElement())
- widget.setParent(self)
-
- def remove(self, widget):
- pass
-
- def onAttach(self):
- Widget.onAttach(self)
- for child in self:
- child.onAttach()
-
- def onDetach(self):
- Widget.onDetach(self)
- for child in self:
- child.onDetach()
-
- def __iter__(self):
- return self.children.__iter__()
-
-
- class CellFormatter:
-
- def __init__(self, outer):
- self.outer = outer
-
- def addStyleName(self, row, column, styleName):
- self.outer.prepareCell(row, column)
- self.outer.setStyleName(self.getElement(row, column), styleName, True)
-
- def getElement(self, row, column):
- self.outer.checkCellBounds(row, column)
- return DOM.getChild(self.outer.rowFormatter.getRow(self.outer.bodyElem, row), column)
-
- def getStyleName(self, row, column):
- return DOM.getAttribute(self.getElement(row, column), "className")
-
- def isVisible(self, row, column):
- element = self.getElement(row, column)
- return self.outer.isVisible(element)
-
- def removeStyleName(self, row, column, styleName):
- self.checkCellBounds(row, column)
- self.outer.setStyleName(self.getElement(row, column), styleName, False)
-
- def setAlignment(self, row, column, hAlign, vAlign):
- self.setHorizontalAlignment(row, column, hAlign)
- self.setVerticalAlignment(row, column, vAlign)
-
- def setHeight(self, row, column, height):
- self.outer.prepareCell(row, column)
- element = self.getCellElement(self.outer.bodyElem, row, column)
- DOM.setStyleAttribute(element, "height", height)
-
- def setHorizontalAlignment(self, row, column, align):
- self.outer.prepareCell(row, column)
- element = self.getCellElement(self.outer.bodyElem, row, column)
- DOM.setAttribute(element, "align", align)
-
- def setStyleName(self, row, column, styleName):
- self.outer.prepareCell(row, column)
- self.setAttr(row, column, "className", styleName)
-
- def setVerticalAlignment(self, row, column, align):
- self.outer.prepareCell(row, column)
- DOM.setStyleAttribute(self.getCellElement(self.outer.bodyElem, row, column), "verticalAlign", align)
-
- def setVisible(self, row, column, visible):
- element = self.ensureElement(row, column)
- self.outer.setVisible(element, visible)
-
- def setWidth(self, row, column, width):
- self.outer.prepareCell(row, column)
- DOM.setStyleAttribute(self.getCellElement(self.outer.bodyElem, row, column), "width", width)
-
- def setWordWrap(self, row, column, wrap):
- self.outer.prepareCell(row, column)
- if wrap:
- wrap_str = ""
- else:
- wrap_str = "nowrap"
-
- DOM.setStyleAttribute(self.getElement(row, column), "whiteSpace", wrap_str)
-
- def getCellElement(self, table, row, col):
- JS("""
- var out = table.rows[row].cells[col];
- return (out == null ? null : out);
- """)
-
- def getRawElement(self, row, column):
- return self.getCellElement(self.outer.bodyElem, row, column)
-
- def ensureElement(self, row, column):
- self.outer.prepareCell(row, column)
- return DOM.getChild(self.outer.rowFormatter.ensureElement(row), column)
-
- def getAttr(self, row, column, attr):
- elem = self.getElement(row, column)
- return DOM.getAttribute(elem, attr)
-
- def setAttr(self, row, column, attrName, value):
- elem = self.getElement(row, column)
- DOM.setAttribute(elem, attrName, value)
-
-
-
- class RowFormatter:
-
- def __init__(self, outer):
- self.outer = outer
-
- def addStyleName(self, row, styleName):
- self.outer.setStyleName(self.ensureElement(row), styleName, True)
-
- def getElement(self, row):
- self.outer.checkRowBounds(row)
- return self.getRow(self.outer.bodyElem, row)
-
- def getStyleName(self, row):
- return DOM.getAttribute(self.getElement(row), "className")
-
- def isVisible(self, row):
- element = self.getElement(row)
- return self.outer.isVisible(element)
-
- def removeStyleName(self, row, styleName):
- self.outer.setStyleName(self.getElement(row), styleName, False)
-
- def setStyleName(self, row, styleName):
- elem = self.ensureElement(row)
- DOM.setAttribute(elem, "className", styleName)
-
- def setVerticalAlign(self, row, align):
- DOM.setStyleAttribute(self.ensureElement(row), "verticalAlign", align)
-
- def setVisible(self, row, visible):
- element = self.ensureElement(row)
- self.outer.setVisible(element, visible)
-
- def ensureElement(self, row):
- self.outer.prepareRow(row)
- return self.getRow(self.outer.bodyElem, row)
-
- def getRow(self, element, row):
- JS("""
- return element.rows[row];
- """)
-
- def setAttr(self, row, attrName, value):
- element = self.ensureElement(row)
- DOM.setAttribute(element, attrName, value)
-
-
- class HTMLTable(Panel):
-
- def __init__(self):
- Panel.__init__(self)
- self.cellFormatter = CellFormatter(self)
- self.rowFormatter = RowFormatter(self)
- self.tableListeners = []
- self.widgetMap = {}
-
- self.tableElem = DOM.createTable()
- self.bodyElem = DOM.createTBody()
- DOM.appendChild(self.tableElem, self.bodyElem)
- self.setElement(self.tableElem)
- self.sinkEvents(Event.ONCLICK)
-
- def addTableListener(self, listener):
- self.tableListeners.append(listener)
-
- def clear(self):
- for row in range(self.getRowCount()):
- for col in range(self.getCellCount(row)):
- child = self.getWidget(row, col)
- if child != None:
- self.removeWidget(child)
- # assert len(self.widgetMap) == 0
-
- def clearCell(self, row, column):
- td = self.cellFormatter.getElement(row, column)
- return self.internalClearCell(td)
-
- def getCellCount(self, row):
- return 0
-
- def getCellFormatter(self):
- return self.cellFormatter
-
- def getCellPadding(self):
- return DOM.getIntAttribute(self.tableElem, "cellPadding")
-
- def getCellSpacing(self):
- return DOM.getIntAttribute(self.tableElem, "cellSpacing")
-
- def getHTML(self, row, column):
- element = self.cellFormatter.getElement(row, column)
- return DOM.getInnerHTML(element)
-
- def getRowCount(self):
- return 0
-
- def getRowFormatter(self):
- return self.rowFormatter
-
- def getText(self, row, column):
- self.checkCellBounds(row, column)
- element = self.cellFormatter.getElement(row, column)
- return DOM.getInnerText(element)
-
- # also callable as getWidget(widgetElement)
- def getWidget(self, row, column=None):
- if column == None:
- key = self.computeKeyForElement(row)
- else:
- self.checkCellBounds(row, column)
- key = self.computeKey(row, column)
-
- if key == None:
- return None
- return self.widgetMap[key]
-
- def isCellPresent(self, row, column):
- # GWT uses "and", possibly a bug
- if row >= self.getRowCount() or row < 0:
- return False
-
- if column < 0 or column >= self.getCellCount(row):
- return False
-
- return True
-
- def __iter__(self):
- return self.widgetMap.itervalues()
-
- def onBrowserEvent(self, event):
- if DOM.eventGetType(event) == "click":
- td = self.getEventTargetCell(event)
- if not td:
- return
-
- tr = DOM.getParent(td)
- body = DOM.getParent(tr)
- row = DOM.getChildIndex(body, tr)
- column = DOM.getChildIndex(tr, td)
-
- for listener in self.tableListeners:
- if listener.onCellClicked:
- listener.onCellClicked(self, row, column)
- else:
- listener(self)
-
- def remove(self, widget):
- if widget.getParent() != self:
- return False
-
- self.removeWidget(widget)
- return True
-
- def removeTableListener(self, listener):
- self.tableListeners.remove(listener)
-
- def setBorderWidth(self, width):
- DOM.setAttribute(self.tableElem, "border", width)
-
- def setCellPadding(self, padding):
- DOM.setIntAttribute(self.tableElem, "cellPadding", padding)
-
- def setCellSpacing(self, spacing):
- DOM.setIntAttribute(self.tableElem, "cellSpacing", spacing)
-
- def setHTML(self, row, column, html):
- self.prepareCell(row, column)
- td = self.cleanCell(row, column)
- if html != None:
- DOM.setInnerHTML(td, html)
-
- def setText(self, row, column, text):
- self.prepareCell(row, column)
- td = self.cleanCell(row, column)
- if text != None:
- DOM.setInnerText(td, text)
-
- def setWidget(self, row, column, widget):
- self.prepareCell(row, column)
- if widget == None:
- return
-
- widget.removeFromParent()
- td = self.cleanCell(row, column)
- widget_hash = hash(widget)
- element = widget.getElement()
- DOM.setAttribute(element, "__hash", widget_hash)
- self.widgetMap[widget_hash] = widget
- self.adopt(widget, td)
-
- def cleanCell(self, row, column):
- td = self.cellFormatter.getRawElement(row, column)
- self.internalClearCell(td)
- return td
-
- def computeKey(self, row, column):
- element = self.cellFormatter.getRawElement(row, column)
- child = DOM.getFirstChild(element)
- if child == None:
- return None
-
- return self.computeKeyForElement(child)
-
- def computeKeyForElement(self, widgetElement):
- return DOM.getAttribute(widgetElement, "__hash")
-
- def removeWidget(self, widget):
- self.disown(widget)
-
- del self.widgetMap[self.computeKeyForElement(widget.getElement())]
- return True
-
- def checkCellBounds(self, row, column):
- self.checkRowBounds(row)
- #if column<0: raise IndexError, "Column " + column + " must be non-negative: " + column
-
- cellSize = self.getCellCount(row)
- #if cellSize<column: raise IndexError, "Column " + column + " does not exist, col at row " + row + " size is " + self.getCellCount(row) + "cell(s)"
-
- def checkRowBounds(self, row):
- rowSize = self.getRowCount()
- #if row >= rowSize or row < 0: raise IndexError, "Row " + row + " does not exist, row size is " + self.getRowCount()
-
- def createCell(self):
- return DOM.createTD()
-
- def getBodyElement(self):
- return self.bodyElem
-
- # also callable as getDOMCellCount(row)
- def getDOMCellCount(self, element, row=None):
- if row == None:
- return self.getDOMCellCountImpl(self.bodyElem, element)
- return self.getDOMCellCountImpl(element, row)
-
- def getDOMCellCountImpl(self, element, row):
- JS("""
- return element.rows[row].cells.length;
- """)
-
- # also callable as getDOMRowCount(element)
- def getDOMRowCount(self, element=None):
- if element == None:
- element = self.bodyElem
- return self.getDOMRowCountImpl(element)
-
- def getDOMRowCountImpl(self, element):
- JS("""
- return element.rows.length;
- """)
-
- def getEventTargetCell(self, event):
- td = DOM.eventGetTarget(event)
- while td != None:
- if DOM.getAttribute(td, "tagName").lower() == "td":
- tr = DOM.getParent(td)
- body = DOM.getParent(tr)
- if DOM.compare(body, self.bodyElem):
- return td
- if DOM.compare(td, self.bodyElem):
- return None
- td = DOM.getParent(td)
-
- return None
-
- def insertCell(self, row, column):
- tr = self.rowFormatter.getRow(self.bodyElem, row)
- td = self.createCell()
- DOM.insertChild(tr, td, column)
-
- def insertCells(self, row, column, count):
- tr = self.rowFormatter.getRow(self.bodyElem, row)
- for i in range(column, column + count):
- td = self.createCell()
- DOM.insertChild(tr, td, i)
-
- def insertRow(self, beforeRow):
- if beforeRow != self.getRowCount():
- self.checkRowBounds(beforeRow)
-
- tr = DOM.createTR()
- DOM.insertChild(self.bodyElem, tr, beforeRow)
- return beforeRow
-
- def internalClearCell(self, td):
- maybeChild = DOM.getFirstChild(td)
- widget = None
- if maybeChild != None:
- widget = self.getWidget(maybeChild)
-
- if widget != None:
- self.removeWidget(widget)
- return True
-
- DOM.setInnerHTML(td, "")
- return False
-
- def prepareCell(self, row, column):
- pass
-
- def prepareRow(self, row):
- pass
-
- def removeCell(self, row, column):
- self.checkCellBounds(row, column)
- td = self.cleanCell(row, column)
- tr = self.rowFormatter.getRow(self.bodyElem, row)
- DOM.removeChild(tr, td)
-
- def removeRow(self, row):
- for column in range(self.getCellCount(row)):
- self.cleanCell(row, column)
- DOM.removeChild(self.bodyElem, self.rowFormatter.getRow(self.bodyElem, row))
-
- def setCellFormatter(self, cellFormatter):
- self.cellFormatter = cellFormatter
-
- def setRowFormatter(self, rowFormatter):
- self.rowFormatter = rowFormatter
-
-
- class Grid(HTMLTable):
-
- def __init__(self, rows=0, columns=0):
- HTMLTable.__init__(self)
- self.cellFormatter = CellFormatter(self)
- self.rowFormatter = RowFormatter(self)
- self.numColumns = 0
- self.numRows = 0
- if rows > 0 or columns > 0:
- self.resize(rows, columns)
-
- def resize(self, rows, columns):
- self.resizeColumns(columns)
- self.resizeRows(rows)
-
- def resizeColumns(self, columns):
- if self.numColumns == columns:
- return
-
- if self.numColumns > columns:
- for i in range(0, self.numRows):
- for j in range(self.numColumns - 1, columns - 1, -1):
- self.removeCell(i, j)
- else:
- for i in range(self.numRows):
- for j in range(self.numColumns, columns):
- self.insertCell(i, j)
- self.numColumns = columns
-
- def resizeRows(self, rows):
- if self.numRows == rows:
- return
-
- if self.numRows < rows:
- self.addRows(self.getBodyElement(), rows - self.numRows, self.numColumns)
- self.numRows = rows
- else:
- while self.numRows > rows:
- self.numRows -= 1
- self.removeRow(self.numRows)
-
- def createCell(self):
- td = HTMLTable.createCell(self)
- DOM.setInnerHTML(td, " ")
- return td
-
- def clearCell(self, row, column):
- td = self.cellFormatter.getElement(row, column)
- b = HTMLTable.internalClearCell(self, td)
- DOM.setInnerHTML(td, " ")
- return b
-
- def prepareCell(self, row, column):
- pass
-
- def prepareRow(self, row):
- pass
-
- def getCellCount(self, row):
- return self.numColumns
-
- def getColumnCount(self):
- return self.numColumns
-
- def getRowCount(self):
- return self.numRows
-
- def addRows(self, table, numRows, columns):
- JS("""
- var td = $doc.createElement("td");
- td.innerHTML = " ";
- var row = $doc.createElement("tr");
- for(var cellNum = 0; cellNum < columns; cellNum++) {
- var cell = td.cloneNode(true);
- row.appendChild(cell);
- }
- table.appendChild(row);
- for(var rowNum = 1; rowNum < numRows; rowNum++) {
- table.appendChild(row.cloneNode(true));
- }
- """)
-
-
- class FlexCellFormatter(CellFormatter):
- def __init__(self, outer):
- CellFormatter.__init__(self, outer)
-
- def getColSpan(self, row, column):
- return DOM.getIntAttribute(self.getElement(row, column), "colSpan")
-
- def getRowSpan(self, row, column):
- return DOM.getIntAttribute(self.getElement(row, column), "rowSpan")
-
- def setColSpan(self, row, column, colSpan):
- DOM.setIntAttribute(self.ensureElement(row, column), "colSpan", colSpan)
-
- def setRowSpan(self, row, column, rowSpan):
- DOM.setIntAttribute(self.ensureElement(row, column), "rowSpan", rowSpan)
-
-
- class FlexTable(HTMLTable):
- def __init__(self):
- HTMLTable.__init__(self)
- self.cellFormatter = FlexCellFormatter(self)
- self.rowFormatter = RowFormatter(self)
-
- def addCell(self, row):
- self.insertCell(row, self.getCellCount(row))
-
- def getCellCount(self, row):
- self.checkRowBounds(row)
- return self.getDOMCellCount(self.getBodyElement(), row)
-
- def getFlexCellFormatter(self):
- return self.getCellFormatter()
-
- def getRowCount(self):
- return self.getDOMRowCount()
-
- def removeCells(self, row, column, num):
- for i in range(i):
- self.removeCell(row, column)
-
- def prepareCell(self, row, column):
- self.prepareRow(row)
- #if column < 0: throw new IndexOutOfBoundsException("Cannot create a column with a negative index: " + column);
-
- cellCount = self.getCellCount(row)
- required = column + 1 - cellCount
- if required > 0:
- self.addCells(self.getBodyElement(), row, required)
-
- def prepareRow(self, row):
- #if row < 0: throw new IndexOutOfBoundsException("Cannot create a row with a negative index: " + row);
-
- rowCount = self.getRowCount()
- for i in range(rowCount, row + 1):
- self.insertRow(i)
-
- def addCells(self, table, row, num):
- JS("""
- var rowElem = table.rows[row];
- for(var i = 0; i < num; i++){
- var cell = $doc.createElement("td");
- rowElem.appendChild(cell);
- }
- """)
-
-
- class ComplexPanel(Panel):
- """
- Superclass for widgets with multiple children.
- """
- def __init__(self):
- Panel.__init__(self)
- self.children = []
-
- def add(self, widget, container):
- self.insert(widget, container, len(self.children))
-
- def getChildren(self):
- return self.children
-
- def insert(self, widget, container, beforeIndex):
- if widget.getParent() == self:
- return
-
- self.adopt(widget, container)
- self.children.insert(beforeIndex, widget)
-
- def remove(self, widget):
- if widget not in self.children:
- return False
-
- self.disown(widget)
- self.children.remove(widget)
- return True
-
-
- class AbsolutePanel(ComplexPanel):
-
- def __init__(self):
- ComplexPanel.__init__(self)
- self.setElement(DOM.createDiv())
- DOM.setStyleAttribute(self.getElement(), "position", "relative")
- DOM.setStyleAttribute(self.getElement(), "overflow", "hidden")
-
- def add(self, widget, left=None, top=None):
- ComplexPanel.add(self, widget, self.getElement())
-
- if left != None:
- self.setWidgetPosition(widget, left, top)
-
- def setWidgetPosition(self, widget, left, top):
- self.checkWidgetParent(widget)
-
- h = widget.getElement()
- if (left == -1) and (top == -1):
- DOM.setStyleAttribute(h, "left", "")
- DOM.setStyleAttribute(h, "top", "")
- DOM.setStyleAttribute(h, "position", "static")
- else:
- DOM.setStyleAttribute(h, "position", "absolute")
- DOM.setStyleAttribute(h, "left", left + "px")
- DOM.setStyleAttribute(h, "top", top + "px")
-
- def getWidgetLeft(self, widget):
- self.checkWidgetParent(widget)
- return DOM.getIntAttribute(widget.getElement(), "offsetLeft")
-
- def getWidgetTop(self, widget):
- self.checkWidgetParent(widget)
- return DOM.getIntAttribute(widget.getElement(), "offsetTop")
-
- def checkWidgetParent(self, widget):
- if widget.getParent() != self:
- console.error("Widget must be a child of this panel.")
-
-
- class Label(Widget):
-
- def __init__(self, text=None, wordWrap=True):
- Widget.__init__(self)
- self.horzAlign = ""
- self.clickListeners = []
- self.mouseListeners = []
-
- self.setElement(DOM.createDiv())
- self.sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS)
- self.setStyleName("gwt-Label")
- if text:
- self.setText(text)
-
- self.setWordWrap(wordWrap)
-
- def addClickListener(self, listener):
- self.clickListeners.append(listener)
-
- def addMouseListener(self, listener):
- self.mouseListeners.append(listener)
-
- def getHorizontalAlignment(self):
- return self.horzAlign
-
- def getText(self):
- return DOM.getInnerText(self.getElement())
-
- def getWordWrap(self):
- return not (DOM.getStyleAttribute(self.getElement(), "whiteSpace") == "nowrap")
-
- def onBrowserEvent(self, event):
- type = DOM.eventGetType(event)
- if type == "click":
- for listener in self.clickListeners:
- if listener.onClick: listener.onClick(self, event)
- else: listener(self, event)
- elif type == "mousedown" or type == "mouseup" or type == "mousemove" or type == "mouseover" or type == "mouseout":
- MouseListener.fireMouseEvent(self, self.mouseListeners, self, event)
-
- def removeClickListener(self, listener):
- self.clickListeners.remove(listener)
-
- def removeMouseListener(self, listener):
- self.mouseListeners.remove(listener)
-
- def setHorizontalAlignment(self, align):
- self.horzAlign = align
- DOM.setStyleAttribute(self.getElement(), "textAlign", align)
-
- def setText(self, text):
- DOM.setInnerText(self.getElement(), text)
-
- def setWordWrap(self, wrap):
- if wrap:
- style = "normal"
- else:
- style = "nowrap"
- DOM.setStyleAttribute(self.getElement(), "whiteSpace", style)
-
-
- class HTML(Label):
-
- def __init__(self, html=None, wordWrap=True):
- Label.__init__(self)
-
- self.setElement(DOM.createDiv())
- self.sinkEvents(Event.ONCLICK | Event.MOUSEEVENTS)
- self.setStyleName("gwt-HTML")
- if html:
- self.setHTML(html)
-
- self.setWordWrap(wordWrap)
-
- def getHTML(self):
- return DOM.getInnerHTML(self.getElement())
-
- def setHTML(self, html):
- DOM.setInnerHTML(self.getElement(), html)
-
-
- class HasHorizontalAlignment:
- ALIGN_LEFT = "left"
- ALIGN_CENTER = "center"
- ALIGN_RIGHT = "right"
-
-
- class HasVerticalAlignment:
- ALIGN_TOP = "top"
- ALIGN_MIDDLE = "middle"
- ALIGN_BOTTOM = "bottom"
-
-
- class HasAlignment:
- ALIGN_BOTTOM = "bottom"
- ALIGN_MIDDLE = "middle"
- ALIGN_TOP = "top"
- ALIGN_CENTER = "center"
- ALIGN_LEFT = "left"
- ALIGN_RIGHT = "right"
-
-
- class CellPanel(ComplexPanel):
-
- def __init__(self):
- ComplexPanel.__init__(self)
-
- self.table = DOM.createTable()
- self.body = DOM.createTBody()
- DOM.appendChild(self.table, self.body)
- self.setElement(self.table)
-
- def getTable(self):
- return self.table
-
- def getBody(self):
- return self.body
-
- def getSpacing(self):
- return self.spacing
-
- def getWidgetTd(self, widget):
- if widget.getParent() != self:
- return None
- return DOM.getParent(widget.getElement())
-
- def setBorderWidth(self, width):
- DOM.setAttribute(self.table, "border", "" + width)
-
- def setCellHeight(self, widget, height):
- td = DOM.getParent(widget.getElement())
- DOM.setAttribute(td, "height", height)
-
- def setCellHorizontalAlignment(self, widget, align):
- td = self.getWidgetTd(widget)
- if td != None:
- DOM.setAttribute(td, "align", align)
-
- def setCellVerticalAlignment(self, widget, align):
- td = self.getWidgetTd(widget)
- if td != None:
- DOM.setStyleAttribute(td, "verticalAlign", align)
-
- def setCellWidth(self, widget, width):
- td = DOM.getParent(widget.getElement())
- DOM.setAttribute(td, "width", width)
-
- def setSpacing(self, spacing):
- self.spacing = spacing
- DOM.setIntAttribute(self.table, "cellSpacing", spacing)
-
-
- class HorizontalPanel(CellPanel):
-
- def __init__(self):
- CellPanel.__init__(self)
-
- self.horzAlign = HasHorizontalAlignment.ALIGN_LEFT
- self.vertAlign = HasVerticalAlignment.ALIGN_TOP
-
- self.tableRow = DOM.createTR()
- DOM.appendChild(self.getBody(), self.tableRow)
-
- DOM.setAttribute(self.getTable(), "cellSpacing", "0")
- DOM.setAttribute(self.getTable(), "cellPadding", "0")
-
- def add(self, widget):
- self.insert(widget, self.getWidgetCount())
-
- def getHorizontalAlignment(self):
- return self.horzAlign
-
- def getVerticalAlignment(self):
- return self.vertAlign
-
- def getWidget(self, index):
- return self.children[index]
-
- def getWidgetCount(self):
- return len(self.children)
-
- def getWidgetIndex(self, child):
- return self.children.index(child)
-
- def insert(self, widget, beforeIndex):
- widget.removeFromParent()
-
- td = DOM.createTD()
- DOM.insertChild(self.tableRow, td, beforeIndex)
-
- CellPanel.insert(self, widget, td, beforeIndex)
-
- self.setCellHorizontalAlignment(widget, self.horzAlign)
- self.setCellVerticalAlignment(widget, self.vertAlign)
-
- def remove(self, widget):
- if widget.getParent() != self:
- return False
-
- td = DOM.getParent(widget.getElement())
- DOM.removeChild(self.tableRow, td)
-
- CellPanel.remove(widget)
- return True
-
- def setHorizontalAlignment(self, align):
- self.horzAlign = align
-
- def setVerticalAlignment(self, align):
- self.vertAlign = align
-
-
- class VerticalPanel(CellPanel):
-
- def __init__(self):
- CellPanel.__init__(self)
-
- self.horzAlign = HasHorizontalAlignment.ALIGN_LEFT
- self.vertAlign = HasVerticalAlignment.ALIGN_TOP
-
- DOM.setAttribute(self.getTable(), "cellSpacing", "0")
- DOM.setAttribute(self.getTable(), "cellPadding", "0")
-
- def add(self, widget):
- self.insert(widget, self.getWidgetCount())
-
- def getHorizontalAlignment(self):
- return self.horzAlign
-
- def getVerticalAlignment(self):
- return self.vertAlign
-
- def getWidget(self, index):
- return self.children[index]
-
- def getWidgetCount(self):
- return len(self.children)
-
- def getWidgetIndex(self, child):
- return self.children.index(child)
-
- def setWidget(self, index, widget):
- """Replace the widget at the given index with a new one"""
- existing = self.getWidget(index)
- if existing:
- self.remove(existing)
- self.insert(widget, index)
-
- def insert(self, widget, beforeIndex):
- widget.removeFromParent()
-
- tr = DOM.createTR()
- td = DOM.createTD()
-
- DOM.insertChild(self.getBody(), tr, beforeIndex)
- DOM.appendChild(tr, td)
-
- CellPanel.insert(self, widget, td, beforeIndex)
-
- self.setCellHorizontalAlignment(widget, self.horzAlign)
- self.setCellVerticalAlignment(widget, self.vertAlign)
-
- def remove(self, widget):
- if pyjslib.isNumber(widget):
- widget = self.getWidget(widget)
-
- if widget.getParent() != self:
- return False
-
- td = DOM.getParent(widget.getElement())
- tr = DOM.getParent(td)
- DOM.removeChild(self.getBody(), tr)
-
- CellPanel.remove(self, widget)
- return True
-
- def setHorizontalAlignment(self, align):
- self.horzAlign = align
-
- def setVerticalAlig…
Large files files are truncated, but you can click here to view the full file