Package pyjamas :: Package ui :: Module HTMLTable
[hide private]
[frames] | no frames]

Source Code for Module pyjamas.ui.HTMLTable

  1  # Copyright 2006 James Tauber and contributors 
  2  # Copyright (C) 2009 Luke Kenneth Casson Leighton <lkcl@lkcl.net> 
  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  from pyjamas import DOM 
 16  from pyjamas import Factory 
 17   
 18  from Panel import Panel 
 19  from pyjamas.ui import Event 
 20  from CellFormatter import CellFormatter 
 21  from RowFormatter import RowFormatter 
 22   
 23  widgethash = {} 
 24   
25 -class HTMLTable(Panel):
26
27 - def __init__(self, **kwargs):
28 if not kwargs.has_key('CellFormatter'): 29 kwargs['CellFormatter'] = CellFormatter(self) 30 if not kwargs.has_key('RowFormatter'): 31 kwargs['RowFormatter'] = RowFormatter(self) 32 33 self.tableListeners = [] 34 self.widgetMap = {} 35 36 if kwargs.has_key('Element'): 37 self.tableElem = kwargs.pop('Element') 38 fc = DOM.getFirstChild(self.tableElem) 39 if fc: 40 self.bodyElem = fc 41 else: 42 self.bodyElem = DOM.createTBody() 43 DOM.appendChild(self.tableElem, self.bodyElem) 44 else: 45 self.tableElem = DOM.createTable() 46 self.bodyElem = DOM.createTBody() 47 DOM.appendChild(self.tableElem, self.bodyElem) 48 self.setElement(self.tableElem) 49 50 self.sinkEvents(Event.ONCLICK) 51 52 Panel.__init__(self, **kwargs)
53
54 - def addTableListener(self, listener):
55 self.tableListeners.append(listener)
56
57 - def clear(self):
58 for row in range(self.getRowCount()): 59 for col in range(self.getCellCount(row)): 60 child = self.getWidget(row, col) 61 if child is not None: 62 self.removeWidget(child)
63 # assert len(self.widgetMap) == 0 64
65 - def clearCell(self, row, column):
66 td = self.cellFormatter.getElement(row, column) 67 return self.internalClearCell(td)
68
69 - def getCellCount(self, row):
70 return 0
71
72 - def getCellFormatter(self):
73 return self.cellFormatter
74
75 - def getCellPadding(self):
76 return DOM.getIntAttribute(self.tableElem, "cellPadding")
77
78 - def getCellSpacing(self):
79 return DOM.getIntAttribute(self.tableElem, "cellSpacing")
80
81 - def getHTML(self, row, column):
82 element = self.cellFormatter.getElement(row, column) 83 return DOM.getInnerHTML(element)
84
85 - def getRowCount(self):
86 return 0
87
88 - def getRowFormatter(self):
89 return self.rowFormatter
90
91 - def getText(self, row, column):
92 self.checkCellBounds(row, column) 93 element = self.cellFormatter.getElement(row, column) 94 return DOM.getInnerText(element)
95 96 # also callable as getWidget(widgetElement)
97 - def getWidget(self, row, column=None):
98 if column is None: 99 key = self.computeKeyForElement(row) 100 else: 101 self.checkCellBounds(row, column) 102 key = self.computeKey(row, column) 103 104 if key is None: 105 return None 106 return self.widgetMap[key]
107
108 - def isCellPresent(self, row, column):
109 # GWT uses "and", possibly a bug 110 if row >= self.getRowCount() or row < 0: 111 return False 112 113 if column < 0 or column >= self.getCellCount(row): 114 return False 115 116 return True
117
118 - def __iter__(self):
119 return self.widgetMap.itervalues()
120
121 - def onBrowserEvent(self, event):
122 if DOM.eventGetType(event) == "click": 123 td = self.getEventTargetCell(event) 124 if not td: 125 return 126 127 tr = DOM.getParent(td) 128 body = DOM.getParent(tr) 129 row = DOM.getChildIndex(body, tr) 130 column = DOM.getChildIndex(tr, td) 131 132 for listener in self.tableListeners: 133 if hasattr(listener, 'onCellClicked'): 134 listener.onCellClicked(self, row, column) 135 else: 136 listener(self)
137
138 - def remove(self, widget):
139 if widget.getParent() != self: 140 return False 141 142 self.removeWidget(widget) 143 return True
144
145 - def removeTableListener(self, listener):
146 self.tableListeners.remove(listener)
147
148 - def setBorderWidth(self, width):
149 DOM.setAttribute(self.tableElem, "border", str(width))
150
151 - def setCellPadding(self, padding):
152 DOM.setAttribute(self.tableElem, "cellPadding", str(padding))
153
154 - def setCellSpacing(self, spacing):
155 DOM.setAttribute(self.tableElem, "cellSpacing", str(spacing))
156
157 - def setHTML(self, row, column, html):
158 self.prepareCell(row, column) 159 td = self.cleanCell(row, column) 160 if html is not None: 161 DOM.setInnerHTML(td, html)
162
163 - def setText(self, row, column, text):
164 self.prepareCell(row, column) 165 td = self.cleanCell(row, column) 166 if text is not None: 167 DOM.setInnerText(td, text)
168
169 - def setWidget(self, row, column, widget):
170 self.prepareCell(row, column) 171 if widget is None: 172 return 173 174 widget.removeFromParent() 175 td = self.cleanCell(row, column) 176 widget_hash = widget 177 element = widget.getElement() 178 widgethash[element] = widget_hash 179 self.widgetMap[widget_hash] = widget 180 self.adopt(widget, td)
181
182 - def cleanCell(self, row, column):
183 td = self.cellFormatter.getRawElement(row, column) 184 self.internalClearCell(td) 185 return td
186
187 - def computeKey(self, row, column):
188 element = self.cellFormatter.getRawElement(row, column) 189 child = DOM.getFirstChild(element) 190 if child is None: 191 return None 192 193 return self.computeKeyForElement(child)
194
195 - def computeKeyForElement(self, widgetElement):
196 return widgethash.get(widgetElement)
197
198 - def removeWidget(self, widget):
199 self.disown(widget) 200 element = widget.getElement() 201 del self.widgetMap[self.computeKeyForElement(element)] 202 del widgethash[element] 203 return True
204
205 - def checkCellBounds(self, row, column):
206 self.checkRowBounds(row) 207 #if column<0: raise IndexError, "Column " + column + " must be non-negative: " + column 208 209 cellSize = self.getCellCount(row)
210 #if cellSize<column: raise IndexError, "Column " + column + " does not exist, col at row " + row + " size is " + self.getCellCount(row) + "cell(s)" 211
212 - def checkRowBounds(self, row):
213 rowSize = self.getRowCount()
214 #if row >= rowSize or row < 0: raise IndexError, "Row " + row + " does not exist, row size is " + self.getRowCount() 215
216 - def createCell(self):
217 return DOM.createTD()
218
219 - def getBodyElement(self):
220 return self.bodyElem
221 222 # also callable as getDOMCellCount(row)
223 - def getDOMCellCount(self, element, row=None):
224 if row is None: 225 return self.getDOMCellCountImpl(self.bodyElem, element) 226 return self.getDOMCellCountImpl(element, row)
227
228 - def getDOMCellCountImpl(self, element, row):
229 return element.rows.item(row).cells.length
230 231 # also callable as getDOMRowCount(element)
232 - def getDOMRowCount(self, element=None):
233 if element is None: 234 element = self.bodyElem 235 return self.getDOMRowCountImpl(element)
236
237 - def getDOMRowCountImpl(self, element):
238 return element.rows.length
239
240 - def getEventTargetCell(self, event):
241 td = DOM.eventGetTarget(event) 242 while td is not None: 243 if DOM.getAttribute(td, "tagName").lower() == "td": 244 tr = DOM.getParent(td) 245 body = DOM.getParent(tr) 246 if DOM.compare(body, self.bodyElem): 247 return td 248 if DOM.compare(td, self.bodyElem): 249 return None 250 td = DOM.getParent(td) 251 252 return None
253
254 - def insertCell(self, row, column):
255 tr = self.rowFormatter.getRow(self.bodyElem, row) 256 td = self.createCell() 257 DOM.insertChild(tr, td, column)
258
259 - def insertCells(self, row, column, count):
260 tr = self.rowFormatter.getRow(self.bodyElem, row) 261 for i in range(column, column + count): 262 td = self.createCell() 263 DOM.insertChild(tr, td, i)
264
265 - def insertRow(self, beforeRow):
266 if beforeRow != self.getRowCount(): 267 self.checkRowBounds(beforeRow) 268 269 tr = DOM.createTR() 270 DOM.insertChild(self.bodyElem, tr, beforeRow) 271 return beforeRow
272
273 - def internalClearCell(self, td):
274 maybeChild = DOM.getFirstChild(td) 275 widget = None 276 if maybeChild is not None: 277 widget = self.getWidget(maybeChild) 278 279 if widget is not None: 280 self.removeWidget(widget) 281 return True 282 283 DOM.setInnerHTML(td, "") 284 return False
285
286 - def prepareCell(self, row, column):
287 pass
288
289 - def prepareRow(self, row):
290 pass
291
292 - def removeCell(self, row, column):
293 self.checkCellBounds(row, column) 294 td = self.cleanCell(row, column) 295 tr = self.rowFormatter.getRow(self.bodyElem, row) 296 DOM.removeChild(tr, td)
297
298 - def removeRow(self, row):
299 for column in range(self.getCellCount(row)): 300 self.cleanCell(row, column) 301 DOM.removeChild(self.bodyElem, self.rowFormatter.getRow(self.bodyElem, row))
302
303 - def setCellFormatter(self, cellFormatter):
304 self.cellFormatter = cellFormatter
305
306 - def setRowFormatter(self, rowFormatter):
307 self.rowFormatter = rowFormatter
308 309 Factory.registerClass('pyjamas.ui.HTMLTable', HTMLTable) 310