On 28/04/12 02:43, [email protected] wrote:

Comment #12 on issue 715 by [email protected]: Images used by Tree.py and DisclosurePanel.py are not found by pyjd.
http://code.google.com/p/pyjamas/issues/detail?id=715

all right, we'll work something out.


I've had a go at trying to draw the images using GWTCanvas with mixed results. Basically I've replaced the image element in TreeItem by a canvas element and, where the code loaded an image previously, I now draw the image again.

It almost works:
In pyjd/MSHTML, the canvas is redrawn properly when I click on it but the drawing seems to hide the focus element, so one has to poke around to find the outer region of the canvas which responds to a click. In pyjs mode, tested on Firefox and Chrome, the whole canvas area responds to the click but the image doesn't get redrawn properly in spite of the drawing code running. It looks as if canvas.clear() is not working. Does any of this sound like a known problem, or have I just written some crap code?

I have attached my modified version of pyjamas/library/ui/TreeItem.py
# Copyright 2006 James Tauber and contributors
# Copyright (C) 2009 Luke Kenneth Casson Leighton <[email protected]>
# Copyright (C) 2011 Vsevolod Fedorov <[email protected]>
#
# 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 DOM
from pyjamas import Factory
from pyjamas.Canvas.GWTCanvas import GWTCanvas
from pyjamas.Canvas import Color

from pyjamas.ui.UIObject import UIObject
from pyjamas.ui.TreeContentPanel import TreeContentPanel

