Subversion Repositories freemyipod

Rev

Rev 826 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
824 theseven 1
//
2
//
3
//    Copyright 2011 TheSeven
4
//
5
//
6
//    This file is part of emCORE.
7
//
8
//    emCORE is free software: you can redistribute it and/or
9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
13
//    emCORE is distributed in the hope that it will be useful,
14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
20
//
21
//
22
 
23
 
24
#include "emcorelib.h"
25
#include "libui.h"
26
#include "settingchooser.h"
27
#include "chooser.h"
28
#include "chooser_renderer_list.h"
29
#include "chooser_action_handler_wheel.h"
30
 
31
 
32
static bool settingchooser_event_filter(struct chooser_data* data, enum button_event event,
33
                                        int which, int value)
34
{
35
    struct settingchooser_data* state = (struct settingchooser_data*)data->info->userparams;
36
    struct settingchooser_info* info = (struct settingchooser_info*)state->info;
37
    struct settingchooser_item* item = (struct settingchooser_item*)data->selected->user;
38
    struct chooser_renderer_list_itemdata* rp;
39
    rp = (struct chooser_renderer_list_itemdata*)data->selected->renderparams;
40
    bool redraw = false;
41
    bool handled = false;
42
    bool setcolors = false;
43
    switch (event)
44
    {
45
        case BUTTON_PRESS:
46
            switch (which)
47
            {
48
                case 0:
49
                    switch (item->type)
50
                    {
51
                        case SETTINGCHOOSER_TYPE_INTEGER:
52
                            handled = true;
53
                            setcolors = true;
54
                            state->editing = !state->editing;
55
                            if (state->editing) state->collect = 0;
56
                            break;
57
                    }
58
                    break;
59
 
60
                case 2:
61
                    if (state->editing)
62
                    {
63
                        handled = true;
64
                        setcolors = true;
65
                        state->editing = false;
66
                    }
67
                    break;
68
 
69
                default:
70
                    handled = state->editing;
71
                    break;
72
            }
73
            break;
74
 
75
        case WHEEL_MOVED_ACCEL:
76
            if (state->editing)
77
            {
78
                switch (item->type)
79
                {
80
                    case SETTINGCHOOSER_TYPE_INTEGER:
81
                        handled = true;
82
                        state->collect += value;
83
                        int change = (state->collect * item->config.integer.step) / 128;
84
                        if (!change) break;
85
                        state->collect -= (change * 128) / item->config.integer.step;
86
                        int* setting = (int*)item->setting;
87
                        if (*setting + change < item->config.integer.min)
88
                            *setting = item->config.integer.min;
89
                        else if (*setting + change > item->config.integer.max)
90
                            *setting = item->config.integer.max;
91
                        else *setting += change;
92
                        if (item->validator) item->validator(item->setting);
93
                        state->changed = true;
94
                        redraw = true;
95
                        break;
96
                }
97
            }
98
            break;
99
    }
100
    if (setcolors)
101
    {
102
        if (state->editing)
103
        {
104
            rp->fill_color_selected = info->itemparams.fill_color_active;
105
            rp->text_color_selected = info->itemparams.text_color_active;
106
            rp->icon_selected_opacity = info->itemparams.icon_active_opacity;
107
        }
108
        else
109
        {
110
            rp->fill_color_selected = info->itemparams.fill_color_selected;
111
            rp->text_color_selected = info->itemparams.text_color_selected;
112
            rp->icon_selected_opacity = info->itemparams.icon_selected_opacity;
113
        }
114
        redraw = true;
115
    }
116
    if (redraw)
117
    {
118
        mutex_lock(&data->statemutex, TIMEOUT_BLOCK);
119
        data->redrawneeded = true;
120
        wakeup_signal(&data->eventwakeup);
121
        mutex_unlock(&data->statemutex);
122
    }
123
    return handled;
124
}
125
 
