kapstok / NHL-DePa2 (public) (License: Unspecified) (since 2018-11-09) (hash sha1)
Design Patterns school project; a GUI using multiple Design Patterns.
List of commits:
Subject Hash Author Date (UTC)
Make groups movable and resizable. 1ca7c18ab103a8d1055b27f63192038fd75aef3e Jan Allersma 2018-10-17 14:51:32
Use translations instead of positions for moving shapes. 9551c7d2608f01c3950743fd97bd217aab8f5766 Jan Allersma 2018-10-16 16:11:03
Implement Visitor pattern for Groups. bd30477ce616362d3f58cef072d1ebc78077fa85 Jan Allersma 2018-10-16 13:28:37
Implement Visitor pattern for Shapes. e52412c3059c1ee5fa9abdf4a32db0f47981eee1 Jan Allersma 2018-10-16 12:43:17
Use different strats instead of seperate Shapes. a56e1e665a0292d15139eddfd8ebdeb8c95251b4 Jan Allersma 2018-10-01 11:37:45
Fix bug in Rect from commit 6c91140 in other Shapes as well. 4165a5da98dd9a548a222c6160390e4e54026d48 Jan Allersma 2018-09-28 14:53:40
Fully implement File I/O. 45cbb48489a24857cfc76144b38b12ccebfd9e61 Jan Allersma 2018-09-27 16:03:40
Fix GroupMenu bug. be41e51819be1a23e7761ea0662eb188ac641aca Jan Allersma 2018-09-27 14:55:20
Fix TODO's from previous commit. 89d8172b77336a6c18f30521147eb81287961f11 Jan Allersma 2018-09-27 14:06:30
Add groups as preparation for step 3. a91368128e7444f69b3a30ee4d17f9063c8846b8 Jan Allersma 2018-09-26 18:31:49
Fix minor bug. Small cleanup 'ellipse' code. 6c911405eb8e48ffe2d63aaff5255adbd4aec889 Jan Allersma 2018-09-21 18:10:01
Implement file I/O. 6219eca932d454a7dab5fe8679f07865ce3cf49d Jan Allersma 2018-09-21 15:52:45
Add shape 'ellipse'. 99d8b029c769bc291af73df3fd445da3cbf5bef4 Jan Allersma 2018-09-21 10:44:36
Add shape 'circle'. 092cb3c3f788b461192a6e164955c53acaf58720 Jan Allersma 2018-09-21 09:35:27
Add resize option (again). 08c95e97268cf9d74bcb963503eec512e528edfe Jan Allersma 2018-09-20 18:09:03
Fix undo bug. 6ab126be633075923cdcce53044e2468f967db41 Jan Allersma 2018-09-20 10:46:50
Implement 'delete shape' feature. 16d42472d44a9dae988c4745c90c791a8770541b Jan Allersma 2018-09-19 09:04:40
Fix undo/redo for 'MoveCmd'. be51bea021bfe5ff79e16a92d350677aed736ddd Jan Allersma 2018-09-19 08:49:55
Implement shapeOptions without undo/redo. bbe699f41e5dacbfdadfaa879452ac2f4501f5a1 Jan Allersma 2018-09-18 19:44:44
WIP: Restore 'shapeOptions.d'. 888b8ea647c0f25cfbeefcd97ee7ebb59e7f0751 Jan Allersma 2018-09-18 15:46:05
Commit 1ca7c18ab103a8d1055b27f63192038fd75aef3e - Make groups movable and resizable.
- Import `dp.ent.shape` and `dp.ent.group` publically in `dp.ent.entity`.
- Remove obsolete `saveable` property in Entity classes.
Author: Jan Allersma
Author date (UTC): 2018-10-17 14:51
Committer name: Jan Allersma
Committer date (UTC): 2018-10-17 14:51
Parent(s): 9551c7d2608f01c3950743fd97bd217aab8f5766
Signing key:
Tree: b16194b093e6a23ec1ff9a5eed90867b2977960b
File Lines added Lines deleted
source/brush.d 2 2
source/canvas.d 10 2
source/commands/create.d 1 1
source/commands/load.d 1 1
source/commands/move.d 13 10
source/commands/resize.d 8 10
source/entities/entity.d 8 1
source/entities/group.d 3 1
source/frontend/resizeDialog.d 25 4
source/frontend/shapeOptions.d 34 1
source/history.d 1 1
File source/brush.d changed (mode: 100644) (index 2df920c..763992e)
1 1 module dp.brush; module dp.brush;
2 2
3 import dp.ent.shape;
4 import dp.ent.group;
3 import dp.ent.entity;
5 4
5 static bool cloneGroup;
6 6 static Shape clone; static Shape clone;
7 7 static string shape; static string shape;
8 8 static double red; static double red;
File source/canvas.d changed (mode: 100644) (index b7e5700..6eae7ff)
... ... import gdk.Event;
5 5 import cairo.Context; import cairo.Context;
6 6 import cairo.ImageSurface; import cairo.ImageSurface;
7 7
8 import dp.ent.shape;
8 import dp.ent.entity;
9 9 import dp.strat.rect; import dp.strat.rect;
10 10 import dp.strat.circle; import dp.strat.circle;
11 11 import dp.strat.ellipse; import dp.strat.ellipse;
 
