Ejemplo n.º 1
0
class GtkUmlClassWidget(gtk.HBox):

	__gsignals__ = {
			'class-changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,))
	}
	
	# Class appearance properties
	general_border = 5
	area_padding = 10
	multiline_lines = 3
	multiline_separation_distance = 5
	line_width = 1
	background_color = (1,1,1,1)
	border_color = (0,0,0,1)

	def __init__(self, class_name):
		super(GtkUmlClassWidget, self).__gobject_init__()
		
		## We declare and initialize all of the class's instance properties
		# It's important to do this in the constructor and not in the main body of the class. Otherwise those of the which are references will get SHARED AMONG INSTANCES!
		
		# Subwidgets
		self._inner_box = gtk.VBox()
		self._titleLabel = GtkAutoresizableEntry()
		self._attributesArea =  GtkUmlAttributeTable()
		self._methodsArea =  GtkUmlMethodTable()
		self.itemAreas = [self._attributesArea, self._methodsArea]
		self._all_subwidgets = [self._titleLabel, self._attributesArea, self._methodsArea] # Only functional widgets, not padding (inner_box), nor decoration (multilines)
		self._below_title_separator = GtkMultilineSeparatorWidget()
		self._between_attributes_methods_separator = GtkMultilineSeparatorWidget()
		self._between_methods_subclases_separator = None # Should be created only as subclases are added
		self._subclases_area = None
		self._all_separators = [self._below_title_separator, self._between_attributes_methods_separator, self._between_methods_subclases_separator]
		self._non_title_separators = [self._between_attributes_methods_separator, self._between_methods_subclases_separator]

		# Class logic properties
		self.className = class_name
		self.classSuperClass = None
		self.classAttributes = self._attributesArea._items
		self.classMethods = self._methodsArea._items
		self.hasSubclases = False
		
		## End of instance properties 
		
		## Start of actual initialization code
		
		# Inner box for the widget border
		self.pack_start(self._inner_box, padding = self.general_border + 1)
		
		# Title label and its decorations
		self._titleLabel.set_text(self.className)
		self._titleLabel.set_has_frame(False)
		self._inner_box.pack_start(GtkPaddedSingleContainer(self._titleLabel, self.area_padding), False, padding = 0)
		self._below_title_separator.change_properties(self.multiline_lines, self.line_width, self.multiline_separation_distance, self.border_color, self.background_color)
		self._inner_box.pack_start(self._below_title_separator, False, padding = 0)
		
		# Attributes table and its decorations
		self._inner_box.pack_start(GtkPaddedSingleContainer(self._attributesArea, self.area_padding), padding = 0)
		self._between_attributes_methods_separator.change_properties(1, self.line_width, self.multiline_separation_distance, self.border_color, self.background_color)
		self._inner_box.pack_start(self._between_attributes_methods_separator, False, padding = 0)
		
		# Methods table and its decorations
		self._inner_box.pack_start(GtkPaddedSingleContainer(self._methodsArea, self.area_padding), padding = self.area_padding)
		
		# Subclases area and its decorations
		self._between_methods_subclases_separator = GtkMultilineSeparatorWidget()
		self._subclases_area = GtkUmlLayout()
		self.subclases_area_container = GtkUmlSubclassArea(self._subclases_area)
		self._inner_box.pack_start(self._between_methods_subclases_separator, False, padding = 0)
		self._between_methods_subclases_separator.show()
		self._inner_box.pack_start(GtkPaddedSingleContainer(self.subclases_area_container, self.area_padding), padding = self.area_padding)
		
		# Connect some events
		self.connect("expose_event", self._on_expose)
		self.connect("size-allocate", self._on_size_allocate)
		for a in self.itemAreas:
			a.connect('item-added', lambda w, s1, s2, s3, s4, i1 : self.emit('class-changed', a))
			a.connect('item-deleted', lambda w, s1, s2, s3, s4, i1 : self.emit('class-changed', a))	
		
		## End of the initialization code
		
	def _on_expose(self, widget, event):
		context = widget._inner_box.window.cairo_create()
		context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
		context.clip()

		self._draw(context)
 
		return False		
	
	# To ensure the border and contained elements are redrawn when the widget is resized	
	def _on_size_allocate(self, widget, allocation):
		self.queue_draw() # Will send an "expose_event" as soon as reasonable, will perhaps do some other things. 
 
		return False		
	
	def _draw(self, context):
	
		# Cairo preparations
		context.set_line_width(self.line_width)				
		
		# Draw the outer rectangular border
		rect = self.get_allocation()
		make_current_color(context, self.background_color)
		context.rectangle(rect.x, rect.y, rect.width, rect.height)
		context.fill()
		sx = rect.x + self.general_border
		sy = rect.y + self.general_border
		ex = rect.width - 2*self.general_border
		ey = rect.height - 2*self.general_border
		make_current_color(context, self.border_color)
		context.rectangle(sx, sy, ex, ey)
		context.stroke()

	def add_subclass(self, widget, super_class = None, outer_class = None):
		if(self.hasSubclases == False):
			if(outer_class == self.className or outer_class == None):
				self.hasSubclases = True	
				self._subclases_area.connect('class-added', lambda w1, w2, s1, s2 : self.emit('class-changed', self._subclases_area))
				self._subclases_area.add_class(widget, super_class)
				self._subclases_area.show_all()
			else:
				return	
		else:
			if(outer_class == self.className):
				self._subclases_area.add_class(widget, super_class, None)
			else:
				self._subclases_area.add_class(widget, super_class, outer_class)
			return
			
	def add_attribute(self, ac_mod, att_type, name):
		# Create the item dictionary
		attribute = {"name" : name, "ac_mod" : ac_mod, "type" : att_type, "signature" : name, "index" : -1}	
	
		return self._attributesArea._add_item_dict(attribute)	
		
	def add_method(self, ac_mod, method_type, name, params):
		# unique_name is a unique method identifier derived from the method's name and TYPEs (but not names) of its parameters.
		unique_name = name
		
		# The method's signature is its name followed by (, followed by the list of parameters, followed by )
		append_coma = False
		signature = name + "("
	
		# We unpack the parameters to construct the signature and methods unique_name
		for (t, n) in params:
			unique_name += " " + t
			if append_coma:
				signature += ", " + t + " " + n
			else:
				append_coma = True
				signature += t  + " " + n
		
		signature += ")"		
			
		# Create the item dictionary
		method = {"name" : unique_name, "ac_mod" : ac_mod, "type" : method_type, "signature" : signature, "index" : -1}	
	
		return self._methodsArea._add_item_dict(method)	
		
	def get_methods(self):
		return self._methodsArea.get_methods()
	
	def get_attributes(self):
		return self._attributesArea.get_attributes();
	
	def get_inner_clases(self):
		if(self.hasSubclases == False):
			return []
		else:
			return self._subclases_area.get_clases()
	
	def get_schema(self):
		schema = {}
		schema["name"] = self.className
		schema["attributes"] = self.get_attributes()
		schema["methods"] = self.get_methods()
		schema["inner_clases"] = self.get_inner_clases()
		if self.classSuperClass != None:
			schema["super_class"] = self.classSuperClass.className
		else:
			schema["super_class"] = None
		return schema
