Skip to content

Commit

Permalink
Elements in groups: Align to corners/centre (#2810)
Browse files Browse the repository at this point in the history
  • Loading branch information
maurofmferrao authored Nov 26, 2024
1 parent 977391f commit ab62984
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 29 deletions.
1 change: 1 addition & 0 deletions ui/bundle_templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ window.templates = {
header: require('./src/templates/forms/inputs/header.hbs'),
richText: require('./src/templates/forms/inputs/richText.hbs'),
divider: require('./src/templates/forms/inputs/divider.hbs'),
buttonSwitch: require('./src/templates/forms/inputs/buttonSwitch.hbs'),
custom: require('./src/templates/forms/inputs/custom.hbs'),
datasetSelector:
require('./src/templates/forms/inputs/datasetSelector.hbs'),
Expand Down
23 changes: 23 additions & 0 deletions ui/src/core/forms.js
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,29 @@ window.forms = {
});
});

// Button group switch
findElements(
'.button-switch-input-group',
target,
).each(function(_k, el) {
const $buttonGroup = $(el).find('.btn-group');
const $hiddenInput = $(el).find('input[type="hidden"]');

$buttonGroup.find('button').on('click', function(ev) {
const $button = $(ev.currentTarget);

// Deselect all other buttons
$buttonGroup.find('button')
.removeClass('selected');
// Add selected to target button
$button.addClass('selected');

// Update hidden input with chosen button value
$hiddenInput.val($button.data('value'))
.trigger('change');
});
});

// Dataset order clause
findElements(
'.dataset-order-clause',
Expand Down
66 changes: 65 additions & 1 deletion ui/src/editor-core/element-group.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ ElementGroup.prototype.transform = function(transform) {
scaleY: 0,
};

const originalDimensions = {
width: this.width,
height: this.height,
};

// Apply changes to the group ( updating values )
if (transform.width) {
transformation.scaleX = transform.width / this.width;
Expand Down Expand Up @@ -275,7 +280,66 @@ ElementGroup.prototype.transform = function(transform) {
left: elGroup.left + elRelativePositionScaled.left,
});
} else {
// TODO: Don't scale, but stick to corners
// Keep top and left on the same place by default
let newTop = el.top - elGroup.top;
let newLeft = el.left - elGroup.left;

// If bottom bound
if (
el.groupScaleTypeV === 'bottom'
) {
// Distance to bottom
const distToBottom = originalDimensions.height - el.height;

// Calculate top based on bottom position
newTop = newTop - (distToBottom - (elGroup.height - el.height));
} else if (
el.groupScaleTypeV === 'middle'
) {
// Group middle
const groupMiddle = originalDimensions.height / 2;

const newGroupMiddle = elGroup.height /2;

// Element middle
const elMiddle = el.height / 2;

// Distance to middle
const distMiddleToMiddle = groupMiddle - elMiddle;

// Calculate top based on bottom position
newTop = newTop + (newGroupMiddle - distMiddleToMiddle - elMiddle);
}

// If right bound
if (
el.groupScaleTypeH === 'right'
) {
// Calculate left based on right position
newLeft = newLeft - (originalDimensions.width - elGroup.width);
} else if (
el.groupScaleTypeV === 'middle'
) {
// Group center
const groupCenter = originalDimensions.width / 2;

const newGroupCenter = elGroup.width /2;

// Element center
const elCenter = el.width / 2;

// Distance to center
const distCenterToCenter = groupCenter - elCenter;

// Calculate top based on bottom position
newLeft = newLeft + (newGroupCenter - distCenterToCenter - elCenter);
}

// Transform without scaling
el.transform({
top: elGroup.top + newTop,
left: elGroup.left + newLeft,
});
}
});
};
Expand Down
6 changes: 4 additions & 2 deletions ui/src/editor-core/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ const Element = function(data, widgetId, regionId, parentWidget) {
// Group scale
this.groupScale = (data.groupScale != undefined) ?
data.groupScale : 1;
this.groupScaleType = (data.groupScaleType != undefined) ?
data.groupScaleType : 'top_left';
this.groupScaleTypeV = (data.groupScaleTypeV != undefined) ?
data.groupScaleTypeV : 'top';
this.groupScaleTypeH = (data.groupScaleTypeH != undefined) ?
data.groupScaleTypeH : 'left';

// Animation effect
this.effect = data.effect || 'noTransition';
Expand Down
66 changes: 49 additions & 17 deletions ui/src/editor-core/properties-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -916,48 +916,75 @@ PropertiesPanel.prototype.render = function(
// Create common fields
const commonFields = [];

// TODO: for now we disable scaling type
// Show scaling type if element is in a group
if (
false &&
targetAux.groupId != '' &&
targetAux.groupId != undefined
) {
commonFields.unshift(
{
id: 'groupScale',
customClass: 'group-scale-properties',
title: propertiesPanelTrans.groupScale,
helpText: propertiesPanelTrans.groupScaleHelpText,
value: targetAux.groupScale,
type: 'checkbox',
visibility: [],
},
{
id: 'groupScaleType',
title: propertiesPanelTrans.groupScaleType,
helpText: propertiesPanelTrans.groupScaleTypeHelpText,
value: targetAux.groupScaleType,
id: 'groupScaleTypeH',
customClass: 'group-scale-properties',
title: propertiesPanelTrans.groupScaleTypeH,
helpText: propertiesPanelTrans.groupScaleTypeHHelpText,
value: targetAux.groupScaleTypeH,
options: [
{
title: propertiesPanelTrans.groupScaleTypeOptions.topLeft,
name: 'top_left',
title: propertiesPanelTrans.groupScaleTypeOptions.left,
name: 'left',
},
{
title: propertiesPanelTrans.groupScaleTypeOptions.topRight,
name: 'top_right',
title: propertiesPanelTrans.groupScaleTypeOptions.center,
name: 'center',
},
{
title: propertiesPanelTrans
.groupScaleTypeOptions.bottomLeft,
name: 'bottom_left',
title: propertiesPanelTrans.groupScaleTypeOptions.right,
name: 'right',
},
],
type: 'buttonSwitch',
visibility: [
{
conditions: [
{
field: 'groupScale',
type: 'eq',
value: '0',
},
],
},
],
},
{
id: 'groupScaleTypeV',
customClass: 'group-scale-properties',
title: propertiesPanelTrans.groupScaleTypeV,
helpText: propertiesPanelTrans.groupScaleTypeVHelpText,
value: targetAux.groupScaleTypeV,
options: [
{
title: propertiesPanelTrans
.groupScaleTypeOptions.bottomRight,
name: 'bottom_right',
title: propertiesPanelTrans.groupScaleTypeOptions.top,
name: 'top',
},
{
title: propertiesPanelTrans.groupScaleTypeOptions.middle,
name: 'middle',
},
{
title: propertiesPanelTrans.groupScaleTypeOptions.bottom,
name: 'bottom',
},
],
type: 'dropdown',
type: 'buttonSwitch',
visibility: [
{
conditions: [
Expand Down Expand Up @@ -1700,6 +1727,11 @@ PropertiesPanel.prototype.render = function(
// Update moveable
lD.viewer.updateMoveable();
});

// Check if we have group scale properties for elements
// and move them to the top of the position tab
self.DOMObject.find('#appearanceTab .group-scale-properties')
.prependTo(self.DOMObject.find('#positionTab'));
};

// If it's an element, get properties, first to update it
Expand Down
8 changes: 6 additions & 2 deletions ui/src/editor-core/widget.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,9 +513,13 @@ const Widget = function(id, data, regionId = null, layoutObject = null) {
// Save group scale type if exists
if (element.groupScale) {
elementObject.groupScale = 1;
} else if (element.groupScaleType) {
} else if (
element.groupScaleTypeH &&
element.groupScaleTypeV
) {
elementObject.groupScale = 0;
elementObject.groupScaleType = element.groupScaleType;
elementObject.groupScaleTypeH = element.groupScaleTypeH;
elementObject.groupScaleTypeV = element.groupScaleTypeV;
}
} else {
// Save effect if exists
Expand Down
7 changes: 6 additions & 1 deletion ui/src/layout-editor/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2813,6 +2813,11 @@ Viewer.prototype.initMoveable = function() {
// Save transformation
transformSplit = saveTransformation(e.target);

// Check if item was not resized
if (transformSplit.length === 1) {
return;
}

// Check if the region moved when resizing
const moved = (
parseFloat(transformSplit[1]) != 0 ||
Expand Down Expand Up @@ -2850,7 +2855,7 @@ Viewer.prototype.initMoveable = function() {
lD.selectedObject.type == 'element-group'
) && self.saveElementGroupProperties(
e.target,
false,
true,
true,
);
});
Expand Down
18 changes: 18 additions & 0 deletions ui/src/style/forms.scss
Original file line number Diff line number Diff line change
Expand Up @@ -865,4 +865,22 @@ select[readonly].select2-hidden-accessible + .select2-container .select2-selecti
}
}
}
}

// Button switch
.button-switch-input-group {
button {
color: $xibo-color-primary;
border-color: $xibo-color-primary;

&:not(.selected):hover {
color: $xibo-color-primary;
background-color: lighten($xibo-color-primary, 35%);
}

&.selected {
background-color: $xibo-color-primary;
color: $xibo-color-neutral-0;
}
}
}
36 changes: 36 additions & 0 deletions ui/src/templates/forms/inputs/buttonSwitch.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<div class="form-group xibo-form-input button-switch-input-group
{{customClass}}
{{variant}}"
{{#if visibility}}data-visibility="{{visibility}}"{{/if}}
{{#if dependsOn}}data-depends-on="{{dependsOn}}"{{/if}}
{{#if isRequired}}data-is-required="{{isRequired}}"{{/if}}
>
<label for="{{#unless forceId}}input_{{/unless}}{{id}}" class="control-label"><strong>{{title}}</strong></label>
<div class="input-info-container">
{{#if helpText}}
{{> add-ons/helpText helpText=helpText}}
{{/if}}
</div>
<input id="{{#unless forceId}}input_{{/unless}}{{id}}" name="{{#if name}}{{name}}{{else}}{{id}}{{/if}}" value="{{value}}" type="hidden"/>
<div class="btn-group btn-block" role="group"
{{#each customData}}
data-{{this.name}}="{{this.value}}"
{{/each}}
{{#if readonly}}readonly{{/if}}
>
{{!-- Set default property values --}}
{{#unless optionsValue}}
{{set "optionsValue" "name"}}
{{/unless}}
{{#unless optionsTitle}}
{{set "optionsTitle" "title"}}
{{/unless}}

{{!-- Render options --}}
{{#each options}}
<button type="button" class="btn btn-sm {{#eq (lookup this ../optionsValue) ../value}}selected{{/eq}}"
data-value="{{lookup this ../optionsValue}}"
>{{lookup this ../optionsTitle}}</button>
{{/each}}
</div>
</div>
16 changes: 10 additions & 6 deletions views/editorTranslations.twig
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,17 @@
pinSlotHelpText: "{{ "The first item that appears in a slot will be pinned and will not cycle with the rest of the items."|trans }}",
groupScale: "{{ "Scale with group"|trans }}",
groupScaleHelpText: "{{ "Scale element when scaling containing group."|trans }}",
groupScaleType: "{{ "Align"|trans }}",
groupScaleTypeHelpText: "{{ "Alignment when scaling the containing group."|trans }}",
groupScaleTypeH: "{{ "Horizontal Align"|trans }}",
groupScaleTypeHHelpText: "{{ "Horizontal alignment when scaling the containing group."|trans }}",
groupScaleTypeV: "{{ "Vertical Align"|trans }}",
groupScaleTypeVHelpText: "{{ "Vertical alignment when scaling the containing group."|trans }}",
groupScaleTypeOptions: {
topLeft: "{{ "Top/Left" |trans }}",
topRight: "{{ "Top/Right" |trans }}",
bottomLeft: "{{ "Bottom/Left" |trans }}",
bottomRight: "{{ "Bottom/Right" |trans }}",
left: "{{ "Left" |trans }}",
center: "{{ "Center" |trans }}",
right: "{{ "Right" |trans }}",
top: "{{ "Top" |trans }}",
middle: "{{ "Middle" |trans }}",
bottom: "{{ "Bottom" |trans }}",
},
somethingWentWrong: "{{ "Something went wrong!"|trans }}",
somethingWentWrongEditPermissions: "{{ "Selected item is not shared with you with edit permission!"|trans }}",
Expand Down

0 comments on commit ab62984

Please sign in to comment.