mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-02 10:23:51 +00:00
Bug 4104: Highlight most current tag when timer changes. Also removed direct write-access to list of tags at TagListProvider.
This commit is contained in:
1 parent
f2b1fafc2c
commit
18b9bdd86d
2 files changed
+130
-32
No files matched your search
+79
-18
@@ -1,22 +1,26 @@
|
||||
package com.sap.sailing.gwt.ui.raceboard.tagging;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.gwt.view.client.ListDataProvider;
|
||||
import com.sap.sailing.domain.common.dto.TagDTO;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.filter.Filter;
|
||||
import com.sap.sse.common.filter.FilterSet;
|
||||
|
||||
/**
|
||||
* Provides list of {@link TagDTO tags} and is able to filter theses {@link TagDTO tags} with the current selected
|
||||
* {@link FilterSet}.
|
||||
* Provides list of {@link TagDTO tags} sorted by race timepoint and is able to filter theses {@link TagDTO tags} with
|
||||
* the current selected {@link FilterSet}.
|
||||
*/
|
||||
public class TagListProvider extends ListDataProvider<TagDTO> {
|
||||
|
||||
private FilterSet<TagDTO, Filter<TagDTO>> currentFilterSet;
|
||||
/**
|
||||
* Stores {@link TagDTO tags} sorted by their {@link TagDTO#getRaceTimepoint() race timepoint}.
|
||||
*/
|
||||
private final List<TagDTO> allTags;
|
||||
private final List<TagFilterLabel> observingLabels;
|
||||
|
||||
@@ -28,6 +32,69 @@ public class TagListProvider extends ListDataProvider<TagDTO> {
|
||||
observingLabels = new ArrayList<TagFilterLabel>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link TagDTO tag} to {@link #getAllTags() list of all tags}.
|
||||
*
|
||||
* @param tag
|
||||
* tag to be added
|
||||
*/
|
||||
protected void add(TagDTO tag) {
|
||||
// tags are sorted by race timepoint
|
||||
for (int i = 0; i < allTags.size(); i++) {
|
||||
if (allTags.get(i).getRaceTimepoint().after(tag.getRaceTimepoint())) {
|
||||
allTags.add(i, tag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// add tag to end in case there is no newer tag
|
||||
allTags.add(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds list of {@link TagDTO tags} to {@link #getAllTags() list of all tags}.
|
||||
*
|
||||
* @param tags
|
||||
* tags to be added
|
||||
*/
|
||||
protected void addAll(List<TagDTO> tags) {
|
||||
for (TagDTO tag : tags) {
|
||||
add(tag);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes {@link TagDTO tag} from {@link #getAllTags() list of all tags}.
|
||||
*
|
||||
* @param tag
|
||||
* tag to be removed
|
||||
*/
|
||||
protected void remove(TagDTO tag) {
|
||||
allTags.remove(tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all private {@link TagDTO tags} from {@link #getAllTags() list of all tags}.
|
||||
*/
|
||||
protected void removePrivateTags() {
|
||||
allTags.removeIf(tag -> !tag.isVisibleForPublic());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears {@link #getAllTags() list of all tags}.
|
||||
*/
|
||||
protected void clear() {
|
||||
allTags.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns unmodifiable list of all {@link TagDTO tags} ignoring the {@link #currentFilterSet current filter set}.
|
||||
*
|
||||
* @return list of all {@link TagDTO tags}
|
||||
*/
|
||||
protected List<TagDTO> getAllTags() {
|
||||
return Collections.unmodifiableList(allTags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by {@link TagFilterLabel} to inform {@link TagFilterLabel} about changes of the {@link #currentFilterSet
|
||||
* current filter set}.
|
||||
@@ -48,15 +115,6 @@ public class TagListProvider extends ListDataProvider<TagDTO> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all {@link TagDTO tags} ignoring the {@link #currentFilterSet current filter set}.
|
||||
*
|
||||
* @return list of all {@link TagDTO tags}
|
||||
*/
|
||||
protected List<TagDTO> getAllTags() {
|
||||
return allTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of all {@link TagDTO tags} which are filtered by {@link #currentFilterSet current filter set}.
|
||||
*
|
||||
@@ -82,12 +140,15 @@ public class TagListProvider extends ListDataProvider<TagDTO> {
|
||||
}
|
||||
}
|
||||
|
||||
currentFilteredList.sort(new Comparator<TagDTO>() {
|
||||
@Override
|
||||
public int compare(TagDTO tag1, TagDTO tag2) {
|
||||
long time1 = tag1.getRaceTimepoint().asMillis();
|
||||
long time2 = tag2.getRaceTimepoint().asMillis();
|
||||
return time1 < time2 ? -1 : time1 == time2 ? 0 : 1;
|
||||
currentFilteredList.sort((tag1, tag2) -> {
|
||||
TimePoint tag1Time = tag1.getRaceTimepoint();
|
||||
TimePoint tag2Time = tag2.getRaceTimepoint();
|
||||
if (tag1Time.before(tag2Time)) {
|
||||
return -1;
|
||||
} else if (tag1Time.after(tag2Time)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
setList(currentFilteredList);
|
||||
|
||||
+51
-14
@@ -34,6 +34,7 @@ import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.gwt.client.Notification;
|
||||
import com.sap.sse.gwt.client.Notification.NotificationType;
|
||||
import com.sap.sse.gwt.client.player.TimeListener;
|
||||
import com.sap.sse.gwt.client.player.Timer;
|
||||
import com.sap.sse.gwt.client.shared.components.Component;
|
||||
import com.sap.sse.gwt.client.shared.components.ComponentWithoutSettings;
|
||||
@@ -57,7 +58,7 @@ import com.sap.sse.security.ui.shared.UserDTO;
|
||||
* TaggingPanel itself.
|
||||
*/
|
||||
public class TaggingPanel extends ComponentWithoutSettings
|
||||
implements RaceTimesInfoProviderListener, UserStatusEventHandler {
|
||||
implements RaceTimesInfoProviderListener, UserStatusEventHandler, TimeListener {
|
||||
|
||||
/**
|
||||
* Describes the {@link TaggingPanel#currentState current state} of the {@link TaggingPanel}.
|
||||
@@ -159,7 +160,15 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
tagCellList.setSelectionModel(tagSelectionModel);
|
||||
tagSelectionModel.addSelectionChangeHandler(event -> {
|
||||
// set time slider to corresponding position
|
||||
timer.setTime(tagSelectionModel.getSelectedObject().getRaceTimepoint().asMillis());
|
||||
TagDTO selectedTag = tagSelectionModel.getSelectedObject();
|
||||
if (selectedTag != null) {
|
||||
// remove time change listener when manual selecting tag cells as this could end in an infinite loop of
|
||||
// timer change -> automatic selection change -> timer change -> ...
|
||||
timer.removeTimeListener(this);
|
||||
timer.setTime(selectedTag.getRaceTimepoint().asMillis());
|
||||
// adding time change listener again
|
||||
timer.addTimeListener(this);
|
||||
}
|
||||
});
|
||||
|
||||
createTagsButton.setTitle(stringMessages.tagAddTags());
|
||||
@@ -307,7 +316,7 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
@Override
|
||||
public void onSuccess(SuccessInfo result) {
|
||||
if (result.isSuccessful()) {
|
||||
tagListProvider.getAllTags().remove(tag);
|
||||
tagListProvider.remove(tag);
|
||||
updateContent();
|
||||
if (!silent) {
|
||||
Notification.notify(stringMessages.tagRemovedSuccessfully(), NotificationType.SUCCESS);
|
||||
@@ -340,7 +349,7 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
@Override
|
||||
public void onSuccess(SuccessInfo result) {
|
||||
if (result.isSuccessful()) {
|
||||
tagListProvider.getAllTags().remove(tagToUpdate);
|
||||
tagListProvider.remove(tagToUpdate);
|
||||
// If old tag was or new tag is private, reload all private tags. Otherwise just refresh UI.
|
||||
if (!tagToUpdate.isVisibleForPublic() || !visibleForPublic) {
|
||||
reloadPrivateTags();
|
||||
@@ -370,9 +379,9 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<TagDTO> result) {
|
||||
tagListProvider.getAllTags().removeIf(tag -> !tag.isVisibleForPublic());
|
||||
tagListProvider.removePrivateTags();
|
||||
if (result != null && !result.isEmpty()) {
|
||||
tagListProvider.getAllTags().addAll(result);
|
||||
tagListProvider.addAll(result);
|
||||
}
|
||||
updateContent();
|
||||
}
|
||||
@@ -492,7 +501,8 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
// Setting footerPanel.setVisible(false) is not sufficient as panel would still be
|
||||
// rendered as 20px high white space instead of being hidden.
|
||||
// Fix: remove panel completely from footer.
|
||||
if (!currentState.equals(State.VIEW) || (currentState.equals(State.VIEW) && !getTagButtons().isEmpty())) {
|
||||
if (currentState != null && (!currentState.equals(State.VIEW)
|
||||
|| (currentState.equals(State.VIEW) && !getTagButtons().isEmpty()))) {
|
||||
taggingPanel.setFooterWidget(footerPanel);
|
||||
footerPanel.setCurrentState(currentState);
|
||||
} else {
|
||||
@@ -524,8 +534,6 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
boolean modifiedTags = false;
|
||||
// Will be true if latestReceivedTagTime needs to be updated in raceTimesInfoprovider, otherwise false.
|
||||
boolean updatedLatestTag = false;
|
||||
// local list of already received tags
|
||||
List<TagDTO> currentTags = tagListProvider.getAllTags();
|
||||
// createdAt or revokedAt timepoint of latest received tag
|
||||
TimePoint latestReceivedTagTime = raceTimesInfoProvider.getLatestReceivedTagTime(raceIdentifier);
|
||||
// get difference in tags since latestReceivedTagTime
|
||||
@@ -534,17 +542,17 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
if (tag.getRevokedAt() != null) {
|
||||
// received tag is revoked => latestReceivedTagTime will be revokedAt if revoke event
|
||||
// occured before latestReceivedTagTime
|
||||
currentTags.remove(tag);
|
||||
tagListProvider.remove(tag);
|
||||
modifiedTags = true;
|
||||
if (latestReceivedTagTime == null || (latestReceivedTagTime != null
|
||||
&& latestReceivedTagTime.before(tag.getRevokedAt()))) {
|
||||
latestReceivedTagTime = tag.getRevokedAt();
|
||||
updatedLatestTag = true;
|
||||
}
|
||||
} else if (!currentTags.contains(tag)) {
|
||||
} else if (!tagListProvider.getAllTags().contains(tag)) {
|
||||
// received tag is NOT revoked => latestReceivedTagTime will be createdAt if tag event
|
||||
// occured before latestReceivedTagTime
|
||||
currentTags.add(tag);
|
||||
tagListProvider.add(tag);
|
||||
modifiedTags = true;
|
||||
if (latestReceivedTagTime == null || (latestReceivedTagTime != null
|
||||
&& latestReceivedTagTime.before(tag.getCreatedAt()))) {
|
||||
@@ -586,7 +594,7 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
@Override
|
||||
public void onUserStatusChange(UserDTO user, boolean preAuthenticated) {
|
||||
// clear list of local tags to hide private tags of previous user and reset cache
|
||||
tagListProvider.getAllTags().clear();
|
||||
tagListProvider.clear();
|
||||
raceTimesInfoProvider.getRaceIdentifiers().forEach((raceIdentifier) -> {
|
||||
raceTimesInfoProvider.setLatestReceivedTagTime(raceIdentifier, null);
|
||||
});
|
||||
@@ -598,7 +606,33 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
|
||||
// update UI
|
||||
setCurrentState(State.VIEW);
|
||||
updateContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlights most current tag when timer changes.
|
||||
*/
|
||||
@Override
|
||||
public void timeChanged(Date newTime, Date oldTime) {
|
||||
// When reopening Tagging-Panel after it was opened and closed by the user, the TouchSplitLayoutPanel will
|
||||
// set the timer to the current time and not the race time, oldTime will be null in this case. This would cause
|
||||
// a jump in time as TaggingPanel selects most current tag when time changes. When time continues while timer is
|
||||
// in "play"-mode, oldValue won't be null. This can be used as a workaround to discover this "false" time
|
||||
// change.
|
||||
// => workaround: Check if oldValue is not null to avoid jumps in time
|
||||
if (oldTime != null) {
|
||||
TagDTO toHighlight = null;
|
||||
for (TagDTO tag : tagListProvider.getAllTags()) {
|
||||
if (tag.getRaceTimepoint().asDate().getTime() <= newTime.getTime()) {
|
||||
toHighlight = tag;
|
||||
} else if (tag.getRaceTimepoint().asDate().getTime() > newTime.getTime()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
tagSelectionModel.clear();
|
||||
if (toHighlight != null) {
|
||||
tagSelectionModel.setSelected(toHighlight, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -629,8 +663,10 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
if (raceTimesInfoProvider != null) {
|
||||
if (visible) {
|
||||
raceTimesInfoProvider.enableTagRequests();
|
||||
timer.addTimeListener(this);
|
||||
} else {
|
||||
raceTimesInfoProvider.disableTagRequests();
|
||||
timer.removeTimeListener(this);
|
||||
}
|
||||
}
|
||||
taggingPanel.setVisible(visible);
|
||||
@@ -640,4 +676,5 @@ public class TaggingPanel extends ComponentWithoutSettings
|
||||
public String getDependentCssClassName() {
|
||||
return "tags";
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user