126
static struct chooser_action_handler_wheel_params settingchooser_aparams =
127
{
128
    .version = CHOOSER_ACTION_HANDLER_WHEEL_PARAMS_VERSION,
129
    .stepsperitem = 128,
130
    .eventfilter = settingchooser_event_filter,
131
    .timeout_initial = TIMEOUT_BLOCK,
132
    .timeout_idle = TIMEOUT_BLOCK,
133
    .timeout_item = 0,
134
    .tick_force_redraw = true,
135
    .buttoncount = 5,
136
    .buttonmap =
137
    {
138
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
139
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NONE,
140
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_CANCEL,
141
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NEXT,
142
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_PREV
143
    }
144
};
145
static struct chooser_action_handler_wheel_params settingchooser_aparams2 =
146
{
147
    .version = CHOOSER_ACTION_HANDLER_WHEEL_PARAMS_VERSION,
148
    .stepsperitem = 128,
149
    .eventfilter = NULL,
150
    .timeout_initial = TIMEOUT_BLOCK,
151
    .timeout_idle = TIMEOUT_BLOCK,
152
    .timeout_item = 0,
153
    .tick_force_redraw = true,
154
    .buttoncount = 5,
155
    .buttonmap =
156
    {
157
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_SELECT,
158
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NONE,
159
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_CANCEL,
160
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_NEXT,
161
        CHOOSER_ACTION_HANDLER_WHEEL_ACTION_PREV
162
    }
163
};
164
 
165
static void settingchooser_render_preview(struct chooser_data* data,
166
                                          const struct chooser_item* item,
167
                                          bool selected, int x, int y)
168
{
169
    struct settingchooser_item* itemdata = (struct settingchooser_item*)item->user;
170
    int value = *((int*)itemdata->setting);
171
    const char* str = NULL;
172
    char buf[16];
173
    switch (itemdata->type)
174
    {
175
        case SETTINGCHOOSER_TYPE_INTEGER:
176
            if (itemdata->config.integer.tostring)
177
                itemdata->config.integer.tostring(buf, sizeof(buf), itemdata->setting, value);
178
            else snprintf(buf, sizeof(buf), "%d", value);
179
            str = buf;
180
            break;
181
 
182
        case SETTINGCHOOSER_TYPE_SELECT:
183
            if (value < itemdata->config.select.options->optioncount)
184
                str = itemdata->config.select.options->options[value].preview;
185
            break;
186
    }
187
    if (str) chooser_renderer_list_render_attached_text(data, item, selected, x, y, str);
188
}
189
 
190
static void settingchooser_populate_rp(const struct settingchooser_info* info,
191
                                       struct chooser_renderer_list_itemdata* rp)
192
{
193
    rp->size = info->itemparams.size;
194
    rp->fill_box = info->itemparams.fill_box;
195
    rp->fill_color = info->itemparams.fill_color;
196
    rp->fill_color_selected = info->itemparams.fill_color_selected;
197
    rp->icon_pos = info->itemparams.icon_pos;
198
    rp->icon_opacity = info->itemparams.icon_opacity;
199
    rp->icon_selected_opacity = info->itemparams.icon_selected_opacity;
200
    rp->text_pos = info->itemparams.text_pos;
201
    rp->text_color = info->itemparams.text_color;
202
    rp->text_color_selected = info->itemparams.text_color_selected;
203
}
204
 
