Rectangles in incons

This commit is contained in:
2026-07-27 14:03:06 +02:00
parent 09a9e3f12f
commit 035cbdf53f
8 changed files with 403 additions and 47 deletions

5
.vscode/launch.json vendored
View File

@@ -14,7 +14,10 @@
"env": {
"QT_QPA_PLATFORMTHEME": "qt6ct",
"QT_QPA_PLATFORM": "xcb"
}
},
"args": [
"-f", "${workspaceFolder}/untitled.bedit.json"
]
}
]
}

View File

@@ -1,6 +1,7 @@
from __future__ import annotations
import sys
import argparse
from PySide6.QtWidgets import QApplication
@@ -15,8 +16,22 @@ from bedit_gui.documents import Document
from bedit_gui.services.application_settings import ApplicationSettings
from bedit_gui.views.main_window import MainWindow
def parse_arguments():
parser = argparse.ArgumentParser(exit_on_error=False)
parser.add_argument(
"-f", "--file", type=str, help="Path to a file to open", default=None, required=False
)
return parser.parse_args()
def main() -> int:
try:
args = parse_arguments()
except argparse.ArgumentError as e:
print(e.message)
return 1
app = QApplication(sys.argv)
app.setOrganizationName("BEdit")
@@ -36,7 +51,11 @@ def main() -> int:
window_state_controller = WindowStateController(app, window)
window_state_controller.restore()
document.new()
if args.file:
document.open(args.file)
else:
document.new()
window.showMaximized()
return app.exec()

View File

@@ -45,13 +45,13 @@ class Rectangle(Shape):
line_type: LineType = LineType.SOLID
line_thickness: float = 1.0
corner_radius: float = 0.0
line_color: str = "#000000"
fill_color: str = "#ffffff"
line_color: str = "#000000ff"
fill_color: str = "#ffffff00"
@classmethod
def from_data(cls, data: Mapping[str, Any]) -> Rectangle:
pos = data.get("pos", [0, 0])
return cls(layer=int(data.get("layer", 0)), pos=(int(pos[0]), int(pos[1])), width=float(data.get("width", 100.0)), height=float(data.get("height", 100.0)), line_type=LineType(data.get("line_type", "solid")), line_thickness=float(data.get("line_thickness", 1.0)), corner_radius=float(data.get("corner_radius", 0.0)), line_color=str(data.get("line_color", "#000000")), fill_color=str(data.get("fill_color", "#ffffff")))
return cls(layer=int(data.get("layer", 0)), pos=(int(pos[0]), int(pos[1])), width=float(data.get("width", 100.0)), height=float(data.get("height", 100.0)), line_type=LineType(data.get("line_type", "solid")), line_thickness=float(data.get("line_thickness", 1.0)), corner_radius=float(data.get("corner_radius", 0.0)), line_color=str(data.get("line_color", "#000000ff")), fill_color=str(data.get("fill_color", "#ffffff00")))
def to_data(self) -> dict[str, Any]:
return {**super().to_data(), "width": self.width, "height": self.height, "line_type": self.line_type.value, "line_thickness": self.line_thickness, "corner_radius": self.corner_radius, "line_color": self.line_color, "fill_color": self.fill_color}

View File

@@ -0,0 +1,42 @@
from __future__ import annotations
from PySide6.QtGui import QColor
from PySide6.QtWidgets import QColorDialog, QPushButton, QWidget
class ColorButton(QPushButton):
def __init__(self, color: str, parent: QWidget | None = None) -> None:
super().__init__(parent)
self.setObjectName("colorButton")
self._color = self._from_rgba(color)
self.clicked.connect(self._select_color)
self._update_display()
def color(self) -> str:
return f"#{self._color.red():02x}{self._color.green():02x}{self._color.blue():02x}{self._color.alpha():02x}"
def set_color(self, color: str) -> None:
self._color = self._from_rgba(color)
self._update_display()
def _select_color(self) -> None:
parent = self.window()
dialog = QColorDialog(self._color, parent if parent is not self else None)
dialog.setOption(QColorDialog.ColorDialogOption.ShowAlphaChannel)
if dialog.exec() == QColorDialog.DialogCode.Accepted:
self._color = dialog.selectedColor()
self._update_display()
def _update_display(self) -> None:
self.setText(self.color())
foreground = "#000000" if self._color.lightness() > 127 or self._color.alpha() < 128 else "#ffffff"
self.setStyleSheet(f"QPushButton#colorButton {{ background-color: rgba({self._color.red()}, {self._color.green()}, {self._color.blue()}, {self._color.alpha()}); color: {foreground}; }}")
@staticmethod
def _from_rgba(value: str) -> QColor:
color = value.removeprefix("#")
if len(color) == 6:
color += "ff"
if len(color) == 8:
return QColor(int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16), int(color[6:8], 16))
return QColor(value)

