def addPanel(self, title, panel = None): """Can add an existing panel, or have a panel created by default. Adding an existing panel is useful for adding special panel types (splitters/tabs) """ if not panel: panel = Panel() self.addChild(panel) panel.moveto(self.innerRect[0], self.innerRect[1]) panel.resize(self.innerRect[2], self.innerRect[3]) panel.calcSize() panel.tabTitle = title self.tabPanels[title] = panel self._tabBar.addTab(title) if not self.activePanel: self.activePanel = panel self.setDirty() return panel
class Window(Base): """window - contains other objects. Windows have a main panel (_panel) which can be replaced with a custom panel. this main panel is kept the size of the interior of the window. """ def __init__(self, x, y, w, h, topmost = 0): self._panel = Panel() Base.__init__(self) self.topMost = topmost # the content panel is added as a child through Base::addChild to avoid recursively adding it to itself Base.addChild(self, self._panel) self._panel.setWindow(self) self._panel.setParent(self) self.placeInnerObjects() self.drawCommands = [] # these are drawing callbacks to draw _after_ all the widgets are drawn self.drawLastCallbacks = [] self.moveto(x, y) self.resize(w, h) getDesktop().addWindow(self) # Create the graphics context that will be used to display this window self.graphicsContext = getPresenter().getDeviceContext().createGraphicsContext((w, h)) def getGraphicsContext(self): return self.graphicsContext def beginDraw(self): self.graphicsContext.beginDraw(self.posX, self.posY) def endDraw(self): self.graphicsContext.endDraw() def present(self, presenter): """Performs the rendering of the window and it's children to the windows graphic context. """ if self.graphicsContext.getSize() != (self.width, self.height): # The size has changed since we last rendered, we need to resize the graphics context. # Note we only really need to do this when we redraw it, since creating and releasing # the context every time we get a window resize call may be very inefficient. self.graphicsContext.resize((self.width, self.height)) # Draw the window first presenter.drawWidget("WINDOW", self, self.graphicsContext) # Draw each of the children on to the graphics context using the theme supplied through # the presenter for child in self.children: child.present(presenter, self.graphicsContext) def render(self): self.graphicsContext.render((self.posX, self.posY)) def resize(self, w, h): Base.resize(self, w, h) self._panel.resize(w,h) def addDrawCallback(self, callback): self.drawLastCallbacks.append(callback) # for windows, children get added to the content panel def addChild(self, child, option = None): self._panel.addChild(child, option) child.calcSize() def move(self, x, y): Base.move(self, x,y) def moveto(self, x, y): Base.moveto(self, x,y) def setLayout(self, layout): self._panel.setLayout(layout) layout.setPanel(self._panel) def pack(self): self._panel.pack() def destroy(self): self._panel = None self.handle = 0 self.drawList = [] Base.destroy(self) def replacePanel(self, panel): for c in self.children: if c.id == self._panel.id: self.children.remove(c) self._panel = panel Base.addChild(self, self._panel) self._panel.setWindow(self) self.calcInnerRect() self.placeInnerObjects() self._panel.moveto(self.innerRect[0], self.innerRect[1]) self._panel.resize(self.innerRect[2], self.innerRect[3]) self._panel.calcInnerRect() self._panel.placeInnerObjects() def placeInnerObjects(self): self._panel.moveto(0,0) self._panel.resize(self.width, self.height) def setDirty(self, collide = 1): #self.dirty = 1 if self.dirty: return if collide: getDesktop().dirtyCollidingWindows(self.rect) Base.setDirty(self) def setTopMost(self, value): if value == 0: self.topMost = 0 else: self.topMost = 1 #print "set topmost to ", self.topMost def setShow(self, value): if value: getDesktop().activateWindow(self) return Base.setShow(self, value) def isWindow(self): return True def desktopToWindow(self, point): """Convert a point in desktop coordinates into coordinates relative to the windows position. """ x = int(point[0] - self.posX) y = int(point[1] - self.posY) return (x, y)
class SplitterPanel(Panel): """A panel that is split in half - vertically or horizontally. Can use pixels or percentage to split. Each side of the split is a panel. The default panels can be replaced with custom panels. There is a middle bar of the splitter panel. This middle bar _could_ be used to resize it... """ VERTICAL = 0 HORIZONTAL = 1 PIXELS = 0 PERCENTAGE = 1 PADDING = 2 def __init__(self, direction = VERTICAL, method = PERCENTAGE, ratio = 50 ): self.direction = direction # vertical/horizontal self.method = method # pixels/percentage self.ratio = ratio # number of pixels or percentage self.splitPos = 0 # pixel width/height of first panel if self.method == SplitterPanel.PERCENTAGE: self.ratio = float(ratio) / 100.0 Panel.__init__(self) self.panel1 = Panel() self.panel2 = Panel() self.addChild(self.panel1) self.addChild(self.panel2) def setVerticalSplit(self, x): self.panel1.moveto(0,0) self.panel1.resize(x-self.PADDING, self.height) self.panel2.moveto(x+self.PADDING, 0) self.panel2.resize(self.width-x-self.PADDING, self.height) self.splitPos = x def setHorizontalSplit(self, y): self.panel1.moveto(0,0) self.panel1.resize(self.width, y-self.PADDING) self.panel2.moveto(0, y+self.PADDING) self.panel2.resize(self.width, self.height-y-self.PADDING) self.splitPos = y def resize(self, w, h): Base.resize(self, w,h) #print "splitter resizing", w, h if self.method == SplitterPanel.PIXELS: if self.direction == SplitterPanel.VERTICAL: if self.ratio >= 0: self.setVerticalSplit(self.ratio) else: self.setVerticalSplit(self.width + self.ratio) if self.direction == SplitterPanel.HORIZONTAL: if self.ratio >= 0: self.setHorizontalSplit(self.ratio) else: self.setHorizontalSplit(self.height + self.ratio) else: if self.direction == SplitterPanel.VERTICAL: self.setVerticalSplit(self.width * self.ratio) if self.direction == SplitterPanel.HORIZONTAL: self.setHorizontalSplit(self.height * self.ratio) def draw(self, renderer): self.panel1.draw(renderer) if self.direction == SplitterPanel.HORIZONTAL: getTheme().drawSplitter( (self.windowRect[0], self.windowRect[1]+self.splitPos-self.PADDING, self.width, self.PADDING*2)) else: getTheme().drawSplitter( (self.windowRect[0]+self.splitPos-self.PADDING, self.windowRect[1], 2*self.PADDING, self.height)) self.panel2.draw(renderer) def pack(self): self.panel1.pack() self.panel2.pack() def getFirstPanel(self): """ returns the left or top panel """ return self.panel1 def getSecondPanel(self): """ returns to right or bottom panel """ return self.panel2 def replaceFirstPanel(self, panel): panel.moveto(self.panel1.posX, self.panel1.posY) for c in self.children: if c.id == self.panel1.id: self.children.remove(c) c.destroy() self.addChild(panel) self.panel1 = panel self.resize(self.width, self.height) def replaceSecondPanel(self, panel): panel.moveto(self.panel2.posX, self.panel2.posY) for c in self.children: if c.id == self.panel2.id: self.children.remove(c) c.destroy() self.addChild(panel) self.panel2 = panel self.resize(self.width, self.height)