Skip to content

Commit

Permalink
Merge pull request #33 from chekoopa/component-marks
Browse files Browse the repository at this point in the history
Метки компонентов
  • Loading branch information
chekoopa committed Oct 3, 2023
2 parents fb5ea93 + 14e876a commit 8e84118
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 91 deletions.
8 changes: 6 additions & 2 deletions demos/demo4 (schema v2).json
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,17 @@
"components": {
"diod1": {
"parameters": {
"pin": "12"
"pin": "12",
"labelColor": "#0008f5",
"label": "1"
},
"type": "LED"
},
"button1": {
"parameters": {
"pin": "4"
"pin": "4",
"labelColor": "#c70000",
"label": "1"
},
"type": "Button"
}
Expand Down
46 changes: 34 additions & 12 deletions src/renderer/src/components/ComponentEditModal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useEffect, useState } from 'react';

import { Modal } from './Modal/Modal';

import { ComponentProto } from '@renderer/types/platform';
import { Component as ComponentData } from '@renderer/types/diagram';
import { ComponentProto } from '@renderer/types/platform';

import { Modal } from './Modal/Modal';

interface ComponentEditModalProps {
isOpen: boolean;
Expand Down Expand Up @@ -77,15 +77,37 @@ export const ComponentEditModal: React.FC<ComponentEditModalProps> = ({
{proto.singletone ? (
''
) : (
<label className="mb-2 flex items-center gap-2">
Name:
<input
className="w-[250px] max-w-[250px] rounded border border-white bg-transparent px-2 py-1 outline-none transition-colors placeholder:font-normal"
maxLength={20}
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
<>
<label className="mb-2 flex items-center gap-2">
Название:
<input
className="w-[250px] max-w-[250px] rounded border border-white bg-transparent px-2 py-1 outline-none transition-colors placeholder:font-normal"
maxLength={20}
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
<label key="label" className="flex items-center gap-2">
Метка:
<input
className="w-[250px] max-w-[250px] rounded border bg-transparent px-2 py-1 outline-none transition-colors placeholder:font-normal"
value={parameters['label'] ?? ''}
name={'label'}
maxLength={3}
onChange={handleInputChange}
/>
</label>
<label key="labelColor" className="flex items-center gap-2">
Цвет метки:
<input
className="ml-2 rounded border border-neutral-200 bg-transparent text-neutral-50 outline-none transition-colors focus:border-neutral-50"
value={parameters['labelColor'] ?? '#FFFFFF'}
name={'labelColor'}
type="color"
onChange={handleInputChange}
/>
</label>
</>
)}
{Object.entries(proto.parameters ?? {}).map(([idx, param]) => {
const name = param.name ?? idx;
Expand Down
13 changes: 3 additions & 10 deletions src/renderer/src/components/CreateModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,7 @@ export const CreateModal: React.FC<CreateModalProps> = ({
value: idx,
label: (
<div className="flex items-center">
<img
src={machine.platform.getComponentIconUrl(idx, true)}
className="mr-1 h-7 w-7 object-contain"
/>
{machine.platform.getFullComponentIcon(idx, 'mr-1 h-7 w-7')}
{idx}
</div>
),
Expand Down Expand Up @@ -240,8 +237,7 @@ export const CreateModal: React.FC<CreateModalProps> = ({
const [argForm, setArgForm] = useState<ArgForm>([]);

const retrieveArgForm = (compo: string, method: string) => {
const compoType = machine.platform.resolveComponent(compo);
const component = machine.platform.data.components[compoType];
const component = machine.platform.getComponent(compo);
if (!component) return [];

const argList: ArgumentProto[] | undefined = isEditingEvent
Expand Down Expand Up @@ -794,10 +790,7 @@ export const CreateModal: React.FC<CreateModalProps> = ({
'm-2 flex min-h-[3rem] w-36 items-center justify-around rounded-lg border-2 bg-neutral-700 px-1'
)}
>
<img
style={{ height: '32px', width: '32px' }}
src={machine.platform.getComponentIconUrl(data.component, true)}
/>
{machine.platform.getFullComponentIcon(data.component)}
<div className="h-full border-2 border-white"></div>
<img
style={{ height: '32px', width: '32px' }}
Expand Down
8 changes: 2 additions & 6 deletions src/renderer/src/components/EventsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,7 @@ export const CreateEventsModal: React.FC<EventsModalProps> = ({
value: idx,
label: (
<div className="flex items-center">
<img
src={machine.platform.getComponentIconUrl(idx, true)}
className="mr-1 h-7 w-7 object-contain"
/>
{machine.platform.getFullComponentIcon(idx, 'mr-1 h-7 w-7')}
{idx}
</div>
),
Expand Down Expand Up @@ -128,8 +125,7 @@ export const CreateEventsModal: React.FC<EventsModalProps> = ({
const [argForm, setArgForm] = useState<ArgForm>([]);

const retrieveArgForm = (compo: string, method: string) => {
const compoType = machine.platform.resolveComponent(compo);
const component = machine.platform.data.components[compoType];
const component = machine.platform.getComponent(compo);
if (!component) return [];

const argList: ArgumentProto[] | undefined = isEditingEvent
Expand Down
8 changes: 1 addition & 7 deletions src/renderer/src/components/Explorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import React, { useState } from 'react';
import { twMerge } from 'tailwind-merge';

import { ReactComponent as AddIcon } from '@renderer/assets/icons/new transition.svg';
import UnknownIcon from '@renderer/assets/icons/unknown.svg';
import { ComponentEditModal, ComponentAddModal, ComponentDeleteModal } from '@renderer/components';
import { useAddComponent, useEditDeleteComponent } from '@renderer/hooks';
import { CanvasEditor } from '@renderer/lib/CanvasEditor';
Expand Down Expand Up @@ -86,12 +85,7 @@ export const Explorer: React.FC<ExplorerProps> = ({ editor, manager }) => {
onDoubleClick={() => onCompDblClick(key)}
onContextMenu={() => onCompRightClick(key)}
>
<img
className="h-8 w-8 object-contain"
src={
editor?.container.machine.platform?.getComponentIconUrl(key, true) ?? UnknownIcon
}
/>
{editor?.container.machine.platform?.getFullComponentIcon(key)}
<p className="ml-2 line-clamp-1">{key}</p>
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { Platform } from '@renderer/types/platform';
import { icons, picto } from '../drawable/Picto';
import { Action, Condition, Event, Variable } from '@renderer/types/diagram';
import { ComponentProto } from '@renderer/types/platform';
import { Platform, ComponentProto } from '@renderer/types/platform';

import { MarkedIconData, icons, picto } from '../drawable/Picto';
import { stateStyle } from '../styles';

export type VisualCompoData = {
component: string;
label?: string;
color?: string;
};

export type ListEntry = {
name: string;
description?: string;
Expand Down Expand Up @@ -46,11 +52,12 @@ export class PlatformManager {
data!: Platform;

/**
* Проекция названия компонента к его типу.
* Проекция названия компонента к его типу и метке.
* Если платформа не видит проекцию, она будет считать
* переданное название типом компонента.
* переданное название типом компонента,
* а данные метки – пустыми.
*/
nameToComponent: Map<string, string> = new Map();
nameToVisual: Map<string, VisualCompoData> = new Map();

componentToIcon: Map<string, string> = new Map();
eventToIcon: Map<string, string> = new Map();
Expand Down Expand Up @@ -97,13 +104,17 @@ export class PlatformManager {
}
}

resolveComponent(name: string): string {
return this.nameToComponent.get(name) ?? name;
resolveComponent(name: string) {
return this.nameToVisual.get(name) ?? { component: name };
}

resolveComponentType(name: string): string {
return this.nameToVisual.get(name)?.component ?? name;
}

getComponent(name: string, isType?: boolean): ComponentProto | undefined {
if (name == 'System') return systemComponent;
const query = isType ? name : this.resolveComponent(name);
const query = isType ? name : this.resolveComponentType(name);
return this.data.components[query];
}

Expand Down Expand Up @@ -153,7 +164,7 @@ export class PlatformManager {
}

getComponentIcon(name: string, isName?: boolean) {
const query = isName ? this.resolveComponent(name) : name;
const query = isName ? this.resolveComponentType(name) : name;
const icon = this.componentToIcon.get(query);
// console.log(['getComponentIcon', name, isName, icon]);
if (icon && icons.has(icon)) {
Expand All @@ -169,6 +180,17 @@ export class PlatformManager {
return icons.get(query)!.src;
}

getFullComponentIcon(name: string, className?: string): React.ReactNode {
const query = this.nameToVisual.get(name) ?? { component: name };
const iconQuery = {
...query,
icon: this.getComponentIcon(query.component, false),
};
// console.log(['getComponentIcon', name, isName, query, icons.get(query)!.src]);
// return <img className="h-8 w-8 object-contain" src={icon?.src ?? UnknownIcon} />;
return picto.getMarkedSvg(iconQuery, className);
}

getEventIcon(component: string, method: string) {
const icon = this.eventToIcon.get(`${component}/${method}`);
if (icon && icons.has(icon)) {
Expand All @@ -179,7 +201,7 @@ export class PlatformManager {
}

getEventIconUrl(component: string, method: string, isName?: boolean) {
const compoQuery = isName ? this.resolveComponent(component) : component;
const compoQuery = isName ? this.resolveComponentType(component) : component;
const query = this.getEventIcon(compoQuery, method);
// console.log(['getEventIconUrl', component, isName, compoQuery, method, query, icons.get(query)!.src,]);
return icons.get(query)!.src;
Expand All @@ -195,7 +217,7 @@ export class PlatformManager {
}

getActionIconUrl(component: string, method: string, isName?: boolean) {
const compoQuery = isName ? this.resolveComponent(component) : component;
const compoQuery = isName ? this.resolveComponentType(component) : component;
const query = this.getActionIcon(compoQuery, method);
// console.log(['getActionIconUrl', component, isName, compoQuery, method, query, icons.get(query)!.src,]);
return icons.get(query)!.src;
Expand All @@ -211,25 +233,29 @@ export class PlatformManager {
}

getVariableIconUrl(component: string, method: string, isName?: boolean) {
const compoQuery = isName ? this.resolveComponent(component) : component;
const compoQuery = isName ? this.resolveComponentType(component) : component;
const query = this.getVariableIcon(compoQuery, method);
// console.log(['getEventIconUrl', component, isName, compoQuery, method, query, icons.get(query)!.src,]);
return icons.get(query)!.src;
}

drawEvent(ctx: CanvasRenderingContext2D, ev: Event, x: number, y: number) {
let leftIcon: string | undefined = undefined;
let leftIcon: string | MarkedIconData | undefined = undefined;
let rightIcon = 'unknown';
let bgColor = '#3a426b';
let fgColor = '#fff';
const bgColor = '#3a426b';
const fgColor = '#fff';
let argQuery: string = '';

if (ev.component === 'System') {
// ev.method === 'onEnter' || ev.method === 'onExit'
rightIcon = ev.method;
} else {
const component = this.resolveComponent(ev.component);
leftIcon = this.getComponentIcon(component);
const compoData = this.resolveComponent(ev.component);
const component = compoData.component;
leftIcon = {
...compoData,
icon: this.getComponentIcon(component),
};
rightIcon = this.getEventIcon(component, ev.method);

const parameterList = this.data.components[component]?.signals[ev.method]?.parameters;
Expand Down Expand Up @@ -262,18 +288,22 @@ export class PlatformManager {
}

drawAction(ctx: CanvasRenderingContext2D, ac: Action, x: number, y: number, alpha?: number) {
let leftIcon: string | undefined = undefined;
let leftIcon: string | MarkedIconData | undefined = undefined;
let rightIcon = 'unknown';
let bgColor = '#5b5f73';
let fgColor = '#fff';
let opacity = alpha ?? 1.0;
const bgColor = '#5b5f73';
const fgColor = '#fff';
const opacity = alpha ?? 1.0;
let argQuery: string = '';

if (ac.component === 'System') {
rightIcon = ac.method;
} else {
const component = this.resolveComponent(ac.component);
leftIcon = this.getComponentIcon(component);
const compoData = this.resolveComponent(ac.component);
const component = compoData.component;
leftIcon = {
...compoData,
icon: this.getComponentIcon(component),
};
rightIcon = this.getActionIcon(component, ac.method);

const parameterList = this.data.components[component]?.methods[ac.method]?.parameters;
Expand Down Expand Up @@ -335,12 +365,12 @@ export class PlatformManager {
y: number,
alpha?: number
) {
let bgColor = '#5b7173';
let fgColor = '#fff';
let opacity = alpha ?? 1.0;
const bgColor = '#5b7173';
const fgColor = '#fff';
const opacity = alpha ?? 1.0;

if (ac.type == 'component') {
let leftIcon: string | undefined = undefined;
let leftIcon: string | MarkedIconData | undefined = undefined;
let rightIcon = 'unknown';

// FIXME: столько проверок ради простой валидации...
Expand All @@ -353,8 +383,12 @@ export class PlatformManager {
if (vr.component === 'System') {
rightIcon = vr.method;
} else {
const component = this.resolveComponent(vr.component);
leftIcon = this.getComponentIcon(component);
const compoData = this.resolveComponent(vr.component);
const component = compoData.component;
leftIcon = {
...compoData,
icon: this.getComponentIcon(component),
};
rightIcon = this.getVariableIcon(component, vr.method);
}
}
Expand All @@ -379,7 +413,7 @@ export class PlatformManager {

const mr = picto.eventMargin;
const icoW = (picto.eventHeight + picto.eventMargin) / picto.scale;
let leftW = (this.measureCondition(ac.value[0]) + mr) / picto.scale;
const leftW = (this.measureCondition(ac.value[0]) + mr) / picto.scale;

this.drawCondition(ctx, ac.value[0], x, y, alpha);
picto.drawMono(ctx, x + leftW, y, {
Expand Down
Loading

0 comments on commit 8e84118

Please sign in to comment.