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