def __init__(self, is_host=False, is_cohost=False): self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._window, self._text_widget = self.create_window(is_host) self._instruction_queue = queue.SimpleQueue() self._text_callback = None self._change_thread = threading.Thread( target=self.apply_remote_changes, daemon=True) self._cursor_blink_thread = threading.Thread(target=self._cursor_blink, daemon=True) self.socket_lock = threading.Lock() self._remote_users = dict() self.is_host = is_host self.is_cohost = is_cohost # For hosts self._text_callback = self._text_widget.bind("<KeyPress>", self.broadcast_keypress, True) self._cursor_callback = self.bind_curosr_callbacks() self.host_thread = threading.Thread(target=self.accept_connections, daemon=True) self._max_connections = 5 self.connections = dict() # For clients self.receiver_thread = threading.Thread(target=self.receive, args=(self.socket_lock, ), daemon=True) self.my_id = get_new_id() self.initialized = False
def accept_connections(self): self._sock.bind(SOCK_ADDR) self._sock.listen(self._max_connections) while True: client, add = self._sock.accept() print("New connection at:", add) handler_lock = threading.Lock() handler_thread = threading.Thread(target=self.receive, args=(add, )) author_id = get_new_id() new_user = RemoteUser(author_id, "", random.sample(USER_COLORS, 1)) self.connections[add] = { "author_id": author_id, "handler_thread": handler_thread, "lock": handler_lock, "socket": client } self.send_current_state(author_id, add) self._remote_users[str(author_id)] = new_user handler_thread.start() print("Users:\n", self._remote_users)
def create_linear_gradient(self, id = None, start = None, stop = None, xlink = None): """ Create a new L{linear gradient<svg.elements.LinearGradient>} within this container. Note that you need to define either start/end or an xlink for the gradient. You can also just create a blank gradient and add them later, but don't specify both. @type id: string @param id: A unique identifier for this L{gradient<svg.elements.LinearGradient>}. @type start: list @param start: The [x, y] coordinates of the start of the gradient. @type stop: list @param stop: The [x, y] coordinate of the stop of the gradient. @type xlink: string @param xlink: A link to a defined gradient's identifier. """ if not id: id = get_new_id("linearGradient") attributes = { "id" : id } if start: if not stop: log.warning("Please specify stop coordinates for the gradient!") attributes["x1"] = start[0] attributes["y1"] = start[1] if stop: if not start: log.warning("Please specify start coordinates for the gradient!") attributes["x2"] = stop[0] attributes["y2"] = stop[1] if xlink: if start or stop: log.warning("You may not want to specify a start/stop and xlink!") attributes["xlink"] = xlink return self.create_child("linearGradient", self.__dict__["container_map"]["linear_gradient"], attributes)
def create_pattern(self, id = None): """ Create a new pattern in this container. @type id: string @param id: A unique identifier for the L{pattern<svg.elements.Pattern>}. """ if not id: id = get_new_id("pattern") attributes = { "id" : id } return self.add_child_tag("pattern", self.__dict__["container_map"]["pattern"], attributes)
def create_tref(self, id = None, xlink = None, text = None, pos = [0, 0], deviation = None, rotation = None, length = None, font_weight = None, fill = None, stroke = None): """ Create a tref object within this container. @type id: string or number @param id: A unique identifier for this L{Tref<svg.elements.Tref>} element. @type text: string @param text: The text that this tref holds. @type pos: list @param pos: [x, y] cooridnates of this L{Tref<svg.elements.Tref>} element. @type deviation: list @param deviation: [x, y] deviation amount. @type rotation: number @param rotation: The number of degrees the text is rotated. @type length: number @param length: The length of the text. @type font_weight: number @param font_weight: The boldness of the text's font. @type fill: #RRGGBBAA form color @param fill: The fill value of this text. @type stroke: #RRGGBBAA form color @param stroke: The stroke value of the text. """ if id == None or id == "": id = get_new_id("tref") attributes = {"id" : tref_id, "x" : pos[0], "y" : pos[1]} if text: attributes["text"] = text if deviation: attributes["dx"] = deviation[0] attributes["dy"] = deviation[1] if rotation: attributes["rotation"] = rotation if length: attributes["length"] = length if font_weight: attributes["font-weight"] = font_weight tref = self.add_child_tag("tref", self.__dict__["container_map"]["tref"], attributes) # do this because the fill/stroke are special attributes! if fill: tref.fill = fill if stroke: tref.stroke = stroke return tref
def create_stop(self, id = None, color = "#000000ff", offset = "1"): """ Append a gradient stop as a child. @type id: string @param id: The unique ID of the stop. One will be generated if none is passed. @type color: string @param color: The color value of the stop. It can be either a named color or a color in #RRGGBBAA form. @type offset: float @param offset: The offset of the gradient, which should be a value between 0.0 and 1.0. @rtype: L{Stop<svg.elements.Stop>} @return: The newly created L{Stop<svg.elements.Stop>} element. """ if id == None: id = get_new_id() stop = self.create_child("stop", self.__dict__["container_map"]["stop"], { "id" : str(id), "color" : color, "offset" : offset }) return stop
def create_shape(self, tag = None, shape_id = None, attributes = {}, fill = None, stroke = None, stroke_width = None, shape_type = None): """ Add a new shape to this container. Provides common functionality for all shapes that can be added. @type tag: string @param tag: The name of the shape's XML tag @type shape_id: string @param shape_id: The unique identifier of the shape @type attributes: dict @param attributes: A dictionary of attribute:value pairs for attributes to be set in the new shape. @type fill: string @param fill: The fill value of this shape @type stroke: string @param stroke: The stroke value of this shape @type stroke_width: string @param stroke_width: The width of the stroke value @type shape_type: L{XMLElement<svg.svgelement.XMLElement>}-based class @param shape_type: The class type of the shape to be created @rtype: shape_type @return: The newly added shape. """ # if no shape id is specified get a numerical one if shape_id == None: shape_id = get_new_id(tag) attributes["id"] = str(shape_id) if stroke_width != None: attributes["stroke-width"] = stroke_width shape = self.create_child(tag, shape_type, attributes) if fill: shape.fill = fill if stroke: shape.stroke = stroke return shape