From 8ec86f1907f4af0068110e4786e33e06bcdce41c Mon Sep 17 00:00:00 2001 From: Adam Peter Banham Date: Tue, 12 Jul 2022 11:51:40 +1000 Subject: [PATCH] separated code for ProMList away from controllers --- .../gui/ExogenousTraceView.java | 267 +----------------- .../TraceBreakdownEventListener.java | 37 +-- .../gui/promlist/EventHighlightWedger.java | 35 +++ .../gui/promlist/ProMListComponents.java | 246 ++++++++++++++++ .../gui/promlist/WedgeBuilderFactory.java | 26 ++ .../workers/TraceVisTraceBreakdownCharts.java | 2 +- 6 files changed, 325 insertions(+), 288 deletions(-) create mode 100644 src/org/processmining/qut/exogenousaware/gui/promlist/EventHighlightWedger.java create mode 100644 src/org/processmining/qut/exogenousaware/gui/promlist/ProMListComponents.java create mode 100644 src/org/processmining/qut/exogenousaware/gui/promlist/WedgeBuilderFactory.java diff --git a/src/org/processmining/qut/exogenousaware/gui/ExogenousTraceView.java b/src/org/processmining/qut/exogenousaware/gui/ExogenousTraceView.java index 8c1d480..894c633 100644 --- a/src/org/processmining/qut/exogenousaware/gui/ExogenousTraceView.java +++ b/src/org/processmining/qut/exogenousaware/gui/ExogenousTraceView.java @@ -7,9 +7,6 @@ import java.awt.Font; import java.awt.GridLayout; import java.awt.event.MouseEvent; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -25,7 +22,6 @@ import org.deckfour.xes.model.XAttributeTimestamp; import org.deckfour.xes.model.XEvent; import org.deckfour.xes.model.XTrace; -import org.deckfour.xes.model.impl.XAttributeLiteralImpl; import org.jfree.chart.ChartPanel; import org.processmining.contexts.uitopia.UIPluginContext; import org.processmining.contexts.uitopia.annotations.Visualizer; @@ -34,13 +30,11 @@ import org.processmining.framework.util.ui.widgets.ProMSplitPane; import org.processmining.framework.util.ui.widgets.traceview.ProMTraceList; import org.processmining.framework.util.ui.widgets.traceview.ProMTraceList.ClickListener; -import org.processmining.framework.util.ui.widgets.traceview.ProMTraceList.TraceBuilder; -import org.processmining.framework.util.ui.widgets.traceview.ProMTraceView.Event; -import org.processmining.framework.util.ui.widgets.traceview.ProMTraceView.Trace; import org.processmining.qut.exogenousaware.data.ExogenousAnnotatedLog; import org.processmining.qut.exogenousaware.gui.listeners.EndoTraceListener; import org.processmining.qut.exogenousaware.gui.panels.ExogenousTraceViewJChartFilterPanel; import org.processmining.qut.exogenousaware.gui.panels.ExogenousTraceViewJChartFilterPanel.EventFilter; +import org.processmining.qut.exogenousaware.gui.promlist.ProMListComponents.exoTraceBuilder; import org.processmining.qut.exogenousaware.gui.workers.TraceVisEventChart; import org.processmining.qut.exogenousaware.gui.workers.TraceVisOverviewChart; import org.processmining.qut.exogenousaware.gui.workers.TraceVisTraceBreakdownCharts; @@ -299,7 +293,6 @@ public void highlightEventSlice(XTrace trace, int eventIndex) { } } - public boolean setSelectEndogenous(XTrace select, EndoTraceListener listener) { if (this.selectedEndogenous == null) { this.selectedEndogenous = select; @@ -344,7 +337,7 @@ public boolean setSelectEndogenous(XTrace select) { } public double getEventTimestampMillis(XEvent ev) { - return (double) ((XAttributeTimestamp) ev.getAttributes().get("time:timestamp")).getValueMillis(); + return ((XAttributeTimestamp) ev.getAttributes().get("time:timestamp")).getValueMillis(); } public double getExoEventValue(XEvent ev) { @@ -369,8 +362,7 @@ public void updateTraceBreakdownEvent(XEvent ev, int eventIndex) { this.traceBreakdownView.removeFilter(this.eventfilter); this.eventfilter = null; } -// this.traceBreakdownView.validate(); -// this.traceBreakdownView.getParent().validate(); + this.rightTopBottom.validate(); } @@ -385,6 +377,17 @@ public JPanel buildIndividualEventBreakdown(XEvent ev) { return chartbuilder.getView(); } + public static JLabel createLeftAlignedLabel(String text, Boolean bold, int fontSize) { + JLabel label = new JLabel(text, SwingConstants.LEADING); + label.setFont(new Font("Times new Roman", bold ? Font.BOLD : null, fontSize)); + label.setBackground(Color.DARK_GRAY); + label.setHorizontalAlignment(JLabel.LEFT); + label.setAlignmentX(JPanel.RIGHT_ALIGNMENT); + return label; + } + + +// interfaces public static class endoClickListener implements ClickListener { private ExogenousTraceView source; @@ -395,257 +398,15 @@ public endoClickListener(ExogenousTraceView source) { @Override public void traceMouseDoubleClicked(XTrace trace, int traceIndex, int eventIndex, MouseEvent e) { - // TODO Auto-generated method stub this.source.setSelectEndogenous(trace); } @Override public void traceMouseClicked(XTrace trace, int traceIndex, int eventIndex, MouseEvent e) { - // TODO Auto-generated method stub this.source.setSelectEndogenous(trace); } } - - public static JLabel createLeftAlignedLabel(String text, Boolean bold, int fontSize) { - JLabel label = new JLabel(text, SwingConstants.LEADING); - label.setFont(new Font("Times new Roman", bold ? Font.BOLD : null, fontSize)); - label.setBackground(Color.DARK_GRAY); - label.setHorizontalAlignment(JLabel.LEFT); - label.setAlignmentX(JPanel.RIGHT_ALIGNMENT); - return label; - } - -// Usage -// #TODO colors for events with exogenous linked subseries -// ProMTraceList traceView = new ProMTraceList( -// new exoTraceBuilder() -// ); -// traceView.addAll(this.source.getEndogenousLog()); - public static class exoTraceBuilder implements TraceBuilder { - - private Set exoEvents; - private boolean highlight = false; - private int eventid = -1; - - public exoTraceBuilder(Set exoEvents) { - this.exoEvents = exoEvents; - } - - - @Override - public Trace build(XTrace element) { - // TODO Auto-generated method stub - Boolean hasExo = false; - if (element.getAttributes().keySet().contains("exogenous:exist")) { - hasExo = ((XAttributeLiteralImpl) element.getAttributes().get("exogenous:exist") ).getValue().contentEquals("True"); - } - if (this.highlight) { - return new exoTrace(element, - hasExo, - exoEvents, - this.eventid - ); - } else { - return new exoTrace(element, - hasExo, - exoEvents - ); - } - } - - public void setHighlight(int eventid) { - this.highlight = true; - this.eventid = eventid; - } - - public void dehighlight() { - this.highlight = false; - this.eventid = -1; - } - - - public static class exoTrace implements Trace { - - private XTrace source; - private Boolean hasExo; - private Set exoEvents; - private int highlightevent = -1; - - public exoTrace(XTrace source, Boolean hasExo, Set exoEvents) { - this(source,hasExo,exoEvents,-1); - } - - public exoTrace(XTrace source, Boolean hasExo, Set exoEvents, int highlightevent) { - this.source = source; - this.hasExo = hasExo; - this.exoEvents = exoEvents; - this.highlightevent = highlightevent; - } - - @Override - public Iterator iterator() { - - List evSet = this.source.stream().map(ev -> ev.getID().toString()).collect(Collectors.toList()); - return new exoIterator( - this.source.iterator(), - this.hasExo ? this.exoEvents.stream().filter(s -> evSet.contains(s)).collect(Collectors.toSet()) : new HashSet(), - this.highlightevent - ); - } - - @Override - public String getName() { - return this.source.getAttributes().get("concept:name").toString(); - } - - @Override - public Color getNameColor() { - return this.hasExo ? new Color(65,150,98) : Color.red; - } - @Override - public String getInfo() { - // TODO Auto-generated method stub - String info = ""; - for(String key: this.source.getAttributes().keySet()) { - info += String.format("%s : %s \n", - key, this.source.getAttributes().get(key) - ); - } - return info; - } - - @Override - public Color getInfoColor() { - // TODO Auto-generated method stub - return Color.black; - } - - } - - public static class exoIterator implements Iterator { - - Iterator source; - private Set exoEvents; - private int highlightevent = -1; - private int counter = -1; - - public exoIterator(Iterator source, Set exoEvents, int highlightevent) { - this.source = source; - this.exoEvents = exoEvents; - this.highlightevent = highlightevent; - } - - @Override - public boolean hasNext() { - // TODO Auto-generated method stub - return this.source.hasNext(); - } - - @Override - public Event next() { - // TODO Auto-generated method stub - this.counter++; - XEvent ev = this.source.next(); - return new exoEvent( - ev, - counter, - ev.getAttributes().keySet().stream().anyMatch(s -> s.contains("exogenous:dataset")), - this.counter == this.highlightevent - ); - } - - } - - public static class exoEvent implements Event { - - private XEvent source; - private boolean hasExo; - private boolean highlight; - public int eventID; - - public exoEvent(XEvent source, int eventID, boolean hasExo) { - this(source, eventID, hasExo, false); - } - - public exoEvent(XEvent source, int eventID, boolean hasExo, boolean highlight) { - this.source = source; - this.hasExo = hasExo; - this.highlight = highlight; - this.eventID = eventID; - } - - public void setHighlight(boolean highlight) { - this.highlight = highlight; - } - - @Override - public Color getWedgeColor() { - if (this.highlight) { - return Color.orange; - } - else if (this.hasExo) { - return new Color(65,150,98); - } else { - return Color.red; - } - } - - @Override - public Color getBorderColor() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getLabel() { - return this.source.getAttributes().get("concept:name").toString(); - } - - @Override - public Color getLabelColor() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getTopLabel() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Color getTopLabelColor() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getBottomLabel() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Color getBottomLabelColor() { - // TODO Auto-generated method stub - return null; - } - - @Override - public String getBottomLabel2() { - // TODO Auto-generated method stub - return null; - } - - @Override - public Color getBottomLabel2Color() { - // TODO Auto-generated method stub - return null; - } - - } - } } diff --git a/src/org/processmining/qut/exogenousaware/gui/listeners/TraceBreakdownEventListener.java b/src/org/processmining/qut/exogenousaware/gui/listeners/TraceBreakdownEventListener.java index 6e041ae..53f5cf9 100644 --- a/src/org/processmining/qut/exogenousaware/gui/listeners/TraceBreakdownEventListener.java +++ b/src/org/processmining/qut/exogenousaware/gui/listeners/TraceBreakdownEventListener.java @@ -1,18 +1,14 @@ package org.processmining.qut.exogenousaware.gui.listeners; -import java.awt.Color; import java.awt.event.MouseEvent; import org.deckfour.xes.model.XEvent; import org.deckfour.xes.model.XTrace; import org.processmining.framework.util.ui.widgets.traceview.ProMTraceList; import org.processmining.framework.util.ui.widgets.traceview.ProMTraceList.ClickListener; -import org.processmining.framework.util.ui.widgets.traceview.ProMTraceList.DefaultWedgeBuilder; -import org.processmining.framework.util.ui.widgets.traceview.ProMTraceView.Event; -import org.processmining.framework.util.ui.widgets.traceview.ProMTraceView.Trace; import org.processmining.qut.exogenousaware.gui.ExogenousTraceView; -import org.processmining.qut.exogenousaware.gui.ExogenousTraceView.exoTraceBuilder; -import org.processmining.qut.exogenousaware.gui.ExogenousTraceView.exoTraceBuilder.exoEvent; +import org.processmining.qut.exogenousaware.gui.promlist.ProMListComponents.exoTraceBuilder; +import org.processmining.qut.exogenousaware.gui.promlist.WedgeBuilderFactory; import lombok.Builder; import lombok.NonNull; @@ -43,37 +39,10 @@ public void traceMouseClicked(XTrace trace, int traceIndex, int eventIndex, Mous // highlight this event slice in the overview chart this.source.highlightEventSlice(trace, eventIndex); // highlight wedge that was clicked - this.controller.setWedgeBuilder(new AdjustedWedgeBuilder(previousEvent != eventIndex ? eventIndex : -2)); + this.controller.setWedgeBuilder(WedgeBuilderFactory.createEventHighlight(previousEvent != eventIndex ? eventIndex : -2)); this.controller.updateUI(); this.previousEvent = previousEvent == eventIndex ? -1 : eventIndex; } } - - public class AdjustedWedgeBuilder extends DefaultWedgeBuilder { - - private int highlight = -1; - - public AdjustedWedgeBuilder(int highlight) { - this.highlight = highlight; - } - - @Override - public Color buildWedgeColor(Trace trace, Event event) { - exoEvent neweventype = (exoEvent) event; - neweventype.setHighlight(neweventype.eventID == this.highlight); - return event.getWedgeColor(); - - } - - @Override - public Integer assignWedgeGap(Trace trace, Event event) { - exoEvent neweventype = (exoEvent) event; - if ((neweventype.eventID == this.highlight)||(neweventype.eventID==(this.highlight-1))) { - return 10; - } - return null; - } - - } } diff --git a/src/org/processmining/qut/exogenousaware/gui/promlist/EventHighlightWedger.java b/src/org/processmining/qut/exogenousaware/gui/promlist/EventHighlightWedger.java new file mode 100644 index 0000000..5263504 --- /dev/null +++ b/src/org/processmining/qut/exogenousaware/gui/promlist/EventHighlightWedger.java @@ -0,0 +1,35 @@ +package org.processmining.qut.exogenousaware.gui.promlist; + +import java.awt.Color; + +import org.processmining.framework.util.ui.widgets.traceview.ProMTraceList.DefaultWedgeBuilder; +import org.processmining.framework.util.ui.widgets.traceview.ProMTraceView.Event; +import org.processmining.framework.util.ui.widgets.traceview.ProMTraceView.Trace; +import org.processmining.qut.exogenousaware.gui.promlist.ProMListComponents.exoEvent; + +public class EventHighlightWedger extends DefaultWedgeBuilder{ + + private int highlight = -1; + + public EventHighlightWedger(int eventNumber) { + this.highlight = eventNumber; + } + + @Override + public Color buildWedgeColor(Trace trace, Event event) { + exoEvent neweventype = (exoEvent) event; + neweventype.setHighlight(neweventype.eventID == this.highlight); + return event.getWedgeColor(); + + } + + @Override + public Integer assignWedgeGap(Trace trace, Event event) { + exoEvent neweventype = (exoEvent) event; + if ((neweventype.eventID == this.highlight)||(neweventype.eventID==(this.highlight-1))) { + return 10; + } + return null; + } + +} diff --git a/src/org/processmining/qut/exogenousaware/gui/promlist/ProMListComponents.java b/src/org/processmining/qut/exogenousaware/gui/promlist/ProMListComponents.java new file mode 100644 index 0000000..2aa1a49 --- /dev/null +++ b/src/org/processmining/qut/exogenousaware/gui/promlist/ProMListComponents.java @@ -0,0 +1,246 @@ +package org.processmining.qut.exogenousaware.gui.promlist; + +import java.awt.Color; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.deckfour.xes.model.XEvent; +import org.deckfour.xes.model.XTrace; +import org.deckfour.xes.model.impl.XAttributeLiteralImpl; +import org.processmining.framework.util.ui.widgets.traceview.ProMTraceList.TraceBuilder; +import org.processmining.framework.util.ui.widgets.traceview.ProMTraceView.Event; +import org.processmining.framework.util.ui.widgets.traceview.ProMTraceView.Trace; + +public class ProMListComponents { + + private ProMListComponents() {}; + + public static class exoTraceBuilder implements TraceBuilder { + + private Set exoEvents; + private boolean highlight = false; + private int eventid = -1; + + public exoTraceBuilder(Set exoEvents) { + this.exoEvents = exoEvents; + } + + + @Override + public Trace build(XTrace element) { + // TODO Auto-generated method stub + Boolean hasExo = false; + if (element.getAttributes().keySet().contains("exogenous:exist")) { + hasExo = ((XAttributeLiteralImpl) element.getAttributes().get("exogenous:exist") ).getValue().contentEquals("True"); + } + if (this.highlight) { + return new exoTrace(element, + hasExo, + exoEvents, + this.eventid + ); + } else { + return new exoTrace(element, + hasExo, + exoEvents + ); + } + } + + public void setHighlight(int eventid) { + this.highlight = true; + this.eventid = eventid; + } + + public void dehighlight() { + this.highlight = false; + this.eventid = -1; + } + + } + + public static class exoTrace implements Trace { + + private XTrace source; + private Boolean hasExo; + private Set exoEvents; + private int highlightevent = -1; + + public exoTrace(XTrace source, Boolean hasExo, Set exoEvents) { + this(source,hasExo,exoEvents,-1); + } + + public exoTrace(XTrace source, Boolean hasExo, Set exoEvents, int highlightevent) { + this.source = source; + this.hasExo = hasExo; + this.exoEvents = exoEvents; + this.highlightevent = highlightevent; + } + + @Override + public Iterator iterator() { + + List evSet = this.source.stream().map(ev -> ev.getID().toString()).collect(Collectors.toList()); + return new exoIterator( + this.source.iterator(), + this.hasExo ? this.exoEvents.stream().filter(s -> evSet.contains(s)).collect(Collectors.toSet()) : new HashSet(), + this.highlightevent + ); + } + + @Override + public String getName() { + return this.source.getAttributes().get("concept:name").toString(); + } + + @Override + public Color getNameColor() { + return this.hasExo ? new Color(65,150,98) : Color.red; + } + + @Override + public String getInfo() { + // TODO Auto-generated method stub + String info = ""; + for(String key: this.source.getAttributes().keySet()) { + info += String.format("%s : %s \n", + key, this.source.getAttributes().get(key) + ); + } + return info; + } + + @Override + public Color getInfoColor() { + // TODO Auto-generated method stub + return Color.black; + } + + } + + public static class exoIterator implements Iterator { + + Iterator source; + private Set exoEvents; + private int highlightevent = -1; + private int counter = -1; + + public exoIterator(Iterator source, Set exoEvents, int highlightevent) { + this.source = source; + this.exoEvents = exoEvents; + this.highlightevent = highlightevent; + } + + @Override + public boolean hasNext() { + // TODO Auto-generated method stub + return this.source.hasNext(); + } + + @Override + public Event next() { + // TODO Auto-generated method stub + this.counter++; + XEvent ev = this.source.next(); + return new exoEvent( + ev, + counter, + ev.getAttributes().keySet().stream().anyMatch(s -> s.contains("exogenous:dataset")), + this.counter == this.highlightevent + ); + } + + } + + public static class exoEvent implements Event { + + private XEvent source; + private boolean hasExo; + private boolean highlight; + public int eventID; + + public exoEvent(XEvent source, int eventID, boolean hasExo) { + this(source, eventID, hasExo, false); + } + + public exoEvent(XEvent source, int eventID, boolean hasExo, boolean highlight) { + this.source = source; + this.hasExo = hasExo; + this.highlight = highlight; + this.eventID = eventID; + } + + public void setHighlight(boolean highlight) { + this.highlight = highlight; + } + + @Override + public Color getWedgeColor() { + if (this.highlight) { + return Color.orange; + } + else if (this.hasExo) { + return new Color(65,150,98); + } else { + return Color.red; + } + } + + @Override + public Color getBorderColor() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getLabel() { + return this.source.getAttributes().get("concept:name").toString(); + } + + @Override + public Color getLabelColor() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getTopLabel() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Color getTopLabelColor() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getBottomLabel() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Color getBottomLabelColor() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getBottomLabel2() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Color getBottomLabel2Color() { + // TODO Auto-generated method stub + return null; + } + + } +} diff --git a/src/org/processmining/qut/exogenousaware/gui/promlist/WedgeBuilderFactory.java b/src/org/processmining/qut/exogenousaware/gui/promlist/WedgeBuilderFactory.java new file mode 100644 index 0000000..4cd2cf0 --- /dev/null +++ b/src/org/processmining/qut/exogenousaware/gui/promlist/WedgeBuilderFactory.java @@ -0,0 +1,26 @@ +package org.processmining.qut.exogenousaware.gui.promlist; + +import org.processmining.framework.util.ui.widgets.traceview.ProMTraceList.DefaultWedgeBuilder; + +/** + * A factory for making wedge builders on the fly for ProMLists + * + * To trigger dynamic colour changes to wedges in ProMList use the following call sequence:
+ *
+ * + * ProMTraceList controller
+ * controller.setWedgeBuilder(WedgeBuilderFactory.???(??))
+ * controller.updateUI();
+ * + * + */ +public class WedgeBuilderFactory { + + + private WedgeBuilderFactory() {}; + + public static DefaultWedgeBuilder createEventHighlight(int eventNumber) { + return new EventHighlightWedger(eventNumber); + } + +} diff --git a/src/org/processmining/qut/exogenousaware/gui/workers/TraceVisTraceBreakdownCharts.java b/src/org/processmining/qut/exogenousaware/gui/workers/TraceVisTraceBreakdownCharts.java index 8b2f513..f61d996 100644 --- a/src/org/processmining/qut/exogenousaware/gui/workers/TraceVisTraceBreakdownCharts.java +++ b/src/org/processmining/qut/exogenousaware/gui/workers/TraceVisTraceBreakdownCharts.java @@ -31,13 +31,13 @@ import org.jfree.chart.ChartPanel; import org.processmining.framework.util.ui.widgets.traceview.ProMTraceList; import org.processmining.qut.exogenousaware.gui.ExogenousTraceView; -import org.processmining.qut.exogenousaware.gui.ExogenousTraceView.exoTraceBuilder; import org.processmining.qut.exogenousaware.gui.listeners.TraceBreakdownEventListener; import org.processmining.qut.exogenousaware.gui.panels.ExogenousTraceViewJChartFilterPanel; import org.processmining.qut.exogenousaware.gui.panels.ExogenousTraceViewJChartFilterPanel.ChartFilter; import org.processmining.qut.exogenousaware.gui.panels.ExogenousTraceViewJChartFilterPanel.ChartHolder; import org.processmining.qut.exogenousaware.gui.panels.ExogenousTraceViewJChartFilterPanel.PanelFilter; import org.processmining.qut.exogenousaware.gui.panels.ExogenousTraceViewJChartFilterPanel.SlicerFilter; +import org.processmining.qut.exogenousaware.gui.promlist.ProMListComponents.exoTraceBuilder; import org.processmining.qut.exogenousaware.gui.workers.TraceVisEventChart.ChartSeriesController; import com.fluxicon.slickerbox.factory.SlickerFactory;