Skip to content

Commit d7276d0

Browse files
authored
Merge pull request #23 from doubleSlashde/feature/settings_color_timeline
Feature/settings color timeline
2 parents 9f05955 + dbbe715 commit d7276d0

File tree

10 files changed

+238
-107
lines changed

10 files changed

+238
-107
lines changed

src/main/java/de/doubleslash/keeptime/Main.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ private void readSettings() {
173173
final Settings settings;
174174
if (settingsList.isEmpty()) {
175175
settings = new Settings();
176-
settings.setTaskBarColor(Model.TASK_BAR_COLOR.get());
176+
settings.setTaskBarColor(model.taskBarColor.get());
177177

178178
settings.setDefaultBackgroundColor(Model.ORIGINAL_DEFAULT_BACKGROUND_COLOR);
179179
settings.setDefaultFontColor(Model.ORIGINAL_DEFAULT_FONT_COLOR);
@@ -188,23 +188,23 @@ private void readSettings() {
188188
settings = settingsList.get(0);
189189
}
190190

191-
Model.DEFAULT_BACKGROUND_COLOR.set(settings.getDefaultBackgroundColor());
192-
Model.DEFAULT_FONT_COLOR.set(settings.getDefaultFontColor());
193-
Model.HOVER_BACKGROUND_COLOR.set(settings.getHoverBackgroundColor());
194-
Model.HOVER_FONT_COLOR.set(settings.getHoverFontColor());
195-
Model.TASK_BAR_COLOR.set(settings.getTaskBarColor());
196-
Model.USE_HOTKEY.set(settings.isUseHotkey());
197-
Model.DISPLAY_PROJECTS_RIGHT.set(settings.isDisplayProjectsRight());
198-
Model.HIDE_PROJECTS_ON_MOUSE_EXIT.set(settings.isHideProjectsOnMouseExit());
191+
model.defaultBackgroundColor.set(settings.getDefaultBackgroundColor());
192+
model.defaultFontColor.set(settings.getDefaultFontColor());
193+
model.hoverBackgroundColor.set(settings.getHoverBackgroundColor());
194+
model.hoverFontColor.set(settings.getHoverFontColor());
195+
model.taskBarColor.set(settings.getTaskBarColor());
196+
model.useHotkey.set(settings.isUseHotkey());
197+
model.displayProjectsRight.set(settings.isDisplayProjectsRight());
198+
model.hideProjectsOnMouseExit.set(settings.isHideProjectsOnMouseExit());
199199
}
200200

201201
private void initialisePopupUI(final Stage primaryStage) throws IOException {
202202
LOG.debug("Initialising popup UI.");
203203

204204
globalScreenListener = new GlobalScreenListener();
205205

206-
Model.USE_HOTKEY.addListener((a, b, newValue) -> globalScreenListener.register(newValue));
207-
globalScreenListener.register(Model.USE_HOTKEY.get());
206+
model.useHotkey.addListener((a, b, newValue) -> globalScreenListener.register(newValue));
207+
globalScreenListener.register(model.useHotkey.get());
208208

209209
popupViewStage = new Stage();
210210
popupViewStage.initOwner(primaryStage);

src/main/java/de/doubleslash/keeptime/controller/Controller.java

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.time.LocalDateTime;
2222
import java.util.ArrayList;
2323
import java.util.List;
24-
import java.util.Optional;
2524

2625
import javax.annotation.PreDestroy;
2726

@@ -59,7 +58,7 @@ public void changeProject(final Project newProject) {
5958
}
6059

6160
public void changeProject(final Project newProject, final long minusSeconds) {
62-
final Work currentWork = Model.activeWorkItem.get();
61+
final Work currentWork = model.activeWorkItem.get();
6362

6463
final LocalDateTime now = dateProvider.dateTimeNow().minusSeconds(minusSeconds);
6564
final LocalDate dateNow = now.toLocalDate();
@@ -89,7 +88,7 @@ public void changeProject(final Project newProject, final long minusSeconds) {
8988
model.getPastWorkItems().removeIf(w -> !dateNow.isEqual(w.getCreationDate()));
9089
LOG.debug("Removed '{}' work items from past work items.", sizeBefore - model.getPastWorkItems().size());
9190
}
92-
Model.activeWorkItem.set(work);
91+
model.activeWorkItem.set(work);
9392
}
9493

9594
public void addNewProject(final String projectName, final boolean isWork, final Color projectColor,
@@ -122,14 +121,14 @@ public void updateSettings(final Color hoverBackgroundColor, final Color hoverFo
122121

123122
model.getSettingsRepository().save(settings);
124123

125-
Model.DEFAULT_BACKGROUND_COLOR.set(settings.getDefaultBackgroundColor());
126-
Model.DEFAULT_FONT_COLOR.set(settings.getDefaultFontColor());
127-
Model.HOVER_BACKGROUND_COLOR.set(settings.getHoverBackgroundColor());
128-
Model.HOVER_FONT_COLOR.set(settings.getHoverFontColor());
129-
Model.TASK_BAR_COLOR.set(settings.getTaskBarColor());
130-
Model.USE_HOTKEY.set(settings.isUseHotkey());
131-
Model.DISPLAY_PROJECTS_RIGHT.set(settings.isDisplayProjectsRight());
132-
Model.HIDE_PROJECTS_ON_MOUSE_EXIT.set(settings.isHideProjectsOnMouseExit());
124+
model.defaultBackgroundColor.set(settings.getDefaultBackgroundColor());
125+
model.defaultFontColor.set(settings.getDefaultFontColor());
126+
model.hoverBackgroundColor.set(settings.getHoverBackgroundColor());
127+
model.hoverFontColor.set(settings.getHoverFontColor());
128+
model.taskBarColor.set(settings.getTaskBarColor());
129+
model.useHotkey.set(settings.isUseHotkey());
130+
model.displayProjectsRight.set(settings.isDisplayProjectsRight());
131+
model.hideProjectsOnMouseExit.set(settings.isHideProjectsOnMouseExit());
133132
}
134133

135134
@PreDestroy
@@ -245,37 +244,49 @@ List<Project> adaptProjectIndexesAfterRemoving(final List<Project> originalList,
245244
}
246245

247246
public void setComment(final String notes) {
248-
final Work work = Model.activeWorkItem.get();
247+
final Work work = model.activeWorkItem.get();
249248
work.setNotes(notes);
250249
}
251250

252251
/**
253252
* Calculate todays seconds counted as work
254253
*/
255254
public long calcTodaysWorkSeconds() {
255+
final List<Work> workItems = new ArrayList<>();
256256

257-
return model.getPastWorkItems().stream().filter(work -> {
257+
for (final Work work : model.getPastWorkItems()) {
258258
final Project project = work.getProject();
259-
// find up to date reference to project
260-
final Optional<Project> optionalProject = model.getAllProjects().stream()
261-
.filter(p -> p.getId() == project.getId()).findAny();
262-
if (optionalProject.isPresent()) {
263-
return optionalProject.get().isWork();
259+
for (final Project p : model.getAllProjects()) {
260+
if (p.getId() == project.getId()) {
261+
if (p.isWork()) {
262+
workItems.add(work);
263+
}
264+
break;
265+
}
264266
}
265-
// TODO should not happen
266-
return false;
267-
}).mapToLong(work -> Duration.between(work.getStartTime(), work.getEndTime()).getSeconds()).sum();
267+
}
268+
269+
return calcSeconds(workItems);
268270
}
269271

270272
/**
271273
* Calculate todays present seconds (work+nonWork)
272274
*/
273275
public long calcTodaysSeconds() {
274-
return model.getPastWorkItems().stream()
275-
.mapToLong(work -> Duration.between(work.getStartTime(), work.getEndTime()).getSeconds()).sum();
276+
return calcSeconds(model.getPastWorkItems());
276277
}
277278

278279
public ObservableList<Project> getAvailableProjects() {
279280
return model.getAvailableProjects();
280281
}
282+
283+
public long calcSeconds(final List<Work> workItems) {
284+
long seconds = 0;
285+
286+
for (final Work w : workItems) {
287+
seconds += Duration.between(w.getStartTime(), w.getEndTime()).getSeconds();
288+
}
289+
290+
return seconds;
291+
}
281292
}

src/main/java/de/doubleslash/keeptime/model/Model.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,21 +62,20 @@ public Model(final ProjectRepository projectRepository, final WorkRepository wor
6262
Comparator.comparing(Project::getIndex));
6363
private ObservableList<Project> allProjects = FXCollections.observableArrayList();
6464

65-
protected static final ObservableList<Work> pastWorkItems = FXCollections.observableArrayList();
66-
public static final ObjectProperty<Work> activeWorkItem = new SimpleObjectProperty<>();
65+
protected final ObservableList<Work> pastWorkItems = FXCollections.observableArrayList();
66+
public final ObjectProperty<Work> activeWorkItem = new SimpleObjectProperty<>();
6767

68-
public static final ObjectProperty<Color> TASK_BAR_COLOR = new SimpleObjectProperty<>(ORIGINAL_TASK_BAR_FONT_COLOR);
68+
public final ObjectProperty<Color> taskBarColor = new SimpleObjectProperty<>(ORIGINAL_TASK_BAR_FONT_COLOR);
6969

70-
public static final ObjectProperty<Color> HOVER_BACKGROUND_COLOR = new SimpleObjectProperty<>(
70+
public final ObjectProperty<Color> hoverBackgroundColor = new SimpleObjectProperty<>(
7171
ORIGINAL_HOVER_BACKGROUND_COLOR);
72-
public static final ObjectProperty<Color> HOVER_FONT_COLOR = new SimpleObjectProperty<>(ORIGINAL_HOVER_Font_COLOR);
73-
public static final ObjectProperty<Color> DEFAULT_BACKGROUND_COLOR = new SimpleObjectProperty<>(
72+
public final ObjectProperty<Color> hoverFontColor = new SimpleObjectProperty<>(ORIGINAL_HOVER_Font_COLOR);
73+
public final ObjectProperty<Color> defaultBackgroundColor = new SimpleObjectProperty<>(
7474
ORIGINAL_DEFAULT_BACKGROUND_COLOR);
75-
public static final ObjectProperty<Color> DEFAULT_FONT_COLOR = new SimpleObjectProperty<>(
76-
ORIGINAL_DEFAULT_FONT_COLOR);
77-
public static final ObjectProperty<Boolean> USE_HOTKEY = new SimpleObjectProperty<>(false);
78-
public static final ObjectProperty<Boolean> DISPLAY_PROJECTS_RIGHT = new SimpleObjectProperty<>(false);
79-
public static final ObjectProperty<Boolean> HIDE_PROJECTS_ON_MOUSE_EXIT = new SimpleObjectProperty<>(true);
75+
public final ObjectProperty<Color> defaultFontColor = new SimpleObjectProperty<>(ORIGINAL_DEFAULT_FONT_COLOR);
76+
public final ObjectProperty<Boolean> useHotkey = new SimpleObjectProperty<>(false);
77+
public final ObjectProperty<Boolean> displayProjectsRight = new SimpleObjectProperty<>(false);
78+
public final ObjectProperty<Boolean> hideProjectsOnMouseExit = new SimpleObjectProperty<>(true);
8079

8180
public void setWorkRepository(final WorkRepository workRepository) {
8281
this.workRepository = workRepository;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2019 doubleSlash Net Business GmbH
2+
//
3+
// This file is part of KeepTime.
4+
// KeepTime is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package de.doubleslash.keeptime.view;
18+
19+
import java.time.Duration;
20+
import java.util.List;
21+
22+
import de.doubleslash.keeptime.model.Work;
23+
import javafx.scene.canvas.Canvas;
24+
import javafx.scene.canvas.GraphicsContext;
25+
import javafx.scene.paint.Color;
26+
27+
public class ColorTimeLine {
28+
29+
private final Canvas canvas;
30+
31+
public ColorTimeLine(final Canvas canvas) {
32+
this.canvas = canvas;
33+
}
34+
35+
public void update(final List<Work> workItems, final long seconds) {
36+
final GraphicsContext gc = canvas.getGraphicsContext2D();
37+
38+
gc.setFill(new Color(.3, .3, .3, .3));
39+
gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
40+
gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());
41+
double currentX = 0;
42+
for (final Work w : workItems) {
43+
final long workedSeconds = Duration.between(w.getStartTime(), w.getEndTime()).getSeconds();
44+
final double width = (double) workedSeconds / seconds * canvas.getWidth();
45+
final Color fill = w.getProject().getColor();
46+
47+
gc.setFill(fill);
48+
gc.fillRect(currentX, 0, width, canvas.getHeight());
49+
50+
currentX += width;
51+
}
52+
53+
}
54+
55+
}

src/main/java/de/doubleslash/keeptime/view/ReportController.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,17 @@
3030

3131
import de.doubleslash.keeptime.common.DateFormatter;
3232
import de.doubleslash.keeptime.common.FontProvider;
33+
import de.doubleslash.keeptime.controller.Controller;
3334
import de.doubleslash.keeptime.model.Model;
3435
import de.doubleslash.keeptime.model.Project;
3536
import de.doubleslash.keeptime.model.Work;
3637
import javafx.event.ActionEvent;
3738
import javafx.event.EventHandler;
3839
import javafx.fxml.FXML;
40+
import javafx.geometry.Insets;
41+
import javafx.geometry.Pos;
3942
import javafx.scene.Node;
43+
import javafx.scene.canvas.Canvas;
4044
import javafx.scene.control.Button;
4145
import javafx.scene.control.DateCell;
4246
import javafx.scene.control.DatePicker;
@@ -46,6 +50,8 @@
4650
import javafx.scene.input.ClipboardContent;
4751
import javafx.scene.layout.BorderPane;
4852
import javafx.scene.layout.GridPane;
53+
import javafx.scene.layout.HBox;
54+
import javafx.scene.shape.Circle;
4955
import javafx.util.Callback;
5056

5157
public class ReportController {
@@ -71,12 +77,19 @@ public class ReportController {
7177
@FXML
7278
private ScrollPane scrollPane;
7379

80+
@FXML
81+
private Canvas colorTimeLineCanvas;
82+
7483
private static final Logger LOG = LoggerFactory.getLogger(ReportController.class);
7584

76-
private DatePicker datePicker; // for calender element
85+
private DatePicker datePicker; // for calendar element
7786

7887
private Model model;
7988

89+
private Controller controller;
90+
91+
private ColorTimeLine colorTimeLine;
92+
8093
@FXML
8194
private void initialize() {
8295
LOG.info("Init reportController");
@@ -86,17 +99,22 @@ private void initialize() {
8699
LOG.info("Datepicker selected value changed to {}", newvalue);
87100
updateReport(newvalue);
88101
});
102+
103+
colorTimeLine = new ColorTimeLine(colorTimeLineCanvas);
89104
}
90105

91106
private void updateReport(final LocalDate newvalue) {
92107
this.currentDayLabel.setText(DateFormatter.toDayDateString(newvalue));
93108
final List<Work> currentWorkItems = model.getWorkRepository().findByCreationDate(newvalue);
94109

110+
colorTimeLine.update(currentWorkItems, controller.calcSeconds(currentWorkItems));
111+
95112
final SortedSet<Project> workedProjectsSet = currentWorkItems.stream().map(Work::getProject)
96113
.collect(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Project::getName))));
97114

98115
this.gridPane.getChildren().clear();
99116
this.gridPane.getRowConstraints().clear();
117+
this.gridPane.getColumnConstraints().get(0).setPrefWidth(300);
100118

101119
int rowIndex = 0;
102120
long currentWorkSeconds = 0;
@@ -105,13 +123,23 @@ private void updateReport(final LocalDate newvalue) {
105123
for (final Project project : workedProjectsSet) {
106124
final Label projectName = new Label(project.getName());
107125
projectName.setFont(FontProvider.getBoldFont());
108-
this.gridPane.add(projectName, 0, rowIndex);
126+
projectName.setUnderline(project.isWork());
127+
final Circle circle = new Circle(5, project.getColor());
128+
129+
final HBox projectNameHBox = new HBox();
130+
projectNameHBox.setAlignment(Pos.CENTER_LEFT);
131+
projectNameHBox.setPadding(new Insets(0, 0, 0, 5));
132+
projectNameHBox.setSpacing(5);
133+
134+
projectNameHBox.getChildren().add(circle);
135+
projectNameHBox.getChildren().add(projectName);
136+
137+
this.gridPane.add(projectNameHBox, 0, rowIndex);
109138

110139
final List<Work> onlyCurrentProjectWork = currentWorkItems.stream().filter(w -> w.getProject() == project)
111140
.collect(Collectors.toList());
112141

113-
final long todaysWorkSeconds = onlyCurrentProjectWork.stream()
114-
.mapToLong(work -> DateFormatter.getSecondsBewtween(work.getStartTime(), work.getEndTime())).sum();
142+
final long todaysWorkSeconds = controller.calcSeconds(onlyCurrentProjectWork);
115143

116144
currentSeconds += todaysWorkSeconds;
117145
if (project.isWork()) {
@@ -153,13 +181,13 @@ private void updateReport(final LocalDate newvalue) {
153181

154182
rowIndex++;
155183
}
156-
// textArea.setText(pr.getNotes(true));
157184
bProjectReport.setUserData(pr.getNotes(true));
158185
}
159186
this.scrollPane.setVvalue(0); // scroll to the top
160187

161188
this.currentDayTimeLabel.setText(DateFormatter.secondsToHHMMSS(currentSeconds));
162189
this.currentDayWorkTimeLabel.setText(DateFormatter.secondsToHHMMSS(currentWorkSeconds));
190+
163191
}
164192

165193
private Button createProjectReport() {
@@ -209,4 +237,8 @@ public void updateItem(final LocalDate item, final boolean empty) {
209237
public void update() {
210238
updateReport(this.datePicker.getValue());
211239
}
240+
241+
public void setController(final Controller controller) {
242+
this.controller = controller;
243+
}
212244
}

0 commit comments

Comments
 (0)