/*
 * ARX: Powerful Data Anonymization
 * Copyright 2012 - 2017 Fabian Prasser, Florian Kohlmayer and contributors
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.deidentifier.arx.gui.view.impl.common;

import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;

/**
 * A listener that acts as a selection listener and a modify listener which defers change
 * events for a given amount of time
 * 
 * @author Fabian Prasser
 */
public abstract class DelayedChangeListener implements SelectionListener, ModifyListener, Listener {

    /** Tick in milliseconds */
    private static final int TICK  = 100;
    /** Flag */
    private boolean          event = false;
    /** Time */
    private long             time;
    /** Delay in milliseconds */
    private final long       delay;

    /**
     * Delay in milliseconds
     * @param delay
     */
    public DelayedChangeListener(long delay) {
        this.delay = delay;
        
        // Create repeating task
        final Display display = Display.getCurrent();
        display.timerExec(TICK, new Runnable() {
            @Override
            public void run() {
                if (event && System.currentTimeMillis() > time) {
                    delayedEvent();
                    event = false;
                }
                display.timerExec(TICK, this);
            }
        });
    }
    
    /**
     * Implement this
     * @param arg0
     */
    public abstract void delayedEvent();

    @Override
    public void handleEvent(Event arg0) {
        this.event = true;
        this.time = System.currentTimeMillis() + delay;
    }

    @Override
    public void modifyText(ModifyEvent arg0) {
        this.event = true;
        this.time = System.currentTimeMillis() + delay;
    }

    @Override
    public void widgetDefaultSelected(SelectionEvent arg0) {
        this.event = true;
        this.time = System.currentTimeMillis() + delay;
    }

    @Override
    public void widgetSelected(SelectionEvent arg0) {
        this.event = true;
        this.time = System.currentTimeMillis() + delay;
    }
}
@@ -1736,24 +1736,27 @@
 delay;%0D%0A    
+%7D%0D%0A
     %0D%0A      
@@ -1757,151 +1757,109 @@
     
-    // Create repeating task
+/**%0D%0A     * Implement this
 %0D%0A     
- 
-  final Display display = Display.getCurrent();%0D%0A        display.timerExec(TICK, new Runnable() %7B%0D%0A        
+* @param arg0%0D%0A     */%0D%0A    public abstract void delayedEvent();%0D%0A%0D%0A
     
@@ -1867,26 +1867,17 @@
 Override
-%0D
 %0A
-        
     publ
@@ -1888,237 +1888,320 @@
 oid 
-run() %7B%0D%0A                if (event && System.currentTimeMillis() %3E time) %7B%0D%0A                    delayedEvent();%0D%0A                    event = false;%0D%0A            
+handleEvent(Event arg0) %7B%0D%0A        fire();%0D%0A    %7D%0D%0A%0D%0A    @Override%0A    public void modifyText(ModifyEvent arg0) %7B%0D%0A        fire();%0D%0A    %7D%0D%0A%0D%0A    @Override%0D%0A    public void widgetDefaultSelected(SelectionEvent arg0) %7B%0D%0A        fire();%0D%0A
     %7D%0D%0A
-  
+%0D%0A
     
-          display.timerExec(TICK, this);%0D%0A            %7D
+@Override%0D%0A    public void widgetSelected(SelectionEvent arg0) %7B
 %0D%0A  
@@ -2206,17 +2206,21 @@
         
-%7D
+fire(
 );%0D%0A    
@@ -2214,36 +2214,32 @@
 fire();%0D%0A    %7D%0D%0A
-    
 %0D%0A    /**%0D%0A     
@@ -2244,310 +2244,178 @@
   * 
-Implement this%0D%0A     * @param arg0%0D%0A     */%0D%0A    public abstract void delayedEvent();%0D%0A%0D%0A    @Override%0A    public void handleEvent(Event arg0) %7B%0D%0A        this.event = true;%0D%0A        this.time = System.currentTimeMillis() + delay;%0D%0A    %7D%0D%0A%0D%0A    @Override%0A    public void modifyText(ModifyEvent arg0) %7B%0D%0A
+Generic fire event%0D%0A     */%0D%0A    private void fire() %7B%0D%0A%0D%0A        this.time = System.currentTimeMillis() + delay;%0D%0A            %0D%0A        if (!event) %7B%0D%0A            %0D%0A    
     
@@ -2446,394 +2446,530 @@
     
+%0D%0A  
     
-this.time = System.currentTimeMillis() + delay;%0D%0A    %7D%0D%0A%0D%0A    @Override%0D%0A    public void widgetDefaultSelected(SelectionEvent arg0) %7B%0D%0A        this.event = true;%0D%0A        this.time = System.currentTimeMillis() + delay;%0D%0A    %7D%0D%0A%0D%0A    @Override%0D%0A    public void widgetSelected(SelectionEvent arg0) %7B%0D%0A        this.event = true;%0D%0A        this.time = System.currentTimeMillis() + delay;
+      // Create repeating task%0D%0A            final Display display = Display.getCurrent();%0D%0A            display.timerExec(TICK, new Runnable() %7B%0D%0A                @Override%0D%0A                public void run() %7B%0D%0A                    if (event && System.currentTimeMillis() %3E time) %7B%0D%0A                        delayedEvent();%0D%0A                        event = false;%0D%0A                        return;%0D%0A                    %7D%0D%0A                    display.timerExec(TICK, this);%0D%0A                %7D%0D%0A            %7D);%0D%0A        %7D
 %0D%0A  

Fix memory leaks by fixing DelayedChangeListener