Skip to content

Commit

Permalink
Update editor UI
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiaslehnertum committed May 6, 2024
1 parent 431aa1b commit e9167e3
Show file tree
Hide file tree
Showing 21 changed files with 249 additions and 177 deletions.
34 changes: 9 additions & 25 deletions src/main/components/canvas/mouse-eventlistener.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { withCanvas } from './with-canvas';
import { UMLElementState } from '../../services/uml-element/uml-element-types';
import { IUMLElement } from '../../services/uml-element/uml-element';
import { EditorRepository } from '../../services/editor/editor-repository';
import { IBoundary } from '../../utils/geometry/boundary';
import { areBoundsIntersecting, IBoundary } from '../../utils/geometry/boundary';
import { IPoint } from '../../utils/geometry/point';
import { defaults as getTheme } from '../../components/theme/styles';

Expand Down Expand Up @@ -229,30 +229,14 @@ class MouseEventListenerComponent extends Component<Props, LocalState> {
return false;
}

const elementCornerPoints: IPoint[] = [
{ x: element.bounds.x, y: element.bounds.y },
{ x: element.bounds.x + element.bounds.width, y: element.bounds.y },
{ x: element.bounds.x + element.bounds.width, y: element.bounds.y + element.bounds.height },
{ x: element.bounds.x, y: element.bounds.y + element.bounds.height },
];

const selectionRectangleStartX =
Math.min(x, x + width) / this.props.zoomFactor - canvasOrigin.x / this.props.zoomFactor;
const selectionRectangleEndX =
Math.max(x, x + width) / this.props.zoomFactor - canvasOrigin.x / this.props.zoomFactor;
const selectionRectangleStartY =
Math.min(y, y + height) / this.props.zoomFactor - canvasOrigin.y / this.props.zoomFactor;
const selectionRectangleEndY =
Math.max(y, y + height) / this.props.zoomFactor - canvasOrigin.y / this.props.zoomFactor;

// Determine if the given element is at least partially contained within the selection rectangle
return elementCornerPoints.some(
(point) =>
selectionRectangleStartX <= point.x &&
point.x <= selectionRectangleEndX &&
selectionRectangleStartY <= point.y &&
point.y <= selectionRectangleEndY,
);
const normalizedSelectionBounds: IBoundary = {
x: (x - canvasOrigin.x) / this.props.zoomFactor,
y: (y - canvasOrigin.y) / this.props.zoomFactor,
height: height / this.props.zoomFactor,
width: width / this.props.zoomFactor,
};

return areBoundsIntersecting(element.bounds, normalizedSelectionBounds);
};

