aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremias Stotter <jeremias@stotter.eu>2024-03-31 20:43:33 +0200
committerJeremias Stotter <jeremias@stotter.eu>2024-03-31 20:43:33 +0200
commit86d679b957d25e86a3e01e24a805fe9759acba73 (patch)
tree8c8a37ff3dfff99e3f6e9bcae7d075d8036af681
parent0430a3a0184931f26f6435ab6c3d93a54400bd8c (diff)
downloadnetwork-simulator-86d679b957d25e86a3e01e24a805fe9759acba73.tar.gz
network-simulator-86d679b957d25e86a3e01e24a805fe9759acba73.tar.bz2
network-simulator-86d679b957d25e86a3e01e24a805fe9759acba73.zip
Use the sibling feature of undo redo for device selection movements
-rw-r--r--gui.c91
-rw-r--r--undo-redo.c20
-rw-r--r--undo-redo.h5
3 files changed, 65 insertions, 51 deletions
diff --git a/gui.c b/gui.c
index dfdc556..be3cf81 100644
--- a/gui.c
+++ b/gui.c
@@ -800,30 +800,12 @@ void drawing_area_click(GtkGestureClick* self, gint n_press, gdouble x, gdouble
area_moving = false;
}
-static inline void move_single_dev(struct device* dev, double xoff, double yoff) {
- dev->X += xoff;
- if(dev->X < 0) dev->X = 0;
- dev->Y += yoff;
- if(dev->Y < 0) dev->Y = 0;
-}
-
-// Adds another device to the undo_device_action
-void add_move_undo_device(size_t* devices_size, struct device* dev, struct undo_entry* entry) {
- size_t devices_offset = *devices_size;
- struct undo_move_data* data = entry->undo_data;
- *devices_size += strlen(dev->name) + 1;
- data->devices = realloc_or_abort(data->devices, *devices_size);
- char* insert_at = data->devices + devices_offset;
- strcpy(insert_at, dev->name);
- data->dev_n++;
-}
-
// This will move a device or select the devices below the area
// Set undo to true if this should be recorded in the undo stack
void move_things(double x, double y, bool undo) {
double xoff = x - x_last;
double yoff = y - y_last;
- // Get the device at the selection
+ // @todo refactor this at some point
if(current_move_deco) {
current_move_deco->X += xoff;
current_move_deco->Y += yoff;
@@ -838,39 +820,76 @@ void move_things(double x, double y, bool undo) {
undo_add_entry(undo_new);
}
} else {
+ // Get the device at the selection
struct device_selection* single_device = get_device_at(x_last,y_last,x_last,y_last);
if(single_device) {
struct device* move_dev = single_device->selected_device;
if(current_move_dev && device_in_selection(single_device, current_move_dev))
move_dev = current_move_dev;
- // Add the action to the list
- struct undo_entry* undo_new = NULL;
- struct undo_move_data* undo_move_new = NULL;
- size_t devices_size = 0;
- if(undo) {
- NEW_UNDO_STRUCT(undo_move, undo_move_data, undo_new, undo_move_new);
- undo_move_new->X_off = x - xstart;
- undo_move_new->Y_off = y - ystart;
- undo_move_new->devices = NULL;
- undo_move_new->dev_n = 0;
- undo_add_entry(undo_new);
- }
// See if the device is part of the selection, if so move all of them
if(device_in_selection(selected_devices, move_dev)) {
+ // First get the the left and top bounds of the selection
+ double bound_x = selected_devices->selected_device->X, bound_y = selected_devices->selected_device->Y;
+ LL_FOR(struct device_selection, selected_devices, this_selection) {
+ if(this_selection->selected_device->X < bound_x)
+ bound_x = this_selection->selected_device->X;
+ if(this_selection->selected_device->Y < bound_y)
+ bound_y = this_selection->selected_device->Y;
+ }
+
+ int xoff_move = xoff, yoff_move = yoff;
+ // if we would move past 0, move to 0 instead
+ if((-xoff_move) > bound_x)
+ xoff_move = (-bound_x);
+ if((-yoff_move) > bound_y)
+ yoff_move = (-bound_y);
+
+ xstart -= (xoff-xoff_move);
+ ystart -= (yoff-yoff_move);
+
+ struct undo_entry* first_undo = NULL;
+
// Move all devices by the offset
LL_FOR(struct device_selection, selected_devices, this_selection) {
- move_single_dev(this_selection->selected_device, xoff, yoff);
+ this_selection->selected_device->X += xoff_move;
+ this_selection->selected_device->Y += yoff_move;
if(undo) {
- add_move_undo_device(&devices_size, this_selection->selected_device, undo_new);
+ struct undo_entry* undo_new = NULL;
+ struct undo_move_data* move_undo_data_new = NULL;
+ NEW_UNDO_STRUCT(undo_move, undo_move_data, undo_new, move_undo_data_new);
+ if(first_undo) {
+ first_undo->prev_sibling = undo_new;
+ }
+ undo_new->next_sibling = first_undo;
+ move_undo_data_new->device = malloc_or_abort(strlen(this_selection->selected_device->name)+1);
+ strcpy(move_undo_data_new->device, this_selection->selected_device->name);
+ move_undo_data_new->X_off = x-xstart;
+ move_undo_data_new->Y_off = y-ystart;
+ first_undo = undo_new;
}
}
+ if(undo)
+ undo_add_entry(first_undo);
// Otherwise move just the one device
} else {
+ struct undo_entry* undo_new;
free_selection(selected_devices);
selected_devices = NULL;
- move_single_dev(move_dev, xoff, yoff);
+
+ move_dev->X += xoff;
+ if(move_dev->X < 0) move_dev->X = 0;
+ move_dev->Y += yoff;
+ if(move_dev->Y < 0) move_dev->Y = 0;
+
if(undo) {
- add_move_undo_device(&devices_size, move_dev, undo_new);
+ struct undo_move_data* move_undo_data_new = NULL;
+ NEW_UNDO_STRUCT(undo_move, undo_move_data, undo_new, move_undo_data_new);
+ move_undo_data_new->device = malloc_or_abort(strlen(move_dev->name)+1);
+ strcpy(move_undo_data_new->device, move_dev->name);
+ move_undo_data_new->X_off = x - xstart;
+ move_undo_data_new->Y_off = y - ystart;
+
+ undo_add_entry(undo_new);
}
}
free_selection(single_device);
@@ -1263,7 +1282,7 @@ void drawing_area_motion(GtkEventControllerKey* self, gdouble x, gdouble y, gpoi
xnow = x;
ynow = y;
- if(area_mode == MODE_MOVE && area_moving)
+ if(area_mode == MODE_MOVE && area_moving && x >= 0 && y >= 0)
move_things(x, y, false);
else if(area_mode == MODE_NEW_RECT || area_mode == MODE_NEW_CIRCLE) {
if(sizing_deco) {
diff --git a/undo-redo.c b/undo-redo.c
index ece1886..e7d0c59 100644
--- a/undo-redo.c
+++ b/undo-redo.c
@@ -35,7 +35,7 @@ void free_undo_entry(struct undo_entry* fentry) {
while(fentry) {
switch(fentry->action) {
case undo_move:
- free(((struct undo_move_data*)fentry->undo_data)->devices);
+ free(((struct undo_move_data*)fentry->undo_data)->device);
break;
case undo_move_deco:
deco_put(((struct undo_move_deco_data*)fentry->undo_data)->deco);
@@ -119,15 +119,11 @@ void undo_add_entry(struct undo_entry* entry) {
actions_since_save++;
}
-void undo_move_devices(char* names, int dev_n, float X_off, float Y_off) {
- for(int i = 0; i < dev_n; i++) {
- struct device* move_dev = dev_from_name(start_device, names);
- if(!move_dev) continue;
- move_dev->X += X_off;
- move_dev->Y += Y_off;
- for(; *names != '\0'; names++);
- names++;
- }
+void undo_move_device(char* name, float X_off, float Y_off) {
+ struct device* move_dev = dev_from_name(start_device, name);
+ if(!move_dev) return;
+ move_dev->X += X_off;
+ move_dev->Y += Y_off;
}
int undo() {
@@ -137,7 +133,7 @@ int undo() {
case undo_move:
{
struct undo_move_data* move_data = uentry->undo_data;
- undo_move_devices(move_data->devices, move_data->dev_n, -move_data->X_off, -move_data->Y_off);
+ undo_move_device(move_data->device, -move_data->X_off, -move_data->Y_off);
}
break;
case undo_move_deco:
@@ -220,7 +216,7 @@ int redo() {
case undo_move:
{
struct undo_move_data* move_data = rentry->undo_data;
- undo_move_devices(move_data->devices, move_data->dev_n, move_data->X_off, move_data->Y_off);
+ undo_move_device(move_data->device, move_data->X_off, move_data->Y_off);
}
break;
case undo_move_deco:
diff --git a/undo-redo.h b/undo-redo.h
index 6b11ed9..77528f1 100644
--- a/undo-redo.h
+++ b/undo-redo.h
@@ -51,9 +51,8 @@ int redo();
// Following are structs containing the data for each the above actions needed to undo and redo
struct undo_move_data {
- // devices should be multiple (dev_n) strings seperated by \0
- int dev_n;
- char* devices;
+ // Name of the device
+ char* device;
// This will be how much the device was moved
double X_off;
double Y_off;
Jeremias Stotters git repositories generated by CGIT