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)
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
Rebuild project from scratch. df0f2f82a86581ba9fa3a169d63a950229341a9f Jan Allersma 2018-09-18 15:04:32
Add resize option. 961e464090918d83690ff66838f2fc96c6ad213a Jan Allersma 2018-09-13 18:29:44
Make `MoveCmd` Command-oriented. 2970a8d862285752551be2464422375ca958357f Jan Allersma 2018-09-12 15:33:17
Change of strategy: Make project command-oriented. ce40dffb1675661922411eeb07f148f61a176c22 Jan Allersma 2018-09-12 11:35:45
Initial commit. 38c8818349679937ae25dde38949202ec45ea7b2 Jan Allersma 2018-09-11 20:21:57
Commit a91368128e7444f69b3a30ee4d17f9063c8846b8 - Add groups as preparation for step 3.
Instead of using Shape as most basic class for objects from the end-user side, Entity is now the most basic class.

TODO:

* Add File I/O for groups.

* Show graphical indication at runtime what belongs to a group.

* Using commands to store all relevant file I/O could cause issues. A suggested setup would be a seperation between things that handle file I/O and undo/redo operations. This way CreateCmds for Shapes could be undone without undoing a whole Group. Maybe the decorator pattern could show it's usefulness in this case?
Author: Jan Allersma
Author date (UTC): 2018-09-26 18:31
Committer name: Jan Allersma
Committer date (UTC): 2018-10-05 17:17
Parent(s): 6c911405eb8e48ffe2d63aaff5255adbd4aec889
Signing key:
Tree: dd167a58cc031defa620632895162737958b1ed7
File Lines added Lines deleted
README.md 9 6
source/brush.d 3 1
source/canvas.d 21 2
source/commands/create.d 13 9
source/commands/destruct.d 1 1
source/commands/load.d 15 15
source/commands/move.d 1 1
source/commands/resize.d 1 1
source/entities/circle.d 2 3
source/entities/ellipse.d 2 4
source/entities/entity.d 15 0
source/entities/group.d 104 0
source/entities/rect.d 2 3
source/entities/shape.d 21 13
source/file.d 25 9
source/frontend/mainWindow.d 2 0
source/frontend/menubar.d 61 1
source/frontend/resizeDialog.d 1 1
source/frontend/shapeOptions.d 1 1
source/globals.d 8 0
source/selection.d 16 0
File README.md changed (mode: 100644) (index daf3a8e..533da74)
1 1 # NHL-DPainter # NHL-DPainter
2
2 3 This repo is a school project for Design Patterns. This repo is a school project for Design Patterns.
3 4
4 5 use 'dub' to compile and run the code. use 'dub' to compile and run the code.
 
... ... use 'dub' to compile and run the code.
22 23
23 24 - `newPath()`: Clear path from context. - `newPath()`: Clear path from context.
24 25
25 # Vragen
26 # Roadmap
27
28 - Delete group? Hoe?
29
30 - File I/O voor groups.
26 31
27 - Is het toegstaan om een implementatie aan een interface toe te voegen, zoals
28 ik in 'command.d' heb gedaan of breekt dit het Command pattern?
32 - Grafische indicatie van een groep.
29 33
30 - Hoe strict is de grammatica voor de file I/O? Dit programma redeneert vanuit
31 het centrum van een shape en doet alleen aan non-uniform scaling. Daarom is de
32 huidige toegepaste grammatica handiger.
34 - `public import Global = dp.global;` en `public import std.stdio; // Debug`
35 in app.d zetten en daarna alle overbodige imports uit de andere files halen.
File source/brush.d changed (mode: 100644) (index 783a7b1..2df920c)
1 1 module dp.brush; module dp.brush;
2 2
3 import dp.shape.shape;
3 import dp.ent.shape;
4 import dp.ent.group;
4 5
5 6 static Shape clone; static Shape clone;
6 7 static string shape; static string shape;
 