Ejemplo n.º 2
0
	def __init__(self, class_name):
		super(GtkUmlClassWidget, self).__gobject_init__()
		
		## We declare and initialize all of the class's instance properties
		# It's important to do this in the constructor and not in the main body of the class. Otherwise those of the which are references will get SHARED AMONG INSTANCES!
		
		# Subwidgets
		self._inner_box = gtk.VBox()
		self._titleLabel = GtkAutoresizableEntry()
		self._attributesArea =  GtkUmlAttributeTable()
		self._methodsArea =  GtkUmlMethodTable()
		self.itemAreas = [self._attributesArea, self._methodsArea]
		self._all_subwidgets = [self._titleLabel, self._attributesArea, self._methodsArea] # Only functional widgets, not padding (inner_box), nor decoration (multilines)
		self._below_title_separator = GtkMultilineSeparatorWidget()
		self._between_attributes_methods_separator = GtkMultilineSeparatorWidget()
		self._between_methods_subclases_separator = None # Should be created only as subclases are added
		self._subclases_area = None
		self._all_separators = [self._below_title_separator, self._between_attributes_methods_separator, self._between_methods_subclases_separator]
		self._non_title_separators = [self._between_attributes_methods_separator, self._between_methods_subclases_separator]

		# Class logic properties
		self.className = class_name
		self.classSuperClass = None
		self.classAttributes = self._attributesArea._items
		self.classMethods = self._methodsArea._items
		self.hasSubclases = False
		
		## End of instance properties 
		
		## Start of actual initialization code
		
		# Inner box for the widget border
		self.pack_start(self._inner_box, padding = self.general_border + 1)
		
		# Title label and its decorations
		self._titleLabel.set_text(self.className)
		self._titleLabel.set_has_frame(False)
		self._inner_box.pack_start(GtkPaddedSingleContainer(self._titleLabel, self.area_padding), False, padding = 0)
		self._below_title_separator.change_properties(self.multiline_lines, self.line_width, self.multiline_separation_distance, self.border_color, self.background_color)
		self._inner_box.pack_start(self._below_title_separator, False, padding = 0)
		
		# Attributes table and its decorations
		self._inner_box.pack_start(GtkPaddedSingleContainer(self._attributesArea, self.area_padding), padding = 0)
		self._between_attributes_methods_separator.change_properties(1, self.line_width, self.multiline_separation_distance, self.border_color, self.background_color)
		self._inner_box.pack_start(self._between_attributes_methods_separator, False, padding = 0)
		
		# Methods table and its decorations
		self._inner_box.pack_start(GtkPaddedSingleContainer(self._methodsArea, self.area_padding), padding = self.area_padding)
		
		# Subclases area and its decorations
		self._between_methods_subclases_separator = GtkMultilineSeparatorWidget()
		self._subclases_area = GtkUmlLayout()
		self.subclases_area_container = GtkUmlSubclassArea(self._subclases_area)
		self._inner_box.pack_start(self._between_methods_subclases_separator, False, padding = 0)
		self._between_methods_subclases_separator.show()
		self._inner_box.pack_start(GtkPaddedSingleContainer(self.subclases_area_container, self.area_padding), padding = self.area_padding)
		
		# Connect some events
		self.connect("expose_event", self._on_expose)
		self.connect("size-allocate", self._on_size_allocate)
		for a in self.itemAreas:
			a.connect('item-added', lambda w, s1, s2, s3, s4, i1 : self.emit('class-changed', a))
			a.connect('item-deleted', lambda w, s1, s2, s3, s4, i1 : self.emit('class-changed', a))	
