Added some logic (idk?)
This commit is contained in:
parent
0dbd5f57e6
commit
342de3e1d1
@ -17,6 +17,9 @@ class UMLClass:
|
|||||||
self._position = pos
|
self._position = pos
|
||||||
self._dimension = dim
|
self._dimension = dim
|
||||||
|
|
||||||
|
self._base_classes = List(type(self))
|
||||||
|
self._sub_classes = List(type(self))
|
||||||
|
|
||||||
self._attributes = ''
|
self._attributes = ''
|
||||||
self._functions = ''
|
self._functions = ''
|
||||||
|
|
||||||
@ -40,6 +43,22 @@ class UMLClass:
|
|||||||
def dimension(self, value: int):
|
def dimension(self, value: int):
|
||||||
self._dimension = value
|
self._dimension = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def base_classes(self) -> List['UMLClass']:
|
||||||
|
return self._base_classes
|
||||||
|
|
||||||
|
@base_classes.setter
|
||||||
|
def base_classes(self, value: List['UMLClass']):
|
||||||
|
self._base_classes = value
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sub_classes(self) -> List['UMLClass']:
|
||||||
|
return self._sub_classes
|
||||||
|
|
||||||
|
@sub_classes.setter
|
||||||
|
def sub_classes(self, value: List['UMLClass']):
|
||||||
|
self._sub_classes = value
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'<{type(self).__name__} {self._cls}: {self._position} {self._dimension}>'
|
return f'<{type(self).__name__} {self._cls}: {self._position} {self._dimension}>'
|
||||||
|
|
||||||
|
@ -26,176 +26,53 @@ class UmletCreatorService(UmletCreatorABC):
|
|||||||
self._moved_classes: list[UMLClass] = []
|
self._moved_classes: list[UMLClass] = []
|
||||||
self._padding = 30
|
self._padding = 30
|
||||||
|
|
||||||
def _sort_by_implementation(self, uml_classes: List[UMLClass], implementations: List[ClassImplementation]):
|
@staticmethod
|
||||||
base_sub_map: dict[UMLClass, list[UMLClass]] = {}
|
def _resolve_implementations(classes: List[UMLClass], implementations: List[ClassImplementation]) -> List[UMLClass]:
|
||||||
|
new_classes = List(UMLClass)
|
||||||
|
sub_classes = List(UMLClass)
|
||||||
for implementation in implementations:
|
for implementation in implementations:
|
||||||
sub_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.subclass).first()
|
implementation: ClassImplementation = implementation
|
||||||
base_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.base).first()
|
base: UMLClass = classes.where(lambda c: c.cls == implementation.base).first()
|
||||||
|
sub: UMLClass = classes.where(lambda c: c.cls == implementation.subclass).first()
|
||||||
|
|
||||||
if base_class not in base_sub_map:
|
base.sub_classes.append(sub)
|
||||||
base_sub_map[base_class] = []
|
sub.base_classes.append(base)
|
||||||
|
if base not in new_classes:
|
||||||
|
new_classes.append(base)
|
||||||
|
sub_classes.append(sub)
|
||||||
|
|
||||||
if sub_class in base_sub_map[base_class]:
|
for cls in classes:
|
||||||
continue
|
if cls not in new_classes and cls not in sub_classes:
|
||||||
base_sub_map[base_class].append(sub_class)
|
new_classes.append(cls)
|
||||||
|
|
||||||
last_base = Position(self._padding, self._padding)
|
return new_classes
|
||||||
highest_y = self._padding
|
|
||||||
|
|
||||||
for base in base_sub_map:
|
def _move_classes(self, classes: List[UMLClass], moved_classes: List[UMLClass], next_pos: Position, highest_y: int):
|
||||||
subclasses = base_sub_map[base]
|
for cls in classes:
|
||||||
|
if cls.cls.name in self._parser_settings.ignore_class_names:
|
||||||
base.position.x = last_base.x
|
|
||||||
base.position.y = last_base.y
|
|
||||||
|
|
||||||
last_sub = Position(base.position.x, base.position.y + base.dimension.height)
|
|
||||||
for sub_class in subclasses:
|
|
||||||
if sub_class not in self._moved_classes:
|
|
||||||
sub_class.position.x = base.position.x
|
|
||||||
sub_class.position.y = base.position.y
|
|
||||||
|
|
||||||
if sub_class.position.x <= last_sub.x:
|
|
||||||
sub_class.position.x = last_sub.x
|
|
||||||
if sub_class.position.y <= last_sub.y:
|
|
||||||
sub_class.position.y = last_sub.y + self._padding * 2
|
|
||||||
|
|
||||||
last_sub.x = sub_class.position.x + sub_class.dimension.width + self._padding
|
|
||||||
if sub_class.position.y + sub_class.dimension.height > highest_y:
|
|
||||||
highest_y = sub_class.position.y + sub_class.dimension.height
|
|
||||||
|
|
||||||
self._moved_classes.append(sub_class)
|
|
||||||
|
|
||||||
last_base.x = last_sub.x
|
|
||||||
if last_base.x <= self._settings.max_pixel_x:
|
|
||||||
last_base.x += self._padding * 2
|
|
||||||
else:
|
|
||||||
last_base.x = self._padding
|
|
||||||
last_base.y = highest_y + self._padding * 2
|
|
||||||
|
|
||||||
self._moved_classes.append(base)
|
|
||||||
|
|
||||||
for cls in uml_classes:
|
|
||||||
if cls in self._moved_classes:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
new_x = last_base.x
|
if cls not in moved_classes:
|
||||||
if new_x <= self._settings.max_pixel_x:
|
Console.write_line(f'MOVE {cls.cls.name} to {next_pos} - {cls.dimension}')
|
||||||
cls.position.x = new_x
|
|
||||||
last_base.x = new_x + cls.dimension.width + self._padding
|
|
||||||
cls.position.y = last_base.y
|
|
||||||
else:
|
|
||||||
cls.position.x = self._padding
|
|
||||||
cls.position.y = highest_y + self._padding * 2
|
|
||||||
last_base = cls.position
|
|
||||||
|
|
||||||
if cls.position.y + cls.dimension.height > highest_y:
|
if next_pos.x > self._settings.max_pixel_x:
|
||||||
highest_y = cls.position.y + cls.dimension.height
|
next_pos.x = self._padding
|
||||||
|
next_pos.y = highest_y + self._padding * 2
|
||||||
|
|
||||||
def _sort_implementations_by_base_order(self, implementations: List[ClassImplementation]) -> OrderedImplementation:
|
cls.position.x = next_pos.x
|
||||||
"""
|
|
||||||
Sort given implementations by order of base classes
|
|
||||||
SubClass(FirstBaseClass, SecondBaseClass, ThirdBaseClass)
|
|
||||||
"""
|
|
||||||
ordered_implementations: OrderedImplementation = {}
|
|
||||||
for implementation in list(implementations):
|
|
||||||
if not implementation.is_first or implementation.base.name in self._parser_settings.ignore_class_names:
|
|
||||||
continue
|
|
||||||
|
|
||||||
ordered_implementations[implementation] = implementations.where(lambda i: i.subclass == implementation.subclass and not i.is_first)
|
|
||||||
|
|
||||||
return ordered_implementations
|
|
||||||
|
|
||||||
def _move_by_implementation(self, implementations: OrderedImplementation, uml_classes: List[UMLClass]) -> List[UMLClass]:
|
|
||||||
base_sub_map: dict[UMLClass, list[UMLClass]] = {}
|
|
||||||
for implementation in implementations:
|
|
||||||
sub_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.subclass).first()
|
|
||||||
base_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.base).first()
|
|
||||||
|
|
||||||
if base_class not in base_sub_map:
|
|
||||||
base_sub_map[base_class] = []
|
|
||||||
|
|
||||||
if sub_class in base_sub_map[base_class]:
|
|
||||||
continue
|
|
||||||
|
|
||||||
base_sub_map[base_class].append(sub_class)
|
|
||||||
for sub_impl in implementations[implementation]:
|
|
||||||
si_sub_class: UMLClass = uml_classes.where(lambda u: u.cls == sub_impl.subclass).first()
|
|
||||||
si_base_class: UMLClass = uml_classes.where(lambda u: u.cls == sub_impl.base).first()
|
|
||||||
|
|
||||||
if si_base_class not in base_sub_map:
|
|
||||||
base_sub_map[si_base_class] = []
|
|
||||||
|
|
||||||
if si_sub_class in base_sub_map[si_base_class]:
|
|
||||||
continue
|
|
||||||
base_sub_map[si_base_class].append(si_sub_class)
|
|
||||||
|
|
||||||
moved_classes = List(UMLClass)
|
|
||||||
next_pos = Position(self._padding, self._padding)
|
|
||||||
highest_y = 0
|
|
||||||
for base in base_sub_map:
|
|
||||||
subclasses = base_sub_map[base]
|
|
||||||
if base in moved_classes:
|
|
||||||
Console.write_line('b_SKIP', base)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if next_pos.x >= self._settings.max_pixel_x:
|
|
||||||
next_pos.x = self._padding
|
|
||||||
next_pos.y = highest_y + self._padding
|
|
||||||
|
|
||||||
base.position.x = next_pos.x
|
|
||||||
base.position.y = next_pos.y
|
|
||||||
if base.position.y + base.dimension.height > highest_y:
|
|
||||||
highest_y = base.position.y + base.dimension.height
|
|
||||||
|
|
||||||
next_pos.y = base.position.y + base.dimension.height + self._padding
|
|
||||||
|
|
||||||
Console.write_line('moved b', base)
|
|
||||||
moved_classes.append(base)
|
|
||||||
|
|
||||||
moved_subclasses = []
|
|
||||||
for sub in subclasses:
|
|
||||||
if sub in moved_classes:
|
|
||||||
Console.write_line('s_SKIP', sub)
|
|
||||||
continue
|
|
||||||
|
|
||||||
sub.position.x = next_pos.x
|
|
||||||
sub.position.y = next_pos.y
|
|
||||||
next_pos.x += sub.dimension.width + self._padding
|
|
||||||
if sub.position.y + sub.dimension.height > highest_y:
|
|
||||||
highest_y = sub.position.y + sub.dimension.height
|
|
||||||
|
|
||||||
Console.write_line('moved s', sub)
|
|
||||||
moved_classes.append(sub)
|
|
||||||
moved_subclasses.append(sub)
|
|
||||||
|
|
||||||
delta_x = self._padding
|
|
||||||
if len(moved_subclasses) == 0:
|
|
||||||
delta_x += base.dimension.width
|
|
||||||
next_pos.x += delta_x
|
|
||||||
next_pos.y = base.position.y
|
|
||||||
|
|
||||||
for cls in uml_classes:
|
|
||||||
if cls in moved_classes:
|
|
||||||
continue
|
|
||||||
|
|
||||||
new_x = next_pos.x
|
|
||||||
if new_x <= self._settings.max_pixel_x:
|
|
||||||
cls.position.x = new_x
|
|
||||||
next_pos.x = new_x + cls.dimension.width + self._padding
|
|
||||||
cls.position.y = next_pos.y
|
cls.position.y = next_pos.y
|
||||||
else:
|
|
||||||
cls.position.x = self._padding
|
next_pos.x = cls.position.x + cls.dimension.width + self._padding
|
||||||
cls.position.y = highest_y + self._padding * 2
|
|
||||||
|
if cls.position.y + cls.dimension.height > highest_y:
|
||||||
|
highest_y = cls.position.y + cls.dimension.height
|
||||||
|
|
||||||
|
moved_classes.append(cls)
|
||||||
|
|
||||||
|
if cls.sub_classes.count() > 0:
|
||||||
next_pos.x = cls.position.x
|
next_pos.x = cls.position.x
|
||||||
next_pos.y = cls.position.y
|
next_pos.y = cls.position.y + cls.dimension.height + self._padding
|
||||||
|
self._move_classes(cls.sub_classes, moved_classes, next_pos, highest_y)
|
||||||
if cls.position.y + cls.dimension.height > highest_y:
|
|
||||||
highest_y = cls.position.y + cls.dimension.height
|
|
||||||
|
|
||||||
moved_classes.append(cls)
|
|
||||||
# Console.write_line('moved c', cls)
|
|
||||||
|
|
||||||
return moved_classes
|
|
||||||
|
|
||||||
def generate_xml(self, classes: List[PythonClass], implementations: List[ClassImplementation]) -> str:
|
def generate_xml(self, classes: List[PythonClass], implementations: List[ClassImplementation]) -> str:
|
||||||
uml_classes = List(UMLClass)
|
uml_classes = List(UMLClass)
|
||||||
@ -208,21 +85,32 @@ class UmletCreatorService(UmletCreatorABC):
|
|||||||
uml_cls.create_xml_body()
|
uml_cls.create_xml_body()
|
||||||
uml_classes.append(uml_cls)
|
uml_classes.append(uml_cls)
|
||||||
|
|
||||||
# self._sort_by_implementation(uml_classes, implementations)
|
sorted_classes = self._resolve_implementations(uml_classes, implementations)
|
||||||
oi = self._sort_implementations_by_base_order(implementations)
|
moved_classes = List(UMLClass)
|
||||||
for uml_cls in self._move_by_implementation(oi, uml_classes):
|
self._move_classes(sorted_classes, moved_classes, Position(self._padding, self._padding), 0)
|
||||||
|
|
||||||
|
for uml_cls in moved_classes:
|
||||||
# save class xml
|
# save class xml
|
||||||
if uml_cls.cls.name in self._parser_settings.ignore_class_names:
|
if uml_cls.cls.name in self._parser_settings.ignore_class_names:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
xml_classes += uml_cls.as_xml()
|
xml_classes += uml_cls.as_xml()
|
||||||
|
|
||||||
for implementation in implementations:
|
# self._sort_by_implementation(uml_classes, implementations)
|
||||||
sub_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.subclass).first()
|
# oi = self._sort_implementations_by_base_order(implementations)
|
||||||
base_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.base).first()
|
# for uml_cls in self._move_by_implementation(oi, uml_classes):
|
||||||
if base_class.cls.name in self._parser_settings.ignore_class_names:
|
# save class xml
|
||||||
continue
|
# if uml_cls.cls.name in self._parser_settings.ignore_class_names:
|
||||||
xml_relations += sub_class.implementation_as_xml(base_class)
|
# continue
|
||||||
|
#
|
||||||
|
# xml_classes += uml_cls.as_xml()
|
||||||
|
|
||||||
|
# for implementation in implementations:
|
||||||
|
# sub_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.subclass).first()
|
||||||
|
# base_class: UMLClass = uml_classes.where(lambda u: u.cls == implementation.base).first()
|
||||||
|
# if base_class.cls.name in self._parser_settings.ignore_class_names:
|
||||||
|
# continue
|
||||||
|
# xml_relations += sub_class.implementation_as_xml(base_class)
|
||||||
|
|
||||||
return f"""\
|
return f"""\
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
Loading…
Reference in New Issue
Block a user