bm-core-ui 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1624 -0
- package/LICENSE +21 -0
- package/README.md +145 -0
- package/build/@types/index.d.ts +14078 -0
- package/build/BMCodeEditor/BMCodeEditor.js +707 -0
- package/build/BMCollectionView/BMCollectionView.js +5861 -0
- package/build/BMCollectionView/BMCollectionViewCell.js +688 -0
- package/build/BMCollectionView/BMCollectionViewFlowLayout.js +4467 -0
- package/build/BMCollectionView/BMCollectionViewLayout.js +830 -0
- package/build/BMCollectionView/BMCollectionViewLayoutAttributes.js +673 -0
- package/build/BMCollectionView/BMCollectionViewMasonryLayout.js +491 -0
- package/build/BMCollectionView/BMCollectionViewStackLayout.js +634 -0
- package/build/BMCollectionView/BMCollectionViewTileLayout.js +1121 -0
- package/build/BMCoreUI.css +2833 -0
- package/build/BMView/BMAttributedLabelView.js +310 -0
- package/build/BMView/BMLayoutConstraint_v2.5.js +1813 -0
- package/build/BMView/BMLayoutGuide.js +192 -0
- package/build/BMView/BMLayoutSizeClass.js +466 -0
- package/build/BMView/BMMenu.js +574 -0
- package/build/BMView/BMScrollView.js +247 -0
- package/build/BMView/BMTextField.js +512 -0
- package/build/BMView/BMTextFieldDelegate.js +71 -0
- package/build/BMView/BMView_v2.5.js +3572 -0
- package/build/BMView/BMViewport.js +221 -0
- package/build/BMViewLayoutEditor/BMLayoutEditor.js +6117 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorConstraintSettings.js +417 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorDelegate.js +59 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorSettingCells.js +1653 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorSettings.js +1480 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorSettingsComplexCells.js +431 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorSettingsDelegate.js +46 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorVariablesController.js +460 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorViewGroupSettings.js +293 -0
- package/build/BMViewLayoutEditor/BMLayoutEditorViewSettings.js +382 -0
- package/build/BMViewLayoutEditor/BMLayoutVariableProvider.js +202 -0
- package/build/BMWindow/BMConfirmationPopup.js +477 -0
- package/build/BMWindow/BMKeyboardShortcut.js +151 -0
- package/build/BMWindow/BMPopover/BMPopover.js +492 -0
- package/build/BMWindow/BMToolWindow.js +71 -0
- package/build/BMWindow/BMWindow.js +2000 -0
- package/build/Core/BMAnimationContext.js +1181 -0
- package/build/Core/BMColor.js +991 -0
- package/build/Core/BMCoreUI.js +470 -0
- package/build/Core/BMFunctionCollection.js +110 -0
- package/build/Core/BMIndexPath.js +165 -0
- package/build/Core/BMInset.js +138 -0
- package/build/Core/BMKeyPath.js +100 -0
- package/build/Core/BMPoint.js +291 -0
- package/build/Core/BMRect.js +556 -0
- package/build/Core/BMSize.js +137 -0
- package/build/iScroll/LICENSE +22 -0
- package/build/iScroll/iscroll-probe.js +2154 -0
- package/build/images/AlignBottom.png +0 -0
- package/build/images/AlignCenterX.png +0 -0
- package/build/images/AlignCenterY.png +0 -0
- package/build/images/AlignLeading.png +0 -0
- package/build/images/AlignTop.png +0 -0
- package/build/images/AlignTrailing.png +0 -0
- package/build/images/AllConstraints.png +0 -0
- package/build/images/BottomConstraint.png +0 -0
- package/build/images/CenterXConstraint.png +0 -0
- package/build/images/CenterYConstraint.png +0 -0
- package/build/images/CoreUI2.png +0 -0
- package/build/images/CoreUI2@2x.png +0 -0
- package/build/images/Desktop.png +0 -0
- package/build/images/DesktopMini.png +0 -0
- package/build/images/EqualHeight.png +0 -0
- package/build/images/EqualHorizontalSpacing.png +0 -0
- package/build/images/EqualHorizontalSpacingInSuperview.png +0 -0
- package/build/images/EqualVerticalSpacing.png +0 -0
- package/build/images/EqualVerticalSpacingInSuperview.png +0 -0
- package/build/images/EqualWidth.png +0 -0
- package/build/images/HeightConstraint.png +0 -0
- package/build/images/InactiveConstraints.png +0 -0
- package/build/images/Layout.png +0 -0
- package/build/images/LayoutVariables.png +0 -0
- package/build/images/LeftConstraint.png +0 -0
- package/build/images/OwnConstraints.png +0 -0
- package/build/images/Phone.png +0 -0
- package/build/images/PhoneLandscape.png +0 -0
- package/build/images/PhoneLandscapeMini.png +0 -0
- package/build/images/PhoneMini.png +0 -0
- package/build/images/PhonePortrait.png +0 -0
- package/build/images/PhonePortraitMini.png +0 -0
- package/build/images/Properties.png +0 -0
- package/build/images/RightConstraint.png +0 -0
- package/build/images/SubviewConstraints.png +0 -0
- package/build/images/Tablet.png +0 -0
- package/build/images/TabletLandscape.png +0 -0
- package/build/images/TabletLandscapeMini.png +0 -0
- package/build/images/TabletMini.png +0 -0
- package/build/images/TabletPortrait.png +0 -0
- package/build/images/TabletPortraitMini.png +0 -0
- package/build/images/TopConstraint.png +0 -0
- package/build/images/WidthConstraint.png +0 -0
- package/build/index.js +40 -0
- package/lib/@types/BMCoreUI.min.d.ts +14078 -0
- package/lib/BMCoreUI.min.js +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import {YES, NO, BMExtend} from '../Core/BMCoreUI'
|
|
3
|
+
import { __BMVelocityAnimate} from '../Core/BMAnimationContext'
|
|
4
|
+
import { _BMLayoutEditorCollectionSettingsPanel, _BMLayoutEditorSettingsPanel, _BMURLOfImageAtPath} from './BMLayoutEditorSettings'
|
|
5
|
+
import { BMEqualSpacingLayoutConstraint, BMLayoutConstraintKind, BMLayoutAttribute, BMEqualAttributeLayoutConstraint } from '../BMView/BMLayoutConstraint_v2.5';
|
|
6
|
+
|
|
7
|
+
// @type _BMLayoutEditorViewGroupSettingsPanel
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A class that controls the settings for a view.
|
|
11
|
+
*/
|
|
12
|
+
export function _BMLayoutEditorViewGroupSettingsPanel() {} // <constructor>
|
|
13
|
+
|
|
14
|
+
_BMLayoutEditorViewGroupSettingsPanel.prototype = BMExtend(Object.create(_BMLayoutEditorSettingsPanel.prototype), {
|
|
15
|
+
constructor: _BMLayoutEditorViewGroupSettingsPanel,
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The views whose settings are displayed.
|
|
19
|
+
*/
|
|
20
|
+
_views: undefined, // <[BMView]>
|
|
21
|
+
get views() {
|
|
22
|
+
return this._views;
|
|
23
|
+
},
|
|
24
|
+
set views(views) {
|
|
25
|
+
this._views = views;
|
|
26
|
+
this.title = views.length + ' Selected';
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Designated initializer. Initializes this settings panel with the given settings view.
|
|
31
|
+
* @param view <_BMLayoutSettingsView> The settings view.
|
|
32
|
+
* @return <_BMLayoutEditorSettingsPanel> This setttings panel.
|
|
33
|
+
*/
|
|
34
|
+
initWithSettingsView(settingsView, {forViews: views}) {
|
|
35
|
+
_BMLayoutEditorSettingsPanel.prototype.initWithSettingsView.call(this, settingsView);
|
|
36
|
+
|
|
37
|
+
this._views = views;
|
|
38
|
+
|
|
39
|
+
this.title = views.length + ' Selected';
|
|
40
|
+
|
|
41
|
+
return this;
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Constructs and returns the DOM node for a readonly setting.
|
|
46
|
+
* @param name <String> The name of the setting.
|
|
47
|
+
* {
|
|
48
|
+
* @param value <String> The readonly value to display.
|
|
49
|
+
* @param action <void ^(Event), nullable> An optional action that will take place
|
|
50
|
+
* when the value is clicked.
|
|
51
|
+
* }
|
|
52
|
+
* @return <DOMNode> A DOM node.
|
|
53
|
+
*/
|
|
54
|
+
readonlySettingWithName(name, args) {
|
|
55
|
+
let item = document.createElement('div');
|
|
56
|
+
item.className = 'BMLayoutEditorDetailsItemTitle';
|
|
57
|
+
item.innerText = name;
|
|
58
|
+
item.style.textAlign = 'left';
|
|
59
|
+
item.style.paddingLeft = '8px';
|
|
60
|
+
return item;
|
|
61
|
+
|
|
62
|
+
let title = document.createElement('div');
|
|
63
|
+
title.className = 'BMLayoutEditorDetailsItemTitle';
|
|
64
|
+
title.innerText = name;
|
|
65
|
+
item.appendChild(title);
|
|
66
|
+
|
|
67
|
+
let value;
|
|
68
|
+
if (args.value) {
|
|
69
|
+
value = document.createElement('div');
|
|
70
|
+
value.className = 'BMLayoutEditorDetailsItemReadonlyValue';
|
|
71
|
+
value.innerText = args.value;
|
|
72
|
+
item.appendChild(value);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
//title.style.width = '240px';
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (args.action) {
|
|
79
|
+
value.classList.add('BMLayoutEditorDetailsItemReadonlyValueClickable');
|
|
80
|
+
value.addEventListener('click', args.action);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return item;
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Constructs and returns a button with a handler that will be invoked when the button is pressed.
|
|
88
|
+
* @param name <String> The text that will appear on this button.
|
|
89
|
+
* {
|
|
90
|
+
* @param class <String, nullable> If specified, this class will be added to the button.
|
|
91
|
+
* @param action <void ^(Event)> A callback that will be invoked when this button is pressed.
|
|
92
|
+
* }
|
|
93
|
+
* @return <DOMNode> A button.
|
|
94
|
+
*/
|
|
95
|
+
buttonSettingWithName(name, args) {
|
|
96
|
+
let button;
|
|
97
|
+
if (args.class) {
|
|
98
|
+
button = document.createElement('div');
|
|
99
|
+
button.className = 'BMLayoutEditorImageButton ' + args.class;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
button = document.createElement('button');
|
|
103
|
+
button.className = 'BMWindowButton';
|
|
104
|
+
button.innerText = name;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
button.addEventListener('click', args.action);
|
|
108
|
+
|
|
109
|
+
return button;
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Constructs and returns a divier.
|
|
114
|
+
* @return <DOMNode> A divider.
|
|
115
|
+
*/
|
|
116
|
+
settingsDivider() {
|
|
117
|
+
let divider = document.createElement('div');
|
|
118
|
+
divider.className = 'BMLayoutEditorDetailsDivider';
|
|
119
|
+
return divider;
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Constructs and returns a settings button that creates an equal attribute constraint
|
|
124
|
+
* over a set of views.
|
|
125
|
+
* @param name <String> The name of the button.
|
|
126
|
+
* {
|
|
127
|
+
* @param icon <String, nullable> Overrides name if specified. The icon to use for the button.
|
|
128
|
+
* @param attribute <BMLayoutAttribute> The layout attribute with which the constraint will be created.
|
|
129
|
+
* }
|
|
130
|
+
*/
|
|
131
|
+
equalConstraintSettingWithName(name, args) {
|
|
132
|
+
let setting = this.buttonSettingWithName(name, {class: args.class, action: event => {
|
|
133
|
+
let constraint = BMEqualAttributeLayoutConstraint.constraintWithAttribute(args.attribute, {
|
|
134
|
+
forViews: this.views,
|
|
135
|
+
_internal: event.shiftKey
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (event.shiftKey) {
|
|
139
|
+
constraint.constituentConstraints.forEach(constraint => {
|
|
140
|
+
constraint._install();
|
|
141
|
+
this.layoutEditor.addConstraint(constraint)
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
this.layoutEditor.addConstraint(constraint);
|
|
146
|
+
}
|
|
147
|
+
}});
|
|
148
|
+
return setting;
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
// @override - BMLayoutEditorSettingsPanel
|
|
152
|
+
settingsPanelDidLoad() {
|
|
153
|
+
// TODO: Consider redoing this method; it works for now though
|
|
154
|
+
const content = this.view.node;
|
|
155
|
+
|
|
156
|
+
let constraintsTitle = this.readonlySettingWithName('Align Horizontal', {value: ''});
|
|
157
|
+
content.appendChild(constraintsTitle);
|
|
158
|
+
|
|
159
|
+
let flexContainer = document.createElement('div');
|
|
160
|
+
flexContainer.style.cssText = 'display: flex; flex-direction: row; align-self: center; justify-content: center;';
|
|
161
|
+
content.appendChild(flexContainer);
|
|
162
|
+
|
|
163
|
+
flexContainer.appendChild(this.equalConstraintSettingWithName('Align Top', {class: 'BMLayoutEditorImageButtonAlignAlignTop', attribute: BMLayoutAttribute.Top}));
|
|
164
|
+
flexContainer.appendChild(this.equalConstraintSettingWithName('Align Center', {class: 'BMLayoutEditorImageButtonAlignCenterY', attribute: BMLayoutAttribute.CenterY}));
|
|
165
|
+
flexContainer.appendChild(this.equalConstraintSettingWithName('Align Bottom', {class: 'BMLayoutEditorImageButtonAlignBottom', attribute: BMLayoutAttribute.Bottom}));
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
//---------------------------------------------------------------------------------------------------------
|
|
169
|
+
content.appendChild(this.settingsDivider());
|
|
170
|
+
let internalConstraintsTitle = this.readonlySettingWithName('Distribute Horizontal', {value: ''});
|
|
171
|
+
content.appendChild(internalConstraintsTitle);
|
|
172
|
+
|
|
173
|
+
flexContainer = document.createElement('div');
|
|
174
|
+
flexContainer.style.cssText = 'display: flex; flex-direction: row; align-self: center; justify-content: center;';
|
|
175
|
+
content.appendChild(flexContainer);
|
|
176
|
+
|
|
177
|
+
flexContainer.appendChild(this.buttonSettingWithName('Equal Spacing', {class: 'BMLayoutEditorImageButtonEqualHorizontalSpacing', action: event => {
|
|
178
|
+
let constraint = BMEqualSpacingLayoutConstraint.constraintOfKind(BMLayoutConstraintKind.Horizontal, {
|
|
179
|
+
forViews: this.views.slice().sort((a, b) => a.node.getBoundingClientRect().left - b.node.getBoundingClientRect().left),
|
|
180
|
+
withSuperview: NO,
|
|
181
|
+
_internal: event.shiftKey
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
if (event.shiftKey) {
|
|
185
|
+
constraint.constituentConstraints.forEach(constraint => {
|
|
186
|
+
constraint._install();
|
|
187
|
+
this.layoutEditor.addConstraint(constraint)
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
this.layoutEditor.addConstraint(constraint);
|
|
192
|
+
}
|
|
193
|
+
}}));
|
|
194
|
+
flexContainer.appendChild(this.buttonSettingWithName('Equal Spacing In Superview', {class: 'BMLayoutEditorImageButtonEqualHorizontalSpacingInSuperview', action: event => {
|
|
195
|
+
let constraint = BMEqualSpacingLayoutConstraint.constraintOfKind(BMLayoutConstraintKind.Horizontal, {
|
|
196
|
+
forViews: this.views.slice().sort((a, b) => a.node.getBoundingClientRect().left - b.node.getBoundingClientRect().left),
|
|
197
|
+
withSuperview: YES,
|
|
198
|
+
_internal: event.shiftKey
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
if (event.shiftKey) {
|
|
202
|
+
constraint.constituentConstraints.forEach(constraint => {
|
|
203
|
+
constraint._install();
|
|
204
|
+
this.layoutEditor.addConstraint(constraint)
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
this.layoutEditor.addConstraint(constraint);
|
|
209
|
+
}
|
|
210
|
+
}}));
|
|
211
|
+
flexContainer.appendChild(this.equalConstraintSettingWithName('Equal Width', {class: 'BMLayoutEditorImageButtonEqualWidth', attribute: BMLayoutAttribute.Width}));
|
|
212
|
+
|
|
213
|
+
//---------------------------------------------------------------------------------------------------------
|
|
214
|
+
content.appendChild(this.settingsDivider());
|
|
215
|
+
internalConstraintsTitle = this.readonlySettingWithName('Align Vertical', {value: ''});
|
|
216
|
+
content.appendChild(internalConstraintsTitle);
|
|
217
|
+
|
|
218
|
+
flexContainer = document.createElement('div');
|
|
219
|
+
flexContainer.style.cssText = 'display: flex; flex-direction: row; align-self: center; justify-content: center;';
|
|
220
|
+
content.appendChild(flexContainer);
|
|
221
|
+
|
|
222
|
+
flexContainer.appendChild(this.equalConstraintSettingWithName('Align Leading', {class: 'BMLayoutEditorImageButtonAlignLeading', attribute: BMLayoutAttribute.Leading}));
|
|
223
|
+
flexContainer.appendChild(this.equalConstraintSettingWithName('Align Center', {class: 'BMLayoutEditorImageButtonAlignCenterX', attribute: BMLayoutAttribute.CenterX}));
|
|
224
|
+
flexContainer.appendChild(this.equalConstraintSettingWithName('Align Trailing', {class: 'BMLayoutEditorImageButtonAlignTrailing', attribute: BMLayoutAttribute.Trailing}));
|
|
225
|
+
|
|
226
|
+
//---------------------------------------------------------------------------------------------------------
|
|
227
|
+
content.appendChild(this.settingsDivider());
|
|
228
|
+
internalConstraintsTitle = this.readonlySettingWithName('Distribute Vertical', {value: ''});
|
|
229
|
+
content.appendChild(internalConstraintsTitle);
|
|
230
|
+
|
|
231
|
+
flexContainer = document.createElement('div');
|
|
232
|
+
flexContainer.style.cssText = 'display: flex; flex-direction: row; align-self: center; justify-content: center;';
|
|
233
|
+
content.appendChild(flexContainer);
|
|
234
|
+
|
|
235
|
+
flexContainer.appendChild(this.buttonSettingWithName('Equal Spacing', {class: 'BMLayoutEditorImageButtonEqualVerticalSpacing', action: event => {
|
|
236
|
+
let constraint = BMEqualSpacingLayoutConstraint.constraintOfKind(BMLayoutConstraintKind.Vertical, {
|
|
237
|
+
forViews: this.views.slice().sort((a, b) => a.node.getBoundingClientRect().top - b.node.getBoundingClientRect().top),
|
|
238
|
+
withSuperview: NO,
|
|
239
|
+
_internal: event.shiftKey
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
if (event.shiftKey) {
|
|
243
|
+
constraint.constituentConstraints(constraint => {
|
|
244
|
+
constraint._install();
|
|
245
|
+
this.layoutEditor.addConstraint(constraint)
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
this.layoutEditor.addConstraint(constraint);
|
|
250
|
+
}
|
|
251
|
+
}}));
|
|
252
|
+
flexContainer.appendChild(this.buttonSettingWithName('Equal Spacing In Superview', {class: 'BMLayoutEditorImageButtonEqualVerticalSpacingInSuperview', action: event => {
|
|
253
|
+
let constraint = BMEqualSpacingLayoutConstraint.constraintOfKind(BMLayoutConstraintKind.Vertical, {
|
|
254
|
+
forViews: this.views.slice().sort((a, b) => a.node.getBoundingClientRect().top - b.node.getBoundingClientRect().top),
|
|
255
|
+
withSuperview: YES,
|
|
256
|
+
_internal: event.shiftKey
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
if (event.shiftKey) {
|
|
260
|
+
constraint.constituentConstraints(constraint => {
|
|
261
|
+
constraint._install();
|
|
262
|
+
this.layoutEditor.addConstraint(constraint)
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
this.layoutEditor.addConstraint(constraint);
|
|
267
|
+
}
|
|
268
|
+
}}));
|
|
269
|
+
flexContainer.appendChild(this.equalConstraintSettingWithName('Equal Height', {class: 'BMLayoutEditorImageButtonEqualHeight', attribute: BMLayoutAttribute.Height}));
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
// @override - BMLayoutEditorSettingsPanel
|
|
273
|
+
settingsPanelWillAppear(animated) {
|
|
274
|
+
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
// @override - BMLayoutEditorSettingsPanel
|
|
278
|
+
settingsPanelDidAppear(animated) {
|
|
279
|
+
|
|
280
|
+
},
|
|
281
|
+
|
|
282
|
+
// @override - BMLayoutEditorSettingsPanel
|
|
283
|
+
settingsPanelWillDisappear(animated) {
|
|
284
|
+
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
// @override - BMLayoutEditorSettingsPanel
|
|
288
|
+
settingsPanelDidDisappear(animated) {
|
|
289
|
+
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// @endtype
|
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import {YES, NO, BMExtend} from '../Core/BMCoreUI'
|
|
3
|
+
import {__BMVelocityAnimate} from '../Core/BMAnimationContext'
|
|
4
|
+
import {BMMenuItem} from '../BMView/BMMenu'
|
|
5
|
+
import { _BMLayoutEditorCollectionSettingsPanel, BMLayoutEditorSettingsTab, _BMLayoutEditorSettingsPanel, _BMURLOfImageAtPath, BMLayoutEditorSettingKind, BMLayoutEditorSettingsSection, BMLayoutEditorSetting, BMLayoutEditorEnumSetting } from './BMLayoutEditorSettings'
|
|
6
|
+
|
|
7
|
+
// @type _BMLayoutEditorViewSettingsPanel
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A class that controls the settings for a view.
|
|
11
|
+
*/
|
|
12
|
+
export function _BMLayoutEditorViewSettingsPanel() {} // <constructor>
|
|
13
|
+
|
|
14
|
+
_BMLayoutEditorViewSettingsPanel.prototype = BMExtend(Object.create(_BMLayoutEditorCollectionSettingsPanel.prototype), {
|
|
15
|
+
constructor: _BMLayoutEditorViewSettingsPanel,
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The view whose settings are displayed.
|
|
19
|
+
*/
|
|
20
|
+
_displayedView: undefined, // <BMView>
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The visual attributes tab.
|
|
24
|
+
*/
|
|
25
|
+
_attributesTab: undefined, // <BMLayoutEditorSettingsTab>
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The layout tab.
|
|
29
|
+
*/
|
|
30
|
+
_layoutTab: undefined, // <BMLayoutEditorSettingsTab>
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Designated initializer. Initializes this settings panel with the given settings view.
|
|
34
|
+
* @param view <_BMLayoutSettingsView> The settings view.
|
|
35
|
+
* @return <_BMLayoutEditorSettingsPanel> This setttings panel.
|
|
36
|
+
*/
|
|
37
|
+
initWithSettingsView(settingsView, {forView: view}) {
|
|
38
|
+
_BMLayoutEditorSettingsPanel.prototype.initWithSettingsView.call(this, settingsView);
|
|
39
|
+
|
|
40
|
+
this._displayedView = view;
|
|
41
|
+
|
|
42
|
+
// Create the default tabs
|
|
43
|
+
this._attributesTab = BMLayoutEditorSettingsTab.tabWithName('Attributes', {icon: _BMURLOfImageAtPath('images/Properties.png')});
|
|
44
|
+
|
|
45
|
+
this._layoutTab = _BMLayoutEditorViewLayoutSettingsTab.viewLayoutTabForView(view);
|
|
46
|
+
|
|
47
|
+
this._currentTab = this._layoutTab;
|
|
48
|
+
|
|
49
|
+
this._tabs = [this._attributesTab, this._layoutTab, ...view.additionalSettingTabsForLayoutEditor(this.layoutEditor)];
|
|
50
|
+
|
|
51
|
+
this.title = view.debuggingName;
|
|
52
|
+
|
|
53
|
+
if (this.layoutEditor.delegate && this.layoutEditor.delegate.layoutEditorAdditionalSettingTabsForView) {
|
|
54
|
+
const additionalTabs = this.layoutEditor.delegate.layoutEditorAdditionalSettingTabsForView(this.layoutEditor, view);
|
|
55
|
+
this._tabs = this._tabs.concat(additionalTabs);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
for (const tab of this._tabs) {
|
|
59
|
+
tab._settingsPanel = this;
|
|
60
|
+
tab._view = view;
|
|
61
|
+
tab.updateSettings();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return this;
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Invoked by tabs when their settings have been invalidated and should be updated.
|
|
69
|
+
* @param tab <BMLayoutEditorSettingsTab> The tab whose settings have been invalidated.
|
|
70
|
+
*/
|
|
71
|
+
_updateSettingsForTab(tab) {
|
|
72
|
+
tab._settingSections = [];
|
|
73
|
+
|
|
74
|
+
if (tab == this._attributesTab) {
|
|
75
|
+
const view = this._displayedView;
|
|
76
|
+
|
|
77
|
+
// Add the attribute settings
|
|
78
|
+
const attributesSection = BMLayoutEditorSettingsSection.section();
|
|
79
|
+
attributesSection._settings[0] = BMLayoutEditorSetting.settingWithName('Opacity', {kind: BMLayoutEditorSettingKind.Number, target: view, variations: YES, property: 'opacity'});
|
|
80
|
+
attributesSection._settings[1] = BMLayoutEditorSetting.settingWithName('Visible', {kind: BMLayoutEditorSettingKind.Boolean, target: view, variations: YES, property: 'isVisible'});
|
|
81
|
+
attributesSection._settings[2] = BMLayoutEditorSetting.settingWithName('CSS Class', {kind: BMLayoutEditorSettingKind.String, target: view, variations: YES, property: 'CSSClass'});
|
|
82
|
+
this._attributesTab._settingSections.push(attributesSection);
|
|
83
|
+
|
|
84
|
+
const edgeInsetsSection = BMLayoutEditorSettingsSection.section();
|
|
85
|
+
edgeInsetsSection._settings[0] = BMLayoutEditorSetting.settingWithName('Content Insets', {kind: BMLayoutEditorSettingKind.Insets, target: view, variations: YES, nullable: YES, property: 'contentInsets'});
|
|
86
|
+
this._attributesTab._settingSections.push(edgeInsetsSection);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
for (const section of this._displayedView.additionalSettingSectionsForTab(tab, {layoutEditor: this.layoutEditor})) {
|
|
90
|
+
tab._settingSections.push(section);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (this.layoutEditor.delegate && this.layoutEditor.delegate.layoutEditorAdditionalSettingSectionsForTab) {
|
|
94
|
+
for (const section of this.layoutEditor.delegate.layoutEditorAdditionalSettingSectionsForTab(this.layoutEditor, tab)) {
|
|
95
|
+
tab._settingSections.push(section);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
|
|
100
|
+
// @override - BMLayoutEditorSettingsPanel
|
|
101
|
+
settingsPanelWillAppear(animated) {
|
|
102
|
+
this.layoutEditor.selectView(this._displayedView);
|
|
103
|
+
//this.layoutEditor._drawConstraintsForView(this._displayedView, {includesInactiveConstraints: this._layoutTab._showsInactiveConstraints, includesSubviewConstraints: this._layoutTab._showsSubviewConstraints});
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
// @override - BMLayoutEditorSettingsPanel
|
|
107
|
+
settingsPanelDidAppear(animated) {
|
|
108
|
+
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
// @override - BMLayoutEditorSettingsPanel
|
|
112
|
+
settingsPanelWillDisappear(animated) {
|
|
113
|
+
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
// @override - BMLayoutEditorSettingsPanel
|
|
117
|
+
settingsPanelDidDisappear(animated) {
|
|
118
|
+
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// @endtype
|
|
123
|
+
|
|
124
|
+
// @type _BMLayoutEditorViewLayoutSettingsTab
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* A specialized settings tab used for displaying view layout settings.
|
|
128
|
+
*/
|
|
129
|
+
export function _BMLayoutEditorViewLayoutSettingsTab() {} // <constructor>
|
|
130
|
+
|
|
131
|
+
_BMLayoutEditorViewLayoutSettingsTab.prototype = BMExtend(Object.create(BMLayoutEditorSettingsTab.prototype), {
|
|
132
|
+
constructor: _BMLayoutEditorViewLayoutSettingsTab,
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* The view whose constraints are displayed.
|
|
136
|
+
*/
|
|
137
|
+
_displayedView: undefined, // <BMView>
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Controls whether subview constraints are displayed.
|
|
141
|
+
*/
|
|
142
|
+
_showsSubviewConstraints: YES, // <Boolean>
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* The categories of the view's own constraints.
|
|
146
|
+
*/
|
|
147
|
+
_constraintCategories: undefined, // <Object<String, [BMLayoutConstraint]>
|
|
148
|
+
|
|
149
|
+
get showsSubviewConstraints() {
|
|
150
|
+
return this._showsSubviewConstraints;
|
|
151
|
+
},
|
|
152
|
+
set showsSubviewConstraints(shows) {
|
|
153
|
+
this._showsSubviewConstraints = shows;
|
|
154
|
+
this._updateSettings();
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Controls whether inactive constraints are displayed.
|
|
159
|
+
*/
|
|
160
|
+
_showsInactiveConstraints: NO, // <Boolean>
|
|
161
|
+
|
|
162
|
+
get showsInactiveConstraints() {
|
|
163
|
+
return this._showsInactiveConstraints;
|
|
164
|
+
},
|
|
165
|
+
set showsInactiveConstraints(shows) {
|
|
166
|
+
this._showsInactiveConstraints = shows;
|
|
167
|
+
this._updateSettings();
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Controls which types of constraints are displayed by this tab.
|
|
172
|
+
*/
|
|
173
|
+
get _displayMode() { // <String>
|
|
174
|
+
if (this._showsInactiveConstraints && this._showsSubviewConstraints) return 'all';
|
|
175
|
+
if (this._showsInactiveConstraints) return 'inactive';
|
|
176
|
+
if (this._showsSubviewConstraints) return 'subview';
|
|
177
|
+
return 'own';
|
|
178
|
+
},
|
|
179
|
+
set _displayMode(mode) {
|
|
180
|
+
if (mode == 'all') {
|
|
181
|
+
this._showsSubviewConstraints = YES;
|
|
182
|
+
this.showsInactiveConstraints = YES;
|
|
183
|
+
}
|
|
184
|
+
else if (mode == 'subview') {
|
|
185
|
+
this._showsInactiveConstraints = NO;
|
|
186
|
+
this.showsSubviewConstraints = YES;
|
|
187
|
+
}
|
|
188
|
+
else if (mode == 'inactive') {
|
|
189
|
+
this._showsInactiveConstraints = YES;
|
|
190
|
+
this.showsSubviewConstraints = YES;
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
this._showsSubviewConstraints = YES;
|
|
194
|
+
this.showsInactiveConstraints = NO;
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Designated initializer. Initializes this view layout tab for the specified view.
|
|
200
|
+
* @param view <BMView> The view whose constraints will be displayed.
|
|
201
|
+
*/
|
|
202
|
+
initWithView(view) {
|
|
203
|
+
BMLayoutEditorSettingsTab.prototype.initWithName.call(this, 'Layout', {icon: _BMURLOfImageAtPath('images/Layout.png')});
|
|
204
|
+
this._displayedView = view;
|
|
205
|
+
|
|
206
|
+
return this;
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
// @override - BMLayoutEditorSettingsTab
|
|
210
|
+
updateSettings() {
|
|
211
|
+
this._updateSettings();
|
|
212
|
+
},
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Updates the visible constraints.
|
|
216
|
+
* If this tab is visible, it also updates the displayed constraints.
|
|
217
|
+
*/
|
|
218
|
+
_updateSettings() {
|
|
219
|
+
const view = this._displayedView;
|
|
220
|
+
|
|
221
|
+
this.beginUpdates();
|
|
222
|
+
|
|
223
|
+
this._settingSections.length = 0;
|
|
224
|
+
|
|
225
|
+
if (this._intrinsicResistanceSection) {
|
|
226
|
+
if (view.supportsIntrinsicSize) this._settingSections.push(this._intrinsicResistanceSection);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
const intrinsicResistanceSection = BMLayoutEditorSettingsSection.section();
|
|
230
|
+
this._intrinsicResistanceSection = intrinsicResistanceSection;
|
|
231
|
+
intrinsicResistanceSection.name = 'Intrinsic Size Resistance';
|
|
232
|
+
intrinsicResistanceSection._settings[0] = BMLayoutEditorSetting.settingWithName('Compression', {kind: BMLayoutEditorSettingKind.Integer, target: view, property: 'compressionResistance'});
|
|
233
|
+
intrinsicResistanceSection._settings[1] = BMLayoutEditorSetting.settingWithName('Expansion', {kind: BMLayoutEditorSettingKind.Integer, target: view, property: 'expansionResistance'});
|
|
234
|
+
if (view.supportsIntrinsicSize) this._settingSections.push(intrinsicResistanceSection);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
this._settingsPanel._updateSettingsForTab(this);
|
|
238
|
+
|
|
239
|
+
/*
|
|
240
|
+
if (this._intrinsicSizeSection) {
|
|
241
|
+
if (view.supportsIntrinsicSize) this._settingSections.push(this._intrinsicSizeSection);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
const intrinsicSizeSection = BMLayoutEditorSettingsSection.section();
|
|
245
|
+
this._intrinsicSizeSection = intrinsicSizeSection;
|
|
246
|
+
intrinsicSizeSection._settings[0] = BMLayoutEditorSetting.settingWithName('Intrinsic Size', {kind: BMLayoutEditorSettingKind.Info, target: view, property: 'supportsIntrinsicSize'});
|
|
247
|
+
if (view.supportsIntrinsicSize) this._settingSections.push(intrinsicSizeSection);
|
|
248
|
+
}
|
|
249
|
+
*/
|
|
250
|
+
|
|
251
|
+
const constraintViewPicker = this._constraintViewPickerSection || BMLayoutEditorSettingsSection.section();
|
|
252
|
+
this._constraintViewPickerSection = constraintViewPicker;
|
|
253
|
+
constraintViewPicker.name = 'Show';
|
|
254
|
+
constraintViewPicker._settings[0] = BMLayoutEditorEnumSetting.settingWithName('Show', {kind: BMLayoutEditorSettingKind.Segment, target: this, property: '_displayMode'});
|
|
255
|
+
constraintViewPicker._settings[0].options = [
|
|
256
|
+
BMMenuItem.menuItemWithName('This Size Class', {icon: _BMURLOfImageAtPath('images/OwnConstraints.png'), userInfo: 'subview'}),
|
|
257
|
+
//BMMenuItem.menuItemWithName('Subview Constraints', {icon: _BMURLOfImageAtPath('images/SubviewConstraints.png'), userInfo: 'subview'}),
|
|
258
|
+
BMMenuItem.menuItemWithName('All Size Classes', {icon: _BMURLOfImageAtPath('images/InactiveConstraints.png'), userInfo: 'inactive'}),
|
|
259
|
+
//BMMenuItem.menuItemWithName('All Constraints', {icon: _BMURLOfImageAtPath('images/AllConstraints.png'), userInfo: 'all'})
|
|
260
|
+
];
|
|
261
|
+
this._settingSections.push(constraintViewPicker);
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
// View constraints will be split into four groups:
|
|
265
|
+
//
|
|
266
|
+
// 1. Visible by default and non-collapsible will be the constraints that directly affect the view,
|
|
267
|
+
// or link the view to its siblings or ancestors
|
|
268
|
+
//
|
|
269
|
+
// 2. A second, collapsed by default group, will show the constraints that link the view to its descendants - This is currently no longer active and subview constraints are now merged into group 1
|
|
270
|
+
//
|
|
271
|
+
// 3. A third, collapsed by default group, will show the inactive constraints
|
|
272
|
+
//
|
|
273
|
+
// 4. A final group shows the view's internal constraints in a read-only mode
|
|
274
|
+
let constraintCategoryMap = {};
|
|
275
|
+
let subviewConstraintCategoryMap = {};
|
|
276
|
+
let inactiveConstraintsMap = {};
|
|
277
|
+
let hasSubviewConstraints = NO;
|
|
278
|
+
let hasInactiveConstraints = NO;
|
|
279
|
+
|
|
280
|
+
// Split up the constraints into the various categories
|
|
281
|
+
view.localConstraints.forEach(constraint => {
|
|
282
|
+
let category = constraint.categoryKind;
|
|
283
|
+
|
|
284
|
+
if (!constraint._configuration.isActive) {
|
|
285
|
+
hasInactiveConstraints = YES;
|
|
286
|
+
inactiveConstraintsMap[category] = inactiveConstraintsMap[category] || [];
|
|
287
|
+
inactiveConstraintsMap[category].push(constraint);
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/*if (!constraint._isConstraintCollection) {
|
|
292
|
+
// Push subview constraints into their own categories
|
|
293
|
+
if (constraint._sourceView == view && constraint._targetView && constraint._targetView.isDescendantOfView(view)) {
|
|
294
|
+
subviewConstraintCategoryMap[category] = subviewConstraintCategoryMap[category] || [];
|
|
295
|
+
subviewConstraintCategoryMap[category].push(constraint);
|
|
296
|
+
hasSubviewConstraints = YES;
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (constraint._targetView == view && constraint._sourceView.isDescendantOfView(view)) {
|
|
300
|
+
subviewConstraintCategoryMap[category] = subviewConstraintCategoryMap[category] || [];
|
|
301
|
+
subviewConstraintCategoryMap[category].push(constraint);
|
|
302
|
+
hasSubviewConstraints = YES;
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
}*/
|
|
306
|
+
|
|
307
|
+
constraintCategoryMap[category] = constraintCategoryMap[category] || [];
|
|
308
|
+
constraintCategoryMap[category].push(constraint);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
for (const category of Object.keys(constraintCategoryMap).sort()) {
|
|
312
|
+
const section = this[`_${category}`] || BMLayoutEditorSettingsSection.section();
|
|
313
|
+
this[`_${category}`] = section;
|
|
314
|
+
section.length = 0;
|
|
315
|
+
section.name = category + ' Constraints';
|
|
316
|
+
section._settings = constraintCategoryMap[category].map(constraint => BMLayoutEditorSetting.settingWithName(constraint.toString(), {kind: BMLayoutEditorSettingKind.Constraint, target: constraint}));
|
|
317
|
+
|
|
318
|
+
this._settingSections.push(section);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
this._constraintCategories = constraintCategoryMap;
|
|
322
|
+
|
|
323
|
+
//---------------------------------------------------------------------------------------------------------
|
|
324
|
+
if (hasSubviewConstraints && this._showsSubviewConstraints) {
|
|
325
|
+
for (const category of Object.keys(subviewConstraintCategoryMap).sort()) {
|
|
326
|
+
const categoryName = '_subview' + category;
|
|
327
|
+
const section = this[categoryName] || BMLayoutEditorSettingsSection.section();
|
|
328
|
+
this[categoryName] = section;
|
|
329
|
+
section.length = 0;
|
|
330
|
+
section.name = 'Subview ' + category + ' Constraints';
|
|
331
|
+
section._settings = subviewConstraintCategoryMap[category].map(constraint => BMLayoutEditorSetting.settingWithName(constraint.toString(), {kind: BMLayoutEditorSettingKind.Constraint, target: constraint}));
|
|
332
|
+
|
|
333
|
+
this._settingSections.push(section);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
//---------------------------------------------------------------------------------------------------------
|
|
338
|
+
if (hasInactiveConstraints && this._showsInactiveConstraints) {
|
|
339
|
+
for (const category of Object.keys(inactiveConstraintsMap).sort()) {
|
|
340
|
+
const categoryName = '_inactive' + category;
|
|
341
|
+
const section = this[category] || BMLayoutEditorSettingsSection.section();
|
|
342
|
+
this[category] = section;
|
|
343
|
+
section.length = 0;
|
|
344
|
+
section.name = 'Inactive ' + category + ' Constraints';
|
|
345
|
+
section._settings = inactiveConstraintsMap[category].map(constraint => BMLayoutEditorSetting.settingWithName(constraint.toString(), {kind: BMLayoutEditorSettingKind.Constraint, target: constraint}));
|
|
346
|
+
|
|
347
|
+
this._settingSections.push(section);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
//---------------------------------------------------------------------------------------------------------
|
|
352
|
+
let internalConstraints = view.internalConstraints();
|
|
353
|
+
if (internalConstraints.length) {
|
|
354
|
+
const section = this._internalConstraintsSection || BMLayoutEditorSettingsSection.section();
|
|
355
|
+
this._internalConstraintsSection = section;
|
|
356
|
+
section.length = 0;
|
|
357
|
+
section.name = 'Internal Constraints';
|
|
358
|
+
section._settings = internalConstraints.map(constraint => BMLayoutEditorSetting.settingWithName(constraint.toString(), {kind: BMLayoutEditorSettingKind.Constraint, target: constraint}));
|
|
359
|
+
|
|
360
|
+
this._settingSections.push(section);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (this.layoutEditor) this.layoutEditor._drawConstraintsForView(this._displayedView, {includesInactiveConstraints: this._showsInactiveConstraints, includesSubviewConstraints: this._showsSubviewConstraints});
|
|
364
|
+
|
|
365
|
+
const deactivateConstraintsSection = BMLayoutEditorSettingsSection.section();
|
|
366
|
+
deactivateConstraintsSection._settings[0] = BMLayoutEditorSetting.settingWithName('Deactivate Constraints', {kind: BMLayoutEditorSettingKind.DeactivateConstraintsButton, target: this});
|
|
367
|
+
this._settingSections.push(deactivateConstraintsSection);
|
|
368
|
+
|
|
369
|
+
this.commitUpdates();
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Constructs and returns a view layout settings tab for the given view.
|
|
375
|
+
* @param view <BMView> The view whose constraints will be displayed.
|
|
376
|
+
* @return <_BMLayoutEditorViewLayoutSettingsTab> A view layout settings tab.
|
|
377
|
+
*/
|
|
378
|
+
_BMLayoutEditorViewLayoutSettingsTab.viewLayoutTabForView = function (view) {
|
|
379
|
+
return (new _BMLayoutEditorViewLayoutSettingsTab).initWithView(view);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// @endtype
|