View File

@@ -3,12 +3,13 @@ from __future__ import annotations
from copy import deepcopy
from PySide6.QtCore import QEvent, QObject, Qt, Signal
from PySide6.QtGui import QKeySequence, QPainter, QShortcut, QUndoCommand, QUndoStack, QWheelEvent
from PySide6.QtWidgets import QGraphicsView, QMainWindow, QWidget
from PySide6.QtGui import QKeySequence, QPainter, QShortcut, QUndoCommand, QUndoStack, QWheelEvent, QShowEvent
from PySide6.QtWidgets import QDialog, QGraphicsView, QMainWindow, QWidget
from bedit_gui.models import Icon, Shape, ShapeID
from bedit_gui.ui.generated.ui_icon_editor_window import Ui_iconEditor
from bedit_gui.views.icon_graphics_scene import IconGraphicsScene, RectangleCreationTool
from bedit_gui.views.shape_options_dialog import ShapeOptionsDialog
class ChangeIconDraftCommand(QUndoCommand):
@@ -39,6 +40,35 @@ class AddShapeCommand(QUndoCommand):
self.editor._remove_shape(self.shape_id)
class ChangeShapeCommand(QUndoCommand):
def __init__(self, editor: IconEditorWindow, shape_id: ShapeID, old_shape: Shape, new_shape: Shape) -> None:
super().__init__(f"Change {new_shape.type}")
self.editor = editor
self.shape_id = shape_id
self.old_shape = deepcopy(old_shape)
self.new_shape = deepcopy(new_shape)
def redo(self) -> None:
self.editor._change_shape(self.shape_id, self.new_shape)
def undo(self) -> None:
self.editor._change_shape(self.shape_id, self.old_shape)
class DeleteShapesCommand(QUndoCommand):
def __init__(self, editor: IconEditorWindow, shapes: dict[ShapeID, Shape]) -> None:
text = "Delete shape" if len(shapes) == 1 else "Delete shapes"
super().__init__(text)
self.editor = editor
self.shapes = deepcopy(shapes)
def redo(self) -> None:
self.editor._remove_shapes(self.shapes)
def undo(self) -> None:
self.editor._restore_shapes(self.shapes)
class IconEditorWindow(QMainWindow):
"""Independent icon editing session with its own undo stack."""
@@ -60,6 +90,8 @@ class IconEditorWindow(QMainWindow):
self.scene = IconGraphicsScene(self)
self.scene.set_icon(self._icon)
self.scene.shape_created.connect(self._shape_created)
self.scene.shape_changed.connect(self._shape_changed)
self.scene.shape_options_requested.connect(self._show_shape_options)
self.scene.tool_active_changed.connect(self._tool_active_changed)
self.ui.graphicsView.setScene(self.scene)
self.ui.graphicsView.setRenderHint(QPainter.RenderHint.Antialiasing)
@@ -69,6 +101,8 @@ class IconEditorWindow(QMainWindow):
self.ui.actionAdd_Rectangle.triggered.connect(self._start_rectangle_tool)
self.cancel_tool_shortcut = QShortcut(QKeySequence(Qt.Key.Key_Escape), self)
self.cancel_tool_shortcut.activated.connect(self.scene.cancel_creation_tool)
self.delete_shortcut = QShortcut(QKeySequence(Qt.Key.Key_Delete), self)
self.delete_shortcut.activated.connect(self._delete_selected_shapes)
self.zoom_in_shortcut = QShortcut(QKeySequence("Ctrl++"), self)
self.zoom_in_alt_shortcut = QShortcut(QKeySequence("Ctrl+="), self)
self.zoom_out_shortcut = QShortcut(QKeySequence("Ctrl+-"), self)
@@ -90,6 +124,10 @@ class IconEditorWindow(QMainWindow):
self.ui.actionUndo.setEnabled(False)
self.ui.actionRedo.setEnabled(False)
def showEvent(self, event: QShowEvent) -> None:
super().showEvent(event)
self.fit_scene()
def icon(self) -> Icon:
return deepcopy(self._icon)
@@ -107,7 +145,10 @@ class IconEditorWindow(QMainWindow):
self._zoom(1 / self.zoom_step)
def reset_zoom(self) -> None:
self.ui.graphicsView.resetTransform()
self.fit_scene()
def fit_scene(self) -> None:
self.ui.graphicsView.fitInView(self.scene.sceneRect(), Qt.AspectRatioMode.KeepAspectRatio)
def eventFilter(self, watched: QObject, event: QEvent) -> bool:
if watched is self.ui.graphicsView.viewport() and isinstance(event, QWheelEvent):
@@ -140,9 +181,44 @@ class IconEditorWindow(QMainWindow):
self.scene.set_icon(self._icon)
self.icon_changed.emit(self.icon())
def _remove_shapes(self, shapes: dict[ShapeID, Shape]) -> None:
for shape_id in shapes:
self._icon.shapes.pop(shape_id, None)
self.scene.set_icon(self._icon)
self.icon_changed.emit(self.icon())
def _restore_shapes(self, shapes: dict[ShapeID, Shape]) -> None:
self._icon.shapes.update(deepcopy(shapes))
self.scene.set_icon(self._icon)
self.icon_changed.emit(self.icon())
def _change_shape(self, shape_id: ShapeID, shape: Shape) -> None:
self._icon.shapes[shape_id] = deepcopy(shape)
self.scene.set_icon(self._icon)
self.icon_changed.emit(self.icon())
def _shape_created(self, shape: Shape) -> None:
self.undo_stack.push(AddShapeCommand(self, ShapeID(), shape))
def _shape_changed(self, shape_id: ShapeID, old_shape: Shape, new_shape: Shape) -> None:
self.undo_stack.push(ChangeShapeCommand(self, shape_id, old_shape, new_shape))
def _delete_selected_shapes(self) -> None:
shape_ids = self.scene.selected_shape_ids()
shapes = {shape_id: self._icon.shapes[shape_id] for shape_id in shape_ids}
if shapes:
self.undo_stack.push(DeleteShapesCommand(self, shapes))
def _show_shape_options(self, shape_id: ShapeID) -> None:
old_shape = self._icon.shapes.get(shape_id)
if old_shape is None:
return
dialog = ShapeOptionsDialog(old_shape, self.scene.sceneRect(), self)
if dialog.exec() == QDialog.DialogCode.Accepted:
new_shape = dialog.shape()
if new_shape != old_shape:
self.undo_stack.push(ChangeShapeCommand(self, shape_id, old_shape, new_shape))
def _start_rectangle_tool(self) -> None:
layer = max((shape.layer for shape in self._icon.shapes.values()), default=-1) + 1
self.scene.set_creation_tool(RectangleCreationTool(self.scene, layer))

