def __init__(self, master=None, toplevel=None, document=None, show_visible=0, show_printable=1, resolution=None, **kw): apply(PyWidget.__init__, (self, master), kw) Viewport.__init__(self, resolution) QueueingPublisher.__init__(self) self.toplevel = toplevel self.move_window_count = 0 self.show_page_outline = 1 self.show_visible = show_visible self.show_printable = show_printable self.gcs_initialized = 0 self.gc = GraphicsDevice() self.renderer = DocRenderer(self) self.widget_size = () self.init_transactions() if document is not None: self.SetDocument(document) else: self.SetDocument(Document(create_layer=1))
class SketchView(PyWidget, Viewport, QueueingPublisher): document = None def __init__(self, master=None, toplevel=None, document=None, show_visible=0, show_printable=1, resolution=None, **kw): apply(PyWidget.__init__, (self, master), kw) Viewport.__init__(self, resolution) QueueingPublisher.__init__(self) self.toplevel = toplevel self.move_window_count = 0 self.show_page_outline = 1 self.show_visible = show_visible self.show_printable = show_printable self.gcs_initialized = 0 self.gc = GraphicsDevice() self.renderer = DocRenderer(self) self.widget_size = () self.init_transactions() if document is not None: self.SetDocument(document) else: self.SetDocument(Document(create_layer=1)) def destroy(self): self.unsubscribe_doc() PyWidget.destroy(self) QueueingPublisher.Destroy(self) def MapMethod(self): # when being mapped the first time, initialise the gcs. this cannot be # done earlier, because the hitgc creates a pixmap which currently # only works after the window (id) has been created. In Xt this can be # done in the Realize widget method (after calling the superclass' # method), but Tk doesn't seem to offer any similar thing. if not self.gcs_initialized: self.init_gcs() self.issue_state() def DestroyMethod(self): # make sure that gc is deleted. gc may have a shared memory ximage # which is not freed if the gc is not destroyed leaving unused shared # memory segments in the system even after the process has finished. self.gc = None PyWidget.DestroyMethod(self) def init_gcs(self): self.gc.init_gc(self.tkwin, graphics_exposures=1) self.gc.draw_visible = self.show_visible self.gc.draw_printable = self.show_printable self.gc.allow_outline = 0 self.gcs_initialized = 1 self.default_view() self.set_gc_transforms() def default_view(self): self.FitPageToWindow() def set_gc_transforms(self): self.gc.SetViewportTransform(self.scale, self.doc_to_win, self.win_to_doc) # # Channels # def issue_state(self): self.queue_message(STATE) def issue_view(self): self.queue_message(VIEW) def issue_document(self): self.doc_changed = 1 def queue_message(self, Publisher): if self.transaction: QueueingPublisher.queue_message(self, Publisher) else: self.issue(Publisher) def init_transactions(self): self.sb_update_pending = 0 self.doc_changed = 0 self.transaction = 0 def begin_transaction(self): self.transaction = self.transaction + 1 def end_transaction(self): self.transaction = self.transaction - 1 if self.transaction == 0: if self.doc_changed: self.issue(DOCUMENT, self.document) self.sb_update_pending = 0 self.doc_changed = 0 self.flush_message_queue() elif self.transaction < 0: raise SketchInternalError('transaction count < 0') # # receivers # def redraw_doc(self, all, rects=None): if all: self.clear_window() else: map(self.clear_area_doc, rects) def layout_changed(self): self.SetPageSize(self.document.Layout().Size()) self.set_gc_transforms() self.update_scrollbars() self.update_rulers() if self.show_page_outline: self.clear_window() def layer_changed(self, *args): if args: redraw = EmptyRect if args[0] == LAYER_STATE: layer, visible_changed, printable_changed, outlined_changed \ = args[1] rect = layer.bounding_rect if rect is not EmptyRect: if self.show_printable and printable_changed: redraw = rect if self.show_visible: if visible_changed: redraw = rect if outlined_changed and layer.Visible(): redraw = rect elif args[0] == LAYER_ORDER: layer = args[1] if (self.show_printable and layer.Printable() or self.show_visible and layer.Visible()): redraw = layer.bounding_rect if len(args) > 2: other = args[2] if (self.show_printable and other.Printable() or self.show_visible and other.Visible()): redraw = IntersectRects(redraw, other.bounding_rect) else: redraw = EmptyRect elif args[0] == LAYER_COLOR: layer = args[1] rect = layer.bounding_rect if self.show_visible and rect is not EmptyRect \ and layer.Visible(): redraw = rect self.clear_area_doc(redraw) # # Widget Methods (Redraw, ... ) # def get_matrix(self): return self.doc_to_win.coeff() time_redraw = 0 def RedrawMethod(self, region=None): # draw the document if self.move_window_count >= 2: self.clear_window(update=0) self.move_window_count = 0 region = self.do_clear(region) tkwin = self.tkwin if region: x, y, w, h = region.ClipBox() if x < 0: w = w - x; x = 0 if y < 0: h = h - y; y = 0 if w > tkwin.width: w = tkwin.width if h > tkwin.height: h = tkwin.height else: x = y = 0 w = tkwin.width h = tkwin.height p1 = self.WinToDoc(x - 1, y - 1) p2 = self.WinToDoc(x + w + 1, y + h + 1) rect = Rect(p1, p2) self.renderer.draw(self.document, rect) return region def ResizedMethod(self, width, height): Viewport.ResizedMethod(self, width, height) self.gc.WindowResized(width, height) if self.widget_size: center = self.WinToDoc(width / 2, height / 2,) dx = ((width - self.widget_size[0]) / 2) / self.scale dy = ((height - self.widget_size[1]) / 2) / self.scale self.SetCenter((center[0] - dx, center[1] + dy)) self.RedrawMethod() self.widget_size = (width, height) # # Viewport- and related methods # # extend some Viewport methods to issue VIEW whenever # the displayed area changes # def ForceRedraw(self): # Force a redraw of the whole window self.clear_window() if __debug__: #self.time_redraw = 1 pass # def SetScrollbars(self, hbar, vbar): # Viewport.SetScrollbars(self, hbar, vbar) # hbar.configure(jump = 1) # vbar.configure(jump = 1) def set_origin(self, xorg, yorg, move_contents=1): self.begin_transaction() try: Viewport.set_origin(self, xorg, yorg, move_contents=move_contents) self.set_gc_transforms() self.issue_view() finally: self.end_transaction() def move_window_contents(self, offx, offy): # implement the method needed by Viewport.set_origin w = self.tkwin width = w.width height = w.height if config.preferences.cairo_enabled : self.clear_window() else: if abs(offx) < width and abs(offy) < height: w.CopyArea(w, self.gc.gc, offx, offy, width, height, 0, 0) self.move_window_count = self.move_window_count + 1 else: self.clear_window() def SetScale(self, scale, do_center=1): # Set current scale self.begin_transaction() try: Viewport.SetScale(self, scale, do_center=do_center) self.set_gc_transforms() finally: self.end_transaction() def zoom_fit_rect(self, rect, save_viewport=0): if save_viewport: self.save_viewport() Viewport.zoom_fit_rect(self, rect) # # other view related methods # def FitToWindow(self, selected_only=0, save_viewport=1): self.begin_transaction() try: if selected_only: rect = self.document.SelectionBoundingRect() else: rect = self.document.BoundingRect() if rect: self.zoom_fit_rect(rect, save_viewport=save_viewport) finally: self.end_transaction() def FitPageToWindow(self, save_viewport=1): self.begin_transaction() try: w, h = self.document.PageSize() self.zoom_fit_rect(Rect(0, 0, w, h), save_viewport=save_viewport) finally: self.end_transaction() # # Outline Mode # # Although not directly related to the viewport methods (the outline # mode doesn't change the displayed area) the outline mode changes the # way the drawing is displayed and thus issues VIEW. def SetOutlineMode(self, on=1): self.begin_transaction() try: if on: if self.gc.IsOutlineActive(): return else: self.gc.StartOutlineMode() self.hitgc.StartOutlineMode() else: if self.gc.IsOutlineActive(): self.gc.EndOutlineMode() self.hitgc.EndOutlineMode() else: return self.issue_view() self.clear_window() finally: self.end_transaction() def ToggleOutlineMode(self): self.SetOutlineMode(not self.IsOutlineMode()) def IsOutlineMode(self): return self.gc and self.gc.IsOutlineActive() # # Show page outline on/off # def SetPageOutlineMode(self, on=1): self.begin_transaction() try: self.show_page_outline = on self.issue_view() self.clear_window() finally: self.end_transaction() def TogglePageOutlineMode(self): self.SetPageOutlineMode(not self.IsPageOutlineMode()) def IsPageOutlineMode(self): return self.show_page_outline # # # def unsubscribe_doc(self): if self.document is not None: self.document.Unsubscribe(REDRAW, self.redraw_doc) self.document.Unsubscribe(LAYOUT, self.layout_changed) self.document.Unsubscribe(LAYER, self.layer_changed) def subscribe_doc(self): self.document.Subscribe(REDRAW, self.redraw_doc) self.document.Subscribe(LAYOUT, self.layout_changed) self.document.Subscribe(LAYER, self.layer_changed) def SetDocument(self, doc): self.begin_transaction() try: self.unsubscribe_doc() self.document = doc self.subscribe_doc() self.clear_window() self.SetPageSize(self.document.Layout().Size()) self.FitPageToWindow(save_viewport=0) self.issue_document() self.issue_state() self.issue_view() finally: self.end_transaction()