class StoryCard(ZNode, Highlightable, Draggable): """A StoryCard consists of some card-shaped background geometry, and on top of that a vbox with a title (DirectLabel), icon (DirectLabel) and main text (DirectEntry).Along the bottom of the card is an hbox containing buttons that control the card. A StoryCard has various binary states that can be toggled: focusable/not-focusable: whether the card can be focused (zoomed to) by the viewport. Functionality from znode. (Or Focusable mixin class?) card.set_zoomable(True|False) draggable/not-draggable: whether the card can be dragged or not, functionality from Draggable mixin class. card.set_draggable(True|False) highlightable/not-highlightable: whether the card responds to mouse-overs or not, functionality from highlightable mixin class. card.set_highlightable(True|False) high-detail/low-detail: whether the highdetail vbox and hbox are shown or the low detail. card.set_detail("high"|"low") editable/not-editable: whether the DirectEntry is active and focussed or not. card.set_editable(True|False) show-buttons/don't-show-buttons: whether or not the row of DirectButton's along the bottom of the card is shown. card.show_buttons(True|False) All of these states must be controlled by user classes, e.g. a StoryCard subclass that is a FocusObserver, a StoryMap that owns the StoryCard, or some sort of global Controller class. """ def __init__(self,function): self.function = function ZNode.__init__(self,geomnode=card(), magnification=.8) self.np.setColor(1,1,1,1) Draggable.__init__(self) Highlightable.__init__(self) # Uncomment to apply a texture to the card. #tex = loader.loadTexture('card.png') #self.np.setTexture(tex) # Now to add the DirectGUI widgets onto the card. A StoryCard has two # VBoxes containing DirectGUI objects, one that is shown when the card # is far from the viewport and displaying itself in low detail, and one # that is shown when the viewport is focused on the card and the card is # showing itself in high detail. self.lowDetailVBox = VBoxList() self.highDetailVBox = VBoxList() self.lowDetailVBox.reparentTo(self.np) self.highDetailVBox.reparentTo(self.np) # The title of the function of this card. font = 'storymaps/data/TypeWritersSubstitute-Black.ttf' title = DirectLabel(text=self.function.name, text_font=loader.loadFont(font), text_bg=(1,1,1,0), frameColor=(1,1,1,1), scale=.7, suppressMouse=0) b = Box() b.fill(title) self.lowDetailVBox.append(b) title = DirectLabel(text=self.function.name, text_font=loader.loadFont(font), text_bg=(1,1,1,0), frameColor=(1,1,1,1), scale=.7, suppressMouse=0) b = Box() b.fill(title) self.highDetailVBox.append(b) # The icon of the function of this card. Use Panda's mipmapping # to handle scaling the image efficiently. tex = loader.loadTexture(function.image) tex.setMagfilter(Texture.FTLinearMipmapLinear) tex.setMinfilter(Texture.FTLinearMipmapLinear) icon = DirectLabel(image=tex) icon.setScale(2.5) b = Box() b.fill(icon) self.lowDetailVBox.append(b) icon = DirectLabel(image=tex) b = Box() b.fill(icon) self.highDetailVBox.append(b) # The longer description of the Propp function. self.entry = DirectEntry(initialText=self.function.desc, text_font=loader.loadFont('storymaps/data/WritersFont.ttf'), scale=.4, width=13, numLines=7, suppressMouse=0, frameColor = (1,1,1,1)) self.entry['state'] = DGG.DISABLED b = Box() b.setColor(1,1,1,0) b.fill(self.entry) self.highDetailVBox.append(b) self.lowDetailVBox.setPos(self.lowDetailVBox.np,-2.6,0,4) self.highDetailVBox.setPos(self.lowDetailVBox.getPos()) self.highDetailVBox.hide() # A place for subclasses to put buttons. self.buttons = HBoxList() self.buttons.reparentTo(self.np) self.buttons.setScale(.6) self.buttons.setPos(-1.8,0,-1.6) self.buttons.hide() self.disabled = False def set_detail(self,detail): if detail == "high": self.lowDetailVBox.hide() self.highDetailVBox.show() elif detail == "low": self.lowDetailVBox.show() self.highDetailVBox.hide() else: raise Exception('Argument to set_detail must be "high" or "low".') def set_editable(self,boolean): if boolean: self.entry['state'] = DGG.NORMAL self.entry['focus'] = 1 else: self.entry['state'] = DGG.DISABLED self.entry['focus'] = 0 def show_buttons(self,boolean): if boolean: self.buttons.show() else: self.buttons.hide() def disable(self): disabled_color = Point4(.5,.5,.5,1) self.np.setColor(disabled_color) for box in self.lowDetailVBox: box.contents.setColor(disabled_color) for box in self.highDetailVBox: box.contents.setColor(disabled_color) for box in self.buttons: box.contents.setColor(disabled_color) self.set_highlightable(False) self.set_draggable(False) self.disabled = True def enable(self): color = Point4(1,1,1,1) self.np.setColor(color) for box in self.lowDetailVBox: box.contents.setColor(color) for box in self.highDetailVBox: box.contents.setColor(color) for box in self.buttons: box.contents.setColor(color) self.set_highlightable(True) self.set_draggable(True) self.disabled = False # Implement the Originator interface of the Memento pattern for saving and # restoring user content. class Memento(Memento): def __init__(self,function,text,cls,disabled): self.function = function self.text = text self.cls = cls self.disabled = disabled def __str__(self): return '\n\n' + self.function.__str__() + '\n\n' + self.text def create_memento(self): return StoryCard.Memento(self.function,self.entry.get(),self.__class__,self.disabled) def restore_memento(self,memento): self.entry.enterText(memento.text) if memento.disabled: self.disable()
hbox = HBoxList() hbox.setPos(-.5, 0, .4) hbox.reparentTo(zcanvas.home) for i in range(5): b = Box(geomnode=DemoItem.cm.generate()) hbox.append(b) i = DemoItem() b.fill(i) vbox = VBoxList() vbox.setPos(-.5, 0, .25) vbox.reparentTo(zcanvas.home) for i in range(5): b = Box(geomnode=DemoItem.cm.generate()) vbox.append(b) gbox = GridBoxList(columns=3) gbox.setPos(.1, 0, .1) gbox.reparentTo(zcanvas.home) for i in range(9): b = Box(geomnode=DemoItem.cm.generate()) gbox.append(b) base.accept('mouse1', zcanvas.drag) base.accept('mouse1-up', zcanvas.drop) zcanvas.message("""Drag the demo items (in white) and drop them onto the boxes (in black).""") run()
hbox = HBoxList() hbox.setPos(-.5,0,.4) hbox.reparentTo(zcanvas.home) for i in range(5): b = Box(geomnode=DemoItem.cm.generate()) hbox.append(b) i = DemoItem() b.fill(i) vbox = VBoxList() vbox.setPos(-.5,0,.25) vbox.reparentTo(zcanvas.home) for i in range(5): b = Box(geomnode=DemoItem.cm.generate()) vbox.append(b) gbox = GridBoxList(columns=3) gbox.setPos(.1,0,.1) gbox.reparentTo(zcanvas.home) for i in range(9): b = Box(geomnode=DemoItem.cm.generate()) gbox.append(b) base.accept('mouse1',zcanvas.drag) base.accept('mouse1-up',zcanvas.drop) zcanvas.message( """Drag the demo items (in white) and drop them onto the boxes (in black).""" )