Ejemplo n.º 3
0
	def _add_item_dict(self, item):
		# item_name must be unique
		if item["name"] in self._items:
			return False	
	
		# Add the new item to our item list
		self._items[item["name"]] = item
		item["index"] = len(self._items)
		
		# Resize the internal table
		self._inner_table.resize(len(self._items), 4)
		
		# Add the Access Modifier button for the new item
		self._inner_table.attach(GtkAccessModifierButton(item["ac_mod"]), 0, 1, len(self._items) - 1, len(self._items), xoptions=gtk.FILL, yoptions=gtk.FILL)
		
		# Add the type of the item
		type_entry = GtkAutoresizableEntry()
		type_entry.set_text(item["type"])
		type_entry.set_has_frame(False)
		self._inner_table.attach(type_entry, 1, 2, len(self._items) - 1, len(self._items))
		type_entry.connect("changed", self._entry_changed_cb, item["name"], "type")
		
		# Add the signature of the item
		sig_entry = GtkAutoresizableEntry()
		sig_entry.set_text(item["signature"])
		sig_entry.set_has_frame(False)
		self._inner_table.attach(sig_entry, 2, 3, len(self._items) - 1, len(self._items))
		type_entry.connect("changed", self._entry_changed_cb, item["name"], "signature")
		
		# Add delete button
		del_button = gtk.Button()
		del_button.set_relief(gtk.RELIEF_NONE)
		del_button.add(gtk.image_new_from_stock(gtk.STOCK_STOP, gtk.ICON_SIZE_MENU))
		self._inner_table.attach(del_button, 3, 4, len(self._items) - 1, len(self._items), xoptions=gtk.FILL, yoptions=gtk.FILL)
		del_button.connect("clicked", lambda w: self._delete_item(item["name"]))
		
		self._inner_table.show_all()
		
		# We signal that the item was added
		if (self._internal_rebuild == 0):
			self.emit('item-added', item["name"], item["ac_mod"], item["type"], item["signature"], item["index"])	
		
		return True