205
bool settingchooser_run(const struct settingchooser_info* info)
206
{
207
    int i;
208
    bool rc = false;
209
    struct chooser_renderer_list_itemdata* rp;
210
    if (info->version != SETTINGCHOOSER_INFO_VERSION) return false;
211
    int allocsize = sizeof(struct settingchooser_data)
212
                  + sizeof(struct chooser_info)
213
                  + sizeof(struct chooser_item) * (info->itemcount + 1)
214
                  + sizeof(struct chooser_renderer_list_itemdata) * (info->itemcount + 1);
215
    void* mem = malloc(allocsize);
216
    if (!mem) return false;
217
    memset(mem, 0, allocsize);
218
    void* ptr = mem;
219
    struct settingchooser_data* data = (struct settingchooser_data*)ptr;
220
    ptr += sizeof(struct settingchooser_data);
221
    struct chooser_info* chooser = (struct chooser_info*)ptr;
222
    ptr += sizeof(struct chooser_info);
223
    ptr += sizeof(struct chooser_item) * (info->itemcount + 1);
224
    for (i = 0; i < info->itemcount + 1; i++)
225
    {
226
        chooser->items[i].renderparams = (struct chooser_renderer_list_itemdata*)ptr;
227
        ptr += sizeof(struct chooser_renderer_list_itemdata);
228
    }
229
    data->info = info;
230
    chooser->version = CHOOSER_INFO_VERSION;
231
    chooser->actionhandler = &chooser_action_handler_wheel;
232
    chooser->actionhandlerparams = &settingchooser_aparams;
233
    chooser->renderer = &chooser_renderer_list;
234
    chooser->rendererparams = &info->rendererparams;
235
    chooser->userparams = data;
236
    chooser->tickinterval = info->tickinterval;
237
    chooser->itemcount = info->itemcount + 1;
238
    rp = (struct chooser_renderer_list_itemdata*)chooser->items[0].renderparams;
239
    settingchooser_populate_rp(info, rp);
240
    rp->text = info->returntext;
241
    rp->render = chooser_renderer_list_show_arrow_left;
242
    for (i = 0; i < info->itemcount; i++)
243
    {
244
        chooser->items[i + 1].user = &info->items[i];
245
        rp = (struct chooser_renderer_list_itemdata*)chooser->items[i + 1].renderparams;
246
        settingchooser_populate_rp(info, rp);
247
        rp->text = info->items[i].text;
248
        rp->icon = info->items[i].icon;
249
        rp->icon_selected = info->items[i].icon_selected;
250
        rp->render = settingchooser_render_preview;
251
    }
252
    while (true)
253
    {
254
        const struct chooser_item* result = chooser_run(chooser);
255
        if (!result) break;
256
        struct settingchooser_item* item = (struct settingchooser_item*)result->user;
257
        if (!item) break;
258
        chooser->defaultitem = result - chooser->items;
259
        const struct settingchooser_select_options* options = item->config.select.options;
260
        int allocsize2 = sizeof(struct chooser_info)
261
                       + sizeof(struct chooser_item) * (options->optioncount + 1)
262
                       + sizeof(struct chooser_renderer_list_itemdata)
263
                       * (options->optioncount + 1);
264
        void* mem2 = malloc(allocsize2);
265
        if (!mem2) continue;
266
        memset(mem2, 0, allocsize2);
267
        void* ptr = mem2;
268
        struct chooser_info* chooser2 = (struct chooser_info*)ptr;
269
        ptr += sizeof(struct chooser_info);
270
        ptr += sizeof(struct chooser_item) * (options->optioncount + 1);
271
        for (i = 0; i < options->optioncount + 1; i++)
272
        {
273
            chooser2->items[i].renderparams = (struct chooser_renderer_list_itemdata*)ptr;
274
            ptr += sizeof(struct chooser_renderer_list_itemdata);
275
        }
276
        chooser2->version = CHOOSER_INFO_VERSION;
277
        chooser2->actionhandler = &chooser_action_handler_wheel;
278
        chooser2->actionhandlerparams = &settingchooser_aparams;
279
        chooser2->renderer = &chooser_renderer_list;
280
        chooser2->rendererparams = &info->rendererparams;
281
        chooser2->userparams = data;
282
        chooser2->tickinterval = info->tickinterval;
283
        chooser2->itemcount = options->optioncount + 1;
284
        chooser2->defaultitem = *((int*)item->setting) + 1;
285
        rp = (struct chooser_renderer_list_itemdata*)chooser2->items[0].renderparams;
286
        settingchooser_populate_rp(info, rp);
287
        rp->text = "Cancel";
288
        rp->render = chooser_renderer_list_show_arrow_left;
289
        for (i = 0; i < options->optioncount; i++)
290
        {
291
            chooser2->items[i + 1].user = &options->options[i];
292
            rp = (struct chooser_renderer_list_itemdata*)chooser2->items[i + 1].renderparams;
293
            settingchooser_populate_rp(info, rp);
294
            rp->text = options->options[i].text;
295
            rp->icon = options->options[i].icon;
296
            rp->icon_selected = options->options[i].icon_selected;
297
        }
298
        result = chooser_run(chooser2);
299
        int value = result - chooser2->items;
300
        if (result && value && *((int*)item->setting) != value - 1)
301
        {
302
            data->changed = true;
303
            *((int*)item->setting) = value - 1;
304
            if (item->validator) item->validator(item->setting);
305
        }
306
        free(mem2);
307
    }
308
    rc = data->changed;
309
    free(mem);
310
    return rc;
311
}