def DrawVertBandInverted(self, dc, rect): """ Draws vertical bands inverted. :param `dc`: an instance of :class:`wx.DC`; :param `rect`: the vertical bands client rectangle. """ vertBands = (self._ledBands > 1 and [self._ledBands] or [self._maxValue*BAND_PERCENT//100])[0] minVertLimit = self._minValue*vertBands//self._maxValue medVertLimit = self._medValue*vertBands//self._maxValue maxVertLimit = vertBands size = wx.Size(rect.width//self._numBands, rect.height//vertBands) rectBand = wx.Rect(rect.GetTopLeft(), size) # Draw band from top? rectBand.Offset(0, 0) xDecal = (self._numBands > 1 and [1] or [0])[0] yDecal = (self._ledBands > 1 and [1] or [0])[0] for horz in range(self._numBands): self._value = self._meterData[horz]._value vertLimit = self._value*vertBands//self._maxValue rectPrev = wx.Rect(*rectBand) for vert in range(vertBands): rectBand.Deflate(xDecal, 0) # Find colour based on range value colourRect = self._clrBackground if self._showGrid: colourRect = DarkenColour(self._clrBackground, GRID_INCREASEBY) # Draw grid line (level) bar if self._showGrid and (vert == minVertLimit or vert == (vertBands-1)): points = [wx.Point() for i in range(2)] points[0].x = rectBand.GetTopLeft().x - xDecal points[0].y = rectBand.GetTopLeft().y + (rectBand.height >> 1) points[1].x = rectBand.GetBottomRight().x + xDecal points[1].y = points[0].y dc.DrawLine(points[0], points[1]) if vert < vertLimit: if InRange(vert, 0, minVertLimit-1): colourRect = self._clrNormal elif InRange(vert, minVertLimit, medVertLimit-1): colourRect = self._clrMedium elif InRange(vert, medVertLimit, maxVertLimit): colourRect = self._clrHigh dc.SetBrush(wx.Brush(colourRect)) dc.DrawRectangle(rectBand) rectBand.Inflate(xDecal, 0) rectBand.Offset(0, size.y) # Draw falloff effect if self._showFalloff: oldPen = dc.GetPen() pen = wx.Pen(DarkenColour(self._clrBackground, FALL_INCREASEBY)) maxHeight = -size.y*vertBands points = [wx.Point() for i in range(2)] points[0].x = rectPrev.GetBottomLeft().x + xDecal points[0].y = rectPrev.GetTopRight().y - self._meterData[horz]._falloff*maxHeight/self._maxValue points[1].x = rectPrev.GetTopRight().x - xDecal points[1].y = points[0].y dc.SetPen(pen) dc.DrawLine(points[0], points[1]) dc.SetPen(oldPen) # Move to Next Horizontal band rectBand.Offset(size.x, -size.y*vertBands)
def DrawEditText(self, t, style, x, y, dc): #dc.DrawText(t, x * self.cell_width_in_pixels, y * self.cell_height_in_pixels) rect = wx.Rect(x * self.cell_width_in_pixels, y * self.cell_height_in_pixels, len(t) * self.cell_width_in_pixels, self.cell_height_in_pixels) self.text_renderer.draw_text(dc, rect, t, style)
def get_vertical_larger_box_rect(self, rect): return wx.Rect(rect.X - 2, rect.Y - 2 - PADDING, rect.Width + 4, rect.Height + 4 + PADDING)
def ShowExpanded(self): """ Show the panel externally expanded. When a panel is minimised, it can be shown full-size in a pop-out window, which is referred to as being (externally) expanded. :returns: ``True`` if the panel was expanded, ``False`` if it was not (possibly due to it not being minimised, or already being expanded). :note: When a panel is expanded, there exist two panels - the original panel (which is referred to as the dummy panel) and the expanded panel. The original is termed a dummy as it sits in the ribbon bar doing nothing, while the expanded panel holds the panel children. :see: :meth:`~RibbonPanel.HideExpanded`, :meth:`~RibbonPanel.GetExpandedPanel` """ if not self.IsMinimised(): return False if self._expanded_dummy is not None or self._expanded_panel != None: return False size = self.GetBestSize() pos = self.GetExpandedPosition( wx.Rect(self.GetScreenPosition(), self.GetSize()), size, self._preferred_expand_direction).GetTopLeft() # Need a top-level frame to contain the expanded panel container = wx.Frame(None, wx.ID_ANY, self.GetLabel(), pos, size, wx.FRAME_NO_TASKBAR | wx.BORDER_NONE) self._expanded_panel = RibbonPanel(container, wx.ID_ANY, self.GetLabel(), self._minimised_icon, wx.Point(0, 0), size, self._flags) self._expanded_panel.SetArtProvider(self._art) self._expanded_panel._expanded_dummy = self # Move all children to the new panel. # Conceptually it might be simpler to reparent self entire panel to the # container and create a new panel to sit in its place while expanded. # This approach has a problem though - when the panel is reinserted into # its original parent, it'll be at a different position in the child list # and thus assume a new position. # NB: Children iterators not used as behaviour is not well defined # when iterating over a container which is being emptied for child in self.GetChildren(): child.Reparent(self._expanded_panel) child.Show() # Move sizer to new panel if self.GetSizer(): sizer = self.GetSizer() self.SetSizer(None, False) self._expanded_panel.SetSizer(sizer) self._expanded_panel.Realize() self.Refresh() container.Show() self._expanded_panel.SetFocus() return True
def getLogicalRect(self): """Returns this instance's rectangle in logical coordinates.""" size = self.getSize() return wx.Rect(self.pos[0], self.pos[1], size[0], size[1])
def RefreshTabBar(self): tab_rect = wx.Rect(0, 0, self.GetClientSize().GetWidth(), self._tab_height) self.Refresh(False, tab_rect)
def DoEraseBackground(self, dc): tabs = wx.Rect(0, 0, *self.GetSize()) tabs.height = self._tab_height self._art.DrawTabCtrlBackground(dc, self, tabs)
def create_handle_rect(): HALF_EVENT_HEIGHT = rect.Height / 2 y = rect.Y + HALF_EVENT_HEIGHT - HALF_HANDLE_SIZE x = rect.X - HALF_HANDLE_SIZE + 1 return wx.Rect(x, y, HANDLE_SIZE, HANDLE_SIZE)
def refresh(self, x=0, y=0, w=0, h=0): if not w: w, h = self.GetSize() self.Refresh(rect=wx.Rect(x, y, w, h))
def inflate_clipping_region(): big_rect = wx.Rect(*rect) big_rect.Inflate(HANDLE_SIZE, HANDLE_SIZE) dc.DestroyClippingRegion() dc.SetClippingRect(big_rect)
def _inflate_clipping_region(self, dc, rect): copy = wx.Rect(*rect) copy.Inflate(10, 0) dc.DestroyClippingRegion() dc.SetClippingRect(copy)
def MakeSnapshot(self, maxColumns=1337): if self.FVsnapshot: self.FVsnapshot = None tbmp = wx.Bitmap(16, 16) tdc = wx.MemoryDC() tdc.SelectObject(tbmp) tdc.SetFont(self.font) columnsWidths = [] for i in range(len(self.DEFAULT_COLS)): columnsWidths.append(0) sFit = Fit.getInstance() try: fit = sFit.getFit(self.activeFitID) except Exception as e: pyfalog.critical("Failed to get fit") pyfalog.critical(e) return if fit is None: return slotMap = {} for slotType in Slot.getTypes(): slot = Slot.getValue(slotType) slotMap[slot] = fit.getSlotsFree(slot) < 0 padding = 2 isize = 16 headerSize = max(isize, tdc.GetTextExtent("W")[0]) + padding * 2 maxRowHeight = isize rows = 0 for st in self.mods: for i, col in enumerate(self.activeColumns): if i > maxColumns: break name = col.getText(st) if not isinstance(name, str): name = "" nx, ny = tdc.GetTextExtent(name) imgId = col.getImageId(st) cw = 0 if imgId != -1: cw += isize + padding if name != "": cw += nx + 4 * padding if imgId == -1 and name == "": cw += isize + padding maxRowHeight = max(ny, maxRowHeight) columnsWidths[i] = max(columnsWidths[i], cw) rows += 1 render = wx.RendererNative.Get() # Fix column widths (use biggest between header or items) for i, col in enumerate(self.activeColumns): if i > maxColumns: break name = col.columnText imgId = col.imageId if not isinstance(name, str): name = "" opts = wx.HeaderButtonParams() if name != "": opts.m_labelText = name if imgId != -1: opts.m_labelBitmap = wx.Bitmap(isize, isize) width = render.DrawHeaderButton(self, tdc, (0, 0, 16, 16), sortArrow=wx.HDR_SORT_ICON_NONE, params=opts) columnsWidths[i] = max(columnsWidths[i], width) tdc.SelectObject(wx.NullBitmap) maxWidth = padding * 2 for i in range(len(self.DEFAULT_COLS)): if i > maxColumns: break maxWidth += columnsWidths[i] mdc = wx.MemoryDC() mbmp = wx.Bitmap(maxWidth, maxRowHeight * rows + padding * 4 + headerSize) mdc.SelectObject(mbmp) mdc.SetBackground( wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW))) mdc.Clear() mdc.SetFont(self.font) mdc.SetTextForeground( wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)) cx = padding for i, col in enumerate(self.activeColumns): if i > maxColumns: break name = col.columnText imgId = col.imageId if not isinstance(name, str): name = "" opts = wx.HeaderButtonParams() opts.m_labelAlignment = wx.ALIGN_LEFT if name != "": opts.m_labelText = name if imgId != -1: bmp = col.bitmap opts.m_labelBitmap = bmp render.DrawHeaderButton( self, mdc, (cx, padding, columnsWidths[i], headerSize), wx.CONTROL_CURRENT, sortArrow=wx.HDR_SORT_ICON_NONE, params=opts) cx += columnsWidths[i] brush = wx.Brush(wx.Colour(224, 51, 51)) pen = wx.Pen(wx.Colour(224, 51, 51)) mdc.SetPen(pen) mdc.SetBrush(brush) cy = padding * 2 + headerSize for st in self.mods: cx = padding if slotMap[st.slot]: mdc.DrawRectangle(cx, cy, maxWidth - cx, maxRowHeight) for i, col in enumerate(self.activeColumns): if i > maxColumns: break name = col.getText(st) if not isinstance(name, str): name = "" imgId = col.getImageId(st) tcx = cx if imgId != -1: self.imageList.Draw(imgId, mdc, cx, cy, wx.IMAGELIST_DRAW_TRANSPARENT, False) tcx += isize + padding if name != "": nx, ny = mdc.GetTextExtent(name) rect = wx.Rect() rect.top = cy rect.left = cx + 2 * padding rect.width = nx rect.height = maxRowHeight + padding mdc.DrawLabel(name, rect, wx.ALIGN_CENTER_VERTICAL) tcx += nx + padding cx += columnsWidths[i] cy += maxRowHeight mdc.SelectObject(wx.NullBitmap) self.FVsnapshot = mbmp
def __init__(self, fp): super().__init__(fp) self["__LabPype__"] = Img.LabPype.GetIcon() if self["FONTFACE_CANVAS"] == "": self["FONTFACE_CANVAS"] = wx.SystemSettings().GetFont( wx.SYS_DEFAULT_GUI_FONT).GetFaceName() if self["FONTFACE_FIXED"] == "": self["FONTFACE_FIXED"] = wx.SystemSettings().GetFont( wx.SYS_ANSI_FIXED_FONT).GetFaceName() # GUI self["PEN_CONNECTION"] = wx.Pen(self["COLOR_CONNECTION"], 3) self["PEN_CONNECTION_SELECTION1"] = wx.Pen(self["COLOR_SELECTION"], 11) self["PEN_CONNECTION_SELECTION2"] = wx.Pen( UI.AlphaBlend(self["COLOR_BG_B"], self["COLOR_SELECTION"], 0.5), 9) self["PEN_SELECTION"] = wx.Pen(self["COLOR_SELECTION"], 1) self["BRUSH_SELECTION"] = wx.Brush( UI.AlphaBlend(self["COLOR_BG_B"], self["COLOR_SELECTION"], 0.3)) # Brush self["BRUSH_WIDGET_DONE"] = wx.Brush(self["COLOR_WIDGET_DONE"]) self["BRUSH_WIDGET_WAIT"] = wx.Brush(self["COLOR_WIDGET_WAIT"]) self["BRUSH_WIDGET_WORK"] = wx.Brush(self["COLOR_WIDGET_WORK"]) self["BRUSH_WIDGET_FAIL"] = wx.Brush(self["COLOR_WIDGET_FAIL"]) self["BRUSH_ANCHOR_RECV"] = wx.Brush(self["COLOR_ANCHOR_RECV"]) self["BRUSH_ANCHOR_SEND"] = wx.Brush(self["COLOR_ANCHOR_SEND"]) self["BRUSH_ANCHOR_PASS"] = wx.Brush(self["COLOR_ANCHOR_PASS"]) self["BRUSH_ANCHOR_FAIL"] = wx.Brush(self["COLOR_ANCHOR_FAIL"]) # Font self.SetMainFont(9, self["FONTFACE_MAIN"]) self["FONT_H1"] = wx.Font(24, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, self["FONTFACE_MAIN"]) self["FONT_H2"] = wx.Font(20, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, self["FONTFACE_MAIN"]) self["FONT_H3"] = wx.Font(16, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, self["FONTFACE_MAIN"]) self["FONT_H4"] = wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, self["FONTFACE_MAIN"]) self["FONT_CANVAS"] = wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, self["FONTFACE_CANVAS"]) self["FONT_FIXED"] = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, self["FONTFACE_FIXED"]) # Bitmap for key in ( "TOOL_OPTION", "TOOL_DELETE", "TOOL_FILE_N", "TOOL_FILE_O", "TOOL_FILE_S", "TOOL_ALGN_L", "TOOL_ALGN_V", "TOOL_ALGN_R", "TOOL_ALGN_T", "TOOL_ALGN_H", "TOOL_ALGN_B", "TOOL_DIST_H", "TOOL_DIST_V", "TOOL_MOVE_U", "TOOL_MOVE_D", "TOOL_MOVE_T", "TOOL_MOVE_B", "TOOL_T_ANCR", "TOOL_T_NAME", "TOOL_T_SNAP", "TOOL_T_CURV", "TOOL_T_DIAG", "TOOL_T_FSCN", "TOOL_CANCEL", "TOOL_T_SHOW", "TOOL_T_TEXT", "TOOL_MANAGE", "DIALOG_MISC", "DIALOG_ATCH", "DIALOG_DTCH", "DIALOG_LOCA", ): self[key] = UI.GetBitmaps(self.GetBitmap(key), 20, 20) for key in ("MANAGE_ADD", "MANAGE_DEL"): self[key] = self.GetBitmap(key) # Resources for widget drawing self["INDICATOR"] = UI.GetBitmaps(self.GetBitmap("INDICATOR"), 10, 10) self.DefaultIcon = Img.WIDGET.GetBitmap() self.MaskCanvas = Img.MASK_CANVAS.GetBitmap() self.MaskGadget = Img.MASK_GADGET.GetBitmap() self.MaskCursor = Img.MASK_CURSOR.GetBitmap() self.RectCanvas = wx.Rect(0, 0, 56, 56) self.RectGadget = wx.Rect(0, 0, 32, 32) self.RectCursor = wx.Rect(0, 0, 30, 30) self.WidgetPen = wx.Pen("#000000", 1)
def __init__(self, app, session=None): wx.Frame.__init__(self, None, -1, "Write++", app.settings["WindowPos"], app.settings["WindowSize"]) self._app = app self.dragsource = -1 self.editor = None self.filetypes = "|".join(filters) self.new = 0 self.managers = {} self.panedict = {} self.rect = wx.Rect(app.settings["WindowPos"], app.settings["WindowSize"]) self.results = 0 self.search = search.SearchSystem(self) self.session = session self.styler = syntax.Styler(self) icons = wx.IconBundle() icons.AddIcon(os.path.join(app.cwd, "images", "write++-16.png"), wx.BITMAP_TYPE_PNG) icons.AddIcon(os.path.join(app.cwd, "images", "write++-32.png"), wx.BITMAP_TYPE_PNG) self.SetIcons(icons) if app.settings["BackupType"] == 2 and (not os.path.isdir( app.settings["BackupDir"])): os.makedirs(app.settings["BackupDir"]) for direction in (wx.LEFT, wx.RIGHT, wx.TOP, wx.BOTTOM): self.managers[direction] = panes.VCPaneManager(self, direction) if not self.session: self.session = app.settings["SessionFile"] firstrun = not len(self.session) if not os.path.isfile(self.session): self.session = os.path.join(app.userdatadir, "Default.write++") self.aui = aui.AuiManager( self, aui.AUI_MGR_DEFAULT | aui.AUI_MGR_USE_NATIVE_MINIFRAMES) dockart = self.aui.GetArtProvider() dockart._inactive_minimize_bitmap = dockart._inactive_pin_bitmap.ConvertToImage( ).Rotate90().ConvertToBitmap() dockart.SetFont(aui.AUI_DOCKART_CAPTION_FONT, self.GetFont()) self.menubar = menu.MenuBar(self) self.SetMenuBar(self.menubar) self.toolbar = toolbar.ToolBar(self) self.aui.AddPane( self.toolbar, aui.AuiPaneInfo().Name("toolbar").ToolbarPane().PaneBorder( False).Top().Row(1)) self.statusbar = self.CreateStatusBar(6) self.statusbar.SetStatusWidths( [-8, -2, -4, -1, -1, self.statusbar.GetTextExtent("OVR")[0] + 8]) self.notebook = notebook.MainNotebook(self) self.aui.AddPane( self.notebook, aui.AuiPaneInfo().Name("notebook").CenterPane().PaneBorder(False)) self.filebrowser = panes.FileBrowser(self) x, y, width, height = self.filebrowser.toolbar.GetToolRect( self.filebrowser.ID_OPTIONS) self.managers[wx.LEFT].AddPane(self.filebrowser, _("File Browser"), self.Bitmap("file-browser"), "filebrowser", x + width + 5) self.searchbar = toolbar.SearchBar(self) self.aui.AddPane( self.searchbar, aui.AuiPaneInfo().Name("searchbar").ToolbarPane().Gripper( False).Resizable().Bottom().Layer(0).DockFixed().Hide()) app.plugins.OnInit(self) filename = os.path.join(app.userdatadir, "write++.aui") if os.path.isfile(filename): perspective = open(filename, 'r') self.aui.LoadPerspective(perspective.read()) perspective.close() if len(app.frames) == 0 or session: self.LoadSession(self.session) else: self.statusbar.SetStatusText(_("untitled"), 1) self.session = "" if firstrun: welcome = os.path.join(app.cwd, "locale", app.locale.GetCanonicalName(), "readme.txt") if not os.path.isfile(welcome): welcome = os.path.join(app.cwd, "locale", "en_US", "readme.txt") self.OpenFile(welcome) editor = self.GetEditor() editor.filename = _("Welcome!") editor.new = True editor.SetReadOnly(True) editor.OnSavePointReached(None) elif not self.notebook.GetPageCount(): self.New() self.GetEditor().SetFocus() for i in self.managers: if len(self.managers[i].panes): self.managers[i].Realize() self.menubar.View.Check(self.menubar.ID_TOOLBAR, self.aui.GetPane("toolbar").IsShown()) for pane in self.panedict: manager = self.managers[self.panedict[pane]] self.menubar.View.Check( getattr(self.menubar, "ID_%s" % pane.upper()), pane in manager.visible) self.searchbar.SetGripperVisible(False) self.aui.Update() if app.settings["MaximizeState"]: self.Maximize() self.Layout() app.plugins.PostInit(self) self.aui.Bind(aui.EVT_AUI_PANE_BUTTON, self.OnAuiPaneButton) self.Bind(wx.EVT_ACTIVATE, self.OnActivate) self.Bind(wx.EVT_MOVE, self.OnMove) self.Bind(wx.EVT_SIZE, self.OnSize) self.Bind(wx.EVT_ICONIZE, self.OnIconize) self.Bind(wx.EVT_CLOSE, self.OnClose)
def OnMouseMove(self, event): """ Handles the ``wx.EVT_MOTION`` event for :class:`RibbonButtonBar`. :param `event`: a :class:`MouseEvent` event to be processed. """ cursor = event.GetPosition() new_hovered = None new_hovered_state = 0 layout = self._layouts[self._current_layout] for instance in layout.buttons: size = instance.base.sizes[instance.size] btn_rect = wx.Rect() btn_rect.SetTopLeft(self._layout_offset + instance.position) btn_rect.SetSize(size.size) if btn_rect.Contains(cursor) and self.IsButtonEnabled(instance.base.id): new_hovered = instance new_hovered_state = instance.base.state new_hovered_state &= ~RIBBON_BUTTONBAR_BUTTON_HOVER_MASK offset = wx.Point(*cursor) offset -= btn_rect.GetTopLeft() if size.normal_region.Contains(offset): new_hovered_state |= RIBBON_BUTTONBAR_BUTTON_NORMAL_HOVERED if size.dropdown_region.Contains(offset): new_hovered_state |= RIBBON_BUTTONBAR_BUTTON_DROPDOWN_HOVERED break if new_hovered is None and self.GetToolTip(): self.SetToolTip("") if new_hovered != self._hovered_button or (self._hovered_button is not None and \ new_hovered_state != self._hovered_button.base.state): if self._hovered_button is not None: self._hovered_button.base.state &= ~RIBBON_BUTTONBAR_BUTTON_HOVER_MASK self._hovered_button = new_hovered if self._hovered_button is not None: self._hovered_button.base.state = new_hovered_state self.SetToolTip(self._hovered_button.base.help_string) self.Refresh(False) if self._active_button and not self._lock_active_state: new_active_state = self._active_button.base.state new_active_state &= ~RIBBON_BUTTONBAR_BUTTON_ACTIVE_MASK size = self._active_button.base.sizes[self._active_button.size] btn_rect = wx.Rect() btn_rect.SetTopLeft(self._layout_offset + self._active_button.position) btn_rect.SetSize(size.size) if btn_rect.Contains(cursor): offset = wx.Point(*cursor) offset -= btn_rect.GetTopLeft() if size.normal_region.Contains(offset): new_active_state |= RIBBON_BUTTONBAR_BUTTON_NORMAL_ACTIVE if size.dropdown_region.Contains(offset): new_active_state |= RIBBON_BUTTONBAR_BUTTON_DROPDOWN_ACTIVE if new_active_state != self._active_button.base.state: self._active_button.base.state = new_active_state self.Refresh(False)
def DrawThumbnail(self, bmp, thumb, index): """ Draws a visible thumbnail. :param bmp: the thumbnail version of the original image; :param thumb: an instance of :class:`Thumb`; :param index: the index of the thumbnail to draw. """ dc = wx.MemoryDC() dc.SelectObject(bmp) x = self._tBorder / 2 y = self._tBorder / 2 # background dc.SetPen(wx.Pen(wx.BLACK, 0, wx.TRANSPARENT)) dc.SetBrush(wx.Brush(self.GetBackgroundColour(), wx.BRUSHSTYLE_SOLID)) dc.DrawRectangle(0, 0, bmp.GetWidth(), bmp.GetHeight()) # image img = thumb.GetBitmap(self._tWidth, self._tHeight) ww = img.GetWidth() hh = img.GetHeight() if index == self.GetPointed() and self.GetHighlightPointed(): # factor = 1.5 img = img.ConvertToImage() pil = Image.new('RGB', (img.GetWidth(), img.GetHeight())) pil.frombytes(bytes(img.GetData())) enh = ImageEnhance.Brightness(pil) enh = enh.enhance(1.5) img.SetData(enh.convert('RGB').tobytes()) img = img.ConvertToBitmap() imgRect = wx.Rect( x + (self._tWidth - img.GetWidth()) / 2, y + (self._tHeight - img.GetHeight()) / 2, img.GetWidth(), img.GetHeight()) if not thumb._alpha and self._dropShadow: dc.Blit( imgRect.x + 5, imgRect.y + 5, imgRect.width, imgRect.height, self.shadow, 500 - ww, 500 - hh) dc.DrawBitmap(img, imgRect.x, imgRect.y, True) # colour = self.GetSelectionColour() selected = self.IsSelected(index) colour = self.GetSelectionColour() # draw caption # sw, sh = 0, 0 if self._showcaptions: # textWidth = 0 dc.SetFont(self.GetCaptionFont()) mycaption = thumb.GetCaption(0) sw, sh = dc.GetTextExtent(mycaption) if sw > self._tWidth: mycaption = self.CalculateBestCaption(dc, mycaption, sw, self._tWidth) sw = self._tWidth textWidth = sw + 8 # tx = x + (self._tWidth - textWidth) / 2 # ty = y + self._tHeight txtcolour = "#7D7D7D" dc.SetTextForeground(txtcolour) tx = x + (self._tWidth - sw) / 2 if hh >= self._tHeight: ty = y + self._tHeight + (self._tTextHeight - sh) / 2 + 3 else: ty = y + hh + (self._tHeight - hh) / 2 + (self._tTextHeight - sh) / 2 + 3 dc.DrawText(mycaption, tx, ty) # outline if self._tOutline != thumbnailctrl.THUMB_OUTLINE_NONE and (self._tOutlineNotSelected or self.IsSelected(index)): dotrect = wx.Rect() dotrect.x = x - 2 dotrect.y = y - 2 dotrect.width = bmp.GetWidth() - self._tBorder + 4 dotrect.height = bmp.GetHeight() - self._tBorder + 4 dc.SetPen(wx.Pen( (self.IsSelected(index) and [colour] or [wx.LIGHT_GREY])[0], 0, wx.PENSTYLE_SOLID)) dc.SetBrush(wx.Brush(wx.BLACK, wx.BRUSHSTYLE_TRANSPARENT)) if self._tOutline == thumbnailctrl.THUMB_OUTLINE_FULL or self._tOutline == thumbnailctrl.THUMB_OUTLINE_RECT: imgRect.x = x imgRect.y = y imgRect.width = bmp.GetWidth() - self._tBorder imgRect.height = bmp.GetHeight() - self._tBorder if self._tOutline == thumbnailctrl.THUMB_OUTLINE_RECT: imgRect.height = self._tHeight dc.SetBrush(wx.TRANSPARENT_BRUSH) if selected: dc.SetPen(self.grayPen) dc.DrawRoundedRectangle(dotrect, 2) dc.SetPen(wx.Pen(wx.WHITE)) dc.DrawRectangle(imgRect.x, imgRect.y, imgRect.width, imgRect.height) pen = wx.Pen((selected and [colour] or [wx.LIGHT_GREY])[0], 2) pen.SetJoin(wx.JOIN_MITER) dc.SetPen(pen) if self._tOutline == thumbnailctrl.THUMB_OUTLINE_FULL: dc.DrawRoundedRectangle( imgRect.x - 1, imgRect.y - 1, imgRect.width + 3, imgRect.height + 3, 2) else: dc.DrawRectangle( imgRect.x - 1, imgRect.y - 1, imgRect.width + 3, imgRect.height + 3) else: dc.SetPen(wx.Pen(wx.LIGHT_GREY)) dc.DrawRectangle( imgRect.x - 1, imgRect.y - 1, imgRect.width + 2, imgRect.height + 2) dc.SelectObject(wx.NullBitmap)
def __init__(self): self.is_supported = True self.size = wx.Size() self.normal_region = wx.Rect() self.dropdown_region = wx.Rect()
def Draw(self, dc): size = self.GetClientSize() width = size.width height = size.height maxBib = unicode(999999) minBarWidth = 48 minBarHeight = 18 maxBarHeight = 28 backColour = self.GetBackgroundColour() backBrush = wx.Brush(backColour, wx.SOLID) greyBrush = wx.Brush(wx.Colour(196, 196, 196), wx.SOLID) lightGreyBrush = wx.Brush(wx.Colour(220, 220, 220), wx.SOLID) backPen = wx.Pen(backColour, 0) dc.SetBackground(backBrush) dc.Clear() tooSmall = (width < 50 or height < 24) if not self.data or self.dataMax == 0 or tooSmall: self.empty = True self.verticalSB.Show(False) self.horizontalSB.Show(False) if tooSmall: dc.SetPen(wx.BLACK_DASHED_PEN) dc.DrawLine(0, height // 2, width, height // 2) return self.empty = False barHeight = int(float(height) / float(len(self.data) + 2)) barHeight = max(barHeight, minBarHeight) barHeight = min(barHeight, maxBarHeight) fontBarLabel = wx.FontFromPixelSize( wx.Size(0, int(min(barHeight - 2, barHeight * 0.9))), wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) dc.SetFont(fontBarLabel) textWidthLeftMax, textHeightMax = dc.GetTextExtent(maxBib) statusTextSpace = dc.GetTextExtent(' ')[0] if self.status: statusTextWidth = max(dc.GetTextExtent(s)[0] for s in self.status) if statusTextWidth: statusTextWidth += statusTextSpace else: statusTextWidth = 0 self.status = [''] * len(self.data) textWidthLeftMax += statusTextWidth maxBibWidth = textWidthLeftMax textWidthRightMax = 0 for label in self.labels: if label not in self.headerSet: textWidthLeftMax = max( textWidthLeftMax, dc.GetTextExtent(label)[0] + statusTextWidth) num = numFromLabel(label) if num is not None: textWidthRightMax = max( textWidthRightMax, dc.GetTextExtent('{}'.format(num))[0]) textWidthRightMax += statusTextWidth if textWidthLeftMax + textWidthRightMax > width: self.horizontalSB.Show(False) self.verticalSB.Show(False) self.empty = True return maxLaps = max(len(d) for d in self.data) if maxLaps and (width - textWidthLeftMax - textWidthRightMax) / maxLaps < minBarWidth: self.horizontalSB.Show(True) else: self.horizontalSB.Show(False) if self.horizontalSB.IsShown(): height -= self.scrollbarWidth barHeight = int(float(height) / float(len(self.data) + 2)) barHeight = max(barHeight, minBarHeight) barHeight = min(barHeight, maxBarHeight) drawHeight = height - 2 * barHeight if barHeight * len(self.data) > drawHeight: self.verticalSB.Show(True) self.verticalSB.SetPosition( (width - self.scrollbarWidth, barHeight)) self.verticalSB.SetSize((self.scrollbarWidth, drawHeight)) pageSize = int(drawHeight / barHeight) SetScrollbarParameters(self.verticalSB, pageSize - 1, len(self.data) - 1, pageSize) else: self.verticalSB.Show(False) if self.verticalSB.IsShown(): width -= self.scrollbarWidth iDataShowStart = self.verticalSB.GetThumbPosition( ) if self.verticalSB.IsShown() else 0 iDataShowEnd = iDataShowStart + self.verticalSB.GetThumbSize( ) + 1 if self.verticalSB.IsShown() else len(self.data) tShowStart = self.horizontalSB.GetThumbPosition( ) if self.horizontalSB.IsShown() else 0 dc.SetFont(fontBarLabel) textWidthLeftMax, textHeightMax = dc.GetTextExtent(maxBib) textWidthRightMax = 0 for label in self.labels: if label not in self.headerSet: textWidthLeftMax = max( textWidthLeftMax, dc.GetTextExtent(label)[0] + statusTextWidth) num = numFromLabel(label) if num is not None: textWidthRightMax = max( textWidthRightMax, dc.GetTextExtent('{}'.format(num))[0]) textWidthRightMax += statusTextWidth if textWidthLeftMax + textWidthRightMax > width: self.horizontalSB.Show(False) self.verticalSB.Show(False) self.empty = True return legendSep = 4 # Separations between legend entries and the Gantt bars. labelsWidthLeft = textWidthLeftMax + legendSep labelsWidthRight = textWidthRightMax + legendSep ''' if labelsWidthLeft > width / 2: labelsWidthLeft = 0 labelsWidthRight = 0 drawLabels = False ''' xLeft = labelsWidthLeft xRight = width - labelsWidthRight yBottom = min(barHeight * (len(self.data) + 1), barHeight + drawHeight) yTop = barHeight if self.horizontalSB.IsShown(): viewWidth = minBarWidth * maxLaps ratio = float(xRight - xLeft) / float(viewWidth) sbMax = int(self.dataMax) + 1 pageSize = int(sbMax * ratio) SetScrollbarParameters(self.horizontalSB, pageSize - 1, sbMax, pageSize) self.horizontalSB.SetPosition((labelsWidthLeft, height)) self.horizontalSB.SetSize((xRight - xLeft, self.scrollbarWidth)) fontLegend = wx.FontFromPixelSize(wx.Size(0, barHeight * .75), wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) fontNote = wx.FontFromPixelSize(wx.Size(0, barHeight * .8), wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) dc.SetFont(fontLegend) textWidth, textHeight = dc.GetTextExtent('00:00' if self.dataMax < 60 * 60 else '00:00:00') # Draw the horizontal labels. # Find some reasonable tickmarks for the x axis. numLabels = (xRight - xLeft) / (textWidth * 1.5) tView = self.dataMax if not self.horizontalSB.IsShown( ) else self.horizontalSB.GetThumbSize() d = tView / max(1.0, float(numLabels)) intervals = [ 1, 2, 5, 10, 15, 20, 30, 1 * 60, 2 * 60, 5 * 60, 10 * 60, 15 * 60, 20 * 60, 30 * 60, 1 * 60 * 60, 2 * 60 * 60, 4 * 60 * 60, 8 * 60 * 60, 12 * 60 * 60, 24 * 60 * 60 ] d = intervals[bisect.bisect_left(intervals, d, 0, len(intervals) - 1)] if self.horizontalSB.IsShown(): tAdjust = self.horizontalSB.GetThumbPosition() viewWidth = minBarWidth * maxLaps dFactor = float(viewWidth) / float(self.dataMax) else: tAdjust = 0 dFactor = (xRight - xLeft) / float(self.dataMax) dc.SetPen(wx.Pen(wx.BLACK, 1)) for t in xrange(0, int(self.dataMax), d): x = xLeft + (t - tAdjust) * dFactor if x < xLeft: continue if x > xRight: break if t < 60 * 60: s = '{}:{:02d}'.format((t / 60), t % 60) else: s = '{}:{:02d}:{:02d}'.format(t / (60 * 60), (t / 60) % 60, t % 60) w, h = dc.GetTextExtent(s) xText = x - w / 2 #xText = x dc.DrawText(s, xText, 0 + 4) dc.DrawText(s, xText, yBottom + 4) dc.DrawLine(x, yBottom + 3, x, yTop - 3) # Draw the Gantt chart. dc.SetFont(fontBarLabel) textWidth, textHeight = dc.GetTextExtent(maxBib) penBar = wx.Pen(wx.Colour(128, 128, 128), 1) penBar.SetCap(wx.CAP_BUTT) penBar.SetJoin(wx.JOIN_MITER) dc.SetPen(penBar) brushBar = wx.Brush(wx.BLACK) transparentBrush = wx.Brush(wx.WHITE, style=wx.TRANSPARENT) ctx = wx.GraphicsContext_Create(dc) ctx.SetPen(wx.Pen(wx.BLACK, 1)) xyInterp = [] xyNumTimeInfo = [] xyDuplicate = [] xFactor = dFactor yLast = barHeight yHighlight = None tLeaderLast = None dy = 0 for i, s in enumerate(self.data): # Record the leader's last x position. if tLeaderLast is None: tLeaderLast = s[-1] if s else 0.0 if not (iDataShowStart <= i < iDataShowEnd): continue try: num = numFromLabel(self.labels[i]) except (TypeError, IndexError): num = -1 yCur = yLast + barHeight xLast = labelsWidthLeft xCur = xLast tTooShort = 9.0 # If a lap is shorter than 9 seconds, consider it a duplicate entry. for j, t in enumerate(s): if xLast >= xRight: break xCur = xOriginal = int(labelsWidthLeft + (t - tAdjust) * xFactor) if xCur < labelsWidthLeft: continue if xCur > xRight: xCur = xRight if j == 0: brushBar.SetColour(wx.WHITE) dc.SetBrush(brushBar) dc.DrawRectangle(xLast, yLast, xCur - xLast + 1, yCur - yLast + 1) else: ctx.SetPen(wx.Pen(wx.WHITE, 1, style=wx.TRANSPARENT)) dy = yCur - yLast + 1 dd = int(dy * 0.3) ic = j % len(self.colours) b1 = ctx.CreateLinearGradientBrush(0, yLast, 0, yLast + dd + 1, self.colours[ic], self.lighterColours[ic]) ctx.SetBrush(b1) ctx.DrawRectangle(xLast, yLast, xCur - xLast + 1, dd + 1) b2 = ctx.CreateLinearGradientBrush(0, yLast + dd, 0, yLast + dy, self.lighterColours[ic], self.colours[ic]) ctx.SetBrush(b2) ctx.DrawRectangle(xLast, yLast + dd, xCur - xLast + 1, dy - dd) dc.SetBrush(transparentBrush) dc.SetPen(penBar) dc.DrawRectangle(xLast, yLast, xCur - xLast + 1, dy) if self.lapNote: note = self.lapNote.get((num, j), None) if note: dc.SetFont(fontNote) noteWidth, noteHeight = dc.GetTextExtent(note) noteBorderWidth = int( dc.GetTextExtent(' ')[0] / 2) noteBarWidth = xCur - xLast - noteBorderWidth * 2 if noteBarWidth <= 0: noteBarWidth = xCur - xLast noteBorderWidth = 0 note = '...' noteWidth, noteHeight = dc.GetTextExtent(note) elif noteWidth > noteBarWidth: lenLeft, lenRight = 1, len(note) while lenRight - lenLeft > 1: lenMid = (lenRight + lenLeft) // 2 noteWidth, noteHeight = dc.GetTextExtent( note[:lenMid].strip() + '...') if noteWidth < noteBarWidth: lenLeft = lenMid else: lenRight = lenMid note = note[:lenLeft].strip() + '...' noteWidth, noteHeight = dc.GetTextExtent(note) dc.DrawText(note, xLast + noteBorderWidth, yLast + (dy - noteHeight) / 2) dc.SetFont(fontBarLabel) if j == self.moveLap and self.moveIRider == i: if hasPhoto(num, t): # Draw a little camera icon. cameraHeight = int(dy * 0.75) cameraWidth = int(cameraHeight * 1.5) dc.SetBrush(wx.BLACK_BRUSH) dc.DrawRoundedRectangle( xCur - 2 - cameraWidth, yLast + (dy - cameraHeight) / 2, cameraWidth, cameraHeight, cameraHeight / 5) dc.SetPen(wx.WHITE_PEN) dc.SetBrush(transparentBrush) dc.DrawCircle(xCur - 2 - cameraWidth / 2, yLast + dy / 2, cameraHeight * (0.6 / 2)) if xOriginal <= xRight: try: if self.interp[i][j]: xyInterp.append((xOriginal, yLast)) except (TypeError, ValueError, IndexError): pass if self.numTimeInfo and self.numTimeInfo.getInfo( num, t) is not None: xyNumTimeInfo.append((xOriginal, yLast)) if t - s[j - 1] < tTooShort: xyDuplicate.append((xOriginal, yLast)) xLast = xCur # Draw the last empty bar. xCur = int(labelsWidthLeft + self.dataMax * xFactor) if xCur > xRight: xCur = xRight dc.SetPen(penBar) brushBar.SetColour(wx.WHITE) dc.SetBrush(brushBar) dc.DrawRectangle(xLast, yLast, xCur - xLast + 1, yCur - yLast + 1) # Draw the label on both ends. if self.greyOutSet and i in self.greyOutSet: dc.SetPen(wx.TRANSPARENT_PEN) dc.SetBrush(greyBrush) dc.DrawRectangle(0, yLast, textWidthLeftMax, yCur - yLast + 1) dc.SetBrush(backBrush) if self.status[i] == _('PUL'): dc.SetPen(wx.TRANSPARENT_PEN) dc.SetBrush(lightGreyBrush) dc.DrawRectangle(0, yLast, textWidthLeftMax, yCur - yLast + 1) dc.SetBrush(backBrush) if self.labels[i] in self.headerSet: dc.DrawText(self.labels[i], labelsWidthLeft + 4, yLast) # This is a Category Label. else: labelWidth = dc.GetTextExtent(self.labels[i])[0] dc.DrawText(self.labels[i], textWidthLeftMax - labelWidth - statusTextWidth, yLast) if statusTextWidth and self.status[i]: dc.DrawText( self.status[i], textWidthLeftMax - statusTextWidth + statusTextSpace, yLast) if not self.minimizeLabels: label = self.labels[i] lastSpace = label.rfind(' ') if lastSpace > 0: label = label[lastSpace + 1:] labelWidth = dc.GetTextExtent(label)[0] dc.DrawText(label, width - labelsWidthRight + legendSep, yLast) if statusTextWidth and self.status[i]: dc.DrawText(self.status[i], width - statusTextWidth + statusTextSpace, yLast) if u'{}'.format(self.numSelect) == u'{}'.format( numFromLabel(self.labels[i])): yHighlight = yCur yLast = yCur if yHighlight is not None and len(self.data) > 1: dc.SetPen(wx.Pen(wx.BLACK, 2)) dc.SetBrush(wx.TRANSPARENT_BRUSH) dc.DrawLine(0, yHighlight, width, yHighlight) yHighlight -= barHeight dc.DrawLine(0, yHighlight, width, yHighlight) # Draw indicators for interpolated values. radius = (dy / 2) * 0.9 # Define a path for the interp indicator about the origin. diamondPath = ctx.CreatePath() diamondPath.MoveToPoint(0, -radius) diamondPath.AddLineToPoint(-radius, 0) diamondPath.AddLineToPoint(0, radius) diamondPath.AddLineToPoint(radius, 0) diamondPath.AddLineToPoint(0, -radius) def getStarPath(ctx, numPoints, radius, radiusInner): path = ctx.CreatePath() angle = (math.pi * 2.0) / numPoints angle2 = angle / 2.0 path.MoveToPoint(0, -radius) for p in xrange(numPoints): a = p * angle + angle2 + math.pi / 2.0 path.AddLineToPoint( math.cos(a) * radiusInner, -math.sin(a) * radiusInner) a = (p + 1) * angle + math.pi / 2.0 path.AddLineToPoint( math.cos(a) * radius, -math.sin(a) * radius) path.AddLineToPoint(0, -radius) return path starPath = getStarPath(ctx, 5, radius, radius / 2) # Draw the interp indicators. ctx.SetPen(penBar) ctx.SetBrush( ctx.CreateRadialGradientBrush(0, -radius * 0.50, 0, 0, radius + 1, wx.WHITE, self.yellowColour)) for xCur, yCur in xyInterp: ctx.PushState() ctx.Translate(xCur, yCur + dy / 2.0 - (dy / 2.0 - radius) / 4) ctx.DrawPath(diamondPath) ctx.PopState() # Draw the edit indictors. ctx.SetPen(penBar) ctx.SetBrush( ctx.CreateRadialGradientBrush(0, -radius * 0.50, 0, 0, radius + 1, wx.WHITE, self.orangeColour)) for xCur, yCur in xyNumTimeInfo: ctx.PushState() ctx.Translate(xCur, yCur + dy / 2.0 - (dy / 2.0 - radius) / 4) ctx.DrawPath(starPath) ctx.PopState() # Draw the duplicate indicators. radius = int(radius * 1.5) ctx.SetPen(wx.Pen(wx.RED, 3)) ctx.SetBrush(wx.TRANSPARENT_BRUSH) for xCur, yCur in xyDuplicate: ctx.DrawEllipse(xCur - radius, yCur + dy / 2.0 - radius, radius * 2, radius * 2) # Draw the now timeline. timeLineTime = self.nowTime if self.nowTime and self.nowTime < self.dataMax else tLeaderLast nowTimeStr = Utils.formatTime(timeLineTime) labelWidth, labelHeight = dc.GetTextExtent(nowTimeStr) x = int(labelsWidthLeft + (timeLineTime - tAdjust) * xFactor) ntColour = '#339966' dc.SetPen(wx.Pen(ntColour, 3)) dc.DrawLine(x, barHeight - 4, x, yLast + 4) dc.SetPen(wx.Pen(wx.WHITE, 1)) dc.DrawLine(x, barHeight - 4, x, yLast + 4) dc.SetBrush(wx.Brush(ntColour)) dc.SetPen(wx.Pen(ntColour, 1)) rect = wx.Rect(x - labelWidth / 2 - 2, 0, labelWidth + 4, labelHeight) dc.DrawRectangleRect(rect) if not self.minimizeLabels: rect.SetY(yLast + 2) dc.DrawRectangleRect(rect) dc.SetTextForeground(wx.WHITE) dc.DrawText(nowTimeStr, x - labelWidth / 2, 0) if not self.minimizeLabels: dc.DrawText(nowTimeStr, x - labelWidth / 2, yLast + 2) # Store the drawing scale parameters. self.xFactor = xFactor self.barHeight = barHeight self.labelsWidthLeft = labelsWidthLeft
def OnPaint(self, event): dc = wx.AutoBufferedPaintDC(self) if not self.GetUpdateRegion().ContainsRect( wx.Rect(0, 0, self.GetClientSize().GetWidth(), self._tab_height)): # Nothing to do in the tab area, and the page area is handled by the active page return self.DoEraseBackground(dc) numtabs = len(self._pages) sep_visibility = 0.0 draw_sep = False tabs_rect = wx.Rect( self._tab_margin_left, 0, self.GetClientSize().GetWidth() - self._tab_margin_left - self._tab_margin_right, self._tab_height) if self._tab_scroll_buttons_shown: tabs_rect.x += self._tab_scroll_left_button_rect.GetWidth() tabs_rect.width -= self._tab_scroll_left_button_rect.GetWidth( ) + self._tab_scroll_right_button_rect.GetWidth() for info in self._pages: dc.DestroyClippingRegion() if self._tab_scroll_buttons_shown: if not tabs_rect.Intersects(info.rect): continue dc.SetClippingRect(tabs_rect) dc.SetClippingRect(info.rect) self._art.DrawTab(dc, self, info) if info.rect.width < info.small_begin_need_separator_width: draw_sep = True if info.rect.width < info.small_must_have_separator_width: sep_visibility += 1.0 else: sep_visibility += float(info.small_begin_need_separator_width - info.rect.width)/ \ float(info.small_begin_need_separator_width - info.small_must_have_separator_width) if draw_sep: rect = wx.Rect(*self._pages[0].rect) rect.width = self._art.GetMetric(RIBBON_ART_TAB_SEPARATION_SIZE) sep_visibility /= float(numtabs) for i in xrange(0, numtabs - 1): info = self._pages[i] rect.x = info.rect.x + info.rect.width if self._tab_scroll_buttons_shown and not tabs_rect.Intersects( rect): continue dc.DestroyClippingRegion() dc.SetClippingRect(rect) self._art.DrawTabSeparator(dc, self, rect, sep_visibility) if self._tab_scroll_buttons_shown: dc.DestroyClippingRegion() if self._tab_scroll_left_button_rect.GetWidth() != 0: self._art.DrawScrollButton( dc, self, self._tab_scroll_left_button_rect, RIBBON_SCROLL_BTN_LEFT | self._tab_scroll_left_button_state | RIBBON_SCROLL_BTN_FOR_TABS) if self._tab_scroll_right_button_rect.GetWidth() != 0: self._art.DrawScrollButton( dc, self, self._tab_scroll_right_button_rect, RIBBON_SCROLL_BTN_RIGHT | self._tab_scroll_right_button_state | RIBBON_SCROLL_BTN_FOR_TABS)
def OnEraseBackground(self, event=None, paint_object=None): paint_object = event.GetEventObject() if not paint_object.IsShown(): return _dc = event.GetDC() if not _dc: _dc = wx.ClientDC(paint_object) rect = paint_object.GetUpdateRegion().GetBox() _dc.SetClippingRect(rect) dc = GCDC(_dc) dc.SetBackground(wx.Brush(paint_object.GetBackgroundColour(), wx.SOLID)) dc.Clear() # Calculate text extents. paint_message = self.GetPaintMessage() if paint_message: tw, th = self.GetClientSize() cw, ch = tw - MARGIN, th - MARGIN font_size = FONT_SIZE + 1 while (tw >= cw or th >= ch) and font_size > 5: font_size -= 1 font = wx.Font(font_size, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTSTYLE_NORMAL, encoding=wx.FONTENCODING_SYSTEM) dc.SetFont(font) tw, th = dc.GetTextExtent(paint_message) td = font_size / 2 twd = tw + 2 * td thd = th + 2 * td else: tw = th = 0 # Draw logo. ew, eh = paint_object.GetSize() if self.paint_logo: # Draw logo. lw, lh = self._paint_logo.GetSize() lx, ly = (ew - lw) / 2, (eh - lh + 2 * thd) / 2 dc.DrawBitmap(self._paint_logo, lx, ly, True) else: # Skip logo. lx, ly = ew / 2, eh / 2 # Check if text is necessary too. if not paint_message: return # Draw rounded rectangle. if self.paint_logo: rx, ry = (ew - twd) / 2, ly - 2 * thd else: rx, ry = (ew - twd) / 2, (eh - thd) / 2 rect = wx.Rect(rx, ry, twd, thd) if self.paint_border_color: penclr = self.paint_border_color else: penclr = self.paint_color dc.SetPen(wx.Pen(penclr)) dc.SetBrush(wx.Brush(self.paint_color)) dc.DrawRoundedRectangleRect(rect, self.paint_radius) # Draw text. dc.SetTextForeground(paint_object.GetBackgroundColour()) dc.DrawText(paint_message, rx + td, ry + td)
def GetExpandedPosition(self, panel, expanded_size, direction): # Strategy: # 1) Determine primary position based on requested direction # 2) Move the position so that it sits entirely within a display # (for single monitor systems, this moves it into the display region, # but for multiple monitors, it does so without splitting it over # more than one display) # 2.1) Move in the primary axis # 2.2) Move in the secondary axis primary_x = False secondary_x = secondary_y = 0 pos = wx.Point() if direction == wx.NORTH: pos.x = panel.GetX() + (panel.GetWidth() - expanded_size.GetWidth()) / 2 pos.y = panel.GetY() - expanded_size.GetHeight() primary_x = True secondary_y = 1 elif direction == wx.EAST: pos.x = panel.GetRight() pos.y = panel.GetY() + (panel.GetHeight() - expanded_size.GetHeight()) / 2 secondary_x = -1 elif direction == wx.SOUTH: pos.x = panel.GetX() + (panel.GetWidth() - expanded_size.GetWidth()) / 2 pos.y = panel.GetBottom() primary_x = True secondary_y = -1 else: pos.x = panel.GetX() - expanded_size.GetWidth() pos.y = panel.GetY() + (panel.GetHeight() - expanded_size.GetHeight()) / 2 secondary_x = 1 expanded = wx.Rect(pos, expanded_size) best = wx.Rect(*expanded) best_distance = 10000 display_n = wx.Display.GetCount() for display_i in range(display_n): display = wx.Display(display_i).GetGeometry() if display.Contains(expanded): return expanded elif display.Intersects(expanded): new_rect = wx.Rect(*expanded) distance = 0 if primary_x: if expanded.GetRight() > display.GetRight(): distance = expanded.GetRight() - display.GetRight() new_rect.x -= distance elif expanded.GetLeft() < display.GetLeft(): distance = display.GetLeft() - expanded.GetLeft() new_rect.x += distance else: if expanded.GetBottom() > display.GetBottom(): distance = expanded.GetBottom() - display.GetBottom() new_rect.y -= distance elif expanded.GetTop() < display.GetTop(): distance = display.GetTop() - expanded.GetTop() new_rect.y += distance if not display.Contains(new_rect): # Tried moving in primary axis, but failed. # Hence try moving in the secondary axis. dx = secondary_x * (panel.GetWidth() + expanded_size.GetWidth()) dy = secondary_y * (panel.GetHeight() + expanded_size.GetHeight()) new_rect.x += dx new_rect.y += dy # Squaring makes secondary moves more expensive (and also # prevents a negative cost) distance += dx * dx + dy * dy if display.Contains(new_rect) and distance < best_distance: best = new_rect best_distance = distance return best
def refresh(self, x=0, y=0, w=0, h=0, clear=True): if not w: w, h = self.GetSize() self.Refresh(rect=wx.Rect(x, y, w, h), eraseBackground=clear)
def cachePaint(self, size): """ Caches the widget so self.paintBuffer is up-to-date. """ def wordWrap(text, lineWidth, gc): """ Returns a list of lines from a string This is somewhat based on the wordwrap function built into wx.lib. (For some reason, GraphicsContext.GetPartialTextExtents() is returning totally wrong numbers but GetTextExtent() works fine.) This assumes that you've already set up the font you want on the GC. It gloms multiple spaces together, but for our purposes that's ok. """ words = re.finditer('\S+\s*', text.replace('\r', '')) lines = '' currentLine = '' for w in words: word = w.group(0) wordWidth = gc.GetTextExtent(currentLine + word)[0] if wordWidth < lineWidth: currentLine += word if '\n' in word: lines += currentLine currentLine = '' else: lines += currentLine + '\n' currentLine = word lines += currentLine return lines.split('\n') # Which set of colors to use flat = self.app.config.ReadBool('flatDesign') colors = PassageWidget.FLAT_COLORS if flat else PassageWidget.COLORS def dim(c, dim, flat=flat): """Lowers a color's alpha if dim is true.""" if isinstance(c, wx.Colour): c = list(c.Get(includeAlpha=True)) elif type(c) is str: c = bytearray(codecs.decode(c[1:], 'hex')) else: c = list(c) if len(c) < 4: c.append(255) if dim: a = PassageWidget.FLAT_DIMMED_ALPHA if flat else PassageWidget.DIMMED_ALPHA if not self.app.config.ReadBool('fastStoryPanel'): c[3] = int(c[3] * a) else: c[0] *= a c[1] *= a c[2] *= a return wx.Colour(*c) # set up our buffer bitmap = wx.Bitmap(size.width, size.height) self.paintBuffer.SelectObject(bitmap) # switch to a GraphicsContext as necessary gc = self.paintBuffer if self.app.config.ReadBool( 'fastStoryPanel') else wx.GraphicsContext.Create(self.paintBuffer) # text font sizes # wxWindows works with points, so we need to doublecheck on actual pixels titleFontSize = self.parent.toPixels((metrics.size('widgetTitle'), -1), scaleOnly=True)[0] titleFontSize = sorted((metrics.size('fontMin'), titleFontSize, metrics.size('fontMax')))[1] excerptFontSize = sorted((metrics.size('fontMin'), titleFontSize * 0.9, metrics.size('fontMax')))[1] if self.app.config.ReadBool('flatDesign'): titleFont = wx.Font(titleFontSize, wx.SWISS, wx.NORMAL, wx.LIGHT, False, 'Arial') excerptFont = wx.Font(excerptFontSize, wx.SWISS, wx.NORMAL, wx.LIGHT, False, 'Arial') else: titleFont = wx.Font(titleFontSize, wx.SWISS, wx.NORMAL, wx.BOLD, False, 'Arial') excerptFont = wx.Font(excerptFontSize, wx.SWISS, wx.NORMAL, wx.NORMAL, False, 'Arial') titleFontHeight = math.fabs(titleFont.GetPixelSize()[1]) excerptFontHeight = math.fabs(excerptFont.GetPixelSize()[1]) tagBarColor = dim( tuple(i * 256 for i in colorsys.hsv_to_rgb( 0.14 + math.sin(hash("".join(self.passage.tags))) * 0.08, 0.58 if flat else 0.28, 0.88)), self.dimmed) tags = set( self.passage.tags) - (tiddlywiki.TiddlyWiki.INFO_TAGS | self.getHeader().invisiblePassageTags()) # inset for text (we need to know this for layout purposes) inset = titleFontHeight / 3 # frame if self.passage.isAnnotation(): frameColor = colors['frame'] c = wx.Colour(*colors['annotation']) frameInterior = (c, c) else: frameColor = dim(colors['frame'], self.dimmed) frameInterior = (dim(colors['bodyStart'], self.dimmed), dim(colors['bodyEnd'], self.dimmed)) if not flat: gc.SetPen(wx.Pen(frameColor, 1)) if isinstance(gc, wx.GraphicsContext): gc.SetBrush(gc.CreateLinearGradientBrush(0, 0, 0, size.height, \ frameInterior[0], frameInterior[1])) else: gc.GradientFillLinear(wx.Rect(0, 0, size.width - 1, size.height - 1), \ frameInterior[0], frameInterior[1], wx.SOUTH) gc.SetBrush(wx.TRANSPARENT_BRUSH) gc.DrawRectangle(0, 0, size.width - 1, size.height - 1) else: gc.SetPen(wx.Pen(frameInterior[0])) gc.SetBrush(wx.Brush(frameInterior[0])) gc.DrawRectangle(0, 0, size.width, size.height) greek = size.width <= PassageWidget.MIN_GREEKING_SIZE * ( 2 if self.passage.isAnnotation() else 1) # title bar titleBarHeight = PassageWidget.GREEK_HEIGHT * 3 if greek else titleFontHeight + ( 2 * inset) if self.passage.isAnnotation(): titleBarColor = frameInterior[0] else: titleBarColor = dim(self.getTitleColor(), self.dimmed) gc.SetPen(wx.Pen(titleBarColor, 1)) gc.SetBrush(wx.Brush(titleBarColor)) if flat: gc.DrawRectangle(0, 0, size.width, titleBarHeight) else: gc.DrawRectangle(1, 1, size.width - 3, titleBarHeight) if not greek: # draw title # we let clipping prevent writing over the frame if isinstance(gc, wx.GraphicsContext): gc.ResetClip() gc.Clip(inset, inset, size.width - (inset * 2), titleBarHeight - 2) else: gc.DestroyClippingRegion() gc.SetClippingRect( wx.Rect(inset, inset, size.width - (inset * 2), titleBarHeight - 2)) titleTextColor = dim(colors['titleText'], self.dimmed) if isinstance(gc, wx.GraphicsContext): gc.SetFont(titleFont, titleTextColor) else: gc.SetFont(titleFont) gc.SetTextForeground(titleTextColor) if self.passage.title: gc.DrawText(self.passage.title, inset, inset) # draw excerpt if not self.passage.isImage(): excerptTop = inset + titleBarHeight # we split the excerpt by line, then draw them in turn # (we use a library to determine breaks, but have to draw the lines ourselves) if isinstance(gc, wx.GraphicsContext): gc.ResetClip() gc.Clip(inset, inset, size.width - (inset * 2), size.height - (inset * 2) - 1) else: gc.DestroyClippingRegion() gc.SetClippingRect( wx.Rect(inset, inset, size.width - (inset * 2), size.height - (inset * 2) - 1)) if self.passage.isAnnotation(): excerptTextColor = wx.Colour(*colors['annotationText']) else: excerptTextColor = dim(colors['excerptText'], self.dimmed) if isinstance(gc, wx.GraphicsContext): gc.SetFont(excerptFont, excerptTextColor) else: gc.SetFont(excerptFont) gc.SetTextForeground(excerptTextColor) excerptLines = wordWrap(self.passage.text, size.width - (inset * 2), gc) for line in excerptLines: gc.DrawText(line, inset, excerptTop) excerptTop += excerptFontHeight * PassageWidget.LINE_SPACING \ * min(1.75,max(1,1.75*size.width/260 if (self.passage.isAnnotation() and line) else 1)) if excerptTop + excerptFontHeight > size.height - inset: break if (self.passage.isStoryText() or self.passage.isStylesheet()) and tags: tagBarHeight = excerptFontHeight + (2 * inset) gc.SetPen(wx.Pen(tagBarColor, 1)) gc.SetBrush(wx.Brush(tagBarColor)) gc.DrawRectangle(0, size.height - tagBarHeight - 1, size.width, tagBarHeight + 1) # draw tags tagTextColor = dim(colors['frame'], self.dimmed) if isinstance(gc, wx.GraphicsContext): gc.SetFont(excerptFont, tagTextColor) else: gc.SetFont(excerptFont) gc.SetTextForeground(tagTextColor) text = wordWrap(' '.join(tags), size.width - (inset * 2), gc)[0] gc.DrawText(text, inset * 2, (size.height - tagBarHeight)) else: # greek title gc.SetPen(wx.Pen(colors['titleText'], PassageWidget.GREEK_HEIGHT)) height = inset width = (size.width - inset) / 2 if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(inset, height, width, height) else: gc.DrawLine(inset, height, width, height) height += PassageWidget.GREEK_HEIGHT * 3 # greek body text if not self.passage.isImage(): gc.SetPen(wx.Pen(colors['annotationText'] \ if self.passage.isAnnotation() else colors['greek'], PassageWidget.GREEK_HEIGHT)) chars = len(self.passage.text) while height < size.height - inset and chars > 0: width = size.height - inset if height + (PassageWidget.GREEK_HEIGHT * 2) > size.height - inset: width /= 2 elif chars < 80: width = max(4, width * chars / 80) if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(inset, height, width, height) else: gc.DrawLine(inset, height, width, height) height += PassageWidget.GREEK_HEIGHT * 2 chars -= 80 # greek tags if (self.passage.isStoryText() or self.passage.isStylesheet()) and tags: tagBarHeight = PassageWidget.GREEK_HEIGHT * 3 gc.SetPen(wx.Pen(tagBarColor, 1)) gc.SetBrush(wx.Brush(tagBarColor)) height = size.height - tagBarHeight - 2 width = size.width - 4 gc.DrawRectangle(2, height, width, tagBarHeight) gc.SetPen(wx.Pen(colors['greek'], PassageWidget.GREEK_HEIGHT)) height += inset width = (width - inset * 2) / 2 if isinstance(gc, wx.GraphicsContext): gc.StrokeLine(inset, height, width, height) else: gc.DrawLine(inset, height, width, height) if self.passage.isImage(): if self.bitmap: if isinstance(gc, wx.GraphicsContext): gc.ResetClip() gc.Clip(1, titleBarHeight + 1, size.width - 3, size.height - 3) else: gc.DestroyClippingRegion() gc.SetClippingRect( wx.Rect(1, titleBarHeight + 1, size.width - 3, size.height - 3)) width = size.width height = size.height - titleBarHeight # choose smaller of vertical and horizontal scale factor, to preserve aspect ratio scale = min(width / float(self.bitmap.GetWidth()), height / float(self.bitmap.GetHeight())) img = self.bitmap.ConvertToImage() if scale != 1: img = img.Scale(scale * self.bitmap.GetWidth(), scale * self.bitmap.GetHeight()) # offset image horizontally or vertically, to centre after scaling offsetWidth = (width - img.GetWidth()) / 2 offsetHeight = (height - img.GetHeight()) / 2 if isinstance(gc, wx.GraphicsContext): gc.DrawBitmap(img.ConvertToBitmap(self.bitmap.GetDepth()), 1 + offsetWidth, titleBarHeight + 1 + offsetHeight, img.GetWidth(), img.GetHeight()) else: gc.DrawBitmap(img.ConvertToBitmap(self.bitmap.GetDepth()), 1 + offsetWidth, titleBarHeight + 1 + offsetHeight) if isinstance(gc, wx.GraphicsContext): gc.ResetClip() else: gc.DestroyClippingRegion() # draw a broken link emblem in the bottom right if necessary # fixme: not sure how to do this with transparency def showEmblem(emblem, gc=gc, size=size, inset=inset): emblemSize = emblem.GetSize() emblemPos = [ size.width - (emblemSize[0] + inset), \ size.height - (emblemSize[1] + inset) ] if isinstance(gc, wx.GraphicsContext): gc.DrawBitmap(emblem, emblemPos[0], emblemPos[1], emblemSize[0], emblemSize[1]) else: gc.DrawBitmap(emblem, emblemPos[0], emblemPos[1]) if len(self.getBrokenLinks()): showEmblem(self.brokenEmblem) elif len(self.getIncludedLinks()) or len(self.passage.variableLinks): showEmblem(self.externalEmblem) # finally, draw a selection over ourselves if we're selected if self.selected: color = dim( titleBarColor if flat else wx.SystemSettings.GetColour( wx.SYS_COLOUR_HIGHLIGHT), self.dimmed) if self.app.config.ReadBool('fastStoryPanel'): gc.SetPen(wx.Pen(color, 2 + flat)) else: gc.SetPen(wx.TRANSPARENT_PEN) if isinstance(gc, wx.GraphicsContext): r, g, b = color.Get(False) color = wx.Colour(r, g, b, 64) gc.SetBrush(wx.Brush(color)) else: gc.SetBrush(wx.TRANSPARENT_BRUSH) gc.DrawRectangle(0, 0, size.width, size.height) self.paintBufferBounds = size
def invert_text_bitmap(bmp, color=(0, 0, 0)): w, h = bmp.GetSize() img = bmp.ConvertToImage() img.ConvertColourToAlpha(0, 0, 0) img.SetRGBRect(wx.Rect(0, 0, w, h), *color) return img.ConvertToBitmap()
def getPixelRect(self): """Returns this instance's rectangle onscreen.""" origin = self.parent.toPixels(self.pos) size = self.parent.toPixels(self.getSize(), scaleOnly=True) return wx.Rect(origin[0], origin[1], size[0], size[1])
def _refresh(self): self.Refresh(True, (wx.Rect(self._dynam_pos, self._dynam_size)))
def DrawEditText(self, t, style, start_x, show_at_x, x_width, y, dc): #dc.DrawText(t, x * self.cell_width_in_pixels, y * self.cell_height_in_pixels) draw_log.debug("DRAWEDIT: %d %d %d" % (start_x, show_at_x, x_width)) rect = wx.Rect(show_at_x * self.cell_width_in_pixels, y * self.cell_height_in_pixels, x_width * self.cell_width_in_pixels, self.cell_height_in_pixels) self.table.hex_renderer.draw_text(dc, rect, [t], [style], x_width)
def draw_grid(self, grid_control, dc, first_row, visible_rows, first_cell, visible_cells): t = grid_control.table first_col = self.cell_to_col[first_cell] last_cell = min(first_cell + visible_cells, self.num_cells) last_col = self.cell_to_col[last_cell - 1] + 1 last_row = min(first_row + visible_rows, t.num_rows) log.debug("draw_grid: rows:%d,%d (vis %d, num %d) cols:%d,%d" % (first_row, last_row, visible_rows, t.num_rows, first_col, last_col)) ul_rect = self.col_to_rect(first_row, first_col) lr_rect = self.col_to_rect(last_row - 1, last_col - 1) frame_rect = wx.Rect(ul_rect.x, ul_rect.y, lr_rect.x - ul_rect.x + lr_rect.width, lr_rect.y - ul_rect.y + lr_rect.height) dc.SetClippingRegion(frame_rect) # First and last rows may not span entire width. Process those # separately # # First row may not have bytes at the beginning of the row if the start # offset is not zero if first_row == 0: try: col, index, last_index = self.calc_column_range(grid_control, first_row, first_col, last_col) except IndexError: pass # skip lines with no visible cells else: self.draw_line(grid_control, dc, first_row, col, index, last_index) first_row += 1 if first_row == last_row: return frame_rect.y += ul_rect.height # Last row may not have bytes at the end of the row if last_row == t.num_rows: try: col, index, last_index = self.calc_column_range(grid_control, last_row - 1, first_col, last_col) except IndexError: pass # skip lines with no visible cells else: self.draw_line(grid_control, dc, last_row - 1, col, index, last_index) last_row -= 1 bytes_per_row = t.items_per_row nr = last_row - first_row nc = last_col - first_col first_index = (first_row * bytes_per_row) - t.start_offset last_index = (last_row * bytes_per_row) - t.start_offset t = t if last_index > len(t.data): last_index = len(t.data) data = np.zeros((nr * bytes_per_row), dtype=np.uint8) data[0:last_index - first_index] = t.data[first_index:last_index] style = np.zeros((nr * bytes_per_row), dtype=np.uint8) style[0:last_index - first_index] = t.style[first_index:last_index] else: data = t.data[first_index:last_index] style = t.style[first_index:last_index] data = data.reshape((nr, -1)) style = style.reshape((nr, -1)) # get_image(cls, machine, antic_font, bytes, style, start_byte, end_byte, bytes_per_row, nr, start_col, visible_cols): array = grid_control.font_renderer.get_image(grid_control.segment_viewer, grid_control.segment_viewer.current_antic_font, data, style, first_index, last_index, bytes_per_row, nr, first_col, nc) width = array.shape[1] height = array.shape[0] if width > 0 and height > 0: array = intscale(array, grid_control.zoom_h, grid_control.zoom_w) #print("bitmap: %d,%d,3 after scaling: %s" % (height, width, str(array.shape))) image = wx.Image(array.shape[1], array.shape[0]) image.SetData(array.tostring()) bmp = wx.Bitmap(image) dc.DrawBitmap(bmp, frame_rect.x, frame_rect.y)
def DoDrawButton(self, dc, xpos, bidx, selected=False, draw_label=False): """Draw a button @param dc: DC to draw on @param xpos: X coordinate @param bidx: button dict @keyword selected: is this the selected button (bool) @keyword draw_label: draw the label (bool) return: int (next xpos) """ button = self._buttons[bidx] rect = self.GetRect() height = rect.GetHeight() bsize = button['bsize'] bxpos = ((self._segsize[0] / 2) - (bsize.GetWidth() / 2)) + xpos bpos = (bxpos, SegmentBar.VPAD) rside = xpos + self._segsize[0] brect = wx.Rect(xpos, 0, rside - xpos, height) if selected: self.DoPaintBackground(dc, brect, self._scolor1, self._scolor2) bmp = button['bmp'] dc.DrawBitmap(bmp, bpos[0], bpos[1], bmp.GetMask() != None) if draw_label: twidth, theight = button['lsize'] typos = height - theight - 2 trect = wx.Rect(xpos, typos, self._segsize[0], theight + 3) dc.DrawLabel(button['label'], trect, wx.ALIGN_CENTER) if not selected: if not (self._style & CTRLBAR_STYLE_NO_DIVIDERS): dc.SetPen(self._pen) dc.DrawLine(xpos, 0, xpos, height) dc.DrawLine(rside, 0, rside, height) else: dc.SetPen(self._spen) tmpx = xpos + 1 trside = rside - 1 dc.DrawLine(tmpx, 0, tmpx, height) dc.DrawLine(trside, 0, trside, height) tpen = wx.Pen(self._spen.GetColour()) tpen.SetJoin(wx.JOIN_BEVEL) mpoint = height / 2 mlen = mpoint / 2 dc.DrawLine(tmpx + 1, mpoint, tmpx, 0) dc.DrawLine(tmpx + 1, mpoint, tmpx, height) dc.DrawLine(trside - 1, mpoint, trside, 0) dc.DrawLine(trside - 1, mpoint, trside, height) button['bx1'] = xpos + 1 button['bx2'] = rside - 1 button['selected'] = selected if self.SegmentHasCloseButton(bidx): brect = wx.Rect(button['bx1'], 0, button['bx2'] - (xpos - 1), height) self.DoDrawCloseBtn(dc, button, brect) return rside
def DrawHorzBand(self, dc, rect): """ Draws horizontal bands. :param `dc`: an instance of :class:`wx.DC`; :param `rect`: the horizontal bands client rectangle. .. todo:: Implement falloff effect for horizontal bands. """ horzBands = (self._ledBands > 1 and [self._ledBands] or [self._maxValue*BAND_PERCENT//100])[0] minHorzLimit = self._minValue*horzBands//self._maxValue medHorzLimit = self._medValue*horzBands//self._maxValue maxHorzLimit = horzBands size = wx.Size(rect.width//horzBands, rect.height//self._numBands) rectBand = wx.Rect(rect.GetTopLeft(), size) # Draw band from top rectBand.Offset(0, rect.height-size.y*self._numBands) xDecal = (self._ledBands > 1 and [1] or [0])[0] yDecal = (self._numBands > 1 and [1] or [0])[0] rectPrev = wx.Rect(*rectBand) for vert in range(self._numBands): self._value = self._meterData[vert]._value horzLimit = self._value*horzBands//self._maxValue for horz in range(horzBands): rectBand.Deflate(0, yDecal) # Find colour based on range value colourRect = self._clrBackground if self._showGrid: colourRect = DarkenColour(self._clrBackground, GRID_INCREASEBY) if self._showGrid and (horz == minHorzLimit or horz == (horzBands-1)): points = [wx.Point() for i in range(2)] points[0].x = rectBand.GetTopLeft().x + (rectBand.width >> 1) points[0].y = rectBand.GetTopLeft().y - yDecal points[1].x = points[0].x points[1].y = rectBand.GetBottomRight().y + yDecal dc.DrawLine(points[0], points[1]) if horz < horzLimit: if InRange(horz, 0, minHorzLimit-1): colourRect = self._clrNormal elif InRange(horz, minHorzLimit, medHorzLimit-1): colourRect = self._clrMedium elif InRange(horz, medHorzLimit, maxHorzLimit): colourRect = self._clrHigh dc.SetBrush(wx.Brush(colourRect)) dc.DrawRectangle(rectBand) rectBand.Inflate(0, yDecal) rectBand.Offset(size.x, 0) # Draw falloff effect (Seems to be working now.) if self._showFalloff: oldPen = dc.GetPen() pen = wx.Pen(DarkenColour(self._clrBackground, FALL_INCREASEBY)) maxWidth = size.x*horzBands points = [wx.Point() for i in range(2)] points[0].y = rectPrev.GetTopRight().y - yDecal points[0].x = rectPrev.GetBottomLeft().x + self._meterData[vert]._falloff*maxWidth/self._maxValue points[1].y = rectPrev.GetBottomLeft().y + yDecal points[1].x = points[0].x dc.SetPen(pen) dc.DrawLine(points[0], points[1]) dc.SetPen(oldPen) # Move to Next Vertical band rectBand.Offset(-size.x*horzBands, size.y)