... ... public class Canvas : DrawingArea {
53 53 } }
54 54 else if(Global.Brush.clone !is null) { else if(Global.Brush.clone !is null) {
55 55 Global.Brush.clone.active = true; Global.Brush.clone.active = true;
56 Global.History.addCommand(new MoveCmd(Global.Brush.clone, [mouseX, mouseY]));
56
57 Global.History.addCommand (
58 new MoveCmd (
59 Global.Brush.clone,
60 [mouseX, mouseY],
61 Global.Brush.cloneGroup
62 )
63 );
64
57 65 Global.Brush.clone = null; Global.Brush.clone = null;
58 66 repaint(); repaint();
59 67 } }
File source/commands/create.d changed (mode: 100644) (index 797b0fe..335545b)
... ... public class CreateCmd : Command {
32 32
33 33 // Should be done by Visitor self. // Should be done by Visitor self.
34 34 public override void save(Savefile file) { public override void save(Savefile file) {
35 if(s.saveable)
35 if(s.group !is null)
36 36 s.accept(new SaveVisitor(file)); s.accept(new SaveVisitor(file));
37 37 } }
38 38 } }
File source/commands/load.d changed (mode: 100644) (index e2536b6..231d7cb)
... ... public class LoadCmd : Command {
37 37 // Should be done by Visitor self. // Should be done by Visitor self.
38 38 public override void save(Savefile file) { public override void save(Savefile file) {
39 39 foreach(s; shapes) { foreach(s; shapes) {
40 if(s.saveable)
40 if(s.group !is null)
41 41 s.accept(new SaveVisitor(file)); s.accept(new SaveVisitor(file));
42 42 } }
43 43 } }
File source/commands/move.d changed (mode: 100644) (index afa4b6c..0b68d35)
1 1 module dp.command.move; module dp.command.move;
2 2
3 3 import dp.command.cmd; import dp.command.cmd;
4 import dp.ent.shape;
4 import dp.ent.entity;
5 5 import dp.visitor.move; import dp.visitor.move;
6 6
7 7 import Global = dp.global; import Global = dp.global;
8 8
9 9 public class MoveCmd : Command { public class MoveCmd : Command {
10 private Shape s;
10 private Entity e;
11 11 private int[2] translation; private int[2] translation;
12 12
13 this(Shape shape, int[2] newPosition) {
14 s = shape;
13 this(Shape shape, int[2] newPosition, bool moveGroup) {
14 // Null-check is redundant since ShapeOptions does null-check as
15 // well. But what if the group is called from somewhere else in
16 // the code in the future?
17 e = moveGroup && shape.group !is null ? shape.group : shape;
15 18
16 19 translation = [ translation = [
17 newPosition[0] - s.position[0],
18 newPosition[1] - s.position[1]
20 newPosition[0] - shape.position[0],
21 newPosition[1] - shape.position[1]
19 22 ]; ];
20 23
21 24 execute(); execute();
22 25 } }
23 26
24 27 public override void execute() { public override void execute() {
25 s.accept(new MoveVisitor(translation));
28 e.accept(new MoveVisitor(translation));
26 29 } }
27 30
28 31 public override void undo() { public override void undo() {
29 s.accept(new MoveVisitor([
32 e.accept(new MoveVisitor([
30 33 -translation[0], -translation[0],
31 34 -translation[1] -translation[1]
32 35 ])); ]));
33 36 } }
34 37
35 38 public override void render() { public override void render() {
36 s.render();
39 e.render();
37 40 } }
38 41
39 42 public override void check(int x, int y) { public override void check(int x, int y) {
40 s.checkBounds(x,y);
43 e.checkBounds(x,y);
41 44 } }
42 45 } }
File source/commands/resize.d changed (mode: 100644) (index 34a8eb6..1b7c844)
1 1 module dp.command.resize; module dp.command.resize;
2 2
3 3 import dp.command.cmd; import dp.command.cmd;
4 import dp.ent.shape;
4 import dp.ent.entity;
5 5 import dp.visitor.resize; import dp.visitor.resize;
6 6
7 7 import Global = dp.global; import Global = dp.global;
8 8
9 9 public class ResizeCmd : Command { public class ResizeCmd : Command {
10 private Shape s;
10 private Entity e;
11 11 private int amount; private int amount;
12 12
13 this(Shape shape, int amount) {
14 s = shape;
13 this(Entity entity, int amount) {
14 e = entity;
15 15 this.amount = amount; this.amount = amount;
16 16 execute(); execute();
17 17 } }
18 18
19 19 public override void execute() { public override void execute() {
20 //s.resize(amount);
21 s.accept(new ResizeVisitor(amount));
20 e.accept(new ResizeVisitor(amount));
22 21 } }
23 22
24 23 public override void undo() { public override void undo() {
25 //s.resize(-amount);
26 s.accept(new ResizeVisitor(-amount));
24 e.accept(new ResizeVisitor(-amount));
27 25 } }
28 26
29 27 public override void render() { public override void render() {
30 s.render();
28 e.render();
31 29 } }
32 30
33 31 public override void check(int x, int y) { public override void check(int x, int y) {
34 s.checkBounds(x,y);
32 e.checkBounds(x,y);
35 33 } }
36 34 } }
File source/entities/entity.d changed (mode: 100644) (index b209800..a93d0dc)
1 1 module dp.ent.entity; module dp.ent.entity;
2 2
3 3 public import dp.visitor.visitor; public import dp.visitor.visitor;
4 public import dp.ent.group;
5
6 // Is not being used in Entity class definition,
7 // but the modules are required in a lot of use
8 // cases when importing this module for
9 // implementation of the 'Entity' class.
10 public import dp.ent.shape;
4 11
5 12 class Entity { class Entity {
6 13 public bool active = true; public bool active = true;
7 public bool saveable = true;
14 public Group group = null;
8 15
9 16 @property @property
10 17 public abstract string type(); public abstract string type();
File source/entities/group.d changed (mode: 100644) (index 6b06cbd..a1daf83)
... ... class Group : Entity {
84 84 size_t index = entities.length++; size_t index = entities.length++;
85 85
86 86 entities[index] = entity; entities[index] = entity;
87 entity.saveable = false;
87 entity.group = this;
88 88 return index; return index;
89 89 } }
90 90
91 91 public void remove(size_t index) { public void remove(size_t index) {
92 entities[index].group = null;
93
92 94 for(size_t i = index; i < entities.length; i++) for(size_t i = index; i < entities.length; i++)
93 95 entities[i] = entities[i+1]; entities[i] = entities[i+1];
94 96
File source/frontend/resizeDialog.d changed (mode: 100644) (index b779f0f..a27d1b4)
... ... import gtk.Label;
6 6 import gtk.Button; import gtk.Button;
7 7 import gtk.Entry; import gtk.Entry;
8 8
9 import dp.ent.shape;
9 import dp.ent.entity;
10 10 import dp.history; import dp.history;
11 11 import dp.command.resize; import dp.command.resize;
12 12
 
... ... import std.stdio; // Debug
17 17 import std.string, std.conv; import std.string, std.conv;
18 18
19 19 class ResizeDialog : Dialog { class ResizeDialog : Dialog {
20 Shape shape;
20 Entity entity;
21 21 Entry factorEntry; Entry factorEntry;
22 22
23 23 this(Shape shape) { this(Shape shape) {
24 24 super(); super();
25 25 setTitle("Resize shape"); setTitle("Resize shape");
26 this.shape = shape;
26 entity = shape;
27 27
28 28 factorEntry = new Entry(); factorEntry = new Entry();
29 29 factorEntry.setPlaceholderText("amount"); factorEntry.setPlaceholderText("amount");
 
... ... class ResizeDialog : Dialog {
41 41 showAll(); showAll();
42 42 } }
43 43
44 this(Group group) {
45 super();
46 setTitle("Resize group");
47 entity = group;
48
49 factorEntry = new Entry();
50 factorEntry.setPlaceholderText("amount");
51
52 Button confirmBtn = new Button("Resize!", &clickCallback);
53
54 // Content area, containing non-interactable GTK objects.
55 getContentArea().add(new Label("By what amount should the group be resized?"));
56 getContentArea().setBorderWidth(20);
57
58 // Action area, containing interactable GTK objects.
59 getActionArea().add(factorEntry);
60 getActionArea().add(confirmBtn);
61
62 showAll();
63 }
64
44 65 void clickCallback (Button button) { void clickCallback (Button button) {
45 66 int amount = 1; int amount = 1;
46 67 string input = factorEntry.getText(); string input = factorEntry.getText();
47 68
48 69 if(isNumeric(input)) { if(isNumeric(input)) {
49 70 amount = parse!int(input); amount = parse!int(input);
50 History.addCommand(new ResizeCmd(shape, amount));
71 History.addCommand(new ResizeCmd(entity, amount));
51 72 Global.canvas.repaint(); Global.canvas.repaint();
52 73 this.close(); this.close();
53 74 } }
File source/frontend/shapeOptions.d changed (mode: 100644) (index 4cc0932..cd42f92)
... ... import gtk.Menu, gtk.MenuItem;
4 4 import gtk.Widget; import gtk.Widget;
5 5 import gdk.Event; import gdk.Event;
6 6
7 import dp.ent.shape;
7 import dp.ent.entity;
8 8 import dp.command.destruct; import dp.command.destruct;
9 9 import dp.win.resize; import dp.win.resize;
10 10 import Global = dp.global; import Global = dp.global;
 
... ... public class ShapeOptions : Menu {
20 20 this.append(new DeleteShape()); this.append(new DeleteShape());
21 21 this.append(new MoveShape()); this.append(new MoveShape());
22 22 this.append(new ResizeShape()); this.append(new ResizeShape());
23 this.append(new MoveGroup());
24 this.append(new ResizeGroup());
23 25 } }
24 26
25 27 public void selectShape (Shape shape) { // Shows options of param shape. public void selectShape (Shape shape) { // Shows options of param shape.
 
... ... protected class MoveShape : MenuItem {
50 52
51 53 private bool relCallback (Event event, Widget widget) { private bool relCallback (Event event, Widget widget) {
52 54 Global.Brush.clone = s; Global.Brush.clone = s;
55 Global.Brush.cloneGroup = false;
53 56 s.active = false; // In de tussentijd niet gaan drawen totdat het verplaatsen gelukt is!!! s.active = false; // In de tussentijd niet gaan drawen totdat het verplaatsen gelukt is!!!
54 57 // Create ghost shape. // Create ghost shape.
55 58 return false; // Hide ShapeOptions when button is released. return false; // Hide ShapeOptions when button is released.
 
... ... protected class ResizeShape : MenuItem {
67 70 return false; // Hide ShapeOptions when button is released. return false; // Hide ShapeOptions when button is released.
68 71 } }
69 72 } }
73
74 protected class MoveGroup : MenuItem {
75 this() {
76 super("Move group");
77 addOnButtonRelease(&relCallback);
78 }
79
80 private bool relCallback (Event event, Widget widget) {
81 if(s.group !is null) {
82 Global.Brush.clone = s;
83 Global.Brush.cloneGroup = true;
84 s.group.active = false; // In de tussentijd niet gaan drawen totdat het verplaatsen gelukt is!!!
85 // Create ghost group.
86 }
87 return false; // Hide ShapeOptions when button is released.
88 }
89 }
90
91 protected class ResizeGroup : MenuItem {
92 this() {
93 super("Resize group");
94 addOnButtonRelease(&relCallback);
95 }
96
97 private bool relCallback (Event event, Widget widget) {
98 if(s.group !is null)
99 rd = new ResizeDialog(s.group);
100 return false; // Hide ShapeOptions when button is released.
101 }
102 }
File source/history.d changed (mode: 100644) (index 4a3378c..394b2ce)
... ... static class History {
71 71 command.save(file); command.save(file);
72 72
73 73 foreach(group; Global.Groups.get) { foreach(group; Global.Groups.get) {
74 if(group.saveable)
74 if(group.group !is null)
75 75 file.toFile(group); file.toFile(group);
76 76 } }
77 77
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/kapstok/NHL-DePa2

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/kapstok/NHL-DePa2

Clone this repository using git:
git clone git://git.rocketgit.com/user/kapstok/NHL-DePa2

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main