View File

@@ -1,12 +1,14 @@
from __future__ import annotations
import math
from copy import deepcopy
from typing import Protocol
from PySide6.QtCore import QObject, QPointF, QRectF, Qt, Signal
from PySide6.QtGui import QBrush, QColor, QPainterPath, QPen
from PySide6.QtWidgets import QGraphicsPathItem, QGraphicsRectItem, QGraphicsScene, QGraphicsSceneMouseEvent
from PySide6.QtGui import QBrush, QColor, QPainter, QPainterPath, QPen
from PySide6.QtWidgets import QGraphicsItem, QGraphicsPathItem, QGraphicsRectItem, QGraphicsScene, QGraphicsSceneContextMenuEvent, QGraphicsSceneMouseEvent, QMenu, QStyleOptionGraphicsItem, QWidget
from bedit_gui.models import Icon, LineType, Rectangle, Shape
from bedit_gui.models import Icon, LineType, Rectangle, Shape, ShapeID
class ShapeCreationTool(Protocol):
@@ -24,16 +26,19 @@ class RectangleCreationTool:
self.preview: QGraphicsRectItem | None = None
def begin(self, position: QPointF) -> None:
position = self._bounded(position)
self.start = position
self.preview = self.scene.addRect(QRectF(position, position), QPen(Qt.PenStyle.DashLine))
def update(self, position: QPointF) -> None:
if self.preview is not None and self.start is not None:
position = self._bounded(position)
self.preview.setRect(QRectF(self.start, position).normalized())
def finish(self, position: QPointF) -> Rectangle | None:
if self.start is None:
return None
position = self._bounded(position)
rect = QRectF(self.start, position).normalized()
self.cancel()
if rect.width() < 1 or rect.height() < 1:
@@ -46,21 +51,143 @@ class RectangleCreationTool:
self.preview = None
self.start = None
def _bounded(self, position: QPointF) -> QPointF:
rect = self.scene.sceneRect()
x = max(rect.left(), min(rect.right(), round(position.x())))
y = max(rect.top(), min(rect.bottom(), round(position.y())))
return QPointF(x, y)
class ShapeGraphicsItem(QGraphicsPathItem):
handle_size = 6.0
def __init__(self, shape_id: ShapeID, shape: Shape, scene: IconGraphicsScene) -> None:
super().__init__()
self.shape_id = shape_id
self.shape_model = deepcopy(shape)
self.icon_scene = scene
self._original_shape: Shape | None = None
self._resizing = False
self.setFlags(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable | QGraphicsItem.GraphicsItemFlag.ItemIsMovable | QGraphicsItem.GraphicsItemFlag.ItemSendsGeometryChanges)
def resize_handle_rect(self) -> QRectF:
size = self.handle_size
corner = self.path().boundingRect().bottomRight()
return QRectF(corner.x() - size / 2, corner.y() - size / 2, size, size)
def boundingRect(self) -> QRectF:
margin = self.handle_size / 2
return super().boundingRect().adjusted(-margin, -margin, margin, margin)
def mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None:
self._original_shape = self.current_shape()
self._resizing = self.isSelected() and self.resize_handle_rect().contains(event.pos())
if self._resizing:
event.accept()
return
super().mousePressEvent(event)
def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent) -> None:
if self._resizing:
self.resize_to(event.scenePos())
event.accept()
return
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent) -> None:
if self._resizing:
self.resize_to(event.scenePos())
self._resizing = False
event.accept()
else:
super().mouseReleaseEvent(event)
current = self.current_shape()
if self._original_shape is not None and current != self._original_shape:
self.icon_scene.shape_changed.emit(self.shape_id, self._original_shape, current)
self._original_shape = None
def contextMenuEvent(self, event: QGraphicsSceneContextMenuEvent) -> None:
if not self.isSelected():
self.icon_scene.clearSelection()
self.setSelected(True)
menu = QMenu()
options = menu.addAction("Shape Options")
if menu.exec(event.screenPos()) is options:
self.icon_scene.shape_options_requested.emit(self.shape_id)
event.accept()
def itemChange(self, change: QGraphicsItem.GraphicsItemChange, value: object) -> object:
if change is QGraphicsItem.GraphicsItemChange.ItemPositionChange and self.scene() is not None:
position = value
if isinstance(position, QPointF):
bounds = self.icon_scene.sceneRect()
size = self.path().boundingRect()
x = max(bounds.left(), min(bounds.right() - size.width(), round(position.x())))
y = max(bounds.top(), min(bounds.bottom() - size.height(), round(position.y())))
return QPointF(x, y)
return super().itemChange(change, value)
def paint(self, painter: QPainter, option: QStyleOptionGraphicsItem, widget: QWidget | None = None) -> None:
super().paint(painter, option, widget)
if self.isSelected():
painter.setPen(QPen(QColor("#ffffff")))
painter.setBrush(QBrush(QColor("#2675bf")))
painter.drawRect(self.resize_handle_rect())
def current_shape(self) -> Shape:
raise NotImplementedError
def resize_to(self, position: QPointF) -> None:
raise NotImplementedError
class RectangleGraphicsItem(ShapeGraphicsItem):
def __init__(self, shape_id: ShapeID, shape: Rectangle, scene: IconGraphicsScene) -> None:
super().__init__(shape_id, shape, scene)
self.rectangle = deepcopy(shape)
self.setPos(shape.pos[0], shape.pos[1])
self._set_size(shape.width, shape.height)
self.setPen(scene._pen(shape))
self.setBrush(QBrush(scene._color(shape.fill_color)))
self.setZValue(shape.layer)
def current_shape(self) -> Rectangle:
shape = deepcopy(self.rectangle)
shape.pos = (round(self.pos().x()), round(self.pos().y()))
rect = self.path().boundingRect()
shape.width = rect.width()
shape.height = rect.height()
return shape
def resize_to(self, position: QPointF) -> None:
bounds = self.icon_scene.sceneRect()
width = max(1.0, min(bounds.right(), round(position.x())) - self.pos().x())
height = max(1.0, min(bounds.bottom(), round(position.y())) - self.pos().y())
self._set_size(width, height)
def _set_size(self, width: float, height: float) -> None:
self.prepareGeometryChange()
path = QPainterPath()
path.addRoundedRect(QRectF(0, 0, width, height), self.rectangle.corner_radius, self.rectangle.corner_radius)
self.setPath(path)
class IconGraphicsScene(QGraphicsScene):
shape_created = Signal(object)
shape_changed = Signal(object, object, object)
shape_options_requested = Signal(object)
tool_active_changed = Signal(bool)
def __init__(self, parent: QObject | None = None) -> None:
super().__init__(parent)
self._tool: ShapeCreationTool | None = None
self.setSceneRect(-100, -100, 200, 200)
self.setSceneRect(-64, -64, 128, 128)
def set_icon(self, icon: Icon) -> None:
self.cancel_creation_tool()
self.clear()
for shape in sorted(icon.shapes.values(), key=lambda item: item.layer):
self._add_shape_item(shape)
for shape_id, shape in sorted(icon.shapes.items(), key=lambda item: item[1].layer):
self._add_shape_item(shape_id, shape)
def set_creation_tool(self, tool: ShapeCreationTool) -> None:
self.cancel_creation_tool()
@@ -77,6 +204,29 @@ class IconGraphicsScene(QGraphicsScene):
def has_creation_tool(self) -> bool:
return self._tool is not None
def selected_shape_ids(self) -> list[ShapeID]:
return [item.shape_id for item in self.selectedItems() if isinstance(item, ShapeGraphicsItem)]
def drawBackground(self, painter: QPainter, rect: QRectF) -> None:
super().drawBackground(painter, rect)
rect = rect.intersected(self.sceneRect())
if rect.isEmpty():
return
pen = QPen(QColor("#d0d0d0"))
pen.setCosmetic(True)
painter.setPen(pen)
first_x = math.floor(rect.left() / 8) * 8
last_x = math.ceil(rect.right() / 8) * 8
first_y = math.floor(rect.top() / 8) * 8
last_y = math.ceil(rect.bottom() / 8) * 8
for x in range(first_x, last_x + 1, 8):
painter.drawLine(QPointF(x, rect.top()), QPointF(x, rect.bottom()))
for y in range(first_y, last_y + 1, 8):
painter.drawLine(QPointF(rect.left(), y), QPointF(rect.right(), y))
def mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None:
if self._tool is not None and event.button() == Qt.MouseButton.LeftButton:
self._tool.begin(event.scenePos())
@@ -103,21 +253,21 @@ class IconGraphicsScene(QGraphicsScene):
return
super().mouseReleaseEvent(event)
def _add_shape_item(self, shape: Shape) -> None:
def _add_shape_item(self, shape_id: ShapeID, shape: Shape) -> None:
if not isinstance(shape, Rectangle):
return
rect = QRectF(shape.pos[0], shape.pos[1], shape.width, shape.height)
path = QPainterPath()
path.addRoundedRect(rect, shape.corner_radius, shape.corner_radius)
item = QGraphicsPathItem(path)
item.setPen(self._pen(shape))
item.setBrush(QBrush(QColor(shape.fill_color)))
item.setZValue(shape.layer)
self.addItem(item)
self.addItem(RectangleGraphicsItem(shape_id, shape, self))
@staticmethod
def _pen(shape: Rectangle) -> QPen:
styles = {LineType.SOLID: Qt.PenStyle.SolidLine, LineType.DASHED: Qt.PenStyle.DashLine, LineType.DOTTED: Qt.PenStyle.DotLine, LineType.DASH_DOT: Qt.PenStyle.DashDotLine}
if shape.line_type is LineType.NONE:
return QPen(Qt.PenStyle.NoPen)
return QPen(QColor(shape.line_color), shape.line_thickness, styles[shape.line_type])
return QPen(IconGraphicsScene._color(shape.line_color), shape.line_thickness, styles[shape.line_type])
@staticmethod
def _color(value: str) -> QColor:
color = value.removeprefix("#")
if len(color) == 8:
return QColor(int(color[0:2], 16), int(color[2:4], 16), int(color[4:6], 16), int(color[6:8], 16))
return QColor(value)