/**
Expand Down
15 changes: 10 additions & 5 deletions src/main/components/sidebar/sidebar-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { connect } from 'react-redux';
import { compose } from 'redux';
import { EditorRepository } from '../../services/editor/editor-repository';
import { ApollonMode, ApollonView } from '../../services/editor/editor-types';
import { Switch } from '../controls/switch/switch';
import { CreatePane } from '../create-pane/create-pane';
import { I18nContext } from '../i18n/i18n-context';
import { localized } from '../i18n/localized';
Expand Down Expand Up @@ -48,10 +47,16 @@ class SidebarComponent extends Component<Props> {
return (
<Container id="modeling-editor-sidebar" data-cy="modeling-editor-sidebar">
{this.props.mode === ApollonMode.Exporting && (
<Switch value={this.props.view} onChange={this.props.changeView} color="primary">
<Switch.Item value={ApollonView.Modelling}>{this.props.translate('views.modelling')}</Switch.Item>
<Switch.Item value={ApollonView.Exporting}>{this.props.translate('views.exporting')}</Switch.Item>
</Switch>
<div className="dropdown" style={{ width: 128 }}>
<select
value={this.props.view}
onChange={(event) => this.props.changeView(event.target.value as ApollonView)}
color="primary"
>
<option value={ApollonView.Modelling}>{this.props.translate('views.modelling')}</option>
<option value={ApollonView.Exporting}>{this.props.translate('views.exporting')}</option>
</select>
</div>
)}
{this.props.view === ApollonView.Modelling ? (
<CreatePane />
Expand Down
40 changes: 39 additions & 1 deletion src/main/utils/geometry/boundary.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Point } from './point';
import { IPoint, Point } from './point';

export interface IBoundary {
x: number;
Expand All @@ -7,6 +7,10 @@ export interface IBoundary {
height: number;
}

/**
* Compute a bounding box for a set of points
* @param points The points that should be contained within the bounding box
*/
export function computeBoundingBox(points: Point[]): IBoundary {
if (points.length === 0) {
return { x: 0, y: 0, width: 0, height: 0 };
Expand Down Expand Up @@ -36,6 +40,10 @@ export function computeBoundingBox(points: Point[]): IBoundary {
};
}

/**
* Calculate the bounding box for a set of elements
* @param elements The elements for which a common bounding box should be calculated
*/
export function computeBoundingBoxForElements(elements: { bounds: IBoundary }[]): IBoundary {
if (!elements.length) {
return { x: 0, y: 0, width: 0, height: 0 };
Expand All @@ -55,3 +63,33 @@ export function computeDimension(scale: number, value: number, isCircle?: boolea
return Math.round((value * scale) / 10) * 10;
}
}

/**
* Check whether a given element is intersected by a boundary. This method is used for checking if an element is
* intersected.
*
* @param bounds The bounds for which intersection by the intersecting boundaries is determined
* @param intersectingBounds The potentially intersecting bounds
*/
export const areBoundsIntersecting = (bounds: IBoundary, intersectingBounds: IBoundary): boolean => {
const cornerPoints: IPoint[] = [
{ x: bounds.x, y: bounds.y },
{ x: bounds.x + bounds.width, y: bounds.y },
{ x: bounds.x + bounds.width, y: bounds.y + bounds.height },
{ x: bounds.x, y: bounds.y + bounds.height },
];

const intersectingBoundsStartX = Math.min(intersectingBounds.x, intersectingBounds.x + intersectingBounds.width);
const intersectingBoundsEndX = Math.max(intersectingBounds.x, intersectingBounds.x + intersectingBounds.width);
const intersectingBoundsStartY = Math.min(intersectingBounds.y, intersectingBounds.y + intersectingBounds.height);
const intersectingBoundsEndY = Math.max(intersectingBounds.y, intersectingBounds.y + intersectingBounds.height);

// Determine if the given bounds are at least partially contained within the intersecting bounds
return cornerPoints.some(
(point) =>
intersectingBoundsStartX <= point.x &&
point.x <= intersectingBoundsEndX &&
intersectingBoundsStartY <= point.y &&
point.y <= intersectingBoundsEndY,
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -147,53 +147,6 @@ exports[`test update pane render with element 1`] = `
color: var(--apollon-background,#ffffff);
}
.c14 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
min-height: 1.9rem;
}
.c16 {
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
.c16:not(:first-child) {
margin-left: -1px;
}
.c16:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.c16:last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.c16:not(:first-child):not(:last-child) {
border-radius: 0;
}
.c8 {
background-clip: padding-box;
background-color: var(--apollon-background,#ffffff);
Expand Down Expand Up @@ -289,6 +242,53 @@ exports[`test update pane render with element 1`] = `
overflow: visible;
}
.c14 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
min-height: 1.9rem;
}
.c16 {
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 auto;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
}
.c16:not(:first-child) {
margin-left: -1px;
}
.c16:first-child {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.c16:last-child {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.c16:not(:first-child):not(:last-child) {
border-radius: 0;
}
.c18 {
display: -webkit-box;
display: -webkit-flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ exports[`test default element popup render 1`] = `
<div>
<section>
<div
class="sc-kdBSHD gzfaPq"
class="sc-jxOSlx WMFeS"
>
<input
class="sc-dtBdUo sc-kOHTFB nbRZj bHpNZf"
class="sc-bmzYkS sc-iHGNWf fEVqYL gacFBO"
maxLength="100"
/>
<button
class="sc-hmdomO sc-bXCLTC czBNuA iklrvW"
class="sc-eeDRCY sc-koXPp fShmjg dCdHsc"
color="link"
tabindex="-1"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ exports[`test default relationship popup render 1`] = `
<div>
<section>
<div
class="sc-esYiGF jnEhCX"
class="sc-kdBSHD gzfaPq"
>
<h1
class="sc-tagGq gknvxe"
class="sc-lcIPJg chQxvR"
>
Relationship
</h1>
<button
class="sc-hmdomO sc-bXCLTC czBNuA iklrvW"
class="sc-eeDRCY sc-koXPp fShmjg dCdHsc"
color="link"
tabindex="-1"
>
Expand Down
Loading

0 comments on commit e9167e3

Please sign in to comment.