TIMELINES_REDESIGN_R0: TimelinesDesignDraft.java

File TimelinesDesignDraft.java, 10.2 KB (added by sveto, 16 years ago)
Line 
1package org.sophie2.base.model.resources.r4.resources;
2import java.util.Arrays;
3import java.util.List;
4import java.util.Map;
5
6import org.sophie2.base.model.resources.r4.ResourceRef;
7import org.sophie2.base.model.resources.r4.ResourceReferrer;
8import org.sophie2.base.model.resources.r4.access.ResourceAccess;
9import org.sophie2.core.mvc.OperationDef;
10import org.sophie2.core.mvc.events.EventR3;
11import org.sophie2.core.prolib.annot.Immutable;
12import org.sophie2.core.prolib.errors.NotAvailableException;
13import org.sophie2.core.prolib.impl.AutoProperty;
14import org.sophie2.core.prolib.impl.BaseProObject;
15import org.sophie2.core.prolib.interfaces.Prop;
16import org.sophie2.core.prolib.interfaces.RwProp;
17
18
19public class TimelinesDesignDraft {
20       
21        @Immutable
22        final static class TimelineEntry<T> implements Comparable<TimelineEntry<T>> {
23        private final long time;
24        private final T value;
25
26        public TimelineEntry(long time, T value) {
27                this.time = time;
28                this.value = value;
29        }
30
31        public long getTime() {
32                return time;
33        }
34
35        public T getValue() {
36                return value;
37        }
38
39        public int compareTo(TimelineEntry<T> o) {
40                if (getTime() < o.getTime()) {
41                        return -1;
42                } else if (getTime() > o.getTime()) {
43                        return 1;
44                } else {
45                        return 0;
46                }
47        }
48
49        }
50       
51        @Immutable
52        static abstract class Channel<T> {
53                private String name;
54                private ImmList<T> valueInterval;
55                private ImmList<TimelineEntry<T>> entries;
56               
57                public abstract ImmList<TimelineEntry<T>> getEntries();
58                public abstract T getValue(long time);
59                public abstract Channel<T> setValue(long time, T value);
60                public abstract Channel<T> setAll(T value);
61                public abstract Channel<T> setInterval(long start, long end, T value);
62                public abstract TimelineEntry<T> getLastSample(long time);
63                public abstract String getName();
64                public abstract ImmList<T> getValueInterval();
65                protected abstract Class<T> getValueClass();
66                public abstract T getDefault();
67                protected abstract T getBetween(TimelineEntry<T> prev, TimelineEntry<T> next, long time);
68                public abstract Channel<T> createChannel(String channelName,
69                                ImmList<T> valueInterval, ImmList<TimelineEntry<T>> channelEntries);
70        }
71       
72        @Immutable
73        static abstract class BooleanChannel extends Channel<Boolean> {
74                BooleanChannel() {
75                       
76                }
77               
78                protected Boolean getBetween(TimelineEntry<Boolean> prev,
79                                TimelineEntry<Boolean> next, long time) {
80                        return prev != null ? prev.getValue() : getDefault();
81                }
82
83                public Boolean getDefault() {
84                        return true;
85                }
86
87                protected Class<Boolean> getValueClass() {
88                        return Boolean.class;
89                }
90
91                public BooleanChannel createChannel(String name,
92                                ImmList<Boolean> presets, ImmList<TimelineEntry<Boolean>> entries) {
93                        return new BooleanChannel(name, entries);
94                }
95        }
96
97        @Immutable
98        static abstract class ActivationChannel extends BooleanChannel implements ResourceReferrer<ActivationChannel> {
99                private final ResourceRef elementResource;
100
101                public List<ResourceRef> getReferences() {
102                        return Arrays.asList(elementResource);
103                }
104               
105                public ActivationChannel fixReferences(Map<ResourceRef, ResourceRef> replaces) {
106                        if (replaces.containsKey(elementResource)) {
107                                return new ActivationChannel(replaces.get(elementResource), getEntries());
108                        }
109                        return this;
110                }
111
112                public Long getActivationTime(Long time) {
113                        if (getValue(time) == false) {
114                                return null;
115                        }
116                        TimelineEntry<Boolean> last = getLastSample(time);
117
118                        return last != null ? last.getTime() : null;
119                }
120        }
121
122        @Immutable
123        static abstract class TimelineOptions {
124                private int introLen = 0;
125                private int mainLen = 60000;
126                private int outroLen = 0;
127               
128                private boolean mainLooped = false;
129                private boolean asParent = false;
130               
131                public abstract int getIntroLen();
132                public abstract int getOutroLen();             
133                public abstract int getMainLen();               
134                public abstract boolean isMainLooped();         
135                public abstract boolean isAsParent();
136               
137                public abstract TimelineOptions withIntroLen(int introLen);
138                public abstract TimelineOptions withMainLen(int mainLen);
139                public abstract TimelineOptions withOutroLen(int outroLen);
140                public abstract TimelineOptions withMainLooped(boolean mainLooped);
141                public abstract TimelineOptions withAsParent(boolean asParent);
142        }
143       
144        static abstract class TimelineViewOptions extends BaseProObject {
145                // Boundary constant
146                protected static final long C = 1000000000000000L;
147                public static final int TIMELINE_DURATION = 60000;
148
149                public abstract Prop<? extends ElementView> parent();
150
151                public abstract RwProp<Long> wantedLocalTime();
152
153                public abstract Prop<Long> activationTime();
154
155                public Prop<Long> localTime() {
156                        class localTime extends AutoProperty<Long> {
157
158                                @Override
159                                protected Long compute() {
160                                        Long res;
161
162                                        if (wantedLocalTime().get() != null) {
163                                                res = wantedLocalTime().get();
164                                        } else if (activationTime().get() != null
165                                                        && parent().get() != null
166                                                        && parent().get().timedViewParent().get() != null) {
167                                                res = parent().get().timedViewParent().get().timelineView()
168                                                                .get().localTime().get()
169                                                                - activationTime().get();
170                                        } else {
171                                                res = null;
172                                        }
173
174                                        if (res != null) {
175                                                res = toChannelTime(res);
176                                        }
177
178                                        return res;
179                                }
180                        }
181                        return getBean().makeProp(localTime.class);
182                }
183               
184               
185                protected long toChannelTime(long time) {
186                        TimelineOptions timelineOptions = getTimelineOptions();
187                       
188                        int introLen = timelineOptions.getIntroLen();
189                        int mainLen = timelineOptions.getMainLen();
190                        int outroLen = timelineOptions.getOutroLen();
191                       
192                        if (time >= introLen && time < mainLen) {
193                                time += C;
194                        } else if (time >= mainLen && time < outroLen){
195                                time += 2 * C;
196                        }
197                       
198                        return time;
199                }
200               
201                protected long toRealTime(long channelTime) {
202                        if (channelTime >= C && channelTime < 2 * C) {
203                                channelTime -= C;
204                        } else if (channelTime >= 2 * C){
205                                channelTime -= 2 * C;
206                        }
207                       
208                        return channelTime;
209                }
210               
211                abstract TimelineOptions getTimelineOptions();
212        }
213       
214        static abstract class TimelineTopView extends TimelineViewOptions {
215                public abstract RwProp<Long> activationTime();
216                public abstract RwProp<Boolean> timelineStarted();             
217                public abstract void startTimeline();
218                public abstract void stopTimeline();
219        }
220       
221        static abstract class TimelineMemberView extends TimelineViewOptions {
222                private Prop<ActivationChannel> activationChannel() {
223                        class activationChannel extends AutoProperty<ActivationChannel> {
224
225                                @Override
226                                protected ActivationChannel compute() {
227                                        // The view should hold reference to the model as ResourceAcccess
228                                        ResourceAccess resourceAccess = parent().model();
229                                        ResourceAccess parentResourceAccess = parent().parent().model();
230
231                                        ResourceRef ref = resourceAccess.getRaw(ResourceR4.META_KEY_TARGET);
232                                       
233                                        for (ActivationChannel channel : parentResourceAccess.getRaw(ElementR4.OPTIONAL_KEY_SUB_ELEMENTS).asList()) {
234                                                ResourceRef channelRef = channel.getReferences().get(0);
235                                                if (ref.equals(channelRef)) {
236                                                        return channel;
237                                                }
238                                        }
239
240                                        return null;
241                                }
242                        }
243                        return getBean().makeProp(activationChannel.class);
244                }
245               
246                public Prop<Long> activationTime() {
247                        class activationTime extends AutoProperty<Long> {
248
249                                protected Long compute() {
250                                        ActivationChannel ac = null;    // obtain activation channel
251                                        if (ac == null) {
252                                                return null;
253                                        }
254
255                                        ElementView parent = parent().get().timedViewParent().get();
256
257                                        if (parent == null) {
258                                                throw new NotAvailableException();
259                                        }
260
261                                        Long parentTime = parent.timelineView().get().localTime().get();
262                                        Long res = ac.getActivationTime(parentTime);
263                                       
264                                        if (res != null) {
265                                                if (!areAncestorsActive(parent.timelineView().get())) {
266                                                        return null;
267                                                }
268                                        }
269                                       
270                                        return res;
271                                }
272                        }
273                        return getBean().makeProp(activationTime.class);
274                }
275               
276                private boolean areAncestorsActive(TimelineViewOptions timelineViewOptions) {};
277        }
278       
279       
280        // Manipulation of timelines from the view
281        public enum TimelinesPaletteLogic implements OperationDef {
282                SET_POINT_HANDLER {
283                        public boolean handle(EventR3 event) {
284                                TimelinesPalette source = event.getSource(TimelinesPalette.class);
285                               
286                                TimelineItem timelineItem = ...;
287       
288                                final ResourceAccess resourceAccess = source.elementView().model();
289                               
290                                final Channel channel = timelineItem.channel().get();
291                               
292                                final Long time = 10L;
293                                final Boolean bValue = true;
294                               
295                                AutoAction action = new AutoAction() {
296                                        public void performAuto() {
297                                                if (channel instanceof ActivationChannel) {     // Activation channel
298                                                        ImmList<ActivationChannel> channels = resourceAccess.getRaw(ElementR4.OPTIONAL_KEY_SUB_ELEMENTS);
299                                                        channels = channels.immRemove(channel).immAdd(channel.setValue(time, value));
300                                                        changer.setRaw(ElementR4.OPTIONAL_KEY_SUB_ELEMENTS, channels);
301                                                } else {        // Property channel
302                                                        ImmList<Channel<T>> channels = resourceAccess.getRaw(ElementR4.OPTIONAL_KEY_CHANNELS);
303                                                        channels = channels.immRemove(channel).immAdd(channel.setValue(time, value));
304                                                        changer.setRaw(ElementR4.OPTIONAL_KEY_CHANNELS, channels);                                             
305                                                }               
306                                        }
307                                };
308                               
309                                ModelChange change = new ModelChange(null, null, null, false, this.action.getClass(), null);
310       
311                                resourceAccess.registerChange(change);
312                       
313                                return true;
314                        }
315                },
316               
317                SET_INTERVAL_HANDLER {                 
318                },
319               
320                SET_ALL_HANDLER {                       
321                },
322               
323                SET_INTRO_HANDLER {
324                        public boolean handle(EventR3 event) {
325
326                                TimelinesPalette source = event.getSource(TimelinesPalette.class);
327                               
328                                final Integer introLen = 10;
329                               
330                                final ResourceAccess resourceAccess = source.elementView().model();
331                               
332                                AutoAction action = new AutoAction() {
333                                        public void performAuto() {
334                                                TimelineOptions timelineOptions = resourceAccess.getRaw(ElementR4.KEY_TIMELINE_OPTIONS);
335                                                timelineOptions = timelineOptions.withIntro(introLen);
336                                                changer.setRaw(ElementR4.KEY_TIMELINE_OPTIONS, timelineOptions);
337                                        }
338                                };
339                               
340                                ModelChange change = new ModelChange(null, null, null, false, this.action.getClass(), null);
341       
342                                resourceAccess.registerChange(change);
343                               
344                                return true;
345                        }
346                },
347               
348                SET_OUTRO_HANDLER {                     
349                },
350               
351                SET_MAIN_LOOPED_HANDLER {
352                },
353               
354                SET_AS_PARENT_HANDLER {
355                };
356        }       
357}