View File

@@ -0,0 +1,81 @@
from __future__ import annotations
from copy import deepcopy
from PySide6.QtCore import QRectF
from PySide6.QtWidgets import QComboBox, QDialog, QDialogButtonBox, QDoubleSpinBox, QFormLayout, QLabel, QSpinBox, QVBoxLayout, QWidget
from bedit_gui.models import LineType, Rectangle, Shape
from bedit_gui.views.color_button import ColorButton
class ShapeOptionsDialog(QDialog):
def __init__(self, shape: Shape, scene_rect: QRectF, parent: QWidget | None = None) -> None:
super().__init__(parent)
self._shape = deepcopy(shape)
self._scene_rect = scene_rect
self.setWindowTitle("Shape Options")
self.form = QFormLayout()
self.type_label = QLabel(shape.type or "")
self.layer = QSpinBox()
self.layer.setRange(-1000000, 1000000)
self.layer.setValue(shape.layer)
self.x = QSpinBox()
self.x.setRange(round(scene_rect.left()), round(scene_rect.right() - 1))
self.x.setValue(shape.pos[0])
self.y = QSpinBox()
self.y.setRange(round(scene_rect.top()), round(scene_rect.bottom() - 1))
self.y.setValue(shape.pos[1])
self.form.addRow("Type", self.type_label)
self.form.addRow("Layer", self.layer)
self.form.addRow("X", self.x)
self.form.addRow("Y", self.y)
if isinstance(shape, Rectangle):
self._add_rectangle_fields(shape)
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
buttons.accepted.connect(self.accept)
buttons.rejected.connect(self.reject)
layout = QVBoxLayout(self)
layout.addLayout(self.form)
layout.addWidget(buttons)
def shape(self) -> Shape:
if not isinstance(self._shape, Rectangle):
shape = deepcopy(self._shape)
shape.layer = self.layer.value()
shape.pos = (self.x.value(), self.y.value())
return shape
width = min(self.width.value(), self._scene_rect.right() - self.x.value())
height = min(self.height.value(), self._scene_rect.bottom() - self.y.value())
return Rectangle(layer=self.layer.value(), pos=(self.x.value(), self.y.value()), width=width, height=height, line_type=self.line_type.currentData(), line_thickness=self.line_thickness.value(), corner_radius=self.corner_radius.value(), line_color=self.line_color.color(), fill_color=self.fill_color.color())
def _add_rectangle_fields(self, shape: Rectangle) -> None:
self.width = QSpinBox()
self.width.setRange(1, round(self._scene_rect.width()))
self.width.setValue(round(shape.width))
self.height = QSpinBox()
self.height.setRange(1, round(self._scene_rect.height()))
self.height.setValue(round(shape.height))
self.line_type = QComboBox()
for line_type in LineType:
self.line_type.addItem(line_type.value.replace("_", " ").title(), line_type)
self.line_type.setCurrentIndex(self.line_type.findData(shape.line_type))
self.line_thickness = QDoubleSpinBox()
self.line_thickness.setRange(0, 1000)
self.line_thickness.setValue(shape.line_thickness)
self.corner_radius = QDoubleSpinBox()
self.corner_radius.setRange(0, max(self._scene_rect.width(), self._scene_rect.height()))
self.corner_radius.setValue(shape.corner_radius)
self.line_color = ColorButton(shape.line_color)
self.fill_color = ColorButton(shape.fill_color)
self.form.addRow("Width", self.width)
self.form.addRow("Height", self.height)
self.form.addRow("Line type", self.line_type)
self.form.addRow("Line thickness", self.line_thickness)
self.form.addRow("Corner radius", self.corner_radius)
self.form.addRow("Line color", self.line_color)
self.form.addRow("Fill color", self.fill_color)

View File

@@ -402,35 +402,20 @@
"icons": {
"43b3aee6-0b38-429b-9c6d-d38fc097297f": {
"shapes": {
"1749a693-44fe-4275-ab22-eb82db339df4": {
"7b93f7ba-d38e-4503-a64f-beb9fc915285": {
"layer": 0,
"type": "rectangle",
"pos": [
-138,
-84
-40,
-40
],
"width": 241.0,
"height": 217.0,
"width": 80,
"height": 80,
"line_type": "solid",
"line_thickness": 1.0,
"corner_radius": 0.0,
"line_color": "#000000",
"fill_color": "#ffffff"
},
"923075c7-3d34-4d0f-902d-cda24731433a": {
"layer": 1,
"type": "rectangle",
"pos": [
-63,
-31
],
"width": 72.0,
"height": 119.0,
"line_type": "solid",
"line_thickness": 1.0,
"corner_radius": 0.0,
"line_color": "#000000",
"fill_color": "#ffffff"
"corner_radius": 5.0,
"line_color": "#000000ff",
"fill_color": "#c8c8c8ff"
}
}
}