aboutsummaryrefslogtreecommitdiffstats
path: root/main/src/cgeo/geocaching/utils/GeoDirHandler.java
blob: 98a228711b7ba0e8cbe04e6e710b164a64b5b372 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package cgeo.geocaching.utils;

import cgeo.geocaching.IGeoData;
import cgeo.geocaching.settings.Settings;
import cgeo.geocaching.cgeoapplication;

import android.os.Handler;
import android.os.Message;

/**
 * GeoData and Direction handler. Manipulating geodata and direction information
 * through a GeoDirHandler ensures that all listeners are registered from a {@link android.os.Looper} thread.
 * <p>
 * To use this class, override at least one of {@link #updateDirection(float)} or {@link #updateGeoData(IGeoData)}. You
 * need to start the handler using one of
 * <ul>
 * <li>{@link #startDir()}</li>
 * <li>{@link #startGeo()}</li>
 * <li>{@link #startGeoAndDir()}</li>
 * </ul>
 * A good place might be the {@code onResume} method of the Activity. Stop the Handler accordingly in {@code onPause}.
 * </p>
 */
public abstract class GeoDirHandler extends Handler implements IObserver<Object> {

    private static final int OBSERVABLE = 1 << 1;
    private static final int START_GEO = 1 << 2;
    private static final int START_DIR = 1 << 3;
    private static final int STOP_GEO = 1 << 4;
    private static final int STOP_DIR = 1 << 5;

    private static final cgeoapplication app = cgeoapplication.getInstance();

    @Override
    final public void handleMessage(final Message message) {
        if ((message.what & START_GEO) != 0) {
            app.addGeoObserver(this);
        }

        if ((message.what & START_DIR) != 0) {
            app.addDirectionObserver(this);
        }

        if ((message.what & STOP_GEO) != 0) {
            app.deleteGeoObserver(this);
        }

        if ((message.what & STOP_DIR) != 0) {
            app.deleteDirectionObserver(this);
        }

        if ((message.what & OBSERVABLE) != 0) {
            if (message.obj instanceof IGeoData) {
                updateGeoData((IGeoData) message.obj);
            } else {
                updateDirection((Float) message.obj);
            }
        }
    }

    @Override
    final public void update(final Object o) {
        obtainMessage(OBSERVABLE, o).sendToTarget();
    }

    /**
     * Update method called when new IGeoData is available.
     *
     * @param data
     *            the new data
     */
    protected void updateGeoData(final IGeoData data) {
        // Override this in children
    }

    /**
     * Update method called when new direction data is available.
     *
     * @param direction
     *            the new direction
     */
    protected void updateDirection(final float direction) {
        // Override this in children
    }

    /**
     * Register the current GeoDirHandler for GeoData information.
     */
    public void startGeo() {
        sendEmptyMessage(START_GEO);
    }

    /**
     * Register the current GeoDirHandler for direction information if the preferences
     * allow it.
     */
    public void startDir() {
        if (Settings.isUseCompass()) {
            sendEmptyMessage(START_DIR);
        }
    }

    /**
     * Register the current GeoDirHandler for GeoData and direction information (if the
     * preferences allow it).
     */
    public void startGeoAndDir() {
        sendEmptyMessage(START_GEO | (Settings.isUseCompass() ? START_DIR : 0));
    }

    /**
     * Unregister the current GeoDirHandler for GeoData information.
     */
    public void stopGeo() {
        sendEmptyMessage(STOP_GEO);
    }

    /**
     * Unregister the current GeoDirHandler for direction information.
     */
    public void stopDir() {
        sendEmptyMessage(STOP_DIR);
    }

    /**
     * Unregister the current GeoDirHandler for GeoData and direction information.
     */
    public void stopGeoAndDir() {
        sendEmptyMessage(STOP_GEO | STOP_DIR);
    }
}