All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.javafx.event.CompositeEventHandler Maven / Gradle / Ivy

There is a newer version: 24-ea+5
Show newest version
/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.javafx.event;

import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.event.WeakEventHandler;

public final class CompositeEventHandler {
    private EventProcessorRecord firstRecord;
    private EventProcessorRecord lastRecord;

    private EventHandler eventHandler;

    public void setEventHandler(final EventHandler eventHandler) {
        this.eventHandler = eventHandler;
    }

    public EventHandler getEventHandler() {
        return eventHandler;
    }

    public void addEventHandler(final EventHandler eventHandler) {
        if (find(eventHandler, false) == null) {
            append(lastRecord, createEventHandlerRecord(eventHandler));
        }
    }

    public void removeEventHandler(final EventHandler eventHandler) {
        final EventProcessorRecord record = find(eventHandler, false);
        if (record != null) {
            remove(record);
        }
    }

    public void addEventFilter(final EventHandler eventFilter) {
        if (find(eventFilter, true) == null) {
            append(lastRecord, createEventFilterRecord(eventFilter));
        }
    }

    public void removeEventFilter(final EventHandler eventFilter) {
        final EventProcessorRecord record = find(eventFilter, true);
        if (record != null) {
            remove(record);
        }
    }

    public void dispatchBubblingEvent(final Event event) {
        final T specificEvent = (T) event;

        EventProcessorRecord record = firstRecord;
        while (record != null) {
            if (record.isDisconnected()) {
                remove(record);
            } else {
                record.handleBubblingEvent(specificEvent);
            }
            record = record.nextRecord;
        }

        if (eventHandler != null) {
            eventHandler.handle(specificEvent);
        }
    }

    public void dispatchCapturingEvent(final Event event) {
        final T specificEvent = (T) event;

        EventProcessorRecord record = firstRecord;
        while (record != null) {
            if (record.isDisconnected()) {
                remove(record);
            } else {
                record.handleCapturingEvent(specificEvent);
            }
            record = record.nextRecord;
        }
    }

    /* Used for testing. */
    boolean containsHandler(final EventHandler eventHandler) {
        return find(eventHandler, false) != null;
    }

    /* Used for testing. */
    boolean containsFilter(final EventHandler eventFilter) {
        return find(eventFilter, true) != null;
    }

    private EventProcessorRecord createEventHandlerRecord(
            final EventHandler eventHandler) {
        return (eventHandler instanceof WeakEventHandler)
                   ? new WeakEventHandlerRecord(
                             (WeakEventHandler) eventHandler)
                   : new NormalEventHandlerRecord(eventHandler);
    }

    private EventProcessorRecord createEventFilterRecord(
            final EventHandler eventFilter) {
        return (eventFilter instanceof WeakEventHandler)
                   ? new WeakEventFilterRecord(
                             (WeakEventHandler) eventFilter)
                   : new NormalEventFilterRecord(eventFilter);
    }

    private void remove(final EventProcessorRecord record) {
        final EventProcessorRecord prevRecord = record.prevRecord;
        final EventProcessorRecord nextRecord = record.nextRecord;

        if (prevRecord != null) {
            prevRecord.nextRecord = nextRecord;
        } else {
            firstRecord = nextRecord;
        }

        if (nextRecord != null) {
            nextRecord.prevRecord = prevRecord;
        } else {
            lastRecord = prevRecord;
        }

        // leave record.nextRecord set
    }

    private void append(final EventProcessorRecord prevRecord,
                        final EventProcessorRecord newRecord) {
        EventProcessorRecord nextRecord;
        if (prevRecord != null) {
            nextRecord = prevRecord.nextRecord;
            prevRecord.nextRecord = newRecord;
        } else {
            nextRecord = firstRecord;
            firstRecord = newRecord;
        }

        if (nextRecord != null) {
            nextRecord.prevRecord = newRecord;
        } else {
            lastRecord = newRecord;
        }

        newRecord.prevRecord = prevRecord;
        newRecord.nextRecord = nextRecord;
    }

    private EventProcessorRecord find(
            final EventHandler eventProcessor,
            final boolean isFilter) {
        EventProcessorRecord record = firstRecord;
        while (record != null) {
            if (record.isDisconnected()) {
                remove(record);
            } else if (record.stores(eventProcessor, isFilter)) {
                return record;
            }

            record = record.nextRecord;
        }

        return null;
    }

    private static abstract class EventProcessorRecord {
        private EventProcessorRecord nextRecord;
        private EventProcessorRecord prevRecord;

        public abstract boolean stores(EventHandler eventProcessor,
                                       boolean isFilter);

        public abstract void handleBubblingEvent(T event);

        public abstract void handleCapturingEvent(T event);

        public abstract boolean isDisconnected();
    }

    private static final class NormalEventHandlerRecord
            extends EventProcessorRecord {
        private final EventHandler eventHandler;

        public NormalEventHandlerRecord(
                final EventHandler eventHandler) {
            this.eventHandler = eventHandler;
        }

        @Override
        public boolean stores(final EventHandler eventProcessor,
                              final boolean isFilter) {
            return !isFilter && (this.eventHandler == eventProcessor);
        }

        @Override
        public void handleBubblingEvent(final T event) {
            eventHandler.handle(event);
        }

        @Override
        public void handleCapturingEvent(final T event) {
        }

        @Override
        public boolean isDisconnected() {
            return false;
        }
    }

    private static final class WeakEventHandlerRecord
            extends EventProcessorRecord {
        private final WeakEventHandler weakEventHandler;

        public WeakEventHandlerRecord(
                final WeakEventHandler weakEventHandler) {
            this.weakEventHandler = weakEventHandler;
        }

        @Override
        public boolean stores(final EventHandler eventProcessor,
                              final boolean isFilter) {
            return !isFilter && (weakEventHandler == eventProcessor);
        }

        @Override
        public void handleBubblingEvent(final T event) {
            weakEventHandler.handle(event);
        }

        @Override
        public void handleCapturingEvent(final T event) {
        }

        @Override
        public boolean isDisconnected() {
            return weakEventHandler.wasGarbageCollected();
        }
    }

    private static final class NormalEventFilterRecord
            extends EventProcessorRecord {
        private final EventHandler eventFilter;

        public NormalEventFilterRecord(
                final EventHandler eventFilter) {
            this.eventFilter = eventFilter;
        }

        @Override
        public boolean stores(final EventHandler eventProcessor,
                              final boolean isFilter) {
            return isFilter && (this.eventFilter == eventProcessor);
        }

        @Override
        public void handleBubblingEvent(final T event) {
        }

        @Override
        public void handleCapturingEvent(final T event) {
            eventFilter.handle(event);
        }

        @Override
        public boolean isDisconnected() {
            return false;
        }
    }

    private static final class WeakEventFilterRecord
            extends EventProcessorRecord {
        private final WeakEventHandler weakEventFilter;

        public WeakEventFilterRecord(
                final WeakEventHandler weakEventFilter) {
            this.weakEventFilter = weakEventFilter;
        }

        @Override
        public boolean stores(final EventHandler eventProcessor,
                              final boolean isFilter) {
            return isFilter && (weakEventFilter == eventProcessor);
        }

        @Override
        public void handleBubblingEvent(final T event) {
        }

        @Override
        public void handleCapturingEvent(final T event) {
            weakEventFilter.handle(event);
        }

        @Override
        public boolean isDisconnected() {
            return weakEventFilter.wasGarbageCollected();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy