class LoggerPanel(DisclosurePanel): def __init__(self, maxhistory=100, maxloglinelength=200, headerStyleName=None, panelStyleName=None, buttonStyleName=None, labelStyleName=None): super(LoggerPanel, self).__init__(self, header='BLAH', isOpen=False) self.labelStyleName = labelStyleName self.maxhistory = maxhistory self.maxloglinelength = maxloglinelength self.getHeader().setStyleName(headerStyleName) self.logpanel = VerticalPanel(StyleName=panelStyleName) self.setContent(self.logpanel) self.clearbutton = Button('Clear', listener=self.clear, StyleName=buttonStyleName) self.logpanel.add(self.clearbutton) self.updateHeaderText() def log(self, string): self.logpanel.add(Label(string[:self.maxloglinelength], StyleName=self.labelStyleName)) widgcnt = self.logpanel.getWidgetCount() if widgcnt > self.maxhistory: for i in range(0, widgcnt - self.maxhistory): self.logpanel.remove(self.logpanel.getWidget(i)) self.updateHeaderText() def __call__(self, string): self.log(string) return def updateHeaderText(self): self.getHeader().setText('Logging: %s items' % (self.logpanel.getWidgetCount() - 1)) def clear(self): self.logpanel.clear() self.logpanel.add(self.clearbutton) self.updateHeaderText()
class ContentPanel(HorizontalPanel): def __init__(self, onItemPublish, onItemLike, onItemDislike, onSort=None, onFilter=None): super(ContentPanel, self).__init__() self.newItemArgs = {'onPublish':onItemPublish, 'onLike':onItemLike, 'onDislike':onItemDislike} self.sidebar = SideVerticalToolbar(onSort=onSort, onFilter=onFilter) text = '<br>'.join(list('More Tools')) self.sidebarEdge = Button(text, listener=self.onSidebarEdgeClick, StyleName=Styles.TOOLBAR_VERTICALEDGE) self.add(self.sidebarEdge) self.contentpanel = VerticalPanel() self.add(self.contentpanel) self.allContentCells = [] return def _getAllContentItemCells(self): for widg in self.contentpanel.getChildren(): if isinstance(widg, ContentItemCell): yield widg def addItems(self, items): for item in items: widg = ContentItemCell(item, **self.newItemArgs) self.contentpanel.add(widg) self.allContentCells.append(widg) def itemCount(self): return len(self.allContentCells) def onSidebarEdgeClick(self): #If parent is set, hide it- otherwise, remove it if self.sidebar.parent: self.sidebar.removeFromParent() else: self.insert(self.sidebar, 0) def setItemsOpenState(self, state): for cell in self._getAllContentItemCells(): cell.setOpen(state) def sortItems(self, keyselector, ascending): allchildren = list(self.contentpanel.getChildren()) self.contentpanel.clear() sall = sorted(allchildren, key=keyselector) if not ascending: sall = reversed(sall) for child in sall: self.contentpanel.add(child) def filterItems(self, predicate): self.contentpanel.clear() cellsToShow = [cell for cell in self.allContentCells if predicate(cell)] for cell in cellsToShow: self.contentpanel.add(cell)
class Chapter(Sink): def __init__(self): Sink.__init__(self) self.vp = VerticalPanel() self.initWidget(self.vp) self.loaded = False def onShow(self): if self.loaded: return self.name = self.name.replace(" ", "_") self.name = self.name.lower() HTTPRequest().asyncGet("%s.txt" % self.name, ChapterLoader(self)) def setChapter(self, text): self.loaded = True self.text = text + '\n' self.ul_stack1 = 0 self.ul_stack2 = 0 self.doing_code = 0 self.custom_style = False self.txt = '' self.para = '' self.up_to = 0 Timer(1, self) def onTimer(self, timer): count = 0 while count < 10: count += 1 idx = self.text.find("\n", self.up_to) if idx < 0: self.text = None break self.process_line(self.text[self.up_to:idx]) self.up_to = idx+1 if self.text: timer.schedule(1) def process_line(self, line): if self.doing_code: if line == "}}": self.doing_code = 0 self.custom_style = False line = "</pre>" self.txt += line panel = sect_markup(self.txt, self.name) self.vp.add(panel) self.txt = '' return if line: if not self.custom_style: self.txt += escape(line) else: self.txt += line self.txt += "\n" return line = line.strip() ul_line = False ul_line2 = False addline = '' add = False addpara = False if not line: line = "" addpara = True elif line[:2] == "{{": self.doing_code = 1 addpara = True if len(line) > 4 and line[2] == '-': addline = "<pre class='chapter_%s'>" % line[3:] self.custom_style = True elif len(line) > 2: addline = "<pre class='chapter_code'>%s" % line[2:] else: addline = "<pre class='chapter_code'>" elif line[:2] == '= ' and line[-2:] == ' =': addline = "<h1 class='chapter_heading1>%s</h1>" % qr(line[2:-2]) add = True addpara = True elif line[:3] == '== ' and line[-3:] == ' ==': addline = "<h2 class='chapter_heading2>%s</h2>" % qr(line[3:-3]) add = True addpara = True elif line[:2] == '* ': if not self.ul_stack1: self.txt += "<ul class='chapter_list1'>\n" addline = "<li class='chapter_listitem1'/>%s\n" % ts(line[2:], 0) self.ul_stack1 = True ul_line = True addpara = True elif line[:3] == '** ': if not self.ul_stack2: self.txt += "<ul class='chapter_list2'>\n" addline = "<li class='chapter_listitem2'/>%s\n" % ts(line[2:], 0) self.ul_stack2 = True ul_line2 = True ul_line = True if self.ul_stack2 and not ul_line2: self.ul_stack2 = False self.txt += "</ul>\n" if self.ul_stack1 and not ul_line: self.ul_stack1 = False self.txt += "</ul>\n" if addline: self.txt += addline + "\n" elif line: line = line.replace("%", "%") self.para += line + "\n" if not self.ul_stack2 and not self.ul_stack1 and not self.doing_code : add = True if self.para and addpara: self.para = "<p class='chapter_para'>%s</p>" % urlmap(self.para, 0) panel = sect_markup(self.para, self.name) self.vp.add(panel) self.para = '' if add: panel = sect_markup(self.txt, self.name) self.vp.add(panel) self.txt = '' def onError(self, text, code): self.vp.clear() self.vp.add(HTML("TODO: Chapter '%s' not loaded" % self.name)) self.vp.add(HTML(text)) self.vp.add(HTML(code))
class SWFUploadExample(SWFUploadInterface): def onModuleLoad(self): self.panel = VerticalPanel() self.panel.setSpacing(10) RootPanel().add(self.panel) self.swfUpload = self.getSWFUpload() self.panel.add(self.swfUpload) self.fileids = [] self.queue = VerticalPanel() self.panel.add(self.queue) startButton = Button('Start Upload') startButton.addClickListener(getattr(self, 'onStartUpload')) self.panel.add(startButton) self.progress = Label() self.panel.add(self.progress) def getSWFUpload(self): swfUpload = SWFUpload() swfUpload.setSettings(self.getSettings()) swfUpload.setID('SWFUploadPanel') return swfUpload def showQueue(self): self.queue.clear() for fileid in self.fileids: file = self.swfUpload.getFile(fileid) label = Label('%s (%s Bytes)' % (file.name, file.size)) self.queue.add(label) def getSettings(self): settings = Settings() settings.setURL('upload.html') settings.setButtonHTML('<span class="uploadButton">add Files</span>') settings.setButtonCSS( '.uploadButton { font-size: 12; font-weight: bold; }') settings.setButtonWidth(60) settings.setButtonHeight(25) settings.setButtonTopPadding(10) settings.setButtonLeftPadding(5) settings.setEventListener(self) settings.setFlashURL('swf/swfupload.swf') return settings def onStartUpload(self): #log.writebr('Starting Upload') self.swfUpload.startUpload() """ SWFUpload Events """ def swfUploadLoaded(self): #log.writebr('swfUploadLoaded') pass def uploadProgress(self, file, bytesLoaded, totalBytes): self.progress.setText('%s - %s of %s uploaded' % (file.name, bytesLoaded, totalBytes)) def uploadError(self, file, errorCode, message): log.writebr('uploadError: %s, %s' % (errorCode, message)) def uploadSuccess(self, file, receivedResponse, serverData): self.fileids.remove(file.id) self.showQueue() def uploadComplete(self, file): #log.writebr('uploadComplete: %s' % file.name) if len(self.fileids) > 0: self.swfUpload.startUpload() else: self.progress.setText('All files uploaded') def fileDialogStart(self): #log.writebr('fileDialogStart') pass def fileQueued(self, file): #log.writebr('fileQueued: %s' % file.name) self.fileids.append(file.id) def fileQueueError(self, file, errorCode, message): log.writebr('fileQueueError: %s, %s' % (errorCode, message)) def fileDialogComplete(self, sel, qu, tqu): #log.writebr('fileDialogComplete: %s, %s, %s' % (sel, qu, tqu)) self.showQueue() def uploadStart(self, file): #log.writebr('uploadStart') # Do something before the upload starts, and return True to start the upload return True
class SWFUploadExample(SWFUploadInterface): def onModuleLoad(self): self.panel = VerticalPanel() self.panel.setSpacing(10) RootPanel().add(self.panel) self.swfUpload = self.getSWFUpload() self.panel.add(self.swfUpload) self.fileids = [] self.queue = VerticalPanel() self.panel.add(self.queue) startButton = Button('Start Upload') startButton.addClickListener(getattr(self, 'onStartUpload')) self.panel.add(startButton) self.progress = Label() self.panel.add(self.progress) def getSWFUpload(self): swfUpload = SWFUpload() swfUpload.setSettings(self.getSettings()) swfUpload.setID('SWFUploadPanel') return swfUpload def showQueue(self): self.queue.clear() for fileid in self.fileids: file = self.swfUpload.getFile(fileid) label = Label('%s (%s Bytes)' % (file.name, file.size)) self.queue.add(label) def getSettings(self): settings = Settings() settings.setURL('upload.html') settings.setButtonHTML('<span class="uploadButton">add Files</span>') settings.setButtonCSS('.uploadButton { font-size: 12; font-weight: bold; }') settings.setButtonWidth(60) settings.setButtonHeight(25) settings.setButtonTopPadding(10) settings.setButtonLeftPadding(5) settings.setEventListener(self) settings.setFlashURL('swf/swfupload.swf') return settings def onStartUpload(self): #log.debug('Starting Upload') self.swfUpload.startUpload() """ SWFUpload Events """ def swfUploadLoaded(self): #log.debug('swfUploadLoaded') pass def uploadProgress(self, file, bytesLoaded, totalBytes): self.progress.setText('%s - %s of %s uploaded' % (file.name, bytesLoaded, totalBytes)) def uploadError(self, file, errorCode, message): log.debug('uploadError: %s, %s' % (errorCode, message)) def uploadSuccess(self, file, receivedResponse, serverData): self.fileids.remove(file.id) self.showQueue() def uploadComplete(self, file): #log.debug('uploadComplete: %s' % file.name) if len(self.fileids) > 0: self.swfUpload.startUpload() else: self.progress.setText('All files uploaded') def fileDialogStart(self): #log.debug('fileDialogStart') pass def fileQueued(self, file): #log.debug('fileQueued: %s' % file.name) self.fileids.append(file.id) def fileQueueError(self, file, errorCode, message): log.debug('fileQueueError: %s, %s' % (errorCode, message)) def fileDialogComplete(self, sel, qu, tqu): #log.debug('fileDialogComplete: %s, %s, %s' % (sel, qu, tqu)) self.showQueue() def uploadStart(self, file): #log.debug('uploadStart') # Do something before the upload starts, and return True to start the upload return True
class Chapter(Sink): def __init__(self): Sink.__init__(self) self.vp = VerticalPanel() self.initWidget(self.vp) self.loaded = False def onShow(self): if self.loaded: return self.name = self.name.replace(" ", "_") self.name = self.name.lower() HTTPRequest().asyncGet("%s.txt" % self.name, ChapterLoader(self)) def setChapter(self, text): self.loaded = True self.text = text + '\n' self.ul_stack1 = 0 self.ul_stack2 = 0 self.doing_code = 0 self.custom_style = False self.txt = '' self.para = '' self.up_to = 0 Timer(1, self) def onTimer(self, sender): count = 0 while count < 10: count += 1 idx = self.text.find("\n", self.up_to) if idx < 0: self.text = None break self.process_line(self.text[self.up_to:idx]) self.up_to = idx+1 if self.text: Timer(1, self) def process_line(self, line): if self.doing_code: if line == "}}": self.doing_code = 0 self.custom_style = False line = "</pre>" self.txt += line panel = sect_markup(self.txt, self.name) self.vp.add(panel) self.txt = '' return if line: if not self.custom_style: self.txt += escape(line) else: self.txt += line self.txt += "\n" return line = line.strip() ul_line = False ul_line2 = False addline = '' add = False addpara = False if not line: line = "" addpara = True elif line[:2] == "{{": self.doing_code = 1 addpara = True if len(line) > 4 and line[2] == '-': addline = "<pre class='chapter_%s'>" % line[3:] self.custom_style = True elif len(line) > 2: addline = "<pre class='chapter_code'>%s" % line[2:] else: addline = "<pre class='chapter_code'>" elif line[:2] == '= ' and line[-2:] == ' =': addline = "<h1 class='chapter_heading1>%s</h1>" % qr(line[2:-2]) add = True addpara = True elif line[:3] == '== ' and line[-3:] == ' ==': addline = "<h2 class='chapter_heading2>%s</h2>" % qr(line[3:-3]) add = True addpara = True elif line[:2] == '* ': if not self.ul_stack1: self.txt += "<ul class='chapter_list1'>\n" addline = "<li class='chapter_listitem1'/>%s\n" % ts(line[2:], 0) self.ul_stack1 = True ul_line = True addpara = True elif line[:3] == '** ': if not self.ul_stack2: self.txt += "<ul class='chapter_list2'>\n" addline = "<li class='chapter_listitem2'/>%s\n" % ts(line[2:], 0) self.ul_stack2 = True ul_line2 = True ul_line = True if self.ul_stack2 and not ul_line2: self.ul_stack2 = False self.txt += "</ul>\n" if self.ul_stack1 and not ul_line: self.ul_stack1 = False self.txt += "</ul>\n" if addline: self.txt += addline + "\n" elif line: line = line.replace("%", "%") self.para += line + "\n" if not self.ul_stack2 and not self.ul_stack1 and not self.doing_code : add = True if self.para and addpara: self.para = "<p class='chapter_para'>%s</p>" % urlmap(self.para, 0) panel = sect_markup(self.para, self.name) self.vp.add(panel) self.para = '' if add: panel = sect_markup(self.txt, self.name) self.vp.add(panel) self.txt = '' def onError(self, text, code): self.vp.clear() self.vp.add(HTML("TODO: Chapter '%s' not loaded" % self.name)) self.vp.add(HTML(text)) self.vp.add(HTML(code))
class Photos(Composite): def __init__(self): Composite.__init__(self) self.albums = [] self.photos = [] self.grid = Grid(4, 4, CellPadding=4, CellSpacing=4) self.grid.addTableListener(self) self.drill = 0 self.pos = 0 self.up = Button("Up", self) self.next = Button("Next", self) self.prev = Button("Prev", self) self.timer = Timer(notify=self) self.userid = "jameskhedley" self.album_url = "http://picasaweb.google.com/data/feed/base/user/" + self.userid + "?alt=json-in-script&kind=album&hl=en_US&callback=restCb" self.doRESTQuery(self.album_url, self.timer) self.vp = VerticalPanel() self.disclosure = DisclosurePanel( "Click for boring technical details.") self.disclosure.add( HTML( '''<p>OK so you want to write client JS to do a RESTful HTTP query from picasa right? Well you can't because of the Same Origin Policy. Basically this means that because the domain of the query and the domain of the hosted site are different, then that could well be a cross-site scripting (XSS) attack. So, the workaround is to do the call from a script tag so the JSON we get back is part of the document. But since we don't know what URL to hit yet, once we find out then we have to inject a new script tag dynamically which the browser will run as soon as we append it. To be honest I'm not 100% why Google use RESTful services and not JSON-RPC or somesuch, which would be easier. Well, easier for me.''')) self.IDPanel = HorizontalPanel() self.IDPanel.add(Label("Enter google account:")) self.IDButton = Button("Go", self) self.IDBox = TextBox() self.IDBox.setText(self.userid) self.IDPanel.add(self.IDBox) self.IDPanel.add(self.IDButton) self.vp.add(self.IDPanel) self.vp.add(self.disclosure) self.vp.add(self.grid) self.initWidget(self.vp) def doRESTQuery(self, url, timer): """this is a totally different from an RPC call in that we have to dynamically add script tags to the DOM when we want to query the REST API. These rely on callbacks in the DOM so we can either add them dynamically or pre-define them in public/Main.html. Once we've done that have to wait for the response. Which means we need to provide a listener for the timer""" new_script = DOM.createElement("script") DOM.setElemAttribute(new_script, "src", url) DOM.setElemAttribute(new_script, "type", "text/javascript") doc().body.appendChild(new_script) self.timer.schedule(100) def onCellClicked(self, sender, row, col): if self.drill == 0: self.drill += 1 self.vp.clear() self.grid.clear() self.vp.add(self.up) self.vp.add(self.grid) gridcols = self.grid.getColumnCount() album = self.albums[row + col + (row * (gridcols - 1))] url = "http://picasaweb.google.com/data/feed/base/user/" + self.userid + "/albumid/" + album[ "id"] + "?alt=json-in-script&kind=photo&hl=en_US&callback=restCb" self.doRESTQuery(url, self.timer) elif self.drill == 1: self.drill += 1 gridcols = self.grid.getColumnCount() self.pos = row + col + (row * (gridcols - 1)) photo = self.photos[self.pos] self.vp.clear() self.fullsize = HTML('<img src="' + photo["full"] + '"/>') hp = HorizontalPanel() hp.add(self.up) hp.add(self.prev) hp.add(self.next) hp.setSpacing(8) self.vp.add(hp) self.vp.add(self.fullsize) def onClick(self, sender): if sender == self.IDButton: self.userid = self.IDBox.getText() if self.userid == "" or self.userid.isdigit(): return self.drill = 0 self.album_url = "http://picasaweb.google.com/data/feed/base/user/" + self.userid + "?alt=json-in-script&kind=album&hl=en_US&callback=restCb" self.grid.clear() self.doRESTQuery(self.album_url, self.timer) else: if self.drill == 2: if sender == self.up: self.drill = 1 self.vp.clear() self.vp.add(self.up) self.vp.add(self.grid) self.fillGrid(self.photos, "photos") else: if sender == self.next: if self.pos >= len(self.photos): return self.pos += 1 elif sender == self.prev: if self.pos < 1: return self.pos -= 1 photo = self.photos[self.pos] self.fullsize.setHTML('<img src="' + photo["full"] + '"/>') elif self.drill == 1: self.drill = 0 self.vp.clear() self.vp.add(self.IDPanel) self.vp.add(self.disclosure) self.vp.add(self.grid) self.fillGrid(self.albums, "albums") def onTimer(self, timer): fd = doc().getElementById("__pygwt_hiddenData") receiver = fd.innerHTML if receiver == 'wait': self.timer.schedule(1000) return fd.innerHTML = 'wait' if self.drill == 0: self.parseAlbums(receiver) self.fillGrid(self.albums, "albums") elif self.drill == 1: self.parsePhotos(receiver) self.fillGrid(self.photos, "photos") def fillGrid(self, items, type): self.grid.clear() cols = self.grid.getColumnCount() self.grid.resizeRows((len(items) / cols) + 1) rows = self.grid.getRowCount() for i in range(len(items)): vp = VerticalPanel() if type == 'photos': vp.add(items[i]['thumb']) else: vp.add(items[i]['thumb']) vp.add(items[i]['title']) self.grid.setWidget(int(i / cols), i % cols, vp) def parsePhotos(self, items): photo_list = json.loads(items) self.photos = [] for ph in photo_list: aphoto = {} aphoto['thumb'] = HTML( '<img src="' + ph[u"media$group"][u"media$thumbnail"][1][u"url"] + '"/>') aphoto['full'] = ph[u"media$group"][u"media$content"][0][u"url"] self.photos.append(aphoto) def parseAlbums(self, items): album_list = json.loads(items) self.albums = [] for al in album_list: analbum = {} analbum['title'] = HTML(al[u"title"][u"$t"]) analbum['thumb'] = HTML( '<img src="' + al[u"media$group"][u"media$thumbnail"][0][u"url"] + '"/>') url = al[u"id"][u"$t"] analbum['id'] = url.split(u'albumid/')[1].split(u'?alt')[0] self.albums.append(analbum)
class Photos(Composite): def __init__(self): Composite.__init__(self) self.albums = [] self.photos = [] self.grid = Grid(4, 4, CellPadding=4, CellSpacing=4) self.grid.addTableListener(self) self.drill = 0 self.pos = 0 self.up = Button("Up", self) self.next = Button("Next", self) self.prev = Button("Prev", self) self.timer = Timer(notify=self) self.userid = "jameskhedley" self.album_url = "http://picasaweb.google.com/data/feed/base/user/" + self.userid + "?alt=json-in-script&kind=album&hl=en_US&callback=restCb" self.doRESTQuery(self.album_url, self.timer) self.vp = VerticalPanel() self.disclosure = DisclosurePanel("Click for boring technical details.") self.disclosure.add(HTML('''<p>OK so you want to write client JS to do a RESTful HTTP query from picasa right? Well you can't because of the Same Origin Policy. Basically this means that because the domain of the query and the domain of the hosted site are different, then that could well be a cross-site scripting (XSS) attack. So, the workaround is to do the call from a script tag so the JSON we get back is part of the document. But since we don't know what URL to hit yet, once we find out then we have to inject a new script tag dynamically which the browser will run as soon as we append it. To be honest I'm not 100% why Google use RESTful services and not JSON-RPC or somesuch, which would be easier. Well, easier for me.''')) self.IDPanel = HorizontalPanel() self.IDPanel.add(Label("Enter google account:")) self.IDButton = Button("Go", self) self.IDBox = TextBox() self.IDBox.setText(self.userid) self.IDPanel.add(self.IDBox) self.IDPanel.add(self.IDButton) self.vp.add(self.IDPanel) self.vp.add(self.disclosure) self.vp.add(self.grid) self.initWidget(self.vp) def doRESTQuery(self, url, timer): """this is a totally different from an RPC call in that we have to dynamically add script tags to the DOM when we want to query the REST API. These rely on callbacks in the DOM so we can either add them dynamically or pre-define them in public/Main.html. Once we've done that have to wait for the response. Which means we need to provide a listener for the timer""" JS("$wnd.receiver = 'wait'") new_script = DOM.createElement("script") DOM.setElemAttribute(new_script, "src", url) DOM.setElemAttribute(new_script, "type","text/javascript") JS("$wnd.document.body.appendChild(@{{new_script}})") self.timer.schedule(100) def onCellClicked(self, sender, row, col): if self.drill==0: self.drill += 1 self.vp.clear() self.grid.clear() self.vp.add(self.up) self.vp.add(self.grid) gridcols = self.grid.getColumnCount() album = self.albums[row+col+(row*(gridcols-1))] url = "http://picasaweb.google.com/data/feed/base/user/" + self.userid + "/albumid/" + album["id"] + "?alt=json-in-script&kind=photo&hl=en_US&callback=restCb" self.doRESTQuery(url, self.timer) elif self.drill==1: self.drill += 1 gridcols = self.grid.getColumnCount() self.pos =row+col+(row*(gridcols-1)) photo = self.photos[self.pos] self.vp.clear() self.fullsize = HTML('<img src="' + photo["full"] + '"/>') hp = HorizontalPanel() hp.add(self.up) hp.add(self.prev) hp.add(self.next) hp.setSpacing(8) self.vp.add(hp) self.vp.add(self.fullsize) def onClick(self, sender): if sender == self.IDButton: self.userid = self.IDBox.getText() if self.userid == "" or self.userid.isdigit(): return self.drill = 0 self.album_url = "http://picasaweb.google.com/data/feed/base/user/" + self.userid + "?alt=json-in-script&kind=album&hl=en_US&callback=restCb" self.grid.clear() self.doRESTQuery(self.album_url, self.timer) else: if self.drill == 2: if sender == self.up: self.drill=1 self.vp.clear() self.vp.add(self.up) self.vp.add(self.grid) self.fillGrid(self.photos, "photos") else: if sender == self.next: if self.pos >= len(self.photos): return self.pos +=1 elif sender == self.prev: if self.pos < 1: return self.pos -=1 photo = self.photos[self.pos] self.fullsize.setHTML('<img src="' + photo["full"] + '"/>') elif self.drill == 1: self.drill=0 self.vp.clear() self.vp.add(self.IDPanel) self.vp.add(self.disclosure) self.vp.add(self.grid) self.fillGrid(self.albums, "albums") def onTimer(self, timer): receiver = JS("$wnd.receiver") if receiver == 'wait': self.timer.schedule(1000) return JS("$wnd.receiver = 'wait'") if self.drill == 0: self.parseAlbums(receiver) self.fillGrid(self.albums, "albums") elif self.drill == 1: self.parsePhotos(receiver) self.fillGrid(self.photos, "photos") def fillGrid(self, items, type): self.grid.clear() cols = self.grid.getColumnCount() self.grid.resizeRows((len(items)/cols)+1) rows = self.grid.getRowCount() for i in range(len(items)): vp = VerticalPanel() if type == 'photos': vp.add(items[i]['thumb']) else: vp.add(items[i]['thumb']) vp.add(items[i]['title']) self.grid.setWidget(int(i/cols), i%cols, vp) def parsePhotos(self, items): photo_list = JSONParser().jsObjectToPyObject(items) self.photos = [] for i in range(len(photo_list)): index = "%s" % i aphoto = {} aphoto['thumb'] = HTML('<img src="' + photo_list[index]["media$group"]["media$thumbnail"]["1"]["url"] + '"/>') aphoto['full'] = photo_list[index]["media$group"]["media$content"]["0"]["url"] self.photos.append(aphoto) def parseAlbums(self, items): album_list = JSONParser().jsObjectToPyObject(items) self.albums = [] for i in range(len(album_list)): index = "%s" % i analbum = {} analbum['title'] = HTML(album_list[index]["title"]["$t"]) analbum['thumb'] = HTML('<img src="' + album_list[index]["media$group"]["media$thumbnail"]["0"]["url"] + '"/>') url = album_list[index]["id"]["$t"] analbum['id'] = url.split('albumid/')[1].split('?alt')[0] self.albums.append(analbum)
class CompaniesAppGUI(AbsolutePanel): def __init__(self): AbsolutePanel.__init__(self) self.app = CompaniesApp() self.history = [] self.save = Button("save", self) self.selectDepartment = Button("select", self) self.selectEmployee = Button("select", self) self.edit = Button("edit", self) self.cut = Button("cut", self) self.back = Button("back", self) self.name = TextBox() self.address = TextBox() self.manager = TextBox() self.departments = ListBox(Size=("100%"), VisibleItemCount="5") self.employees = ListBox(Size=("100%"), VisibleItemCount="5") self.total = TextBox() self.errors = VerticalPanel() self.grid = Grid() self.allPanels = VerticalPanel() self.allPanels.add(self.grid) self.allPanels.add(self.errors) self.add(self.allPanels) self.initCompanyGUI() def onClick(self, sender): self.errors.clear() if sender == self.cut: self.current.cut() self.total.setText(self.current.total()) if sender == self.save: if self.current.__class__.__name__ == "Employee": if self.validateEmployee(self.current.id, self.name.getText(), self.address.getText(), self.total.getText()) == True: self.current.save(self.name.getText(), self.address.getText(), float(self.total.getText())) else: if self.validateDepartment(self.current.id, self.name.getText()) == True: self.current.save(self.name.getText()) if sender == self.selectDepartment: if (self.departments.getSelectedIndex() > -1): self.history.append(self.current) self.current = self.app.getDepartment(self.departments.getValue(self.departments.getSelectedIndex())) self.initDepartmentGUI() if sender == self.selectEmployee: if (self.employees.getSelectedIndex() > -1): self.history.append(self.current) self.current = self.app.getEmployee(self.employees.getValue(self.employees.getSelectedIndex())) self.initEmployeeGUI() if sender == self.edit: self.history.append(self.current) self.current = self.current.getManager() self.initEmployeeGUI() if sender == self.back: if len(self.history) > 0: self.current = self.history.pop() if self.current.__class__.__name__ == "Company": self.initCompanyGUI() else: self.initDepartmentGUI() def validateDepartment(self, index, name): valid = True if name == "": self.errors.add(Label("- Enter a valid name, please.")) valid = False for item in self.app.departments: if item.id != index and name == item.name: self.errors.add(Label("- There is already a department with the same name. Enter a valid name, please.")) valid = False return valid def validateEmployee(self, index, name, address, salary): valid = True if name == "": self.errors.add(Label("- Enter a valid name, please.")) valid = False if address == "": self.errors.add(Label("- Enter a valid address, please.")) valid = False if salary == "": self.errors.add(Label("- Enter a valid salary, please.")) valid = False try: float(salary) except ValueError: self.errors.add(Label("- The salary must be a number. Enter a valid salary, please.")) valid = False for item in self.app.employees: if item.id != index and name == item.name and item.address == address: self.errors.add(Label("- There is already an employee with the same name and address combination. Enter a valid name and address, please.")) valid = False return valid def initCompanyGUI(self): self.current = self.app.company self.grid.clear() self.grid.resize(4, 3) # row 1 self.grid.setWidget(0, 0, Label("Name:")) self.grid.setWidget(1, 0, Label("Department:")) self.grid.setWidget(2, 0, Label("Total:")) # row 2 self.grid.setWidget(0, 1, self.name) self.grid.setWidget(1, 1, self.departments) self.grid.setWidget(2, 1, self.total) # row 3 self.grid.setWidget(0, 2, self.save) self.grid.setWidget(1, 2, self.selectDepartment) self.grid.setWidget(2, 2, self.cut) self.name.setText(self.current.name) self.departments.clear() for item in self.current.departments: self.departments.addItem(item.name, item.id) if self.departments.getItemCount() > 0: self.departments.setSelectedIndex(0) self.total.setText(self.current.total()) def initDepartmentGUI(self): self.grid.clear() self.grid.resize(6, 3) # row 1 self.grid.setWidget(0, 0, Label("Name:")) self.grid.setWidget(1, 0, Label("Manager:")) self.grid.setWidget(2, 0, Label("Department:")) self.grid.setWidget(3, 0, Label("Employee:")) self.grid.setWidget(4, 0, Label("Total:")) # row 2 self.grid.setWidget(0, 1, self.name) self.grid.setWidget(1, 1, self.manager) self.grid.setWidget(2, 1, self.departments) self.grid.setWidget(3, 1, self.employees) self.grid.setWidget(4, 1, self.total) # row 3 self.grid.setWidget(0, 2, self.save) self.grid.setWidget(1, 2, self.edit) self.grid.setWidget(2, 2, self.selectDepartment) self.grid.setWidget(3, 2, self.selectEmployee) self.grid.setWidget(4, 2, self.cut) # back self.grid.setWidget(5, 2, self.back) self.name.setText(self.current.name) self.departments.clear() self.employees.clear() for item in self.current.departments: self.departments.addItem(item.name, item.id) if self.departments.getItemCount() > 0: self.departments.setSelectedIndex(0) for item in self.current.employees: if item.manager == 0: self.employees.addItem(item.name, item.id) else: self.manager.setText(item.name) if self.employees.getItemCount() > 0: self.employees.setSelectedIndex(0) self.total.setText(self.current.total()) def initEmployeeGUI(self): self.grid.clear() self.grid.resize(4, 3) # row 1 self.grid.setWidget(0, 0, Label("Name:")) self.grid.setWidget(1, 0, Label("Address:")) self.grid.setWidget(2, 0, Label("Salary:")) # row 2 self.grid.setWidget(0, 1, self.name) self.grid.setWidget(1, 1, self.address) self.grid.setWidget(2, 1, self.total) # row 3 self.grid.setWidget(0, 2, self.save) self.grid.setWidget(2, 2, self.cut) self.grid.setWidget(3, 2, self.back) self.name.setText(self.current.name) self.address.setText(self.current.address) self.total.setText(self.current.salary)
class Slide(Sink): def __init__(self): Sink.__init__(self) text = "<div class='infoProse'>This is the Kitchen Sink sample. " self.vp = VerticalPanel() self.initWidget(self.vp) self.loaded = False def onShow(self): if self.loaded: return name = self.name.replace(" ", "_") name = name.lower() HTTPRequest().asyncGet("%s.txt" % name, SlideLoader(self)) def setSlide(self, text): self.loaded = True ul_stack1 = 0 ul_stack2 = 0 doing_code = 0 txt = '' text += '\n' for line in text.split("\n"): if doing_code: if line == "}}": doing_code = 0 line = "</pre>" txt += line self.vp.add(HTML(txt)) txt = '' continue if line: txt += line txt += "\n" continue line = line.strip() ul_line = False ul_line2 = False add = False if not line: line = " " elif line[:2] == "{{": doing_code = 1 if len(line) > 2: line = "<pre class='slide_code'>%s" % line[2:] else: line = "<pre class='slide_code'>" elif line[:2] == '= ' and line[-2:] == ' =': line = "<h1 class='slide_heading1'>%s</h1>" % line[2:-2] elif line[:3] == '== ' and line[-3:] == ' ==': line = "<h2 class='slide_heading2>%s</h2>" % line[3:-3] elif line[:2] == '* ': if not ul_stack1: txt += "<ul class='slide_list1'>\n" line = "<li class='slide_listitem1'/>%s\n" % ts(line[2:]) ul_stack1 = True ul_line = True elif line[:3] == '** ': if not ul_stack2: txt += "<ul class='slide_list2'>\n" line = "<li class='slide_listitem2'/>%s\n" % ts(line[2:]) ul_stack2 = True ul_line2 = True ul_line = True else: if not doing_code: line = "<p class='slide_para'>%s</p>" % line if ul_stack2 and not ul_line2: ul_stack2 = False txt += "</ul>\n" if ul_stack1 and not ul_line: ul_stack1 = False txt += "</ul>\n" if not ul_stack2 and not ul_stack1 and not doing_code: add = True txt += line if add: self.vp.add(HTML(txt)) txt = '' def onError(self, text, code): self.vp.clear() self.vp.add(HTML("TODO: Slide '%s' not loaded" % self.name)) self.vp.add(HTML(text)) self.vp.add(HTML(code)) def onProgress(self, event): self.vp.clear()
def clear(self): VerticalPanel.clear(self) self.nSelected = 0
class UserListPanel(VerticalPanel): def __init__(self, tabPanel, topPanel, **kwargs): VerticalPanel.__init__(self, StyleName='user-list-panel', **kwargs) self.tabPanel = tabPanel self.topPanel = topPanel self.iconAdder = None self.iconPanel = None self.nSelected = 0 self.leftPanelWidth = 340 self.widthFudgeFactor = 25 def clear(self): VerticalPanel.clear(self) self.nSelected = 0 def updateResultLink(self): self.resultLink.setHTML('Results: <a href="%s">link</a>' % self.tabPanel.resultsLink()) def setUsers(self, title, users, kwargs): self.users = users self.nUsers = len(users) self.title = title self.resultPanel = HorizontalPanel(StyleName='result-panel') self.add(self.resultPanel) self.leftPanel = VerticalPanel(StyleName='results-left-panel', Width=self.leftPanelWidth) self.resultPanel.add(self.leftPanel) if not users: self.iconPanel = None self.leftPanel.add(HTML(title, StyleName='result-title')) else: # Set a display order that will show everything for now. self.displayOrder = range(self.nUsers) self.largeAvatar = LargeAvatar(self, self.tabPanel, self.topPanel) self.leftPanel.add(self.largeAvatar) resultPanelBottomLeft = VerticalPanel( StyleName='results-left-panel-bottom-left') self.resultLink = HTML(StyleName='result-detail') self.updateResultLink() resultPanelBottomLeft.add(self.resultLink) self.iconSizePanel = HorizontalPanel() self.iconSizePanel.add( HTML('Icons: ', StyleName='result-detail')) self.iconSizeLb = lb = ListBox() i = 0 for text, key in _iconData: lb.addItem(text, key) if key == _iconSize: lb.setSelectedIndex(i) i += 1 lb.addChangeListener(IconSizeChanger(self)) self.iconSizePanel.add(lb) resultPanelBottomLeft.add(self.iconSizePanel) if self.nUsers > 1: self.sortPanel = HorizontalPanel() self.sortPanel.add( HTML('Sort: ', StyleName='result-detail')) self.lb = lb = ListBox() i = 0 for text, key in _sortKeyData: lb.addItem(text, key) if key == _sortKey: lb.setSelectedIndex(i) i += 1 lb.addChangeListener(self) self.sortPanel.add(lb) resultPanelBottomLeft.add(self.sortPanel) self.filterPanel = HorizontalPanel() resultPanelBottomLeft.add(self.filterPanel) self.addFilterWidgets() if self.topPanel.loggedIn(): if 'screennames' in kwargs: resultPanelBottomLeft.add(tweet.SimpleTweetPanel( kwargs['screennames'], len(self.users), self.topPanel)) elif 'query' in kwargs: resultPanelBottomLeft.add(tweet.PrepareTweetButton( kwargs['query'], len(self.users), self.tabPanel.tabName, self.topPanel)) self.leftPanel.add(resultPanelBottomLeft) self.iconPanel = VerticalPanel(StyleName='icon-outer-panel') self.resultPanel.add(self.iconPanel) self.images = [] for u in users: url = u['profile_image_url'] i = Image(url, StyleName='avatar-' + _iconSize) # Does calling prefetch actually help? i.prefetch(url) i._user = u i._selected = False i.addMouseListener(self) self.images.append(i) self.showUsers() def addFilterWidgets(self): """If we're logged in (and hence the friends list is available), create a filter listbox. If not, tell the loginPanel that we exist so it can call us when the login is complete.""" if self.topPanel.loggedIn(): # Window.alert('Logged in') self.filterPanel.add( HTML('Filter: ', StyleName='result-detail')) self.filterChanger = FilterChanger(self, self.topPanel) self.filterBox = ListBox() self.filterBox.addItem('None', 0) self.filterBox.addItem( 'Following (%d of %d)' % (self.filterChanger.nFriends, self.nUsers), 1) self.filterBox.addItem( "Not following (%d of %d)" % (self.nUsers - self.filterChanger.nFriends, self.nUsers), 2) self.filterBox.addChangeListener(self.filterChanger) self.filterPanel.add(self.filterBox) else: # Not yet logged in. Add ourselves to the list of UserListPanels # that the loginPanel will call when it's ready. self.topPanel.loginPanel.addUserListPanel(self) def onChange(self, sender): global _sortKey _sortKey = self.lb.getValue(self.lb.getSelectedIndex()) self.updateResultLink() self.showUsers() def showUsers(self): # Cancel any existing timed icon additions before changing # self.displayOrder. if self.iconAdder is not None: self.iconAdder.cancel() self.iconAdder = None self.iconPanel.clear() # Set a title above the icons. if hasattr(self, 'filterChanger'): order = self.filterChanger.currentOrder if order == 0: title = self.title else: if order == 1: n = self.filterChanger.nFriends detail = 'follow' else: n = self.nUsers - self.filterChanger.nFriends detail = "don't follow" if n == 0: if detail == 'follow': title = "You don't follow any of them!" else: title = "You already follow them all!" else: if n > 1: plural = 's' else: plural = '' title = 'The %d user%s you %s:' % (n, plural, detail) else: title = self.title self.iconPanel.add(HTML(title, StyleName='result-title')) if not self.displayOrder: # There are no users to show. return decreasing = _sortKey in ( 'friends_count', 'followers_count', 'statuses_count') alpha = _sortKey in ('screen_name', 'name', 'location') def _keyFunc(n): value = self.users[n][_sortKey] if decreasing: return -1 * value elif alpha: if value: return value.lower().strip() else: # Uh, put this towards the end (of ASCII at least) return '~~~' else: return value # Don't use sorted here, as it replaces the display order list # (which is actually being maintained for us by our FilterChanger # instance). self.displayOrder.sort(key=_keyFunc) self.icons = FlowPanel(StyleName='icon-panel') self.adjustWidths() self.iconPanel.add(self.icons) self.iconAdder = IconAdder(self) Timer.Timer(1, self.iconAdder) if self.nSelected == 0: self.largeAvatar.setUser(self.users[self.displayOrder[0]]) def onMouseEnter(self, img): if not self.nSelected: self.largeAvatar.setUser(img._user) def onMouseMove(self, img, x, y): pass def onMouseLeave(self, img): pass def onMouseDown(self, img, x, y): self.largeAvatar.setUser(img._user) if not img._selected and self.nSelected: self._unselectAll() self._toggleSelect(img) def onMouseUp(self, img, x, y): pass def _toggleSelect(self, img): if img._selected: self._unselect(img) else: self._select(img) def _unselect(self, img): if img._selected: img.removeStyleDependentName('selected') self.nSelected -= 1 img._selected = False def _select(self, img): if not img._selected: img.addStyleDependentName('selected') self.nSelected += 1 img._selected = True def _unselectAll(self): for img in self.images: self._unselect(img) def unselectNotFollowed(self): for img in self.images: if not img._user['following'] and img._selected: self._unselect(img) def unselectFollowed(self): for img in self.images: if img._user['following'] and img._selected: self._unselect(img) def setIconSizes(self): for img in self.images: selected = img._selected if selected: self._unselect(img) img.setStyleName('avatar-' + _iconSize) if selected: self._select(img) def adjustWidths(self, windowWidth=None): if windowWidth is None: windowWidth = Window.getClientWidth() width = windowWidth - self.leftPanelWidth - self.widthFudgeFactor if self.iconPanel is not None: self.icons.setWidth(width) def adjustSize(self, width, height): self.adjustWidths(width)
class Slide(Sink): def __init__(self): Sink.__init__(self) text="<div class='infoProse'>This is the Kitchen Sink sample. " self.vp = VerticalPanel() self.initWidget(self.vp) self.loaded = False def onShow(self): if self.loaded: return name = self.name.replace(" ", "_") name = name.lower() HTTPRequest().asyncGet("%s.txt" % name, SlideLoader(self)) def setSlide(self, text): self.loaded = True ul_stack1 = 0 ul_stack2 = 0 doing_code = 0 txt = '' text += '\n' for line in text.split("\n"): if doing_code: if line == "}}": doing_code = 0 line = "</pre>" txt += line self.vp.add(HTML(txt)) txt = '' continue if line: txt += line txt += "\n" continue line = line.strip() ul_line = False ul_line2 = False add = False if not line: line = " " elif line[:2] == "{{": doing_code = 1 if len(line) > 2: line = "<pre class='slide_code'>%s" % line[2:] else: line = "<pre class='slide_code'>" elif line[:2] == '= ' and line[-2:] == ' =': line = "<h1 class='slide_heading1'>%s</h1>" % line[2:-2] elif line[:3] == '== ' and line[-3:] == ' ==': line = "<h2 class='slide_heading2>%s</h2>" % line[3:-3] elif line[:2] == '* ': if not ul_stack1: txt += "<ul class='slide_list1'>\n" line = "<li class='slide_listitem1'/>%s\n" % ts(line[2:]) ul_stack1 = True ul_line = True elif line[:3] == '** ': if not ul_stack2: txt += "<ul class='slide_list2'>\n" line = "<li class='slide_listitem2'/>%s\n" % ts(line[2:]) ul_stack2 = True ul_line2 = True ul_line = True else: if not doing_code: line = "<p class='slide_para'>%s</p>" % line if ul_stack2 and not ul_line2: ul_stack2 = False txt += "</ul>\n" if ul_stack1 and not ul_line: ul_stack1 = False txt += "</ul>\n" if not ul_stack2 and not ul_stack1 and not doing_code: add = True txt += line if add: self.vp.add(HTML(txt)) txt = '' def onError(self, text, code): self.vp.clear() self.vp.add(HTML("TODO: Slide '%s' not loaded" % self.name)) self.vp.add(HTML(text)) self.vp.add(HTML(code))