1
0
mirror of https://github.com/beestat/app.git synced 2025-07-09 03:04:07 -04:00

Added undo/redo

This commit is contained in:
Jon Ziebell 2022-08-09 09:05:34 -04:00
parent 0572527d6f
commit 46340a3dd8
7 changed files with 324 additions and 50 deletions

View File

@ -443,6 +443,7 @@ input[type=radio] {
.icon.cloud_question:before { content: "\F0A39"; } .icon.cloud_question:before { content: "\F0A39"; }
.icon.code_tags:before { content: "\F0174"; } .icon.code_tags:before { content: "\F0174"; }
.icon.cog:before { content: "\F0493"; } .icon.cog:before { content: "\F0493"; }
.icon.delete:before { content: "\F01B4"; }
.icon.dots_vertical:before { content: "\F01D9"; } .icon.dots_vertical:before { content: "\F01D9"; }
.icon.download:before { content: "\F01DA"; } .icon.download:before { content: "\F01DA"; }
.icon.earth:before { content: "\F01E7"; } .icon.earth:before { content: "\F01E7"; }
@ -500,7 +501,10 @@ input[type=radio] {
.icon.numeric_9_box:before { content: "\F03BC"; } .icon.numeric_9_box:before { content: "\F03BC"; }
.icon.open_in_new:before { content: "\F03CC"; } .icon.open_in_new:before { content: "\F03CC"; }
.icon.patreon:before { content: "\F0882"; } .icon.patreon:before { content: "\F0882"; }
.icon.pencil:before { content: "\F03EB"; }
.icon.plus:before { content: "\F0415"; }
.icon.pound:before { content: "\F0423"; } .icon.pound:before { content: "\F0423"; }
.icon.redo:before { content: "\F044E"; }
.icon.refresh:before { content: "\F0450"; } .icon.refresh:before { content: "\F0450"; }
.icon.resistor:before { content: "\F0B44"; } .icon.resistor:before { content: "\F0B44"; }
.icon.snowflake:before { content: "\F0717"; } .icon.snowflake:before { content: "\F0717"; }
@ -509,6 +513,7 @@ input[type=radio] {
.icon.thumb_up:before { content: "\F0513"; } .icon.thumb_up:before { content: "\F0513"; }
.icon.tune:before { content: "\F062E"; } .icon.tune:before { content: "\F062E"; }
.icon.twitter:before { content: "\F0544"; } .icon.twitter:before { content: "\F0544"; }
.icon.undo:before { content: "\F054C"; }
.icon.update:before { content: "\F06B0"; } .icon.update:before { content: "\F06B0"; }
.icon.vector_square_plus:before { content: "\F18DB"; } .icon.vector_square_plus:before { content: "\F18DB"; }
.icon.vector_square_remove:before { content: "\F18DC"; } .icon.vector_square_remove:before { content: "\F18DC"; }
@ -530,9 +535,6 @@ input[type=radio] {
.icon.wifi_strength_1_alert:before { content: "\F0920"; } .icon.wifi_strength_1_alert:before { content: "\F0920"; }
.icon.wifi_strength_4:before { content: "\F0928"; } .icon.wifi_strength_4:before { content: "\F0928"; }
.icon.zigbee:before { content: "\F0D41"; } .icon.zigbee:before { content: "\F0D41"; }
.icon.pencil:before { content: "\F03EB"; }
.icon.plus:before { content: "\F0415"; }
.icon.delete:before { content: "\F01B4"; }
.icon.f16:before { font-size: 16px; } .icon.f16:before { font-size: 16px; }
.icon.f24:before { font-size: 24px; } .icon.f24:before { font-size: 24px; }

View File

@ -8,6 +8,7 @@ beestat.component.card.floor_plan_editor = function(thermostat_id) {
this.thermostat_id_ = thermostat_id; this.thermostat_id_ = thermostat_id;
var change_function = beestat.debounce(function() { var change_function = beestat.debounce(function() {
// todo replace these with (if entity set active false?)
delete self.state_.active_group; delete self.state_.active_group;
delete self.state_.active_room; delete self.state_.active_room;
@ -71,10 +72,42 @@ beestat.component.card.floor_plan_editor.prototype.decorate_contents_ = function
center_container.appendChild(get_started_button); center_container.appendChild(get_started_button);
} else { } else {
const floor_plan = beestat.cache.floor_plan[beestat.setting('floor_plan_id')]; const floor_plan = beestat.cache.floor_plan[beestat.setting('floor_plan_id')];
if (this.state_.active_group === undefined) {
this.state_.active_group = floor_plan.data.groups[0]; // Set group ids if they are not set.
floor_plan.data.groups.forEach(function(group) {
if (group.group_id === undefined) {
group.group_id = window.crypto.randomUUID();
}
});
/**
* If there is an active_group_id, override whatever the current active
* group is. Used for undo/redo.
*/
if (this.state_.active_group_id !== undefined) {
for (let i = 0; i < floor_plan.data.groups.length; i++) {
if (floor_plan.data.groups[i].group_id === this.state_.active_group_id) {
this.state_.active_group = floor_plan.data.groups[i];
delete this.state_.active_group_id;
break;
}
}
} }
// If there is no active group, set it to best guess of ground floor.
if (this.state_.active_group === undefined) {
let closest_distance = Infinity;
let closest_group;
floor_plan.data.groups.forEach(function(group) {
if (Math.abs(group.elevation) < closest_distance) {
closest_group = group;
closest_distance = Math.abs(group.elevation);
}
});
this.state_.active_group = closest_group;
}
// Decorate everything.
const drawing_pane_container = $.createElement('div'); const drawing_pane_container = $.createElement('div');
drawing_pane_container.style({ drawing_pane_container.style({
'position': 'relative', 'position': 'relative',
@ -135,7 +168,14 @@ beestat.component.card.floor_plan_editor.prototype.decorate_drawing_pane_ = func
self.update_floor_plan_(); self.update_floor_plan_();
self.rerender(); self.rerender();
}); });
this.floor_plan_.addEventListener('clear_room', self.rerender.bind(this)); this.floor_plan_.addEventListener('undo', function() {
self.update_floor_plan_();
self.rerender();
});
this.floor_plan_.addEventListener('redo', function() {
self.update_floor_plan_();
self.rerender();
});
this.floor_plan_.addEventListener('change_group', self.rerender.bind(this)); this.floor_plan_.addEventListener('change_group', self.rerender.bind(this));
// Add all of the entities to the SVG. // Add all of the entities to the SVG.
@ -170,17 +210,28 @@ beestat.component.card.floor_plan_editor.prototype.decorate_drawing_pane_ = func
// Update GUI when a room is selected. // Update GUI when a room is selected.
room_entity.addEventListener('activate', function() { room_entity.addEventListener('activate', function() {
self.floor_plan_.update_infobox(); self.floor_plan_.update_infobox();
self.floor_plan_.update_toolbar();
self.update_info_pane_();
});
// Update GUI when a room is deselected.
room_entity.addEventListener('inactivate', function() {
self.floor_plan_.update_infobox();
self.floor_plan_.update_toolbar();
self.update_info_pane_(); self.update_info_pane_();
}); });
// Activate the currently active room (mostly for rerenders). // Activate the currently active room (mostly for rerenders).
if (room === self.state_.active_room) { if (
self.state_.active_room_entity !== undefined &&
room.room_id === self.state_.active_room_entity.get_room().room_id
) {
room_entity.set_active(true); room_entity.set_active(true);
} else {
// Render the room and save to the list of current entities.
room_entity.render(self.floor_plan_.get_g());
self.entities_.room.push(room_entity);
} }
// Render the room and save to the list of current entities.
room_entity.render(self.floor_plan_.get_g());
self.entities_.room.push(room_entity);
}); });
/** /**
@ -489,6 +540,8 @@ beestat.component.card.floor_plan_editor.prototype.get_subtitle_ = function() {
* only run so fast. * only run so fast.
*/ */
beestat.component.card.floor_plan_editor.prototype.update_floor_plan_ = function() { beestat.component.card.floor_plan_editor.prototype.update_floor_plan_ = function() {
const self = this;
window.clearTimeout(this.update_timeout_); window.clearTimeout(this.update_timeout_);
this.update_timeout_ = window.setTimeout(function() { this.update_timeout_ = window.setTimeout(function() {
new beestat.api() new beestat.api()
@ -498,7 +551,7 @@ beestat.component.card.floor_plan_editor.prototype.update_floor_plan_ = function
{ {
'attributes': { 'attributes': {
'floor_plan_id': beestat.setting('floor_plan_id'), 'floor_plan_id': beestat.setting('floor_plan_id'),
'data': beestat.cache.floor_plan[beestat.setting('floor_plan_id')].data 'data': self.get_floor_plan_data_(beestat.setting('floor_plan_id'))
} }
}, },
'update_floor_plan' 'update_floor_plan'
@ -507,6 +560,25 @@ beestat.component.card.floor_plan_editor.prototype.update_floor_plan_ = function
}, 1000); }, 1000);
}; };
/**
* Get floor plan data with UUIDs stripped.
*
* @param {number} floor_plan_id Floor plan ID
*
* @return {object} The modified floor plan data.
*/
beestat.component.card.floor_plan_editor.prototype.get_floor_plan_data_ = function(floor_plan_id) {
const floor_plan = beestat.cache.floor_plan[floor_plan_id];
const data = beestat.clone(floor_plan.data);
data.groups.forEach(function(group) {
delete group.group_id;
group.rooms.forEach(function(room) {
delete room.room_id;
});
});
return data;
};
/** /**
* Decorate the menu. * Decorate the menu.
* *
@ -557,7 +629,6 @@ beestat.component.card.floor_plan_editor.prototype.decorate_top_right_ = functio
).render(); ).render();
})); }));
} }
} }
menu.add_menu_item(new beestat.component.menu_item() menu.add_menu_item(new beestat.component.menu_item()

View File

@ -132,7 +132,12 @@ beestat.component.floor_plan.prototype.render = function(parent) {
e.key.toLowerCase() === 'z' && e.key.toLowerCase() === 'z' &&
e.ctrlKey === true e.ctrlKey === true
) { ) {
console.log('undo'); self.undo_();
} else if (
e.key.toLowerCase() === 'y' &&
e.ctrlKey === true
) {
self.redo_();
} else if ( } else if (
e.key === 'ArrowLeft' || e.key === 'ArrowLeft' ||
e.key === 'ArrowRight' || e.key === 'ArrowRight' ||
@ -150,16 +155,16 @@ beestat.component.floor_plan.prototype.render = function(parent) {
switch (e.key) { switch (e.key) {
case 'ArrowLeft': case 'ArrowLeft':
entity.set_xy(x === null ? null : x - 1, y); entity.set_xy(x === null ? null : x - 1, y, 'update');
break; break;
case 'ArrowRight': case 'ArrowRight':
entity.set_xy(x === null ? null : x + 1, y); entity.set_xy(x === null ? null : x + 1, y, 'update');
break; break;
case 'ArrowUp': case 'ArrowUp':
entity.set_xy(x, y === null ? null : y - 1); entity.set_xy(x, y === null ? null : y - 1, 'update');
break; break;
case 'ArrowDown': case 'ArrowDown':
entity.set_xy(x, y === null ? null : y + 1); entity.set_xy(x, y === null ? null : y + 1, 'update');
break; break;
} }
} }
@ -492,6 +497,48 @@ beestat.component.floor_plan.prototype.update_toolbar = function() {
.addEventListener('click', this.toggle_snapping_.bind(this)) .addEventListener('click', this.toggle_snapping_.bind(this))
); );
// Undo
const undo_button = new beestat.component.tile()
.set_icon('undo')
.set_title('Undo [Ctrl+Z]')
.set_background_color(beestat.style.color.bluegray.base);
this.button_group_.add_button(undo_button);
if (
this.can_undo_() === true
) {
undo_button
.set_background_hover_color(beestat.style.color.bluegray.light)
.set_text_color(beestat.style.color.gray.light)
.addEventListener('click', function() {
self.undo_();
});
} else {
undo_button
.set_text_color(beestat.style.color.bluegray.dark);
}
// Redo
const redo_button = new beestat.component.tile()
.set_icon('redo')
.set_title('redo [Ctrl+Y]')
.set_background_color(beestat.style.color.bluegray.base);
this.button_group_.add_button(redo_button);
if (
this.can_redo_() === true
) {
redo_button
.set_background_hover_color(beestat.style.color.bluegray.light)
.set_text_color(beestat.style.color.gray.light)
.addEventListener('click', function() {
self.redo_();
});
} else {
redo_button
.set_text_color(beestat.style.color.bluegray.dark);
}
// Zoom in // Zoom in
const zoom_in_button = new beestat.component.tile() const zoom_in_button = new beestat.component.tile()
.set_icon('magnify_plus_outline') .set_icon('magnify_plus_outline')
@ -624,12 +671,15 @@ beestat.component.floor_plan.prototype.toggle_snapping_ = function() {
* @param {object} room Optional room to copy from. * @param {object} room Optional room to copy from.
*/ */
beestat.component.floor_plan.prototype.add_room_ = function(room) { beestat.component.floor_plan.prototype.add_room_ = function(room) {
this.save_buffer();
const svg_view_box = this.view_box_; const svg_view_box = this.view_box_;
let new_room; let new_room;
if (room === undefined) { if (room === undefined) {
const new_room_size = 120; const new_room_size = 120;
new_room = { new_room = {
'room_id': window.crypto.randomUUID(),
'x': svg_view_box.x + (svg_view_box.width / 2) - (new_room_size / 2), 'x': svg_view_box.x + (svg_view_box.width / 2) - (new_room_size / 2),
'y': svg_view_box.y + (svg_view_box.height / 2) - (new_room_size / 2), 'y': svg_view_box.y + (svg_view_box.height / 2) - (new_room_size / 2),
'points': [ 'points': [
@ -665,6 +715,7 @@ beestat.component.floor_plan.prototype.add_room_ = function(room) {
}); });
new_room = { new_room = {
'room_id': window.crypto.randomUUID(),
'x': svg_view_box.x + (svg_view_box.width / 2) - ((max_x - min_x) / 2), 'x': svg_view_box.x + (svg_view_box.width / 2) - ((max_x - min_x) / 2),
'y': svg_view_box.y + (svg_view_box.height / 2) - ((max_y - min_y) / 2), 'y': svg_view_box.y + (svg_view_box.height / 2) - ((max_y - min_y) / 2),
'points': beestat.clone(room.points) 'points': beestat.clone(room.points)
@ -672,11 +723,10 @@ beestat.component.floor_plan.prototype.add_room_ = function(room) {
} }
this.state_.active_group.rooms.push(new_room); this.state_.active_group.rooms.push(new_room);
this.state_.active_room = new_room; new beestat.component.floor_plan_entity.room(this, this.state_)
.set_room(new_room)
if (this.state_.active_point_entity !== undefined) { .set_group(this.state_.active_group)
this.state_.active_point_entity.set_active(false); .set_active(true);
}
this.dispatchEvent('add_room'); this.dispatchEvent('add_room');
}; };
@ -685,6 +735,8 @@ beestat.component.floor_plan.prototype.add_room_ = function(room) {
* Remove the currently active room. * Remove the currently active room.
*/ */
beestat.component.floor_plan.prototype.remove_room_ = function() { beestat.component.floor_plan.prototype.remove_room_ = function() {
this.save_buffer();
const self = this; const self = this;
const index = this.state_.active_group.rooms.findIndex(function(active_room) { const index = this.state_.active_group.rooms.findIndex(function(active_room) {
@ -718,13 +770,14 @@ beestat.component.floor_plan.prototype.clear_room_ = function() {
if (this.state_.active_point_entity !== undefined) { if (this.state_.active_point_entity !== undefined) {
this.state_.active_point_entity.set_active(false); this.state_.active_point_entity.set_active(false);
} }
this.dispatchEvent('clear_room');
}; };
/** /**
* Remove the currently active point. * Remove the currently active point.
*/ */
beestat.component.floor_plan.prototype.remove_point_ = function() { beestat.component.floor_plan.prototype.remove_point_ = function() {
this.save_buffer();
if (this.state_.active_room.points.length > 3) { if (this.state_.active_room.points.length > 3) {
for (let i = 0; i < this.state_.active_room.points.length; i++) { for (let i = 0; i < this.state_.active_room.points.length; i++) {
if (this.state_.active_point === this.state_.active_room.points[i]) { if (this.state_.active_point === this.state_.active_room.points[i]) {
@ -934,3 +987,121 @@ beestat.component.floor_plan.prototype.center_content = function() {
this.update_view_box_(); this.update_view_box_();
} }
}; };
/**
* Save the current state to the undo/redo buffer.
*
* @param {boolean} clear Whether or not to allow clearing future buffer
* entries.
*/
beestat.component.floor_plan.prototype.save_buffer = function(clear = true) {
const buffer_size = 1000;
if (this.state_.buffer === undefined) {
this.state_.buffer = [];
this.state_.buffer_pointer = 0;
}
// If the buffer pointer is not at the end, clear those out.
if (
clear === true &&
this.state_.buffer_pointer !== this.state_.buffer.length + 1
) {
this.state_.buffer.length = this.state_.buffer_pointer;
}
this.state_.buffer.push({
'floor_plan': beestat.clone(beestat.cache.floor_plan[beestat.setting('floor_plan_id')]),
'active_room_entity': this.state_.active_room_entity,
'active_group_id': this.state_.active_group.group_id
});
// If the buffer gets too long shrink it.
if (this.state_.buffer.length > buffer_size) {
this.state_.buffer.shift();
}
/**
* Update the buffer pointer. It always points at the index where the next
* buffer write will happen.
*/
this.state_.buffer_pointer = this.state_.buffer.length;
this.update_toolbar();
};
/**
* Undo
*/
beestat.component.floor_plan.prototype.undo_ = function() {
if (this.can_undo_() === true) {
/**
* When undoing, first save the buffer if the pointer is at the end to
* capture the current state then shift the buffer pointer back an extra.
*/
if (this.state_.buffer_pointer === this.state_.buffer.length) {
this.save_buffer(false);
this.state_.buffer_pointer--;
}
// Decrement buffer pointer back to the previous row.
this.state_.buffer_pointer--;
// Restore the floor plan.
beestat.cache.floor_plan[this.floor_plan_id_] =
beestat.clone(this.state_.buffer[this.state_.buffer_pointer].floor_plan);
// Restore any active room.
this.state_.active_room_entity =
this.state_.buffer[this.state_.buffer_pointer].active_room_entity;
// Restore any active group.
this.state_.active_group_id =
this.state_.buffer[this.state_.buffer_pointer].active_group_id;
this.update_toolbar();
this.dispatchEvent('undo');
}
};
/**
* Whether or not you can undo.
*
* @return {boolean}
*/
beestat.component.floor_plan.prototype.can_undo_ = function() {
return this.state_.buffer_pointer > 0;
};
/**
* Redo
*/
beestat.component.floor_plan.prototype.redo_ = function() {
if (this.can_redo_() === true) {
this.state_.buffer_pointer++;
// Restore the floor plan.
beestat.cache.floor_plan[this.floor_plan_id_] =
beestat.clone(this.state_.buffer[this.state_.buffer_pointer].floor_plan);
// Restore any active room.
this.state_.active_room_entity =
this.state_.buffer[this.state_.buffer_pointer].active_room_entity;
// Restore any active group.
this.state_.active_group_id =
this.state_.buffer[this.state_.buffer_pointer].active_group_id;
this.update_toolbar();
this.dispatchEvent('redo');
}
};
/**
* Whether or not you can redo.
*
* @return {boolean}
*/
beestat.component.floor_plan.prototype.can_redo_ = function() {
return this.state_.buffer !== undefined &&
this.state_.buffer_pointer + 1 < this.state_.buffer.length;
};

View File

@ -189,6 +189,7 @@ beestat.component.floor_plan_entity.prototype.mousemove_handler_ = function(e) {
if (this.dragged_ === false) { if (this.dragged_ === false) {
this.dispatchEvent('drag_start'); this.dispatchEvent('drag_start');
this.dragged_ = true; this.dragged_ = true;
this.floor_plan_.save_buffer();
} }
this.after_mousemove_handler_(e); this.after_mousemove_handler_(e);
@ -218,6 +219,7 @@ beestat.component.floor_plan_entity.prototype.mouseup_handler_ = function(e) {
// If the mouse was actually moved at all then fire the drag stop event. // If the mouse was actually moved at all then fire the drag stop event.
if (this.dragged_ === true) { if (this.dragged_ === true) {
this.dispatchEvent('drag_stop'); this.dispatchEvent('drag_stop');
this.dispatchEvent('update');
} }
this.after_mouseup_handler_(e); this.after_mouseup_handler_(e);

View File

@ -15,7 +15,6 @@ beestat.extend(beestat.component.floor_plan_entity.point, beestat.component.floo
*/ */
beestat.component.floor_plan_entity.point.prototype.decorate_ = function(parent) { beestat.component.floor_plan_entity.point.prototype.decorate_ = function(parent) {
this.decorate_rect_(parent); this.decorate_rect_(parent);
this.set_draggable_(true); this.set_draggable_(true);
}; };
@ -125,10 +124,15 @@ beestat.component.floor_plan_entity.point.prototype.set_room = function(room) {
* *
* @param {number} x The x position of this entity. * @param {number} x The x position of this entity.
* @param {number} y The y position of this entity. * @param {number} y The y position of this entity.
* @param {string} event Optional event to fire when done.
* *
* @return {beestat.component.floor_plan_entity.point} This. * @return {beestat.component.floor_plan_entity.point} This.
*/ */
beestat.component.floor_plan_entity.point.prototype.set_xy = function(x, y) { beestat.component.floor_plan_entity.point.prototype.set_xy = function(x, y, event = 'lesser_update') {
if (event === 'update') {
this.floor_plan_.save_buffer();
}
let clamped_x = x + this.room_.get_x(); let clamped_x = x + this.room_.get_x();
let clamped_y = y + this.room_.get_y(); let clamped_y = y + this.room_.get_y();
@ -146,7 +150,7 @@ beestat.component.floor_plan_entity.point.prototype.set_xy = function(x, y) {
this.update_rect_(); this.update_rect_();
this.dispatchEvent('update'); this.dispatchEvent(event);
return this; return this;
}; };
@ -349,6 +353,8 @@ beestat.component.floor_plan_entity.point.prototype.set_active = function(active
} else { } else {
delete this.state_.active_point; delete this.state_.active_point;
delete this.state_.active_point_entity; delete this.state_.active_point_entity;
this.dispatchEvent('inactivate');
} }
if (this.rendered_ === true) { if (this.rendered_ === true) {

View File

@ -111,18 +111,17 @@ beestat.component.floor_plan_entity.prototype.decorate_points_ = function(parent
.render(parent); .render(parent);
// Update when a point is moved // Update when a point is moved
point_entity.addEventListener('update', function() { point_entity.addEventListener('lesser_update', function() {
self.update_polygon_(); self.update_polygon_();
self.update_walls_(); self.update_walls_();
self.dispatchEvent('update');
}); });
// When a point is done moving normalize the points // When a point is done moving normalize the points
point_entity.addEventListener('drag_stop', function() { point_entity.addEventListener('update', function() {
self.normalize_points_(); self.normalize_points_();
self.update_points_(); self.update_points_();
self.update_walls_();
self.update_polygon_(); self.update_polygon_();
self.update_walls_();
self.update_snap_points_(); self.update_snap_points_();
self.dispatchEvent('update'); self.dispatchEvent('update');
}); });
@ -174,25 +173,16 @@ beestat.component.floor_plan_entity.prototype.decorate_walls_ = function(parent)
.render(parent); .render(parent);
self.walls_.push(wall_entity); self.walls_.push(wall_entity);
wall_entity.addEventListener('update', function() { wall_entity.addEventListener('lesser_update', function() {
self.update_polygon_(); self.update_polygon_();
self.update_points_(); self.update_points_();
self.update_walls_(); self.update_walls_();
self.dispatchEvent('update');
}); });
// Clear any active points on drag start. wall_entity.addEventListener('update', function() {
wall_entity.addEventListener('drag_start', function() {
if (self.active_point_entity_ !== undefined) {
self.active_point_entity_.set_active(false);
delete self.active_point_entity_;
}
});
wall_entity.addEventListener('drag_stop', function() {
self.normalize_points_(); self.normalize_points_();
self.update_polygon_();
self.update_points_(); self.update_points_();
self.update_polygon_();
self.update_walls_(); self.update_walls_();
self.update_snap_points_(); self.update_snap_points_();
self.dispatchEvent('update'); self.dispatchEvent('update');
@ -240,6 +230,20 @@ beestat.component.floor_plan_entity.prototype.update_walls_ = function() {
* @return {beestat.component.floor_plan_entity.room} This. * @return {beestat.component.floor_plan_entity.room} This.
*/ */
beestat.component.floor_plan_entity.room.prototype.set_active = function(active) { beestat.component.floor_plan_entity.room.prototype.set_active = function(active) {
/**
* Always clear the active point and wall when clicking on a room, even if
* it's already active. Also force a toolbar update. This is a little hacky
* but works.
*/
if (this.state_.active_point_entity !== undefined) {
this.state_.active_point_entity.set_active(false);
this.floor_plan_.update_toolbar();
}
if (this.state_.active_wall_entity !== undefined) {
this.state_.active_wall_entity.set_active(false);
this.floor_plan_.update_toolbar();
}
if (active !== this.active_) { if (active !== this.active_) {
this.active_ = active; this.active_ = active;
@ -270,13 +274,13 @@ beestat.component.floor_plan_entity.room.prototype.set_active = function(active)
if (this.state_.active_point_entity !== undefined) { if (this.state_.active_point_entity !== undefined) {
this.state_.active_point_entity.set_active(false); this.state_.active_point_entity.set_active(false);
} }
this.dispatchEvent('inactivate');
} }
if (this.rendered_ === true) { if (this.rendered_ === true) {
this.rerender(); this.rerender();
} }
this.floor_plan_.update_toolbar();
} }
return this; return this;
@ -337,6 +341,11 @@ beestat.component.floor_plan_entity.room.prototype.set_room = function(room) {
this.x_ = room.x; this.x_ = room.x;
this.y_ = room.y; this.y_ = room.y;
// Ensure a UUID is set on the room.
if (this.room_.room_id === undefined) {
this.room_.room_id = window.crypto.randomUUID();
}
return this; return this;
}; };
@ -359,10 +368,15 @@ beestat.component.floor_plan_entity.room.prototype.set_group = function(group) {
* *
* @param {number} x The x position of this entity. * @param {number} x The x position of this entity.
* @param {number} y The y position of this entity. * @param {number} y The y position of this entity.
* @param {string} event Optional event to fire when done.
* *
* @return {beestat.component.floor_plan_entity} This. * @return {beestat.component.floor_plan_entity} This.
*/ */
beestat.component.floor_plan_entity.room.prototype.set_xy = function(x, y) { beestat.component.floor_plan_entity.room.prototype.set_xy = function(x, y, event = 'lesser_update') {
if (event === 'update') {
this.floor_plan_.save_buffer();
}
let clamped_x = x; let clamped_x = x;
let clamped_y = y; let clamped_y = y;
@ -382,7 +396,7 @@ beestat.component.floor_plan_entity.room.prototype.set_xy = function(x, y) {
this.room_.x = Math.round(clamped_x); this.room_.x = Math.round(clamped_x);
this.room_.y = Math.round(clamped_y); this.room_.y = Math.round(clamped_y);
this.dispatchEvent('update'); this.dispatchEvent(event);
return beestat.component.floor_plan_entity.prototype.set_xy.apply( return beestat.component.floor_plan_entity.prototype.set_xy.apply(
this, this,
@ -485,7 +499,6 @@ beestat.component.floor_plan_entity.room.prototype.after_mouseup_handler_ = func
if (this.dragged_ === true) { if (this.dragged_ === true) {
this.clear_snap_lines_(); this.clear_snap_lines_();
this.update_snap_points_(); this.update_snap_points_();
this.dispatchEvent('update');
} }
}; };

View File

@ -65,6 +65,8 @@ beestat.component.floor_plan_entity.wall.prototype.decorate_line_ = function(par
* @param {Event} e * @param {Event} e
*/ */
beestat.component.floor_plan_entity.wall.prototype.add_point = function(e) { beestat.component.floor_plan_entity.wall.prototype.add_point = function(e) {
this.floor_plan_.save_buffer();
const room = this.room_.get_room(); const room = this.room_.get_room();
for (let i = 0; i < room.points.length; i++) { for (let i = 0; i < room.points.length; i++) {
if (this.point_1_ === room.points[i]) { if (this.point_1_ === room.points[i]) {
@ -303,10 +305,15 @@ beestat.component.floor_plan_entity.wall.prototype.set_room = function(room) {
* *
* @param {number} x The x position of this entity. * @param {number} x The x position of this entity.
* @param {number} y The y position of this entity. * @param {number} y The y position of this entity.
* @param {string} event Optional event to fire when done.
* *
* @return {beestat.component.floor_plan_entity.wall} This. * @return {beestat.component.floor_plan_entity.wall} This.
*/ */
beestat.component.floor_plan_entity.wall.prototype.set_xy = function(x, y) { beestat.component.floor_plan_entity.wall.prototype.set_xy = function(x, y, event = 'lesser_update') {
if (event === 'update') {
this.floor_plan_.save_buffer();
}
let clamped_x = x + this.room_.get_x(); let clamped_x = x + this.room_.get_x();
let clamped_y = y + this.room_.get_y(); let clamped_y = y + this.room_.get_y();
@ -326,7 +333,7 @@ beestat.component.floor_plan_entity.wall.prototype.set_xy = function(x, y) {
this.point_2_.y = Math.round(clamped_y - this.room_.get_y()); this.point_2_.y = Math.round(clamped_y - this.room_.get_y());
} }
this.dispatchEvent('update'); this.dispatchEvent(event);
return this; return this;
}; };
@ -568,6 +575,8 @@ beestat.component.floor_plan_entity.wall.prototype.set_active = function(active)
this.dispatchEvent('activate'); this.dispatchEvent('activate');
} else { } else {
delete this.state_.active_wall_entity; delete this.state_.active_wall_entity;
this.dispatchEvent('inactivate');
} }
if (this.rendered_ === true) { if (this.rendered_ === true) {