... ... static double red;
8 9 static double green; static double green;
9 10 static double blue; static double blue;
10 11 static double alpha; static double alpha;
12 static Group group;
File source/canvas.d changed (mode: 100644) (index 56f90cf..6d5c3e8)
... ... import gdk.Event;
5 5 import cairo.Context; import cairo.Context;
6 6 import cairo.ImageSurface; import cairo.ImageSurface;
7 7
8 import dp.shape.shape;
9 import dp.shape.rect, dp.shape.circle, dp.shape.ellipse;
8 import dp.ent.shape;
9 import dp.ent.rect, dp.ent.circle, dp.ent.ellipse;
10 10 import dp.command.create, dp.command.move; import dp.command.create, dp.command.move;
11 11
12 12 import std.stdio; // For debug import std.stdio; // For debug
 
... ... public class Canvas : DrawingArea {
55 55 Global.Brush.clone = null; Global.Brush.clone = null;
56 56 repaint(); repaint();
57 57 } }
58 else if(Global.Brush.group !is null && Global.Brush.shape !is null) {
59 Shape s;
60 final switch (Global.Brush.shape) {
61 case "rectangle":
62 s = new Rectangle(mouseX, mouseY, newContext);
63 break;
64 case "circle":
65 s = new Circle(mouseX, mouseY, newContext);
66 break;
67 case "ellipse":
68 s = new Ellipse(mouseX, mouseY, newContext);
69 break;
70 }
71 Global.History.addCommand(new CreateCmd(s, true));
72 Global.Brush.group.add(s);
73
74 Global.Brush.shape = null;
75 repaint();
76 }
58 77 else if(Global.Brush.shape !is null) { else if(Global.Brush.shape !is null) {
59 78 final switch (Global.Brush.shape) { final switch (Global.Brush.shape) {
60 79 case "rectangle": case "rectangle":
File source/commands/create.d changed (mode: 100644) (index fe3ceae..a772131)
1 1 module dp.command.create; module dp.command.create;
2 2
3 3 import dp.command.cmd; import dp.command.cmd;
4 import dp.shape.shape;
4 import dp.ent.entity;
5 5
6 6 import Global = dp.global; import Global = dp.global;
7 7
8 8 public class CreateCmd : Command { public class CreateCmd : Command {
9 private Shape s;
9 private Entity e;
10 private bool groupmember;
10 11
11 this(Shape shape) {
12 s = shape;
12 this(Entity entity, bool groupmember = false) {
13 e = entity;
14 this.groupmember = groupmember;
13 15 execute(); // Obsolete, but remained for consistency between 'Command' classes. execute(); // Obsolete, but remained for consistency between 'Command' classes.
14 16 } }
15 17
16 18 public override void execute() { public override void execute() {
17 s.active = true;
19 e.active = true;
18 20 } }
19 21
20 22 public override void undo() { public override void undo() {
21 s.active = false;
23 e.active = false;
22 24 } }
23 25
24 26 public override void render() { public override void render() {
25 s.render();
27 //if(!groupmember)
28 e.render();
26 29 } }
27 30
28 31 public override void check(int x, int y) { public override void check(int x, int y) {
29 s.checkBounds(x,y);
32 e.checkBounds(x,y);
30 33 } }
31 34
32 35 public override void save(Savefile file) { public override void save(Savefile file) {
33 file.toFile(s);
36 if(!groupmember)
37 file.toFile(e);
34 38 } }
35 39 } }
File source/commands/destruct.d changed (mode: 100644) (index 893b57c..84596e7)
1 1 module dp.command.destruct; // don't use 'dp.command.delete' as module. Causes bug. module dp.command.destruct; // don't use 'dp.command.delete' as module. Causes bug.
2 2
3 3 import dp.command.cmd; import dp.command.cmd;
4 import dp.shape.shape;
4 import dp.ent.shape;
5 5
6 6 import Global = dp.global; import Global = dp.global;
7 7
File source/commands/load.d changed (mode: 100644) (index cb91ace..ea288ee)
1 1 module dp.command.load; module dp.command.load;
2 2
3 3 import dp.command.cmd; import dp.command.cmd;
4 import dp.shape.shape;
4 import dp.ent.entity;
5 5
6 6 import Global = dp.global; import Global = dp.global;
7 7
8 8 public class LoadCmd : Command { public class LoadCmd : Command {
9 private Shape[] shapes;
9 private Entity[] entities;
10 10
11 this(Shape[] shapes) {
12 this.shapes = shapes;
11 this(Entity[] entities) {
12 this.entities = entities;
13 13 execute(); // Obsolete, but remained for consistency between 'Command' classes. execute(); // Obsolete, but remained for consistency between 'Command' classes.
14 14 } }
15 15
16 16 public override void execute() { public override void execute() {
17 foreach(shape; shapes)
18 shape.active = true;
17 foreach(e; entities)
18 e.active = true;
19 19 } }
20 20
21 21 public override void undo() { public override void undo() {
22 foreach(shape; shapes)
23 shape.active = false;
22 foreach(e; entities)
23 e.active = false;
24 24 } }
25 25
26 26 public override void render() { public override void render() {
27 foreach(shape; shapes)
28 shape.render();
27 foreach(e; entities)
28 e.render();
29 29 } }
30 30
31 31 public override void check(int x, int y) { public override void check(int x, int y) {
32 foreach(shape; shapes)
33 shape.checkBounds(x,y);
32 foreach(e; entities)
33 e.checkBounds(x,y);
34 34 } }
35
35
36 36 public override void save(Savefile file) { public override void save(Savefile file) {
37 foreach(shape; shapes)
38 file.toFile(shape);
37 foreach(e; entities)
38 file.toFile(e);
39 39 } }
40 40 } }
File source/commands/move.d changed (mode: 100644) (index 010192f..44446c4)
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.shape.shape;
4 import dp.ent.shape;
5 5
6 6 import Global = dp.global; import Global = dp.global;
7 7
File source/commands/resize.d changed (mode: 100644) (index 646fa24..dfb73ac)
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.shape.shape;
4 import dp.ent.shape;
5 5
6 6 import Global = dp.global; import Global = dp.global;
7 7
File source/entities/circle.d renamed from source/shapes/circle.d (similarity 88%) (mode: 100644) (index 37160e1..00936ce)
1 module dp.shape.circle;
1 module dp.ent.circle;
2 2
3 3 import cairo.Context; import cairo.Context;
4 import dp.shape.shape;
4 import dp.ent.shape;
5 5 import std.conv; import std.conv;
6 6
7 7 import Global = dp.global; import Global = dp.global;
 
... ... class Circle : Shape {
53 53 } }
54 54
55 55 protected override void draw() { protected override void draw() {
56 c.setSourceRgba(Global.Brush.red, Global.Brush.green, Global.Brush.blue, Global.Brush.alpha);
57 56 c.arc(bounds[0][0] + size, bounds[0][1] + size, size, 0, 2 * pi); c.arc(bounds[0][0] + size, bounds[0][1] + size, size, 0, 2 * pi);
58 57 } }
59 58 } }
File source/entities/ellipse.d renamed from source/shapes/ellipse.d (similarity 88%) (mode: 100644) (index 6e1a032..27642ad)
1 module dp.shape.ellipse;
1 module dp.ent.ellipse;
2 2
3 3 import cairo.Context; import cairo.Context;
4 import dp.shape.shape;
4 import dp.ent.shape;
5 5 import std.conv; import std.conv;
6 6
7 7 import Global = dp.global; import Global = dp.global;
 
... ... class Ellipse : Shape {
53 53 } }
54 54
55 55 protected override void draw() { protected override void draw() {
56 c.setSourceRgba(Global.Brush.red, Global.Brush.green, Global.Brush.blue, Global.Brush.alpha);
57
58 56 c.scale(0.5, 1); c.scale(0.5, 1);
59 57 c.arc(bounds[0][0] * 2 + size, bounds[0][1] + size, size, 0, 2 * pi); c.arc(bounds[0][0] * 2 + size, bounds[0][1] + size, size, 0, 2 * pi);
60 58 c.scale(2, 1); c.scale(2, 1);
File source/entities/entity.d added (mode: 100644) (index 0000000..010741f)
1 module dp.ent.entity;
2
3 class Entity {
4 public bool active = true;
5
6 @property
7 public abstract string type();
8
9 @property
10 public abstract string to_string();
11
12 public abstract void checkBounds(int x, int y);
13
14 public abstract void render();
15 }
File source/entities/group.d added (mode: 100644) (index 0000000..13c1123)
1 module dp.ent.group;
2
3 import dp.ent.shape;
4 import dp.ent.entity;
5 import dp.file;
6
7 import std.conv;
8 import std.random;
9
10 import Global = dp.global;
11
12 class Group : Entity {
13 public int[3] colour; // R, G, B
14 private Entity[] entities;
15
16 this() {
17 auto random = rndGen();
18 entities = [];
19 active = true;
20 colour = [
21 uniform(0x0, 0xFF, random),
22 uniform(0x0, 0xFF, random),
23 uniform(0x0, 0xFF, random)
24 ];
25 }
26
27 @property
28 public size_t length() {
29 return entities.length;
30 }
31
32 @property
33 public override string type() {
34 return "group";
35 }
36
37 @property
38 public override string to_string() {
39 string result = type ~ " " ~ to!string(length) ~ "\n";
40
41 foreach(e; entities) {
42 if(e.active) {
43 result ~= "\t";
44 result ~= e.to_string();
45 }
46 }
47
48 return result;
49 }
50
51 public override void render() {
52 /*if(!active)
53 return;
54
55 float[3] tmp = [
56 Global.Brush.red,
57 Global.Brush.green,
58 Global.Brush.blue
59 ];
60
61 foreach(e; entities) {
62 final switch(e.type) {
63 case "rectangle":
64 case "circle":
65 case "ellipse":
66 Global.Brush.red = 0.3;//colour[0] / 0xFF;
67 Global.Brush.green = 0.3;//colour[1] / 0xFF;
68 Global.Brush.blue = 0.3;//colour[2] / 0xFF;
69 e.render();
70 Global.Brush.red = tmp[0];
71 Global.Brush.green = tmp[1];
72 Global.Brush.blue = tmp[2];
73 break;
74 case "group":
75 e.render();
76 break;
77 }
78 } */
79 }
80
81 public override void checkBounds(int x, int y) {
82 if(active)
83 foreach(e; entities)
84 e.checkBounds(x,y);
85 }
86
87 public size_t add(Entity entity) {
88 size_t index = entities.length++;
89
90 entities[index] = entity;
91 return index;
92 }
93
94 public void remove(size_t index) {
95 for(size_t i = index; i < entities.length; i++)
96 entities[i] = entities[i+1];
97
98 entities.length--;
99 }
100
101 public Entity get(size_t index) {
102 return entities[index];
103 }
104 }
File source/entities/rect.d renamed from source/shapes/rect.d (similarity 90%) (mode: 100644) (index 24f1b74..bed8e8d)
1 module dp.shape.rect;
1 module dp.ent.rect;
2 2
3 3 import cairo.Context; import cairo.Context;
4 import dp.shape.shape;
4 import dp.ent.shape;
5 5 import std.conv; import std.conv;
6 6
7 7 import Global = dp.global; import Global = dp.global;
 
... ... class Rectangle : Shape {
58 58 } }
59 59
60 60 protected override void draw() { protected override void draw() {
61 c.setSourceRgba(Global.Brush.red, Global.Brush.green, Global.Brush.blue, Global.Brush.alpha);
62 61 c.rectangle(bounds[0][0], bounds[0][1], size, size); c.rectangle(bounds[0][0], bounds[0][1], size, size);
63 62 } }
64 63 } }
File source/entities/shape.d renamed from source/shapes/shape.d (similarity 65%) (mode: 100644) (index 85bec67..ebd2d4f)
1 module dp.shape.shape;
1 module dp.ent.shape;
2 2
3 3 import cairo.Context; import cairo.Context;
4 4 import std.conv; import std.conv;
5 import dp.ent.entity;
6
7 import std.stdio; // Debug
5 8
6 9 import Global = dp.global; import Global = dp.global;
7 10
8 class Shape {
11 class Shape : Entity {
9 12 /+ /+
10 13 bounds[0][0] = minX bounds[0][0] = minX
11 14 bounds[1][0] = maxX bounds[1][0] = maxX
 
... ... class Shape {
13 16 bounds[1][1] = maxY bounds[1][1] = maxY
14 17 +/ +/
15 18
19 public double size;
16 20 protected Context c; protected Context c;
17 21 protected double[2][2] bounds; protected double[2][2] bounds;
18 public double size;
19 public bool active;
20 22
21 23 this(int x, int y, Context context, double size = 0) { this(int x, int y, Context context, double size = 0) {
22 24 c = context; c = context;
 
... ... class Shape {
27 29 } }
28 30
29 31 @property @property
30 public abstract string type();
32 public override string to_string() {
33 string result = type ~ " ";
34 result ~= to!string(position[0]) ~ " ";
35 result ~= to!string(position[1]) ~ " ";
36 result ~= to!string(size) ~ "\n";
37
38 return result;
39 }
31 40
32 41 // Returns center of shape. // Returns center of shape.
33 42 @property @property
34 43 public abstract int[2] position(); public abstract int[2] position();
35 44
36 /+
37 public string toString() {
38 return text(type, " ", position[0], " ", position[1], " ", size);
39 }
40 +/
41
42 45 public abstract void resize(int amount); public abstract void resize(int amount);
43 46
44 47 protected abstract double[2][2] calcBounds(int x, int y); protected abstract double[2][2] calcBounds(int x, int y);
 
... ... class Shape {
49 52 this.bounds = calcBounds(x,y); this.bounds = calcBounds(x,y);
50 53 } }
51 54
52 public void checkBounds(int x, int y) {
55 public override void checkBounds(int x, int y) {
53 56 double[2] p = [to!double(x), to!double(y)]; double[2] p = [to!double(x), to!double(y)];
54 57
55 58 if ( if (
 
... ... class Shape {
62 65 } }
63 66 } }
64 67
65 public void render() {
68 public override void render() {
66 69 if(active) { if(active) {
70 writeln(type ~ to!string(Global.Brush.red));
71 c.setSourceRgba (
72 Global.Brush.red, Global.Brush.green,
73 Global.Brush.blue, Global.Brush.alpha
74 );
67 75 draw(); draw();
68 76 c.fill(); c.fill();
69 77 } }
File source/file.d changed (mode: 100644) (index 5a454bf..4d8c67e)
... ... import std.conv;
6 6 import std.array; import std.array;
7 7 import std.string; import std.string;
8 8
9 import dp.shape.shape;
10 import dp.shape.rect, dp.shape.circle, dp.shape.ellipse;
9 import dp.ent.entity;
10 import dp.ent.rect, dp.ent.circle, dp.ent.ellipse;
11 11 import dp.command.load; import dp.command.load;
12 12
13 13 import Global = dp.global; import Global = dp.global;
 
... ... public class Savefile {
20 20 content = ""; content = "";
21 21 this.filename = filename; this.filename = filename;
22 22 } }
23
24 public void toFile(Shape shape) {
23 /*
24 public void toFile(Shape shape, bool fromGroup = false) {
25 25 if(!shape.active) if(!shape.active)
26 26 return; return;
27 27
28 if(fromGroup)
29 content ~= "\t";
30
28 31 content ~= shape.type ~ " "; content ~= shape.type ~ " ";
29 32 content ~= to!string(shape.position[0]) ~ " "; content ~= to!string(shape.position[0]) ~ " ";
30 33 content ~= to!string(shape.position[1]) ~ " "; content ~= to!string(shape.position[1]) ~ " ";
31 34 content ~= to!string(shape.size) ~ "\n"; content ~= to!string(shape.size) ~ "\n";
32 35 } }
33 36
37 public void toFile(Group group) {
38 if(group.active)
39 content ~= "group " ~ to!string(group.length) ~ "\n";
40
41 group.save(this);
42 }
43 */
44
45 public void toFile(Entity entity) {
46 if(entity.active)
47 content ~= entity.to_string();
48 }
49
34 50 public void fromFile() { public void fromFile() {
35 Shape[] shapes = [];
51 Entity[] entities = [];
36 52 File f = File(filename, "r"); File f = File(filename, "r");
37 53
38 54 while(!f.eof()) { while(!f.eof()) {
 
... ... public class Savefile {
41 57 if(line == "") if(line == "")
42 58 break; break;
43 59
44 shapes.length++;
45 shapes[shapes.length - 1] = parseLine(line);
60 entities.length++;
61 entities[entities.length - 1] = parseLine(line);
46 62 } }
47 63
48 64 f.close(); f.close();
49 65
50 66 Global.History.clear(); Global.History.clear();
51 Global.History.addCommand(new LoadCmd(shapes));
67 Global.History.addCommand(new LoadCmd(entities));
52 68 } }
53 69
54 70 public void save() { public void save() {
 
... ... public class Savefile {
60 76 content = ""; content = "";
61 77 } }
62 78
63 private Shape parseLine(string line) {
79 private Entity parseLine(string line) {
64 80 auto words = line.split(); auto words = line.split();
65 81
66 82 writeln(words); writeln(words);
File source/frontend/mainWindow.d changed (mode: 100644) (index e915f48..5dccf9c)
... ... module dp.win.main;
3 3 import gtk.Application; import gtk.Application;
4 4 import gtk.ApplicationWindow; import gtk.ApplicationWindow;
5 5 import gtk.Box; import gtk.Box;
6 import gtk.Label;
6 7
7 8 import Global = dp.global; import Global = dp.global;
8 9 import dp.menubar; import dp.menubar;
 
... ... class Win : ApplicationWindow {
20 21
21 22 Global.init(); Global.init();
22 23 container.add(Global.canvas); container.add(Global.canvas);
24 container.add(Global.selection);
23 25
24 26 add(container); add(container);
25 27 showAll(); showAll();
File source/frontend/menubar.d changed (mode: 100644) (index 72636ab..2f2bcf9)
... ... import gtk.MenuBar, gtk.Menu, gtk.MenuItem;
5 5 import gtk.Widget; import gtk.Widget;
6 6 import gdk.Event; import gdk.Event;
7 7
8 import dp.shape.rect;
8 import dp.ent.rect;
9 import dp.ent.group;
9 10 import dp.command.load; import dp.command.load;
11 import dp.command.create;
12
13 import std.conv;
10 14
11 15 import Global = dp.global; import Global = dp.global;
12 16
 
... ... public class Menubar : Box {
19 23 menubar.append(new FileMenu()); menubar.append(new FileMenu());
20 24 menubar.append(new EditMenu()); menubar.append(new EditMenu());
21 25 menubar.append(new ShapeMenu()); menubar.append(new ShapeMenu());
26 menubar.append(new GroupMenu());
22 27
23 28 this.packStart(menubar, false, false, 0); this.packStart(menubar, false, false, 0);
24 29 } }
 
... ... public class ShapeMenu : MenuItem { // protected
144 149 return true; return true;
145 150 } }
146 151 } }
152
153 public class GroupMenu : MenuItem { // protected
154 Menu groupMenu;
155
156 MenuItem newGroup;
157 MenuItem clearGroup;
158 MenuItem[] existingGroups = [];
159
160 this () {
161 super("Groups");
162 groupMenu = new Menu();
163 this.addOnButtonPress(&activateCallback);
164
165 clearGroup = new MenuItem("Clear group selection");
166 clearGroup.addOnButtonPress(&clearGroupCallback);
167 groupMenu.append(clearGroup);
168
169 newGroup = new MenuItem("Add new group");
170 newGroup.addOnButtonPress(&newGroupCallback);
171 groupMenu.append(newGroup);
172
173 setSubmenu(groupMenu);
174 }
175
176 private bool activateCallback(Event event, Widget widget) {
177 showAll();
178 return false;
179 }
180
181 private bool clearGroupCallback(Event event, Widget widget) {
182 Global.Brush.group = null;
183 Global.selection.update(null);
184 return true;
185 }
186
187 private bool newGroupCallback(Event event, Widget widget) {
188 size_t index = Global.groups.length++;
189 existingGroups.length = Global.groups.length;
190
191 Global.Brush.group = Global.groups[index] = new Group();
192
193 existingGroups[index] = new MenuItem("Group " ~ to!string(index));
194 existingGroups[index].addOnButtonPress(&exGroupCallback);
195 groupMenu.append(existingGroups[index]);
196 exGroupCallback(null, existingGroups[index]);
197
198 return true;
199 }
200
201 private bool exGroupCallback(Event event, Widget widget) {
202 MenuItem item = cast(MenuItem) widget;
203 Global.selection.update(item.getLabel());
204 return true;
205 }
206 }
File source/frontend/resizeDialog.d changed (mode: 100644) (index 7cec216..b779f0f)
... ... import gtk.Label;
6 6 import gtk.Button; import gtk.Button;
7 7 import gtk.Entry; import gtk.Entry;
8 8
9 import dp.shape.shape;
9 import dp.ent.shape;
10 10 import dp.history; import dp.history;
11 11 import dp.command.resize; import dp.command.resize;
12 12
File source/frontend/shapeOptions.d changed (mode: 100644) (index e3a2650..4cc0932)
... ... 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.shape.shape;
7 import dp.ent.shape;
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;
File source/globals.d changed (mode: 100644) (index ccd5fa9..1914165)
1 1 module dp.global; module dp.global;
2 2
3 3 import dp.canvas; import dp.canvas;
4 import dp.selection;
4 5 import dp.shapeOptions; import dp.shapeOptions;
6 import dp.ent.group;
5 7
6 8 public import dp.history; public import dp.history;
7 9 public import Brush = dp.brush; public import Brush = dp.brush;
8 10
9 11 public static Canvas canvas; public static Canvas canvas;
12 public static Selection selection;
10 13 public static ShapeOptions shapeOptn; public static ShapeOptions shapeOptn;
11 14
15 public static Group[] groups;
16
12 17 public static void init() { public static void init() {
18 selection = new Selection();
13 19 canvas = new Canvas(500,500); canvas = new Canvas(500,500);
14 20 shapeOptn = new ShapeOptions(); shapeOptn = new ShapeOptions();
21 groups = [];
15 22 Brush.clone = null; Brush.clone = null;
16 23 Brush.shape = null; Brush.shape = null;
17 24 Brush.red = 0.5; Brush.red = 0.5;
18 25 Brush.green = 0.9; Brush.green = 0.9;
19 26 Brush.blue = 0.5; Brush.blue = 0.5;
20 27 Brush.alpha = 0.8; Brush.alpha = 0.8;
28 Brush.group = null;
21 29 } }
File source/selection.d added (mode: 100644) (index 0000000..9076c2d)
1 module dp.selection;
2
3 import gtk.Label;
4
5 import std.conv;
6
7 public class Selection : Label {
8 this() {
9 super("No group selected.");
10 }
11
12 public void update(string groupname) {
13 groupname is null ? setText("No group selected") : setText("Selected group: '" ~ groupname ~ "'.");
14 show();
15 }
16 }
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