class TreeItem(UIObject):

    # also callable as TreeItem(widget)
    def __init__(self, html=None, **ka):
        self.children = []
        self.attached = False
        self.contentPanel = None
        self.itemTable = None
        self.contentElem = None
        self.imgElem = None
        self.childSpanElem = None
        self.open = False
        self.parent = None
        self.selected = False
        self.tree = None
        self.userObject = None

        element = ka.pop('Element', None) or DOM.createDiv()
        self.setElement(element)

        self.itemTable = DOM.createTable()
        self.contentElem = DOM.createSpan()
        self.childSpanElem = DOM.createSpan()
        #self.imgElem = DOM.createImg()
        self.canvas = GWTCanvas(16,16,16,16)
        self.imgElem = self.canvas.getCanvasElement()

        tbody = DOM.createTBody()
        tr = DOM.createTR()
        tdImg = DOM.createTD()
        tdContent = DOM.createTD()
        DOM.appendChild(self.itemTable, tbody)
        DOM.appendChild(tbody, tr)
        DOM.appendChild(tr, tdImg)
        DOM.appendChild(tr, tdContent)
        DOM.setStyleAttribute(tdImg, "verticalAlign", "middle")
        DOM.setStyleAttribute(tdContent, "verticalAlign", "middle")
        DOM.setStyleAttribute(self.getElement(), "cursor", "pointer")

        DOM.appendChild(self.getElement(), self.itemTable)
        DOM.appendChild(self.getElement(), self.childSpanElem)
        DOM.appendChild(tdImg, self.imgElem)
        DOM.appendChild(tdContent, self.contentElem)

        # XXX - can't set pos relative on a div node,
        # or white_space on an HTML Table..
        try:
            DOM.setAttribute(self.getElement(), "position", "relative")
        except:
            pass
        DOM.setStyleAttribute(self.contentElem, "display", "inline")
        DOM.setStyleAttribute(self.getElement(), "whiteSpace", "nowrap")
        try:
            DOM.setAttribute(self.itemTable, "whiteSpace", "nowrap")
        except:
            pass
        DOM.setStyleAttribute(self.childSpanElem, "whiteSpace", "nowrap")
        self.setStyleName(self.contentElem, "gwt-TreeItem", True)

        #if not ka.has_key('StyleName'): ka['StyleName']="gwt-TreeItem"

        if html is not None:
            try:
                # messy. pyjd can do unicode, pyjs can't
                if isinstance(html, unicode):
                    ka['HTML'] = html
                elif isinstance(html, basestring):
                    ka['HTML'] = html
                else:
                    ka['Widget'] = html
            except:
                if isinstance(html, basestring):
                    ka['HTML'] = html
                else:
                    ka['Widget'] = html

        UIObject.__init__(self, **ka)

    def __iter__(self):
        return self.children.__iter__()

    # also callable as addItem(widget) and addItem(itemText)
    def addItem(self, item):
        return self.insertItem(item)

    # also callable as addItem(widget) and addItem(itemText)
    def insertItem(self, item, index=None):
        if not hasattr(item, "getTree"):
            #if not item.getTree:
            item = TreeItem(item)

        if (item.getParentItem() is not None) or (item.getTree() is not None):
            item.remove()

        item.setTree(self.tree)
        item.setParentItem(self)
        if index is None:
            self.children.append(item)
        else:
            self.children.insert(index, item)
        DOM.setStyleAttribute(item.getElement(), "marginLeft", "16px")
        if index is None:
            DOM.appendChild(self.childSpanElem, item.getElement())
        else:
            DOM.insertChild(self.childSpanElem, item.getElement(), index)

        if len(self.children) == 1:
            self.updateState()

        return item

    def onAttach(self):
        if self.attached:
            return
        self.attached = True
        for item in self.children:
            item.onAttach()
        w = self.getWidget()
        if w:
           w.onAttach()

    def onDetach(self):
        self.attached = False
        for item in self.children:
            item.onDetach()
        w = self.getWidget()
        if w:
           w.onDetach()

    def getChild(self, index):
        if (index < 0) or (index >= len(self.children)):
            return None

        return self.children[index]

    def getChildCount(self):
        return len(self.children)

    def getChildIndex(self, child):
        return self.children.index(child)

    def getHTML(self):
        return DOM.getInnerHTML(self.contentElem)

    def getText(self):
        return DOM.getInnerText(self.contentElem)

    def getParentItem(self):
        return self.parent

    def getState(self):
        return self.open

    def getTree(self):
        return self.tree

    def getUserObject(self):
        return self.userObject

    def getWidget(self):
        if self.contentPanel is None:
            return None

        return self.contentPanel.getWidget()

    def isSelected(self):
        return self.selected

    def remove(self):
        if self.parent is not None:
            self.parent.removeItem(self)
        elif self.tree is not None:
            self.tree.removeItem(self)

    def removeItem(self, item):
        if item not in self.children:
            return

        item.setTree(None)
        item.setParentItem(None)
        self.children.remove(item)
        DOM.removeChild(self.childSpanElem, item.getElement())
        if len(self.children) == 0:
            self.updateState()

    def removeItems(self):
        while self.getChildCount() > 0:
            self.removeItem(self.getChild(0))

    def setHTML(self, html):
        self.clearContentPanel()
        DOM.setInnerHTML(self.contentElem, html)

    def setText(self, text):
        self.clearContentPanel()
        DOM.setInnerText(self.contentElem, text)

    def setSelected(self, selected):
        if self.selected == selected:
            return
        self.selected = selected
        self.setStyleName(self.contentElem, "gwt-TreeItem-selected", selected)

    def setState(self, open, fireEvents=True):

        # lkcl: experiment with allowing event state changed to be
        # fired even on items with no children.  otherwise you never
        # get to find out if an end-item was selected!
        if not open or len(self.children) != 0:
            self.open = open
            self.updateState()

        if fireEvents:
            self.tree.fireStateChanged(self)

    def setUserObject(self, userObj):
        self.userObject = userObj

    def setWidget(self, widget):
        self.ensureContentPanel()
        self.contentPanel.setWidget(widget)

    def clearContentPanel(self):
        if self.contentPanel is not None:
            child = self.contentPanel.getWidget()
            if child is not None:
                self.contentPanel.remove(child)

            if self.tree is not None:
                self.tree.disown(self.contentPanel)
                self.contentPanel = None

    def ensureContentPanel(self):
        if self.contentPanel is None:
            DOM.setInnerHTML(self.contentElem, "")
            self.contentPanel = TreeContentPanel(self.contentElem)
            self.contentPanel.setTreeItem(self)
            if self.getTree() is not None:
                self.tree.adopt(self.contentPanel)

    def addTreeItems(self, accum):
        for item in self.children:
            accum.append(item)
            item.addTreeItems(accum)

    def getChildren(self):
        return self.children

    def getContentElem(self):
        return self.contentElem

    def getContentHeight(self):
        return DOM.getIntAttribute(self.itemTable, "offsetHeight")

    def getImageElement(self):
        return self.imgElem

    def getTreeTop(self):
        item = self
        ret = 0

        while item is not None:
            ret += DOM.getIntAttribute(item.getElement(), "offsetTop")
            item = item.getParentItem()

        return ret

    def getFocusableWidget(self):
        widget = self.getWidget()
        if hasattr(widget, "setFocus"):
            return widget
        return None

    def imgSrc(self, img):
        if self.tree is None:
            return img
        src = self.tree.getImageBase() + img
        return src

    def setParentItem(self, parent):
        self.parent = parent

    def setTree(self, tree):
        if self.tree == tree:
            return

        if self.tree is not None:
            if self.tree.getSelectedItem() == self:
                self.tree.setSelectedItem(None)

            if self.contentPanel is not None:
                self.tree.disown(self.contentPanel)

        self.tree = tree
        for child in self.children:
            child.setTree(tree)
        self.updateState()
        if tree is not None and self.contentPanel is not None:
                tree.adopt(self.contentPanel)

    def updateState(self):
        print "updateState"
        if not self.tree: return
        if len(self.children) == 0:
            self.setVisible(self.childSpanElem, False)
            #DOM.setAttribute(self.imgElem, "src", self.imgSrc("tree_white.gif"))
            self.drawImage("white")
            return

        if self.open:
            self.setVisible(self.childSpanElem, True)
            #DOM.setAttribute(self.imgElem, "src", self.imgSrc("tree_open.gif"))
            self.drawImage("open")
        else:
            self.setVisible(self.childSpanElem, False)
            #DOM.setAttribute(self.imgElem, "src", self.imgSrc("tree_closed.gif"))
            self.drawImage("closed")

    def updateStateRecursive(self):
        self.updateState()
        for i in range(len(self.children)):
            child = self.children[i]
            child.updateStateRecursive()

    def drawImage(self, mode):
        canvas = self.canvas
        canvas.clear()
        if mode == "white": return
        canvas.setLineWidth(1)
        canvas.setStrokeStyle(Color.Color("#cccccc"))
        canvas.strokeRect(4,4,8,8)
        canvas.setStrokeStyle(Color.Color("#888888"))
        canvas.moveTo(5,8)
        canvas.lineTo(11,8)
        if mode == "closed":
            canvas.moveTo(8,5)
            canvas.lineTo(8,11)
        canvas.stroke()


class RootTreeItem(TreeItem):
    def addItem(self, item):
        self.insertItem(item)

    def insertItem(self, item, index=None):
        if (item.getParentItem() is not None) or (item.getTree() is not None):
            item.remove()
        item.setTree(self.getTree())

        item.setParentItem(None)
        if index is None:
            self.children.append(item)
        else:
            self.children.insert(index, item)

        DOM.setIntStyleAttribute(item.getElement(), "marginLeft", 0)

    def removeItem(self, item):
        if item not in self.children:
            return

        item.setTree(None)
        item.setParentItem(None)
        self.children.remove(item)

Factory.registerClass('pyjamas.ui.TreeItem', 'TreeItem', TreeItem)

Reply via email to